首页
社区
课程
招聘
[原创][封装]简单易用的Api Hook函数 - MyApiHookFun
发表于: 2015-6-7 22:48 8992

[原创][封装]简单易用的Api Hook函数 - MyApiHookFun

2015-6-7 22:48
8992
使用方法:
0.首先使用者请保证跑我的函数时已经注入到目标程序中
1.引用外部变量
extern DWORD *g_pApiAddr;
extern BYTE *g_pOldCode;
2.建立一个hook后工作函数

以下是hook后的测试函数
LPVOID _declspec(naked) WINAPI TestFun(LPVOID UnKnow1, LPVOID UnKnow2)
{
    ::MessageBox(NULL, TEXT("这是一个hook提示"), TEXT("提示"), NULL);

    //以下汇编不可动
    _asm
    {
        push g_pOldCode
        ret;
    }
}

3.调用
例子:
    MODULEAPI tagModuleAPI = {
        {TEXT("kernel32.dll"), "ExitProcess"},
    };
    MyApiHookFun(&tagModuleAPI,TestFun);
MyApiHookFun.h:
#pragma once
#include <windows.h>
//////////////////////////////////////////////////////////////////////////
//定义
typedef struct _MODULE_API
{
    TCHAR *pModuleName;
    char  *pApiName;
}MODULEAPI,*PMODULEAPI;
//////////////////////////////////////////////////////////////////////////
//函数声明
BOOL WINAPI MyApiHookFun(PMODULEAPI pModuleAPI, LPVOID pfnHookFun);

MyApiHookFun.cpp:
#include "MyApiHookFun.h"

DWORD g_dwApiAddr = NULL;
BYTE *g_pOldCode = NULL;
/************************************************************************
函数名字:BOOL WINAPI MyApiHookFun(PMODULEAPI pModuleAPI, LPVOID pfnHookFun)
功    能:API HOOK主函数
参  数 1:pModuleAPI  模块和api名字的数组
参  数 2:pfnHookFun  hook后执行的函数数组
返 回 值:TRUE - 成功/ FALSE - 失败
************************************************************************/
BOOL WINAPI MyApiHookFun(PMODULEAPI pModuleAPI, LPVOID pfnHookFun)
{
    char chE9 = (char)0xe9;
    TCHAR szTmp[MAX_PATH] = {0};
    DWORD dwPID = 0;
    BOOL bRet = FALSE;
    LPVOID pAllocAddr = NULL;
    DWORD dwOld = 0;
    HMODULE hModule = NULL;
    
    g_pOldCode = new BYTE[12];
    if (g_pOldCode == NULL)
    {
#ifdef _DEBUG
        ::OutputDebugString(TEXT("new g_pOldCode Error!"));
#endif
        return FALSE;
    }
    memset(g_pOldCode, 0, 12);

    //获得API地址
    hModule = ::GetModuleHandle(pModuleAPI->pModuleName);
    if (hModule == NULL)
    {
#ifdef _DEBUG
        ::OutputDebugString(TEXT("GetModuleHandle Error!"));
#endif
        return FALSE;
    }

    g_dwApiAddr = (DWORD)::GetProcAddress(hModule, pModuleAPI->pApiName);
    if (g_dwApiAddr == NULL)
    {
#ifdef _DEBUG
        ::OutputDebugString(TEXT("GetProcAddress Error!"));
#endif
        return NULL;
    }
    
    //改变内存属性 HOOK
    bRet = ::VirtualProtect((LPVOID)g_dwApiAddr,
                            5,
                            PAGE_EXECUTE_READWRITE,
                            &dwOld);
    if (bRet == FALSE)
    {
#ifdef _DEBUG
        wsprintf(szTmp, TEXT("VirtualProtect %08X Error!"), pApiAddr[i]);
        OutputDebugString(szTmp);
#endif
        return FALSE;
    }

    //shell code
    g_pOldCode[0] = (char)0xb8;
    *(DWORD *)(&g_pOldCode[1]) = g_dwApiAddr + 5;
    g_pOldCode[5] = *(BYTE *)g_dwApiAddr;
    *(DWORD *)(&g_pOldCode[6]) = *(DWORD *)(g_dwApiAddr + 1);
    g_pOldCode[10] = (char)0xff;
    g_pOldCode[11] = (char)0xe0;

    //写入
    *(BYTE *)g_dwApiAddr = 0xE9;
    *(DWORD *)(g_dwApiAddr + 1) = (DWORD)pfnHookFun - (g_dwApiAddr + 5);

    bRet = ::VirtualProtect((LPVOID)g_dwApiAddr,
                            5,
                            dwOld,
                            &dwOld);
    if (bRet == FALSE)
    {
#ifdef _DEBUG
        wsprintf(szTmp, TEXT("VirtualProtect2 %08X Error!"), pApiAddr[i]);
        OutputDebugString(szTmp);
#endif
        return FALSE;
    }
    return TRUE;
}


