修复内存泄漏。并且优化代码格式
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user