Loading... # 引言 最近想要破解一手 sandboxie-plus,在rutracker中找到了他的赞助凭证,但是签名已经被硬编码到`SbieSvc.exe`中,它本身又被数字签名,不能直接进行修改,想到了DLL注入,在写这篇文章的时候,我还没有成功,这里写一下我的试验思路和过程。 # 准备工具 - visual studio - dbgview - x96dbg (可选) - die (可选) # 准备阶段 ```c++ // dll_injure_exe.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <windows.h> #include <stdio.h> #include <string.h> #include <iostream> const char* target_string = "63F49D96BDBA28F8428B4A5008D1A587"; int main() { std::cout << "Start\n"; // Load the version.dll library HMODULE hModule = LoadLibrary(L"version.dll"); std::cout << "Key: " << target_string <<std::endl; if (hModule == NULL) { std::cerr << "Failed to load version.dll. Error code: " << GetLastError() << std::endl; return 1; // Exit with error } std::cout << "version.dll loaded successfully!" << std::endl; // Optionally, retrieve an exported function from the library FARPROC pFunction = GetProcAddress(hModule, "GetFileVersionInfoSizeA"); if (pFunction == NULL) { std::cerr << "Failed to find GetFileVersionInfoSizeA. Error code: " << GetLastError() << std::endl; // Clean up by freeing the library FreeLibrary(hModule); return 1; // Exit with error } std::cout << "GetFileVersionInfoSizeA function address: " << pFunction << std::endl; // Use the function pointer as needed (example usage omitted for simplicity) // Free the library when done if (!FreeLibrary(hModule)) { std::cerr << "Failed to free version.dll. Error code: " << GetLastError() << std::endl; return 1; // Exit with error } std::cout << "version.dll unloaded successfully!" << std::endl; return 0; // Exit successfully } ``` 当没有把version.dll放置到exe路径,运行效果如下 ![image.png](https://www.zunmx.top/usr/uploads/2025/01/1509483505.png) # 准备dll ```c++ // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "pch.h" #include <windows.h> #include <stdio.h> #include <string.h> const char* target_string = "63F49D96BDBA28F8428B4A5008D1A587"; const char* replacement_string = "12341234123412341234123412341234"; void replace_string_in_memory() { OutputDebugStringA("set target_string\n"); SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); MEMORY_BASIC_INFORMATION mem_info; char* current_address = (char*)sys_info.lpMinimumApplicationAddress; char* max_address = (char*)sys_info.lpMaximumApplicationAddress; while (current_address < max_address) { if (VirtualQuery(current_address, &mem_info, sizeof(mem_info)) == sizeof(mem_info)) { // 只处理已提交且包含目标字符串的内存区域 if (mem_info.State == MEM_COMMIT && (mem_info.Protect & PAGE_READONLY)) { OutputDebugStringA("Checking read-only memory region...\n"); // 查找目标字符串 for (char* ptr = (char*)mem_info.BaseAddress; ptr < (char*)mem_info.BaseAddress + mem_info.RegionSize - strlen(target_string); ++ptr) { if (memcmp(ptr, target_string, strlen(target_string)) == 0) { // 找到目标字符串,输出调试信息 char debugMsg[256]; snprintf(debugMsg, sizeof(debugMsg), "Found target string at: %p\n", ptr); OutputDebugStringA(debugMsg); // 修改内存访问权限,使其可写 DWORD old_protect; if (VirtualProtect(ptr, strlen(replacement_string), PAGE_READWRITE, &old_protect)) { OutputDebugStringA("Memory protection changed to READWRITE\n"); // 替换字符串 memcpy(ptr, replacement_string, strlen(replacement_string)); // 恢复为只读权限 VirtualProtect(ptr, strlen(replacement_string), old_protect, &old_protect); OutputDebugStringA("String replacement successful!\n"); MessageBox(NULL, "String replaced successfully!", "DLL Notification", MB_OK); return; // 一旦替换成功,退出函数 } else { OutputDebugStringA("Failed to change memory protection.\n"); } } } } else { OutputDebugStringA("Skipping non-readonly memory region.\n"); } } current_address += mem_info.RegionSize; } OutputDebugStringA("Target string not found in memory.\n"); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { OutputDebugStringA("ZUNMX called\n"); printf("[#] DLL LOADED!\n"); switch (ul_reason_for_call) { case DLL_THREAD_ATTACH: OutputDebugStringA("DLL_THREAD_ATTACH called\n"); replace_string_in_memory(); break; case DLL_THREAD_DETACH: OutputDebugStringA("DLL_THREAD_DETACH called\n"); break; case DLL_PROCESS_DETACH: OutputDebugStringA("DLL_PROCESS_DETACH called\n"); break; case DLL_PROCESS_ATTACH: OutputDebugStringA("DLL_PROCESS_ATTACH called\n"); replace_string_in_memory(); break; } return TRUE; } ``` 当exe和dll在相同路径中时,运行结果如下。 ![image.png](https://www.zunmx.top/usr/uploads/2025/01/732308749.png) ![image.png](https://www.zunmx.top/usr/uploads/2025/01/1580562839.png) 目录结构如下: ![image.png](https://www.zunmx.top/usr/uploads/2025/01/4209605407.png) # 需要优化的地方 1. 新的VERSION.dll并没有导出原来的函数,如果exe程序没有做一些异常捕获,可能导致程序异常。 2. 如果目标程序没有导入VERSION.dll,那么这样做就没用了。 # dll注入的优势 当目标程序被签名、无法轻易修改、加强壳时可考虑这种办法。 # 实用工具推荐 - [aheadlib](https://github.com/strivexjun/AheadLib-x86-x64) © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