学习windows 应用层 inline hook 原理总结
2015-12-23 18:21
405 查看
inline hook 实际上就是指 通过改变目标函数头部的代码来使改变后的代码跳转到我们自己设置的一个函数里,产生hook。
今天就拿MessageBoxA这个api函数来做实验。功能就是当程序调用MessageBoxA 时,我们打印出MessageBoxA的参数
大概代码结构应该是这样
我们先看看汇编是怎样调用MessageBoxA的
![](http://images.cnitblog.com/blog/174805/201304/08120346-9a12a49e3b7b452783165a3ef0dcca97.jpg)
首先看到,MessageBoxA里面
mov edi,edi
mov ebp
mov ebp,esp
刚好是5个字节,5个字节可以做一个远jmp
直接汇编改成我们自己的jmp
改后结果如下
![](http://images.cnitblog.com/blog/174805/201304/08120347-c81a43bbd1ef4a0791d81f34e73df06c.png)
单步执行发现hook成功。但程序崩溃。原因主要是由于
我们破坏了真正的MessageBox使们想要调用真正的MessageBox时也会调用失败了,所以我们要调用真正的MessageBox时要加上头部被我们换掉的部分,我们要内联汇编,里面不能含有编译器自动添加的代码,所以在myMessageBox头部要加上 _declspec(naked)
vs2010的debug版本每执行一个函数都要 cmp esi,esp 来验证堆栈的。所以还要加一句push esi 和pop esi
下面说一下用代码来写MessageBoxA着呢5个字节
首先要懂得 JMP指令转换公式推导 不懂的话 看 http://www.cnblogs.com/zhangdongsheng/archive/2012/12/06/2804234.html
先声明一个JMP结构体。注意前面加 #pragma pack(1)来避免内存对齐的一些规则
接下来写hook函数
现在测试成功。
![](http://images.cnitblog.com/blog/174805/201304/08120348-3c0811fe50924dba9d0561e1bf5f6536.png)
完整源代码如下:
出处:http://www.cnblogs.com/zhangdongsheng/
作者:张东升 QQ:290387340
今天就拿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的
![](http://images.cnitblog.com/blog/174805/201304/08120346-9a12a49e3b7b452783165a3ef0dcca97.jpg)
首先看到,MessageBoxA里面
mov edi,edi
mov ebp
mov ebp,esp
刚好是5个字节,5个字节可以做一个远jmp
直接汇编改成我们自己的jmp
改后结果如下
![](http://images.cnitblog.com/blog/174805/201304/08120347-c81a43bbd1ef4a0791d81f34e73df06c.png)
单步执行发现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指令转换公式推导 不懂的话 看 http://www.cnblogs.com/zhangdongsheng/archive/2012/12/06/2804234.html
先声明一个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); }
现在测试成功。
![](http://images.cnitblog.com/blog/174805/201304/08120348-3c0811fe50924dba9d0561e1bf5f6536.png)
完整源代码如下:
// hook_blog_writer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
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://www.cnblogs.com/zhangdongsheng/
作者:张东升 QQ:290387340
相关文章推荐
- jQuery 插件--jQuery.timers
- 建立Maven私服 - Nexus (七)
- 正则表达式
- bootstrap实现弹出窗口
- ARduino - 用Arduino主板调试蓝牙模块
- memcached的安装
- RMAN实战11:数据文件的恢复
- 初次使用netfilter,写了一个禁止ping命令的小程序
- Spring 注释实现任务调度
- Hibernate常用方法之get
- Maven的聚合和继承(六)
- Codeforces #252 (Div. 2) B. Valera and Fruits
- Spring in Action读书笔记 (二)
- KVC
- 在XP系统上运行win7 sp1 ADO程序 800401f3 GetLastError 14000 Error_sxs_section_not_found
- 浅析:手游智能云更新使用方法
- 经典算法之线切面 (2)排序
- windows下杀进程
- 关于UGUI图集AssetBundle的加载与释放
- Linux下apache tomcat集群搭建