x64dbg插件无驱动过vmp3.9.4反调试












复制代码 隐藏代码#include"pch.h"#include<windows.h>#include<vector>#include<string>#include"pluginsdk/bridgemain.h"#include"pluginsdk/_plugins.h"#include"pluginsdk/_scriptapi_module.h"#include"pluginsdk/_scriptapi_memory.h"#include"pluginsdk/_scriptapi_debug.h"#include"unicorn/unicorn.h"#pragma comment(lib, "unicorn.lib")#pragma comment(lib, "x64dbg.lib") // x64dbg 的库(64位)#pragma comment(lib, "x64bridge.lib") // x64bridge 的库(64位)#define MENU_UNICORN_ID 1int pluginHandle;duint mainModuleBase = 0;duint mainModuleSize = 0;int hMenu;// ---------------------- 全局控制变量 ----------------------HANDLE g_hSimulateEvent = NULL; // 唤醒工作线程的事件HANDLE g_hSimulateThread = NULL; // 工作线程句柄BOOL g_bStopSimulation = FALSE; // 是否停止工作线程BOOL g_bWaitingForBreakpoint = FALSE;// 是否在等待 rdtsc 断点duint g_rdtscNextRip = 0; // rdtsc 下一条指令地址int g_stop_reason = 0; // 模拟停止原因:1=rdtsc, 2=syscall, 3=out_of_moduleBOOL gsreg = FALSE;BOOL api = FALSE;// ---------------------- Unicorn 钩子函数 ----------------------staticvoidhook_code(uc_engine* uc, uint64_t address, uint32_t size, void* user_data){ WORD code = 0;uc_mem_read(uc, address, &code, 2);if (code == 0x310f) { // rdtsc _plugin_logprintf(u8"rdtsc at address: %llx\n", address); g_stop_reason = 1; g_rdtscNextRip = address + size; // 下一条指令地址uc_emu_stop(uc);return; }if (code == 0x50f) { // syscall _plugin_logprintf(u8"syscall at address: %llx\n", address); g_stop_reason = 2;uc_emu_stop(uc);return; }// 如果指令地址超出主模块范围,停止模拟if (address < mainModuleBase || address >= (mainModuleBase + mainModuleSize)) { _plugin_logprintf(u8"[Unicorn] 停止模拟,交回控制权给 x64dbg。api address:%llx\n", address); g_stop_reason = 3;uc_emu_stop(uc); }}staticboolhook_mem_unmapped(uc_engine* uc, uc_mem_type type, uint64_t address, int size, int64_t value, void* user_data){uint64_t current_rip;uc_reg_read(uc, UC_X86_REG_RIP, ¤t_rip); _plugin_logprintf(u8"[Unicorn] MEM_UNMAPPED at RIP=0x%llX: type=%d, addr=0x%llX, size=%d\n", current_rip, type, address, size); duint pageBase = (duint)address & ~0xFFF;if (!Script::Memory::IsValidPtr(pageBase)) { _plugin_logprintf(u8"[Unicorn] 致命错误:尝试访问无效指针 0x%llX \n", pageBase);uc_emu_stop(uc);returnfalse; } _plugin_logprintf(u8"[Unicorn] 触发缺页中断,懒加载映射内存页: 0x%llX\n", pageBase); uc_err err = uc_mem_map(uc, pageBase, 0x1000, UC_PROT_ALL);if (err != UC_ERR_OK && err != UC_ERR_MAP) { _plugin_logprintf(u8"[Unicorn] 内存映射失败: %s\n", uc_strerror(err));returnfalse; }unsignedchar pageBuf[0x1000] = { 0 };if (Script::Memory::Read(pageBase, pageBuf, 0x1000, nullptr)) {uc_mem_write(uc, pageBase, pageBuf, 0x1000);returntrue; }returnfalse;}// ---------------------- 工作线程:执行模拟 ----------------------DWORD WINAPI SimulationWorker(LPVOID lpParam){while (!g_bStopSimulation) {// 等待事件触发WaitForSingleObject(g_hSimulateEvent, INFINITE);ResetEvent(g_hSimulateEvent);// 如果是因为断点唤醒,需要删除之前设置的硬件断点if (g_bWaitingForBreakpoint) { Script::Debug::DeleteHardwareBreakpoint(g_rdtscNextRip); g_bWaitingForBreakpoint = FALSE; }// 重新初始化 Unicorn 引擎 uc_engine* uc; uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);if (err != UC_ERR_OK) { _plugin_logprintf(u8"uc_open 失败: %u\n", err);continue; }// 1. 获取主模块范围(每次重新获取,因为调试器可能已加载新模块) mainModuleBase = Script::Module::GetMainModuleBase(); mainModuleSize = Script::Module::SizeFromAddr(mainModuleBase);// 2. 映射所有已提交的内存页到 Unicorn MEMMAP memoryMap = { 0 };DbgMemMap(&memoryMap);for (int i = 0; i < memoryMap.count; i++) {auto& page = memoryMap.page[i];if (page.mbi.State == MEM_COMMIT) { duint base = (duint)page.mbi.BaseAddress; SIZE_T size = page.mbi.RegionSize; duint alignedBase = base & ~0xFFF; duint alignedSize = (size + 0xFFF) & ~0xFFF;uc_mem_map(uc, alignedBase, alignedSize, UC_PROT_ALL);std::vector<uint8_t> buffer(size);if (Script::Memory::Read(base, buffer.data(), size, nullptr)) {uc_mem_write(uc, base, buffer.data(), size); } } }// 3. 同步寄存器状态(64位) REGDUMP_AVX512 regdump = { 0 };if (!DbgGetRegDumpEx(®dump, sizeof(regdump))) { _plugin_logprintf(u8"[Unicorn] 无法获取寄存器,模拟跳过\n");uc_close(uc);continue; }uint64_t rax = regdump.regcontext.cax;uint64_t rbx = regdump.regcontext.cbx;uint64_t rcx = regdump.regcontext.ccx;uint64_t rdx = regdump.regcontext.cdx;uint64_t rsi = regdump.regcontext.csi;uint64_t rdi = regdump.regcontext.cdi;uint64_t rsp = regdump.regcontext.csp;uint64_t rbp = regdump.regcontext.cbp;uint64_t rip = regdump.regcontext.cip;uint64_t rflags = regdump.regcontext.eflags; rflags &= ~0x100; // 清除 TF 位uint64_t r8 = regdump.regcontext.r8;uint64_t r9 = regdump.regcontext.r9;uint64_t r10 = regdump.regcontext.r10;uint64_t r11 = regdump.regcontext.r11;uint64_t r12 = regdump.regcontext.r12;uint64_t r13 = regdump.regcontext.r13;uint64_t r14 = regdump.regcontext.r14;uint64_t r15 = regdump.regcontext.r15;uc_reg_write(uc, UC_X86_REG_RAX, &rax);uc_reg_write(uc, UC_X86_REG_RBX, &rbx);uc_reg_write(uc, UC_X86_REG_RCX, &rcx);uc_reg_write(uc, UC_X86_REG_RDX, &rdx);uc_reg_write(uc, UC_X86_REG_RSI, &rsi);uc_reg_write(uc, UC_X86_REG_RDI, &rdi);uc_reg_write(uc, UC_X86_REG_RSP, &rsp);uc_reg_write(uc, UC_X86_REG_RBP, &rbp);uc_reg_write(uc, UC_X86_REG_RIP, &rip);uc_reg_write(uc, UC_X86_REG_RFLAGS, &rflags);uc_reg_write(uc, UC_X86_REG_R8, &r8);uc_reg_write(uc, UC_X86_REG_R9, &r9);uc_reg_write(uc, UC_X86_REG_R10, &r10);uc_reg_write(uc, UC_X86_REG_R11, &r11);uc_reg_write(uc, UC_X86_REG_R12, &r12);uc_reg_write(uc, UC_X86_REG_R13, &r13);uc_reg_write(uc, UC_X86_REG_R14, &r14);uc_reg_write(uc, UC_X86_REG_R15, &r15);// 4. 设置钩子 uc_hook trace_code, trace_mem;uc_hook_add(uc, &trace_code, UC_HOOK_CODE, hook_code, NULL, 1, 0);uc_hook_add(uc, &trace_mem, UC_HOOK_MEM_UNMAPPED, hook_mem_unmapped, NULL, 1, 0);// 5. 开始模拟 _plugin_logprintf(u8"[Unicorn] 开始模拟,起始 RIP: 0x%llX\n", rip); g_stop_reason = 0; // 清除停止原因 err = uc_emu_start(uc, rip, UINT64_MAX, 0, 0);if (err != UC_ERR_OK) { _plugin_logprintf(u8"[Unicorn] 模拟停止,原因: %s\n", uc_strerror(err)); }else { _plugin_logprintf(u8"[Unicorn] 模拟正常完成。\n"); }// 获取停止时的 RIPuint64_t stop_rip = 0;uc_reg_read(uc, UC_X86_REG_RIP, &stop_rip); _plugin_logprintf(u8"[Unicorn] 停止时 RIP: 0x%llX, 停止原因: %d\n", stop_rip, g_stop_reason);// 根据停止原因决定后续动作if (g_stop_reason == 1) { // rdtsc// 在 rdtsc 下一条指令设置硬件断点 g_rdtscNextRip = stop_rip+2; // 实际上 stop_rip 就是 rdtsc 地址,但 hook_code 中已存储 g_rdtscNextRip Script::Debug::SetHardwareBreakpoint(g_rdtscNextRip); g_bWaitingForBreakpoint = TRUE;// 让调试器继续执行到断点DbgCmdExec("go"); }elseif (g_stop_reason == 2) { // syscall _plugin_logprintf(u8"[Unicorn] 遇到 syscall,模拟结束。\n"); Script::Debug::SetHardwareBreakpoint(stop_rip);DbgCmdExec("go");// 不再继续模拟,线程回到等待状态(等待用户再次触发) }elseif (g_stop_reason == 3) { // 超出模块范围 _plugin_logprintf(u8"[Unicorn] 超出主模块,模拟结束。\n"); api = TRUE; Script::Debug::SetHardwareBreakpoint(stop_rip);DbgCmdExec("go");// 不再继续模拟,线程回到等待状态 }else {// 其他未知停止原因(可能 uc_emu_start 错误),也不继续 gsreg = TRUE; BASIC_INSTRUCTION_INFO info;DbgDisasmFastAt(stop_rip, &info); Script::Debug::SetHardwareBreakpoint(stop_rip+info.size);DbgCmdExec("go"); _plugin_logprintf(u8"[Unicorn] 模拟因未知原因停止。\n"); }uc_close(uc); }return0;}// ---------------------- 断点回调 ----------------------BOOL g_bDebugMenuActive = FALSE; // 标记是否处于调试模式(菜单 DEBUG_ID 按下后)extern"C" __declspec(dllexport) voidCBBREAKPOINT(CBTYPE cbType, PLUG_CB_BREAKPOINT * info){// 处理调试模式下的硬件断点(仅当 g_bDebugMenuActive 为真)if (g_bDebugMenuActive && info->breakpoint->type == bp_hardware) {// 如果是之前为 rdtsc 设置的下一条指令断点if (info->breakpoint->addr == g_rdtscNextRip) { _plugin_logprintf(u8"[Unicorn] rdtsc 下一条指令断点命中: 0x%llX\n", info->breakpoint->addr);// 唤醒工作线程继续模拟 Script::Debug::DeleteHardwareBreakpoint(g_rdtscNextRip);SetEvent(g_hSimulateEvent);// 注意:断点命中后调试器处于暂停状态,工作线程会重新获取寄存器并模拟// 此时不要执行 go,否则工作线程还没准备好就继续运行了return; } WORD op = 0;if (DbgMemRead(info->breakpoint->addr, &op, 2)) {if (op == 0x50f) { _plugin_logprintf(u8"syscall:%llx\n", info->breakpoint->addr); Script::Debug::DeleteHardwareBreakpoint(info->breakpoint->addr);return; }/*else { DbgCmdExec("StepInto"); }*/ } }if (gsreg && info->breakpoint->type == bp_hardware) { gsreg = FALSE; Script::Debug::DeleteHardwareBreakpoint(info->breakpoint->addr);SetEvent(g_hSimulateEvent);return; }if (api && info->breakpoint->type == bp_hardware) { api = FALSE; Script::Debug::DeleteHardwareBreakpoint(info->breakpoint->addr);return; }}// ---------------------- 菜单回调 ----------------------extern"C" __declspec(dllexport) voidCBMENUENTRY(CBTYPE cbType, PLUG_CB_MENUENTRY * info){if (info->hEntry == MENU_UNICORN_ID) {// 启动模拟(唤醒工作线程) g_bDebugMenuActive = TRUE; // 确保不在调试模式下 g_bWaitingForBreakpoint = FALSE; // 清除等待断点标志SetEvent(g_hSimulateEvent);return; }}// ---------------------- 插件入口函数 ----------------------extern"C" __declspec(dllexport) boolpluginit(PLUG_INITSTRUCT * initStruct){ initStruct->pluginVersion = 1; initStruct->sdkVersion = PLUG_SDKVERSION;strcpy_s(initStruct->pluginName, "UnicornPlugin"); pluginHandle = initStruct->pluginHandle;returntrue;}extern"C" __declspec(dllexport) voidplugsetup(PLUG_SETUPSTRUCT * setupStruct){ hMenu = setupStruct->hMenu; _plugin_menuaddentry(hMenu, MENU_UNICORN_ID, "sys_trace");// 创建事件和常驻工作线程 g_hSimulateEvent = CreateEvent(NULL, FALSE, FALSE, NULL); g_hSimulateThread = CreateThread(NULL, 0, SimulationWorker, NULL, 0, NULL); _plugin_logputs("[UnicornPlugin] plugsetup called, worker thread started.");}extern"C" __declspec(dllexport) boolplugstop(){// 停止工作线程if (g_hSimulateEvent) { g_bStopSimulation = TRUE;SetEvent(g_hSimulateEvent);if (g_hSimulateThread) {WaitForSingleObject(g_hSimulateThread, INFINITE);CloseHandle(g_hSimulateThread); g_hSimulateThread = NULL; }CloseHandle(g_hSimulateEvent); g_hSimulateEvent = NULL; } _plugin_logputs("[UnicornPlugin] plugstop called, worker thread stopped.");returntrue;}// ---------------------- DllMain ----------------------BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){switch (ul_reason_for_call) {case DLL_PROCESS_ATTACH:case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break; }return TRUE;}
通过网盘分享的文件:plugin.zip链接: https://pan.baidu.com/s/1KIxIQjQCCzhqMfhRXNfklQ?pwd=b228 提取码: b228–来自百度网盘超级会员v8的分享
-官方论坛
www.52pojie.cn
👆👆👆

夜雨聆风