diff --git a/ai_anti_malware/head.h b/ai_anti_malware/head.h index f99b4c4..0cc949c 100644 --- a/ai_anti_malware/head.h +++ b/ai_anti_malware/head.h @@ -1,5 +1,5 @@ #pragma once -#define LOG_LEVEL 0 +#define LOG_LEVEL 1 #define _CRT_SECURE_NO_WARNINGS #include diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index aa33398..4e63964 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -164,8 +164,8 @@ class cFixImprot : public peconv::t_function_resolver { for (const auto& module : m_sandbox->m_moduleList) { // 检查模块名是否匹配 if (_stricmp(module->name, lib_name) == 0) { - // 遍历模块的导出函数 - for (const auto& exp : m_sandbox->m_exportFuncDict) { + // 遍历该模块的导出函数 + for (const auto& exp : module->export_function) { // 检查函数名是否匹配 if (strcmp(exp->name, func_name) == 0) { auto newBase = reinterpret_cast( @@ -177,18 +177,24 @@ class cFixImprot : public peconv::t_function_resolver { } } } + + // 如果没有找到精确匹配的模块名,尝试在所有模块中查找该函数 for (const auto& module : m_sandbox->m_moduleList) { - for (const auto& exp : m_sandbox->m_exportFuncDict) { + for (const auto& exp : module->export_function) { // 检查函数名是否匹配 if (strcmp(exp->name, func_name) == 0) { auto newBase = reinterpret_cast( module->base + exp->function_address); - printf("fix import: %s => %llx \n", func_name, newBase); + printf("fix import (fallback): %s found in %s => %llx \n", + func_name, module->name, newBase); // 返回在模拟器中的虚拟地址 return newBase; } } } + + printf("Warning: Could not resolve import: %s from library: %s\n", + func_name, lib_name); //__debugbreak(); return nullptr; } @@ -200,7 +206,7 @@ Sandbox::Sandbox() { m_ucEngine = nullptr; m_peInfo = nullptr; m_nextWfpEngineHandle = (HANDLE)0x1000; // 初始化WFP引擎句柄 - m_lastImpRead = { 0,0 }; + m_lastImpRead = {0, 0}; } Sandbox::~Sandbox() { @@ -253,16 +259,22 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void { m_usedModuleBase = DLL_MODULE_BASE; } // 创建新模块 - auto newModule = CreateModuleInfo(dllName, AlignSize(m_usedModuleBase, PAGE_SIZE), moduleBase, moduleBase); + auto newModule = + CreateModuleInfo(dllName, AlignSize(m_usedModuleBase, PAGE_SIZE), + moduleBase, moduleBase); m_usedModuleBase += PAGE_SIZE + newModule->size; m_moduleList.push_back(newModule); printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule->name, newModule->base, newModule->size); - uc_mem_map(m_ucEngine, newModule->base, newModule->size, - UC_PROT_READ | UC_PROT_EXEC); - uc_mem_write(m_ucEngine, newModule->base, (void*)moduleBase, - newModule->size); + if (uc_mem_map(m_ucEngine, newModule->base, newModule->size, + UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) { + throw std::runtime_error("Failed to map module"); + } + if (uc_mem_write(m_ucEngine, newModule->base, (void*)moduleBase, + newModule->size) != UC_ERR_OK) { + throw std::runtime_error("Failed to write data to map module"); + } if (peconv::relocate_module((BYTE*)moduleBase, newModule->size, newModule->base) == false) { throw std::runtime_error("Failed to relocate module"); @@ -274,8 +286,8 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void { } } -auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase, uint64_t realModuleBase, - uint64_t bufferAddress) +auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase, + uint64_t realModuleBase, uint64_t bufferAddress) -> std::shared_ptr { // 解析PE头 auto* dosHeader = reinterpret_cast(bufferAddress); @@ -574,6 +586,13 @@ auto Sandbox::SetupVirtualMachine() -> void { m_teb32.ProcessEnvironmentBlock = static_cast(m_pebBase); m_teb32.NtTib.StackBase = static_cast(m_stackBase); m_teb32.NtTib.StackLimit = static_cast(m_stackSize); + // 初始化NT_TIB结构的其余部分 + m_teb32.NtTib.Self = + static_cast(m_tebBase); // 关键:设置Self指针指向TEB本身 + m_teb32.NtTib.ExceptionList = 0xFFFFFFFF; // 初始异常链表指向特殊值 + m_teb32.NtTib.Version = 0; + m_teb32.NtTib.FiberData = 0; + m_teb32.NtTib.ArbitraryUserPointer = 0; // 设置堆 m_peb32.ProcessHeap = static_cast(m_heapBase); @@ -591,6 +610,7 @@ auto Sandbox::SetupVirtualMachine() -> void { // 对于32位,我们需要设置FS段寄存器指向TEB SegmentSelector fs = {0}; fs.fields.index = 3; + // 不需要设置present和dpl,因为SegmentSelector结构体中没有这些字段 uc_reg_write(m_ucEngine, UC_X86_REG_FS, &fs.all); // 设置FS基址MSR @@ -598,6 +618,19 @@ auto Sandbox::SetupVirtualMachine() -> void { msr.rid = static_cast(Msr::kIa32FsBase); msr.value = m_tebBase; uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr); + + // 确保TEB中关键字段被正确初始化 + // 特别是FS:18h (0x18)处应该指向自身 + // 根据Native_Struct.h中X32TEB定义,偏移0x18处是SelfTeb + uint32_t self_teb_ptr = static_cast(m_tebBase); + // 在NT_TIB中设置SelfTeb (offset 0x18) + uc_mem_write(m_ucEngine, m_tebBase + 0x18, &self_teb_ptr, + sizeof(uint32_t)); + + // 确保TEB中的ProcessEnvironmentBlock字段指向PEB + uint32_t peb_ptr = static_cast(m_pebBase); + // 偏移0x30处是ProcessEnvironmentBlock + uc_mem_write(m_ucEngine, m_tebBase + 0x30, &peb_ptr, sizeof(uint32_t)); } // 映射新的内存区域 size_t envSize = @@ -635,9 +668,9 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { throw std::runtime_error("Failed to initialize Unicorn"); } // 一定要确保他是第一个. - auto newModule = - CreateModuleInfo("huoji.exe", m_peInfo->RecImageBase, m_peInfo->RecImageBase, - reinterpret_cast(m_peInfo->peBuffer)); + auto newModule = CreateModuleInfo( + "huoji.exe", m_peInfo->RecImageBase, m_peInfo->RecImageBase, + reinterpret_cast(m_peInfo->peBuffer)); _ASSERTE(m_moduleList.size() == 0); m_moduleList.push_back(newModule); @@ -842,8 +875,8 @@ auto Sandbox::GetEnvString() -> std::vector { L"PROMPT=$P$G", L"SystemDrive=C:", L"SystemRoot=C:\\Windows", - L"TEMP=C:\\Users\\User\\AppData\\Local\\Temp", - L"TMP=C:\\Users\\User\\AppData\\Local\\Temp", + L"TEMP=C:\\Users\\huoji\\AppData\\Local\\Temp", + L"TMP=C:\\Users\\huoji\\AppData\\Local\\Temp", L"USERDOMAIN=DESKTOP", L"USERNAME=User", L"USERPROFILE=C:\\Users\\User", diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 4e74666..c8f6d04 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -235,11 +235,13 @@ class Sandbox { auto GetImpFuncDict() -> std::vector> { return m_impFuncDict; } - auto GetLastImpRead() -> std::pair> { + auto GetLastImpRead() + -> std::pair> { return m_lastImpRead; } - auto SetLastImpRead(uint64_t address, std::shared_ptr imp) -> void { - m_lastImpRead = { address, imp }; + auto SetLastImpRead(uint64_t address, std::shared_ptr imp) + -> void { + m_lastImpRead = {address, imp}; } private: @@ -292,16 +294,16 @@ class Sandbox { L"PROMPT=$P$G", L"SystemDrive=C:", L"SystemRoot=C:\\Windows", - L"TEMP=C:\\Users\\User\\AppData\\Local\\Temp", - L"TMP=C:\\Users\\User\\AppData\\Local\\Temp", + L"TEMP=C:\\Users\\huoji\\AppData\\Local\\Temp", + L"TMP=C:\\Users\\huoji\\AppData\\Local\\Temp", L"USERDOMAIN=DESKTOP", L"USERNAME=User", - L"USERPROFILE=C:\\Users\\User", + L"USERPROFILE=C:\\Users\\huoji", L"windir=C:\\Windows"}; auto ResoveImport() -> void; auto ResolveImportExports() -> void; - auto CreateModuleInfo(const char* dllName, uint64_t moduleBase, uint64_t realModuleBase, - uint64_t bufferAddress) + auto CreateModuleInfo(const char* dllName, uint64_t moduleBase, + uint64_t realModuleBase, uint64_t bufferAddress) -> std::shared_ptr; auto ResolveExport(uint64_t moduleBase) -> std::vector>; @@ -439,4 +441,6 @@ auto Api_FwpmEngineClose0(void* sandbox, uc_engine* uc, uint64_t address) -> void; 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; \ No newline at end of file +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 diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index 0417174..5170a5c 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -1359,6 +1359,9 @@ auto Sandbox::InitApiHooks() -> void { _fakeApi{.func = Api_GetStringTypeW, .paramCount = 4}; auto FakeApi_LCMapStringW = _fakeApi{.func = Api_LCMapStringW, .paramCount = 6}; + auto FakeApi__initterm_e = + _fakeApi{.func = Api__initterm_e, .paramCount = 2}; + auto FakeApi_getenv = _fakeApi{.func = Api_getenv, .paramCount = 1}; api_map = { {"GetSystemTimeAsFileTime", @@ -1492,8 +1495,10 @@ auto Sandbox::InitApiHooks() -> void { {"TlsFree", std::make_shared<_fakeApi>(FakeApi_TlsFree)}, {"FlsAlloc", std::make_shared<_fakeApi>(FakeApi_FlsAlloc)}, {"FlsGetValue", std::make_shared<_fakeApi>(FakeApi_FlsGetValue)}, + {"_initterm_e", std::make_shared<_fakeApi>(FakeApi__initterm_e)}, {"GetStringTypeW", std::make_shared<_fakeApi>(FakeApi_GetStringTypeW)}, {"LCMapStringW", std::make_shared<_fakeApi>(FakeApi_LCMapStringW)}, + {"getenv", std::make_shared<_fakeApi>(FakeApi_getenv)}, }; } auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, @@ -1548,6 +1553,6 @@ auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, return true; } printf("ApiName: %s not found\n", ApiName.c_str()); - //uc_emu_stop(uc); + uc_emu_stop(uc); return 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 03fc224..9aa34ac 100644 --- a/ai_anti_malware/sandbox_api_stl.cpp +++ b/ai_anti_malware/sandbox_api_stl.cpp @@ -574,7 +574,7 @@ auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address) } } else { // 使用指定长度 - if (cchWideChar > 0 && cchWideChar <= MAX_PATH) { + if (cchWideChar > 0 && cchWideChar <= 4 * 1024) { srcBuffer.resize(cchWideChar); if (uc_mem_read(uc, lpWideCharStr, srcBuffer.data(), cchWideChar * 2) != UC_ERR_OK) { @@ -699,7 +699,7 @@ auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address) "WideLen=%d, MultiStr=%p, MultiLen=%d, Result=%d\n", CodePage, dwFlags, (void*)lpWideCharStr, cchWideChar, (void*)lpMultiByteStr, cbMultiByte, result); - + printf("[*] WideCharToMultiByte: pre=%s\n", multiByteBuffer.data()); uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); @@ -1338,8 +1338,7 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address) if (context->GetPeInfo()->isX64) { currentThreadHandle = (HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread; - } - else { + } else { currentThreadHandle = (HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread; } @@ -1347,21 +1346,19 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address) if (lpCriticalSection != 0) { if (context->GetPeInfo()->isX64) { RTL_CRITICAL_SECTION cs; - uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION)); - + uc_mem_read(uc, lpCriticalSection, &cs, + sizeof(RTL_CRITICAL_SECTION)); // 如果当前线程已经拥有锁,增加递归计数 if (cs.OwningThread == currentThreadHandle) { cs.RecursionCount++; - } - else { + } else { // 如果没有线程拥有锁,获取它 if (cs.LockCount == -1) { cs.OwningThread = currentThreadHandle; cs.RecursionCount = 1; cs.LockCount = 0; - } - else { + } else { // 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁 cs.OwningThread = currentThreadHandle; cs.RecursionCount = 1; @@ -1370,25 +1367,23 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address) } // 写回更新后的关键段结构 - uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION)); - } - else { + uc_mem_write(uc, lpCriticalSection, &cs, + sizeof(RTL_CRITICAL_SECTION)); + } else { RTL_CRITICAL_SECTION32 cs; - uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION32)); - + uc_mem_read(uc, lpCriticalSection, &cs, + sizeof(RTL_CRITICAL_SECTION32)); // 如果当前线程已经拥有锁,增加递归计数 if (cs.OwningThread == (DWORD)currentThreadHandle) { cs.RecursionCount++; - } - else { + } else { // 如果没有线程拥有锁,获取它 if (cs.LockCount == -1) { cs.OwningThread = (DWORD)currentThreadHandle; cs.RecursionCount = 1; cs.LockCount = 0; - } - else { + } else { // 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁 cs.OwningThread = (DWORD)currentThreadHandle; cs.RecursionCount = 1; @@ -1397,7 +1392,8 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address) } // 写回更新后的关键段结构 - uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION32)); + uc_mem_write(uc, lpCriticalSection, &cs, + sizeof(RTL_CRITICAL_SECTION32)); } } @@ -1475,9 +1471,8 @@ auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address) } if (lpStartupInfo != 0) { - if (context->GetPeInfo()->isX64) { - STARTUPINFOW si = { 0 }; + STARTUPINFOW si = {0}; si.cb = sizeof(STARTUPINFOW); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; @@ -1496,9 +1491,8 @@ auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address) si.hStdOutput = nullptr; si.hStdError = nullptr; uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW)); - } - else { - STARTUPINFOW32 si = { 0 }; + } else { + STARTUPINFOW32 si = {0}; si.cb = sizeof(STARTUPINFOW32); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; @@ -2111,21 +2105,24 @@ auto Api_RtlFormatCurrentUserKeyPath(void* sandbox, uc_engine* uc, if (context->GetPeInfo()->isX64) { // 创建UNICODE_STRING结构 UNICODE_STRING unicodeString; - unicodeString.Length = static_cast(pathLen * sizeof(wchar_t)); + unicodeString.Length = + static_cast(pathLen * sizeof(wchar_t)); unicodeString.MaximumLength = static_cast(bufferSize); unicodeString.Buffer = reinterpret_cast(stringBuffer); // 将UNICODE_STRING结构写入到提供的缓冲区 - uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING)); - } - else { + uc_mem_write(uc, keyPathBuffer, &unicodeString, + sizeof(UNICODE_STRING)); + } else { UNICODE_STRING32 unicodeString; - unicodeString.Length = static_cast(pathLen * sizeof(wchar_t)); + unicodeString.Length = + static_cast(pathLen * sizeof(wchar_t)); unicodeString.MaximumLength = static_cast(bufferSize); unicodeString.Buffer = (DWORD)(stringBuffer); // 将UNICODE_STRING结构写入到提供的缓冲区 - uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING32)); + uc_mem_write(uc, keyPathBuffer, &unicodeString, + sizeof(UNICODE_STRING32)); } } @@ -2389,3 +2386,148 @@ auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void { context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &return_value); } + +auto Api__initterm_e(void* sandbox, uc_engine* uc, uint64_t address) -> void { + auto context = static_cast(sandbox); + uint64_t table_start = 0; + uint64_t table_end = 0; + + // 获取参数:函数表的起始地址和结束地址 + if (context->GetPeInfo()->isX64) { + // x64: 参数在RCX和RDX中 + uc_reg_read(uc, UC_X86_REG_RCX, &table_start); + uc_reg_read(uc, UC_X86_REG_RDX, &table_end); + } else { + // x86: 从栈上读取参数 + uint32_t esp = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp); + esp += 0x4; // 跳过返回地址 + + uint32_t temp_start; + uc_mem_read(uc, esp, &temp_start, sizeof(uint32_t)); + table_start = temp_start; + + esp += 0x4; + uint32_t temp_end; + uc_mem_read(uc, esp, &temp_end, sizeof(uint32_t)); + table_end = temp_end; + } + + // 返回值,默认为0(成功) + int32_t return_value = 0; + + // 遍历函数表并调用每个初始化函数 + // 在表的每一项都是函数指针 + printf("[*] _initterm_e: Start=0x%llx, End=0x%llx\n", table_start, + table_end); + + // 只有当表的起始地址和结束地址有效时才进行处理 + if (table_start < table_end) { + uint64_t current = table_start; + uint64_t ptr_size = context->GetPeInfo()->isX64 ? 8 : 4; + + // 遍历函数表 + while (current < table_end) { + uint64_t function_ptr = 0; + + // 读取当前表项中的函数指针 + uc_mem_read(uc, current, &function_ptr, ptr_size); + + // 非空函数指针才调用 + if (function_ptr != 0) { + printf("[*] _initterm_e: Calling function at 0x%llx\n", + function_ptr); + + // 在实际环境中,这里会调用该函数并检查返回值 + // 但在沙箱中,我们模拟这个调用并返回成功 + // 如果需要执行真实函数,可以使用uc_emu_start + + // 如果有错误发生,设置返回值并退出 + // 这里简化处理,始终假设初始化成功 + // 实际实现可能需要更复杂的逻辑 + } + + // 移动到下一个表项 + current += ptr_size; + } + } + + // 设置返回值 + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &return_value); +} + +// 实现getenv API +auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void { + auto context = static_cast(sandbox); + uint64_t name_ptr = 0; + char name[256] = {0}; + uint64_t return_value = 0; // 默认返回NULL + + // 获取参数 - 环境变量名称 + if (context->GetPeInfo()->isX64) { + // x64: rcx = name + uc_reg_read(uc, UC_X86_REG_RCX, &name_ptr); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uint32_t temp_name_ptr = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + uc_mem_read(uc, esp_address, &temp_name_ptr, sizeof(uint32_t)); + name_ptr = temp_name_ptr; + } + + // 读取环境变量名 + if (name_ptr != 0) { + size_t i = 0; + uint8_t byte = 1; + while (byte != 0 && i < sizeof(name) - 1) { + uc_mem_read(uc, name_ptr + i, &byte, 1); + name[i++] = static_cast(byte); + } + name[i] = '\0'; + } + + printf("[*] getenv: Looking for env var '%s'\n", name); + + // 获取环境变量值 + bool found = false; + std::string value; + std::vector envStrings = context->GetEnvStrings(); + + for (const auto& var : envStrings) { + std::string varA(var.begin(), var.end()); + size_t pos = varA.find('='); + if (pos != std::string::npos) { + std::string varName = varA.substr(0, pos); + if (_stricmp(varName.c_str(), name) == 0) { + value = varA.substr(pos + 1); + found = true; + break; + } + } + } + + if (found) { + // 分配内存存储环境变量值 + uint64_t valueSize = value.size() + 1; // 包括结束符 + uint64_t valuePtr = context->AllocateMemory(valueSize); + + if (valuePtr) { + // 复制字符串到内存 + uc_mem_write(uc, valuePtr, value.c_str(), valueSize); + return_value = valuePtr; + printf("[*] getenv: Found '%s'='%s' at 0x%llx\n", name, + value.c_str(), valuePtr); + } + } else { + printf("[*] getenv: Env var '%s' not found\n", name); + } + + // 设置返回值 + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &return_value); +}