tonyfeng 发表于 2024-8-18 19:46

函数拦截技术

我做了2个函数拦截并显示某个功能,有一个成功 ,有一个报错不知道哪出问题了,是不是返回类型错了还是?

2个原型是


PK_linkage_m PK_ERROR_code_t PK_BODY_extrude
(
/* received */
PK_BODY_t                   /*profile*/,      /* minimum, wire or sheet profile */
PK_VECTOR1_t                /*path*/,         /* direction of linear extrusion */
const PK_BODY_extrude_o_t * /*options*/,      /* options structure */
/* returned */
PK_BODY_t         *const/*body*/,         /* resulting extruded body */
PK_TOPOL_track_r_t*const/*tracking*/,   /* tracking information */
PK_TOPOL_local_r_t*const/*results*/       /* status information */
);
/*
This function creates a new body by performing a linear extrusion of a given
profile.
*/



PK_linkage_m PK_ERROR_code_t PK_CURVE_make_wire_body_2
(
/* received */
int                                 /*n_curves*/,   /* number of curves (ie, */
const PK_CURVE_t                      /*curves*/[],   /* curves to create a wire */
const PK_INTERVAL_t                   /*bounds*/[],   /* bounds of each curve */
const PK_CURVE_make_wire_body_o_t   * /*options*/,      /* options structure */
/* returned */
PK_BODY_t                     *const/*body*/,         /* the created wire body */
int                           *const/*n_new_edges*/,/* number of new edges */
PK_EDGE_t                  **const/*new_edges*/,    /* new edges */
int                        **const/*edge_index*/    /* pos in original array */
);
/*
This function creates a wire body from an array of curves and intervals. The
curves do not need to be ordered (unless specified otherwise) or directed.
*/


拦截代码如下,如果某个命令用到这2个函数就提示,使用了某函数
用于分析代码使用哪些函数完成的
HookApi_PK_BODY_extrude是成功的
BOOL HookApi_PK_BODY_extrude();
BOOL UnhookApi_PK_BODY_extrude();
typedef PK_ERROR_code_t(WINAPI* typedef_PK_BODY_extrude)(PK_BODY_t profile, PK_VECTOR1_t path, const PK_BODY_extrude_o_t* options, PK_BODY_t* const body, PK_TOPOL_track_r_t* const tracking, PK_TOPOL_local_r_t* const results);
PK_ERROR_code_t WINAPI New_PK_BODY_extrude(PK_BODY_t profile, PK_VECTOR1_t path, const PK_BODY_extrude_o_t* options, PK_BODY_t* const body, PK_TOPOL_track_r_t* const tracking, PK_TOPOL_local_r_t* const results);

BOOL UnhookApi_PK_BODY_extrude()
{
        char* dll_name = "pskernel.dll";
        char* addressname = "PK_BODY_extrude";
        HMODULE hDll = ::GetModuleHandleA(dll_name);
        if (NULL == hDll) { return FALSE; }
        PVOID OldMessageBoxA = ::GetProcAddress(hDll, addressname);
        if (NULL == OldMessageBoxA) { return FALSE; }
        DWORD dwNewDataSize = 12;
        DWORD dwOldProtect = 0;
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
        ::RtlCopyMemory(OldMessageBoxA, g_pOldData, dwNewDataSize);
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, dwOldProtect, &dwOldProtect);
        return TRUE;
}

PK_ERROR_code_t WINAPI New_PK_BODY_extrude(PK_BODY_t profile, PK_VECTOR1_t path, const PK_BODY_extrude_o_t* options, PK_BODY_t* const body, PK_TOPOL_track_r_t* const tracking, PK_TOPOL_local_r_t* const results)
{
        PK_ERROR_code_t fanhui = 0;
        char* dll_name = "pskernel.dll";
        char* addressname = "PK_BODY_extrude";
        UnhookApi_PK_BODY_extrude();
        HMODULE hDll = ::GetModuleHandleA(dll_name);
        if (NULL == hDll) { return fanhui; }
        typedef_PK_BODY_extrude OldFuncAddr = (typedef_PK_BODY_extrude)::GetProcAddress(hDll, addressname);
        if (NULL == OldFuncAddr) { return fanhui; }
        fanhui = OldFuncAddr(profile, path, options, body, tracking, results);
        UF_UI_write_listing_window("你使用了PK_BODY_extrude函数\n");
        HookApi_PK_BODY_extrude();
        return fanhui;
}

