diff --git a/ai_anti_malware/native_struct.h b/ai_anti_malware/native_struct.h index 0a323f9..3c37f06 100644 --- a/ai_anti_malware/native_struct.h +++ b/ai_anti_malware/native_struct.h @@ -1007,6 +1007,8 @@ struct moudle_export { uint64_t function_address; void* function_callback; uint64_t ordinal; + uc_hook sys_ook; + }; struct moudle_import { char name[MAX_PATH]; diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index 19cfbab..ff05030 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -548,7 +548,10 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { } mapSystemModuleToVmByName("kernelbase.dll"); } + // 闭合ldr + FinalizeLdrLinks(); // 给所有导入表加c3 + /* for (const auto& module : this->GetModuleList()) { // 遍历导出函数查找对应名称 for (const auto& exp : module->export_function) { @@ -556,6 +559,15 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { uc_mem_write(m_ucEngine, inMemAddr, "\xCC", sizeof(char)); } } + */ + // 挂导入表钩子 + for (const auto& module : this->GetModuleList()) { + // 遍历导出函数查找对应名称 + for (const auto& exp : module->export_function) { + auto inMemAddr = module->base + exp->function_address; + uc_hook_add(m_ucEngine, &exp->sys_ook, UC_HOOK_CODE, sandboxCallbacks::handleApiCall,(void*)this, inMemAddr, inMemAddr + 5, 0); + } + } uc_err ucErr = uc_mem_map(m_ucEngine, m_peInfo->RecImageBase, m_peInfo->peSize, UC_PROT_ALL); if (ucErr != UC_ERR_OK) { @@ -682,7 +694,6 @@ auto Sandbox::Run(uint64_t address) -> void { // 为参数腾出空间 rsp -= 3 * 4; // 三个参数:hinstDLL, fdwReason, lpvReserved uc_reg_write(m_ucEngine, UC_X86_REG_ESP, &rsp); - // 按照从右到左的顺序压栈 uint32_t lpvReserved = 0; // 第三个参数为NULL uint32_t reason = dll_fdwReason; // DLL_PROCESS_ATTACH @@ -704,6 +715,7 @@ auto Sandbox::Run(uint64_t address) -> void { } } err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, timeout, 0); + // 2. 有自定义地址 再跑自定义地址 std::cerr << "Entry Point Emulation error: " << uc_strerror(err) << std::endl; diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 3e2e133..9f82c90 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -247,6 +247,8 @@ class Sandbox { } auto TestLdrListTraversal() -> bool; + auto FinalizeLdrLinks() -> void; + // 注册COM相关API void RegisterComApis(); @@ -338,6 +340,8 @@ class Sandbox { auto AddModuleToLdr(const std::shared_ptr& module) -> void; + auto CloseLdrList(uint64_t listHeadAddr, size_t entryLinkOffset) -> void; + auto DumpLdrList(const char* listName, uint64_t ldrDataBase, size_t listOffset, size_t entryLinkOffset) -> void; // 创建LDR_DATA_TABLE_ENTRY结构 diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index f05b8b5..eb36323 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -66,140 +66,142 @@ auto Api_GetCurrentThread(void* sandbox, uc_engine* uc, uint64_t address) printf("[*] GetCurrentThread called, returning pseudo-handle 0x%llx\n", pseudo_handle); } -auto Api_LoadLibraryA(void* sandbox, uc_engine* uc, uint64_t address) -> void { - auto context = static_cast(sandbox); - uint64_t params_address = 0; - - // 获取参数地址 - if (context->GetPeInfo()->isX64) { - uc_reg_read(uc, UC_X86_REG_RCX, ¶ms_address); - } else { - uint64_t ebp_address = 0; - uc_reg_read(uc, UC_X86_REG_ESP, &ebp_address); - ebp_address += 0x4; - uc_mem_read(uc, ebp_address, ¶ms_address, 0x4); - } - - uint64_t return_address = 0; - std::string module_name; - char buffer[MAX_PATH]; - size_t i = 0; - - // 读取模块名称 - if (params_address != 0) { - do { - uint8_t byte; - uc_mem_read(uc, params_address + i, &byte, 1); - buffer[i] = byte; - i++; - } while (buffer[i - 1] != 0 && i < MAX_PATH); - - if (i > 0 && i < MAX_PATH) { - module_name = std::string(buffer); - // 确保模块名以.dll结尾(不区分大小写) - if (module_name.length() > 4) { - std::string ext = module_name.substr(module_name.length() - 4); - if (_stricmp(ext.c_str(), ".dll") != 0) { - module_name += ".dll"; - } - } else { - module_name += ".dll"; - } - std::string fuck_up_api_ms = module_name; - if (fuck_up_api_ms.find("api-ms-") != std::string::npos) { - module_name = getDllNameFromApiSetMap(fuck_up_api_ms); - if (module_name.size() <= 1) __debugbreak(); - } - - // 从模块列表中查找对应模块 - for (const auto& module : context->GetModuleList()) { - if ((*module).name == module_name.c_str()) { - return_address = (*module).base; - break; - } - } - } - } - - printf("[*] LoadLibraryA: Module=%s, Base=0x%llx\n", module_name.c_str(), - return_address); - uc_reg_write(uc, - context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &return_address); -} -auto Api_LoadLibraryExW(void* sandbox, uc_engine* uc, uint64_t address) - -> void { +// 统一的LoadLibrary辅助函数 +auto LoadLibraryHelper(void* sandbox, uc_engine* uc, uint64_t address, + bool isWideChar, bool isEx = false) -> void { auto context = static_cast(sandbox); uint64_t module_name_address = 0; uint64_t flags = 0; // 获取参数 if (context->GetPeInfo()->isX64) { - // x64: rcx = lpLibFileName, r8 = dwFlags uc_reg_read(uc, UC_X86_REG_RCX, &module_name_address); - uc_reg_read(uc, UC_X86_REG_R8, &flags); - } else { - // x86: 从栈上读取参数 + if (isEx) { + uc_reg_read(uc, UC_X86_REG_R8, &flags); + } + } + else { uint64_t esp_address = 0; uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); esp_address += 0x4; // 跳过返回地址 uc_mem_read(uc, esp_address, &module_name_address, 0x4); - esp_address += 0x8; // 跳过hFile参数 - uc_mem_read(uc, esp_address, &flags, 0x4); + + if (isEx) { + esp_address += 0x8; // 跳过hFile参数 + uc_mem_read(uc, esp_address, &flags, 0x4); + } } uint64_t return_address = 0; - std::wstring module_name; - wchar_t buffer[MAX_PATH]; - size_t i = 0; + std::string ansi_name; + bool isApiSetMapMeme = false; - // 读取宽字符模块名称 + + // 读取模块名称 if (module_name_address != 0) { - do { - uint16_t wchar; - uc_mem_read(uc, module_name_address + (i * 2), &wchar, 2); - buffer[i] = wchar; - i++; - } while (buffer[i - 1] != 0 && i < MAX_PATH); + if (isWideChar) { + // 读取宽字符串 + std::wstring module_name; + wchar_t buffer[MAX_PATH]; + size_t i = 0; - if (i > 0 && i < MAX_PATH) { - module_name = std::wstring(buffer); - std::string ansi_name(module_name.begin(), module_name.end()); + do { + uint16_t wchar; + uc_mem_read(uc, module_name_address + (i * 2), &wchar, 2); + buffer[i] = wchar; + i++; + } while (buffer[i - 1] != 0 && i < MAX_PATH); - std::string fuck_up_api_ms = ansi_name; - if (ansi_name.length() > 4) { - std::string ext = ansi_name.substr(ansi_name.length() - 4); - if (_stricmp(ext.c_str(), ".dll") != 0) { - ansi_name += ".dll"; - } - } else { + if (i > 0 && i < MAX_PATH) { + module_name = std::wstring(buffer); + ansi_name = std::string(module_name.begin(), module_name.end()); + } + } + else { + // 读取ASCII字符串 + char buffer[MAX_PATH]; + size_t i = 0; + + do { + uint8_t byte; + uc_mem_read(uc, module_name_address + i, &byte, 1); + buffer[i] = byte; + i++; + } while (buffer[i - 1] != 0 && i < MAX_PATH); + + if (i > 0 && i < MAX_PATH) { + ansi_name = std::string(buffer); + } + } + + // 确保模块名以.dll结尾 + if (ansi_name.length() > 4) { + std::string ext = ansi_name.substr(ansi_name.length() - 4); + if (_stricmp(ext.c_str(), ".dll") != 0) { ansi_name += ".dll"; } - if (ansi_name.find("api-ms-") != std::string::npos) { - ansi_name = getDllNameFromApiSetMap(ansi_name); - isApiSetMapMeme = true; - // if (ansi_name.size() <= 1) __debugbreak(); - } + } + else { + ansi_name += ".dll"; + } - // 从模块列表中查找对应模块 - for (const auto& module : context->GetModuleList()) { - if ((*module).name == ansi_name.c_str()) { - return_address = (*module).base; - break; - } + // 处理api-ms-前缀 + if (ansi_name.find("api-ms-") != std::string::npos) { + ansi_name = getDllNameFromApiSetMap(ansi_name); + isApiSetMapMeme = true; + if (!isEx && ansi_name.size() <= 1) __debugbreak(); + } + + // 从模块列表中查找对应模块 + for (const auto& module : context->GetModuleList()) { + if ((*module).name == ansi_name.c_str()) { + return_address = (*module).base; + break; } } } - printf("[*] LoadLibraryExW: Module=%ls, Flags=0x%llx, Base=0x%llx\n", - module_name.c_str(), flags, return_address); - if (return_address == 0 && isApiSetMapMeme) { + // 根据调用的函数输出日志 + if (isEx) { + printf("[*] LoadLibraryExW: Module=%s, Flags=0x%llx, Base=0x%llx\n", + ansi_name.c_str(), flags, return_address); + } + else { + if (isWideChar) { + printf("[*] LoadLibraryW: Module=%s, Base=0x%llx\n", + ansi_name.c_str(), return_address); + } + else { + printf("[*] LoadLibraryA: Module=%s, Base=0x%llx\n", + ansi_name.c_str(), return_address); + } + } + + // 处理API set映射失败的特殊情况 + if (return_address == 0 && isApiSetMapMeme && isEx) { // 找不到就不管他了,操 return_address = 0x1337; } + + // 设置返回值 uc_reg_write(uc, - context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, - &return_address); + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &return_address); +} + +// LoadLibraryA函数包装器 +auto Api_LoadLibraryA(void* sandbox, uc_engine* uc, uint64_t address) -> void { + LoadLibraryHelper(sandbox, uc, address, false); +} + +// 新增的LoadLibraryW函数包装器 +auto Api_LoadLibraryW(void* sandbox, uc_engine* uc, uint64_t address) -> void { + LoadLibraryHelper(sandbox, uc, address, true); +} + +// LoadLibraryExW函数包装器 +auto Api_LoadLibraryExW(void* sandbox, uc_engine* uc, uint64_t address) -> void { + LoadLibraryHelper(sandbox, uc, address, true, true); } auto Api_GetProcAddress(void* sandbox, uc_engine* uc, uint64_t address) -> void { @@ -1376,7 +1378,9 @@ auto Sandbox::InitApiHooks() -> void { _fakeApi{.func = Api_VariantClear, .paramCount = 1}; auto FakeApi_SysAllocString = _fakeApi{.func = Api_SysAllocString, .paramCount = 1}; - + auto FakeApi_LoadLibraryW = + _fakeApi{ .func = Api_LoadLibraryW, .paramCount = 1 }; + api_map = { {"GetSystemTimeAsFileTime", std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)}, @@ -1519,6 +1523,7 @@ auto Sandbox::InitApiHooks() -> void { {"VariantInit", std::make_shared<_fakeApi>(FakeApi_VariantInit)}, {"VariantClear", std::make_shared<_fakeApi>(FakeApi_VariantClear)}, {"SysAllocString", std::make_shared<_fakeApi>(FakeApi_SysAllocString)}, + {"LoadLibraryW", std::make_shared<_fakeApi>(FakeApi_LoadLibraryW)}, }; } auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, diff --git a/ai_anti_malware/sandbox_callbacks.cpp b/ai_anti_malware/sandbox_callbacks.cpp index 421f68a..eecf736 100644 --- a/ai_anti_malware/sandbox_callbacks.cpp +++ b/ai_anti_malware/sandbox_callbacks.cpp @@ -1,11 +1,30 @@ #include "sandbox_callbacks.h" +// 通用模板函数实现绝对值 +template +inline T duck_abs(T value) { + // 针对有符号类型 + if constexpr (std::is_signed::value) { + return value < 0 ? -value : value; + } + // 无符号类型直接返回 + else { + return value; + } +} + +// 或者使用这个更简单的实现 +inline uint64_t duck_abs(int64_t a, int64_t b) { + uint64_t diff = (a > b) ? (uint64_t)(a - b) : (uint64_t)(b - a); + return diff; +} + namespace sandboxCallbacks { +static uint64_t lastRip = 0; void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, void* userData) { uint64_t currentRip = 0; uint64_t currentRsp = 0; uint64_t currentRax = 0; - static uint64_t lastRip = 0; auto* sandbox = static_cast(userData); if (!sandbox) return; @@ -66,7 +85,9 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, if (currentSectionIndex >= 0) { sandbox->SetLastExecuteSectionIndex(currentSectionIndex); } + /* auto [lastReadImpAddr, lastImp] = sandbox->GetLastImpRead(); + if (lastImp != nullptr && currentRip == lastReadImpAddr) { printf( "direct call function [%s]%s at file address: %llx lastRip: " @@ -76,19 +97,24 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, sandbox->EmulateApi(uc, lastReadImpAddr, currentRip, lastImp->name); sandbox->SetLastImpRead(0, nullptr); } else { - for (auto module : sandbox->GetModuleList()) { - for (auto item : module->export_function) { - const auto vmAddress = module->base + item->function_address; - if (vmAddress == currentRip) { - printf("[!!!]detect no correct call, currentRip: 0x%llx\n", - currentRip); - sandbox->SetLastImpRead(0, nullptr); + + if (duck_abs(currentRip - address) > PAGE_SIZE) { + for (auto module : sandbox->GetModuleList()) { + for (auto item : module->export_function) { + const auto vmAddress = module->base + item->function_address; + if (vmAddress == currentRip) { + printf("[!!!]detect no correct call, currentRip: 0x%llx\n", + currentRip); + sandbox->SetLastImpRead(0, nullptr); - sandbox->EmulateApi(uc, vmAddress, currentRip, item->name); + sandbox->EmulateApi(uc, vmAddress, currentRip, item->name); + } } } } + } + */ lastRip = currentRip; if (LOG_LEVEL > 2) { // 使用Capstone反汇编 @@ -107,6 +133,43 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, } } +void handleApiCall(uc_engine* uc, uint64_t address, uint32_t size, void* userData) +{ + uint64_t currentRip = 0; + auto* sandbox = static_cast(userData); + if (!sandbox) return; + + uc_reg_read(uc, + sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP, + ¤tRip); + + auto [lastReadImpAddr, lastImp] = sandbox->GetLastImpRead(); + + if (lastImp != nullptr && currentRip == lastReadImpAddr) { + printf( + "direct call function [%s]%s at file address: %llx lastRip: " + "%llx\n", + lastImp->dll_name, + lastImp->name, address, lastRip); + sandbox->EmulateApi(uc, lastReadImpAddr, currentRip, lastImp->name); + sandbox->SetLastImpRead(0, nullptr); + } + else { + for (auto module : sandbox->GetModuleList()) { + for (auto item : module->export_function) { + const auto vmAddress = module->base + item->function_address; + if (vmAddress == currentRip) { + printf("[!!!]detect no correct call, currentRip: 0x%llx\n", + currentRip); + sandbox->SetLastImpRead(0, nullptr); + + sandbox->EmulateApi(uc, vmAddress, currentRip, item->name); + } + } + } + } +} + void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address, int size, int64_t value, void* userData) { auto* sandbox = static_cast(userData); diff --git a/ai_anti_malware/sandbox_callbacks.h b/ai_anti_malware/sandbox_callbacks.h index cecad91..fb6be62 100644 --- a/ai_anti_malware/sandbox_callbacks.h +++ b/ai_anti_malware/sandbox_callbacks.h @@ -3,6 +3,7 @@ namespace sandboxCallbacks { void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, void* userData); +void handleApiCall(uc_engine* uc, uint64_t address, uint32_t size, 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, diff --git a/ai_anti_malware/sandbox_ldr.cpp b/ai_anti_malware/sandbox_ldr.cpp index bea5e83..ac88609 100644 --- a/ai_anti_malware/sandbox_ldr.cpp +++ b/ai_anti_malware/sandbox_ldr.cpp @@ -283,7 +283,80 @@ auto Sandbox::TestLdrListTraversal() -> bool { } return true; } +auto Sandbox::FinalizeLdrLinks() -> void { + if (!m_peInfo->isX64) { + return; + } + // ȡͷַ + uint64_t inLoadOrderListHead = m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList); + uint64_t inMemoryOrderListHead = m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList); + uint64_t inInitOrderListHead = m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList); + + // պInLoadOrderModuleList + CloseLdrList(inLoadOrderListHead, offsetof(LDR_DATA_TABLE_ENTRY, InLoadOrderLinks)); + + // պInMemoryOrderModuleList + CloseLdrList(inMemoryOrderListHead, offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks)); + + // պInInitializationOrderModuleList + CloseLdrList(inInitOrderListHead, offsetof(LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks)); +} + +auto Sandbox::CloseLdrList(uint64_t listHeadAddr, size_t entryLinkOffset) -> void { + LIST_ENTRY listHead; + uc_mem_read(m_ucEngine, listHeadAddr, &listHead, sizeof(LIST_ENTRY)); + + // Ϊգ账 + if (listHead.Flink == (LIST_ENTRY*)listHeadAddr) { + return; + } + + // ҵһԪ + uint64_t currentLink = (uint64_t)listHead.Flink; + uint64_t lastLink = 0; + + while (currentLink != listHeadAddr && currentLink != 0) { + LIST_ENTRY currentEntry; + uc_mem_read(m_ucEngine, currentLink, ¤tEntry, sizeof(LIST_ENTRY)); + + // һΪջָԼǰڵһЧڵ + if (currentEntry.Flink == nullptr || + (uint64_t)currentEntry.Flink == currentLink || + (uint64_t)currentEntry.Flink == 0) { + lastLink = currentLink; + break; + } + + // һͷ˵ȷպ + if ((uint64_t)currentEntry.Flink == listHeadAddr) { + return; // ȷպϣ޸ + } + + lastLink = currentLink; + currentLink = (uint64_t)currentEntry.Flink; + } + + // ҵһԪأ޸ + if (lastLink != 0) { + // ȡһԪ + LIST_ENTRY lastEntry; + uc_mem_read(m_ucEngine, lastLink, &lastEntry, sizeof(LIST_ENTRY)); + + // һԪصFlinkָͷ + lastEntry.Flink = (LIST_ENTRY*)listHeadAddr; + uc_mem_write(m_ucEngine, lastLink, &lastEntry, sizeof(LIST_ENTRY)); + + // ͷBlinkָһԪ + listHead.Blink = (LIST_ENTRY*)lastLink; + uc_mem_write(m_ucEngine, listHeadAddr, &listHead, sizeof(LIST_ENTRY)); + + if (LOG_LEVEL > 4) { + printf("޸ͷ=0x%llx, Ԫ=0x%llx\n", + listHeadAddr, lastLink); + } + } +} // ӡָLDR auto Sandbox::DumpLdrList(const char* listName, uint64_t ldrDataBase, size_t listOffset, size_t entryLinkOffset) -> void { if (LOG_LEVEL > 4) {