【软件逆向】如何在windows下远程注入dll并进行虚表hook

需要准备的工具

  1. Microsoft Visual Studio开发工具。
  2. IDA pro动态调试工具。
  3. Process Hacker 2进程监控工具。
  4. 被远程注入的exe程序。(以crackme.exe为例)

远程注入dll进行虚表hook

一、IDA pro反编译找到函数逻辑地址

  1. 使用IDA pro打开crackme.exe,开启动态调试。
    在这里插入图片描述
  2. 找到需要hook的地方,一般是系统库里的函数,以jmp cs:EnterCriticalSection为例。(其中EnterCriticalSection可以是其他系统函数)
    在这里插入图片描述
  3. 双击函数名,找到其真实地址为0x7ff6472bd0c8。
    在这里插入图片描述
  4. 找到程序的起始地址为0x7ff6472a0000。
    在这里插入图片描述
  5. 可以计算得出EnterCriticalSection函数相对程序入口的逻辑地址为0x7ff6472bd0c8-0x7ff6472a0000=0x1d0c8。
    在这里插入图片描述

二、VS编写虚表hook动态链接库

  1. 打开Visual Studio,创建一个DLL项目。
    在这里插入图片描述
  2. 将dllmain.cpp修改为以下代码,其中其中0x1d0c8修改为第一步中函数逻辑地址,Hooked_VtableFunc函数中写自己想要执行的代码。
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
#include <stdio.h>
#include <iostream>
typedef void(__fastcall* VtableFunc_t)();
VtableFunc_t VtableFunc = nullptr;

// 需要执行的函数
void __fastcall Hooked_VtableFunc() {
    printf("正确\n");
    system("pause");
    return VtableFunc();
}

void HookVtableTest() {
    uintptr_t VtableAddress = (uintptr_t)GetModuleHandleA(0) + 0x1d0c8; //其中0x1d0c8修改为第一步中函数逻辑地址
    DWORD old_protect = 0;
    VirtualProtect((LPVOID)VtableAddress, 0x8, PAGE_EXECUTE_READWRITE, &old_protect);
    *(uintptr_t*)(VtableAddress) = (uintptr_t)Hooked_VtableFunc;
    VirtualProtect((LPVOID)VtableAddress, 0x8, old_protect, &old_protect);
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        HookVtableTest(); break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
  1. 生成解决方案后,可以得到虚表hook的dll文件。dll文件一般在“项目路径/x64/Debug/”。
    在这里插入图片描述

三、VS编写远程注入代码

  1. 打开Visual Studio,创建一个控制台应用。
    在这里插入图片描述
  2. 将以下代码复制到cpp源文件中,其中main函数的第一行wStr变量修改为第二步中生成的dll的路径(windows路径下的\需要用\转译),第二行修改为进程名(可以打开任务管理器查看)。
#include <iostream>
#include <vector>
#include <Windows.h>
#include <tlhelp32.h>
#include <fstream>
using namespace std;

bool Inject(DWORD dwId, WCHAR* szPath)//参数1:目标进程PID  参数2:DLL路径
{
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
    LPVOID pRemoteAddress = VirtualAllocEx(
        hProcess,
        NULL,
        wcslen(szPath) * 2,
        MEM_COMMIT,
        PAGE_READWRITE
    );
    DWORD dwWriteSize = 0;
    BOOL bRet = WriteProcessMemory(hProcess, pRemoteAddress, szPath, wcslen(szPath) * 2, NULL);
    HMODULE hModule = GetModuleHandle(L"kernel32.dll");
    if (!hModule)
    {
        printf("GetModuleHandle Error !\n");
        GetLastError();
        CloseHandle(hProcess);
        return FALSE;
    }
    LPTHREAD_START_ROUTINE dwLoadAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryW");
    if (!dwLoadAddr)
    {
        printf("GetProcAddress Error !\n");
        CloseHandle(hProcess);
        CloseHandle(hModule);
        return FALSE;
    }

    HANDLE hThread = CreateRemoteThread(
        hProcess,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)dwLoadAddr,
        pRemoteAddress,
        NULL,
        NULL
    );
    return 0;
}
DWORD GetPid(WCHAR* szName)
{
    HANDLE hprocessSnap = NULL;
    PROCESSENTRY32  pe32 = { 0 };
    hprocessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(hprocessSnap, &pe32))
    {
        do {
            if (!wcscmp(szName, pe32.szExeFile))
                return (int)pe32.th32ProcessID;
        } while (Process32Next(hprocessSnap, &pe32));
    }
    else
        CloseHandle(hprocessSnap);
    return 0;
}

int main()
{
    wchar_t wStr[] = L"C:\\Users\\zhang\\source\\repos\\crackme_dll\\x64\\Release\\crackme_dll.dll";
    WCHAR S[] = L"crackme.exe";
    DWORD SS = GetPid(S);
    printf("目标窗口的进程PID为:%d\n", SS);
    Inject(SS, wStr);
    return 0;
}
  1. 生成解决方案后,可以得到远程注入的exe文件。exe文件一般在“项目路径/x64/Debug/”。

四、远程注入dll并使用Process Hack 2观察注入结果

  1. 管理员运行crackme.exe,管理员运行Process Hacker 2,搜索crackme,并查看Modules,可以看到没有我们注入的dll。
    在这里插入图片描述
  2. 管理员运行第三步中exe程序,再次打开Process Hacker 2,可以看到crackme_dll.dll已经注入成功。
    在这里插入图片描述
  3. 可以看到第二步代码中Hooked_VtableFunc函数成功执行
    在这里插入图片描述
    如果帮到你了,麻烦点个赞。如果暂时用不到,不妨也收藏以下,可能以后会有用。教程中有错误的地方也麻烦留言或私信指正,尽量及时修正。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
