这里主要借助OllyDbg的汇编功能,使用汇编语言编写注入代码即ThreadProc()函数。与上一篇文章的CodeInject.cpp代码类似,但区别在于THREAD_PARAM结构体不包含字符串成员,且使用指令字节数组替代了ThreadProc()函数(因为代码本身同时包含所需的字符串数据)。
汇编语言常用的开发工具(Assembler)有MASM、TASM和FASM等。
编写简单的待修改程序
编写一个并无啥功能的asmtest.exe程序以用于通过OllyDbg使用汇编编写注入代码。
asmtest.cpp
#include "stdio.h"
int test(){
return 0;
}
int main(int argc, char* argv[]){
return test();
}
编译生成asmtest.exe。
使用OllyDbg的Assemble功能修改汇编代码
使用OllyDbg打开asmtest.exe,划到代码区域的顶端位置,右键New origin here,将EIP更改为改地址401000:
注意,New origin here命令仅用来修改EIP寄存器值,与直接通过调用方式转到指定地址是不一样的,因为寄存器与栈中内容并未改变。
空格键即可弹出输入汇编命令的窗口,将其中的复选“Fill with NOP's”取消掉(若处于复选状态,输入代码长度短于已有代码时,剩余长度会填充为NOP指令,以整体对齐代码):
接下来使用汇编编写ThreadProc()函数。与C语言编写的不同在于,需要的Data(字符串)已包含在Code中。
自EP处输入代码至40102E地址的call指令处(后续再说明为啥call地址为40103E):
简单地说一下,就是先建立栈帧,401001地址处的MOV指令将ESI指向LoadLibraryA(),接下来3条PUSH指令为“User32.dll”的ASCII码(这种将字符串压入栈的方法仅适用于汇编编写的程序),接着PUSH ESP将上述字符串压入栈中,再CALL指令调用LoadLibraryA(‘User32.dll’);接着3条PUSH为“MessageBoxA”,压入栈后PUSH EAX将use32.dll地址压入栈,再CALL指令调用GetProcAddress();PUSH 0指令压入MessageBoxA()第四个参数uType值0,最后的CALL指令相当于PUSH+JMP指令,即将下列的字符串压入栈后再跳转到下一个位置执行。
接着在紧跟着的地址401033中输入字符串,Ctrl+E打开Edit窗口,在ASCII栏输入字符串“SKI12”,再到HEX栏最后输入00即NULL结束字符串,其为MessageBoxA()第三个参数lpCaption:
接着在40103E地址处填写call指令,可以看到之前的call指向现在的call指令,中间保存的是输入的‘SKI12’字符串,之所以显示奇怪的命令在于OllyDbg将字符串误认为IA