修复内存泄漏。并且优化代码格式

This commit is contained in:
Huoji's
2025-04-20 21:00:38 +08:00
parent 13f5160ddc
commit 143a336c8b
11 changed files with 683 additions and 595 deletions

View File

@@ -23,7 +23,7 @@
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{e12c93d6-6150-484d-85e1-7a644e393d5a}</ProjectGuid>
<RootNamespace>aiantimalware</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -180,11 +180,14 @@
<ClCompile Include="sandbox_api_file.cpp" />
<ClCompile Include="sandbox_api_process.cpp" />
<ClCompile Include="sandbox_api_regs.cpp" />
<ClCompile Include="sandbox_api_setmap.cpp" />
<ClCompile Include="sandbox_api_stl.cpp" />
<ClCompile Include="sandbox_api_wfp.cpp" />
<ClCompile Include="sandbox_api_winhttp.cpp" />
<ClCompile Include="sandbox_api_wlan.cpp" />
<ClCompile Include="sandbox_callbacks.cpp" />
<ClCompile Include="sandbox_dump_pe.cpp" />
<ClCompile Include="sandbox_ldr.cpp" />
<ClCompile Include="sandbox_malware_check.cpp" />
</ItemGroup>
<ItemGroup>

View File

@@ -159,6 +159,15 @@
<ClCompile Include="sandbox_api_com.cpp">
<Filter>源文件\sandbox\apis</Filter>
</ClCompile>
<ClCompile Include="sandbox_ldr.cpp">
<Filter>源文件\sandbox</Filter>
</ClCompile>
<ClCompile Include="sandbox_dump_pe.cpp">
<Filter>源文件\sandbox</Filter>
</ClCompile>
<ClCompile Include="sandbox_api_setmap.cpp">
<Filter>源文件\sandbox</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="head.h">

View File

@@ -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"

View File

@@ -5,59 +5,109 @@
#ifdef _DEBUG
#include <iostream>
#endif
typedef LPVOID(WINAPI* PFN_MapViewOfFile)(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);
#include <windows.h>
#include <iostream>
//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

View File

