diff --git a/ai_anti_malware/ai_anti_malware.vcxproj b/ai_anti_malware/ai_anti_malware.vcxproj index 62fb2fa..013b624 100644 --- a/ai_anti_malware/ai_anti_malware.vcxproj +++ b/ai_anti_malware/ai_anti_malware.vcxproj @@ -23,7 +23,7 @@ Win32Proj {e12c93d6-6150-484d-85e1-7a644e393d5a} aiantimalware - 10.0 + 10.0.19041.0 @@ -180,11 +180,14 @@ + + + diff --git a/ai_anti_malware/ai_anti_malware.vcxproj.filters b/ai_anti_malware/ai_anti_malware.vcxproj.filters index b1a4695..1592437 100644 --- a/ai_anti_malware/ai_anti_malware.vcxproj.filters +++ b/ai_anti_malware/ai_anti_malware.vcxproj.filters @@ -159,6 +159,15 @@ 源文件\sandbox\apis + + 源文件\sandbox + + + 源文件\sandbox + + + 源文件\sandbox + diff --git a/ai_anti_malware/head.h b/ai_anti_malware/head.h index 0cc949c..09b0d16 100644 --- a/ai_anti_malware/head.h +++ b/ai_anti_malware/head.h @@ -32,6 +32,12 @@ struct BasicPeInfo { PIMAGE_NT_HEADERS ntHead64; PIMAGE_NT_HEADERS32 ntHead32; bool isDll; + ~BasicPeInfo() { + if (peBuffer != nullptr) { + peconv::free_pe_buffer(peBuffer); + peBuffer = nullptr; + } + } }; #include "sandbox.h" #include "ml.h" \ No newline at end of file diff --git a/ai_anti_malware/libpeconv/libpeconv/src/file_util.cpp b/ai_anti_malware/libpeconv/libpeconv/src/file_util.cpp index 68aecca..b13f72b 100644 --- a/ai_anti_malware/libpeconv/libpeconv/src/file_util.cpp +++ b/ai_anti_malware/libpeconv/libpeconv/src/file_util.cpp @@ -5,59 +5,109 @@ #ifdef _DEBUG #include #endif +typedef LPVOID(WINAPI* PFN_MapViewOfFile)( + HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + SIZE_T dwNumberOfBytesToMap + ); +#include +#include -//load file content using MapViewOfFile -peconv::ALIGNED_BUF peconv::load_file(IN const char *filename, OUT size_t &read_size) -{ - HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if(file == INVALID_HANDLE_VALUE) { -#ifdef _DEBUG - std::cerr << "Could not open file!" << std::endl; -#endif - return nullptr; - } - HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0); - if (!mapping) { -#ifdef _DEBUG - std::cerr << "Could not create mapping!" << std::endl; -#endif - CloseHandle(file); - return nullptr; - } - BYTE *dllRawData = (BYTE*) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); - if (!dllRawData) { -#ifdef _DEBUG - std::cerr << "Could not map view of file" << std::endl; -#endif - CloseHandle(mapping); - CloseHandle(file); - return nullptr; - } - size_t r_size = GetFileSize(file, 0); - if (read_size != 0 && read_size <= r_size) { - r_size = read_size; - } - if (IsBadReadPtr(dllRawData, r_size)) { - std::cerr << "[-] Mapping of " << filename << " is invalid!" << std::endl; - UnmapViewOfFile(dllRawData); - CloseHandle(mapping); - CloseHandle(file); - return nullptr; - } - peconv::ALIGNED_BUF localCopyAddress = peconv::alloc_aligned(r_size, PAGE_READWRITE); - if (localCopyAddress != nullptr) { - memcpy(localCopyAddress, dllRawData, r_size); - read_size = r_size; - } else { +typedef LPVOID(WINAPI* PFN_MapViewOfFile)( + HANDLE, + DWORD, + DWORD, + DWORD, + SIZE_T + ); +typedef BOOL(WINAPI* PFN_UnmapViewOfFile)(LPCVOID); +typedef DWORD(WINAPI* PFN_GetFileSize)(HANDLE, LPDWORD); + +namespace peconv { + ALIGNED_BUF load_file(IN const char* filename, OUT size_t& read_size) + { read_size = 0; + + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { #ifdef _DEBUG - std::cerr << "Could not allocate memory in the current process" << std::endl; + std::cerr << "[-] Could not open file: " << filename << std::endl; #endif + return nullptr; + } + + HANDLE hMapping = CreateFileMappingA(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr); + if (!hMapping) { +#ifdef _DEBUG + std::cerr << "[-] Could not create file mapping!" << std::endl; +#endif + CloseHandle(hFile); + return nullptr; + } + + HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); + if (!hKernel32) { +#ifdef _DEBUG + std::cerr << "[-] Could not get handle to kernel32.dll" << std::endl; +#endif + CloseHandle(hMapping); + CloseHandle(hFile); + return nullptr; + } + + PFN_MapViewOfFile pMapViewOfFile = (PFN_MapViewOfFile)GetProcAddress(hKernel32, "MapViewOfFile"); + PFN_UnmapViewOfFile pUnmapViewOfFile = (PFN_UnmapViewOfFile)GetProcAddress(hKernel32, "UnmapViewOfFile"); + PFN_GetFileSize pGetFileSize = (PFN_GetFileSize)GetProcAddress(hKernel32, "GetFileSize"); + + if (!pMapViewOfFile || !pUnmapViewOfFile || !pGetFileSize) { +#ifdef _DEBUG + std::cerr << "[-] Could not get required API functions from kernel32.dll" << std::endl; +#endif + CloseHandle(hMapping); + CloseHandle(hFile); + return nullptr; + } + + BYTE* dllRawData = (BYTE*)pMapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + if (!dllRawData) { +#ifdef _DEBUG + std::cerr << "[-] Failed to map view of file" << std::endl; +#endif + CloseHandle(hMapping); + CloseHandle(hFile); + return nullptr; + } + + size_t fileSize = pGetFileSize(hFile, nullptr); + size_t toReadSize = (read_size != 0 && read_size <= fileSize) ? read_size : fileSize; + + if (IsBadReadPtr(dllRawData, toReadSize)) { +#ifdef _DEBUG + std::cerr << "[-] Mapped memory is invalid: " << filename << std::endl; +#endif + pUnmapViewOfFile(dllRawData); + CloseHandle(hMapping); + CloseHandle(hFile); + } + ALIGNED_BUF localCopy = peconv::alloc_aligned(toReadSize, PAGE_READWRITE); + if (localCopy) { + memcpy(localCopy, dllRawData, toReadSize); + read_size = toReadSize; + } + else { +#ifdef _DEBUG + std::cerr << "[-] Failed to allocate memory in current process" << std::endl; +#endif + read_size = 0; + } + + pUnmapViewOfFile(dllRawData); + CloseHandle(hMapping); + CloseHandle(hFile); + return localCopy; } - UnmapViewOfFile(dllRawData); - CloseHandle(mapping); - CloseHandle(file); - return localCopyAddress; } //load file content using ReadFile diff --git a/ai_anti_malware/ml.h b/ai_anti_malware/ml.h index 9989264..1e2f1a1 100644 --- a/ai_anti_malware/ml.h +++ b/ai_anti_malware/ml.h @@ -14,7 +14,7 @@ // 前向声明 struct PeInfo; struct SectionInfo; -class BasicPeInfo; +struct BasicPeInfo; struct RichEntry { uint16_t productId; // 组件ID uint16_t buildId; // 版本号 diff --git a/ai_anti_malware/native_struct.h b/ai_anti_malware/native_struct.h index b3de3ec..ab6abbd 100644 --- a/ai_anti_malware/native_struct.h +++ b/ai_anti_malware/native_struct.h @@ -1024,6 +1024,9 @@ struct struct_moudle { uint64_t base; uint64_t size; uint64_t real_base; + uint64_t mapped_address; + uint64_t mapped_size; + std::vector> import_function; std::vector> export_function; std::vector> sections; diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index e6d4592..6e7c1bf 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -1,7 +1,6 @@ #include "sandbox.h" #include "sandbox_callbacks.h" #include "sandbox_api_com.h" - // 在文件开头添加AllocateMemory函数的声明 auto Sandbox::AllocateMemory(size_t size) -> uint64_t { // 使用一个简单的内存分配策略 @@ -24,71 +23,8 @@ auto Sandbox::AllocateMemory(size_t size) -> uint64_t { return allocated_address; } -std::string getDllNameFromApiSetMap(const std::string& apiSet) { - const std::wstring wApiSet(apiSet.begin(), apiSet.end()); - - // 获取系统版本信息 - using RtlGetVersionFunc = LONG(__stdcall*)(PRTL_OSVERSIONINFOW); - const auto pRtlGetVersion = reinterpret_cast( - GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion")); - - RTL_OSVERSIONINFOEXW verInfo{}; - verInfo.dwOSVersionInfoSize = sizeof(verInfo); - pRtlGetVersion(reinterpret_cast(&verInfo)); - - const ULONG verShort = (verInfo.dwMajorVersion << 8) | - (verInfo.dwMinorVersion << 4) | - verInfo.wServicePackMajor; - - if (verShort >= static_cast(WinVer::kWin10)) { - const auto apiSetMap = reinterpret_cast( - reinterpret_cast(__readgsqword(0x60))->ApiSetMap); - const auto apiSetMapAsNumber = reinterpret_cast(apiSetMap); - auto nsEntry = reinterpret_cast( - apiSetMap->Start + apiSetMapAsNumber); - - // 遍历API集合查找匹配项 - for (ULONG i = 0; i < apiSetMap->Count; i++) { - UNICODE_STRING nameString{}, valueString{}; - nameString.MaximumLength = static_cast(nsEntry->NameLength); - nameString.Length = static_cast(nsEntry->NameLength); - nameString.Buffer = reinterpret_cast(apiSetMapAsNumber + - nsEntry->NameOffset); - - const std::wstring name(nameString.Buffer, - nameString.Length / sizeof(WCHAR)); - const std::wstring fullName = name + L".dll"; - - if (_wcsicmp(wApiSet.c_str(), fullName.c_str()) == 0) { - if (nsEntry->ValueCount == 0) { - return ""; - } - - const auto valueEntry = - reinterpret_cast( - apiSetMapAsNumber + nsEntry->ValueOffset); - valueString.Buffer = reinterpret_cast( - apiSetMapAsNumber + valueEntry->ValueOffset); - valueString.MaximumLength = - static_cast(valueEntry->ValueLength); - valueString.Length = - static_cast(valueEntry->ValueLength); - - const std::wstring value(valueString.Buffer, - valueString.Length / sizeof(WCHAR)); - return {value.begin(), value.end()}; - } - ++nsEntry; - } - } else { - // 不支持Windows 10以下版本 - throw std::runtime_error("Unsupported Windows version"); - } - return ""; -} - class ImportResolver : public peconv::t_function_resolver { - public: +public: explicit ImportResolver(std::map context) : _functionMap(std::move(context)) {} @@ -96,22 +32,22 @@ class ImportResolver : public peconv::t_function_resolver { return reinterpret_cast(_functionMap[std::string(funcName)]); } - private: +private: std::map _functionMap; }; class cListImportNames : public peconv::ImportThunksCallback { - public: +public: cListImportNames( BYTE* _modulePtr, size_t _moduleSize, std::vector>& name_to_addr, std::vector>& name_to_ordinal) : ImportThunksCallback(_modulePtr, _moduleSize), - nameToAddr(name_to_addr), - ordinalImportFunc(name_to_ordinal) {} + nameToAddr(name_to_addr), + ordinalImportFunc(name_to_ordinal) {} virtual bool processThunks(LPSTR lib_name, ULONG_PTR origFirstThunkPtr, - ULONG_PTR firstThunkPtr) { + ULONG_PTR firstThunkPtr) { if (this->is64b) { IMAGE_THUNK_DATA64* desc = reinterpret_cast(origFirstThunkPtr); @@ -126,17 +62,17 @@ class cListImportNames : public peconv::ImportThunksCallback { lib_name, desc, call_via, IMAGE_ORDINAL_FLAG32); } - protected: +protected: template bool processThunks_tpl(LPSTR lib_name, T_IMAGE_THUNK_DATA* desc, - T_FIELD* call_via, T_FIELD ordinal_flag) { + T_FIELD* call_via, T_FIELD ordinal_flag) { DWORD call_via_rva = static_cast((ULONG_PTR)call_via - - (ULONG_PTR)this->modulePtr); + (ULONG_PTR)this->modulePtr); LPSTR func_name = NULL; if ((desc->u1.Ordinal & ordinal_flag) == 0) { PIMAGE_IMPORT_BY_NAME by_name = (PIMAGE_IMPORT_BY_NAME)((ULONGLONG)modulePtr + - desc->u1.AddressOfData); + desc->u1.AddressOfData); func_name = reinterpret_cast(by_name->Name); std::string fuck_up_api_ms = lib_name; if (fuck_up_api_ms.find("api-ms-") != std::string::npos) { @@ -146,11 +82,12 @@ class cListImportNames : public peconv::ImportThunksCallback { auto import_data = std::make_shared(); memcpy(import_data->name, func_name, strlen(func_name)); memcpy(import_data->dll_name, fuck_up_api_ms.c_str(), - fuck_up_api_ms.size()); + fuck_up_api_ms.size()); import_data->function_address = call_via_rva; import_data->is_delayed_import = false; nameToAddr.push_back(import_data); - } else { + } + else { auto importFunc = std::make_shared(); T_FIELD raw_ordinal = desc->u1.Ordinal & (~ordinal_flag); importFunc->dll_name = lib_name; @@ -165,7 +102,7 @@ class cListImportNames : public peconv::ImportThunksCallback { std::vector>& ordinalImportFunc; }; class cFixImprot : public peconv::t_function_resolver { - public: +public: // 构造函数接收Sandbox实例的引用 explicit cFixImprot(Sandbox* sandbox) : m_sandbox(sandbox) {} @@ -200,7 +137,7 @@ class cFixImprot : public peconv::t_function_resolver { if (strcmp(exp->name, func_name) == 0) { #ifdef LOG_LEVEL > 1 printf("fix import (fallback): %s found in %s => %llx \n", - func_name, module->name, newBase); + func_name, module->name, newBase); // 返回在模拟器中的虚拟地址 #endif return newBase; @@ -225,12 +162,12 @@ class cFixImprot : public peconv::t_function_resolver { } printf("Warning: Could not resolve import: %s from library: %s\n", - func_name, lib_name); + func_name, lib_name); //__debugbreak(); return nullptr; } - private: +private: Sandbox* m_sandbox; // Sandbox实例的指针 }; Sandbox::Sandbox() { @@ -272,6 +209,13 @@ Sandbox::~Sandbox() { delete segment; } m_heapSegments.clear(); + // 4. 清理模块 + for (auto module : m_moduleList) { + //为0的是主程序. + if (module->mapped_address != 0) { + peconv::free_pe_buffer((peconv::ALIGNED_BUF)module.get()->mapped_address, module.get()->mapped_size); + } + } // 5. 最后清理底层资源 if (m_csHandle) { @@ -279,7 +223,7 @@ Sandbox::~Sandbox() { } } -auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void { +auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase, uint64_t mappedSize) -> void { for (auto module : m_moduleList) { if (module->real_base == moduleBase) { printf("skip module name: %s (already loaded)\n", module->name); @@ -310,6 +254,8 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void { newModule->base) == false) { throw std::runtime_error("Failed to relocate module"); } + newModule->mapped_address = moduleBase; + newModule->mapped_size = mappedSize; // 将模块添加到LDR链表中 if (m_peInfo->isX64) { @@ -479,7 +425,7 @@ auto Sandbox::mapSystemModuleToVmByName(std::string systemName) -> void { } // 添加到虚拟机 - PushModuleToVM(systemName.c_str(), moduleBase); + PushModuleToVM(systemName.c_str(), moduleBase, mappedPeSize); } auto Sandbox::processImportModule(const moudle_import* importModule) -> void { @@ -995,465 +941,3 @@ auto Sandbox::getVirtualMemorySize(BYTE* peBuffer) -> size_t { return static_cast(totalSize); } - -auto Sandbox::DumpPE() -> std::pair, size_t> { - // 查找目标模块 - 这里我们使用主模块(通常是被分析的可执行文件) - std::shared_ptr targetModule = nullptr; - for (const auto& module : m_moduleList) { - if (strcmp(module->name, "huoji.exe") == 0) { - targetModule = module; - break; - } - } - - if (!targetModule) { - throw std::runtime_error("No modules found to dump"); - } - - // 计算虚拟内存大小 - auto virtualMemorySize = getVirtualMemorySize(m_peInfo->peBuffer); - - // 创建用于存储转储数据的缓冲区 - auto resultBuffer = std::make_unique(virtualMemorySize); - - // 从虚拟机内存中读取PE文件 - uc_err err = uc_mem_read(m_ucEngine, m_peInfo->RecImageBase, - resultBuffer.get(), virtualMemorySize); - if (err != UC_ERR_OK) { - throw std::runtime_error("Failed to read memory during PE dump: " + - std::string(uc_strerror(err))); - } - - // 确保PE头部的签名有效 - auto* dosHeader = reinterpret_cast(resultBuffer.get()); - if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { - throw std::runtime_error("Invalid DOS signature in dumped PE"); - } - - auto* ntHeaders = reinterpret_cast(resultBuffer.get() + - dosHeader->e_lfanew); - if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { - throw std::runtime_error("Invalid NT signature in dumped PE"); - } - - // 获取当前RIP/EIP作为新的入口点 - uint64_t currentEntryPoint = 0; - if (this->GetCrossSectionExecution().size() > 0) { - currentEntryPoint = this->GetCrossSectionExecution() - [this->GetCrossSectionExecution().size() - 1] - - m_peInfo->RecImageBase; - } - - PIMAGE_SECTION_HEADER sectionHeaders = nullptr; - WORD numberOfSections = 0; - - // 处理32位或64位PE文件 - if (m_peInfo->isX64) { - auto* optHeader64 = - &reinterpret_cast(ntHeaders)->OptionalHeader; - optHeader64->ImageBase = m_peInfo->RecImageBase; - if (currentEntryPoint != 0) { - // 修改入口点为当前执行位置 - optHeader64->AddressOfEntryPoint = - static_cast(currentEntryPoint); - } - - // 修改SizeOfImage - optHeader64->SizeOfImage = static_cast(AlignToSectionAlignment( - virtualMemorySize, optHeader64->SectionAlignment)); - - // 修改DllCharacteristics以移除ASLR标记 - optHeader64->DllCharacteristics &= - ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; - - // 获取区段头信息 - sectionHeaders = reinterpret_cast( - reinterpret_cast(ntHeaders) + - sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) + - ntHeaders->FileHeader.SizeOfOptionalHeader); - numberOfSections = ntHeaders->FileHeader.NumberOfSections; - } else { - auto* optHeader32 = - &reinterpret_cast(ntHeaders)->OptionalHeader; - optHeader32->ImageBase = static_cast(m_peInfo->RecImageBase); - - if (currentEntryPoint != 0) { - // 修改入口点为当前执行位置 - optHeader32->AddressOfEntryPoint = - static_cast(currentEntryPoint); - } - - // 修改SizeOfImage - optHeader32->SizeOfImage = static_cast(AlignToSectionAlignment( - virtualMemorySize, optHeader32->SectionAlignment)); - - // 修改DllCharacteristics以移除ASLR标记 - optHeader32->DllCharacteristics &= - ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; - - // 获取区段头信息 - sectionHeaders = reinterpret_cast( - reinterpret_cast(ntHeaders) + - sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) + - ntHeaders->FileHeader.SizeOfOptionalHeader); - numberOfSections = ntHeaders->FileHeader.NumberOfSections; - } - - // 更新代码基址和大小 - UpdateBaseOfCode(sectionHeaders, ntHeaders, numberOfSections, - static_cast(currentEntryPoint)); - - // 修复区段 - FixSections(sectionHeaders, numberOfSections, virtualMemorySize); - - // 创建一个ExportsMapper对象用于导入表修复 - peconv::ExportsMapper exportsMap; - - // 添加所有已加载模块到导出表映射中 - for (const auto& module : m_moduleList) { - if (module->base == 0 || module->size == 0) { - continue; - } - - // 创建临时缓冲区以存储模块内容 - std::unique_ptr moduleBuffer = - std::make_unique(module->size); - - // 从虚拟机内存读取模块内容 - uc_err readErr = uc_mem_read(m_ucEngine, module->base, - moduleBuffer.get(), module->size); - if (readErr != UC_ERR_OK) { - printf( - "Warning: Could not read module %s for exports mapping: %s\n", - module->name, uc_strerror(readErr)); - continue; - } - - // 添加模块到导出表映射 - exportsMap.add_to_lookup(module->name, - reinterpret_cast(moduleBuffer.get()), - module->base); - } - // 这里有一个严重的问题,就懒得处理了: - // 壳里面吐出来的代码的导入表和壳的导入表不是同样一个. - // 这个修的是壳的 导入表,所以导入表 修 不 全 - // 有个很简单的办法,需要搜索IAT结构,然后修改脱壳后的IAT的字段到壳的字段里面,然后再执行一次fix_imports - // 懒得写了,家庭作业.自己完成 - bool importsFixed = peconv::fix_imports( - resultBuffer.get(), virtualMemorySize, exportsMap, nullptr); - if (importsFixed) { - printf("PE file imports fixed successfully\n"); - } else { - printf("Warning: Failed to fix PE file imports\n"); - } - - size_t out_size = 0; - - // 重新计算校验和 - if (m_peInfo->isX64) { - auto* optHeader64 = - &reinterpret_cast(ntHeaders)->OptionalHeader; - optHeader64->CheckSum = - CalculateChecksum(resultBuffer.get(), virtualMemorySize); - } else { - auto* optHeader32 = - &reinterpret_cast(ntHeaders)->OptionalHeader; - optHeader32->CheckSum = - CalculateChecksum(resultBuffer.get(), virtualMemorySize); - } - - printf( - "PE file dumped successfully from address: 0x%llx, size: %zu bytes\n", - m_peInfo->RecImageBase, virtualMemorySize); - printf("Entry point set to: 0x%llx (RVA: 0x%llx)\n", - m_peInfo->RecImageBase + currentEntryPoint, currentEntryPoint); - - return {std::move(resultBuffer), virtualMemorySize}; -} - -// 修复区段信息 -void Sandbox::FixSections(PIMAGE_SECTION_HEADER sectionHeaders, - WORD numberOfSections, size_t virtualMemorySize) { - if (numberOfSections == 0 || sectionHeaders == nullptr) { - return; - } - - // 修复每个区段的信息 - for (WORD i = 0; i < numberOfSections - 1; i++) { - auto& currentSection = sectionHeaders[i]; - auto& nextSection = sectionHeaders[i + 1]; - - // 修复大小,使之与下一个区段的起始地址对齐 - currentSection.SizeOfRawData = - nextSection.VirtualAddress - currentSection.VirtualAddress; - currentSection.PointerToRawData = currentSection.VirtualAddress; - currentSection.Misc.VirtualSize = currentSection.SizeOfRawData; - } - - // 修复最后一个区段 - auto& lastSection = sectionHeaders[numberOfSections - 1]; - lastSection.SizeOfRawData = - static_cast(virtualMemorySize) - lastSection.VirtualAddress; - lastSection.PointerToRawData = lastSection.VirtualAddress; - lastSection.Misc.VirtualSize = lastSection.SizeOfRawData; -} - -// 计算校验和 -DWORD Sandbox::CalculateChecksum(const BYTE* peBuffer, size_t size) { - DWORD sum = 0; - const DWORD* ptr = reinterpret_cast(peBuffer); - const DWORD count = static_cast(size / sizeof(DWORD)); - - // 获取校验和字段的偏移 - const auto dosHeader = (PIMAGE_DOS_HEADER)(peBuffer); - const auto ntHeaders = (PIMAGE_NT_HEADERS)(peBuffer + dosHeader->e_lfanew); - DWORD checksumOffset = dosHeader->e_lfanew + - FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + - FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum); - - // 计算总和,跳过校验和字段本身 - for (DWORD i = 0; i < count; i++) { - // 跳过校验和字段 - if ((i * sizeof(DWORD)) == checksumOffset || - (i * sizeof(DWORD)) == checksumOffset + sizeof(DWORD) - 1) { - continue; - } - sum += ptr[i]; - // 处理溢出 - if (sum < ptr[i]) { - sum++; - } - } - - // 完成计算 - sum = (sum & 0xFFFF) + (sum >> 16); - sum = (sum & 0xFFFF) + (sum >> 16); - sum = sum + static_cast(size); - - return sum; -} - -// 按区段对齐大小进行对齐 -DWORD Sandbox::AlignToSectionAlignment(size_t size, DWORD alignment) { - return static_cast(((size + alignment - 1) / alignment) * alignment); -} - -// 更新代码基址和代码大小 -void Sandbox::UpdateBaseOfCode(PIMAGE_SECTION_HEADER sectionHeader, - PIMAGE_NT_HEADERS ntHeaders, - WORD numberOfSections, DWORD entryPoint) { - if (sectionHeader == nullptr || ntHeaders == nullptr || - numberOfSections == 0) { - return; - } - - DWORD baseOfCode = 0; - DWORD sizeOfCode = 0; - bool foundSection = false; - - // 寻找包含入口点的区段 - for (WORD i = 0; i < numberOfSections; i++) { - auto& section = sectionHeader[i]; - if (entryPoint >= section.VirtualAddress && - entryPoint < (section.VirtualAddress + section.Misc.VirtualSize)) { - baseOfCode = section.VirtualAddress; - sizeOfCode = section.Misc.VirtualSize; - foundSection = true; - break; - } - } - - // 如果没有找到包含入口点的区段,使用第一个可执行区段 - if (!foundSection) { - for (WORD i = 0; i < numberOfSections; i++) { - auto& section = sectionHeader[i]; - if (section.Characteristics & IMAGE_SCN_MEM_EXECUTE) { - baseOfCode = section.VirtualAddress; - sizeOfCode = section.Misc.VirtualSize; - foundSection = true; - break; - } - } - } - - // 更新NT头部信息 - if (foundSection) { - if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { - // 64位PE - auto* optHeader64 = - &reinterpret_cast(ntHeaders) - ->OptionalHeader; - optHeader64->BaseOfCode = baseOfCode; - } else { - // 32位PE - auto* optHeader32 = - &reinterpret_cast(ntHeaders) - ->OptionalHeader; - optHeader32->BaseOfCode = baseOfCode; - optHeader32->SizeOfCode = sizeOfCode; - } - } -} - -auto Sandbox::InitializeLdrData() -> void { - if (m_peInfo->isX64 && m_peb64.Ldr == 0) { - // 为LDR_DATA分配内存 - uint64_t ldrDataAddress = m_pebBase + sizeof(X64PEB); - m_pebEnd = ldrDataAddress + sizeof(X64_PEB_LDR_DATA); - m_peb64.Ldr = ldrDataAddress; - - // 映射LDR数据内存 - uc_mem_map(m_ucEngine, ldrDataAddress, sizeof(X64_PEB_LDR_DATA), - UC_PROT_ALL); - - // 初始化LDR_DATA结构 - X64_PEB_LDR_DATA ldrData = {0}; - 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; - - LIST_ENTRY inMemoryOrderList = { - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)), - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList))}; - ldrData.InMemoryOrderModuleList = inMemoryOrderList; - - LIST_ENTRY inInitOrderList = { - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)), - reinterpret_cast( - ldrDataAddress + - offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList))}; - ldrData.InInitializationOrderModuleList = inInitOrderList; - - 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}; - 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)); - - // 设置全路径 - entry.FullDllName.Length = - static_cast(wcslen(nameBuffer) * 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.MaximumLength = MAX_PATH * sizeof(wchar_t); - entry.BaseDllName.Buffer = reinterpret_cast(baseNameAddress); - - // 写入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)); - - 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)); - - // 写回更新后的LDR_DATA - uc_mem_write(m_ucEngine, m_peb64.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA)); -} - -auto Sandbox::AddModuleToLdr(const std::shared_ptr& module) - -> void { - if (!m_peInfo->isX64) { - return; // 暂时只处理64位 - } - - if (m_peb64.Ldr == 0) { - InitializeLdrData(); - } - - // 为模块创建LDR_DATA_TABLE_ENTRY - uint64_t entrySize = sizeof(LDR_DATA_TABLE_ENTRY) + - MAX_PATH * 2; // 额外空间用于Unicode字符串 - uint64_t entryAddress = m_pebEnd; - m_pebEnd += entrySize; - - // 映射内存 - uc_mem_map(m_ucEngine, entryAddress, entrySize, UC_PROT_ALL); - - // 设置Unicode字符串地址 - uint64_t fullNameAddress = entryAddress + sizeof(LDR_DATA_TABLE_ENTRY); - uint64_t baseNameAddress = fullNameAddress + MAX_PATH; - - // 创建并初始化LDR_DATA_TABLE_ENTRY - auto entry = - CreateLdrEntry(module, entryAddress, fullNameAddress, baseNameAddress); - - // 从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)); - - // 更新链表 - UpdateLdrLinks(entry, entryAddress, ldrData); - - printf("Added module '%s' to LDR data tables at 0x%llx\n", module->name, - entryAddress); -} - diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 63f251c..277f9b7 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -95,6 +95,7 @@ class Sandbox { Sandbox(); ~Sandbox(); + auto PushModuleToVM(const char* dllName, uint64_t moduleBase, uint64_t mappedSize) -> void; std::map process_enum_state; // 用于跟踪每个句柄的枚举状态 // Public methods @@ -165,7 +166,6 @@ class Sandbox { DWORD CalculateChecksum(const BYTE* buffer, size_t size); auto SetupVirtualMachine() -> void; - auto PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void; auto processImportModule(const moudle_import* importModule) -> void; auto GetCrossSectionExecution() -> std::vector { return m_crossSectionExecution; diff --git a/ai_anti_malware/sandbox_api_setmap.cpp b/ai_anti_malware/sandbox_api_setmap.cpp new file mode 100644 index 0000000..a8b051a --- /dev/null +++ b/ai_anti_malware/sandbox_api_setmap.cpp @@ -0,0 +1,65 @@ +#include "sandbox.h" + +std::string getDllNameFromApiSetMap(const std::string& apiSet) { + const std::wstring wApiSet(apiSet.begin(), apiSet.end()); + + // ȡϵͳ汾Ϣ + using RtlGetVersionFunc = LONG(__stdcall*)(PRTL_OSVERSIONINFOW); + const auto pRtlGetVersion = reinterpret_cast( + GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion")); + + RTL_OSVERSIONINFOEXW verInfo{}; + verInfo.dwOSVersionInfoSize = sizeof(verInfo); + pRtlGetVersion(reinterpret_cast(&verInfo)); + + const ULONG verShort = (verInfo.dwMajorVersion << 8) | + (verInfo.dwMinorVersion << 4) | + verInfo.wServicePackMajor; + + if (verShort >= static_cast(WinVer::kWin10)) { + const auto apiSetMap = reinterpret_cast( + reinterpret_cast(__readgsqword(0x60))->ApiSetMap); + const auto apiSetMapAsNumber = reinterpret_cast(apiSetMap); + auto nsEntry = reinterpret_cast( + apiSetMap->Start + apiSetMapAsNumber); + + // APIϲƥ + for (ULONG i = 0; i < apiSetMap->Count; i++) { + UNICODE_STRING nameString{}, valueString{}; + nameString.MaximumLength = static_cast(nsEntry->NameLength); + nameString.Length = static_cast(nsEntry->NameLength); + nameString.Buffer = reinterpret_cast(apiSetMapAsNumber + + nsEntry->NameOffset); + + const std::wstring name(nameString.Buffer, + nameString.Length / sizeof(WCHAR)); + const std::wstring fullName = name + L".dll"; + + if (_wcsicmp(wApiSet.c_str(), fullName.c_str()) == 0) { + if (nsEntry->ValueCount == 0) { + return ""; + } + + const auto valueEntry = + reinterpret_cast( + apiSetMapAsNumber + nsEntry->ValueOffset); + valueString.Buffer = reinterpret_cast( + apiSetMapAsNumber + valueEntry->ValueOffset); + valueString.MaximumLength = + static_cast(valueEntry->ValueLength); + valueString.Length = + static_cast(valueEntry->ValueLength); + + const std::wstring value(valueString.Buffer, + valueString.Length / sizeof(WCHAR)); + return { value.begin(), value.end() }; + } + ++nsEntry; + } + } + else { + // ֧Windows 10°汾 + throw std::runtime_error("Unsupported Windows version"); + } + return ""; +} diff --git a/ai_anti_malware/sandbox_dump_pe.cpp b/ai_anti_malware/sandbox_dump_pe.cpp new file mode 100644 index 0000000..f56174f --- /dev/null +++ b/ai_anti_malware/sandbox_dump_pe.cpp @@ -0,0 +1,304 @@ +#include "sandbox.h" + +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) { + targetModule = module; + break; + } + } + + if (!targetModule) { + throw std::runtime_error("No modules found to dump"); + } + + // ڴС + auto virtualMemorySize = getVirtualMemorySize(m_peInfo->peBuffer); + + // ڴ洢תݵĻ + auto resultBuffer = std::make_unique(virtualMemorySize); + + // ڴжȡPEļ + uc_err err = uc_mem_read(m_ucEngine, m_peInfo->RecImageBase, + resultBuffer.get(), virtualMemorySize); + if (err != UC_ERR_OK) { + throw std::runtime_error("Failed to read memory during PE dump: " + + std::string(uc_strerror(err))); + } + + // ȷPEͷǩЧ + auto* dosHeader = reinterpret_cast(resultBuffer.get()); + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + throw std::runtime_error("Invalid DOS signature in dumped PE"); + } + + auto* ntHeaders = reinterpret_cast(resultBuffer.get() + + dosHeader->e_lfanew); + if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { + throw std::runtime_error("Invalid NT signature in dumped PE"); + } + + // ȡǰRIP/EIPΪµڵ + uint64_t currentEntryPoint = 0; + if (this->GetCrossSectionExecution().size() > 0) { + currentEntryPoint = this->GetCrossSectionExecution() + [this->GetCrossSectionExecution().size() - 1] - + m_peInfo->RecImageBase; + } + + PIMAGE_SECTION_HEADER sectionHeaders = nullptr; + WORD numberOfSections = 0; + + // 32λ64λPEļ + if (m_peInfo->isX64) { + auto* optHeader64 = + &reinterpret_cast(ntHeaders)->OptionalHeader; + optHeader64->ImageBase = m_peInfo->RecImageBase; + if (currentEntryPoint != 0) { + // ޸ڵΪǰִλ + optHeader64->AddressOfEntryPoint = + static_cast(currentEntryPoint); + } + + // ޸SizeOfImage + optHeader64->SizeOfImage = static_cast(AlignToSectionAlignment( + virtualMemorySize, optHeader64->SectionAlignment)); + + // ޸DllCharacteristicsƳASLR + optHeader64->DllCharacteristics &= + ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; + + // ȡͷϢ + sectionHeaders = reinterpret_cast( + reinterpret_cast(ntHeaders) + + sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) + + ntHeaders->FileHeader.SizeOfOptionalHeader); + numberOfSections = ntHeaders->FileHeader.NumberOfSections; + } + else { + auto* optHeader32 = + &reinterpret_cast(ntHeaders)->OptionalHeader; + optHeader32->ImageBase = static_cast(m_peInfo->RecImageBase); + + if (currentEntryPoint != 0) { + // ޸ڵΪǰִλ + optHeader32->AddressOfEntryPoint = + static_cast(currentEntryPoint); + } + + // ޸SizeOfImage + optHeader32->SizeOfImage = static_cast(AlignToSectionAlignment( + virtualMemorySize, optHeader32->SectionAlignment)); + + // ޸DllCharacteristicsƳASLR + optHeader32->DllCharacteristics &= + ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; + + // ȡͷϢ + sectionHeaders = reinterpret_cast( + reinterpret_cast(ntHeaders) + + sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) + + ntHeaders->FileHeader.SizeOfOptionalHeader); + numberOfSections = ntHeaders->FileHeader.NumberOfSections; + } + + // ´ַʹС + UpdateBaseOfCode(sectionHeaders, ntHeaders, numberOfSections, + static_cast(currentEntryPoint)); + + // ޸ + FixSections(sectionHeaders, numberOfSections, virtualMemorySize); + + // һExportsMapperڵ޸ + peconv::ExportsMapper exportsMap; + + // Ѽģ鵽ӳ + for (const auto& module : m_moduleList) { + if (module->base == 0 || module->size == 0) { + continue; + } + + // ʱԴ洢ģ + std::unique_ptr moduleBuffer = + std::make_unique(module->size); + + // ڴȡģ + uc_err readErr = uc_mem_read(m_ucEngine, module->base, + moduleBuffer.get(), module->size); + if (readErr != UC_ERR_OK) { + printf( + "Warning: Could not read module %s for exports mapping: %s\n", + module->name, uc_strerror(readErr)); + continue; + } + + // ģ鵽ӳ + exportsMap.add_to_lookup(module->name, + reinterpret_cast(moduleBuffer.get()), + module->base); + } + // һص,ô: + // ³ĴĵͿǵĵͬһ. + // ޵ǿǵ ,Ե ȫ + // иܼ򵥵İ취,ҪIATṹ,Ȼ޸ѿǺIATֶεǵֶ,Ȼִһfix_imports + // д,ͥҵ.Լ + bool importsFixed = peconv::fix_imports( + resultBuffer.get(), virtualMemorySize, exportsMap, nullptr); + if (importsFixed) { + printf("PE file imports fixed successfully\n"); + } + else { + printf("Warning: Failed to fix PE file imports\n"); + } + + size_t out_size = 0; + + // ¼У + if (m_peInfo->isX64) { + auto* optHeader64 = + &reinterpret_cast(ntHeaders)->OptionalHeader; + optHeader64->CheckSum = + CalculateChecksum(resultBuffer.get(), virtualMemorySize); + } + else { + auto* optHeader32 = + &reinterpret_cast(ntHeaders)->OptionalHeader; + optHeader32->CheckSum = + CalculateChecksum(resultBuffer.get(), virtualMemorySize); + } + + printf( + "PE file dumped successfully from address: 0x%llx, size: %zu bytes\n", + m_peInfo->RecImageBase, virtualMemorySize); + printf("Entry point set to: 0x%llx (RVA: 0x%llx)\n", + m_peInfo->RecImageBase + currentEntryPoint, currentEntryPoint); + + return { std::move(resultBuffer), virtualMemorySize }; +} + +// ޸Ϣ +void Sandbox::FixSections(PIMAGE_SECTION_HEADER sectionHeaders, + WORD numberOfSections, size_t virtualMemorySize) { + if (numberOfSections == 0 || sectionHeaders == nullptr) { + return; + } + + // ޸ÿεϢ + for (WORD i = 0; i < numberOfSections - 1; i++) { + auto& currentSection = sectionHeaders[i]; + auto& nextSection = sectionHeaders[i + 1]; + + // ޸Сʹ֮һεʼַ + currentSection.SizeOfRawData = + nextSection.VirtualAddress - currentSection.VirtualAddress; + currentSection.PointerToRawData = currentSection.VirtualAddress; + currentSection.Misc.VirtualSize = currentSection.SizeOfRawData; + } + + // ޸һ + auto& lastSection = sectionHeaders[numberOfSections - 1]; + lastSection.SizeOfRawData = + static_cast(virtualMemorySize) - lastSection.VirtualAddress; + lastSection.PointerToRawData = lastSection.VirtualAddress; + lastSection.Misc.VirtualSize = lastSection.SizeOfRawData; +} + +// У +DWORD Sandbox::CalculateChecksum(const BYTE* peBuffer, size_t size) { + DWORD sum = 0; + const DWORD* ptr = reinterpret_cast(peBuffer); + const DWORD count = static_cast(size / sizeof(DWORD)); + + // ȡУֶεƫ + const auto dosHeader = (PIMAGE_DOS_HEADER)(peBuffer); + const auto ntHeaders = (PIMAGE_NT_HEADERS)(peBuffer + dosHeader->e_lfanew); + DWORD checksumOffset = dosHeader->e_lfanew + + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum); + + // ܺͣУֶα + for (DWORD i = 0; i < count; i++) { + // Уֶ + if ((i * sizeof(DWORD)) == checksumOffset || + (i * sizeof(DWORD)) == checksumOffset + sizeof(DWORD) - 1) { + continue; + } + sum += ptr[i]; + // + if (sum < ptr[i]) { + sum++; + } + } + + // ɼ + sum = (sum & 0xFFFF) + (sum >> 16); + sum = (sum & 0xFFFF) + (sum >> 16); + sum = sum + static_cast(size); + + return sum; +} + +// ζСж +DWORD Sandbox::AlignToSectionAlignment(size_t size, DWORD alignment) { + return static_cast(((size + alignment - 1) / alignment) * alignment); +} + +// ´ַʹС +void Sandbox::UpdateBaseOfCode(PIMAGE_SECTION_HEADER sectionHeader, + PIMAGE_NT_HEADERS ntHeaders, + WORD numberOfSections, DWORD entryPoint) { + if (sectionHeader == nullptr || ntHeaders == nullptr || + numberOfSections == 0) { + return; + } + + DWORD baseOfCode = 0; + DWORD sizeOfCode = 0; + bool foundSection = false; + + // ѰҰڵ + for (WORD i = 0; i < numberOfSections; i++) { + auto& section = sectionHeader[i]; + if (entryPoint >= section.VirtualAddress && + entryPoint < (section.VirtualAddress + section.Misc.VirtualSize)) { + baseOfCode = section.VirtualAddress; + sizeOfCode = section.Misc.VirtualSize; + foundSection = true; + break; + } + } + + // ûҵڵΣʹõһִ + if (!foundSection) { + for (WORD i = 0; i < numberOfSections; i++) { + auto& section = sectionHeader[i]; + if (section.Characteristics & IMAGE_SCN_MEM_EXECUTE) { + baseOfCode = section.VirtualAddress; + sizeOfCode = section.Misc.VirtualSize; + foundSection = true; + break; + } + } + } + + // NTͷϢ + if (foundSection) { + if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) { + // 64λPE + auto* optHeader64 = + &reinterpret_cast(ntHeaders) + ->OptionalHeader; + optHeader64->BaseOfCode = baseOfCode; + } + else { + // 32λPE + auto* optHeader32 = + &reinterpret_cast(ntHeaders) + ->OptionalHeader; + optHeader32->BaseOfCode = baseOfCode; + optHeader32->SizeOfCode = sizeOfCode; + } + } +} diff --git a/ai_anti_malware/sandbox_ldr.cpp b/ai_anti_malware/sandbox_ldr.cpp new file mode 100644 index 0000000..e8df912 --- /dev/null +++ b/ai_anti_malware/sandbox_ldr.cpp @@ -0,0 +1,164 @@ +#include "sandbox.h" + + +auto Sandbox::InitializeLdrData() -> void { + if (m_peInfo->isX64 && m_peb64.Ldr == 0) { + // ΪLDR_DATAڴ + uint64_t ldrDataAddress = m_pebBase + sizeof(X64PEB); + m_pebEnd = ldrDataAddress + sizeof(X64_PEB_LDR_DATA); + m_peb64.Ldr = ldrDataAddress; + + // ӳLDRڴ + uc_mem_map(m_ucEngine, ldrDataAddress, sizeof(X64_PEB_LDR_DATA), + UC_PROT_ALL); + + // ʼLDR_DATAṹ + X64_PEB_LDR_DATA ldrData = { 0 }; + 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; + + LIST_ENTRY inMemoryOrderList = { + reinterpret_cast( + ldrDataAddress + + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)), + reinterpret_cast( + ldrDataAddress + + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)) }; + ldrData.InMemoryOrderModuleList = inMemoryOrderList; + + LIST_ENTRY inInitOrderList = { + reinterpret_cast( + ldrDataAddress + + offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)), + reinterpret_cast( + ldrDataAddress + + offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)) }; + ldrData.InInitializationOrderModuleList = inInitOrderList; + + 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 }; + 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)); + + // ȫ· + entry.FullDllName.Length = + static_cast(wcslen(nameBuffer) * 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.MaximumLength = MAX_PATH * sizeof(wchar_t); + entry.BaseDllName.Buffer = reinterpret_cast(baseNameAddress); + + // д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)); + + 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)); + + // дظºLDR_DATA + uc_mem_write(m_ucEngine, m_peb64.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA)); +} + +auto Sandbox::AddModuleToLdr(const std::shared_ptr& module) +-> void { + if (!m_peInfo->isX64) { + return; // ʱֻ64λ + } + + if (m_peb64.Ldr == 0) { + InitializeLdrData(); + } + + // Ϊģ鴴LDR_DATA_TABLE_ENTRY + uint64_t entrySize = sizeof(LDR_DATA_TABLE_ENTRY) + + MAX_PATH * 2; // ռUnicodeַ + uint64_t entryAddress = m_pebEnd; + m_pebEnd += entrySize; + + // ӳڴ + uc_mem_map(m_ucEngine, entryAddress, entrySize, UC_PROT_ALL); + + // Unicodeַַ + uint64_t fullNameAddress = entryAddress + sizeof(LDR_DATA_TABLE_ENTRY); + uint64_t baseNameAddress = fullNameAddress + MAX_PATH; + + // ʼLDR_DATA_TABLE_ENTRY + auto entry = + CreateLdrEntry(module, entryAddress, fullNameAddress, baseNameAddress); + + // 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)); + + // + UpdateLdrLinks(entry, entryAddress, ldrData); + + printf("Added module '%s' to LDR data tables at 0x%llx\n", module->name, + entryAddress); +}