Files
2025-04-25 16:08:22 +08:00

817 lines
30 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "sandbox.h"
#include "sandbox_callbacks.h"
#include "sandbox_api_com.h"
// 在文件开头添加AllocateMemory函数的声明
auto Sandbox::AllocateMemory(size_t size) -> uint64_t {
// 使用一个简单的内存分配策略
static uint64_t next_address = 0x60000000; // 起始地址
uint64_t allocated_address = next_address;
// 对齐到4KB
size = (size + 0xFFF) & ~0xFFF;
// 分配内存
uc_err err = uc_mem_map(m_ucEngine, allocated_address, size, UC_PROT_ALL);
if (err != UC_ERR_OK) {
printf("[!] Failed to allocate memory at 0x%llx: %u\n",
allocated_address, err);
return 0;
}
// 更新下一个可用地址
next_address += size + 0x1000; // 添加一个页面的间隔
return allocated_address;
}
class ImportResolver : public peconv::t_function_resolver {
public:
explicit ImportResolver(std::map<std::string, uint64_t> context)
: _functionMap(std::move(context)) {}
FARPROC resolve_func(LPSTR libName, LPSTR funcName) override {
return reinterpret_cast<FARPROC>(_functionMap[std::string(funcName)]);
}
private:
std::map<std::string, uint64_t> _functionMap;
};
class cListImportNames : public peconv::ImportThunksCallback {
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) {}
virtual bool processThunks(LPSTR lib_name, ULONG_PTR origFirstThunkPtr,
ULONG_PTR firstThunkPtr) {
if (this->is64b) {
IMAGE_THUNK_DATA64* desc =
reinterpret_cast<IMAGE_THUNK_DATA64*>(origFirstThunkPtr);
ULONGLONG* call_via = reinterpret_cast<ULONGLONG*>(firstThunkPtr);
return processThunks_tpl<ULONGLONG, IMAGE_THUNK_DATA64>(
lib_name, desc, call_via, IMAGE_ORDINAL_FLAG64);
}
IMAGE_THUNK_DATA32* desc =
reinterpret_cast<IMAGE_THUNK_DATA32*>(origFirstThunkPtr);
DWORD* call_via = reinterpret_cast<DWORD*>(firstThunkPtr);
return processThunks_tpl<DWORD, IMAGE_THUNK_DATA32>(
lib_name, desc, call_via, IMAGE_ORDINAL_FLAG32);
}
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) {
DWORD call_via_rva = static_cast<DWORD>((ULONG_PTR)call_via -
(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);
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) {
fuck_up_api_ms = getDllNameFromApiSetMap(fuck_up_api_ms);
if (fuck_up_api_ms.size() <= 1) __debugbreak();
}
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());
import_data->function_address = call_via_rva;
import_data->is_delayed_import = false;
nameToAddr.push_back(import_data);
}
else {
auto importFunc = std::make_shared<moudle_import_ordinal>();
T_FIELD raw_ordinal = desc->u1.Ordinal & (~ordinal_flag);
importFunc->dll_name = lib_name;
importFunc->function_address = call_via_rva;
importFunc->ordinal = raw_ordinal;
ordinalImportFunc.push_back(importFunc);
}
return true;
}
std::vector<std::shared_ptr<moudle_import>>& nameToAddr;
std::vector<std::shared_ptr<moudle_import_ordinal>>& ordinalImportFunc;
};
class cFixImprot : public peconv::t_function_resolver {
public:
// 构造函数接收Sandbox实例的引用
explicit cFixImprot(Sandbox* sandbox) : m_sandbox(sandbox) {}
// 实现导入函数解析
virtual FARPROC resolve_func(LPSTR lib_name, LPSTR func_name) override {
// 遍历所有已加载的模块
for (const auto& module : m_sandbox->m_moduleList) {
// 检查模块名是否匹配
if (module->name == std::string(lib_name) == 0) {
// 遍历该模块的导出函数
for (const auto& exp : module->export_function) {
// 检查函数名是否匹配
if (strcmp(exp->name, func_name) == 0) {
auto newBase = reinterpret_cast<FARPROC>(
module->base + exp->function_address);
#ifdef LOG_LEVEL > 2
printf("fix import: %s => %llx \n", func_name, newBase);
// 返回在模拟器中的虚拟地址
#endif
return newBase;
}
}
}
}
// 如果没有找到精确匹配的模块名,尝试在所有模块中查找该函数
for (const auto& module : m_sandbox->m_moduleList) {
for (const auto& exp : module->export_function) {
auto newBase = reinterpret_cast<FARPROC>(
module->base + exp->function_address);
// 检查函数名是否匹配
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);
// 返回在模拟器中的虚拟地址
#endif
return newBase;
}
//序号导出,非常癌症的修复.
if (std::string(lib_name) == module->name) {
int ordinalNum = std::atoi(func_name);
if (exp->ordinal == ordinalNum) {
auto newBase = reinterpret_cast<FARPROC>(
module->base + exp->function_address);
#ifdef LOG_LEVEL > 1
printf("fix import (ordianal): %s found in [%s]%s => %llx \n",
func_name, module->name, exp->name, newBase);
// 返回在模拟器中的虚拟地址
#endif // LOG_LEVEL > 1
return newBase;
}
}
}
}
printf("Warning: Could not resolve import: %s from library: %s\n",
func_name, lib_name);
//__debugbreak();
return nullptr;
}
private:
Sandbox* m_sandbox; // Sandbox实例的指针
};
Sandbox::Sandbox() {
m_ucEngine = nullptr;
m_peInfo = nullptr;
m_nextWfpEngineHandle = (HANDLE)0x1000; // 初始化WFP引擎句柄
m_lastImpRead = {0, 0};
}
Sandbox::~Sandbox() {
// 清理WFP引擎资源
for (auto& pair : m_wfpEngines) {
delete pair.second;
}
m_wfpEngines.clear();
// 清理文件句柄资源
for (auto& pair : m_fileHandles) {
delete pair.second;
}
m_fileHandles.clear();
// 1. 先清理高层资源
m_crossSectionExecution.clear();
envStrings.clear();
api_map.clear();
m_moduleList.clear();
m_impFuncDict.clear();
m_exportFuncDict.clear();
// 2. 清理内存映射
if (m_ucEngine) {
uc_close(m_ucEngine);
m_ucEngine = nullptr;
}
// 3. 清理堆内存
for (auto& [address, segment] : m_heapSegments) {
HeapBlock* current = segment->blocks;
while (current) {
HeapBlock* next = current->next;
delete current;
current = next;
}
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) {
cs_close(&m_csHandle);
}
}
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);
return;
}
}
if (m_usedModuleBase == 0) {
m_usedModuleBase = DLL_MODULE_BASE;
}
// 创建新模块
auto newModule =
CreateModuleInfo(dllName, AlignSize(m_usedModuleBase, PAGE_SIZE),
moduleBase, moduleBase);
m_usedModuleBase += PAGE_SIZE + newModule->size;
m_moduleList.push_back(newModule);
printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule->name,
newModule->base, newModule->size);
if (uc_mem_map(m_ucEngine, newModule->base, newModule->size,
UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) {
throw std::runtime_error("Failed to map module");
}
if (uc_mem_write(m_ucEngine, newModule->base, (void*)moduleBase,
newModule->size) != UC_ERR_OK) {
throw std::runtime_error("Failed to write data to map module");
}
if (peconv::relocate_module((BYTE*)moduleBase, newModule->size,
newModule->base) == false) {
throw std::runtime_error("Failed to relocate module");
}
newModule->mapped_address = moduleBase;
newModule->mapped_size = mappedSize;
// 将模块添加到LDR链表中
if (m_peInfo->isX64) {
AddModuleToLdr(newModule);
}
}
auto Sandbox::CreateModuleInfo(std::string dllName, uint64_t moduleBase,
uint64_t realModuleBase, uint64_t bufferAddress)
-> std::shared_ptr<struct_moudle> {
// 解析PE头
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(bufferAddress);
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<LPBYTE>(bufferAddress) + dosHeader->e_lfanew);
// 获取区段对齐值
DWORD sectionAlignment =
(ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
? reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)
->OptionalHeader.SectionAlignment
: ntHeaders->OptionalHeader.SectionAlignment;
// 获取区段头
auto* sectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<PUCHAR>(ntHeaders) + sizeof(ntHeaders->Signature) +
sizeof(ntHeaders->FileHeader) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
struct_moudle newModule{};
newModule.name = dllName.c_str();
newModule.base = moduleBase;
newModule.real_base = realModuleBase;
newModule.entry = ntHeaders->OptionalHeader.AddressOfEntryPoint;
newModule.size = ntHeaders->OptionalHeader.SizeOfImage;
// 处理区段
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
const auto& section = sectionHeader[i];
// if (!(section.Characteristics &
// (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE))) {
// continue;
// }
// 设置区段保护属性
int protection = UC_PROT_READ;
if (section.Characteristics & IMAGE_SCN_MEM_EXECUTE)
protection |= UC_PROT_EXEC;
if (section.Characteristics & IMAGE_SCN_MEM_WRITE)
protection |= UC_PROT_WRITE;
// 计算区段大小
auto sectionSize = AlignToSectionAlignment(
max(section.Misc.VirtualSize, section.SizeOfRawData),
sectionAlignment);
// 创建区段信息
moudle_section newSection{};
strncpy(newSection.name, reinterpret_cast<const char*>(section.Name),
8);
newSection.base = section.VirtualAddress;
newSection.size = sectionSize;
newSection.protect_flag = protection;
newModule.sections.push_back(
std::make_shared<moudle_section>(newSection));
std::cout << "[PE] " << dllName << " Section found: " << newSection.name
<< '\n';
}
return std::make_shared<struct_moudle>(newModule);
}
auto Sandbox::ResolveExport(uint64_t moduleBase)
-> std::vector<std::shared_ptr<moudle_export>> {
std::vector<std::shared_ptr<moudle_export>> export_list;
DWORD exportSize = 0;
static RtlImageDirectoryEntryToDataFn fnRtlImageDirectoryEntryToData;
if (fnRtlImageDirectoryEntryToData == nullptr) {
fnRtlImageDirectoryEntryToData =
reinterpret_cast<RtlImageDirectoryEntryToDataFn>(GetProcAddress(
GetModuleHandleA("ntdll.dll"), "RtlImageDirectoryEntryToData"));
}
// 获取导出表
PIMAGE_EXPORT_DIRECTORY exportDirectory =
static_cast<PIMAGE_EXPORT_DIRECTORY>(fnRtlImageDirectoryEntryToData(
reinterpret_cast<PUCHAR>(moduleBase), TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize));
if (exportDirectory) {
const DWORD numberOfNames = exportDirectory->NumberOfNames;
PDWORD addressOfFunctions =
reinterpret_cast<PDWORD>(reinterpret_cast<PUCHAR>(moduleBase) +
exportDirectory->AddressOfFunctions);
PDWORD addressOfNames =
reinterpret_cast<PDWORD>(reinterpret_cast<PUCHAR>(moduleBase) +
exportDirectory->AddressOfNames);
PWORD addressOfNameOrdinals =
reinterpret_cast<PWORD>(reinterpret_cast<PUCHAR>(moduleBase) +
exportDirectory->AddressOfNameOrdinals);
// 遍历导出函数
for (size_t i = 0; i < numberOfNames; i++) {
PCHAR functionName = reinterpret_cast<PCHAR>(
reinterpret_cast<PUCHAR>(moduleBase) + addressOfNames[i]);
// 获取函数RVA
const DWORD functionRva =
addressOfFunctions[addressOfNameOrdinals[i]];
// 创建导出数据结构
moudle_export exportData{};
memcpy(exportData.name, functionName, strlen(functionName));
exportData.function_address = functionRva;
exportData.ordinal = static_cast<WORD>(
addressOfNameOrdinals[i] + exportDirectory->Base); // 设置序号
export_list.push_back(
std::make_shared<moudle_export>(exportData));
}
}
return export_list;
}
auto Sandbox::ResolveImportExports() -> void {
for (auto module : m_moduleList) {
if (module->base == m_peInfo->RecImageBase) {
continue;
}
module->export_function = ResolveExport(module->real_base);
for (const auto item : module->export_function) {
if (LOG_LEVEL > 0) {
printf("[ResolveImportExports] import export: [%s] %s => %llx\n", module->name,
item->name, item->function_address);
}
m_exportFuncDict.push_back(item);
}
}
}
auto Sandbox::mapSystemModuleToVmByName(std::string systemName) -> void {
std::string tempMatchName = systemName;
std::transform(tempMatchName.begin(), tempMatchName.end(), tempMatchName.begin(),
[](unsigned char c) { return std::toupper(c); });
for (auto module : m_moduleList) {
std::string listModuleName = module->name;
std::transform(listModuleName.begin(), listModuleName.end(), listModuleName.begin(),
[](unsigned char c) { return std::toupper(c); });
if (tempMatchName == listModuleName) {
if (LOG_LEVEL > 0) {
printf("skip module name: %s (already loaded)\n", module->name);
}
return;
}
}
// 构建模块路径
const std::string systemDir =
m_peInfo->isX64 ? "\\System32\\" : "\\SysWOW64\\";
char windowsPath[MAX_PATH];
if (!GetWindowsDirectoryA(windowsPath, sizeof(windowsPath))) {
throw std::runtime_error("Failed to get Windows directory");
}
const std::string modulePath =
std::string(windowsPath) + systemDir + systemName;
// 加载PE模块
size_t mappedPeSize = 0;
const auto moduleBase = reinterpret_cast<uint64_t>(
peconv::load_pe_module(modulePath.c_str(), mappedPeSize, false, false));
if (!moduleBase) {
return;
}
// 添加到虚拟机
PushModuleToVM(systemName.c_str(), moduleBase, mappedPeSize);
}
auto Sandbox::processImportModule(const moudle_import* importModule) -> void {
std::string impModule = importModule->dll_name;
std::transform(impModule.begin(), impModule.end(), impModule.begin(),
[](unsigned char c) { return std::toupper(c); });
mapSystemModuleToVmByName(impModule);
}
auto Sandbox::ResoveImport() -> void {
// 处理延迟导入
peconv::load_delayed_imports(static_cast<BYTE*>(m_peInfo->peBuffer), 0);
// 解析导入表
cListImportNames importCallback(static_cast<BYTE*>(m_peInfo->peBuffer),
m_peInfo->peSize, m_impFuncDict,
m_impFuncOrdinalDict);
if (!peconv::process_import_table(static_cast<BYTE*>(m_peInfo->peBuffer),
m_peInfo->peSize, &importCallback)) {
throw std::runtime_error("Failed to process import table");
}
// 处理每个导入模块
for (const auto& importModule : m_impFuncDict) {
processImportModule(importModule.get());
}
for (const auto& importModule : m_impFuncOrdinalDict) {
mapSystemModuleToVmByName(importModule->dll_name);
}
}
/*
// 在InitEnv函数之前添加这个函数
void Sandbox::RegisterComApis() {
// 注册COM相关API
_fakeApi coInitializeEx = {Api_CoInitializeEx, 2}; // pvReserved, dwCoInit
_fakeApi coCreateInstance = {
Api_CoCreateInstance, 5}; // rclsid, pUnkOuter, dwClsContext, riid, ppv
_fakeApi variantInit = {Api_VariantInit, 1}; // pvarg
_fakeApi variantClear = {Api_VariantClear, 1}; // pvarg
_fakeApi sysAllocString = {Api_SysAllocString, 1}; // psz
// 将API添加到映射表中
m_apiMap["CoInitializeEx"] = coInitializeEx;
m_apiMap["CoCreateInstance"] = coCreateInstance;
m_apiMap["VariantInit"] = variantInit;
m_apiMap["VariantClear"] = variantClear;
m_apiMap["SysAllocString"] = sysAllocString;
}
*/
// 在InitEnv函数中调用RegisterComApis
auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
m_peInfo = peInfo;
if (cs_open(CS_ARCH_X86, peInfo->isX64 ? CS_MODE_64 : CS_MODE_32,
&m_csHandle) != CS_ERR_OK) {
throw std::runtime_error("Failed to initialize Capstone");
}
if (uc_open(UC_ARCH_X86, peInfo->isX64 ? UC_MODE_64 : UC_MODE_32,
&m_ucEngine) != UC_ERR_OK) {
cs_close(&m_csHandle); // 清理已分配的capstone资源
throw std::runtime_error("Failed to initialize Unicorn");
}
SetupVirtualMachine();
// 一定要确保他是第一个.
auto newModule = CreateModuleInfo(
"huoji.exe", m_peInfo->RecImageBase, m_peInfo->RecImageBase,
reinterpret_cast<uint64_t>(m_peInfo->peBuffer));
_ASSERTE(m_moduleList.size() == 0);
m_moduleList.push_back(newModule);
// 将模块添加到LDR链表中
if (m_peInfo->isX64) {
AddModuleToLdr(newModule);
}
ResoveImport();
ResolveImportExports();
// 修复导入表
cFixImprot importFixer(this);
if (!peconv::load_imports(m_peInfo->peBuffer, &importFixer)) {
throw std::runtime_error("Failed to fix imports");
}
//检查有没有ntdll
bool isFoundNtdll = false;
bool isFoundKernelBase = false;
for (const auto& module : this->GetModuleList()) {
//我tm也不知道为什么 有些病毒这玩意找小写....然后kernel32.dll找大写.wtf is that?
if (module->name == "ntdll.dll") {
isFoundNtdll = true;
}
//真的很懒了,这个是按TAB一键出来的
if (module->name == "KERNELBASE.dll") {
isFoundKernelBase = true;
}
if (isFoundKernelBase && isFoundNtdll) {
break;
}
}
if (isFoundNtdll == false) {
if (LOG_LEVEL > 4) {
printf("Not ntdll.dll Found, manual map it \n");
}
mapSystemModuleToVmByName("ntdll.dll");
}
if (isFoundKernelBase == false) {
if (LOG_LEVEL > 4) {
printf("Not kernelbase.dll Found, manual map it \n");
}
mapSystemModuleToVmByName("kernelbase.dll");
}
// 闭合ldr
FinalizeLdrLinks();
// 给所有导入表加c3
/*
for (const auto& module : this->GetModuleList()) {
// 遍历导出函数查找对应名称
for (const auto& exp : module->export_function) {
auto inMemAddr = module->base + exp->function_address;
uc_mem_write(m_ucEngine, inMemAddr, "\xCC", sizeof(char));
}
}
*/
// 挂导入表钩子
for (const auto& module : this->GetModuleList()) {
// 遍历导出函数查找对应名称
for (const auto& exp : module->export_function) {
auto inMemAddr = module->base + exp->function_address;
uc_hook_add(m_ucEngine, &exp->sys_ook, UC_HOOK_CODE, sandboxCallbacks::handleApiCall,(void*)this, inMemAddr, inMemAddr + 5, 0);
}
}
uc_err ucErr = uc_mem_map(m_ucEngine, m_peInfo->RecImageBase,
m_peInfo->peSize, UC_PROT_ALL);
if (ucErr != UC_ERR_OK) {
throw std::runtime_error("Failed to map memory");
}
uc_mem_write(m_ucEngine, m_peInfo->RecImageBase, m_peInfo->peBuffer,
m_peInfo->peSize);
printf("map file to vm file: %llx\n", m_peInfo->RecImageBase);
printf("map file to vm size: %llx\n", m_peInfo->peSize);
InitCommandLine(peInfo->inputFilePath);
}
auto Sandbox::Run(uint64_t address) -> void {
// 初始化堆栈
uc_err err = uc_mem_map(m_ucEngine, m_stackBase, m_stackSize,
UC_PROT_READ | UC_PROT_WRITE);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to map stack memory");
}
// 初始化堆
err = uc_mem_map(m_ucEngine, m_heapBase, m_heapSize,
UC_PROT_READ | UC_PROT_WRITE);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to map heap memory");
}
// 设置寄存器
uint64_t rsp = m_stackEnd - 256;
err = uc_reg_write(m_ucEngine,
m_peInfo->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP, &rsp);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to write stack pointer");
}
uint64_t rbp =
rsp - (m_peInfo->isX64 ? sizeof(uint64_t) : sizeof(uint32_t));
uc_reg_write(m_ucEngine, m_peInfo->isX64 ? UC_X86_REG_RBP : UC_X86_REG_EBP,
&rbp);
// 设置入口点
uint64_t entryPoint = (m_peInfo->RecImageBase + m_peInfo->entryPoint);
// 添加钩子
uc_hook hook_code, hook_mem, hook_mem_unmap, hook_mem_write, hook_syscall;
// 代码执行钩子
err = uc_hook_add(m_ucEngine, &hook_code, UC_HOOK_CODE,
reinterpret_cast<void*>(sandboxCallbacks::handleCodeRun),
this, 1, 0);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add code hook");
}
// 内存读取钩子
err =
uc_hook_add(m_ucEngine, &hook_mem, UC_HOOK_MEM_READ | UC_HOOK_MEM_FETCH,
reinterpret_cast<void*>(sandboxCallbacks::handleMemoryRead),
this, 1, 0);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add memory read hook");
}
// 未映射内存访问钩子
err = uc_hook_add(
m_ucEngine, &hook_mem_unmap,
UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_MEM_READ_UNMAPPED |
UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_FETCH_PROT,
reinterpret_cast<void*>(sandboxCallbacks::handleMemoryUnmapRead), this,
1, 0);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add unmapped memory hook");
}
// 内存写入钩子
err = uc_hook_add(
m_ucEngine, &hook_mem_write, UC_HOOK_MEM_WRITE | UC_HOOK_MEM_WRITE_PROT,
reinterpret_cast<void*>(sandboxCallbacks::handleMemoryWrite), this, 1,
0);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add memory write hook");
}
// 系统调用钩子
err = uc_hook_add(m_ucEngine, &hook_syscall, UC_HOOK_INTR | UC_HOOK_INSN,
reinterpret_cast<void*>(sandboxCallbacks::handleSyscall),
this, 1, 0, UC_X86_INS_SYSCALL);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add syscall hook");
}
// 系统调用钩子
err = uc_hook_add(m_ucEngine, &hook_syscall, UC_HOOK_INTR | UC_HOOK_INSN,
reinterpret_cast<void*>(sandboxCallbacks::handleSyscall),
this, 1, 0, UC_X86_INS_SYSCALL);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add syscall hook");
}
auto customIP = address;
// 设置EIP/RIP
err = uc_reg_write(m_ucEngine,
m_peInfo->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP,
&entryPoint);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to set entry point");
}
InitApiHooks();
std::cout << "Starting execution at " << std::hex << entryPoint
<< std::endl;
//uint64_t timeout = 2 * 60 * 1000 * 1000;
uint64_t timeout = 0;
// 1.入口点是必须跑的
if (m_peInfo->isDll) {
// 给rcx和rdx设置dll应该设置的
auto dll_fdwReason = 1; // DLL_PROCESS_ATTACH
if (m_peInfo->isX64) {
uc_reg_write(m_ucEngine, UC_X86_REG_RCX, &m_peInfo->RecImageBase);
uc_reg_write(m_ucEngine, UC_X86_REG_RDX, &dll_fdwReason);
} else {
// 32位使用栈传参而不是寄存器传参
uint32_t rsp;
uc_reg_read(m_ucEngine, UC_X86_REG_ESP, &rsp);
// 为参数腾出空间
rsp -= 3 * 4; // 三个参数hinstDLL, fdwReason, lpvReserved
uc_reg_write(m_ucEngine, UC_X86_REG_ESP, &rsp);
// 按照从右到左的顺序压栈
uint32_t lpvReserved = 0; // 第三个参数为NULL
uint32_t reason = dll_fdwReason; // DLL_PROCESS_ATTACH
uint32_t imageBase = static_cast<uint32_t>(m_peInfo->RecImageBase);
// 按照从右到左的调用约定写入参数到栈上
uc_mem_write(m_ucEngine, rsp, &lpvReserved,
sizeof(uint32_t)); // lpvReserved (最右侧参数最先入栈)
uc_mem_write(m_ucEngine, rsp + 4, &reason,
sizeof(uint32_t)); // fdwReason (中间参数次之入栈)
uc_mem_write(m_ucEngine, rsp + 8, &imageBase,
sizeof(uint32_t)); // hinstDLL (最左侧参数最后入栈)
// 在Windows下DLL的返回地址也需要压栈
uint32_t returnAddress = 0xABABABAB; // 虚拟的返回地址
rsp -= 4; // 为返回地址腾出空间
uc_reg_write(m_ucEngine, UC_X86_REG_ESP, &rsp);
uc_mem_write(m_ucEngine, rsp, &returnAddress, sizeof(uint32_t));
}
}
err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, timeout, 0);
// 2. 有自定义地址 再跑自定义地址
std::cerr << "Entry Point Emulation error: " << uc_strerror(err)
<< std::endl;
if (address != 0) {
err = uc_emu_start(m_ucEngine, address + MAIN_MODULE_BASE, m_peInfo->imageEnd, timeout, 0);
std::cerr << "Custom Emulation error: " << uc_strerror(err)
<< std::endl;
}
}
auto Sandbox::GetEnvString() -> std::vector<wchar_t> {
std::vector<wchar_t> envBlock;
// 添加一些基本的环境变量
const std::wstring vars[] = {
L"ALLUSERSPROFILE=C:\\ProgramData",
L"APPDATA=C:\\Users\\User\\AppData\\Roaming",
L"CommonProgramFiles=C:\\Program Files\\Common Files",
L"COMPUTERNAME=DESKTOP",
L"ComSpec=C:\\Windows\\system32\\cmd.exe",
L"HOMEDRIVE=C:",
L"HOMEPATH=\\Users\\User",
L"LOCALAPPDATA=C:\\Users\\User\\AppData\\Local",
L"NUMBER_OF_PROCESSORS=8",
L"OS=Windows_NT",
L"Path=C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem",
L"PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC",
L"PROCESSOR_ARCHITECTURE=AMD64",
L"ProgramData=C:\\ProgramData",
L"ProgramFiles=C:\\Program Files",
L"PROMPT=$P$G",
L"SystemDrive=C:",
L"SystemRoot=C:\\Windows",
L"TEMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
L"TMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
L"USERDOMAIN=DESKTOP",
L"USERNAME=User",
L"USERPROFILE=C:\\Users\\User",
L"windir=C:\\Windows"};
// 将环境变量添加到块中
for (const auto& var : vars) {
envBlock.insert(envBlock.end(), var.begin(), var.end());
envBlock.push_back(L'\0'); // 每个变量以null结尾
}
envBlock.push_back(L'\0'); // 环境块以额外的null结尾
return envBlock;
}
auto Sandbox::GetEnvStringsSize() -> size_t {
return GetEnvString().size() * sizeof(wchar_t);
}
auto Sandbox::getVirtualMemorySize(BYTE* peBuffer) -> size_t {
if (!peBuffer) {
return 0;
}
// 解析PE头
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(peBuffer);
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
return 0;
}
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<LPBYTE>(peBuffer) + dosHeader->e_lfanew);
// 获取区段头
auto* sectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<PUCHAR>(ntHeaders) + sizeof(ntHeaders->Signature) +
sizeof(ntHeaders->FileHeader) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
DWORD minOffset = UINT_MAX;
DWORD totalSize = 0;
// 遍历所有区段
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
const auto& section = sectionHeader[i];
// 查找最小虚拟地址偏移
if (section.VirtualAddress < minOffset) {
minOffset = section.VirtualAddress;
}
// 累加虚拟大小
totalSize += section.Misc.VirtualSize;
}
// 添加最小偏移到总大小
totalSize += minOffset;
return static_cast<size_t>(totalSize);
}