首页
社区
课程
招聘
[原创]inline hook
发表于: 2014-5-27 19:11 27083

[原创]inline hook

2014-5-27 19:11
27083

inline hook介绍(需要了解的基础知识只要汇编和windows api怎么用就可以了)
        前几天刚刚介绍了iat hook,今天再聊聊inline hook,权当学习笔记。
        不管程序语言如何发展,不论是面向过程还是面向对象,程序功能的实现一直都是一个一个的函数,因为现在CPU架构和指令的顺序执行
特点决定了程序最终的执行是由指令流完成的。
        那既然程序由一个一个函数组成,那么改变指令执行流程在函数层面的方法就是在调用函数的瞬间改变调用的函数,这样也就引出了一个
结论:我们要hook一个函数,就在函数开头的地方改变执行流程(至少在要hook的函数返回之前,否则hook就没意义了)。注:我一直对hook
这个词感到迷惑,在windows系统上,hook常常代表消息钩子,但是我觉得在api hook这个短语里面hook没有钩子这个意思,希望大牛能解释解
释。
        我们先定义几个东西:我们要HOOK的函数我们叫它P,我们要转入的函数叫Q,P的地址为&P,Q的地址为&Q,那么P和Q的距离S就是&P-&Q。
        要在函数开头更改执行流程,常见的做法就是直接插入一个JMP指令,JMP指令后跟上S-5,为什么不是S呢?我觉得可以讲讲,很多文章都
没见讲过。假设CPU现在有一个执行流程:ABCDEF,每个字母代表一条CPU指令,现在假设EIP指向A,好,CPU要执行A就要先把A
装进CPU,在A被装进CPU而且A还没有被执行的时候,EIP就已经指向B了,这个时候如果A是一条JMP指令,假设是JMP 0x2
,刚刚不是说在A执行之前EIP就已经指向B了么,那执行完A后,EIP就指向B+2。理解了前面这段我们就可以看要从P跳到Q,JMP
后面需要跟什么了。因为JMP指令在被装入CPU还没执行的时候,EIP已经指向&Q+5了(我们一般用的0xe9这条jmp指令,后面跟上4字节的偏移
地址,一共5个字节),那么现在要在jmp执行完后EIP=&P,我们假设jmp后面是X,那么就是X+&Q+5=&P,那么X=&P-&Q-5=S-5,很好,我们已经
推出了jmp后面需要的偏移了。
        虽然讲了半天,不过我不准备用jmp,我更喜欢push+ret来完成这个任务,虽然多了一个字节(如果我们先把&Q放到寄存器里,反而只需要两个字节就够了),不过理解方便,编写方便。
        很明显,我要在&P那里把指令修改为下面这两条指令:
        push &Q
        ret
        简单直接。
        原理讲完了,我们就看看怎么做:我们来hook这个api函数:ExitProcess。
        首先得到ExitProcess函数的地址,不过我们不能直接就去修改它开头的字节,因为这个页面是属于代码页,一般的属性是不可写的,所以
先修改页属性,然后就可以修改了,最后我们调用这个函数,可以看到效果。
        简单实现:
        .386
    .model flat,stdcall
    option casemap:none

include    \masm32\include\windows.inc
include    \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include    \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

;数据段
    .data
    ;reservebytes db 10h dup(090h) 本来是准备hook完了再改回去的,但是懒得写了,能做演示作用足够了
    kernel32dll db "kernel32.dll",0h
    hkernel32 dd 0h
    exitprocessname db "ExitProcess",0h
    hexitprocess dd 0h
    sztext db "你以为点确定就可以退出?",0h
    sztitle db "hooked" , 0h
    errortext db "error",0h
    errortitle db "error",0h
    oldprotect dd 0h
;数据段?
    .data?
       

;代码段
    .code
    newexitprocess proc p1:dword
    invoke MessageBoxA,NULL,addr sztext,addr sztitle,MB_OK
    newexitprocess endp