@@ -14,7 +14,7 @@
// 前向声明
struct PeInfo;
struct SectionInfo;
class BasicPeInfo;
struct BasicPeInfo;
struct RichEntry {
uint16_t productId; // 组件ID
uint16_t buildId; // 版本号

View File

@@ -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<std::shared_ptr<moudle_import>> import_function;
std::vector<std::shared_ptr<moudle_export>> export_function;
std::vector<std::shared_ptr<moudle_section>> sections;

View File

@@ -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<RtlGetVersionFunc>(
GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion"));
RTL_OSVERSIONINFOEXW verInfo{};
verInfo.dwOSVersionInfoSize = sizeof(verInfo);
pRtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&verInfo));
const ULONG verShort = (verInfo.dwMajorVersion << 8) |
(verInfo.dwMinorVersion << 4) |
verInfo.wServicePackMajor;
if (verShort >= static_cast<ULONG>(WinVer::kWin10)) {
const auto apiSetMap = reinterpret_cast<API_SET_NAMESPACE_ARRAY_10*>(
reinterpret_cast<X64PEB*>(__readgsqword(0x60))->ApiSetMap);
const auto apiSetMapAsNumber = reinterpret_cast<ULONG_PTR>(apiSetMap);
auto nsEntry = reinterpret_cast<PAPI_SET_NAMESPACE_ENTRY_10>(
apiSetMap->Start + apiSetMapAsNumber);
// 遍历API集合查找匹配项
for (ULONG i = 0; i < apiSetMap->Count; i++) {
UNICODE_STRING nameString{}, valueString{};
nameString.MaximumLength = static_cast<USHORT>(nsEntry->NameLength);
nameString.Length = static_cast<USHORT>(nsEntry->NameLength);
nameString.Buffer = reinterpret_cast<PWCHAR>(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<PAPI_SET_VALUE_ENTRY_10>(
apiSetMapAsNumber + nsEntry->ValueOffset);
valueString.Buffer = reinterpret_cast<PWCHAR>(
apiSetMapAsNumber + valueEntry->ValueOffset);
valueString.MaximumLength =
static_cast<USHORT>(valueEntry->ValueLength);
valueString.Length =
static_cast<USHORT>(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<std::string, uint64_t> context)
: _functionMap(std::move(context)) {}
@@ -96,22 +32,22 @@ class ImportResolver : public peconv::t_function_resolver {
return reinterpret_cast<FARPROC>(_functionMap[std::string(funcName)]);
}
private:
private:
std::map<std::string, uint64_t> _functionMap;
};
class cListImportNames : public peconv::ImportThunksCallback {
public:
public:
cListImportNames(
BYTE* _modulePtr, size_t _moduleSize,
std::vector<std::shared_ptr<moudle_import>>& name_to_addr,
std::vector<std::shared_ptr<moudle_import_ordinal>>& 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<IMAGE_THUNK_DATA64*>(origFirstThunkPtr);
@@ -126,17 +62,17 @@ class cListImportNames : public peconv::ImportThunksCallback {
lib_name, desc, call_via, IMAGE_ORDINAL_FLAG32);
}
protected:
protected:
template <typename T_FIELD, typename T_IMAGE_THUNK_DATA>
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<DWORD>((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<LPSTR>(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<moudle_import>();
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<moudle_import_ordinal>();
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<std::shared_ptr<moudle_import_ordinal>>& 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<size_t>(totalSize);
}
auto Sandbox::DumpPE() -> std::pair<std::unique_ptr<BYTE[]>, size_t> {
// 查找目标模块 - 这里我们使用主模块(通常是被分析的可执行文件)
std::shared_ptr<struct_moudle> 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<BYTE[]>(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<PIMAGE_DOS_HEADER>(resultBuffer.get());
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
throw std::runtime_error("Invalid DOS signature in dumped PE");
}
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(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<PIMAGE_NT_HEADERS64>(ntHeaders)->OptionalHeader;
optHeader64->ImageBase = m_peInfo->RecImageBase;
if (currentEntryPoint != 0) {
// 修改入口点为当前执行位置
optHeader64->AddressOfEntryPoint =
static_cast<DWORD>(currentEntryPoint);
}
// 修改SizeOfImage
optHeader64->SizeOfImage = static_cast<DWORD>(AlignToSectionAlignment(
virtualMemorySize, optHeader64->SectionAlignment));
// 修改DllCharacteristics以移除ASLR标记
optHeader64->DllCharacteristics &=
~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
// 获取区段头信息
sectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<ULONG_PTR>(ntHeaders) +
sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
numberOfSections = ntHeaders->FileHeader.NumberOfSections;
} else {
auto* optHeader32 =
&reinterpret_cast<PIMAGE_NT_HEADERS32>(ntHeaders)->OptionalHeader;
optHeader32->ImageBase = static_cast<DWORD>(m_peInfo->RecImageBase);
if (currentEntryPoint != 0) {
// 修改入口点为当前执行位置
optHeader32->AddressOfEntryPoint =
static_cast<DWORD>(currentEntryPoint);
}
// 修改SizeOfImage
optHeader32->SizeOfImage = static_cast<DWORD>(AlignToSectionAlignment(
virtualMemorySize, optHeader32->SectionAlignment));
// 修改DllCharacteristics以移除ASLR标记
optHeader32->DllCharacteristics &=
~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
// 获取区段头信息
sectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<ULONG_PTR>(ntHeaders) +
sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
numberOfSections = ntHeaders->FileHeader.NumberOfSections;
}
// 更新代码基址和大小
UpdateBaseOfCode(sectionHeaders, ntHeaders, numberOfSections,
static_cast<DWORD>(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<BYTE[]> moduleBuffer =
std::make_unique<BYTE[]>(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<HMODULE>(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<PIMAGE_NT_HEADERS64>(ntHeaders)->OptionalHeader;
optHeader64->CheckSum =
CalculateChecksum(resultBuffer.get(), virtualMemorySize);
} else {
auto* optHeader32 =
&reinterpret_cast<PIMAGE_NT_HEADERS32>(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<DWORD>(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<const DWORD*>(peBuffer);
const DWORD count = static_cast<DWORD>(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<DWORD>(size);
return sum;
}
// 按区段对齐大小进行对齐
DWORD Sandbox::AlignToSectionAlignment(size_t size, DWORD alignment) {
return static_cast<DWORD>(((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<PIMAGE_NT_HEADERS64>(ntHeaders)
->OptionalHeader;
optHeader64->BaseOfCode = baseOfCode;
} else {
// 32位PE
auto* optHeader32 =
&reinterpret_cast<PIMAGE_NT_HEADERS32>(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<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)),
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList))};
ldrData.InLoadOrderModuleList = inLoadOrderList;
LIST_ENTRY inMemoryOrderList = {
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)),
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList))};
ldrData.InMemoryOrderModuleList = inMemoryOrderList;
LIST_ENTRY inInitOrderList = {
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)),
reinterpret_cast<LIST_ENTRY*>(
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<struct_moudle>& module,
uint64_t entryAddress, uint64_t fullNameAddress,
uint64_t baseNameAddress) -> LDR_DATA_TABLE_ENTRY {
LDR_DATA_TABLE_ENTRY entry = {0};
entry.DllBase = reinterpret_cast<PVOID>(module->base);
entry.EntryPoint = reinterpret_cast<PVOID>(module->base + module->entry);
entry.SizeOfImages = static_cast<ULONG>(module->size);
// 准备模块名称的Unicode字符串
wchar_t nameBuffer[MAX_PATH] = {0};
std::mbstowcs(nameBuffer, module->name, strlen(module->name));
// 设置全路径
entry.FullDllName.Length =
static_cast<USHORT>(wcslen(nameBuffer) * sizeof(wchar_t));
entry.FullDllName.MaximumLength = MAX_PATH * sizeof(wchar_t);
entry.FullDllName.Buffer = reinterpret_cast<PWSTR>(fullNameAddress);
// 设置基本名称
entry.BaseDllName.Length =
static_cast<USHORT>(wcslen(nameBuffer) * sizeof(wchar_t));
entry.BaseDllName.MaximumLength = MAX_PATH * sizeof(wchar_t);
entry.BaseDllName.Buffer = reinterpret_cast<PWSTR>(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<LIST_ENTRY*>(
entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InLoadOrderLinks));
ldrData.InMemoryOrderModuleList.Flink = reinterpret_cast<LIST_ENTRY*>(
entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks));
ldrData.InInitializationOrderModuleList.Flink =
reinterpret_cast<LIST_ENTRY*>(
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<struct_moudle>& 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<LIST_ENTRY*>(
reinterpret_cast<uintptr_t>(ldrData.InLoadOrderModuleList.Flink));
entry.InLoadOrderLinks.Blink = reinterpret_cast<LIST_ENTRY*>(
m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList));
entry.InMemoryOrderLinks.Flink = reinterpret_cast<LIST_ENTRY*>(
reinterpret_cast<uintptr_t>(ldrData.InMemoryOrderModuleList.Flink));
entry.InMemoryOrderLinks.Blink = reinterpret_cast<LIST_ENTRY*>(
m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList));
entry.InInitializationOrderLinks.Flink =
reinterpret_cast<LIST_ENTRY*>(reinterpret_cast<uintptr_t>(
ldrData.InInitializationOrderModuleList.Flink));
entry.InInitializationOrderLinks.Blink = reinterpret_cast<LIST_ENTRY*>(
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);
}

View File

@@ -95,6 +95,7 @@ class Sandbox {
Sandbox();
~Sandbox();
auto PushModuleToVM(const char* dllName, uint64_t moduleBase, uint64_t mappedSize) -> void;
std::map<uint64_t, size_t>
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<uint64_t> {
return m_crossSectionExecution;

View File

@@ -0,0 +1,65 @@
#include "sandbox.h"
std::string getDllNameFromApiSetMap(const std::string& apiSet) {
const std::wstring wApiSet(apiSet.begin(), apiSet.end());
// <20><>ȡϵͳ<CFB5><EFBFBD><E6B1BE>Ϣ
using RtlGetVersionFunc = LONG(__stdcall*)(PRTL_OSVERSIONINFOW);
const auto pRtlGetVersion = reinterpret_cast<RtlGetVersionFunc>(
GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion"));
RTL_OSVERSIONINFOEXW verInfo{};
verInfo.dwOSVersionInfoSize = sizeof(verInfo);
pRtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&verInfo));
const ULONG verShort = (verInfo.dwMajorVersion << 8) |
(verInfo.dwMinorVersion << 4) |
verInfo.wServicePackMajor;
if (verShort >= static_cast<ULONG>(WinVer::kWin10)) {
const auto apiSetMap = reinterpret_cast<API_SET_NAMESPACE_ARRAY_10*>(
reinterpret_cast<X64PEB*>(__readgsqword(0x60))->ApiSetMap);
const auto apiSetMapAsNumber = reinterpret_cast<ULONG_PTR>(apiSetMap);
auto nsEntry = reinterpret_cast<PAPI_SET_NAMESPACE_ENTRY_10>(
apiSetMap->Start + apiSetMapAsNumber);
// <20><><EFBFBD><EFBFBD>API<50><49><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD>
for (ULONG i = 0; i < apiSetMap->Count; i++) {
UNICODE_STRING nameString{}, valueString{};
nameString.MaximumLength = static_cast<USHORT>(nsEntry->NameLength);
nameString.Length = static_cast<USHORT>(nsEntry->NameLength);
nameString.Buffer = reinterpret_cast<PWCHAR>(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<PAPI_SET_VALUE_ENTRY_10>(
apiSetMapAsNumber + nsEntry->ValueOffset);
valueString.Buffer = reinterpret_cast<PWCHAR>(
apiSetMapAsNumber + valueEntry->ValueOffset);
valueString.MaximumLength =
static_cast<USHORT>(valueEntry->ValueLength);
valueString.Length =
static_cast<USHORT>(valueEntry->ValueLength);
const std::wstring value(valueString.Buffer,
valueString.Length / sizeof(WCHAR));
return { value.begin(), value.end() };
}
++nsEntry;
}
}
else {
// <20><>֧<EFBFBD><D6A7>Windows 10<31><30><EFBFBD>°汾
throw std::runtime_error("Unsupported Windows version");
}
return "";
}

View File

@@ -0,0 +1,304 @@
#include "sandbox.h"
auto Sandbox::DumpPE() -> std::pair<std::unique_ptr<BYTE[]>, size_t> {
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>ģ<EFBFBD><C4A3> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><><CDA8><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>ļ<EFBFBD>)
std::shared_ptr<struct_moudle> 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");
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>С
auto virtualMemorySize = getVirtualMemorySize(m_peInfo->peBuffer);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢ת<E6B4A2><D7AA><EFBFBD><EFBFBD><EFBFBD>ݵĻ<DDB5><C4BB><EFBFBD><EFBFBD><EFBFBD>
auto resultBuffer = std::make_unique<BYTE[]>(virtualMemorySize);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ж<EFBFBD>ȡPE<50>ļ<EFBFBD>
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)));
}
// ȷ<><C8B7>PEͷ<45><CDB7><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>Ч
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(resultBuffer.get());
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
throw std::runtime_error("Invalid DOS signature in dumped PE");
}
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(resultBuffer.get() +
dosHeader->e_lfanew);
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
throw std::runtime_error("Invalid NT signature in dumped PE");
}
// <20><>ȡ<EFBFBD><C8A1>ǰRIP/EIP<49><50>Ϊ<EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>ڵ<EFBFBD>
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;
// <20><><EFBFBD><EFBFBD>32λ<32><CEBB>64λPE<50>ļ<EFBFBD>
if (m_peInfo->isX64) {
auto* optHeader64 =
&reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)->OptionalHeader;
optHeader64->ImageBase = m_peInfo->RecImageBase;
if (currentEntryPoint != 0) {
// <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD>ڵ<EFBFBD>Ϊ<EFBFBD><CEAA>ǰִ<C7B0><D6B4>λ<EFBFBD><CEBB>
optHeader64->AddressOfEntryPoint =
static_cast<DWORD>(currentEntryPoint);
}
// <20>޸<EFBFBD>SizeOfImage
optHeader64->SizeOfImage = static_cast<DWORD>(AlignToSectionAlignment(
virtualMemorySize, optHeader64->SectionAlignment));
// <20>޸<EFBFBD>DllCharacteristics<63><73><EFBFBD>Ƴ<EFBFBD>ASLR<4C><52><EFBFBD><EFBFBD>
optHeader64->DllCharacteristics &=
~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>Ϣ
sectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<ULONG_PTR>(ntHeaders) +
sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
numberOfSections = ntHeaders->FileHeader.NumberOfSections;
}
else {
auto* optHeader32 =
&reinterpret_cast<PIMAGE_NT_HEADERS32>(ntHeaders)->OptionalHeader;
optHeader32->ImageBase = static_cast<DWORD>(m_peInfo->RecImageBase);
if (currentEntryPoint != 0) {
// <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD>ڵ<EFBFBD>Ϊ<EFBFBD><CEAA>ǰִ<C7B0><D6B4>λ<EFBFBD><CEBB>
optHeader32->AddressOfEntryPoint =
static_cast<DWORD>(currentEntryPoint);
}
// <20>޸<EFBFBD>SizeOfImage
optHeader32->SizeOfImage = static_cast<DWORD>(AlignToSectionAlignment(
virtualMemorySize, optHeader32->SectionAlignment));
// <20>޸<EFBFBD>DllCharacteristics<63><73><EFBFBD>Ƴ<EFBFBD>ASLR<4C><52><EFBFBD><EFBFBD>
optHeader32->DllCharacteristics &=
~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>Ϣ
sectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<ULONG_PTR>(ntHeaders) +
sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
numberOfSections = ntHeaders->FileHeader.NumberOfSections;
}
// <20><><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʹ<EFBFBD>С
UpdateBaseOfCode(sectionHeaders, ntHeaders, numberOfSections,
static_cast<DWORD>(currentEntryPoint));
// <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD>
FixSections(sectionHeaders, numberOfSections, virtualMemorySize);
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ExportsMapper<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>
peconv::ExportsMapper exportsMap;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѽ<EFBFBD><D1BC><EFBFBD>ģ<EFBFBD><EFBFBD><E9B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD>
for (const auto& module : m_moduleList) {
if (module->base == 0 || module->size == 0) {
continue;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ洢ģ<E6B4A2><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::unique_ptr<BYTE[]> moduleBuffer =
std::make_unique<BYTE[]>(module->size);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>ȡģ<C8A1><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}
// <20><><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><E9B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3>
exportsMap.add_to_lookup(module->name,
reinterpret_cast<HMODULE>(moduleBuffer.get()),
module->base);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD>:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD><C2B3><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳǵĵ<C7B5><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>һ<EFBFBD><D2BB>.
// <20><><EFBFBD><EFBFBD><EFBFBD>޵<EFBFBD><DEB5>ǿǵ<C7BF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> ȫ
// <20>и<EFBFBD><D0B8>ܼ򵥵İ취,<2C><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>IAT<41>ṹ,Ȼ<><C8BB><EFBFBD>޸<EFBFBD><DEB8>ѿǺ<D1BF><C7BA><EFBFBD>IAT<41><54><EFBFBD>ֶε<D6B6><CEB5>ǵ<EFBFBD><C7B5>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><><C8BB><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>һ<EFBFBD><D2BB>fix_imports
// <20><><EFBFBD><EFBFBD>д<EFBFBD><D0B4>,<2C><>ͥ<EFBFBD><CDA5>ҵ.<2E>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>
if (m_peInfo->isX64) {
auto* optHeader64 =
&reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)->OptionalHeader;
optHeader64->CheckSum =
CalculateChecksum(resultBuffer.get(), virtualMemorySize);
}
else {
auto* optHeader32 =
&reinterpret_cast<PIMAGE_NT_HEADERS32>(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 };
}
// <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
void Sandbox::FixSections(PIMAGE_SECTION_HEADER sectionHeaders,
WORD numberOfSections, size_t virtualMemorySize) {
if (numberOfSections == 0 || sectionHeaders == nullptr) {
return;
}
// <20>޸<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD>Ϣ
for (WORD i = 0; i < numberOfSections - 1; i++) {
auto& currentSection = sectionHeaders[i];
auto& nextSection = sectionHeaders[i + 1];
// <20>޸<EFBFBD><DEB8><EFBFBD>С<EFBFBD><D0A1>ʹ֮<CAB9><D6AE><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><CEB5><EFBFBD>ʼ<EFBFBD><CABC>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>
currentSection.SizeOfRawData =
nextSection.VirtualAddress - currentSection.VirtualAddress;
currentSection.PointerToRawData = currentSection.VirtualAddress;
currentSection.Misc.VirtualSize = currentSection.SizeOfRawData;
}
// <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
auto& lastSection = sectionHeaders[numberOfSections - 1];
lastSection.SizeOfRawData =
static_cast<DWORD>(virtualMemorySize) - lastSection.VirtualAddress;
lastSection.PointerToRawData = lastSection.VirtualAddress;
lastSection.Misc.VirtualSize = lastSection.SizeOfRawData;
}
// <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>
DWORD Sandbox::CalculateChecksum(const BYTE* peBuffer, size_t size) {
DWORD sum = 0;
const DWORD* ptr = reinterpret_cast<const DWORD*>(peBuffer);
const DWORD count = static_cast<DWORD>(size / sizeof(DWORD));
// <20><>ȡУ<C8A1><D0A3><EFBFBD><EFBFBD><EFBFBD>ֶε<D6B6>ƫ<EFBFBD><C6AB>
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);
// <20><><EFBFBD><EFBFBD><EFBFBD>ܺͣ<DCBA><CDA3><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ֶα<D6B6><CEB1><EFBFBD>
for (DWORD i = 0; i < count; i++) {
// <20><><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
if ((i * sizeof(DWORD)) == checksumOffset ||
(i * sizeof(DWORD)) == checksumOffset + sizeof(DWORD) - 1) {
continue;
}
sum += ptr[i];
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (sum < ptr[i]) {
sum++;
}
}
// <20><><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD>
sum = (sum & 0xFFFF) + (sum >> 16);
sum = (sum & 0xFFFF) + (sum >> 16);
sum = sum + static_cast<DWORD>(size);
return sum;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD><CEB6><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>
DWORD Sandbox::AlignToSectionAlignment(size_t size, DWORD alignment) {
return static_cast<DWORD>(((size + alignment - 1) / alignment) * alignment);
}
// <20><><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʹ<EFBFBD><CDB4><EFBFBD><EFBFBD><EFBFBD>С
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;
// Ѱ<>Ұ<EFBFBD><D2B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}
}
// <20><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD>ʹ<EFBFBD>õ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}
}
}
// <20><><EFBFBD><EFBFBD>NTͷ<54><CDB7><EFBFBD><EFBFBD>Ϣ
if (foundSection) {
if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
// 64λPE
auto* optHeader64 =
&reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)
->OptionalHeader;
optHeader64->BaseOfCode = baseOfCode;
}
else {
// 32λPE
auto* optHeader32 =
&reinterpret_cast<PIMAGE_NT_HEADERS32>(ntHeaders)
->OptionalHeader;
optHeader32->BaseOfCode = baseOfCode;
optHeader32->SizeOfCode = sizeOfCode;
}
}
}

