首页
社区
课程
招聘
[求助]菜鸟的一个令人郁闷至极的Inline Hook的问题。
发表于: 2007-7-18 22:31 6894

[求助]菜鸟的一个令人郁闷至极的Inline Hook的问题。

2007-7-18 22:31
6894
之前看的教程都是先修改了函数的前5字节让函数流程跳到自己的函数,然后恢复原来的字节让原函数继续执行,显然这里有着不可解决的多线程问题。
在内核下也可Inline Hook,IS、Rku都是Inline Hook来进行保护的。看了Rootkit:Subverting the windows kernel里面介绍的内核Hook之后,我修改了下(也在别人的大力帮助下),在Ring0下测试成功。但是在Ring3下模拟了下却出错了,下面是代码,麻烦帮帮小弟,小弟在此谢过了,请各位大虾不吝赐教!!代码教烂,鄙视就鄙视吧~教会我就可以。

说明:MessageBoxA能正常弹出,mian函数能正常接受到返回值,然后就出错 OD调试执行到了一个无法读取的地址。。。。。
代码:

_declspec(naked) int ExecOrig(HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType)
{                      //用来填充,执行被Hook的代码。
        __asm
        {
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
        }
}  

int HookFunc(
        HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType)
{
        DWORD OrigESP;  //保存原来的esp,之前没保存返回不到main
        int bRet;
        __asm
        {
                mov OrigESP,esp
        }
        //打印参数,证明Hook到了
        printf("In MyMsgBox,the params:\n%s\n%s\n",lpText,lpCaption);
        bRet = ExecOrig(hWnd,lpText,lpCaption,uType);
        //打印返回值,证明能得到返回值
        printf("\nIn MyMsgBox,the return Value:\n%d\n",bRet);
        //恢复esp,让函数正常返回。否则回不到main
        __asm
        {
                mov esp,OrigESP
        }
        return bRet;
}

int main()
{
        int nRet;
        int i = 0;
        BYTE jmp[5];  //覆盖MessageBoxA前的5字节代码
        BYTE Old[5];  //保存MessageBoxA原来的代码
        BYTE JmptoOrig[5]; //跳到下一指令
        DWORD dwOld;   //内存保护

        jmp[0] = 0xE9;  //jmp ***
        //得到地址(相对地址)
        *((DWORD *)(jmp + 1)) = (DWORD) ((DWORD)HookFunc - (DWORD)MessageBoxA - 5);

        memcpy( Old,MessageBoxA,5);//保存原函数前5字节
        JmptoOrig[0] = 0xE9;
       
        //需要往回跳的地址
        *((DWORD *)(JmptoOrig + 1)) = (DWORD)MessageBoxA - (DWORD)ExecOrig - 5;

        ::VirtualProtectEx(::GetCurrentProcess(),
                                                ExecOrig,
                                                10,
                                                PAGE_READWRITE,
                                                &dwOld);

        memcpy( ExecOrig,Old,5 );   //写入原来的指令
        memcpy( (void *)((DWORD)ExecOrig + 5),JmptoOrig,5 ); //让函数跳到下面的指令,维持流程

        ::VirtualProtectEx(::GetCurrentProcess(),
                                                ExecOrig,
                                                10,
                                                dwOld,
                                                &dwOld);

        ::VirtualProtectEx(::GetCurrentProcess(),
                                                MessageBoxA,
                                                5,
                                                PAGE_READWRITE,
                                                &dwOld);
        memcpy( MessageBoxA,jmp,5);  //修改MesasgeBoxA的前5字节,让它跳到Hook。
        ::VirtualProtectEx(::GetCurrentProcess(),
                                                MessageBoxA,
                                                5,
                                                dwOld,
                                                &dwOld);
        nRet = ::MessageBox(0,"Test","Test",0); //测试
        printf("\nIn Main,the return:\n%d",nRet);//测试返回值。
        return 0;
}

//========================================
这里是执行结果:
In MyMsgBox,the params:
Test
Test

In MyMsgBox,the return Value:
1

In Main,the return:
1  //到这里就出错了,郁闷至极

