From 8504a9c8f98059ee0ea0366b172294c92fca81e3 Mon Sep 17 00:00:00 2001 From: Huoji's <1296564236@qq.com> Date: Fri, 7 Mar 2025 01:47:01 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E4=B8=8D=E4=BA=86=E4=BA=86=20?= =?UTF-8?q?=E7=BB=88=E6=9E=81=E5=A4=A7=E6=8B=9B=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ai_anti_malware/ai_anti_malware.cpp | 2 +- ai_anti_malware/sandbox.cpp | 14 +- ai_anti_malware/sandbox.h | 6 +- ai_anti_malware/sandbox_api_emu.cpp | 632 +++++++++++++++++++++++++- ai_anti_malware/sandbox_callbacks.cpp | 106 ++++- ai_anti_malware/sandbox_callbacks.h | 13 +- 6 files changed, 748 insertions(+), 25 deletions(-) diff --git a/ai_anti_malware/ai_anti_malware.cpp b/ai_anti_malware/ai_anti_malware.cpp index 794794f..3815a78 100644 --- a/ai_anti_malware/ai_anti_malware.cpp +++ b/ai_anti_malware/ai_anti_malware.cpp @@ -32,7 +32,7 @@ auto getPeInfo(std::string inputFilePath) -> std::shared_ptr { return sampleInfo; } int main() { - auto sampleInfo = getPeInfo("C:\\ConsoleApplication1.exe"); + auto sampleInfo = getPeInfo("E:\\对战平台\\CrowAntiCheat\\CrowAntiCheat\\client\\Console_Test\\x64\\Release\\Console_Test.exe"); printf("input new file %s \n", sampleInfo->inputFilePath); printf("is x64: %d\n", sampleInfo->isX64); printf("is relocated: %d\n", sampleInfo->isRelocated); diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index 26d36d4..45e6684 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -399,8 +399,8 @@ auto Sandbox::SetupVirtualMachine() -> void { m_tebBase = TEB_BASE; // 进程TEB地址 m_pebBase = PEB_BASE; // 进程PEB地址 // stack - m_stackBase = this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32; - m_stackSize = this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32; + m_stackBase = AlignSize(this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32, 16); + m_stackSize = AlignSize(this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32, 16); m_stackEnd = m_stackBase + m_stackSize; // heap @@ -525,7 +525,6 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { printf("map file to vm size: %llx\n", m_peInfo->peSize); SetupVirtualMachine(); InitCommandLine(peInfo->inputFilePath); - } auto Sandbox::Run() -> void { @@ -544,12 +543,16 @@ auto Sandbox::Run() -> void { } // 设置寄存器 - uint64_t rsp = m_stackEnd - 128; + uint64_t rsp = m_stackEnd - 256; err = uc_reg_write(m_ucEngine, m_peInfo->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP, &rsp); if (err != UC_ERR_OK) { throw std::runtime_error("Failed to write stack pointer"); } + uint64_t rbp = + rsp - (m_peInfo->isX64 ? sizeof(uint64_t) : sizeof(uint32_t)); + uc_reg_write(m_ucEngine, m_peInfo->isX64 ? UC_X86_REG_RBP : UC_X86_REG_EBP, + &rbp); // 设置入口点 uint64_t entryPoint = m_peInfo->RecImageBase + m_peInfo->entryPoint; @@ -610,10 +613,9 @@ auto Sandbox::Run() -> void { throw std::runtime_error("Failed to set entry point"); } - // 开始执行 + InitApiHooks(); std::cout << "Starting execution at " << std::hex << entryPoint << std::endl; - InitApiHooks(); err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, 0, 0); if (err != UC_ERR_OK) { std::cerr << "Emulation error: " << uc_strerror(err) << std::endl; diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 89b99c0..148d3f3 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -10,10 +10,10 @@ #define SF_MASK (1 << 7) #define OF_MASK (1 << 11) #define ALL_MASK (OF_MASK | SF_MASK | ZF_MASK | PF_MASK | CF_MASK) -#define STACK_BASE_64 0x7ffffffde000 -#define STACK_BASE_32 0xfffdd000 +#define STACK_BASE_64 0x14A0000 +#define STACK_BASE_32 0x14A0000 #define STACK_SIZE_64 0x40000 -#define STACK_SIZE_32 0x21000 +#define STACK_SIZE_32 0x40000 #define HEAP_ADDRESS_64 0x500000000 #define HEAP_SIZE_64 0x5000000 #define HEAP_ADDRESS_32 0x5000000 diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index 8f985e0..ea4538d 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -1,4 +1,5 @@ #include "sandbox.h" +#include "sandbox_callbacks.h" std::string getDllNameFromApiSetMap(const std::string& apiSet); auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address) -> void { @@ -1145,6 +1146,240 @@ auto Api_GetCPInfo(void* sandbox, uc_engine* uc, uint64_t address) -> void { &success); } +auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint32_t CodePage = 0; + uint32_t dwFlags = 0; + uint64_t lpMultiByteStr = 0; + int32_t cbMultiByte = 0; + uint64_t lpWideCharStr = 0; + int32_t cchWideChar = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + uint64_t temp_codepage = 0; + uint64_t temp_flags = 0; + uint64_t temp_multibyte = 0; + uint64_t temp_cbmultibyte = 0; + + // x64: rcx, rdx, r8, r9, [rsp+0x28], [rsp+0x30] + uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage); + uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags); + uc_reg_read(uc, UC_X86_REG_R8, &temp_multibyte); + uc_reg_read(uc, UC_X86_REG_R9, &temp_cbmultibyte); + + CodePage = static_cast(temp_codepage); + dwFlags = static_cast(temp_flags); + lpMultiByteStr = temp_multibyte; + cbMultiByte = static_cast(temp_cbmultibyte); + + // 获取栈上的参数 + uint64_t rsp = 0; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + + // 为了确保安全访问,先验证栈地址的有效性 + if (rsp < 0x8000000000000000 || rsp + 0x40 > 0x8000000000010000) { + // 无效的栈地址 + DWORD error = ERROR_INVALID_PARAMETER; + context->GetTeb64()->LastErrorValue = error; + int result = 0; + uc_reg_write(uc, UC_X86_REG_RAX, &result); + return; + } + + // 读取栈上的参数 + uint64_t shadow_space = 0x20; // x64调用约定中的shadow space + uc_mem_read(uc, rsp + shadow_space + 0x8, &lpWideCharStr, + sizeof(uint64_t)); + uc_mem_read(uc, rsp + shadow_space + 0x10, &cchWideChar, + sizeof(int32_t)); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + + uc_mem_read(uc, esp_address, &CodePage, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &dwFlags, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x8, &lpMultiByteStr, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0xC, &cbMultiByte, sizeof(int32_t)); + uc_mem_read(uc, esp_address + 0x10, &lpWideCharStr, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x14, &cchWideChar, sizeof(int32_t)); + } + + // 验证参数 + if (lpMultiByteStr == 0 || (lpWideCharStr == 0 && cchWideChar != 0)) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 读取源字符串 + std::vector srcBuffer; + if (cbMultiByte == -1) { + // 如果长度为-1,则源字符串以null结尾 + char ch = 0; + size_t len = 0; + do { + if (uc_mem_read(uc, lpMultiByteStr + len, &ch, 1) != UC_ERR_OK) { + break; + } + srcBuffer.push_back(ch); + len++; + } while (ch != 0 && len < MAX_PATH); // 添加长度限制防止无限循环 + + if (len >= MAX_PATH) { + // 设置错误码 + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + cbMultiByte = static_cast(len); + } else if (cbMultiByte > 0) { + // 使用指定长度,但添加安全检查 + if (cbMultiByte > MAX_PATH) { + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + srcBuffer.resize(cbMultiByte); + if (uc_mem_read(uc, lpMultiByteStr, srcBuffer.data(), cbMultiByte) != + UC_ERR_OK) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + } else { + // 无效的输入长度 + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 计算所需的宽字符缓冲区大小 + int result = MultiByteToWideChar(CodePage, dwFlags, srcBuffer.data(), + cbMultiByte, nullptr, 0); + + if (result == 0) { + // 转换失败,获取错误码 + DWORD error = GetLastError(); + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 如果只是查询所需缓冲区大小 + if (lpWideCharStr == 0 || cchWideChar == 0) { + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 检查目标缓冲区大小是否足够 + if (cchWideChar < result) { + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 执行实际转换 + std::vector wideBuffer(result); + if (MultiByteToWideChar(CodePage, dwFlags, srcBuffer.data(), cbMultiByte, + wideBuffer.data(), result) > 0) { + // 写入转换后的字符串到目标内存 + if (uc_mem_write(uc, lpWideCharStr, wideBuffer.data(), + result * sizeof(wchar_t)) != UC_ERR_OK) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + result = 0; + } + } else { + // 转换失败 + DWORD error = GetLastError(); + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + result = 0; + } + + printf( + "[*] MultiByteToWideChar: CodePage=%u, Flags=0x%x, Input=%p, " + "InputLen=%d, Output=%p, OutputLen=%d, Result=%d\n", + CodePage, dwFlags, (void*)lpMultiByteStr, cbMultiByte, + (void*)lpWideCharStr, cchWideChar, result); + + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} + auto Sandbox::CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment* { auto segment = new HeapSegment(); segment->base = base; @@ -1279,6 +1514,383 @@ auto Sandbox::InitCommandLine(std::string commandLine) -> void { (wCommandLine.length() + 1) * sizeof(wchar_t)); } +auto Api_GetModuleFileNameW(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint64_t hModule = 0; + uint64_t lpFilename = 0; + uint32_t nSize = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = hModule, rdx = lpFilename, r8 = nSize + uc_reg_read(uc, UC_X86_REG_RCX, &hModule); + uc_reg_read(uc, UC_X86_REG_RDX, &lpFilename); + uint64_t temp_size; + uc_reg_read(uc, UC_X86_REG_R8, &temp_size); + nSize = static_cast(temp_size); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + uint32_t temp_module = 0; + uint32_t temp_filename = 0; + uc_mem_read(uc, esp_address, &temp_module, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &temp_filename, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x8, &nSize, sizeof(uint32_t)); + hModule = temp_module; + lpFilename = temp_filename; + } + + uint32_t result = 0; + + // 验证参数 + if (lpFilename == 0 || nSize == 0) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + std::wstring modulePath; + if (hModule == 0) { + // 如果hModule为NULL,返回主模块(PE文件)的路径 + modulePath = std::wstring(context->GetPeInfo()->inputFilePath.begin(), + context->GetPeInfo()->inputFilePath.end()); + } else { + // 在模块列表中查找对应模块 + bool found = false; + for (const auto& module : context->GetModuleList()) { + if (module->base == hModule) { + // 构建完整的模块路径 + char windowsPath[MAX_PATH]; + GetWindowsDirectoryA(windowsPath, sizeof(windowsPath)); + + // 根据PE架构选择正确的系统目录 + const std::string systemDir = context->GetPeInfo()->isX64 + ? "\\System32\\" + : "\\SysWOW64\\"; + + std::string fullPath = + std::string(windowsPath) + systemDir + module->name; + modulePath = std::wstring(fullPath.begin(), fullPath.end()); + found = true; + break; + } + } + + if (!found) { + DWORD error = ERROR_MOD_NOT_FOUND; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + uc_reg_write( + uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + } + + // 检查缓冲区大小是否足够 + if (nSize < modulePath.length() + 1) { + // 缓冲区太小,返回所需大小 + result = static_cast(modulePath.length() + 1); + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + } else { + // 写入路径到缓冲区 + if (uc_mem_write(uc, lpFilename, modulePath.c_str(), + (modulePath.length() + 1) * sizeof(wchar_t)) == + UC_ERR_OK) { + result = static_cast(modulePath.length()); + } else { + result = 0; + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + } + } + + printf( + "[*] GetModuleFileNameW: Module=0x%llx, Buffer=0x%llx, Size=%u, " + "Result=%u, Path=%ls\n", + hModule, lpFilename, nSize, result, modulePath.c_str()); + + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} + +// 实现 AreFileApisANSI API +auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + // 默认返回TRUE,表示使用ANSI字符集 + BOOL isAnsi = TRUE; + printf("[*] AreFileApisANSI: IsAnsi=%d\n", isAnsi); + + // 返回结果 + uc_reg_write(uc, + static_cast(sandbox)->GetPeInfo()->isX64 + ? UC_X86_REG_RAX + : UC_X86_REG_EAX, + &isAnsi); +} + +auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint32_t CodePage = 0; + uint32_t dwFlags = 0; + uint64_t lpWideCharStr = 0; + int32_t cchWideChar = 0; + uint64_t lpMultiByteStr = 0; + int32_t cbMultiByte = 0; + uint64_t lpDefaultChar = 0; + uint64_t lpUsedDefaultChar = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx, rdx, r8, r9, [rsp+0x28], [rsp+0x30], [rsp+0x38], [rsp+0x40] + uint64_t temp_codepage = 0; + uint64_t temp_flags = 0; + uint64_t temp_widechar = 0; + uint64_t temp_cchwidechar = 0; + + uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage); + uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags); + uc_reg_read(uc, UC_X86_REG_R8, &temp_widechar); + uc_reg_read(uc, UC_X86_REG_R9, &temp_cchwidechar); + + CodePage = static_cast(temp_codepage); + dwFlags = static_cast(temp_flags); + lpWideCharStr = temp_widechar; + cchWideChar = static_cast(temp_cchwidechar); + + // 获取栈上的参数 + uint64_t rsp = 0; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uint64_t shadow_space = 0x20; + + uc_mem_read(uc, rsp + shadow_space + 0x8, &lpMultiByteStr, + sizeof(uint64_t)); + uc_mem_read(uc, rsp + shadow_space + 0x10, &cbMultiByte, + sizeof(int32_t)); + uc_mem_read(uc, rsp + shadow_space + 0x18, &lpDefaultChar, + sizeof(uint64_t)); + uc_mem_read(uc, rsp + shadow_space + 0x20, &lpUsedDefaultChar, + sizeof(uint64_t)); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + + uc_mem_read(uc, esp_address, &CodePage, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &dwFlags, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x8, &lpWideCharStr, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0xC, &cchWideChar, sizeof(int32_t)); + uc_mem_read(uc, esp_address + 0x10, &lpMultiByteStr, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x14, &cbMultiByte, sizeof(int32_t)); + uc_mem_read(uc, esp_address + 0x18, &lpDefaultChar, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x1C, &lpUsedDefaultChar, + sizeof(uint32_t)); + } + + // 基本参数验证 + if (lpWideCharStr == 0 || cchWideChar == 0) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 读取源宽字符串 + std::vector srcBuffer; + size_t actualWideLength = 0; + + if (cchWideChar == -1) { + // 如果长度为-1,则源字符串以null结尾 + wchar_t ch = 0; + do { + if (uc_mem_read(uc, lpWideCharStr + (actualWideLength * 2), &ch, + 2) != UC_ERR_OK) { + break; + } + srcBuffer.push_back(ch); + actualWideLength++; + } while (ch != 0 && actualWideLength < MAX_PATH); + + if (actualWideLength >= MAX_PATH) { + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + } else { + // 使用指定长度 + if (cchWideChar > 0 && cchWideChar <= MAX_PATH) { + srcBuffer.resize(cchWideChar); + if (uc_mem_read(uc, lpWideCharStr, srcBuffer.data(), + cchWideChar * 2) != UC_ERR_OK) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX + : UC_X86_REG_EAX, + &result); + return; + } + actualWideLength = cchWideChar; + } else { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + } + + // 读取默认字符和使用默认字符标志 + char defaultChar = '?'; + BOOL usedDefaultChar = FALSE; + if (lpDefaultChar != 0) { + uc_mem_read(uc, lpDefaultChar, &defaultChar, 1); + } + + // 计算所需的多字节缓冲区大小 + int requiredSize = WideCharToMultiByte( + CodePage, dwFlags, srcBuffer.data(), static_cast(actualWideLength), + nullptr, 0, lpDefaultChar ? &defaultChar : nullptr, + lpUsedDefaultChar ? &usedDefaultChar : nullptr); + + if (requiredSize == 0) { + // 获取并设置错误码 + DWORD error = GetLastError(); + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 如果只是查询所需缓冲区大小 + if (lpMultiByteStr == 0 || cbMultiByte == 0) { + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &requiredSize); + return; + } + + // 检查目标缓冲区大小是否足够 + if (cbMultiByte < requiredSize) { + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + int result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + return; + } + + // 执行实际转换 + std::vector multiByteBuffer(requiredSize); + int result = WideCharToMultiByte( + CodePage, dwFlags, srcBuffer.data(), static_cast(actualWideLength), + multiByteBuffer.data(), requiredSize, + lpDefaultChar ? &defaultChar : nullptr, + lpUsedDefaultChar ? &usedDefaultChar : nullptr); + + if (result > 0) { + // 写入转换后的字符串到目标内存 + if (uc_mem_write(uc, lpMultiByteStr, multiByteBuffer.data(), result) != + UC_ERR_OK) { + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + result = 0; + } + + // 如果需要,写回使用默认字符标志 + if (lpUsedDefaultChar != 0) { + uc_mem_write(uc, lpUsedDefaultChar, &usedDefaultChar, sizeof(BOOL)); + } + } else { + // 获取并设置错误码 + DWORD error = GetLastError(); + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + } + + printf( + "[*] WideCharToMultiByte: CodePage=%u, Flags=0x%x, WideStr=%p, " + "WideLen=%d, MultiStr=%p, MultiLen=%d, Result=%d\n", + CodePage, dwFlags, (void*)lpWideCharStr, cchWideChar, + (void*)lpMultiByteStr, cbMultiByte, result); + + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} + auto Sandbox::InitApiHooks() -> void { auto FakeApi_GetSystemTimeAsFileTime = _fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1}; @@ -1329,6 +1941,14 @@ auto Sandbox::InitApiHooks() -> void { _fakeApi{.func = Api_GetCommandLineW, .paramCount = 0}; auto FakeApi_GetACP = _fakeApi{.func = Api_GetACP, .paramCount = 0}; auto FakeApi_GetCPInfo = _fakeApi{.func = Api_GetCPInfo, .paramCount = 2}; + auto FakeApi_MultiByteToWideChar = + _fakeApi{.func = Api_MultiByteToWideChar, .paramCount = 6}; + auto FakeApi_GetModuleFileNameW = + _fakeApi{.func = Api_GetModuleFileNameW, .paramCount = 3}; + auto FakeApi_AreFileApisANSI = + _fakeApi{.func = Api_AreFileApisANSI, .paramCount = 0}; + auto FakeApi_WideCharToMultiByte = + _fakeApi{.func = Api_WideCharToMultiByte, .paramCount = 8}; api_map = { {"GetSystemTimeAsFileTime", @@ -1370,13 +1990,21 @@ auto Sandbox::InitApiHooks() -> void { {"GetCommandLineW", std::make_shared<_fakeApi>(FakeApi_GetCommandLineW)}, {"GetACP", std::make_shared<_fakeApi>(FakeApi_GetACP)}, - {"GetCPInfo", std::make_shared<_fakeApi>(FakeApi_GetCPInfo)}}; + {"GetCPInfo", std::make_shared<_fakeApi>(FakeApi_GetCPInfo)}, + {"MultiByteToWideChar", + std::make_shared<_fakeApi>(FakeApi_MultiByteToWideChar)}, + {"GetModuleFileNameW", + std::make_shared<_fakeApi>(FakeApi_GetModuleFileNameW)}, + {"AreFileApisANSI", + std::make_shared<_fakeApi>(FakeApi_AreFileApisANSI)}, + {"WideCharToMultiByte", + std::make_shared<_fakeApi>(FakeApi_WideCharToMultiByte)}, + }; } auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, std::string ApiName) -> void { auto it = api_map.find(ApiName); if (it != api_map.end()) { - // 调用API函数 it->second->func(this, uc, address); // 获取参数数量 diff --git a/ai_anti_malware/sandbox_callbacks.cpp b/ai_anti_malware/sandbox_callbacks.cpp index 3635165..b8f7ded 100644 --- a/ai_anti_malware/sandbox_callbacks.cpp +++ b/ai_anti_malware/sandbox_callbacks.cpp @@ -1,5 +1,5 @@ #include "sandbox_callbacks.h" -#define LOG_LEVEL 0 +#define LOG_LEVEL 1 namespace sandboxCallbacks { void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, void* userData) { @@ -46,6 +46,8 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, instruction[0].mnemonic, instruction[0].op_str); } cs_free(instruction, instructionCount); + + dumpVmenv(uc, userData); } } @@ -54,7 +56,10 @@ void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address, auto* sandbox = static_cast(userData); if (!sandbox) return; - uint64_t regRax, regRip; + uint64_t regRax, regRip, regRbp; + uc_reg_read(uc, + sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RBP : UC_X86_REG_EBP, + ®Rbp); uc_reg_read(uc, sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, ®Rax); @@ -68,8 +73,9 @@ void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address, if (LOG_LEVEL > 0) { printf( "[handleMemoryRead] Address: %p Size: %p Rax: %p Rip: %p Error: %d " - "ReadData: %p\n", - address, size, regRax, regRip, readError, readAddress); + "ReadData: %p Rbp: %p\n", + address, size, regRax, regRip, readError, readAddress, regRbp); + sandboxCallbacks::dumpVmenv(uc, sandbox); } } void dumpVmenv(uc_engine* uc, void* userData) { @@ -81,6 +87,8 @@ void dumpVmenv(uc_engine* uc, void* userData) { uint64_t Rbp = 0; uint64_t Rcx = 0; uint64_t Rdx = 0; + uint64_t Eax = 0; + uint64_t Ecx = 0; uc_reg_read(uc, sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP, &Rip); @@ -99,8 +107,94 @@ void dumpVmenv(uc_engine* uc, void* userData) { uc_reg_read(uc, sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RDX : UC_X86_REG_EDX, &Rdx); - printf("[dumpVmenv] Rip: %p Rax: %p Rsp: %p Rbp: %p Rcx: %p Rdx: %p\n", Rip, - Rax, Rsp, Rbp, Rcx, Rdx); + uc_reg_read(uc, + sandbox->GetPeInfo()->isX64 ? UC_X86_REG_EAX : UC_X86_REG_EAX, + &Eax); + uc_reg_read(uc, + sandbox->GetPeInfo()->isX64 ? UC_X86_REG_ECX : UC_X86_REG_ECX, + &Ecx); + printf( + "[dumpVmenv] Rip: %p Rax: %p Rsp: %p Rbp: %p Rcx: %p Rdx: %p Eax: " + "%08x Ecx: %08x\n", + Rip, Rax, Rsp, Rbp, Rcx, Rdx, Eax, Ecx); + + // 打印16层栈内存 + printf("\n[Stack Memory Dump (16 levels)]\n"); + const int STACK_LEVELS = 16; + const int POINTER_SIZE = sandbox->GetPeInfo()->isX64 ? 8 : 4; + + for (int i = 0; i < STACK_LEVELS; i++) { + uint64_t currentAddress = Rsp + (i * POINTER_SIZE); + uint64_t memValue = 0; + + if (uc_mem_read(uc, currentAddress, &memValue, POINTER_SIZE) == + UC_ERR_OK) { + printf("RSP+%02X [%p]: ", i * POINTER_SIZE, currentAddress); + // 按4字节分组显示十六进制 + for (int j = 0; j < POINTER_SIZE; j += 4) { + uint32_t chunk; + size_t chunkSize = min(4, POINTER_SIZE - j); + if (uc_mem_read(uc, currentAddress + j, &chunk, chunkSize) == + UC_ERR_OK) { + printf("%08X ", chunk); + } else { + printf("???????? "); + } + } + + // 显示ASCII字符 + printf("| "); + for (int j = 0; j < POINTER_SIZE; j++) { + uint8_t byte; + if (uc_mem_read(uc, currentAddress + j, &byte, 1) == + UC_ERR_OK) { + printf("%c", (byte >= 32 && byte <= 126) ? byte : '.'); + } else { + printf("?"); + } + } + printf("\n"); + } else { + printf("RSP+%02X [%p]: Unable to read memory\n", i * POINTER_SIZE, + currentAddress); + } + } + + printf("\n[Frame Pointer Stack (16 levels)]\n"); + uint64_t currentBp = Rbp; + for (int i = 0; i < STACK_LEVELS && currentBp != 0; i++) { + uint64_t nextBp = 0; + if (uc_mem_read(uc, currentBp, &nextBp, POINTER_SIZE) == UC_ERR_OK) { + printf("Frame %02d [%p]: ", i, currentBp); + // 按4字节分组显示十六进制 + for (int j = 0; j < POINTER_SIZE; j += 4) { + uint32_t chunk; + size_t chunkSize = min(4, POINTER_SIZE - j); + if (uc_mem_read(uc, currentBp + j, &chunk, chunkSize) == + UC_ERR_OK) { + printf("%08X ", chunk); + } else { + printf("???????? "); + } + } + + // 显示ASCII字符 + printf("| "); + for (int j = 0; j < POINTER_SIZE; j++) { + uint8_t byte; + if (uc_mem_read(uc, currentBp + j, &byte, 1) == UC_ERR_OK) { + printf("%c", (byte >= 32 && byte <= 126) ? byte : '.'); + } else { + printf("?"); + } + } + printf("\n"); + currentBp = nextBp; + } else { + printf("Frame %02d [%p]: Unable to read memory\n", i, currentBp); + break; + } + } } void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type, uint64_t address, int size, int64_t value, void* userData) { diff --git a/ai_anti_malware/sandbox_callbacks.h b/ai_anti_malware/sandbox_callbacks.h index 74f390b..cecad91 100644 --- a/ai_anti_malware/sandbox_callbacks.h +++ b/ai_anti_malware/sandbox_callbacks.h @@ -2,15 +2,14 @@ #include "sandbox.h" namespace sandboxCallbacks { void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, - void* userData); + void* userData); void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address, - int size, int64_t value, void* userData); -void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type, - uint64_t address, int size, int64_t value, - void* userData); + int size, int64_t value, void* userData); +void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void* userData); void handleMemoryWrite(uc_engine* uc, uc_mem_type type, uint64_t address, - int size, int64_t value, void* userData); + int size, int64_t value, void* userData); void handleSyscall(uc_engine* uc, void* userData); auto InitApiHooks() -> void; - +void dumpVmenv(uc_engine* uc, void* userData); }; // namespace sandboxCallbacks