1、有的时候要构造一个CALL ,那么CALL后面的地址对应的4个字节怎么弄呢?,就用下面的 函数
void WriteCall(DWORD ProcAddr,LPVOID lpData)
{
BYTE _data[5];
_data[0]=0xE8;
DWORD OldPro;
VirtualProtect((LPVOID)(ProcAddr),5,PAGE_EXECUTE_READWRITE,&OldPro);
memcpy((LPVOID)(_data+1),lpData,4);//_data是变量的内存地址
memcpy((LPVOID)(ProcAddr),_data,5);
VirtualProtect((LPVOID)(ProcAddr),5,OldPro,&OldPro);//内存属性恢复为只读
}
2、有的时候要构造一个JMP跳转后的字节, 就用下面的代码,其实和CALL差不多
void WriteCall(DWORD ProcAddr,LPVOID lpData)
{
BYTE _data[5];
_data[0]=0xE9;
DWORD OldPro;
VirtualProtect((LPVOID)(ProcAddr),5,PAGE_EXECUTE_READWRITE,&OldPro);
memcpy((LPVOID)(_data+1),lpData,4);//_data是变量的内存地址
memcpy((LPVOID)(ProcAddr),_data,5);
VirtualProtect((LPVOID)(ProcAddr),5,OldPro,&OldPro);//内存属性恢复为只读
}
RMC.exe+16650 - 89 15 56 34 12 00 - mov [00123456],edx
3、有的时候将某个寄存器数字比如上面的edx数值保存到 C语言变量X里面,就用下面的代码
void WriteMovEdx(DWORD ProcAddr,LPVOID lpData)
{
BYTE _data[6];
_data[0]=0x89;
_data[1]=0x15;
DWORD OldPro;
VirtualProtect((LPVOID)(ProcAddr),6,PAGE_EXECUTE_READWRITE,&OldPro);
memcpy((LPVOID)(_data+2),lpData,4);//_data是变量的内存地址
memcpy((LPVOID)(ProcAddr),_data,6);
VirtualProtect((LPVOID)(ProcAddr),6,OldPro,&OldPro);//内存属性恢复为只读
}
void WriteMovEax(DWORD ProcAddr,LPVOID lpData)
{
BYTE _data[6];
_data[0]=0x89;
_data[1]=0x05;
DWORD OldPro;
VirtualProtect((LPVOID)(ProcAddr),6,PAGE_EXECUTE_READWRITE,&OldPro);
memcpy((LPVOID)(_data+2),lpData,4);//_data是变量的内存地址
memcpy((LPVOID)(ProcAddr),_data,6);
VirtualProtect((LPVOID)(ProcAddr),6,OldPro,&OldPro);//内存属性恢复为只读
}
下面是具体调用如上函数的实际例子,在红月这个游戏上测试通过
有的时候将某个寄存器数字比如上面的edx数值保存到 遍历X里面,就用下面的代码
调用如下
DWORD x=0;
x=(DWORD)&x;//获取变量的内存地址
DWORD addr1=0x123456 ;
WriteMovEdx(addr1,&x); // 构建 mov [&x],edx
//下面是CALL的构造 JMP 跳转构造也是类似下面的
JMP 或者CALL后面的 地址对应的机器码计算 公式:目的代码地址 - 当前代码地址-5
DWORD ad1=hMod +0xAAA6C;
DWORD ad2=hMod2+0xD9C0 ;
DWORD cha =ad2-ad1-5; // 目的代码地址 - 当前代码地址-5
WriteCall(ad1,&cha); //call 打印字符的函数
QQ 1016058890