BOOL HookApi_PK_BODY_extrude()
{
        char* dll_name = "pskernel.dll";
        char* addressname = "PK_BODY_extrude";
        HMODULE hDll = ::GetModuleHandleA(dll_name);
        if (NULL == hDll) { return FALSE; }
        PVOID OldFuncAddr = ::GetProcAddress(hDll, addressname);
        if (NULL == OldFuncAddr) { return FALSE; }
        BYTE pNewData = { 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0 };
        DWORD dwNewDataSize = 12;
        ULONGLONG ullNewFuncAddr = (ULONGLONG)New_PK_BODY_extrude;
        ::RtlCopyMemory(&pNewData, &ullNewFuncAddr, sizeof(ullNewFuncAddr));
        DWORD dwOldProtect = 0;
        ::VirtualProtect(OldFuncAddr, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
        ::RtlCopyMemory(g_pOldData, OldFuncAddr, dwNewDataSize);
        ::RtlCopyMemory(OldFuncAddr, pNewData, dwNewDataSize);
        ::VirtualProtect(OldFuncAddr, dwNewDataSize, dwOldProtect, &dwOldProtect);
        return TRUE;
}


//----
另一个不成功
HookApi_PK_CURVE_make_wire_body_2(); 不成功
BOOL HookApi_PK_CURVE_make_wire_body_2();
BOOL UnhookApi_PK_CURVE_make_wire_body_2();

typedef PK_ERROR_code_t(WINAPI* typedef_PK_CURVE_make_wire_body_2)(int n_curves, const PK_CURVE_t curves[], const PK_INTERVAL_t bounds[], const PK_CURVE_make_wire_body_o_t* options, PK_BODY_t* const body, int* const n_new_edges, PK_EDGE_t** const new_edges, int** const edge_index);
PK_ERROR_code_t WINAPI New_PK_CURVE_make_wire_body_2(int n_curves, const PK_CURVE_t curves[], const PK_INTERVAL_t bounds[], const PK_CURVE_make_wire_body_o_t* options, PK_BODY_t* const body, int* const n_new_edges, PK_EDGE_t** const new_edges, int** const edge_index);

BOOL UnhookApi_PK_CURVE_make_wire_body_2()
{
        char* dll_name = "pskernel.dll";
        char* addressname = "PK_CURVE_make_wire_body_2";
        HMODULE hDll = ::GetModuleHandleA(dll_name);
        if (NULL == hDll) { return FALSE; }
        PVOID OldMessageBoxA = ::GetProcAddress(hDll, addressname);
        if (NULL == OldMessageBoxA) { return FALSE; }
        DWORD dwNewDataSize = 12;
        DWORD dwOldProtect = 0;
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
        ::RtlCopyMemory(OldMessageBoxA, g_pOldData, dwNewDataSize);
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, dwOldProtect, &dwOldProtect);
        return TRUE;
}

PK_ERROR_code_t New_PK_CURVE_make_wire_body_2(int n_curves, const PK_CURVE_t curves[], const PK_INTERVAL_t bounds[], const PK_CURVE_make_wire_body_o_t* options, PK_BODY_t* const body, int* const n_new_edges, PK_EDGE_t** const new_edges, int** const edge_index)
{
        PK_ERROR_code_t fanhui = 0;
        char* dll_name = "pskernel.dll";
        char* addressname = "PK_CURVE_make_wire_body_2";
        UnhookApi_PK_CURVE_make_wire_body_2();
        HMODULE hDll = ::GetModuleHandleA(dll_name);
        if (NULL == hDll) { return fanhui; }
        typedef_PK_CURVE_make_wire_body_2 OldFuncAddr = (typedef_PK_CURVE_make_wire_body_2)::GetProcAddress(hDll, addressname);
        if (NULL == OldFuncAddr) { return fanhui; }
        fanhui = OldFuncAddr(n_curves, curves, bounds, options, body, n_new_edges, new_edges, edge_index);
        UF_UI_write_listing_window("你使用了PK_CURVE_make_wire_body_2函数\n");
        HookApi_PK_CURVE_make_wire_body_2();

        return fanhui;
}