附件:

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (16)
雪    币: 94
活跃值: (445)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
通用性如何?支持X64么?
2015-6-8 08:08
0
雪    币: 341
活跃值: (133)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
喜欢这个。。。直接用上试试
2015-6-8 09:43
0
雪    币: 459
活跃值: (344)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
4
肯定不支持64位
2015-6-8 10:08
0
雪    币: 22
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
i下载收一份
2015-6-8 23:19
0
雪    币: 393
活跃值: (224)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
6
不支持x64,指针长度不一样 shellcode没办法写,有需要我改个x64的
2015-6-9 16:44
0
雪    币: 10910
活跃值: (3279)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
留个脚印,收藏一个。
2015-6-27 13:11
0
雪    币: 4305
活跃值: (4221)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
需要支持x64的
2015-6-28 17:27
0
雪    币: 224
活跃值: (157)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
谢谢分享!
2015-6-29 09:24
0
雪    币: 49
活跃值: (261)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
留下脚印。谢谢分享
2015-6-30 19:27
0
雪    币: 90
活跃值: (80)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
多线程环境下 不把所有线程暂停hook的话会有概率崩溃
2015-7-1 16:17
0
雪    币: 174
活跃值: (620)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12

真正稳定的代码是更复杂的
我后来才理解detours为啥那么多代码
2015-7-2 11:56
0
雪    币: 229
活跃值: (94)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
13
恕小生愚昧,LPVOID _declspec(naked) WINAPI TestFun(LPVOID UnKnow1, LPVOID UnKnow2)这个函数是两个参数的,  而ExitProcess是一个参数的,这样InlineHook  栈会平衡吗?
2015-12-29 18:21
0
雪    币: 393
活跃值: (224)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
14
我当初是简单测试过的,而且这个也不是很完美,比如没有写一个取指令长度的引擎。
不过在裸函数中,也就随意了。

可以使用任意引擎改进下代码,比如我的。
标 题: 【原创】国庆时完工的反汇编引擎源码
作 者: BinGzL
时 间: 2015-11-26,10:22:12
链 接: http://bbs.pediy.com/showthread.php?t=206071

或者可以使用下面这个我朋友封装好的
通用hook代码模板
http://www.jmpoep.com/thread-34-1-1.html
2015-12-29 22:21
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
15
楼主,我直接指出你的错误吧!第一,这个不支持X64位,从你的回答中也看到你知道这个问题了。

第二有一个问题,就是,这个HOOK没有注意多线程安全,HOOK是要强调多线程安全的,你的HOOK函数在执行时,你没有保证HOOK不会被别的线程打断,在单线程程序,也就是只有一个主线程的程序里,你的HOOK函数在执行时是可以保证不会被打断的,因为,只有一个主线程,没有别的线程打断你的HOOK了,但是,如果是在一个多线程程序中,并且是频繁调用被HOOK的函数的程序中,问题就出来了,首先,你的HOOK函数,并没有暂停别的线程,这样就有可能导致,别的线程在执行原来的指令时,有几率会被你写入的新的指令覆盖,这会导致不可预估的错误!

不注意多线程安全,是大多数HOOK的通病啊!毕竟,我们在写程序的时候,一直是在单线程中的main函数中编写的,可是要是到了,多线程环境,或者是内核的APC回调函数中,那可就惨了,因为你不知道这些不属于main函数调用的东西是什么时候去调用你正在HOOK的函数,要是在这些函数被别的线程或者内核回调APC中调用你正在HOOK的函数的话,你惨了,HOOK这时候还没完成,指令早就不知道被你写飞到哪里去了!
2015-12-30 01:07
0
雪    币: 393
活跃值: (224)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
16
感谢指出,我写hook还真是没注意过这个问题,也没有触发过。tks
2015-12-30 09:42
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
17
你编程的时候,或者说,你自己开发的时候是在main函数下的,一般情况下这个函数是单线程的,就不会遇到我说的打断hook的问题,但是一旦在别的机器上运行或者是用别的库函数,或者是需要多线程处理的函数,还有内核回调函数的情况下,就有一定的几率遇到这个问题!这个几率是很低的,所以你很可能不会遇到过,但是代表你不会遇到!只是遇到的几率很低而已!
2015-12-30 10:21
0
游客
登录 | 注册 方可回帖
返回
//