首页
社区
课程
招聘
inline hook的几个问题,求大神
发表于: 2013-4-6 23:20 7835

inline hook的几个问题,求大神

2013-4-6 23:20
7835
http://www.54kubi.cn/forum.php?mod=viewthread&tid=32
翻了一个inline hook的代码,大致原理大概知道了,有个函数不是很明白

BOOLEAN RelocateJumps(IN PVOID FuncPtr, IN ULONG Reloc, IN ULONG Length)
{
        ULONG Offset = 0, CodeLen;
        do {
                CodeLen = ade32_disasm((PVOID)((ULONG)FuncPtr + Offset));
                if (CodeLen == 0) return FALSE;
                switch (*(PUCHAR)((ULONG)FuncPtr + Offset)) {
                case 0x70:
                case 0x71:
                case 0x72:
                case 0x73:
                case 0x74:
                case 0x75:
                case 0x76:
                case 0x77:
                case 0x78:
                case 0x79:
                case 0x7a:
                case 0x7b:
                case 0x7c:
                case 0x7d:
                case 0x7e:
                case 0x7f:
                case 0xe0:
                case 0xe1:
                case 0xe2:
                case 0xe3:
                case 0xea:
                case 0xeb:
                        return FALSE;
                case 0xe8:
                case 0xe9:
                        *(PULONG)((ULONG)FuncPtr + Offset + 1) -= Reloc;
                        break;
                }
                Offset += CodeLen;
        } while (Offset < Length);
        return TRUE;
}

HOOK的代码是这样写的

        ULONG uCodeLen = MeasureCodeLength(NtOpenProcess, 5);
        g_OriginalNtOpenProcess = (ULONG)NtOpenProcess + uCodeLen;
        memcpy(g_szBackCode, NtOpenProcess, uCodeLen);

        RelocateJumps(NtOpenProcess, (ULONG)FuckNtOpenProcess - (ULONG)NtOpenProcess, uCodeLen);
        WriteJump(NtOpenProcess, FuckNtOpenProcess);

这个第一个是获取一个5字节以上的完整的汇编长度,然后保存汇编指令。

后面一条是在头上写入5字节跳转指定,但是中间这个是啥意思啊,也不知道他想干嘛
那一段标红的赋值也不知道啥意思~~

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
2
jmp指令需要一个操作数,OffSet
jmp OffSet

这个OffSet是当前指令地址和目标函数地址的差值,需要计算出来
RelocateJumps(NtOpenProcess, (ULONG)FuckNtOpenProcess - (ULONG)NtOpenProcess, uCodeLen);

这条语句的作用就是计算这个OffSet
2013-4-6 23:25
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
不是吧 那个writejump函数是这样的
VOID WriteJump(PVOID FuncPtr, PVOID JumpPtr)
{
        KIRQL OldIrql;
        UCHAR Buffer[5];
        Buffer[0] = 0xe9;
       *(PULONG)&Buffer[1] = (ULONG)JumpPtr - ((ULONG)FuncPtr + 5);
        OldIrql = KeRaiseIrqlToDpcLevel();
    __asm
    {
        cli;
        push eax;
        mov eax, cr0;
        and eax, 0FFFEFFFFh;
        mov cr0, eax;
        pop eax;
    }
       // *(PUSHORT)FuncPtr = 0xfeeb;
       // RtlMoveMemory((PUCHAR)FuncPtr + 2, (PUCHAR)Buffer + 2, 3);
       // *(PUSHORT)FuncPtr = *(PUSHORT)Buffer;
RtlMoveMemory((PUCHAR)FuncPtr, (PUCHAR)Buffer, 5);//我修改了一下
    __asm
    {
        push eax;
        mov eax, cr0;
        or eax, 10000h;
        mov cr0, eax;
        pop eax;
        sti;
    }
        KeLowerIrql(OldIrql);
}

我怎么看这个才是计算跳转的地址啊。。。
2013-4-7 00:02
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
他是看被替换的指令 里面有JMP的 做特殊处理
2013-4-7 09:43
0
雪    币: 11
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
原函数前面如果有 jmp 跳转 就是已经被 HOOk了  那么直接改写 跳转目的地址 到我们的HOOK函数  楼主这几个函数的调用还是做下判断吧  不是;一连串下来的
2013-4-7 10:08
0
雪    币: 11
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
还想说的是  原先作者     
// *(PUSHORT)FuncPtr = 0xfeeb;
       // RtlMoveMemory((PUCHAR)FuncPtr + 2, (PUCHAR)Buffer + 2, 3);
       // *(PUSHORT)FuncPtr = *(PUSHORT)Buffer;