start:
        main proc
        invoke GetModuleHandle,addr kernel32dll
        invoke GetProcAddress , eax , addr exitprocessname
        mov hexitprocess,eax
        invoke VirtualProtect,eax,2h,PAGE_EXECUTE_READWRITE,addr oldprotect
        test eax,eax
        jz fuck
        lea eax,newexitprocess
        call overtrash
        push eax
        ret
        overtrash:
        pop esi
        mov edi,hexitprocess
        movsw
        invoke ExitProcess,NULL
        jmp overfuck
        fuck:
                invoke MessageBoxA,NULL,addr errortext,addr errortitle,MB_OK
        overfuck:
        ret
        main endp
end start


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

收藏
免费 4
支持
分享
最新回复 (14)
雪    币: 2895
活跃值: (3929)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
简单直接
2014-5-27 19:13
0
雪    币: 68
活跃值: (190)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这就是用ASM来写的基本HOOK
2014-5-27 19:16
0
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
虽然暂时看不懂,但简介直白的气质依然能感觉到,收藏先,总有一天会看懂的
2014-5-27 20:37
0
雪    币: 330
活跃值: (105)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
表示菜鸟居然看懂了。
2014-6-11 11:31
0
雪    币: 346
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
还可以这样hook!
2015-6-1 09:39
0
雪    币: 291
活跃值: (213)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
7
这篇帖子作为新手教程,非常棒!不过,我补充解释一下为什么实际的Hook用jmp的比较多,而push-ret相对比较少。

push-ret不用算相对偏移,用起来确实方便。但和jmp相比多了一个字节。毕竟Hook的目的是监控和操纵被Hook函数的行为,多数情况下,还是需要调用原来函数的。这时候,多了一个字节就意味着可能会覆盖更多的指令内容,从而带来不必要的麻烦。例如这种入口:
mov edi, edi
push ebp
mov ebp, esp  ; *    到这里正好5个字节
call XXXXXXXX ; **  麻烦来了
....

原本用jmp的话,只会覆盖到*。构建调用原函数的跳板,只需要把前三条指令拷贝下来即可。如果是push-ret,会覆盖6字节,从而覆盖到**处。而**处指令是call,带的是相对偏移,要构建跳板时,需要手动修正相对偏移,增加了不必要的难度。还有一种情况是,覆盖的区域超出了被Hook函数入口第一个Basic Block的长度,从而可能会导致BB间的跳转出现问题。覆盖的指令序列越长,越有可能遇到麻烦。
除了jmp之外,call指令也是不错的选择,因为长度和jmp一样,还能知道是从哪个函数的hook来的(看压栈地址),从而方便实现统一的hook管理入口。
2015-6-1 13:23
0
雪    币: 118
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
学习了,看雪有你更精彩
2015-6-1 14:58
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
收藏先!谢谢
2015-6-4 13:01
0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
LZ,如何对exe或者sys之类的PE文件修改,实现inline hook?
尤其是jmp 地址,  这里,这个地址肯定是一个我们自己的区域,在exe或sys中如何确定哪一块是安全的,运行我们的代码的时候不会有别人执行到这里?

可否添加到exe或sys文件末尾?  如果添加到exe或者sys文件末尾,PE头什么的需要做哪些修改?
2015-7-8 22:39
0
雪    币: 45
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习学习
2016-3-24 17:00
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
看雪的内容都这么好,为什么网站就是好像没有ui的样子
2016-12-2 14:39
0
雪    币: 0
活跃值: (150)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
mark!!!!
2017-4-28 17:13
0
雪    币: 160
活跃值: (209)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
push  XXXXXXXX
ret
真不错。。。。。。
2017-5-7 09:57
0
雪    币: 8195
活跃值: (6419)
能力值: ( LV12,RANK:207 )
在线值:
发帖
回帖
粉丝
15
很细节,谢谢大佬
2019-10-5 20:03
0
游客
登录 | 注册 方可回帖
返回
//