From e160fd0d574ddee201a5e01b5c70331ec4e243e7 Mon Sep 17 00:00:00 2001 From: huoji Date: Fri, 25 Apr 2025 16:08:22 +0800 Subject: [PATCH] fix up --- ai_anti_malware/ai_anti_malware.cpp | 9 +- ai_anti_malware/ai_anti_malware.vcxproj | 1 + .../ai_anti_malware.vcxproj.filters | 3 + ai_anti_malware/sandbox.cpp | 6 + ai_anti_malware/sandbox.h | 22 +- ai_anti_malware/sandbox_api_emu.cpp | 362 +---------- ai_anti_malware/sandbox_api_files.cpp | 295 +++++++++ ai_anti_malware/sandbox_api_stl.cpp | 588 ++++++++++++++++++ 8 files changed, 937 insertions(+), 349 deletions(-) create mode 100644 ai_anti_malware/sandbox_api_files.cpp diff --git a/ai_anti_malware/ai_anti_malware.cpp b/ai_anti_malware/ai_anti_malware.cpp index 855728f..1f7e897 100644 --- a/ai_anti_malware/ai_anti_malware.cpp +++ b/ai_anti_malware/ai_anti_malware.cpp @@ -375,8 +375,13 @@ int main(int argc, char* argv[]) { } std::string filePath = argv[1]; + + std::string filePath = ""; + DetectEngine scanner; + + DetectEngineType result = scanner.DetectMalware(filePath); + printf("result: %d \n", result); + //DetectMalwareInDirectory(filePath); */ - std::string filePath = "Z:\\123"; - DetectMalwareInDirectory(filePath); return 0; } diff --git a/ai_anti_malware/ai_anti_malware.vcxproj b/ai_anti_malware/ai_anti_malware.vcxproj index 68b9668..28b8c00 100644 --- a/ai_anti_malware/ai_anti_malware.vcxproj +++ b/ai_anti_malware/ai_anti_malware.vcxproj @@ -180,6 +180,7 @@ + diff --git a/ai_anti_malware/ai_anti_malware.vcxproj.filters b/ai_anti_malware/ai_anti_malware.vcxproj.filters index 3d838d4..11162a8 100644 --- a/ai_anti_malware/ai_anti_malware.vcxproj.filters +++ b/ai_anti_malware/ai_anti_malware.vcxproj.filters @@ -171,6 +171,9 @@ 源文件\sandbox + + 源文件\sandbox\apis + diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index ff05030..49968e9 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -185,6 +185,12 @@ Sandbox::~Sandbox() { } m_wfpEngines.clear(); + // 清理文件句柄资源 + for (auto& pair : m_fileHandles) { + delete pair.second; + } + m_fileHandles.clear(); + // 1. 先清理高层资源 m_crossSectionExecution.clear(); envStrings.clear(); diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 9f82c90..76c5494 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -85,6 +85,9 @@ struct InternetHandleInfo { size_t currentPosition; }; +// 添加文件句柄信息前向声明 +struct FileHandleInfo; + class Sandbox { friend class cFixImprot; // 声明cFixImprot为友元类 public: @@ -252,6 +255,13 @@ class Sandbox { // 注册COM相关API void RegisterComApis(); + // 文件句柄管理相关方法 + auto GenerateFileHandle() -> uint64_t; + auto GetFileHandleInfo(uint64_t handle) -> FileHandleInfo*; + + // 文件句柄表 + static std::map m_fileHandles; + private: std::shared_ptr m_peInfo; std::pair> m_lastImpRead; @@ -461,4 +471,14 @@ auto Api_TlsFree(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_FlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api__initterm_e(void* sandbox, uc_engine* uc, uint64_t address) -> void; -auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void; \ No newline at end of file +auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_GetStringTypeW(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_LCMapStringW(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_LCMapStringEx(void* sandbox, uc_engine* uc, uint64_t address) -> void; + +// 文件API函数声明 +auto Api_ReadFileA(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_ReadFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_ReadFile(void* sandbox, uc_engine* uc, uint64_t address, bool isWideChar) -> void; +auto Api_CloseFile(void* sandbox, uc_engine* uc, uint64_t address) -> void; \ No newline at end of file diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index eb36323..28c6c9e 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -858,350 +858,6 @@ auto Api_AdjustTokenPrivileges(void* sandbox, uc_engine* uc, uint64_t address) context->GetTeb32()->LastErrorValue = error; } } -auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address) - -> void { - auto context = static_cast(sandbox); - uint64_t lpPathName = 0; - uint64_t lpSecurityAttributes = 0; - - // 获取参数 - if (context->GetPeInfo()->isX64) { - // x64: rcx = lpPathName, rdx = lpSecurityAttributes - uc_reg_read(uc, UC_X86_REG_RCX, &lpPathName); - uc_reg_read(uc, UC_X86_REG_RDX, &lpSecurityAttributes); - } else { - // x86: 从栈上读取参数 - uint32_t esp_address = 0; - uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); - esp_address += 0x4; // 跳过返回地址 - - uint32_t temp_path_name, temp_security_attr; - uc_mem_read(uc, esp_address, &temp_path_name, sizeof(uint32_t)); - uc_mem_read(uc, esp_address + 0x4, &temp_security_attr, - sizeof(uint32_t)); - - lpPathName = temp_path_name; - lpSecurityAttributes = temp_security_attr; - } - - // 读取目录路径 - wchar_t pathBuffer[MAX_PATH] = {0}; - if (lpPathName != 0) { - size_t i = 0; - do { - uint16_t wchar; - uc_mem_read(uc, lpPathName + (i * 2), &wchar, 2); - pathBuffer[i] = wchar; - i++; - } while (pathBuffer[i - 1] != 0 && i < MAX_PATH); - } - - // 将宽字符转换为常规字符串用于日志输出 - std::wstring widePath(pathBuffer); - std::string path(widePath.begin(), widePath.end()); - - // 在实际的实现中,可能需要检查目录是否已存在 - // 这里简单地返回成功,不实际创建目录 - bool success = true; - - // 输出日志 - printf("[*] CreateDirectoryW: Path=%s, Result=%s\n", path.c_str(), - success ? "TRUE" : "FALSE"); - - // 设置返回值 - uint64_t result = success ? 1 : 0; - uc_reg_write(uc, - context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); - - // 如果失败,可以设置LastError - if (!success) { - DWORD error = ERROR_PATH_NOT_FOUND; // 或其他适当的错误代码 - if (context->GetPeInfo()->isX64) { - context->GetTeb64()->LastErrorValue = error; - } else { - context->GetTeb32()->LastErrorValue = error; - } - } -} -auto Api_GetStringTypeW(void* sandbox, uc_engine* uc, uint64_t address) - -> void { - auto context = static_cast(sandbox); - uint64_t dwInfoType = 0; - uint64_t lpSrcStr = 0; - int32_t cchSrc = 0; - uint64_t lpCharType = 0; - - // 获取参数 - if (context->GetPeInfo()->isX64) { - // x64: rcx = dwInfoType, rdx = lpSrcStr, r8 = cchSrc, r9 = lpCharType - uc_reg_read(uc, UC_X86_REG_RCX, &dwInfoType); - uc_reg_read(uc, UC_X86_REG_RDX, &lpSrcStr); - uint64_t temp_size; - uc_reg_read(uc, UC_X86_REG_R8, &temp_size); - cchSrc = static_cast(temp_size); - uc_reg_read(uc, UC_X86_REG_R9, &lpCharType); - } 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, &dwInfoType, sizeof(uint32_t)); - esp_address += 0x4; - - uint32_t temp_src_str; - uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t)); - lpSrcStr = temp_src_str; - esp_address += 0x4; - - uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t)); - esp_address += 0x4; - - uint32_t temp_char_type; - uc_mem_read(uc, esp_address, &temp_char_type, sizeof(uint32_t)); - lpCharType = temp_char_type; - } - - // 验证参数 - if (lpSrcStr == 0 || lpCharType == 0) { - uint64_t result = 0; // FALSE - uc_reg_write( - uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); - DWORD error = ERROR_INVALID_PARAMETER; - if (context->GetPeInfo()->isX64) { - context->GetTeb64()->LastErrorValue = error; - } else { - context->GetTeb32()->LastErrorValue = error; - } - return; - } - - // 如果cchSrc为负数,计算字符串长度 - if (cchSrc < 0) { - cchSrc = 0; - wchar_t temp_char; - do { - uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char, - sizeof(wchar_t)); - cchSrc++; - } while (temp_char != 0 && cchSrc < 1024); // 设置一个合理的上限 - cchSrc--; // 不包括null终止符 - } - - // 读取源字符串 - std::vector srcStr(cchSrc); - uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t)); - - // 处理每个字符 - std::vector charTypes(cchSrc); - for (int i = 0; i < cchSrc; i++) { - WORD type = 0; - wchar_t ch = srcStr[i]; - - switch (dwInfoType) { - case CT_CTYPE1: { - // 基本字符类型检查 - if (iswupper(ch)) type |= C1_UPPER; - if (iswlower(ch)) type |= C1_LOWER; - if (iswdigit(ch)) type |= C1_DIGIT; - if (iswspace(ch)) type |= C1_SPACE; - if (iswpunct(ch)) type |= C1_PUNCT; - if (iswcntrl(ch)) type |= C1_CNTRL; - if (ch == L' ' || ch == L'\t') type |= C1_BLANK; - if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'F') || - (ch >= L'a' && ch <= L'f')) - type |= C1_XDIGIT; - if (iswalpha(ch)) type |= C1_ALPHA; - if (type == 0) type |= C1_DEFINED; - break; - } - case CT_CTYPE2: { - // 简单的双向文本支持 - if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z') || - (ch >= L'0' && ch <= L'9')) { - type = C2_LEFTTORIGHT; - } else if (iswspace(ch)) { - type = C2_WHITESPACE; - } else { - type = C2_NOTAPPLICABLE; - } - break; - } - case CT_CTYPE3: { - // 基本文本处理信息 - if (iswalpha(ch)) type |= C3_ALPHA; - // 这里可以添加更多的C3类型检查 - break; - } - } - charTypes[i] = type; - } - - // 写入结果 - uc_mem_write(uc, lpCharType, charTypes.data(), cchSrc * sizeof(WORD)); - - printf("[*] GetStringTypeW: InfoType=0x%x, StrLen=%d\n", dwInfoType, - cchSrc); - - // 返回成功 - uint64_t result = 1; // TRUE - uc_reg_write(uc, - context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); -} - -auto Api_LCMapStringW(void* sandbox, uc_engine* uc, uint64_t address) -> void { - auto context = static_cast(sandbox); - uint32_t Locale = 0; - uint32_t dwMapFlags = 0; - uint64_t lpSrcStr = 0; - int32_t cchSrc = 0; - uint64_t lpDestStr = 0; - int32_t cchDest = 0; - - // 获取参数 - if (context->GetPeInfo()->isX64) { - // x64: rcx = Locale, rdx = dwMapFlags, r8 = lpSrcStr, r9 = cchSrc - uc_reg_read(uc, UC_X86_REG_RCX, &Locale); - uc_reg_read(uc, UC_X86_REG_RDX, &dwMapFlags); - uc_reg_read(uc, UC_X86_REG_R8, &lpSrcStr); - uint64_t temp_src_size; - uc_reg_read(uc, UC_X86_REG_R9, &temp_src_size); - cchSrc = static_cast(temp_src_size); - - // 从栈上读取剩余参数 - uint64_t rsp; - uc_reg_read(uc, UC_X86_REG_RSP, &rsp); - uc_mem_read(uc, rsp + 0x28, &lpDestStr, sizeof(uint64_t)); - uc_mem_read(uc, rsp + 0x30, &cchDest, 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, &Locale, sizeof(uint32_t)); - esp_address += 0x4; - - uc_mem_read(uc, esp_address, &dwMapFlags, sizeof(uint32_t)); - esp_address += 0x4; - - uint32_t temp_src_str; - uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t)); - lpSrcStr = temp_src_str; - esp_address += 0x4; - - uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t)); - esp_address += 0x4; - - uint32_t temp_dest_str; - uc_mem_read(uc, esp_address, &temp_dest_str, sizeof(uint32_t)); - lpDestStr = temp_dest_str; - esp_address += 0x4; - - uc_mem_read(uc, esp_address, &cchDest, sizeof(int32_t)); - } - - // 验证参数 - if (lpSrcStr == 0) { - uint32_t result = 0; - uc_reg_write( - uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); - DWORD error = ERROR_INVALID_PARAMETER; - if (context->GetPeInfo()->isX64) { - context->GetTeb64()->LastErrorValue = error; - } else { - context->GetTeb32()->LastErrorValue = error; - } - return; - } - - // 如果cchSrc为负数,计算源字符串长度 - if (cchSrc < 0) { - cchSrc = 0; - wchar_t temp_char; - do { - uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char, - sizeof(wchar_t)); - cchSrc++; - } while (temp_char != 0 && cchSrc < 1024); // 设置一个合理的上限 - cchSrc--; // 不包括null终止符 - } - - // 读取源字符串 - std::vector srcStr(cchSrc); - uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t)); - - // 如果cchDest为0,返回所需缓冲区大小 - if (cchDest == 0) { - uint32_t required_size = cchSrc; - if (dwMapFlags & LCMAP_SORTKEY) { - required_size = cchSrc * 2 + 1; // 排序键通常需要更多空间 - } - uc_reg_write( - uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &required_size); - return; - } - - // 检查目标缓冲区大小是否足够 - if (cchDest < cchSrc) { - uint32_t result = 0; - uc_reg_write( - uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); - DWORD error = ERROR_INSUFFICIENT_BUFFER; - if (context->GetPeInfo()->isX64) { - context->GetTeb64()->LastErrorValue = error; - } else { - context->GetTeb32()->LastErrorValue = error; - } - return; - } - - // 处理字符串映射 - std::vector destStr(cchSrc); - for (int i = 0; i < cchSrc; i++) { - wchar_t ch = srcStr[i]; - if (dwMapFlags & LCMAP_UPPERCASE) { - destStr[i] = towupper(ch); - } else if (dwMapFlags & LCMAP_LOWERCASE) { - destStr[i] = towlower(ch); - } else { - destStr[i] = ch; // 默认保持不变 - } - } - - // 写入结果 - if (dwMapFlags & LCMAP_SORTKEY) { - // 生成简单的排序键(这里只是一个基本实现) - std::vector sortKey(cchSrc * 2 + 1); - for (int i = 0; i < cchSrc; i++) { - sortKey[i * 2] = static_cast(destStr[i] & 0xFF); - sortKey[i * 2 + 1] = static_cast((destStr[i] >> 8) & 0xFF); - } - sortKey[cchSrc * 2] = 0; // 终止符 - uc_mem_write(uc, lpDestStr, sortKey.data(), sortKey.size()); - uint32_t result = static_cast(sortKey.size()); - uc_reg_write( - uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); - } else { - // 写入映射后的字符串 - uc_mem_write(uc, lpDestStr, destStr.data(), cchSrc * sizeof(wchar_t)); - uint32_t result = cchSrc; - uc_reg_write( - uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &result); - } - - printf( - "[*] LCMapStringW: Locale=0x%x, MapFlags=0x%x, SrcLen=%d, DestLen=%d\n", - Locale, dwMapFlags, cchSrc, cchDest); -} auto Sandbox::InitApiHooks() -> void { auto FakeApi_GetSystemTimeAsFileTime = @@ -1320,7 +976,6 @@ auto Sandbox::InitApiHooks() -> void { _fakeApi{.func = Api_CreateProcessA, .paramCount = 10}; auto FakeApi_CreateProcessW = _fakeApi{.func = Api_CreateProcessW, .paramCount = 10}; - auto FakeApi_ReadFile = _fakeApi{.func = Api_ReadFile, .paramCount = 5}; auto FakeApi_WlanOpenHandle = _fakeApi{.func = Api_WlanOpenHandle, .paramCount = 4}; auto FakeApi_WlanEnumInterfaces = @@ -1380,6 +1035,15 @@ auto Sandbox::InitApiHooks() -> void { _fakeApi{.func = Api_SysAllocString, .paramCount = 1}; auto FakeApi_LoadLibraryW = _fakeApi{ .func = Api_LoadLibraryW, .paramCount = 1 }; + // *** 新增 LCMapStringEx *** + auto FakeApi_LCMapStringEx = + _fakeApi{.func = Api_LCMapStringEx, .paramCount = 9}; // LCMapStringEx 有 9 个参数 + + // 添加文件操作相关API + auto FakeApi_CreateFileW = _fakeApi{.func = Api_CreateFileW, .paramCount = 7}; + auto FakeApi_ReadFileA = _fakeApi{.func = Api_ReadFileA, .paramCount = 5}; + auto FakeApi_ReadFileW = _fakeApi{.func = Api_ReadFileW, .paramCount = 5}; + auto FakeApi_CloseFile = _fakeApi{.func = Api_CloseFile, .paramCount = 1}; api_map = { {"GetSystemTimeAsFileTime", @@ -1477,7 +1141,6 @@ auto Sandbox::InitApiHooks() -> void { {"CreatePipe", std::make_shared<_fakeApi>(FakeApi_CreatePipe)}, {"CreateProcessA", std::make_shared<_fakeApi>(FakeApi_CreateProcessA)}, {"CreateProcessW", std::make_shared<_fakeApi>(FakeApi_CreateProcessW)}, - {"ReadFile", std::make_shared<_fakeApi>(FakeApi_ReadFile)}, {"WlanOpenHandle", std::make_shared<_fakeApi>(FakeApi_WlanOpenHandle)}, {"WlanEnumInterfaces", std::make_shared<_fakeApi>(FakeApi_WlanEnumInterfaces)}, @@ -1524,6 +1187,13 @@ auto Sandbox::InitApiHooks() -> void { {"VariantClear", std::make_shared<_fakeApi>(FakeApi_VariantClear)}, {"SysAllocString", std::make_shared<_fakeApi>(FakeApi_SysAllocString)}, {"LoadLibraryW", std::make_shared<_fakeApi>(FakeApi_LoadLibraryW)}, + // *** 新增 LCMapStringEx 映射 *** + {"LCMapStringEx", std::make_shared<_fakeApi>(FakeApi_LCMapStringEx)}, + // 添加文件操作相关API映射 + {"CreateFileW", std::make_shared<_fakeApi>(FakeApi_CreateFileW)}, + {"ReadFileA", std::make_shared<_fakeApi>(FakeApi_ReadFileA)}, + {"ReadFileW", std::make_shared<_fakeApi>(FakeApi_ReadFileW)}, + {"CloseFile", std::make_shared<_fakeApi>(FakeApi_CloseFile)}, }; } auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, diff --git a/ai_anti_malware/sandbox_api_files.cpp b/ai_anti_malware/sandbox_api_files.cpp new file mode 100644 index 0000000..2941954 --- /dev/null +++ b/ai_anti_malware/sandbox_api_files.cpp @@ -0,0 +1,295 @@ +#include "sandbox.h" +#include "sandbox_callbacks.h" +#include + +// 文件句柄信息结构体 +struct FileHandleInfo { + uint64_t handle; // 文件句柄 + std::string path; // 文件路径 + std::vector content; // 文件内容 + size_t currentPosition; // 当前读取位置 + bool isValid; // 是否有效 +}; + +// 在Sandbox类中添加文件句柄表 +std::map Sandbox::m_fileHandles; + +// 生成唯一的文件句柄 +uint64_t Sandbox::GenerateFileHandle() { + static uint64_t nextHandle = 0x2000; // 起始值,避免与特殊句柄冲突 + return nextHandle++; +} + +// 获取文件句柄信息 +FileHandleInfo* Sandbox::GetFileHandleInfo(uint64_t handle) { + auto it = m_fileHandles.find(handle); + if (it != m_fileHandles.end()) { + return it->second; + } + return nullptr; +} + +// CreateFileW API实现 +auto Api_CreateFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void { + auto context = static_cast(sandbox); + uint64_t lpFileName = 0; + uint64_t dwDesiredAccess = 0; + uint64_t dwShareMode = 0; + uint64_t lpSecurityAttributes = 0; + uint64_t dwCreationDisposition = 0; + uint64_t dwFlagsAndAttributes = 0; + uint64_t hTemplateFile = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = lpFileName, rdx = dwDesiredAccess, r8 = dwShareMode, r9 = lpSecurityAttributes + uc_reg_read(uc, UC_X86_REG_RCX, &lpFileName); + uc_reg_read(uc, UC_X86_REG_RDX, &dwDesiredAccess); + uint64_t temp_share_mode; + uc_reg_read(uc, UC_X86_REG_R8, &temp_share_mode); + dwShareMode = static_cast(temp_share_mode); + uc_reg_read(uc, UC_X86_REG_R9, &lpSecurityAttributes); + + // 从栈上读取其他参数 + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uc_mem_read(uc, rsp + 0x28, &dwCreationDisposition, sizeof(uint32_t)); + uc_mem_read(uc, rsp + 0x30, &dwFlagsAndAttributes, sizeof(uint32_t)); + uc_mem_read(uc, rsp + 0x38, &hTemplateFile, sizeof(uint64_t)); + } else { + // x86: 从栈上读取参数 + uint32_t esp; + uc_reg_read(uc, UC_X86_REG_ESP, &esp); + esp += 0x4; // 跳过返回地址 + + uint32_t temp_values[7]; + for (int i = 0; i < 7; i++) { + uc_mem_read(uc, esp + (i * 4), &temp_values[i], sizeof(uint32_t)); + } + + lpFileName = temp_values[0]; + dwDesiredAccess = temp_values[1]; + dwShareMode = temp_values[2]; + lpSecurityAttributes = temp_values[3]; + dwCreationDisposition = temp_values[4]; + dwFlagsAndAttributes = temp_values[5]; + hTemplateFile = temp_values[6]; + } + + // 读取文件名 + std::wstring filename; + if (lpFileName != 0) { + wchar_t buffer[MAX_PATH] = {0}; + size_t i = 0; + do { + wchar_t wch; + uc_mem_read(uc, lpFileName + (i * 2), &wch, sizeof(wchar_t)); + buffer[i] = wch; + i++; + } while (buffer[i - 1] != 0 && i < MAX_PATH); + + if (i > 0 && i < MAX_PATH) { + filename = buffer; + } + } + + // 将宽字符串转换为窄字符串,用于日志和内部存储 + std::string ansiFilename(filename.begin(), filename.end()); + + // 创建文件句柄信息 + auto fileHandleInfo = new FileHandleInfo(); + fileHandleInfo->path = ansiFilename; + fileHandleInfo->currentPosition = 0; + fileHandleInfo->isValid = true; + + // 读取实际文件内容(如果存在) + std::ifstream file(ansiFilename, std::ios::binary | std::ios::ate); + if (file.is_open()) { + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + + fileHandleInfo->content.resize(size); + if (size > 0) { + file.read(fileHandleInfo->content.data(), size); + } + file.close(); + } else { + // 文件不存在或无法打开 + if (dwCreationDisposition == CREATE_NEW || + dwCreationDisposition == CREATE_ALWAYS || + dwCreationDisposition == OPEN_ALWAYS) { + // 创建空文件 + fileHandleInfo->content.clear(); + } else { + // 返回无效句柄 + delete fileHandleInfo; + uint64_t invalidHandle = (uint64_t)INVALID_HANDLE_VALUE; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &invalidHandle); + + // 设置错误码 + DWORD error = ERROR_FILE_NOT_FOUND; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + return; + } + } + + // 生成唯一的文件句柄 + uint64_t fileHandle = context->GenerateFileHandle(); + fileHandleInfo->handle = fileHandle; + + // 添加到文件句柄表 + context->m_fileHandles[fileHandle] = fileHandleInfo; + + printf("[*] CreateFileW: File=%ls, Access=0x%x, Share=0x%x, Create=0x%x, Handle=0x%llx\n", + filename.c_str(), dwDesiredAccess, dwShareMode, dwCreationDisposition, fileHandle); + + // 返回文件句柄 + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &fileHandle); +} + +// ReadFileA API实现 +auto Api_ReadFileA(void* sandbox, uc_engine* uc, uint64_t address) -> void { + Api_ReadFile(sandbox, uc, address, false); +} + +// ReadFileW API实现 +auto Api_ReadFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void { + Api_ReadFile(sandbox, uc, address, true); +} + +// 统一的ReadFile实现 +auto Api_ReadFile(void* sandbox, uc_engine* uc, uint64_t address, bool isWideChar) -> void { + auto context = static_cast(sandbox); + uint64_t hFile = 0; + uint64_t lpBuffer = 0; + uint32_t nNumberOfBytesToRead = 0; + uint64_t lpNumberOfBytesRead = 0; + uint64_t lpOverlapped = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = hFile, rdx = lpBuffer, r8 = nNumberOfBytesToRead, r9 = lpNumberOfBytesRead + uc_reg_read(uc, UC_X86_REG_RCX, &hFile); + uc_reg_read(uc, UC_X86_REG_RDX, &lpBuffer); + uint64_t temp_bytes_to_read; + uc_reg_read(uc, UC_X86_REG_R8, &temp_bytes_to_read); + nNumberOfBytesToRead = static_cast(temp_bytes_to_read); + uc_reg_read(uc, UC_X86_REG_R9, &lpNumberOfBytesRead); + + // 从栈上读取lpOverlapped参数 + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uc_mem_read(uc, rsp + 0x28, &lpOverlapped, sizeof(uint64_t)); + } else { + // x86: 从栈上读取参数 + uint32_t esp; + uc_reg_read(uc, UC_X86_REG_ESP, &esp); + esp += 0x4; // 跳过返回地址 + + uint32_t temp_handle, temp_buffer, temp_bytes_read, temp_overlapped; + uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t)); + uc_mem_read(uc, esp + 0x4, &temp_buffer, sizeof(uint32_t)); + uc_mem_read(uc, esp + 0x8, &nNumberOfBytesToRead, sizeof(uint32_t)); + uc_mem_read(uc, esp + 0xC, &temp_bytes_read, sizeof(uint32_t)); + uc_mem_read(uc, esp + 0x10, &temp_overlapped, sizeof(uint32_t)); + + hFile = temp_handle; + lpBuffer = temp_buffer; + lpNumberOfBytesRead = temp_bytes_read; + lpOverlapped = temp_overlapped; + } + + // 从文件句柄表中查找句柄信息 + auto fileInfo = context->GetFileHandleInfo(hFile); + bool success = false; + uint32_t bytesRead = 0; + + if (fileInfo && fileInfo->isValid) { + // 计算实际可读取的字节数 + size_t availableBytes = fileInfo->content.size() - fileInfo->currentPosition; + bytesRead = (nNumberOfBytesToRead < availableBytes) ? nNumberOfBytesToRead : (uint32_t)availableBytes; + + if (bytesRead > 0) { + // 读取数据 + uc_mem_write(uc, lpBuffer, + fileInfo->content.data() + fileInfo->currentPosition, + bytesRead); + + // 更新当前位置 + fileInfo->currentPosition += bytesRead; + success = true; + } else { + // 没有更多数据可读 + success = true; // 返回TRUE,但是bytesRead为0 + } + } else { + // 设置错误码 + DWORD error = ERROR_INVALID_HANDLE; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + } + + // 写入实际读取的字节数 + if (lpNumberOfBytesRead != 0) { + uc_mem_write(uc, lpNumberOfBytesRead, &bytesRead, sizeof(uint32_t)); + } + + // 设置返回值 + uint64_t result = success ? TRUE : FALSE; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + + const char* apiName = isWideChar ? "ReadFileW" : "ReadFileA"; + printf("[*] %s: Handle=0x%llx, Buffer=0x%llx, BytesToRead=%u, BytesRead=%u, Result=%s\n", + apiName, hFile, lpBuffer, nNumberOfBytesToRead, bytesRead, + success ? "TRUE" : "FALSE"); +} + +// CloseFile API实现 +auto Api_CloseFile(void* sandbox, uc_engine* uc, uint64_t address) -> void { + auto context = static_cast(sandbox); + uint64_t hFile = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + uc_reg_read(uc, UC_X86_REG_RCX, &hFile); + } else { + uint32_t esp; + uc_reg_read(uc, UC_X86_REG_ESP, &esp); + esp += 0x4; // 跳过返回地址 + uint32_t temp_handle; + uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t)); + hFile = temp_handle; + } + + // 在文件句柄表中查找并释放资源 + auto it = context->m_fileHandles.find(hFile); + bool success = false; + + if (it != context->m_fileHandles.end() && it->second) { + delete it->second; + context->m_fileHandles.erase(it); + success = true; + } + + // 设置返回值 + uint64_t result = success ? TRUE : FALSE; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + + printf("[*] CloseFile: Handle=0x%llx, Result=%s\n", + hFile, success ? "TRUE" : "FALSE"); +} \ No newline at end of file diff --git a/ai_anti_malware/sandbox_api_stl.cpp b/ai_anti_malware/sandbox_api_stl.cpp index 9aa34ac..4810ee9 100644 --- a/ai_anti_malware/sandbox_api_stl.cpp +++ b/ai_anti_malware/sandbox_api_stl.cpp @@ -2531,3 +2531,591 @@ auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void { context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &return_value); } + +auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address) +-> void { + auto context = static_cast(sandbox); + uint64_t lpPathName = 0; + uint64_t lpSecurityAttributes = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = lpPathName, rdx = lpSecurityAttributes + uc_reg_read(uc, UC_X86_REG_RCX, &lpPathName); + uc_reg_read(uc, UC_X86_REG_RDX, &lpSecurityAttributes); + } + else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + + uint32_t temp_path_name, temp_security_attr; + uc_mem_read(uc, esp_address, &temp_path_name, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &temp_security_attr, + sizeof(uint32_t)); + + lpPathName = temp_path_name; + lpSecurityAttributes = temp_security_attr; + } + + // 读取目录路径 + wchar_t pathBuffer[MAX_PATH] = { 0 }; + if (lpPathName != 0) { + size_t i = 0; + do { + uint16_t wchar; + uc_mem_read(uc, lpPathName + (i * 2), &wchar, 2); + pathBuffer[i] = wchar; + i++; + } while (pathBuffer[i - 1] != 0 && i < MAX_PATH); + } + + // 将宽字符转换为常规字符串用于日志输出 + std::wstring widePath(pathBuffer); + std::string path(widePath.begin(), widePath.end()); + + // 在实际的实现中,可能需要检查目录是否已存在 + // 这里简单地返回成功,不实际创建目录 + bool success = true; + + // 输出日志 + printf("[*] CreateDirectoryW: Path=%s, Result=%s\n", path.c_str(), + success ? "TRUE" : "FALSE"); + + // 设置返回值 + uint64_t result = success ? 1 : 0; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + + // 如果失败,可以设置LastError + if (!success) { + DWORD error = ERROR_PATH_NOT_FOUND; // 或其他适当的错误代码 + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } + else { + context->GetTeb32()->LastErrorValue = error; + } + } +} +auto Api_GetStringTypeW(void* sandbox, uc_engine* uc, uint64_t address) +-> void { + auto context = static_cast(sandbox); + uint64_t dwInfoType = 0; + uint64_t lpSrcStr = 0; + int32_t cchSrc = 0; + uint64_t lpCharType = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = dwInfoType, rdx = lpSrcStr, r8 = cchSrc, r9 = lpCharType + uc_reg_read(uc, UC_X86_REG_RCX, &dwInfoType); + uc_reg_read(uc, UC_X86_REG_RDX, &lpSrcStr); + uint64_t temp_size; + uc_reg_read(uc, UC_X86_REG_R8, &temp_size); + cchSrc = static_cast(temp_size); + uc_reg_read(uc, UC_X86_REG_R9, &lpCharType); + } + 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, &dwInfoType, sizeof(uint32_t)); + esp_address += 0x4; + + uint32_t temp_src_str; + uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t)); + lpSrcStr = temp_src_str; + esp_address += 0x4; + + uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t)); + esp_address += 0x4; + + uint32_t temp_char_type; + uc_mem_read(uc, esp_address, &temp_char_type, sizeof(uint32_t)); + lpCharType = temp_char_type; + } + + // 验证参数 + if (lpSrcStr == 0 || lpCharType == 0) { + uint64_t result = 0; // FALSE + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } + else { + context->GetTeb32()->LastErrorValue = error; + } + return; + } + + // 如果cchSrc为负数,计算字符串长度 + if (cchSrc < 0) { + cchSrc = 0; + wchar_t temp_char; + do { + uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char, + sizeof(wchar_t)); + cchSrc++; + } while (temp_char != 0 && cchSrc < 1024); // 设置一个合理的上限 + cchSrc--; // 不包括null终止符 + } + + // 读取源字符串 + std::vector srcStr(cchSrc); + uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t)); + + // 处理每个字符 + std::vector charTypes(cchSrc); + for (int i = 0; i < cchSrc; i++) { + WORD type = 0; + wchar_t ch = srcStr[i]; + + switch (dwInfoType) { + case CT_CTYPE1: { + // 基本字符类型检查 + if (iswupper(ch)) type |= C1_UPPER; + if (iswlower(ch)) type |= C1_LOWER; + if (iswdigit(ch)) type |= C1_DIGIT; + if (iswspace(ch)) type |= C1_SPACE; + if (iswpunct(ch)) type |= C1_PUNCT; + if (iswcntrl(ch)) type |= C1_CNTRL; + if (ch == L' ' || ch == L'\t') type |= C1_BLANK; + if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'F') || + (ch >= L'a' && ch <= L'f')) + type |= C1_XDIGIT; + if (iswalpha(ch)) type |= C1_ALPHA; + if (type == 0) type |= C1_DEFINED; + break; + } + case CT_CTYPE2: { + // 简单的双向文本支持 + if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z') || + (ch >= L'0' && ch <= L'9')) { + type = C2_LEFTTORIGHT; + } + else if (iswspace(ch)) { + type = C2_WHITESPACE; + } + else { + type = C2_NOTAPPLICABLE; + } + break; + } + case CT_CTYPE3: { + // 基本文本处理信息 + if (iswalpha(ch)) type |= C3_ALPHA; + // 这里可以添加更多的C3类型检查 + break; + } + } + charTypes[i] = type; + } + + // 写入结果 + uc_mem_write(uc, lpCharType, charTypes.data(), cchSrc * sizeof(WORD)); + + printf("[*] GetStringTypeW: InfoType=0x%x, StrLen=%d\n", dwInfoType, + cchSrc); + + // 返回成功 + uint64_t result = 1; // TRUE + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} + +auto Api_LCMapStringW(void* sandbox, uc_engine* uc, uint64_t address) -> void { + auto context = static_cast(sandbox); + uint32_t Locale = 0; + uint32_t dwMapFlags = 0; + uint64_t lpSrcStr = 0; + int32_t cchSrc = 0; + uint64_t lpDestStr = 0; + int32_t cchDest = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = Locale, rdx = dwMapFlags, r8 = lpSrcStr, r9 = cchSrc + uc_reg_read(uc, UC_X86_REG_RCX, &Locale); + uc_reg_read(uc, UC_X86_REG_RDX, &dwMapFlags); + uc_reg_read(uc, UC_X86_REG_R8, &lpSrcStr); + uint64_t temp_src_size; + uc_reg_read(uc, UC_X86_REG_R9, &temp_src_size); + cchSrc = static_cast(temp_src_size); + + // 从栈上读取剩余参数 + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uc_mem_read(uc, rsp + 0x28, &lpDestStr, sizeof(uint64_t)); + uc_mem_read(uc, rsp + 0x30, &cchDest, 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, &Locale, sizeof(uint32_t)); + esp_address += 0x4; + + uc_mem_read(uc, esp_address, &dwMapFlags, sizeof(uint32_t)); + esp_address += 0x4; + + uint32_t temp_src_str; + uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t)); + lpSrcStr = temp_src_str; + esp_address += 0x4; + + uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t)); + esp_address += 0x4; + + uint32_t temp_dest_str; + uc_mem_read(uc, esp_address, &temp_dest_str, sizeof(uint32_t)); + lpDestStr = temp_dest_str; + esp_address += 0x4; + + uc_mem_read(uc, esp_address, &cchDest, sizeof(int32_t)); + } + + // 验证参数 + if (lpSrcStr == 0) { + uint32_t result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } + else { + context->GetTeb32()->LastErrorValue = error; + } + return; + } + + // 如果cchSrc为负数,计算源字符串长度 + if (cchSrc < 0) { + cchSrc = 0; + wchar_t temp_char; + do { + uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char, + sizeof(wchar_t)); + cchSrc++; + } while (temp_char != 0 && cchSrc < 1024); // 设置一个合理的上限 + cchSrc--; // 不包括null终止符 + } + + // 读取源字符串 + std::vector srcStr(cchSrc); + uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t)); + + // 如果cchDest为0,返回所需缓冲区大小 + if (cchDest == 0) { + uint32_t required_size = cchSrc; + if (dwMapFlags & LCMAP_SORTKEY) { + required_size = cchSrc * 2 + 1; // 排序键通常需要更多空间 + } + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &required_size); + return; + } + + // 检查目标缓冲区大小是否足够 + if (cchDest < cchSrc) { + uint32_t result = 0; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } + else { + context->GetTeb32()->LastErrorValue = error; + } + return; + } + + // 处理字符串映射 + std::vector destStr(cchSrc); + for (int i = 0; i < cchSrc; i++) { + wchar_t ch = srcStr[i]; + if (dwMapFlags & LCMAP_UPPERCASE) { + destStr[i] = towupper(ch); + } + else if (dwMapFlags & LCMAP_LOWERCASE) { + destStr[i] = towlower(ch); + } + else { + destStr[i] = ch; // 默认保持不变 + } + } + + // 写入结果 + if (dwMapFlags & LCMAP_SORTKEY) { + // 生成简单的排序键(这里只是一个基本实现) + std::vector sortKey(cchSrc * 2 + 1); + for (int i = 0; i < cchSrc; i++) { + sortKey[i * 2] = static_cast(destStr[i] & 0xFF); + sortKey[i * 2 + 1] = static_cast((destStr[i] >> 8) & 0xFF); + } + sortKey[cchSrc * 2] = 0; // 终止符 + uc_mem_write(uc, lpDestStr, sortKey.data(), sortKey.size()); + uint32_t result = static_cast(sortKey.size()); + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + } + else { + // 写入映射后的字符串 + uc_mem_write(uc, lpDestStr, destStr.data(), cchSrc * sizeof(wchar_t)); + uint32_t result = cchSrc; + uc_reg_write( + uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + } + + printf( + "[*] LCMapStringW: Locale=0x%x, MapFlags=0x%x, SrcLen=%d, DestLen=%d\n", + Locale, dwMapFlags, cchSrc, cchDest); +} + +// 实现 LCMapStringEx API +auto Api_LCMapStringEx(void* sandbox, uc_engine* uc, uint64_t address) -> void { + auto context = static_cast(sandbox); + uint64_t lpLocaleName = 0; + uint64_t dwMapFlags = 0; + uint64_t lpSrcStr = 0; + uint64_t cchSrc = 0; + uint64_t lpDestStr = 0; + uint64_t cchDest = 0; + uint64_t lpVersionInformation = 0; // 通常为 NULL + uint64_t lpReserved = 0; // 必须为 NULL + uint64_t sortHandle = 0; // 必须为 0 + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = lpLocaleName, rdx = dwMapFlags, r8 = lpSrcStr, r9 = cchSrc + uc_reg_read(uc, UC_X86_REG_RCX, &lpLocaleName); + uc_reg_read(uc, UC_X86_REG_RDX, &dwMapFlags); + uc_reg_read(uc, UC_X86_REG_R8, &lpSrcStr); + uint64_t temp_src_size; + uc_reg_read(uc, UC_X86_REG_R9, &temp_src_size); + cchSrc = static_cast(temp_src_size); + + // 从栈上读取剩余参数 (参数 5 到 9) + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + // 参数从 rsp + 0x28 开始 (跳过4个寄存器参数的shadow space + 返回地址) + uc_mem_read(uc, rsp + 0x28, &lpDestStr, sizeof(uint64_t)); + uc_mem_read(uc, rsp + 0x30, &cchDest, sizeof(int32_t)); + // 注意:参数在栈上的偏移量可能需要根据调用约定微调 + uc_mem_read(uc, rsp + 0x38, &lpVersionInformation, sizeof(uint64_t)); + uc_mem_read(uc, rsp + 0x40, &lpReserved, sizeof(uint64_t)); + uc_mem_read(uc, rsp + 0x48, &sortHandle, sizeof(uint64_t)); + + } + else { + // x86: 从栈上读取所有参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + + uint32_t temp_locale_name, temp_src_str, temp_dest_str, temp_version_info, temp_reserved, temp_sort_handle; + + uc_mem_read(uc, esp_address, &temp_locale_name, sizeof(uint32_t)); lpLocaleName = temp_locale_name; esp_address += 0x4; + uc_mem_read(uc, esp_address, &dwMapFlags, sizeof(uint32_t)); esp_address += 0x4; + uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t)); lpSrcStr = temp_src_str; esp_address += 0x4; + uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t)); esp_address += 0x4; + uc_mem_read(uc, esp_address, &temp_dest_str, sizeof(uint32_t)); lpDestStr = temp_dest_str; esp_address += 0x4; + uc_mem_read(uc, esp_address, &cchDest, sizeof(int32_t)); esp_address += 0x4; + uc_mem_read(uc, esp_address, &temp_version_info, sizeof(uint32_t)); lpVersionInformation = temp_version_info; esp_address += 0x4; + uc_mem_read(uc, esp_address, &temp_reserved, sizeof(uint32_t)); lpReserved = temp_reserved; esp_address += 0x4; + uc_mem_read(uc, esp_address, &temp_sort_handle, sizeof(uint32_t)); sortHandle = temp_sort_handle; esp_address += 0x4; + } + + // 读取区域设置名称(可选,模拟中可能忽略) + std::wstring localeNameStr; + if (lpLocaleName != 0) { + wchar_t buffer[LOCALE_NAME_MAX_LENGTH] = { 0 }; + size_t i = 0; + do { + uint16_t wchar; + if (uc_mem_read(uc, lpLocaleName + (i * 2), &wchar, 2) != UC_ERR_OK) break; + buffer[i] = wchar; + i++; + } while (buffer[i - 1] != 0 && i < LOCALE_NAME_MAX_LENGTH); + localeNameStr = buffer; + } + + + // 验证参数 (与 LCMapStringW 类似) + if (lpSrcStr == 0 || lpReserved != 0 || sortHandle != 0) { // 添加了对 lpReserved 和 sortHandle 的检查 + uint32_t result = 0; + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } + else { + context->GetTeb32()->LastErrorValue = error; + } + printf("[*] LCMapStringEx: Invalid parameter (lpSrcStr=0x%llx, lpReserved=0x%llx, sortHandle=0x%llx)\\n", lpSrcStr, lpReserved, sortHandle); + return; + } + + // 如果cchSrc为负数,计算源字符串长度 (与 LCMapStringW 相同) + if (cchSrc < 0) { + cchSrc = 0; + wchar_t temp_char; + do { + if (uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char, sizeof(wchar_t)) != UC_ERR_OK) { + // 内存读取错误处理 + uint32_t result = 0; + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); + DWORD error = ERROR_INVALID_PARAMETER; // 或者更具体的错误 + if (context->GetPeInfo()->isX64) context->GetTeb64()->LastErrorValue = error; + else context->GetTeb32()->LastErrorValue = error; + printf("[*] LCMapStringEx: Error reading source string length at 0x%llx\\n", lpSrcStr + (cchSrc * 2)); + return; + } + cchSrc++; + } while (temp_char != 0 && cchSrc < 4096); // 增加合理上限防止死循环 + if (cchSrc >= 4096) { + // 字符串过长或未找到终止符 + uint32_t result = 0; + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); + DWORD error = ERROR_INVALID_PARAMETER; + if (context->GetPeInfo()->isX64) context->GetTeb64()->LastErrorValue = error; + else context->GetTeb32()->LastErrorValue = error; + printf("[*] LCMapStringEx: Source string too long or unterminated at 0x%llx\\n", lpSrcStr); + return; + } + cchSrc--; // 不包括null终止符 + } + + + // 读取源字符串 (与 LCMapStringW 相同) + std::vector srcStr(cchSrc + 1, 0); // 分配足够空间并初始化为0 + if (cchSrc > 0) { + if (uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t)) != UC_ERR_OK) { + // 内存读取错误处理 + uint32_t result = 0; + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); + DWORD error = ERROR_INVALID_PARAMETER; // 或者更具体的错误 + if (context->GetPeInfo()->isX64) context->GetTeb64()->LastErrorValue = error; + else context->GetTeb32()->LastErrorValue = error; + printf("[*] LCMapStringEx: Error reading source string data from 0x%llx\\n", lpSrcStr); + return; + } + } + + + uint32_t required_size = cchSrc; // 默认需要的大小与源长度相同 + bool needs_null_terminator = false; // 是否需要在目标缓冲区添加空终止符 + + // 根据 dwMapFlags 确定是否需要空终止符以及调整所需大小 + if (!(dwMapFlags & LCMAP_BYTEREV) && !(dwMapFlags & LCMAP_SORTKEY)) { + required_size++; // 需要为 null 终止符增加空间 + needs_null_terminator = true; + } + if (dwMapFlags & LCMAP_SORTKEY) { + required_size = cchSrc * 2 + 1; // 排序键通常需要更多空间,包含终止符 + needs_null_terminator = true; // Sortkey is null-terminated byte array + } + + + // 如果cchDest为0,返回所需缓冲区大小 (与 LCMapStringW 类似,但考虑了 null 终止符) + if (cchDest == 0) { + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &required_size); + printf("[*] LCMapStringEx: Querying buffer size. Required: %u\\n", required_size); + return; + } + + // 检查目标缓冲区大小是否足够 + if (cchDest < required_size) { + uint32_t result = 0; + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); + DWORD error = ERROR_INSUFFICIENT_BUFFER; + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } + else { + context->GetTeb32()->LastErrorValue = error; + } + printf("[*] LCMapStringEx: Insufficient buffer. Provided: %d, Required: %u\\n", cchDest, required_size); + return; + } + + // 处理字符串映射 (与 LCMapStringW 类似) + std::vector destStr(cchSrc); + for (int i = 0; i < cchSrc; i++) { + wchar_t ch = srcStr[i]; + if (dwMapFlags & LCMAP_UPPERCASE) { + destStr[i] = towupper(ch); + } + else if (dwMapFlags & LCMAP_LOWERCASE) { + destStr[i] = towlower(ch); + } + else { + destStr[i] = ch; // 默认保持不变 + } + // TODO: 处理其他 dwMapFlags,如 LCMAP_HALFWIDTH, LCMAP_FULLWIDTH, LCMAP_HIRAGANA, LCMAP_KATAKANA, LCMAP_LINGUISTIC_CASING 等 + // 这些需要更复杂的实现,可能需要 NLS 功能库或 ICU + } + + + // 写入结果 + uint32_t written_size = 0; + uc_err write_err = UC_ERR_OK; + + if (dwMapFlags & LCMAP_SORTKEY) { + // 生成简单的排序键(这里只是一个基本实现) (与 LCMapStringW 相同) + std::vector sortKey(required_size); // 使用 required_size + for (int i = 0; i < cchSrc; i++) { + // 简单地将 wchar_t 分解为两个字节 + sortKey[i * 2] = static_cast(destStr[i] & 0xFF); + sortKey[i * 2 + 1] = static_cast((destStr[i] >> 8) & 0xFF); + } + sortKey[cchSrc * 2] = 0; // 终止符 + write_err = uc_mem_write(uc, lpDestStr, sortKey.data(), required_size); + written_size = required_size; + } + else { + // 写入映射后的字符串 + write_err = uc_mem_write(uc, lpDestStr, destStr.data(), cchSrc * sizeof(wchar_t)); + if (write_err == UC_ERR_OK && needs_null_terminator) { + // 写入 null 终止符 + wchar_t null_term = 0; + write_err = uc_mem_write(uc, lpDestStr + (cchSrc * sizeof(wchar_t)), &null_term, sizeof(wchar_t)); + } + written_size = needs_null_terminator ? (cchSrc + 1) : cchSrc; + } + + + if (write_err != UC_ERR_OK) { + // 写入错误处理 + uint32_t result = 0; + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); + DWORD error = ERROR_INVALID_PARAMETER; // 或者更具体的内存写入错误码 + if (context->GetPeInfo()->isX64) context->GetTeb64()->LastErrorValue = error; + else context->GetTeb32()->LastErrorValue = error; + printf("[*] LCMapStringEx: Error writing to destination buffer at 0x%llx. Error: %u\\n", lpDestStr, write_err); + return; + } + + // 设置返回值 (写入的字符数或字节数,取决于 flags) + uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &written_size); + + printf("[*] LCMapStringEx: Locale=%ls, MapFlags=0x%x, SrcLen=%d, DestLen=%d, Result=%u\\n", + localeNameStr.empty() ? L"(null)" : localeNameStr.c_str(), dwMapFlags, cchSrc, cchDest, written_size); +} \ No newline at end of file