x64进程远程hook,x64_远程调用函数,源码更新V1.8.2:2021/4/12 源码为下方连接帖子后续更新内容: 浅谈64位进程远程hook技术: https://bbs.125.la/forum.php?mod=viewthreadtid=14666356extra= 不管您是转载还是使用请保留版权,源码在精益论坛免费发布本人未获利,请不要用于非法途径。 --------------------------------------------------------------- 2021/4/12 模块源码 v1.8.2更新 1:修复 x64_远调用函数()在 易语言 主线程调用时造成消息无法回调,导致易语言主线程窗口卡死的问题。      感谢楼下易友发现的BUG,已经第一时间更新 2021/4/12 模块源码 v1.8.1更新 1:修复 hook全部卸载时的流程写法的一个错误,由于句柄的提前关闭导致多个hook点卸载不干净的问题 2:改写了消息回调时线程传参的代码优化,优化了其他一些小问题 3:  鉴于很多朋友需要,改写了模块自带实列,对TCP,UDP的两组封包函数做了hook实列写法 4:列子中同样增加对x64_远调用函数()的应用写了几个列子,如使用套接字取得本地或远端IP端口API调用的的应用实列 5:本hook模块不支持非模块内存区hook,如申请的动态分配页等,不是不能支持,只是觉得没有任何意义,对这方面有需求的,自行改写模块源码使用 提醒:hook回调函数中尽量减少耗时代码,时间越长返回越慢,回调中谨慎操作控件,如必须要用到可参考源码中实列写法采用线程操作 历史更新 --------------------------------------------------------------- 2021/3/1   模块源码v1.6更新: 1:修复  x64_远程调用函数()命令,在没有提供 寄存器 参数时,没有返回值的BUG。 --------------------------------------------------------------- 2021/2/28 模块源码v1.5更新: 一:修复win7 64位系统下枚举模块 出现部分模块长度出现负数的问题,从而导致部分win7用户不能使用 二:强化 远程hook64指令_安装 的稳定性:        1,穿插代码中增加对标志位的保护,避免hook位置长度下一条指令为跳转时产生跳转错乱的问题,强化了hook任意位置的定位        2,因为穿插代码中会调用API函数,而64位汇编必须遵守栈指针16字节对齐,故对穿插代码进行栈指针16字节对齐,增强稳定性        3,hook指令安装支持长度由6-127字节 变动 为 6-119字节,原因么没必要说了,代码优化造成的,稍微少了一点无所谓了        4,对模块回调进行了适当优化处理,增强稳定性 三:应支持的朋友需要故增加 x64_远程调用函数()命令,易语言可以直接远call64进程,且无需写汇编代码或机器码指令,支持15个参数,支持返回值,支持16个通用寄存器全部取得返回值       该功能调用即16字节栈对齐,不要用户管堆栈,代码内部构成,远线程执行,你只需要知道call有几个参数,需要什么寄存器,对应提供即可。 四:有朋友说原模块x64英文看了烦,那好吧就给改成了中文标识,弄得我自己也不习惯 五:源码内列子改了改,可以自己看,需要注意的是模块注释的很详细,使用前最好看一看,尤其是hook回调接口的写法和安装的写法最好按照模块列子中的写法来,除非你能把64hook模块组看懂一遍,对于一些对本模块一知半解的朋友请不要乱改乱发,这个模块我会继续增强的,只是工作原因时间有限,只能一点一点来
c hook注入dll是一种在Windows系统中实现函数钩子的技术。下面给出一个完整的例子: 首先,创建一个c文件,命名为hookdll.c,代码如下: #include <Windows.h> // 定义要hook的目标函数 typedef bool (WINAPI* ORIGINAL_FUNCTION)(LPCTSTR); ORIGINAL_FUNCTION OriginalFunction; // 定义hook的替代函数 bool WINAPI HookFunction(LPCTSTR lpFileName) { // 在这里编写你的hook函数逻辑 // 可以在这个函数中修改传入参数或返回值,实现钩子的目的 // ... // 调用原始函数 return OriginalFunction(lpFileName); } // Dll入口函数 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { // 加载kernel32.dll HMODULE kernel32 = LoadLibrary("kernel32"); if (kernel32 != NULL) { // 获取目标函数地址 OriginalFunction = (ORIGINAL_FUNCTION)GetProcAddress(kernel32, "函数名"); if (OriginalFunction != NULL) { // 修改函数的内存属性为可执行和可写 DWORD oldProtect; VirtualProtect(OriginalFunction, sizeof(ORIGINAL_FUNCTION), PAGE_EXECUTE_READWRITE, &oldProtect); // 修改函数的指针为hook函数的指针 *OriginalFunction = &HookFunction; // 还原函数的内存属性 VirtualProtect(OriginalFunction, sizeof(ORIGINAL_FUNCTION), oldProtect, &oldProtect); } // 释放kernel32.dll内存 FreeLibrary(kernel32); } } return TRUE; } 编译这个项目,得到一个dll文件,命名为hookdll.dll。 然后,创建一个使用目标dll的示例程序,例如使用了kernel32.dll中的某个方法。然后按照以下步骤实现hook注入: 1. 打开示例程序的源代码,编辑代码,添加以下代码段: #pragma comment(lib, "hookdll.lib") 2. 将hookdll.dll拷贝到示例程序的目录下。 3. 使用LoadLibrary函数在程序中动态加载hookdll.dll。 4. 调用示例程序中使用kernel32.dll中方法的代码,此时会执行被hook函数的替代函数。 通过以上步骤,我们就实现了c hook注入dll的完整例子。在hook函数中可以对传入的参数或返回值进行修改,实现我们想要的钩子效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ninding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值