BOOL HookApi_PK_CURVE_make_wire_body_2()
{
        char* dll_name = "pskernel.dll";
        char* addressname = "PK_CURVE_make_wire_body_2";
        HMODULE hDll = ::GetModuleHandleA(dll_name);
        if (NULL == hDll) { return FALSE; }
        PVOID OldFuncAddr = ::GetProcAddress(hDll, addressname);
        if (NULL == OldFuncAddr) { return FALSE; }
        BYTE pNewData = { 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0 };
        DWORD dwNewDataSize = 12;
        PK_ERROR_code_t ullNewFuncAddr = (PK_ERROR_code_t)New_PK_CURVE_make_wire_body_2;
        ::RtlCopyMemory(&pNewData, &ullNewFuncAddr, sizeof(ullNewFuncAddr));
        DWORD dwOldProtect = 0;
        ::VirtualProtect(OldFuncAddr, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
        ::RtlCopyMemory(g_pOldData, OldFuncAddr, dwNewDataSize);
        ::RtlCopyMemory(OldFuncAddr, pNewData, dwNewDataSize);
        ::VirtualProtect(OldFuncAddr, dwNewDataSize, dwOldProtect, &dwOldProtect);
        return TRUE;
}

我的想法就是,做个DLL,注入某进程 ,某进程运行某个功能 ,看它调用什么哪个函数,然后我也做个命令山寨这样实现平替
不知道哪有问题了

lies2014 发表于 2024-8-18 22:53

C不熟,但觉得 HookApi_PK_CURVE_make_wire_body_2 里这句:
PK_ERROR_code_t ullNewFuncAddr = (PK_ERROR_code_t)New_PK_CURVE_make_wire_body_2
能返回正确地址吗?

QQ我爱破解 发表于 2024-8-18 23:46

这是写 获取程序在跑代码的时候都使用了什么函数吗

xuiaipojie 发表于 2024-8-19 08:23

要是游戏的函数被拦截会不会数据弹出函数缺失无法运行{:1_904:}

tonyfeng 发表于 2024-8-19 08:44

lies2014 发表于 2024-8-18 22:53
C不熟,但觉得 HookApi_PK_CURVE_make_wire_body_2 里这句:
PK_ERROR_code_t ullNewFuncAddr = (PK_ERROR ...

我也半懂不懂的,我怀姨是不是数组问题

lies2014 发表于 2024-8-19 09:05

tonyfeng 发表于 2024-8-19 08:44
我也半懂不懂的,我怀姨是不是数组问题

你就把 PK_ERROR_code_t 改为 ULONGLONG 看看效果呗

yes2 发表于 2024-8-19 09:33

本帖最后由 yes2 于 2024-8-19 09:42 编辑

      PK_ERROR_code_t ullNewFuncAddr = (PK_ERROR_code_t)New_PK_CURVE_make_wire_body_2;
      ::RtlCopyMemory(&pNewData, &ullNewFuncAddr, sizeof(ullNewFuncAddr));
你这句的逻辑是要把New_PK_CURVE_make_wire_body_2函数的地址写入到pNewData这个位置,长度上肯定是要指针长度的,PK_ERROR_code_t你没有给出定义,但是我猜应该是4字节。64位指针长度是8字节,少了一半所以出错了。
第一个函数之所以能成功,是因为用的是sizeof(ULONGLONG),够8个字节。两个hook函数基本都一样的东西为啥会有一个使用sizeof(ULONGLONG),另一个使用sizeof(ullNewFuncAddr)?要么是太粗心,要么就是本身对代码也不太理解,东拼西凑来的。
你对每一个需要hook的函数都有一套对应的hook、unhook函数,但是其实可以抽取出来只用一套hook、unhook函数,其中的变量可以通过参数传递,这样就不会出现你这种情况,明明是90%雷同的东西结果还能有一个出错。
另外sizeof(ullNewFuncAddr)是错的,sizeof(ULONGLONG)虽然能用但是其实也不算规范,应该使用sizeof(void*),这样如果迁移到32位,至少也能自适配,少改一点代码就少一点潜在的错误风险。
最后,这种实现方案在多线程下可能会出问题。

tonyfeng 发表于 2024-8-19 18:24

QQ我爱破解 发表于 2024-8-18 23:46
这是写 获取程序在跑代码的时候都使用了什么函数吗

是的,就是用这个原理就行了

tonyfeng 发表于 2024-8-19 18:26

yes2 发表于 2024-8-19 09:33
      PK_ERROR_code_t ullNewFuncAddr = (PK_ERROR_code_t)New_PK_CURVE_make_wi ...

typedef int PK_ERROR_code_t;
它就是一个Int ,

tonyfeng 发表于 2024-8-19 18:34

yes2 发表于 2024-8-19 09:33
      PK_ERROR_code_t ullNewFuncAddr = (PK_ERROR_code_t)New_PK_CURVE_make_wi ...

参考的代码是这里的,hook代码 不是很会,


#ifndef _HOOK_API_H_
#define _HOOK_API_H_
#include <Windows.h>
typedef int (WINAPI *typedef_MessageBoxA)(
        HWND hWnd,          // handle to owner window
        LPCTSTR lpText,   // text in message box
        LPCTSTR lpCaption,// message box title
        UINT uType          // message box style
        );
int WINAPI NewMessageBoxA(
        HWND hWnd,          // handle to owner window
        LPCTSTR lpText,   // text in message box
        LPCTSTR lpCaption,// message box title
        UINT uType          // message box style
        );

// Hook Api
BOOL HookApi_MessageBoxA();

// Unhook Api
BOOL UnhookApi_MessageBoxA();

#endif

//---------------------



//hookapi.cpp
#include "HookApi.h"




BYTE g_pOldData = {0};


void ShowError(char *pszText)
{
        char szErr = {0};
        ::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
        ::MessageBox(NULL, szErr, "ERROR", MB_OK);
}


// Hook Api
BOOL HookApi_MessageBoxA()
{
        // 获取 user32.dll 模块加载基址
        HMODULE hDll = ::GetModuleHandle("user32.dll");
        if (NULL == hDll)
        {
                return FALSE;
        }
        // 获取 MessageBoxA 函数的导出地址
        PVOID OldMessageBoxA = ::GetProcAddress(hDll, "MessageBoxA");
        if (NULL == OldMessageBoxA)
        {
                return FALSE;
        }
        // 计算写入的前几字节数据, 32位下5字节, 64位下12字节
#ifndef _WIN64
        // 32位
        // 汇编代码:jmp _dwNewAddress
        // 机器码位:e9 _dwOffset(跳转偏移)
        //                addr1 --> jmp _dwNewAddress指令的下一条指令的地址,即eip的值
        //                addr2 --> 跳转地址的值,即_dwNewAddress的值
        //                跳转偏移 _dwOffset = addr2 - addr1
        BYTE pNewData = {0xe9, 0, 0, 0, 0};
        DWORD dwNewDataSize = 5;
        DWORD dwOffset = 0;
        // 计算跳转偏移
        dwOffset = (DWORD)NewMessageBoxA - ((DWORD)OldMessageBoxA + 5);
        ::RtlCopyMemory(&pNewData, &dwOffset, sizeof(dwOffset));
#else
        // 64位
        // 汇编代码:mov rax, _dwNewAddress(0x1122334455667788)
        //         jmp rax
        // 机器码是:
        //        48 b8 _dwNewAddress(0x1122334455667788)
        //        ff e0
        BYTE pNewData = { 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0};
        DWORD dwNewDataSize = 12;
        ULONGLONG ullNewFuncAddr = (ULONGLONG)NewMessageBoxA;
        ::RtlCopyMemory(&pNewData, &ullNewFuncAddr, sizeof(ullNewFuncAddr));
#endif
        // 设置页面的保护属性为 可读、可写、可执行
        DWORD dwOldProtect = 0;
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);

        // 保存原始数据
        ::RtlCopyMemory(g_pOldData, OldMessageBoxA, dwNewDataSize);
        // 开始修改 MessageBoxA 函数的前几字节数据, 实现 Inline Hook API
        ::RtlCopyMemory(OldMessageBoxA, pNewData, dwNewDataSize);

        // 还原页面保护属性
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, dwOldProtect, &dwOldProtect);

        return TRUE;
}