View File

@@ -0,0 +1,164 @@
#include "sandbox.h"
auto Sandbox::InitializeLdrData() -> void {
if (m_peInfo->isX64 && m_peb64.Ldr == 0) {
// ΪLDR_DATA<54><41><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
uint64_t ldrDataAddress = m_pebBase + sizeof(X64PEB);
m_pebEnd = ldrDataAddress + sizeof(X64_PEB_LDR_DATA);
m_peb64.Ldr = ldrDataAddress;
// ӳ<><D3B3>LDR<44><52><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
uc_mem_map(m_ucEngine, ldrDataAddress, sizeof(X64_PEB_LDR_DATA),
UC_PROT_ALL);
// <20><>ʼ<EFBFBD><CABC>LDR_DATA<54>
X64_PEB_LDR_DATA ldrData = { 0 };
ldrData.Length = sizeof(X64_PEB_LDR_DATA);
ldrData.Initialized = 1;
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ - ʹ<><CAB9><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
LIST_ENTRY inLoadOrderList = {
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)),
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList)) };
ldrData.InLoadOrderModuleList = inLoadOrderList;
LIST_ENTRY inMemoryOrderList = {
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)),
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList)) };
ldrData.InMemoryOrderModuleList = inMemoryOrderList;
LIST_ENTRY inInitOrderList = {
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)),
reinterpret_cast<LIST_ENTRY*>(
ldrDataAddress +
offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList)) };
ldrData.InInitializationOrderModuleList = inInitOrderList;
uc_mem_write(m_ucEngine, ldrDataAddress, &ldrData,
sizeof(X64_PEB_LDR_DATA));
// <20><><EFBFBD><EFBFBD>PEB<45>е<EFBFBD>Ldrָ<72><D6B8>
uc_mem_write(m_ucEngine, m_pebBase, &m_peb64, sizeof(X64PEB));
}
}
auto Sandbox::CreateLdrEntry(const std::shared_ptr<struct_moudle>& module,
uint64_t entryAddress, uint64_t fullNameAddress,
uint64_t baseNameAddress) -> LDR_DATA_TABLE_ENTRY {
LDR_DATA_TABLE_ENTRY entry = { 0 };
entry.DllBase = reinterpret_cast<PVOID>(module->base);
entry.EntryPoint = reinterpret_cast<PVOID>(module->base + module->entry);
entry.SizeOfImages = static_cast<ULONG>(module->size);
// ׼<><D7BC>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>Unicode<64>ַ<EFBFBD><D6B7><EFBFBD>
wchar_t nameBuffer[MAX_PATH] = { 0 };
std::mbstowcs(nameBuffer, module->name, strlen(module->name));
// <20><><EFBFBD><EFBFBD>ȫ·<C8AB><C2B7>
entry.FullDllName.Length =
static_cast<USHORT>(wcslen(nameBuffer) * sizeof(wchar_t));
entry.FullDllName.MaximumLength = MAX_PATH * sizeof(wchar_t);
entry.FullDllName.Buffer = reinterpret_cast<PWSTR>(fullNameAddress);
// <20><><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
entry.BaseDllName.Length =
static_cast<USHORT>(wcslen(nameBuffer) * sizeof(wchar_t));
entry.BaseDllName.MaximumLength = MAX_PATH * sizeof(wchar_t);
entry.BaseDllName.Buffer = reinterpret_cast<PWSTR>(baseNameAddress);
// д<><D0B4>Unicode<64>ַ<EFBFBD><D6B7><EFBFBD>
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 {
// <20><><EFBFBD><EFBFBD>LDR_DATA<54>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>ͷ
ldrData.InLoadOrderModuleList.Flink = reinterpret_cast<LIST_ENTRY*>(
entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InLoadOrderLinks));
ldrData.InMemoryOrderModuleList.Flink = reinterpret_cast<LIST_ENTRY*>(
entryAddress + offsetof(LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks));
ldrData.InInitializationOrderModuleList.Flink =
reinterpret_cast<LIST_ENTRY*>(
entryAddress +
offsetof(LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks));
// д<>ظ<EFBFBD><D8B8>º<EFBFBD><C2BA><EFBFBD>LDR_DATA
uc_mem_write(m_ucEngine, m_peb64.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA));
}
auto Sandbox::AddModuleToLdr(const std::shared_ptr<struct_moudle>& module)
-> void {
if (!m_peInfo->isX64) {
return; // <20><>ʱֻ<CAB1><D6BB><EFBFBD><EFBFBD>64λ
}
if (m_peb64.Ldr == 0) {
InitializeLdrData();
}
// Ϊģ<CEAA><EFBFBD><E9B4B4>LDR_DATA_TABLE_ENTRY
uint64_t entrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
MAX_PATH * 2; // <20><><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>Unicode<64>ַ<EFBFBD><D6B7><EFBFBD>
uint64_t entryAddress = m_pebEnd;
m_pebEnd += entrySize;
// ӳ<><D3B3><EFBFBD>ڴ<EFBFBD>
uc_mem_map(m_ucEngine, entryAddress, entrySize, UC_PROT_ALL);
// <20><><EFBFBD><EFBFBD>Unicode<64>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ַ
uint64_t fullNameAddress = entryAddress + sizeof(LDR_DATA_TABLE_ENTRY);
uint64_t baseNameAddress = fullNameAddress + MAX_PATH;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>LDR_DATA_TABLE_ENTRY
auto entry =
CreateLdrEntry(module, entryAddress, fullNameAddress, baseNameAddress);
// <20><>PEB<45><42>ȡ<EFBFBD><C8A1>ǰLDR_DATA<54>
X64_PEB_LDR_DATA ldrData;
uc_mem_read(m_ucEngine, m_peb64.Ldr, &ldrData, sizeof(X64_PEB_LDR_DATA));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
entry.InLoadOrderLinks.Flink = reinterpret_cast<LIST_ENTRY*>(
reinterpret_cast<uintptr_t>(ldrData.InLoadOrderModuleList.Flink));
entry.InLoadOrderLinks.Blink = reinterpret_cast<LIST_ENTRY*>(
m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InLoadOrderModuleList));
entry.InMemoryOrderLinks.Flink = reinterpret_cast<LIST_ENTRY*>(
reinterpret_cast<uintptr_t>(ldrData.InMemoryOrderModuleList.Flink));
entry.InMemoryOrderLinks.Blink = reinterpret_cast<LIST_ENTRY*>(
m_peb64.Ldr + offsetof(X64_PEB_LDR_DATA, InMemoryOrderModuleList));
entry.InInitializationOrderLinks.Flink =
reinterpret_cast<LIST_ENTRY*>(reinterpret_cast<uintptr_t>(
ldrData.InInitializationOrderModuleList.Flink));
entry.InInitializationOrderLinks.Blink = reinterpret_cast<LIST_ENTRY*>(
m_peb64.Ldr +
offsetof(X64_PEB_LDR_DATA, InInitializationOrderModuleList));
// д<><D0B4>LDR_DATA_TABLE_ENTRY<52>
uc_mem_write(m_ucEngine, entryAddress, &entry,
sizeof(LDR_DATA_TABLE_ENTRY));
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
UpdateLdrLinks(entry, entryAddress, ldrData);
printf("Added module '%s' to LDR data tables at 0x%llx\n", module->name,
entryAddress);
}