首页
论坛
课程
招聘
[原创]inline hook
2014-5-27 19:11 24129

[原创]inline hook

2014-5-27 19:11
24129
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

第五届安全开发者峰会(SDC 2021)10月23日上海召开!限时2.5折门票(含自助午餐1份)

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

push-ret不用算相对偏移,用起来确实方便。但和jmp相比多了一个字节。毕竟Hook的目的是监控和操纵被Hook函数的行为,多数情况下,还是需要调用原来函数的。这时