#include "sandbox.h" #include "sandbox_callbacks.h" std::string getDllNameFromApiSetMap(const std::string& apiSet) { const std::wstring wApiSet(apiSet.begin(), apiSet.end()); // 获取系统版本信息 using RtlGetVersionFunc = LONG(__stdcall*)(PRTL_OSVERSIONINFOW); const auto pRtlGetVersion = reinterpret_cast( GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion")); RTL_OSVERSIONINFOEXW verInfo{}; verInfo.dwOSVersionInfoSize = sizeof(verInfo); pRtlGetVersion(reinterpret_cast(&verInfo)); const ULONG verShort = (verInfo.dwMajorVersion << 8) | (verInfo.dwMinorVersion << 4) | verInfo.wServicePackMajor; if (verShort >= static_cast(WinVer::kWin10)) { const auto apiSetMap = reinterpret_cast( reinterpret_cast(__readgsqword(0x60))->ApiSetMap); const auto apiSetMapAsNumber = reinterpret_cast(apiSetMap); auto nsEntry = reinterpret_cast( apiSetMap->Start + apiSetMapAsNumber); // 遍历API集合查找匹配项 for (ULONG i = 0; i < apiSetMap->Count; i++) { UNICODE_STRING nameString{}, valueString{}; nameString.MaximumLength = static_cast(nsEntry->NameLength); nameString.Length = static_cast(nsEntry->NameLength); nameString.Buffer = reinterpret_cast(apiSetMapAsNumber + nsEntry->NameOffset); const std::wstring name(nameString.Buffer, nameString.Length / sizeof(WCHAR)); const std::wstring fullName = name + L".dll"; if (_wcsicmp(wApiSet.c_str(), fullName.c_str()) == 0) { if (nsEntry->ValueCount == 0) { return ""; } const auto valueEntry = reinterpret_cast( apiSetMapAsNumber + nsEntry->ValueOffset); valueString.Buffer = reinterpret_cast( apiSetMapAsNumber + valueEntry->ValueOffset); valueString.MaximumLength = static_cast(valueEntry->ValueLength); valueString.Length = static_cast(valueEntry->ValueLength); const std::wstring value(valueString.Buffer, valueString.Length / sizeof(WCHAR)); return {value.begin(), value.end()}; } ++nsEntry; } } else { // 不支持Windows 10以下版本 throw std::runtime_error("Unsupported Windows version"); } return ""; } class ImportResolver : public peconv::t_function_resolver { public: explicit ImportResolver(std::map context) : _functionMap(std::move(context)) {} FARPROC resolve_func(LPSTR libName, LPSTR funcName) override { return reinterpret_cast(_functionMap[std::string(funcName)]); } private: std::map _functionMap; }; class cListImportNames : public peconv::ImportThunksCallback { public: cListImportNames(BYTE* _modulePtr, size_t _moduleSize, std::vector>& name_to_addr) : ImportThunksCallback(_modulePtr, _moduleSize), nameToAddr(name_to_addr) {} virtual bool processThunks(LPSTR lib_name, ULONG_PTR origFirstThunkPtr, ULONG_PTR firstThunkPtr) { if (this->is64b) { IMAGE_THUNK_DATA64* desc = reinterpret_cast(origFirstThunkPtr); ULONGLONG* call_via = reinterpret_cast(firstThunkPtr); return processThunks_tpl( lib_name, desc, call_via, IMAGE_ORDINAL_FLAG64); } IMAGE_THUNK_DATA32* desc = reinterpret_cast(origFirstThunkPtr); DWORD* call_via = reinterpret_cast(firstThunkPtr); return processThunks_tpl( lib_name, desc, call_via, IMAGE_ORDINAL_FLAG32); } protected: template 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((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(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(); 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); } return true; } std::vector>& nameToAddr; }; Sandbox::Sandbox() {} Sandbox::~Sandbox() {} auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void { for (auto module : m_moduleList) { if (module->real_base == moduleBase) { printf("skip module name: %s (already loaded)\n", module->name); return; } } // 解析PE头 auto* dosHeader = reinterpret_cast(moduleBase); auto* ntHeaders = reinterpret_cast( reinterpret_cast(moduleBase) + dosHeader->e_lfanew); // 获取区段对齐值 DWORD sectionAlignment = (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) ? reinterpret_cast(ntHeaders) ->OptionalHeader.SectionAlignment : ntHeaders->OptionalHeader.SectionAlignment; // 获取区段头 auto* sectionHeader = reinterpret_cast( reinterpret_cast(ntHeaders) + sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) + ntHeaders->FileHeader.SizeOfOptionalHeader); // 创建新模块 struct_moudle newModule{}; strncpy(newModule.name, dllName, strlen(dllName)); newModule.base = this->m_peInfo->isX64 ? moduleBase : static_cast(moduleBase); newModule.real_base = moduleBase; 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 = AlignSize(max(section.Misc.VirtualSize, section.SizeOfRawData), sectionAlignment); // 创建区段信息 moudle_section newSection{}; strncpy(newSection.name, reinterpret_cast(section.Name), 8); newSection.base = section.VirtualAddress; newSection.size = sectionSize; newSection.protect_flag = protection; newModule.sections.push_back( std::make_shared(newSection)); std::cout << "[PE] " << dllName << " Section found: " << newSection.name << '\n'; } m_moduleList.push_back(std::make_shared(newModule)); printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule.name, newModule.base, newModule.size); uc_mem_map(m_ucEngine, newModule.base, newModule.size, UC_PROT_READ | UC_PROT_EXEC); uc_mem_write(m_ucEngine, newModule.base, (void*)moduleBase, newModule.size); } auto Sandbox::ResolveExport() -> void { DWORD exportSize = 0; static RtlImageDirectoryEntryToDataFn fnRtlImageDirectoryEntryToData; if (fnRtlImageDirectoryEntryToData == nullptr) { fnRtlImageDirectoryEntryToData = reinterpret_cast(GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlImageDirectoryEntryToData")); } // 获取导出表 PIMAGE_EXPORT_DIRECTORY exportDirectory = static_cast(fnRtlImageDirectoryEntryToData( m_peInfo->peBuffer, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize)); if (exportDirectory) { const DWORD numberOfNames = exportDirectory->NumberOfNames; PDWORD addressOfFunctions = reinterpret_cast(static_cast(m_peInfo->peBuffer) + exportDirectory->AddressOfFunctions); PDWORD addressOfNames = reinterpret_cast(static_cast(m_peInfo->peBuffer) + exportDirectory->AddressOfNames); PWORD addressOfNameOrdinals = reinterpret_cast(static_cast(m_peInfo->peBuffer) + exportDirectory->AddressOfNameOrdinals); // 遍历导出函数 for (size_t i = 0; i < numberOfNames; i++) { PCHAR functionName = reinterpret_cast( static_cast(m_peInfo->peBuffer) + addressOfNames[i]); // 获取函数RVA const DWORD functionRva = addressOfFunctions[addressOfNameOrdinals[i]]; // 创建导出数据结构 moudle_export exportData{}; memcpy(exportData.name, functionName, strlen(functionName)); exportData.function_address = functionRva; m_exportFuncDict.push_back( std::make_shared(exportData)); } } } auto Sandbox::processImportModule(const moudle_import* importModule) -> void { for (auto module : m_moduleList) { if (strcmp(module->name, importModule->dll_name) == 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 + importModule->dll_name; // 加载PE模块 size_t mappedPeSize = 0; const auto moduleBase = reinterpret_cast( peconv::load_pe_module(modulePath.c_str(), mappedPeSize, false, false)); if (!moduleBase) { return; } // 添加到虚拟机 PushModuleToVM(importModule->dll_name, moduleBase); } auto Sandbox::ResoveImport() -> void { // 处理延迟导入 peconv::load_delayed_imports(static_cast(m_peInfo->peBuffer), 0); // 解析导入表 cListImportNames importCallback(static_cast(m_peInfo->peBuffer), m_peInfo->peSize, m_impFuncDict); if (!peconv::process_import_table(static_cast(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()); } } auto Sandbox::SetupVirtualMachine() -> void { SegmentSelector cs = {0}; cs.fields.index = 1; uc_reg_write(m_ucEngine, UC_X86_REG_CS, &cs.all); SegmentSelector ds = {0}; ds.fields.index = 2; uc_reg_write(m_ucEngine, UC_X86_REG_DS, &ds.all); SegmentSelector ss = {0}; ss.fields.index = 2; uc_reg_write(m_ucEngine, UC_X86_REG_SS, &ss.all); SegmentSelector es = {0}; es.fields.index = 2; uc_reg_write(m_ucEngine, UC_X86_REG_ES, &es.all); SegmentSelector gs = {0}; gs.fields.index = 2; uc_reg_write(m_ucEngine, UC_X86_REG_GS, &gs.all); FlagRegister eflags = {0}; eflags.fields.id = 1; eflags.fields.intf = 1; eflags.fields.reserved1 = 1; uc_reg_write(m_ucEngine, UC_X86_REG_EFLAGS, &eflags.all); uint64_t cr8 = 0; uc_reg_write(m_ucEngine, UC_X86_REG_CR8, &cr8); /* 映射 m_KSharedUserDataBase */ uint64_t m_KSharedUserDataBase = 0x7FFE0000; uint64_t m_KSharedUserDataEnd = 0x7FFE0FFF; // 0x7FFE2000 uint64_t m_KSharedUserDataSize = AlignSize(m_KSharedUserDataEnd - m_KSharedUserDataBase, PAGE_SIZE); uc_mem_map(m_ucEngine, m_KSharedUserDataBase, m_KSharedUserDataSize, UC_PROT_READ); uc_mem_write(m_ucEngine, m_KSharedUserDataBase, (void*)m_KSharedUserDataBase, m_KSharedUserDataSize); m_tebBase = TEB_BASE; // 进程TEB地址 m_pebBase = PEB_BASE; // 进程PEB地址 // stack m_stackBase = this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32; m_stackSize = this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32; m_stackEnd = m_stackBase + m_stackSize; // heap m_heapBase = this->m_peInfo->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32; m_heapSize = this->m_peInfo->isX64 ? HEAP_SIZE_64 : HEAP_SIZE_32; m_heapEnd = m_heapBase + m_heapSize; // 根据PE文件类型设置PEB和TEB if (this->m_peInfo->isX64) { // 设置64位PEB m_peb64.ImageBaseAddress = m_peInfo->RecImageBase; m_pebEnd = m_pebBase + AlignSize(sizeof(X64PEB), PAGE_SIZE); m_tebEnd = m_tebBase + AlignSize(sizeof(X64TEB), PAGE_SIZE); // 设置64位TEB m_teb64.ClientId.UniqueProcess = GetCurrentProcessId(); m_teb64.ClientId.UniqueThread = GetCurrentThreadId(); m_teb64.ProcessEnvironmentBlock = reinterpret_cast(m_pebBase); m_teb64.NtTib.StackBase = (DWORD64)m_stackBase; m_teb64.NtTib.StackLimit = (DWORD64)m_stackSize; // 设置堆 m_peb64.ProcessHeap = m_heapBase; // 设置GS基址结构 m_gsBaseStruct.teb = m_tebBase; m_gsBaseStruct.peb = m_pebBase; uint64_t gsAllocSize = AlignSize(sizeof(struct_gs_base), PAGE_SIZE); // 映射PEB到虚拟内存 uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase, UC_PROT_READ | UC_PROT_WRITE); uc_mem_write(m_ucEngine, m_pebBase, &m_peb64, sizeof(X64PEB)); // 映射TEB到虚拟内存 uc_mem_map(m_ucEngine, m_tebBase, m_tebEnd - m_tebBase, UC_PROT_READ | UC_PROT_WRITE); uc_mem_write(m_ucEngine, m_tebBase, &m_teb64, sizeof(X64TEB)); // 映射GS基址结构到虚拟内存 uc_mem_map(m_ucEngine, m_gsBase, gsAllocSize, UC_PROT_READ); uc_mem_write(m_ucEngine, m_gsBase, &m_gsBaseStruct, sizeof(struct_gs_base)); // 设置GS基址MSR uc_x86_msr msr; msr.rid = static_cast(Msr::kIa32GsBase); msr.value = m_gsBase; uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr); } else { // 设置32位PEB m_peb32.ImageBaseAddress = static_cast(m_peInfo->RecImageBase); m_pebEnd = m_pebBase + AlignSize(sizeof(X32PEB), PAGE_SIZE); m_tebEnd = m_tebBase + AlignSize(sizeof(X32TEB), PAGE_SIZE); // 设置32位TEB m_teb32.ClientId.UniqueProcess = GetCurrentProcessId(); m_teb32.ClientId.UniqueThread = GetCurrentThreadId(); m_teb32.ProcessEnvironmentBlock = static_cast(m_pebBase); m_teb32.NtTib.StackBase = static_cast(m_stackBase); m_teb32.NtTib.StackLimit = static_cast(m_stackSize); // 设置堆 m_peb32.ProcessHeap = static_cast(m_heapBase); // 映射PEB到虚拟内存 uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase, UC_PROT_READ | UC_PROT_WRITE); uc_mem_write(m_ucEngine, m_pebBase, &m_peb32, sizeof(X32PEB)); // 映射TEB到虚拟内存 uc_mem_map(m_ucEngine, m_tebBase, m_tebEnd - m_tebBase, UC_PROT_READ | UC_PROT_WRITE); uc_mem_write(m_ucEngine, m_tebBase, &m_teb32, sizeof(X32TEB)); // 对于32位,我们需要设置FS段寄存器指向TEB SegmentSelector fs = {0}; fs.fields.index = 3; uc_reg_write(m_ucEngine, UC_X86_REG_FS, &fs.all); // 设置FS基址MSR uc_x86_msr msr; msr.rid = static_cast(Msr::kIa32FsBase); msr.value = m_tebBase; uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr); } } auto Sandbox::InitEnv(std::shared_ptr 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"); } ResoveImport(); ResolveExport(); 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); SetupVirtualMachine(); } auto Sandbox::Run() -> 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 - 128; 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 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(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(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(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(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(sandboxCallbacks::handleSyscall), this, 1, 0, UC_X86_INS_SYSCALL); if (err != UC_ERR_OK) { throw std::runtime_error("Failed to add syscall hook"); } // 设置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"); } // 开始执行 std::cout << "Starting execution at " << std::hex << entryPoint << std::endl; err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, 0, 0); if (err != UC_ERR_OK) { std::cerr << "Emulation error: " << uc_strerror(err) << std::endl; // 32位环境下的错误处理 if (!m_peInfo->isX64) { uint32_t eip; uc_reg_read(m_ucEngine, UC_X86_REG_EIP, &eip); std::cerr << "Error occurred at EIP: 0x" << std::hex << eip << std::endl; // 尝试读取当前指令 uint8_t instruction[16]; if (uc_mem_read(m_ucEngine, eip, instruction, sizeof(instruction)) == UC_ERR_OK) { std::cerr << "Instruction bytes: "; for (int i = 0; i < 16; i++) { printf("%02X ", instruction[i]); } std::cerr << std::endl; } } } }