// Unhook Api
BOOL UnhookApi_MessageBoxA()
{
        // 获取 user32.dll 模块加载基址
        HMODULE hDll = ::GetModuleHandle("user32.dll");
        if (NULL == hDll)
        {
                return FALSE;
        }
        // 获取 MessageBoxA 函数的导出地址
        PVOID OldMessageBoxA = ::GetProcAddress(hDll, "MessageBoxA");
        if (NULL == OldMessageBoxA)
        {
                return FALSE;
        }
        // 计算写入的前几字节数据, 32位下5字节, 64位下12字节
#ifndef _WIN64
        DWORD dwNewDataSize = 5;
#else
        DWORD dwNewDataSize = 12;
#endif
        // 设置页面的保护属性为 可读、可写、可执行
        DWORD dwOldProtect = 0;
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);

        // 恢复数据
        ::RtlCopyMemory(OldMessageBoxA, g_pOldData, dwNewDataSize);

        // 还原页面保护属性
        ::VirtualProtect(OldMessageBoxA, dwNewDataSize, dwOldProtect, &dwOldProtect);

        return TRUE;
}


// 新的 API
int WINAPI NewMessageBoxA(
        HWND hWnd,          // handle to owner window
        LPCTSTR lpText,   // text in message box
        LPCTSTR lpCaption,// message box title
        UINT uType          // message box style
        )
{
        // Unhook
        UnhookApi_MessageBoxA();

        // 获取 user32.dll 模块加载基址
        HMODULE hDll = ::GetModuleHandle("user32.dll");
        if (NULL == hDll)
        {
                return FALSE;
        }
        // 获取 MessageBoxA 函数的导出地址
        typedef_MessageBoxA OldMessageBoxA = (typedef_MessageBoxA)::GetProcAddress(hDll, "MessageBoxA");
        if (NULL == OldMessageBoxA)
        {
                return FALSE;
        }
        int iRet = OldMessageBoxA(hWnd, "I am Nobody!!!", "Who Am I", MB_YESNO);

        // Hook
        HookApi_MessageBoxA();

        return iRet;
}
页: [1] 2
查看完整版本: 函数拦截技术