博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习windows 应用层 inline hook 原理总结
阅读量:6457 次
发布时间:2019-06-23

本文共 3831 字,大约阅读时间需要 12 分钟。

inline hook 实际上就是指 通过改变目标函数头部的代码来使改变后的代码跳转到我们自己设置的一个函数里,产生hook。

今天就拿MessageBoxA这个api函数来做实验。功能就是当程序调用MessageBoxA 时,我们打印出MessageBoxA的参数

 

大概代码结构应该是这样

typedef int (WINAPI    *MessageBox_type) (    __in_opt HWND hWnd,    __in_opt LPCSTR lpText,    __in_opt LPCSTR lpCaption,    __in UINT uType) ;MessageBox_type RealMessageBox;//我们自己的MessageBox,每调用MessageBox都要跳到myMessageBox来处理int WINAPI    myMessageBox(    __in_opt HWND hWnd,    __in_opt LPCSTR lpText,    __in_opt LPCSTR lpCaption,    __in UINT uType){    //下面打印MessageBox参数    printf("hwnd:%8X lpText:%s lpCaption:%s,uType:%8X",hWnd,lpText,lpCaption,uType);     return RealMessageBox(hWnd,lpText,lpCaption,uType); //现在开始调用真正的MessageBox}VOID HookMessageBoxA(){}int _tmain(int argc, _TCHAR* argv[]){    HookMessageBoxA();  //hook操作    ::MessageBoxA(NULL,"hook test","tip",MB_OK); //执行api MessageBox    return 0;}

我们先看看汇编是怎样调用MessageBoxA的

 

首先看到,MessageBoxA里面

mov edi,edi 

mov ebp 
mov ebp,esp 
刚好是5个字节,5个字节可以做一个远jmp

直接汇编改成我们自己的jmp

改后结果如下

单步执行发现hook成功。但程序崩溃。原因主要是由于

我们破坏了真正的MessageBox使们想要调用真正的MessageBox时也会调用失败了,所以我们要调用真正的MessageBox时要加上头部被我们换掉的部分,我们要内联汇编,里面不能含有编译器自动添加的代码,所以在myMessageBox头部要加上 _declspec(naked)

vs2010的debug版本每执行一个函数都要 cmp esi,esp 来验证堆栈的。所以还要加一句push esi 和pop esi

//我们自己的MessageBox,每调用MessageBox都要跳到myMessageBox来处理_declspec(naked)  void WINAPI    myMessageBox(    __in_opt HWND hWnd,    __in_opt LPCSTR lpText,    __in_opt LPCSTR lpCaption,    __in UINT uType){        __asm    {        PUSH ebp        mov ebp,esp        /*        vs2010 debug 编译后的代码由于要cmp esi esp来比较堆栈。        所以这里在调用非__asm函数前push一下esi        */        push esi    }    //下面打印MessageBox参数    printf("hwnd:%8X lpText:%s lpCaption:%s,uType:%8X",hWnd,lpText,lpCaption,uType);     __asm    {        /*        vs2010 debug 编译后的代码由于要cmp esi esp来比较堆栈。        所以这里在调用非__asm函数前push一下esi        */        pop esi        mov ebx,RealMessageBox        add ebx,5        jmp ebx    }}

下面说一下用代码来写MessageBoxA着呢5个字节

首先要懂得   不懂的话 看 

 

先声明一个JMP结构体。注意前面加 #pragma pack(1)来避免内存对齐的一些规则

#pragma pack(1)typedef struct _JMPCODE{    BYTE jmp;    DWORD addr;}JMPCODE,*PJMPCODE;

接下来写hook函数

VOID HookMessageBoxA(){    JMPCODE jcode;    jcode.jmp = 0xe9;//jmp    jcode.addr = (DWORD)myMessageBox - (DWORD)RealMessageBox - 5;     RealMessageBox = MessageBoxA;    ::WriteProcessMemory(GetCurrentProcess(),MessageBoxA,&jcode,sizeof(JMPCODE),NULL);}

现在测试成功。

 

完整源代码如下:

// hook_blog_writer.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include 
#include
typedef int (WINAPI *MessageBox_type) ( __in_opt HWND hWnd, __in_opt LPCSTR lpText, __in_opt LPCSTR lpCaption, __in UINT uType) ;MessageBox_type RealMessageBox = MessageBoxA;//我们自己的MessageBox,每调用MessageBox都要跳到myMessageBox来处理_declspec(naked) void WINAPI myMessageBox( __in_opt HWND hWnd, __in_opt LPCSTR lpText, __in_opt LPCSTR lpCaption, __in UINT uType){ __asm { PUSH ebp mov ebp,esp /* vs2010 debug 编译后的代码由于要cmp esi esp来比较堆栈。 所以这里在调用非__asm函数前push一下esi */ push esi } //下面打印MessageBox参数 printf("hwnd:%8X lpText:%s lpCaption:%s,uType:%8X",hWnd,lpText,lpCaption,uType); __asm { /* vs2010 debug 编译后的代码由于要cmp esi esp来比较堆栈。 所以这里在调用非__asm函数前push一下esi */ pop esi mov ebx,RealMessageBox add ebx,5 jmp ebx }}#pragma pack(1)typedef struct _JMPCODE{ BYTE jmp; DWORD addr;}JMPCODE,*PJMPCODE;VOID HookMessageBoxA(){ JMPCODE jcode; jcode.jmp = 0xe9;//jmp jcode.addr = (DWORD)myMessageBox - (DWORD)RealMessageBox - 5; RealMessageBox = MessageBoxA; ::WriteProcessMemory(GetCurrentProcess(),MessageBoxA,&jcode,sizeof(JMPCODE),NULL);}int _tmain(int argc, _TCHAR* argv[]){ HookMessageBoxA(); //hook操作 ::MessageBoxA(NULL,"hook test","tip",MB_OK); //执行api MessageBox return 0;}

 

 

出处:
作者:

转载地址:http://shizo.baihongyu.com/

你可能感兴趣的文章
ORACLE功能GREATEST功能说明具体实例
查看>>
DataGridView 输入数据验证格式(实例)
查看>>
HDOJ 2151
查看>>
Foundation框架 - 快速创建跨平台的网站页面原型
查看>>
open-falcon
查看>>
三菱plc输出指示灯不亮怎么办(转载)
查看>>
doc2vec使用说明(一)gensim工具包TaggedLineDocument
查看>>
Q:图像太大,在opencv上显示不完全
查看>>
修正锚点跳转位置 避免头部fixed固定部分遮挡
查看>>
利用ItextPdf、core-renderer-R8 来生成PDF
查看>>
irc操作小记
查看>>
NavigationController的使用
查看>>
多线程编程之Windows环境下创建新线程
查看>>
CentOS 7使用systemctl如何补全服务名称
查看>>
Unity3D NGUI 给button按钮添加单间事件
查看>>
密码的校验.大小写字母,数字,特殊字符中的至少3种
查看>>
ios 不同sdk4.3 6.0版本号,关于方法的兼容性的通用方法
查看>>
Shell编程学习总结
查看>>
Webstorm常用快捷键备忘
查看>>
js滚动加载到底部
查看>>