From 785f0da7fe4b7bd0b61907f5c3abf2ccdcf43cf4 Mon Sep 17 00:00:00 2001 From: Huoji's <1296564236@qq.com> Date: Wed, 23 Apr 2025 03:48:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E7=85=A7=E6=A0=B7=E6=9C=AC=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BA=86=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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/native_struct.h | 26 +- ai_anti_malware/sandbox.cpp | 249 ++-------- ai_anti_malware/sandbox.h | 9 +- ai_anti_malware/sandbox_api_emu.cpp | 28 +- ai_anti_malware/sandbox_callbacks.cpp | 29 +- ai_anti_malware/sandbox_dump_pe.cpp | 2 +- ai_anti_malware/sandbox_ldr.cpp | 443 ++++++++++++++---- ai_anti_malware/sandbox_setupvm.cpp | 277 +++++++++++ 11 files changed, 747 insertions(+), 329 deletions(-) create mode 100644 ai_anti_malware/sandbox_setupvm.cpp diff --git a/ai_anti_malware/ai_anti_malware.cpp b/ai_anti_malware/ai_anti_malware.cpp index bb16ff2..855728f 100644 --- a/ai_anti_malware/ai_anti_malware.cpp +++ b/ai_anti_malware/ai_anti_malware.cpp @@ -276,7 +276,7 @@ DetectEngineType DetectEngine::DetectMalware(std::string filePath) { if (peAnalyzer.AnalyzePe(peInfo)) { return DetectEngineType::kPeStruct; } - + /* // 先机器学习引擎 MachineLearning ml; double score = 1 - ml.PredictMalwareFromFile(filePath); @@ -286,11 +286,12 @@ DetectEngineType DetectEngine::DetectMalware(std::string filePath) { return DetectEngineType::kMachineLearning; } } - + */ // 再沙盒引擎 Sandbox se; se.InitEnv(peInfo); - se.Run(); + se.TestLdrListTraversal(); + se.Run(0x22A0); if (se.GetMalwareAnalysisType() == MalwareAnalysisType::kSuspicious || se.GetMalwareAnalysisType() == MalwareAnalysisType::kMalware) { return DetectEngineType::kSandbox; @@ -375,7 +376,7 @@ int main(int argc, char* argv[]) { std::string filePath = argv[1]; */ - std::string filePath = "Z:\\malware"; + 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 aa47f0d..68b9668 100644 --- a/ai_anti_malware/ai_anti_malware.vcxproj +++ b/ai_anti_malware/ai_anti_malware.vcxproj @@ -191,6 +191,7 @@ + diff --git a/ai_anti_malware/ai_anti_malware.vcxproj.filters b/ai_anti_malware/ai_anti_malware.vcxproj.filters index ceb4e86..3d838d4 100644 --- a/ai_anti_malware/ai_anti_malware.vcxproj.filters +++ b/ai_anti_malware/ai_anti_malware.vcxproj.filters @@ -168,6 +168,9 @@ 源文件\sandbox + + 源文件\sandbox + diff --git a/ai_anti_malware/native_struct.h b/ai_anti_malware/native_struct.h index ab6abbd..0a323f9 100644 --- a/ai_anti_malware/native_struct.h +++ b/ai_anti_malware/native_struct.h @@ -221,11 +221,27 @@ typedef struct _LDR_DATA_TABLE_ENTRY { }; }; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; +//0x18 bytes (sizeof) +struct _CURDIR +{ + struct _UNICODE_STRING DosPath; //0x0 + VOID* Handle; //0x10 +}; typedef struct _RTL_USER_PROCESS_PARAMETERS { - BYTE Reserved1[16]; - PVOID Reserved2[10]; - UNICODE_STRING ImagePathName; - UNICODE_STRING CommandLine; + ULONG MaximumLength; //0x0 + ULONG Length; //0x4 + ULONG Flags; //0x8 + ULONG DebugFlags; //0xc + VOID* ConsoleHandle; //0x10 + ULONG ConsoleFlags; //0x18 + VOID* StandardInput; //0x20 + VOID* StandardOutput; //0x28 + VOID* StandardError; //0x30 + struct _CURDIR CurrentDirectory; //0x38 + struct _UNICODE_STRING DllPath; //0x50 + struct _UNICODE_STRING ImagePathName; //0x60 + struct _UNICODE_STRING CommandLine; //0x70 + VOID* Environment; //0x80 } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; typedef struct _BASE_RELOCATION_ENTRY { @@ -1019,7 +1035,7 @@ struct struct_handle_table { char name[MAX_PATH]; // 名称 }; struct struct_moudle { - char name[MAX_PATH]; + std::string name; uint64_t entry; uint64_t base; uint64_t size; diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index 6e7c1bf..19cfbab 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -111,7 +111,8 @@ public: // 遍历所有已加载的模块 for (const auto& module : m_sandbox->m_moduleList) { // 检查模块名是否匹配 - if (_stricmp(module->name, lib_name) == 0) { + + if (module->name == std::string(lib_name) == 0) { // 遍历该模块的导出函数 for (const auto& exp : module->export_function) { // 检查函数名是否匹配 @@ -144,7 +145,7 @@ public: } //序号导出,非常癌症的修复. - if (strcmp(module->name, lib_name) == 0) { + if (std::string(lib_name) == module->name) { int ordinalNum = std::atoi(func_name); if (exp->ordinal == ordinalNum) { auto newBase = reinterpret_cast( @@ -263,7 +264,7 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase, uint64_t } } -auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase, +auto Sandbox::CreateModuleInfo(std::string dllName, uint64_t moduleBase, uint64_t realModuleBase, uint64_t bufferAddress) -> std::shared_ptr { // 解析PE头 @@ -283,9 +284,8 @@ auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase, reinterpret_cast(ntHeaders) + sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) + ntHeaders->FileHeader.SizeOfOptionalHeader); - struct_moudle newModule{}; - strncpy(newModule.name, dllName, strlen(dllName)); + newModule.name = dllName.c_str(); newModule.base = moduleBase; newModule.real_base = realModuleBase; newModule.entry = ntHeaders->OptionalHeader.AddressOfEntryPoint; @@ -396,8 +396,16 @@ auto Sandbox::ResolveImportExports() -> void { } } auto Sandbox::mapSystemModuleToVmByName(std::string systemName) -> void { + std::string tempMatchName = systemName; + std::transform(tempMatchName.begin(), tempMatchName.end(), tempMatchName.begin(), + [](unsigned char c) { return std::toupper(c); }); + for (auto module : m_moduleList) { - if (strcmp(module->name, systemName.c_str()) == 0) { + std::string listModuleName = module->name; + std::transform(listModuleName.begin(), listModuleName.end(), listModuleName.begin(), + [](unsigned char c) { return std::toupper(c); }); + + if (tempMatchName == listModuleName) { if (LOG_LEVEL > 0) { printf("skip module name: %s (already loaded)\n", module->name); } @@ -428,8 +436,11 @@ auto Sandbox::mapSystemModuleToVmByName(std::string systemName) -> void { PushModuleToVM(systemName.c_str(), moduleBase, mappedPeSize); } auto Sandbox::processImportModule(const moudle_import* importModule) -> void { + std::string impModule = importModule->dll_name; + std::transform(impModule.begin(), impModule.end(), impModule.begin(), + [](unsigned char c) { return std::toupper(c); }); - mapSystemModuleToVmByName(importModule->dll_name); + mapSystemModuleToVmByName(impModule); } auto Sandbox::ResoveImport() -> void { // 处理延迟导入 @@ -453,194 +464,7 @@ auto Sandbox::ResoveImport() -> void { mapSystemModuleToVmByName(importModule->dll_name); } } -auto Sandbox::SetupVirtualMachine() -> void { - SegmentSelector cs = {0}; - cs.fields.index = 1; - uc_reg_write(m_ucEngine, UC_X86_REG_CS, &cs.all); - SegmentSelector ds = {0}; - ds.fields.index = 2; - uc_reg_write(m_ucEngine, UC_X86_REG_DS, &ds.all); - - SegmentSelector ss = {0}; - ss.fields.index = 2; - uc_reg_write(m_ucEngine, UC_X86_REG_SS, &ss.all); - - SegmentSelector es = {0}; - es.fields.index = 2; - uc_reg_write(m_ucEngine, UC_X86_REG_ES, &es.all); - - SegmentSelector gs = {0}; - gs.fields.index = 2; - uc_reg_write(m_ucEngine, UC_X86_REG_GS, &gs.all); - - FlagRegister eflags = {0}; - eflags.fields.id = 1; - eflags.fields.intf = 1; - eflags.fields.reserved1 = 1; - - uc_reg_write(m_ucEngine, UC_X86_REG_EFLAGS, &eflags.all); - - uint64_t cr8 = 0; - uc_reg_write(m_ucEngine, UC_X86_REG_CR8, &cr8); - - /* - 映射 m_KSharedUserDataBase - */ - m_KSharedUserDataBase = 0x7FFE0000; - uint64_t m_KSharedUserDataEnd = 0x7FFE0FFF; // 0x7FFE2000 - m_KSharedUserDataSize = AlignToSectionAlignment( - m_KSharedUserDataEnd - m_KSharedUserDataBase, PAGE_SIZE); - - uc_mem_map(m_ucEngine, m_KSharedUserDataBase, m_KSharedUserDataSize, - UC_PROT_READ); - uc_mem_write(m_ucEngine, m_KSharedUserDataBase, - (void*)m_KSharedUserDataBase, m_KSharedUserDataSize); - - m_tebBase = TEB_BASE; // 进程TEB地址 - m_pebBase = PEB_BASE; // 进程PEB地址 - m_envBlockBase = ENV_BLOCK_BASE; // 环境变量块地址 - // stack - m_stackBase = AlignToSectionAlignment( - this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32, 16); - m_stackSize = AlignToSectionAlignment( - this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32, 16); - m_stackEnd = m_stackBase + m_stackSize; - - // heap - m_heapBase = this->m_peInfo->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32; - m_heapSize = this->m_peInfo->isX64 ? HEAP_SIZE_64 : HEAP_SIZE_32; - m_heapEnd = m_heapBase + m_heapSize; - - // 根据PE文件类型设置PEB和TEB - if (this->m_peInfo->isX64) { - // 设置64位PEB - m_peb64.ImageBaseAddress = m_peInfo->RecImageBase; - m_pebEnd = - m_pebBase + AlignToSectionAlignment(sizeof(X64PEB), PAGE_SIZE); - m_tebEnd = - m_tebBase + AlignToSectionAlignment(sizeof(X64TEB), PAGE_SIZE); - - // 设置64位TEB - m_teb64.ClientId.UniqueProcess = GetCurrentProcessId(); - m_teb64.ClientId.UniqueThread = GetCurrentThreadId(); - m_teb64.ProcessEnvironmentBlock = reinterpret_cast(m_pebBase); - m_teb64.NtTib.StackBase = (DWORD64)m_stackBase; - m_teb64.NtTib.StackLimit = (DWORD64)m_stackSize; - - // 设置堆 - m_peb64.ProcessHeap = m_heapBase; - - // 设置GS基址结构 - m_gsBaseStruct.teb = m_tebBase; - m_gsBaseStruct.peb = m_pebBase; - uint64_t gsAllocSize = - AlignToSectionAlignment(sizeof(struct_gs_base), PAGE_SIZE); - - // 映射PEB到虚拟内存 - uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase, - UC_PROT_READ | UC_PROT_WRITE); - uc_mem_write(m_ucEngine, m_pebBase, &m_peb64, sizeof(X64PEB)); - - // 映射TEB到虚拟内存 - uc_mem_map(m_ucEngine, m_tebBase, m_tebEnd - m_tebBase, - UC_PROT_READ | UC_PROT_WRITE); - uc_mem_write(m_ucEngine, m_tebBase, &m_teb64, sizeof(X64TEB)); - - // 映射GS基址结构到虚拟内存 - uc_mem_map(m_ucEngine, m_gsBase, gsAllocSize, UC_PROT_READ); - uc_mem_write(m_ucEngine, m_gsBase, &m_gsBaseStruct, - sizeof(struct_gs_base)); - - // 设置GS基址MSR - uc_x86_msr msr; - msr.rid = static_cast(Msr::kIa32GsBase); - msr.value = m_gsBase; - uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr); - } else { - // 设置32位PEB - m_peb32.ImageBaseAddress = static_cast(m_peInfo->RecImageBase); - m_pebEnd = - m_pebBase + AlignToSectionAlignment(sizeof(X32PEB), PAGE_SIZE); - m_tebEnd = - m_tebBase + AlignToSectionAlignment(sizeof(X32TEB), PAGE_SIZE); - - // 设置32位TEB - m_teb32.ClientId.UniqueProcess = GetCurrentProcessId(); - m_teb32.ClientId.UniqueThread = GetCurrentThreadId(); - 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); - - // 映射PEB到虚拟内存 - uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase, - UC_PROT_READ | UC_PROT_WRITE); - uc_mem_write(m_ucEngine, m_pebBase, &m_peb32, sizeof(X32PEB)); - - // 映射TEB到虚拟内存 - uc_mem_map(m_ucEngine, m_tebBase, m_tebEnd - m_tebBase, - UC_PROT_READ | UC_PROT_WRITE); - uc_mem_write(m_ucEngine, m_tebBase, &m_teb32, sizeof(X32TEB)); - - // 对于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 - uc_x86_msr msr; - 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 = - AlignToSectionAlignment(this->GetEnvStringsSize(), PAGE_SIZE); - printf("env block size: %llx\n", envSize); // 添加调试输出 - uc_err envErr = uc_mem_map(m_ucEngine, m_envBlockBase, envSize, - UC_PROT_READ | UC_PROT_WRITE); - if (envErr != UC_ERR_OK) { - throw std::runtime_error("Failed to map environment block"); - } - - auto envData = this->GetEnvString(); - envErr = uc_mem_write(m_ucEngine, m_envBlockBase, envData.data(), - envData.size() * sizeof(wchar_t)); - if (envErr != UC_ERR_OK) { - throw std::runtime_error("Failed to write environment block"); - } - - for (DWORD i = 0; i < 64; i++) { - GetTeb64()->TlsSlots[i] = (void*)0x1337ffffff; - } - for (DWORD i = 0; i < 64; i++) { - GetTeb32()->TlsSlots[i] = 0x1337; - } -} /* // 在InitEnv函数之前添加这个函数 void Sandbox::RegisterComApis() { @@ -672,10 +496,13 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { cs_close(&m_csHandle); // 清理已分配的capstone资源 throw std::runtime_error("Failed to initialize Unicorn"); } + SetupVirtualMachine(); + // 一定要确保他是第一个. 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); @@ -692,7 +519,35 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { if (!peconv::load_imports(m_peInfo->peBuffer, &importFixer)) { throw std::runtime_error("Failed to fix imports"); } + //检查有没有ntdll + bool isFoundNtdll = false; + bool isFoundKernelBase = false; + for (const auto& module : this->GetModuleList()) { + //我tm也不知道为什么 有些病毒这玩意找小写....然后kernel32.dll找大写.wtf is that? + if (module->name == "ntdll.dll") { + isFoundNtdll = true; + } + //真的很懒了,这个是按TAB一键出来的 + if (module->name == "KERNELBASE.dll") { + isFoundKernelBase = true; + } + if (isFoundKernelBase && isFoundNtdll) { + break; + } + } + if (isFoundNtdll == false) { + if (LOG_LEVEL > 4) { + printf("Not ntdll.dll Found, manual map it \n"); + } + mapSystemModuleToVmByName("ntdll.dll"); + } + if (isFoundKernelBase == false) { + if (LOG_LEVEL > 4) { + printf("Not kernelbase.dll Found, manual map it \n"); + } + mapSystemModuleToVmByName("kernelbase.dll"); + } // 给所有导入表加c3 for (const auto& module : this->GetModuleList()) { // 遍历导出函数查找对应名称 @@ -710,7 +565,6 @@ auto Sandbox::InitEnv(std::shared_ptr peInfo) -> void { m_peInfo->peSize); printf("map file to vm file: %llx\n", m_peInfo->RecImageBase); printf("map file to vm size: %llx\n", m_peInfo->peSize); - SetupVirtualMachine(); InitCommandLine(peInfo->inputFilePath); } @@ -811,7 +665,8 @@ auto Sandbox::Run(uint64_t address) -> void { std::cout << "Starting execution at " << std::hex << entryPoint << std::endl; - uint64_t timeout = 2 * 60 * 1000 * 1000; + //uint64_t timeout = 2 * 60 * 1000 * 1000; + uint64_t timeout = 0; // 1.入口点是必须跑的 if (m_peInfo->isDll) { // 给rcx和rdx设置dll应该设置的 @@ -853,7 +708,7 @@ auto Sandbox::Run(uint64_t address) -> void { std::cerr << "Entry Point Emulation error: " << uc_strerror(err) << std::endl; if (address != 0) { - err = uc_emu_start(m_ucEngine, address, m_peInfo->imageEnd, timeout, 0); + err = uc_emu_start(m_ucEngine, address + MAIN_MODULE_BASE, m_peInfo->imageEnd, timeout, 0); std::cerr << "Custom Emulation error: " << uc_strerror(err) << std::endl; } diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index ef1f959..3e2e133 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -26,6 +26,7 @@ #define TEB_BASE 0x90000 #define CMDLINE_ADDRESS 0x100000 // 命令行字符串的固定地址 #define CMDLINEW_ADDRESS 0x110000 // 宽字符命令行字符串的固定地址 +#define PROCESS_PARAMS_BASE 0x120000 // 进程参数结构的基址 #define X86_GDT_ADDR 0x30000 #define X86_GDT_LIMIT 0x1000 @@ -244,6 +245,7 @@ class Sandbox { -> void { m_lastImpRead = {address, imp}; } + auto TestLdrListTraversal() -> bool; // 注册COM相关API void RegisterComApis(); @@ -266,6 +268,7 @@ class Sandbox { uint64_t m_heapEnd; uint64_t m_fakeBase; uint64_t m_envBlockBase; + uint64_t m_processParamsBase; struct_gs_base m_gsBaseStruct = {0}; X64TEB m_teb64 = {0}; X64PEB m_peb64 = {0}; @@ -307,8 +310,9 @@ class Sandbox { L"USERPROFILE=C:\\Users\\huoji", L"windir=C:\\Windows"}; auto ResoveImport() -> void; + auto BuildPebParameter() -> void; auto ResolveImportExports() -> void; - auto CreateModuleInfo(const char* dllName, uint64_t moduleBase, + auto CreateModuleInfo(std::string dllName, uint64_t moduleBase, uint64_t realModuleBase, uint64_t bufferAddress) -> std::shared_ptr; auto ResolveExport(uint64_t moduleBase) @@ -333,6 +337,9 @@ class Sandbox { // 将模块添加到LDR链表中 auto AddModuleToLdr(const std::shared_ptr& module) -> void; + + auto DumpLdrList(const char* listName, uint64_t ldrDataBase, size_t listOffset, size_t entryLinkOffset) -> void; + // 创建LDR_DATA_TABLE_ENTRY结构 auto CreateLdrEntry(const std::shared_ptr& module, uint64_t entryAddress, uint64_t fullNameAddress, diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index 4fc6f72..f05b8b5 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -113,7 +113,7 @@ auto Api_LoadLibraryA(void* sandbox, uc_engine* uc, uint64_t address) -> void { // 从模块列表中查找对应模块 for (const auto& module : context->GetModuleList()) { - if (_stricmp((*module).name, module_name.c_str()) == 0) { + if ((*module).name == module_name.c_str()) { return_address = (*module).base; break; } @@ -183,7 +183,7 @@ auto Api_LoadLibraryExW(void* sandbox, uc_engine* uc, uint64_t address) // 从模块列表中查找对应模块 for (const auto& module : context->GetModuleList()) { - if (_stricmp((*module).name, ansi_name.c_str()) == 0) { + if ((*module).name == ansi_name.c_str()) { return_address = (*module).base; break; } @@ -240,19 +240,21 @@ auto Api_GetProcAddress(void* sandbox, uc_engine* uc, uint64_t address) functionName[i] = byte; i++; } while (functionName[i - 1] != 0 && i < sizeof(functionName)); - context->CheckMalwareActive_GetProcAddress(functionName); + std::string fnName = functionName; + + context->CheckMalwareActive_GetProcAddress(fnName); + if (fnName == "FlsGetValue2") { + fnName = "FlsGetValue"; + } // 在模块列表中查找对应模块 for (const auto& module : context->GetModuleList()) { - if (module->base == moduleHandle) { - // 遍历导出函数查找对应名称 - for (const auto& exp : module->export_function) { - // 使用 _stricmp 进行大小写不敏感的比较 - if (_stricmp(exp->name, functionName) == 0) { - return_address = module->base + exp->function_address; - break; - } + // 遍历导出函数查找对应名称 + for (const auto& exp : module->export_function) { + // 使用 _stricmp 进行大小写不敏感的比较 + if (_stricmp(exp->name, fnName.c_str()) == 0) { + return_address = module->base + exp->function_address; + break; } - break; } } @@ -923,7 +925,7 @@ auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address) auto Api_GetStringTypeW(void* sandbox, uc_engine* uc, uint64_t address) -> void { auto context = static_cast(sandbox); - uint32_t dwInfoType = 0; + uint64_t dwInfoType = 0; uint64_t lpSrcStr = 0; int32_t cchSrc = 0; uint64_t lpCharType = 0; diff --git a/ai_anti_malware/sandbox_callbacks.cpp b/ai_anti_malware/sandbox_callbacks.cpp index 1fe3cb2..421f68a 100644 --- a/ai_anti_malware/sandbox_callbacks.cpp +++ b/ai_anti_malware/sandbox_callbacks.cpp @@ -51,7 +51,17 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size, // 记录跨区段执行地址 sandbox->SetCrossSectionExecution(address); } - + if (address == 0xff1160) { + uint64_t rcx = 0; + uc_reg_read(uc, UC_X86_REG_RCX, &rcx); + printf("malware try find hash: %llx \n", rcx); + } + /* + if (address == 0xff12B7) { + sandboxCallbacks::dumpVmenv(uc, userData); + __debugbreak(); + } + */ // 更新上次执行的区段 if (currentSectionIndex >= 0) { sandbox->SetLastExecuteSectionIndex(currentSectionIndex); @@ -120,8 +130,8 @@ void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address, address < (ldrAddress + sizeof(X64_PEB_LDR_DATA))) { printf( "[WARNING] Suspicious direct LDR access detected at RIP: " - "0x%llx, accessing address: 0x%llx\n", - regRip, address); + "0x%llx, accessing address: 0x%llx accessing offset: 0x%llx\n", + regRip, address, address - ldrAddress); sandbox->SetMalwareAnalysisType(MalwareAnalysisType::kSuspicious); } } else { @@ -170,6 +180,8 @@ void dumpVmenv(uc_engine* uc, void* userData) { uint64_t Rdx = 0; uint64_t Eax = 0; uint64_t Ecx = 0; + uint64_t R15 = 0; + uc_reg_read(uc, sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP, &Rip); @@ -188,16 +200,15 @@ void dumpVmenv(uc_engine* uc, void* userData) { uc_reg_read(uc, sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RDX : UC_X86_REG_EDX, &Rdx); - uc_reg_read(uc, - sandbox->GetPeInfo()->isX64 ? UC_X86_REG_EAX : UC_X86_REG_EAX, - &Eax); + uc_reg_read(uc, UC_X86_REG_EAX, &Eax); uc_reg_read(uc, sandbox->GetPeInfo()->isX64 ? UC_X86_REG_ECX : UC_X86_REG_ECX, &Ecx); + uc_reg_read(uc, UC_X86_REG_R15D, &R15); printf( - "[dumpVmenv] Rip: %p lastRip: %p Rax: %p Rsp: %p Rbp: %p Rcx: %p Rdx: %p Eax: " - "%08x Ecx: %08x\n", - Rip, Rax, Rsp, Rbp, Rcx, Rdx, Eax, Ecx); + "[dumpVmenv] Rip: %p Rax: %p Rsp: %p Rbp: %p Rcx: %p Rdx: %p Eax: " + "%08x Ecx: %llx R15D: %llx\n", + Rip, Rax, Rsp, Rbp, Rcx, Rdx, Eax, Ecx, R15); // 打印32层栈内存 printf("\n[Stack Memory Dump (32 levels)]\n"); diff --git a/ai_anti_malware/sandbox_dump_pe.cpp b/ai_anti_malware/sandbox_dump_pe.cpp index f56174f..61c6652 100644 --- a/ai_anti_malware/sandbox_dump_pe.cpp +++ b/ai_anti_malware/sandbox_dump_pe.cpp @@ -4,7 +4,7 @@ auto Sandbox::DumpPE() -> std::pair, size_t> { // Ŀģ - ʹģ(ͨDZĿִļ) std::shared_ptr targetModule = nullptr; for (const auto& module : m_moduleList) { - if (strcmp(module->name, "huoji.exe") == 0) { + if ((*module).name == "HUOJI.EXE") { targetModule = module; break; } diff --git a/ai_anti_malware/sandbox_ldr.cpp b/ai_anti_malware/sandbox_ldr.cpp index e8df912..bea5e83 100644 --- a/ai_anti_malware/sandbox_ldr.cpp +++ b/ai_anti_malware/sandbox_ldr.cpp @@ -2,7 +2,7 @@ auto Sandbox::InitializeLdrData() -> void { - if (m_peInfo->isX64 && m_peb64.Ldr == 0) { + if (m_peInfo->isX64) { // ΪLDR_DATAڴ uint64_t ldrDataAddress = m_pebBase + sizeof(X64PEB); m_pebEnd = ldrDataAddress + sizeof(X64_PEB_LDR_DATA); @@ -17,148 +17,393 @@ auto Sandbox::InitializeLdrData() -> void { ldrData.Length = sizeof(X64_PEB_LDR_DATA); ldrData.Initialized = 1; - // ʼͷ - ʹʵת - LIST_ENTRY inLoadOrderList = { - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)), - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)) }; - ldrData.InLoadOrderModuleList = inLoadOrderList; + // ʼͷ - ÿͷָԼ() + uint64_t inLoadOrderListHead = ldrDataAddress + offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList); + uint64_t inMemoryOrderListHead = ldrDataAddress + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList); + uint64_t inInitOrderListHead = ldrDataAddress + offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList); - LIST_ENTRY inMemoryOrderList = { - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)), - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)) }; - ldrData.InMemoryOrderModuleList = inMemoryOrderList; + // ÿͷFlinkBlinkָԼ + ldrData.InLoadOrderModuleList.Flink = (LIST_ENTRY*)inLoadOrderListHead; + ldrData.InLoadOrderModuleList.Blink = (LIST_ENTRY*)inLoadOrderListHead; - LIST_ENTRY inInitOrderList = { - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)), - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)) }; - ldrData.InInitializationOrderModuleList = inInitOrderList; + ldrData.InMemoryOrderModuleList.Flink = (LIST_ENTRY*)inMemoryOrderListHead; + ldrData.InMemoryOrderModuleList.Blink = (LIST_ENTRY*)inMemoryOrderListHead; - uc_mem_write(m_ucEngine, ldrDataAddress, &ldrData, - sizeof(X64_PEB_LDR_DATA)); + ldrData.InInitializationOrderModuleList.Flink = (LIST_ENTRY*)inInitOrderListHead; + ldrData.InInitializationOrderModuleList.Blink = (LIST_ENTRY*)inInitOrderListHead; + + // дLDR_DATAṹڴ + uc_mem_write(m_ucEngine, ldrDataAddress, &ldrData, sizeof(X64_PEB_LDR_DATA)); // PEBеLdrָ uc_mem_write(m_ucEngine, m_pebBase, &m_peb64, sizeof(X64PEB)); } } - auto Sandbox::CreateLdrEntry(const std::shared_ptr& module, uint64_t entryAddress, uint64_t fullNameAddress, uint64_t baseNameAddress) -> LDR_DATA_TABLE_ENTRY { - LDR_DATA_TABLE_ENTRY entry = { 0 }; + + // ṹȷֶȷʼ + LDR_DATA_TABLE_ENTRY entry = {}; + if (LOG_LEVEL > 4) { + + // ģַ - nullָ + if (module->base == 0) { + printf("棺ģ'%s'ĻַΪ0ܵ\n", module->name); + } + } + entry.DllBase = reinterpret_cast(module->base); entry.EntryPoint = reinterpret_cast(module->base + module->entry); entry.SizeOfImages = static_cast(module->size); - // ׼ģƵUnicodeַ wchar_t nameBuffer[MAX_PATH] = { 0 }; - std::mbstowcs(nameBuffer, module->name, strlen(module->name)); + size_t convertedChars = 0; + std::string fakeFullName = "c:\\windows\\system32\\" + std::string(module->name); - // ȫ· - entry.FullDllName.Length = - static_cast(wcslen(nameBuffer) * sizeof(wchar_t)); + // ʹøȫmbstowcs_s + mbstowcs_s(&convertedChars, nameBuffer, MAX_PATH, fakeFullName.c_str(), fakeFullName.size()); + + // ֤תַ + size_t nameLen = wcslen(nameBuffer); + if (LOG_LEVEL > 4) { + + if (nameLen == 0 || nameLen >= MAX_PATH) { + printf("棺ģ'%s'ת⣬=%zu\n", module->name, nameLen); + } + } + // ַ + entry.FullDllName.Length = static_cast(nameLen * sizeof(wchar_t)); entry.FullDllName.MaximumLength = MAX_PATH * sizeof(wchar_t); entry.FullDllName.Buffer = reinterpret_cast(fullNameAddress); - // û - entry.BaseDllName.Length = - static_cast(wcslen(nameBuffer) * sizeof(wchar_t)); + entry.BaseDllName.Length = static_cast(nameLen * sizeof(wchar_t)); entry.BaseDllName.MaximumLength = MAX_PATH * sizeof(wchar_t); entry.BaseDllName.Buffer = reinterpret_cast(baseNameAddress); + if (LOG_LEVEL > 4) { + // дַ - ӵ + printf("DEBUG: дģ '%s' ַ 0x%llx 0x%llx\n", + module->name, fullNameAddress, baseNameAddress); + } + uc_mem_write(m_ucEngine, fullNameAddress, nameBuffer, (nameLen + 1) * sizeof(wchar_t)); + uc_mem_write(m_ucEngine, baseNameAddress, nameBuffer, (nameLen + 1) * sizeof(wchar_t)); - // дUnicodeַ - uc_mem_write(m_ucEngine, fullNameAddress, nameBuffer, - (wcslen(nameBuffer) + 1) * sizeof(wchar_t)); - uc_mem_write(m_ucEngine, baseNameAddress, nameBuffer, - (wcslen(nameBuffer) + 1) * sizeof(wchar_t)); + // ʼָΪNULLUpdateLdrLinksã + entry.InLoadOrderLinks.Flink = nullptr; + entry.InLoadOrderLinks.Blink = nullptr; + entry.InMemoryOrderLinks.Flink = nullptr; + entry.InMemoryOrderLinks.Blink = nullptr; + entry.InInitializationOrderLinks.Flink = nullptr; + entry.InInitializationOrderLinks.Blink = nullptr; return entry; } - auto Sandbox::UpdateLdrLinks(const LDR_DATA_TABLE_ENTRY& entry, - uint64_t entryAddress, X64_PEB_LDR_DATA& ldrData) - -> void { - // LDR_DATAеͷ - ldrData.InLoadOrderModuleList.Flink = reinterpret_cast( - entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InLoadOrderLinks)); - ldrData.InMemoryOrderModuleList.Flink = reinterpret_cast( - entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks)); - ldrData.InInitializationOrderModuleList.Flink = - reinterpret_cast( - entryAddress + - offsetof(LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks)); + uint64_t entryAddress, X64_PEB_LDR_DATA& ldrData) -> void { + // ȡͷַ + 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); - // дظºLDR_DATA - uc_mem_write(m_ucEngine, m_peb64.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA)); + // Ŀÿеĵַ + uint64_t entryInLoadOrder = entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + uint64_t entryInMemoryOrder = entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); + uint64_t entryInInitOrder = entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); + + LIST_ENTRY listHead; + LIST_ENTRY entryLinks; + + // InLoadOrderModuleList + uc_mem_read(m_ucEngine, inLoadOrderListHead, &listHead, sizeof(LIST_ENTRY)); + + // Ŀ (Ŀ뵽ͷ֮) + entryLinks.Flink = listHead.Flink; // ĿFlink = ԭͷFlink + entryLinks.Blink = (LIST_ENTRY*)inLoadOrderListHead; // ĿBlink = ͷ + uc_mem_write(m_ucEngine, entryInLoadOrder, &entryLinks, sizeof(LIST_ENTRY)); + + // ͷFlinkָĿ + listHead.Flink = (LIST_ENTRY*)entryInLoadOrder; + uc_mem_write(m_ucEngine, inLoadOrderListHead, &listHead, sizeof(LIST_ENTRY)); + + // ǿԭһڵBlink + if (entryLinks.Flink != (LIST_ENTRY*)inLoadOrderListHead) { + LIST_ENTRY nextEntry; + uc_mem_read(m_ucEngine, (uint64_t)entryLinks.Flink, &nextEntry, sizeof(LIST_ENTRY)); + nextEntry.Blink = (LIST_ENTRY*)entryInLoadOrder; + uc_mem_write(m_ucEngine, (uint64_t)entryLinks.Flink, &nextEntry, sizeof(LIST_ENTRY)); + } + + // ͬInMemoryOrderModuleList + uc_mem_read(m_ucEngine, inMemoryOrderListHead, &listHead, sizeof(LIST_ENTRY)); + entryLinks.Flink = listHead.Flink; + entryLinks.Blink = (LIST_ENTRY*)inMemoryOrderListHead; + uc_mem_write(m_ucEngine, entryInMemoryOrder, &entryLinks, sizeof(LIST_ENTRY)); + listHead.Flink = (LIST_ENTRY*)entryInMemoryOrder; + uc_mem_write(m_ucEngine, inMemoryOrderListHead, &listHead, sizeof(LIST_ENTRY)); + if (entryLinks.Flink != (LIST_ENTRY*)inMemoryOrderListHead) { + LIST_ENTRY nextEntry; + uc_mem_read(m_ucEngine, (uint64_t)entryLinks.Flink, &nextEntry, sizeof(LIST_ENTRY)); + nextEntry.Blink = (LIST_ENTRY*)entryInMemoryOrder; + uc_mem_write(m_ucEngine, (uint64_t)entryLinks.Flink, &nextEntry, sizeof(LIST_ENTRY)); + } + + // InInitializationOrderModuleList + uc_mem_read(m_ucEngine, inInitOrderListHead, &listHead, sizeof(LIST_ENTRY)); + entryLinks.Flink = listHead.Flink; + entryLinks.Blink = (LIST_ENTRY*)inInitOrderListHead; + uc_mem_write(m_ucEngine, entryInInitOrder, &entryLinks, sizeof(LIST_ENTRY)); + listHead.Flink = (LIST_ENTRY*)entryInInitOrder; + uc_mem_write(m_ucEngine, inInitOrderListHead, &listHead, sizeof(LIST_ENTRY)); + if (entryLinks.Flink != (LIST_ENTRY*)inInitOrderListHead) { + LIST_ENTRY nextEntry; + uc_mem_read(m_ucEngine, (uint64_t)entryLinks.Flink, &nextEntry, sizeof(LIST_ENTRY)); + nextEntry.Blink = (LIST_ENTRY*)entryInInitOrder; + uc_mem_write(m_ucEngine, (uint64_t)entryLinks.Flink, &nextEntry, sizeof(LIST_ENTRY)); + } } - -auto Sandbox::AddModuleToLdr(const std::shared_ptr& module) --> void { +auto Sandbox::AddModuleToLdr(const std::shared_ptr& module) -> void { if (!m_peInfo->isX64) { - return; // ʱֻ64λ + return; } - - if (m_peb64.Ldr == 0) { - InitializeLdrData(); + if (LOG_LEVEL > 4) { + // + printf("ģ: '%s', ַ: 0x%llx, ڵ: 0x%llx, С: 0x%llx\n", + module->name, module->base, module->entry, module->size); } + // ڴ + const size_t stringSectionSize = MAX_PATH * sizeof(wchar_t) * 2; + uint64_t entrySize = sizeof(LDR_DATA_TABLE_ENTRY) + stringSectionSize; - // Ϊģ鴴LDR_DATA_TABLE_ENTRY - uint64_t entrySize = sizeof(LDR_DATA_TABLE_ENTRY) + - MAX_PATH * 2; // ռUnicodeַ - uint64_t entryAddress = m_pebEnd; - m_pebEnd += entrySize; - + // ȷַ뵽8ֽڱ߽磨64λṹҪ + uint64_t entryAddress = (m_pebEnd + 7) & ~7ULL; + if (LOG_LEVEL > 4) { + // + printf("LDRĿ: ַ=0x%llx, С=0x%llx\n", entryAddress, entrySize); + } // ӳڴ - uc_mem_map(m_ucEngine, entryAddress, entrySize, UC_PROT_ALL); + const size_t pageSize = 4096; + size_t alignedSize = (entrySize + pageSize - 1) & ~(pageSize - 1); - // Unicodeַַ - uint64_t fullNameAddress = entryAddress + sizeof(LDR_DATA_TABLE_ENTRY); - uint64_t baseNameAddress = fullNameAddress + MAX_PATH; + uc_err err = uc_mem_map(m_ucEngine, entryAddress, alignedSize, UC_PROT_ALL); + if (err != UC_ERR_OK) { + if (LOG_LEVEL > 4) { + printf(": ޷ӳLDRĿڴ @ 0x%llx (=%d)\n", entryAddress, err); + } + return; + } - // ʼLDR_DATA_TABLE_ENTRY - auto entry = - CreateLdrEntry(module, entryAddress, fullNameAddress, baseNameAddress); + // Unicodeַַȷ8ֽڶ + uint64_t fullNameAddress = (entryAddress + sizeof(LDR_DATA_TABLE_ENTRY) + 7) & ~7ULL; + uint64_t baseNameAddress = (fullNameAddress + (MAX_PATH * sizeof(wchar_t)) + 7) & ~7ULL; + if (LOG_LEVEL > 4) { + // ַ֤Χ + printf(": ַַ - FullName=0x%llx, BaseName=0x%llx\n", + fullNameAddress, baseNameAddress); + } + // ȷַַڴ淶Χ + if (baseNameAddress + (MAX_PATH * sizeof(wchar_t)) > entryAddress + alignedSize) { + if (LOG_LEVEL > 4) { + printf(": ַڴ淶Χ!\n"); + } + return; + } + // LDRĿ + auto entry = CreateLdrEntry(module, entryAddress, fullNameAddress, baseNameAddress); + if (LOG_LEVEL > 4) { + + // ֤DllBaseȷ + if ((uint64_t)entry.DllBase != module->base) { + printf(": DllBaseƥ (=%llx, =%llx)\n", + (uint64_t)entry.DllBase, module->base); + } + } // PEBȡǰLDR_DATAṹ X64_PEB_LDR_DATA ldrData; uc_mem_read(m_ucEngine, m_peb64.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA)); - // ָ - entry.InLoadOrderLinks.Flink = reinterpret_cast( - reinterpret_cast(ldrData.InLoadOrderModuleList.Flink)); - entry.InLoadOrderLinks.Blink = reinterpret_cast( - m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)); - - entry.InMemoryOrderLinks.Flink = reinterpret_cast( - reinterpret_cast(ldrData.InMemoryOrderModuleList.Flink)); - entry.InMemoryOrderLinks.Blink = reinterpret_cast( - m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)); - - entry.InInitializationOrderLinks.Flink = - reinterpret_cast(reinterpret_cast( - ldrData.InInitializationOrderModuleList.Flink)); - entry.InInitializationOrderLinks.Blink = reinterpret_cast( - m_peb64.Ldr + - offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)); - // дLDR_DATA_TABLE_ENTRYṹ - uc_mem_write(m_ucEngine, entryAddress, &entry, - sizeof(LDR_DATA_TABLE_ENTRY)); + uc_mem_write(m_ucEngine, entryAddress, &entry, sizeof(LDR_DATA_TABLE_ENTRY)); // UpdateLdrLinks(entry, entryAddress, ldrData); - printf("Added module '%s' to LDR data tables at 0x%llx\n", module->name, - entryAddress); + // PEBβλ + m_pebEnd = entryAddress + alignedSize; + if (LOG_LEVEL > 4) { + + printf("ɹģ '%s' LDRݱ @ 0x%llx\n", module->name, entryAddress); + } } +auto Sandbox::TestLdrListTraversal() -> bool { + if (LOG_LEVEL > 4) { + + printf("\n============ LDR ============\n"); + + // 1. ȡPEBַ + uint64_t pebAddress = m_pebBase; // PEBַ + X64PEB peb; + if (uc_mem_read(m_ucEngine, pebAddress, &peb, sizeof(X64PEB)) != UC_ERR_OK) { + printf("ERROR: ޷ȡPEBṹ\n"); + return false; + } + + printf("PEBλ: 0x%llx\n", pebAddress); + printf("PEB.Ldrָ: 0x%llx\n", peb.Ldr); + + // 2. ȡLDR_DATAṹ + if (peb.Ldr == 0) { + printf("ERROR: PEB.LdrΪNULLLDRδʼ\n"); + return false; + } + + X64_PEB_LDR_DATA ldrData; + if (uc_mem_read(m_ucEngine, peb.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA)) != UC_ERR_OK) { + printf("ERROR: ޷ȡLDR_DATAṹ\n"); + return false; + } + + printf("LDR_DATA.Length: %u\n", ldrData.Length); + printf("LDR_DATA.Initialized: %u\n", ldrData.Initialized); + + // 3. 鲢ӡ + DumpLdrList("InLoadOrderModuleList", peb.Ldr, + offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList), + offsetof(LDR_DATA_TABLE_ENTRY, InLoadOrderLinks)); + + DumpLdrList("InMemoryOrderModuleList", peb.Ldr, + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList), + offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks)); + + DumpLdrList("InInitializationOrderModuleList", peb.Ldr, + offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList), + offsetof(LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks)); + + printf("========================================\n"); + } + return true; +} + +// ӡָLDR +auto Sandbox::DumpLdrList(const char* listName, uint64_t ldrDataBase, size_t listOffset, size_t entryLinkOffset) -> void { + if (LOG_LEVEL > 4) { + + printf("\n--- %s ---\n", listName); + + // ȡͷַ + uint64_t listHeadAddr = ldrDataBase + listOffset; + LIST_ENTRY listHead; + if (uc_mem_read(m_ucEngine, listHeadAddr, &listHead, sizeof(LIST_ENTRY)) != UC_ERR_OK) { + printf("ERROR: ޷ȡͷ @ 0x%llx\n", listHeadAddr); + return; + } + + printf("бͷ @ 0x%llx: Flink=0x%llx, Blink=0x%llx\n", + listHeadAddr, (uint64_t)listHead.Flink, (uint64_t)listHead.Blink); + + // ǷΪ + if (listHead.Flink == (LIST_ENTRY*)listHeadAddr) { + printf("Ϊ (Flinkָ)\n"); + return; + } + + // + uint64_t currentLink = (uint64_t)listHead.Flink; + int entryCount = 0; + + while (currentLink != listHeadAddr && entryCount < 100) { // ֹѭ + entryCount++; + + // 㵱ǰLDR_DATA_TABLE_ENTRYĵַ + uint64_t entryAddr = currentLink - entryLinkOffset; + + // ȡĿ + LDR_DATA_TABLE_ENTRY entry; + if (uc_mem_read(m_ucEngine, entryAddr, &entry, sizeof(LDR_DATA_TABLE_ENTRY)) != UC_ERR_OK) { + printf("ERROR: ޷ȡĿ @ 0x%llx\n", entryAddr); + break; + } + + printf("\nĿ #%d @ 0x%llx:\n", entryCount, entryAddr); + printf(" DllBase: 0x%llx\n", (uint64_t)entry.DllBase); + printf(" EntryPoint: 0x%llx\n", (uint64_t)entry.EntryPoint); + printf(" SizeOfImage: 0x%x\n", entry.SizeOfImages); + + // ȡʹӡģ + if ((uint64_t)entry.FullDllName.Buffer != 0 && entry.FullDllName.Length > 0) { + size_t nameLen = entry.FullDllName.Length / sizeof(wchar_t); + wchar_t* nameBuffer = new wchar_t[nameLen + 1]; + + if (uc_mem_read(m_ucEngine, (uint64_t)entry.FullDllName.Buffer, nameBuffer, entry.FullDllName.Length) == UC_ERR_OK) { + nameBuffer[nameLen] = L'\0'; + + // תΪֽ + char mbName[MAX_PATH * 2] = { 0 }; + wcstombs(mbName, nameBuffer, sizeof(mbName) - 1); + printf(" FullDllName: %s\n", mbName); + } + else { + printf(" ERROR: ޷ȡFullDllName @ 0x%llx (: %d)\n", + (uint64_t)entry.FullDllName.Buffer, entry.FullDllName.Length); + } + + delete[] nameBuffer; + } + else { + printf(" FullDllName: <ջЧ>\n"); + } + + // ͬӡBaseDllName + if ((uint64_t)entry.BaseDllName.Buffer != 0 && entry.BaseDllName.Length > 0) { + size_t nameLen = entry.BaseDllName.Length / sizeof(wchar_t); + wchar_t* nameBuffer = new wchar_t[nameLen + 1]; + + if (uc_mem_read(m_ucEngine, (uint64_t)entry.BaseDllName.Buffer, nameBuffer, entry.BaseDllName.Length) == UC_ERR_OK) { + nameBuffer[nameLen] = L'\0'; + + char mbName[MAX_PATH * 2] = { 0 }; + wcstombs(mbName, nameBuffer, sizeof(mbName) - 1); + printf(" BaseDllName: %s\n", mbName); + } + else { + printf(" ERROR: ޷ȡBaseDllName @ 0x%llx (: %d)\n", + (uint64_t)entry.BaseDllName.Buffer, entry.BaseDllName.Length); + } + + delete[] nameBuffer; + } + else { + printf(" BaseDllName: <ջЧ>\n"); + } + + // ָЧ + printf(" : Flink=0x%llx, Blink=0x%llx\n", + (uint64_t)entry.InLoadOrderLinks.Flink, (uint64_t)entry.InLoadOrderLinks.Blink); + + // ƶһĿ + // ѡȷFlinkֶ + if (listOffset == offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)) + currentLink = (uint64_t)entry.InLoadOrderLinks.Flink; + else if (listOffset == offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)) + currentLink = (uint64_t)entry.InMemoryOrderLinks.Flink; + else if (listOffset == offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)) + currentLink = (uint64_t)entry.InInitializationOrderLinks.Flink; + + // ڴ֤ - ֹЧָ + if (currentLink == 0 || currentLink == entryAddr) { + printf("ЧFlinkָ\n"); + break; + } + } + + if (entryCount == 0) { + printf("棺ûҵĿͷָʾǿ\n"); + } + else if (entryCount >= 100) { + printf("棺ܵѭṹ\n"); + } + else { + printf("\nܹҵ %d Ŀ\n", entryCount); + } + } +} \ No newline at end of file diff --git a/ai_anti_malware/sandbox_setupvm.cpp b/ai_anti_malware/sandbox_setupvm.cpp new file mode 100644 index 0000000..0c5aa6d --- /dev/null +++ b/ai_anti_malware/sandbox_setupvm.cpp @@ -0,0 +1,277 @@ +#include "sandbox.h" +auto Sandbox::BuildPebParameter() -> void { + //peb->ProcessParameters + // ý̲ + RTL_USER_PROCESS_PARAMETERS processParams = {}; + + // ӳ̲ṹڴ + size_t processParamsSize = AlignToSectionAlignment(sizeof(RTL_USER_PROCESS_PARAMETERS), PAGE_SIZE); + uc_err procErr = uc_mem_map(m_ucEngine, m_processParamsBase, processParamsSize, + UC_PROT_READ | UC_PROT_WRITE); + if (procErr != UC_ERR_OK) { + throw std::runtime_error("Failed to map process parameters block"); + } + + // û + processParams.MaximumLength = sizeof(RTL_USER_PROCESS_PARAMETERS); + processParams.Length = sizeof(RTL_USER_PROCESS_PARAMETERS); + + // ַַ + uint64_t stringBufferBase = m_processParamsBase + processParamsSize; + uint64_t currentStringPos = stringBufferBase; + + // ӳַ + size_t stringBufferSize = AlignToSectionAlignment(4096, PAGE_SIZE); // 㹻Ŀռ洢ַ + uc_mem_map(m_ucEngine, stringBufferBase, stringBufferSize, UC_PROT_READ | UC_PROT_WRITE); + + // ӳ· + std::wstring imagePath = L"C:\\Path\\To\\EmulatedImage.exe"; + UNICODE_STRING imagePathUnicode; + imagePathUnicode.Length = static_cast(imagePath.length() * sizeof(wchar_t)); + imagePathUnicode.MaximumLength = imagePathUnicode.Length + sizeof(wchar_t); // ռnullֹ + imagePathUnicode.Buffer = reinterpret_cast(currentStringPos); + + // дӳ·ַ + uc_mem_write(m_ucEngine, currentStringPos, imagePath.c_str(), imagePath.length() * sizeof(wchar_t) + sizeof(wchar_t)); + currentStringPos += AlignToSectionAlignment(imagePathUnicode.MaximumLength, 8); + + // + std::wstring commandLine = L"EmulatedImage.exe argument1 argument2"; + UNICODE_STRING commandLineUnicode; + commandLineUnicode.Length = static_cast(commandLine.length() * sizeof(wchar_t)); + commandLineUnicode.MaximumLength = commandLineUnicode.Length + sizeof(wchar_t); + commandLineUnicode.Buffer = reinterpret_cast(currentStringPos); + + // дַ + uc_mem_write(m_ucEngine, currentStringPos, commandLine.c_str(), commandLine.length() * sizeof(wchar_t) + sizeof(wchar_t)); + currentStringPos += AlignToSectionAlignment(commandLineUnicode.MaximumLength, 8); + + // õǰĿ¼ + std::wstring currentDir = L"C:\\Path\\To"; + UNICODE_STRING currentDirUnicode; + currentDirUnicode.Length = static_cast(currentDir.length() * sizeof(wchar_t)); + currentDirUnicode.MaximumLength = currentDirUnicode.Length + sizeof(wchar_t); + currentDirUnicode.Buffer = reinterpret_cast(currentStringPos); + + // д뵱ǰĿ¼ַ + uc_mem_write(m_ucEngine, currentStringPos, currentDir.c_str(), currentDir.length() * sizeof(wchar_t) + sizeof(wchar_t)); + currentStringPos += AlignToSectionAlignment(currentDirUnicode.MaximumLength, 8); + + // DLL· + std::wstring dllPath = L"C:\\Windows\\System32"; + UNICODE_STRING dllPathUnicode; + dllPathUnicode.Length = static_cast(dllPath.length() * sizeof(wchar_t)); + dllPathUnicode.MaximumLength = dllPathUnicode.Length + sizeof(wchar_t); + dllPathUnicode.Buffer = reinterpret_cast(currentStringPos); + + // дDLL·ַ + uc_mem_write(m_ucEngine, currentStringPos, dllPath.c_str(), dllPath.length() * sizeof(wchar_t) + sizeof(wchar_t)); + + // ý̲ṹеֶַ + processParams.ImagePathName = imagePathUnicode; + processParams.CommandLine = commandLineUnicode; + processParams.CurrentDirectory.DosPath = currentDirUnicode; + processParams.DllPath = dllPathUnicode; + processParams.Environment = reinterpret_cast(m_envBlockBase); + + // д̲ṹ + uc_mem_write(m_ucEngine, m_processParamsBase, &processParams, sizeof(RTL_USER_PROCESS_PARAMETERS)); + +} +auto Sandbox::SetupVirtualMachine() -> void { + SegmentSelector cs = { 0 }; + cs.fields.index = 1; + uc_reg_write(m_ucEngine, UC_X86_REG_CS, &cs.all); + + SegmentSelector ds = { 0 }; + ds.fields.index = 2; + uc_reg_write(m_ucEngine, UC_X86_REG_DS, &ds.all); + + SegmentSelector ss = { 0 }; + ss.fields.index = 2; + uc_reg_write(m_ucEngine, UC_X86_REG_SS, &ss.all); + + SegmentSelector es = { 0 }; + es.fields.index = 2; + uc_reg_write(m_ucEngine, UC_X86_REG_ES, &es.all); + + SegmentSelector gs = { 0 }; + gs.fields.index = 2; + uc_reg_write(m_ucEngine, UC_X86_REG_GS, &gs.all); + + FlagRegister eflags = { 0 }; + eflags.fields.id = 1; + eflags.fields.intf = 1; + eflags.fields.reserved1 = 1; + + uc_reg_write(m_ucEngine, UC_X86_REG_EFLAGS, &eflags.all); + + uint64_t cr8 = 0; + uc_reg_write(m_ucEngine, UC_X86_REG_CR8, &cr8); + + /* + ӳ m_KSharedUserDataBase + */ + m_KSharedUserDataBase = 0x7FFE0000; + uint64_t m_KSharedUserDataEnd = 0x7FFE0FFF; // 0x7FFE2000 + m_KSharedUserDataSize = AlignToSectionAlignment( + m_KSharedUserDataEnd - m_KSharedUserDataBase, PAGE_SIZE); + + uc_mem_map(m_ucEngine, m_KSharedUserDataBase, m_KSharedUserDataSize, + UC_PROT_READ); + uc_mem_write(m_ucEngine, m_KSharedUserDataBase, + (void*)m_KSharedUserDataBase, m_KSharedUserDataSize); + + m_tebBase = TEB_BASE; // TEBַ + m_pebBase = PEB_BASE; // PEBַ + m_envBlockBase = ENV_BLOCK_BASE; // ַ + m_processParamsBase = PROCESS_PARAMS_BASE; // ַ̲ + + // stack + m_stackBase = AlignToSectionAlignment( + this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32, 16); + m_stackSize = AlignToSectionAlignment( + this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32, 16); + m_stackEnd = m_stackBase + m_stackSize; + + // heap + m_heapBase = this->m_peInfo->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32; + m_heapSize = this->m_peInfo->isX64 ? HEAP_SIZE_64 : HEAP_SIZE_32; + m_heapEnd = m_heapBase + m_heapSize; + + BuildPebParameter(); + InitializeLdrData(); + + // PEļPEBTEB + if (this->m_peInfo->isX64) { + // 64λPEB + m_peb64.ImageBaseAddress = m_peInfo->RecImageBase; + m_pebEnd = + m_pebBase + AlignToSectionAlignment(sizeof(X64PEB), PAGE_SIZE); + m_tebEnd = + m_tebBase + AlignToSectionAlignment(sizeof(X64TEB), PAGE_SIZE); + + // 64λTEB + m_teb64.ClientId.UniqueProcess = GetCurrentProcessId(); + m_teb64.ClientId.UniqueThread = GetCurrentThreadId(); + m_teb64.ProcessEnvironmentBlock = reinterpret_cast(m_pebBase); + m_teb64.NtTib.StackBase = (DWORD64)m_stackBase; + m_teb64.NtTib.StackLimit = (DWORD64)m_stackSize; + m_peb64.ProcessParameters = m_processParamsBase; + + // ö + m_peb64.ProcessHeap = m_heapBase; + + // GSַṹ + m_gsBaseStruct.teb = m_tebBase; + m_gsBaseStruct.peb = m_pebBase; + uint64_t gsAllocSize = + AlignToSectionAlignment(sizeof(struct_gs_base), PAGE_SIZE); + + // ӳPEBڴ + uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase, + UC_PROT_READ | UC_PROT_WRITE); + uc_mem_write(m_ucEngine, m_pebBase, &m_peb64, sizeof(X64PEB)); + + // ӳTEBڴ + uc_mem_map(m_ucEngine, m_tebBase, m_tebEnd - m_tebBase, + UC_PROT_READ | UC_PROT_WRITE); + uc_mem_write(m_ucEngine, m_tebBase, &m_teb64, sizeof(X64TEB)); + + // ӳGSַṹڴ + uc_mem_map(m_ucEngine, m_gsBase, gsAllocSize, UC_PROT_READ); + uc_mem_write(m_ucEngine, m_gsBase, &m_gsBaseStruct, + sizeof(struct_gs_base)); + + // GSַMSR + uc_x86_msr msr; + msr.rid = static_cast(Msr::kIa32GsBase); + msr.value = m_gsBase; + uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr); + } + else { + // 32λPEB + m_peb32.ImageBaseAddress = static_cast(m_peInfo->RecImageBase); + m_pebEnd = + m_pebBase + AlignToSectionAlignment(sizeof(X32PEB), PAGE_SIZE); + m_tebEnd = + m_tebBase + AlignToSectionAlignment(sizeof(X32TEB), PAGE_SIZE); + + // 32λTEB + m_teb32.ClientId.UniqueProcess = GetCurrentProcessId(); + m_teb32.ClientId.UniqueThread = GetCurrentThreadId(); + 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.ProcessParameters = m_processParamsBase; + + // ö + m_peb32.ProcessHeap = static_cast(m_heapBase); + + // ӳPEBڴ + uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase, + UC_PROT_READ | UC_PROT_WRITE); + uc_mem_write(m_ucEngine, m_pebBase, &m_peb32, sizeof(X32PEB)); + + // ӳTEBڴ + uc_mem_map(m_ucEngine, m_tebBase, m_tebEnd - m_tebBase, + UC_PROT_READ | UC_PROT_WRITE); + uc_mem_write(m_ucEngine, m_tebBase, &m_teb32, sizeof(X32TEB)); + + // 32λҪFSμĴָTEB + SegmentSelector fs = { 0 }; + fs.fields.index = 3; + // ҪpresentdplΪSegmentSelectorṹûЩֶ + uc_reg_write(m_ucEngine, UC_X86_REG_FS, &fs.all); + + // FSַMSR + uc_x86_msr msr; + 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.hX32TEB壬ƫ0x18SelfTeb + uint32_t self_teb_ptr = static_cast(m_tebBase); + // NT_TIBSelfTeb (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); + // ƫ0x30ProcessEnvironmentBlock + uc_mem_write(m_ucEngine, m_tebBase + 0x30, &peb_ptr, sizeof(uint32_t)); + } + // ӳµڴ + size_t envSize = + AlignToSectionAlignment(this->GetEnvStringsSize(), PAGE_SIZE); + printf("env block size: %llx\n", envSize); // ӵ + uc_err envErr = uc_mem_map(m_ucEngine, m_envBlockBase, envSize, + UC_PROT_READ | UC_PROT_WRITE); + if (envErr != UC_ERR_OK) { + throw std::runtime_error("Failed to map environment block"); + } + + auto envData = this->GetEnvString(); + envErr = uc_mem_write(m_ucEngine, m_envBlockBase, envData.data(), + envData.size() * sizeof(wchar_t)); + if (envErr != UC_ERR_OK) { + throw std::runtime_error("Failed to write environment block"); + } + + for (DWORD i = 0; i < 64; i++) { + GetTeb64()->TlsSlots[i] = (void*)0x1337ffffff; + } + for (DWORD i = 0; i < 64; i++) { + GetTeb32()->TlsSlots[i] = 0x1337; + } + +} \ No newline at end of file