以下是源码和exe。

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
来帮帮忙吧~OK?
2007-7-19 13:03
0
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
简单地拷贝MessageBoxA的头5个字节是会出问题的。

你应该用反汇编函数分析MessageBoxA的入口代码,确保将受影响的指令完整复制到ExecOrig。
2007-7-21 03:42
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
看过了
不会出现指令碎屑。
2007-7-21 21:16
0
雪    币: 331
活跃值: (57)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
今天看到好多Inline Hook;
云舒的<<简单说说SSDT>>
http://www.icylife.net/yunshu/index.php?sortid=2
2007-7-22 22:21
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
和SSDT有什么关系?



看SSDT Hook还是Rootkit:《Subveting the windows kernel》不错
2007-7-23 15:04
0
雪    币: 1489
活跃值: (235)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
MessageBoxA要复制11字节的代码才完整。我改了改,在VC6下能通过。

#include <windows.h>
#include <stdio.h>

_declspec(naked) int ExecOrig(HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType)
{
        __asm
        {
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
        }
}  

int HookFunc(
        HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType)
{
        DWORD OrigESP;
        int bRet;
        __asm
        {
                mov OrigESP,esp
        }
        printf("In MyMsgBox,the params:\n%s\n%s\n",lpText,lpCaption);
        bRet = ExecOrig(hWnd,lpText,lpCaption,uType);
        printf("\nIn MyMsgBox,the return Value:\n%d\n",bRet);
        __asm
        {
                mov esp,OrigESP
        }
        return bRet;
}

int main()
{
        int nRet;
        int i = 0;
        BYTE jmp[5];
        BYTE Old[5];
        BYTE JmptoOrig[5];
        DWORD dwOld;

        jmp[0] = 0xE9;
        *((DWORD *)(jmp + 1)) = (DWORD) ((DWORD)HookFunc - (DWORD)MessageBoxA - 5);

        memcpy( Old,MessageBoxA,5);
        JmptoOrig[0] = 0xE9;
       
        *((DWORD *)(JmptoOrig + 1)) = (DWORD)MessageBoxA - (DWORD)ExecOrig - 5;

        ::VirtualProtectEx(::GetCurrentProcess(),
                                                ExecOrig,
                                                10,
                                                PAGE_READWRITE,
                                                &dwOld);

        memcpy( ExecOrig,Old,5 );
        memcpy( (void *)((DWORD)ExecOrig + 5),JmptoOrig,5 );

        ::VirtualProtectEx(::GetCurrentProcess(),
                                                ExecOrig,
                                                10,
                                                dwOld,
                                                &dwOld);

        ::VirtualProtectEx(::GetCurrentProcess(),
                                                MessageBoxA,
                                                5,
                                                PAGE_READWRITE,
                                                &dwOld);
        memcpy( MessageBoxA,jmp,5);
        ::VirtualProtectEx(::GetCurrentProcess(),
                                                MessageBoxA,
                                                5,
                                                dwOld,
                                                &dwOld);
        nRet = ::MessageBox(0,"Test","Test",0);
        printf("\nIn Main,the return:\n%d",nRet);
        return 0;
}
2007-9-3 09:45
0
雪    币: 125
活跃值: (35)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
看了看MessageBoxA前5字节刚好合适,不知道楼上的为什么说要取11个才完整
个人估计是堆栈平衡得有问题......
我还没有遇到过这样的情况,实现方法有点不大一样
2007-9-3 14:00
0
雪    币: 1489
活跃值: (235)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这是我机器上MessageBoxA的前部分代码。

77E13259 55                   push        ebp
77E1325A 8B EC                mov         ebp,esp
77E1325C 51                   push        ecx
77E1325D 83 3D 58 3B E4 77 00 cmp         dword ptr ds:[77E43B58h],0
2007-9-3 17:59
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
10
我来调试看看
2007-9-3 22:15
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
11
nRet = ::MessageBox(0,"Test","Test",0);
        __asm
        {
                add esp,4
        }
这样就可以了,估计是参数传递了2次缘故.
2007-9-3 22:51
0
游客
登录 | 注册 方可回帖
返回
//