inline hook介绍

2014年06月11日 3776点热度 0人点赞 0条评论

说明

inline hook介绍(需要了解的基础知识只要汇编和windows api怎么用就可以了)

前几天刚刚介绍了iat hook,今天再聊聊inline hook,权当学习笔记。

不管程序语言如何发展,不论是面向过程还是面向对象,程序功能的实现一直都是一个一个的函数,因为现在CPU架构和指令的顺序执行特点决定了程序最终的执行是由指令流完成的。

那既然程序由一个一个函数组成,那么改变指令执行流程在函数层面的方法就是在调用函数的瞬间改变调用的函数,这样也就引出了一个

结论:我们要hook一个函数,就在函数开头的地方改变执行流程(至少在要hook的函数返回之前,否则hook就没意义了)。

注:我一直对hook这个词感到迷惑,在windows系统上,hook常常代表消息钩子,但是我觉得在api hook这个短语里面hook没有钩子这个意思,希望大牛能解释解释。

我们先定义几个东西:我们要HOOK的函数我们叫它P,我们要转入的函数叫QP的地址为&PQ的地址为&Q,那么PQ距离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

转载来自:【原创】inline hook

Sollyu

保持饥渴的专注,追求最佳的品质