不好意思,这个问题我已问过两次, dongfa(一个红角好多年了~~~) 、FengYuanMSFT(袁峰 www.fengyuan.com) 和 lcstudio(铁板牛牛) 已经答复过我。对于挂接API函数的方法大概有两种,
1)通过修改输入节中的函数地址,
2)用JMP指令修改函数的头几个字节(一般为七个字节)。对于第二种方法,我有个不懂的地方:修改函数的头几个字节是不是用来修改它的基址?函数的那个 头几个字节的形式是怎样的?为什么只是修改五个字节?而不是8个字节(地址)?请高手们指点迷津,谢谢!这是 dongfa(一个红角好多年了~~~) 回复的:指令如下:
// mov eax, pNewFuncAddr
// jmp eaxchar chOldCode[7]; // 备份旧函数地址前7个字节
char chNewCode[7]; // 新的数据
....DWORD dwTemp = (DWORD)pNewAddr;
chNewCode[0] = 0xB8;
memcpy(chNewCode + 1, &dwTemp, sizeof(DWORD));
chNewCode[5] = 0xFF;
chNewCode[6] = 0xE0;
谢谢 dongfa(一个红角好多年了~~~) 再问个问题:
这些字节各自代表着什么含义?这是 袁峰大哥 所答复的:0xB8 is the first byte of mov eax, pNewFuncAddre instruction
the rest 4 bytes are just the address0xFF 0xE0 should be jmp eax.In this code, 7 bytes are modified, so there needs to be saved.It's possible to modify 5 bytes only using relative jump instruction: pProc[0] = 0xE9;
* (unsigned *) (pProc+1) = (unsigned)pNewProc - (unsigned) (pProc+5);Check http://www.fengyuan.com/article/wmprint.html这是 铁板牛牛 所回复的:修改函数的头几个字节就是把入口第1,2条汇编指令变成
mov eax,你的处理代码入口
jmp eax
实现控制权的获得现还有几个问题:
1)能否给出函数头字节码的比较清晰的结构,前面dongfa、袁峰大哥、铁板牛牛 所回复的都只是告诉我怎样去用以及各自的意义,但没有说明其作用。我所知道的只是知道第二个字节到第五个字节是用来存放函数地址的。第一字节好像是用来存放指令,而这个指令是否用来操作接下来的那个函数地址字节?第六、第七个字节的作用又是什么?为什么有时可以不用?
2)当为第一个字节赋值JMP机器指令时,好像可以有两种形式:一个是0xEA,一个是0xE9,它们各代表什么指令,是不是第二个是用来跳转到相对地址的?
再者,各位大哥,能否提供全部的机器指令代码?谢谢!
3)* (unsigned *) (pProc+1) = (unsigned)pNewProc - (unsigned) (pProc+5);这个语句不大懂。
好像如果前面pProc[0] = 0xEA,那么是否可以不用后边的 - (unsigned) (pProc+5) ?请高手牛人大哥们回答一下。
谢谢!
1)通过修改输入节中的函数地址,
2)用JMP指令修改函数的头几个字节(一般为七个字节)。对于第二种方法,我有个不懂的地方:修改函数的头几个字节是不是用来修改它的基址?函数的那个 头几个字节的形式是怎样的?为什么只是修改五个字节?而不是8个字节(地址)?请高手们指点迷津,谢谢!这是 dongfa(一个红角好多年了~~~) 回复的:指令如下:
// mov eax, pNewFuncAddr
// jmp eaxchar chOldCode[7]; // 备份旧函数地址前7个字节
char chNewCode[7]; // 新的数据
....DWORD dwTemp = (DWORD)pNewAddr;
chNewCode[0] = 0xB8;
memcpy(chNewCode + 1, &dwTemp, sizeof(DWORD));
chNewCode[5] = 0xFF;
chNewCode[6] = 0xE0;
谢谢 dongfa(一个红角好多年了~~~) 再问个问题:
这些字节各自代表着什么含义?这是 袁峰大哥 所答复的:0xB8 is the first byte of mov eax, pNewFuncAddre instruction
the rest 4 bytes are just the address0xFF 0xE0 should be jmp eax.In this code, 7 bytes are modified, so there needs to be saved.It's possible to modify 5 bytes only using relative jump instruction: pProc[0] = 0xE9;
* (unsigned *) (pProc+1) = (unsigned)pNewProc - (unsigned) (pProc+5);Check http://www.fengyuan.com/article/wmprint.html这是 铁板牛牛 所回复的:修改函数的头几个字节就是把入口第1,2条汇编指令变成
mov eax,你的处理代码入口
jmp eax
实现控制权的获得现还有几个问题:
1)能否给出函数头字节码的比较清晰的结构,前面dongfa、袁峰大哥、铁板牛牛 所回复的都只是告诉我怎样去用以及各自的意义,但没有说明其作用。我所知道的只是知道第二个字节到第五个字节是用来存放函数地址的。第一字节好像是用来存放指令,而这个指令是否用来操作接下来的那个函数地址字节?第六、第七个字节的作用又是什么?为什么有时可以不用?
2)当为第一个字节赋值JMP机器指令时,好像可以有两种形式:一个是0xEA,一个是0xE9,它们各代表什么指令,是不是第二个是用来跳转到相对地址的?
再者,各位大哥,能否提供全部的机器指令代码?谢谢!
3)* (unsigned *) (pProc+1) = (unsigned)pNewProc - (unsigned) (pProc+5);这个语句不大懂。
好像如果前面pProc[0] = 0xEA,那么是否可以不用后边的 - (unsigned) (pProc+5) ?请高手牛人大哥们回答一下。
谢谢!
#include <windows.h>
using namespace std;void new_func()
{
cout << "new_func" << endl;
}int main()
{
char pNewFuncAddr[7] = { '\0' };
pNewFuncAddr[0] = (char)0xB8;
DWORD dwAddr = (DWORD)new_func;
memcpy(pNewFuncAddr+1,&dwAddr,sizeof(DWORD));
pNewFuncAddr[5] = (char)0xFF;
pNewFuncAddr[6] = (char)0xE0;
/**********************
*b8 9c 5e 41 00 ff e0 *
**********************/
/*
(*(void)(*)()(&pNewFuncAddr))();
转换有局限性:void(*)()
*/
_asm
{
lea eax,[pNewFuncAddr];
call eax;
}
/*************************
*lea eax,[pNewFuncAddr] *
*call eax *
*************************
||
\ || /
\\//
\/
*************************
*b8 mov eax *
*9c *
*5e *
*41 00415e9c *
*00 *
*ff e0 jmp eax *
*************************/
return 0;
}