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);
+}