欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]inline hook

[原创]inline hook

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

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功