这样写 也是有用意的  先修改前面的指令为死循环 这样即使后面的修改被打断 (当然中断都关了 这有点不可能)也不会出错
2013-4-7 10:19
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=dancebaby;1162503]不是吧 那个writejump函数是这样的
VOID WriteJump(PVOID FuncPtr, PVOID JumpPtr)
{
        KIRQL OldIrql;
        UCHAR Buffer[5];
        Buffer[0] = 0xe9;
...[/QUOTE]

擦。。。。我的错,我只看了一眼下面的代码

如楼上所说,那个函数是判断目标函数入口是否已经有jmp指令了

至于你的整体代码片段看不出来是干什么用的。
2013-4-7 13:28
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
这个意思是说他是想检测一下前面是不是jmp?如果不是就不写了么?
*(PULONG)((ULONG)FuncPtr + Offset + 1) -= Reloc; 我看这个赋值像是 如果检测到第一个是E8或者E9的话,就直接往他后面写一个地址,但是这个地址这么计算 我实在想不明白呢。。。

这个代码是不是应该判断一下reloc这个函数,如果返回是真的就不再直接把前5个字节写入了呢。。
2013-4-7 23:29
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
E8,E9操作码后跟一个4字节ULONG值,该值的计算方法为:
设E8或E9操作码所在内存地址为uE8E9,要跳转到(E9-jmp)或要调用函数(E8-Call)的绝对地址为uDecAdr,则E8,E9操作码后跟一个4字节ULONG值
   uSize=uDecAdr-uE8E9-5
    即相对跳转(调用)距离=目的地址-当前操作码所在地址-5
2013-4-8 10:46
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
我知道这个是这么算的关键是 我想知道这个
RelocateJumps(NtOpenProcess, (ULONG)FuckNtOpenProcess - (ULONG)NtOpenProcess, uCodeLen);

这个的第二个参数传递的是(ULONG)FuckNtOpenProcess - (ULONG)NtOpenProcess,
后面写入的时候是在e8或者e9的后面写了一个 xx -=reloac,也就是xx = xx -reloac
= xx - ((ULONG)FuckNtOpenProcess - (ULONG)NtOpenProcess)=NtOpenProcess+1-(yy) = NtOpenProcess + NtOpenProcess - FuckNtOpenProcess  +1  这是个啥玩意啊。。。
2013-4-8 21:49
0
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
通过MeasureCodeLength找到一段>=5字节的完整指令后,需要检查下这段指令里是否有分支、跳转、子例程等指令,如果有则找到的指令段不适合inline hook即case break返回FALSE的(因为这几个字节的指令是你要保存好在你的hook函数里执行的,然后再跳回来执行原函数剩下的代码,由于你hook函数的地址和原函数的地址肯定不一样,相关指令在hook函数里执行时地址偏移也就不一样了),但如果是e8和e9还可以直接把e8/e9的地址减去这样一个相对地址来得到新的偏移完成正确执行,也就是这里的*(PULONG)((ULONG)FuncPtr + Offset + 1) -= Reloc;这个赋值。
2013-4-8 22:30
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
e8/e9的地址减去准备hook的相对地址 为啥就是新的函数的地址呢。。。我上面写了一下那个计算式的展开,觉得这个地址很奇怪 所以我才问的呀。

另外还有个很无聊的问题,就是问啥不分支跳转,子例程不适合HOOK是因为??? 是因为跳回来的时候,补全这几个指令不好写?上下文已经变了?
2013-4-8 22:46
0
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
13
假设原函数在0x400000也就是你inline hook的几个指令处有个xx跳转,跳转的相对地址是n。由于你现在inline hook掉了,所以0x400000处的指令可能被你的jmp破坏了。你会在你的hook函数处做些处理后调回原函数,有一种做法是在你的hook函数里先执行被你的jmp破坏的原函数代码,再跳转到原函数后面的地址继续。这时候会发现你hook函数里执行的原函数的代码里有相对于原函数的偏移,指令执行肯定就有问题了。这就是为什么某些地方不适合inline hook,至于为什么e8/e9这么处理后是可以的,建议LZ自己画个跳转图看看。
2013-4-8 23:15
0
雪    币: 48
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
噢 我大概明白了,就是说如果要覆盖原来的JMP的话,之后我的函数里面不能直接把原来的JMP给写上去,要计算出一个值来跳过去,这个就是先计算出来后我们自己去执行的。。是这个情况咯?

我再画画看。。。
2013-4-9 08:07
0
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
15
正解。
2013-4-9 15:26
0
游客
登录 | 注册 方可回帖
返回
//