Files
awesome_anti_virus_engine/ai_anti_malware/sandbox.cpp

799 lines
30 KiB
C++
Raw Normal View History

2025-03-06 04:05:03 +08:00
#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;
}
2025-03-06 04:05:03 +08:00
class ImportResolver : public peconv::t_function_resolver {
public:
2025-03-06 04:05:03 +08:00
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:
2025-03-06 04:05:03 +08:00
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)
2025-03-06 04:05:03 +08:00
: ImportThunksCallback(_modulePtr, _moduleSize),
nameToAddr(name_to_addr),
ordinalImportFunc(name_to_ordinal) {}
2025-03-06 04:05:03 +08:00
virtual bool processThunks(LPSTR lib_name, ULONG_PTR origFirstThunkPtr,
ULONG_PTR firstThunkPtr) {
2025-03-06 04:05:03 +08:00
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:
2025-03-06 04:05:03 +08:00
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) {
2025-03-06 04:05:03 +08:00
DWORD call_via_rva = static_cast<DWORD>((ULONG_PTR)call_via -
(ULONG_PTR)this->modulePtr);
2025-03-06 04:05:03 +08:00
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);
2025-03-06 04:05:03 +08:00
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());
2025-03-06 04:05:03 +08:00
import_data->function_address = call_via_rva;
import_data->is_delayed_import = false;
nameToAddr.push_back(import_data);
}
else {
2025-03-20 19:56:39 +08:00
auto importFunc = std::make_shared<moudle_import_ordinal>();
T_FIELD raw_ordinal = desc->u1.Ordinal & (~ordinal_flag);
importFunc->dll_name = lib_name;
2025-03-20 19:56:39 +08:00
importFunc->function_address = call_via_rva;
importFunc->ordinal = raw_ordinal;
ordinalImportFunc.push_back(importFunc);
}
2025-03-06 04:05:03 +08:00
return true;
}
std::vector<std::shared_ptr<moudle_import>>& nameToAddr;
2025-03-20 19:56:39 +08:00
std::vector<std::shared_ptr<moudle_import_ordinal>>& ordinalImportFunc;
2025-03-06 04:05:03 +08:00
};
2025-03-06 18:39:01 +08:00
class cFixImprot : public peconv::t_function_resolver {
public:
2025-03-06 18:39:01 +08:00
// 构造函数接收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) {
// 检查模块名是否匹配
2025-04-23 03:48:16 +08:00
if (module->name == std::string(lib_name) == 0) {
2025-03-20 04:56:31 +08:00
// 遍历该模块的导出函数
for (const auto& exp : module->export_function) {
2025-03-06 18:39:01 +08:00
// 检查函数名是否匹配
if (strcmp(exp->name, func_name) == 0) {
auto newBase = reinterpret_cast<FARPROC>(
module->base + exp->function_address);
#ifdef LOG_LEVEL > 2
2025-03-06 18:39:01 +08:00
printf("fix import: %s => %llx \n", func_name, newBase);
// 返回在模拟器中的虚拟地址
#endif
2025-03-06 18:39:01 +08:00
return newBase;
}
}
}
}
2025-03-20 04:56:31 +08:00
// 如果没有找到精确匹配的模块名,尝试在所有模块中查找该函数
for (const auto& module : m_sandbox->m_moduleList) {
2025-03-20 04:56:31 +08:00
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
2025-03-20 04:56:31 +08:00
printf("fix import (fallback): %s found in %s => %llx \n",
func_name, module->name, newBase);
// 返回在模拟器中的虚拟地址
#endif
return newBase;
}
//序号导出,非常癌症的修复.
2025-04-23 03:48:16 +08:00
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;
}
}
}
}
2025-03-20 04:56:31 +08:00
printf("Warning: Could not resolve import: %s from library: %s\n",
func_name, lib_name);
2025-03-18 22:26:09 +08:00
//__debugbreak();
2025-03-06 18:39:01 +08:00
return nullptr;
}
2025-03-06 04:05:03 +08:00
private:
2025-03-06 18:39:01 +08:00
Sandbox* m_sandbox; // Sandbox实例的指针
};
Sandbox::Sandbox() {
m_ucEngine = nullptr;
m_peInfo = nullptr;
m_nextWfpEngineHandle = (HANDLE)0x1000; // 初始化WFP引擎句柄
2025-03-20 04:56:31 +08:00
m_lastImpRead = {0, 0};
}
2025-03-06 04:05:03 +08:00
Sandbox::~Sandbox() {
// 清理WFP引擎资源
for (auto& pair : m_wfpEngines) {
delete pair.second;
}
m_wfpEngines.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);
}
}
2025-03-06 04:05:03 +08:00
auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase, uint64_t mappedSize) -> void {
2025-03-06 04:28:34 +08:00
for (auto module : m_moduleList) {
if (module->real_base == moduleBase) {
printf("skip module name: %s (already loaded)\n", module->name);
return;
}
2025-03-06 04:05:03 +08:00
}
2025-03-20 02:18:00 +08:00
if (m_usedModuleBase == 0) {
m_usedModuleBase = DLL_MODULE_BASE;
}
2025-03-09 00:06:37 +08:00
// 创建新模块
2025-03-20 04:56:31 +08:00
auto newModule =
CreateModuleInfo(dllName, AlignSize(m_usedModuleBase, PAGE_SIZE),
moduleBase, moduleBase);
2025-03-09 00:06:37 +08:00
2025-03-20 02:18:00 +08:00
m_usedModuleBase += PAGE_SIZE + newModule->size;
2025-03-09 00:06:37 +08:00
m_moduleList.push_back(newModule);
printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule->name,
newModule->base, newModule->size);
2025-03-20 04:56:31 +08:00
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");
}
2025-03-09 00:06:37 +08:00
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);
}
2025-03-09 00:06:37 +08:00
}
2025-04-23 03:48:16 +08:00
auto Sandbox::CreateModuleInfo(std::string dllName, uint64_t moduleBase,
2025-03-20 04:56:31 +08:00
uint64_t realModuleBase, uint64_t bufferAddress)
2025-03-09 00:06:37 +08:00
-> std::shared_ptr<struct_moudle> {
2025-03-06 04:05:03 +08:00
// 解析PE头
2025-03-09 00:06:37 +08:00
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(bufferAddress);
2025-03-06 04:05:03 +08:00
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
2025-03-09 00:06:37 +08:00
reinterpret_cast<LPBYTE>(bufferAddress) + dosHeader->e_lfanew);
2025-03-06 04:05:03 +08:00
// 获取区段对齐值
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{};
2025-04-23 03:48:16 +08:00
newModule.name = dllName.c_str();
2025-03-20 02:18:00 +08:00
newModule.base = moduleBase;
newModule.real_base = realModuleBase;
2025-03-06 04:05:03 +08:00
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;
// 计算区段大小
2025-03-09 00:06:37 +08:00
auto sectionSize = AlignToSectionAlignment(
max(section.Misc.VirtualSize, section.SizeOfRawData),
sectionAlignment);
2025-03-06 04:05:03 +08:00
// 创建区段信息
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';
}
2025-03-09 00:06:37 +08:00
return std::make_shared<struct_moudle>(newModule);
2025-03-06 04:05:03 +08:00
}
2025-03-09 00:06:37 +08:00
2025-03-06 18:39:01 +08:00
auto Sandbox::ResolveExport(uint64_t moduleBase)
-> std::vector<std::shared_ptr<moudle_export>> {
2025-03-22 01:59:30 +08:00
std::vector<std::shared_ptr<moudle_export>> export_list;
2025-03-06 04:05:03 +08:00
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(
2025-03-06 18:39:01 +08:00
reinterpret_cast<PUCHAR>(moduleBase), TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT, &exportSize));
2025-03-06 04:05:03 +08:00
if (exportDirectory) {
const DWORD numberOfNames = exportDirectory->NumberOfNames;
PDWORD addressOfFunctions =
2025-03-06 18:39:01 +08:00
reinterpret_cast<PDWORD>(reinterpret_cast<PUCHAR>(moduleBase) +
2025-03-06 04:05:03 +08:00
exportDirectory->AddressOfFunctions);
PDWORD addressOfNames =
2025-03-06 18:39:01 +08:00
reinterpret_cast<PDWORD>(reinterpret_cast<PUCHAR>(moduleBase) +
2025-03-06 04:05:03 +08:00
exportDirectory->AddressOfNames);
PWORD addressOfNameOrdinals =
2025-03-06 18:39:01 +08:00
reinterpret_cast<PWORD>(reinterpret_cast<PUCHAR>(moduleBase) +
2025-03-06 04:05:03 +08:00
exportDirectory->AddressOfNameOrdinals);
// 遍历导出函数
for (size_t i = 0; i < numberOfNames; i++) {
PCHAR functionName = reinterpret_cast<PCHAR>(
2025-03-06 18:39:01 +08:00
reinterpret_cast<PUCHAR>(moduleBase) + addressOfNames[i]);
2025-03-06 04:05:03 +08:00
// 获取函数RVA
const DWORD functionRva =
addressOfFunctions[addressOfNameOrdinals[i]];
// 创建导出数据结构
moudle_export exportData{};
memcpy(exportData.name, functionName, strlen(functionName));
exportData.function_address = functionRva;
2025-03-06 18:39:01 +08:00
exportData.ordinal = static_cast<WORD>(
addressOfNameOrdinals[i] + exportDirectory->Base); // 设置序号
2025-03-06 04:05:03 +08:00
2025-03-22 01:59:30 +08:00
export_list.push_back(
2025-03-06 04:05:03 +08:00
std::make_shared<moudle_export>(exportData));
}
}
2025-03-22 01:59:30 +08:00
return export_list;
2025-03-06 18:39:01 +08:00
}
auto Sandbox::ResolveImportExports() -> void {
for (auto module : m_moduleList) {
2025-03-09 00:06:37 +08:00
if (module->base == m_peInfo->RecImageBase) {
continue;
}
2025-03-18 22:26:09 +08:00
2025-03-22 01:59:30 +08:00
module->export_function = ResolveExport(module->real_base);
for (const auto item : module->export_function) {
2025-03-09 03:19:40 +08:00
if (LOG_LEVEL > 0) {
printf("[ResolveImportExports] import export: [%s] %s => %llx\n", module->name,
item->name, item->function_address);
2025-03-09 03:19:40 +08:00
}
2025-03-18 22:26:09 +08:00
2025-03-22 01:59:30 +08:00
m_exportFuncDict.push_back(item);
2025-03-06 18:39:01 +08:00
}
}
2025-03-06 04:05:03 +08:00
}
auto Sandbox::mapSystemModuleToVmByName(std::string systemName) -> void {
2025-04-23 03:48:16 +08:00
std::string tempMatchName = systemName;
std::transform(tempMatchName.begin(), tempMatchName.end(), tempMatchName.begin(),
[](unsigned char c) { return std::toupper(c); });
2025-03-06 04:28:34 +08:00
for (auto module : m_moduleList) {
2025-04-23 03:48:16 +08:00
std::string listModuleName = module->name;
std::transform(listModuleName.begin(), listModuleName.end(), listModuleName.begin(),
[](unsigned char c) { return std::toupper(c); });
if (tempMatchName == listModuleName) {
2025-03-09 03:19:40 +08:00
if (LOG_LEVEL > 0) {
printf("skip module name: %s (already loaded)\n", module->name);
}
2025-03-06 04:28:34 +08:00
return;
}
}
2025-03-06 04:05:03 +08:00
// 构建模块路径
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;
2025-03-06 04:05:03 +08:00
// 加载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 {
2025-04-23 03:48:16 +08:00
std::string impModule = importModule->dll_name;
std::transform(impModule.begin(), impModule.end(), impModule.begin(),
[](unsigned char c) { return std::toupper(c); });
2025-04-23 03:48:16 +08:00
mapSystemModuleToVmByName(impModule);
2025-03-06 04:05:03 +08:00
}
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);
2025-03-06 04:05:03 +08:00
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);
}
2025-03-06 04:05:03 +08:00
}
2025-04-23 03:48:16 +08:00
/*
// 在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
2025-03-06 04:05:03 +08:00
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");
}
2025-04-23 03:48:16 +08:00
SetupVirtualMachine();
2025-03-09 00:06:37 +08:00
// 一定要确保他是第一个.
2025-03-20 04:56:31 +08:00
auto newModule = CreateModuleInfo(
"huoji.exe", m_peInfo->RecImageBase, m_peInfo->RecImageBase,
reinterpret_cast<uint64_t>(m_peInfo->peBuffer));
2025-04-23 03:48:16 +08:00
2025-03-09 00:06:37 +08:00
_ASSERTE(m_moduleList.size() == 0);
m_moduleList.push_back(newModule);
// 将模块添加到LDR链表中
if (m_peInfo->isX64) {
AddModuleToLdr(newModule);
}
2025-03-06 04:05:03 +08:00
ResoveImport();
2025-03-06 18:39:01 +08:00
ResolveImportExports();
// 修复导入表
cFixImprot importFixer(this);
if (!peconv::load_imports(m_peInfo->peBuffer, &importFixer)) {
throw std::runtime_error("Failed to fix imports");
}
2025-04-23 03:48:16 +08:00
//检查有没有ntdll
bool isFoundNtdll = false;
bool isFoundKernelBase = false;
2025-04-23 03:48:16 +08:00
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");
}
2025-03-19 20:47:26 +08:00
// 给所有导入表加c3
2025-03-18 22:26:09 +08:00
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));
}
}
2025-03-06 04:05:03 +08:00
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);
2025-03-06 18:39:01 +08:00
InitCommandLine(peInfo->inputFilePath);
2025-03-06 04:05:03 +08:00
}
auto Sandbox::Run(uint64_t address) -> void {
2025-03-06 04:05:03 +08:00
// 初始化堆栈
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");
}
// 设置寄存器
2025-03-07 01:47:01 +08:00
uint64_t rsp = m_stackEnd - 256;
2025-03-06 04:05:03 +08:00
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");
}
2025-03-07 01:47:01 +08:00
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);
2025-03-06 04:05:03 +08:00
// 设置入口点
uint64_t entryPoint = (m_peInfo->RecImageBase + m_peInfo->entryPoint);
2025-03-06 04:05:03 +08:00
// 添加钩子
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");
}
2025-03-18 22:26:09 +08:00
// 系统调用钩子
err = uc_hook_add(m_ucEngine, &hook_syscall, UC_HOOK_INTR | UC_HOOK_INSN,
2025-03-19 20:47:26 +08:00
reinterpret_cast<void*>(sandboxCallbacks::handleSyscall),
this, 1, 0, UC_X86_INS_SYSCALL);
2025-03-18 22:26:09 +08:00
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add syscall hook");
}
auto customIP = address;
2025-03-06 04:05:03 +08:00
// 设置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");
}
2025-03-07 01:47:01 +08:00
InitApiHooks();
2025-03-06 04:05:03 +08:00
std::cout << "Starting execution at " << std::hex << entryPoint
<< std::endl;
2025-04-23 03:48:16 +08:00
//uint64_t timeout = 2 * 60 * 1000 * 1000;
uint64_t timeout = 0;
// 1.入口点是必须跑的
if (m_peInfo->isDll) {
// 给rcx和rdx设置dll应该设置的
2025-03-19 20:47:26 +08:00
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) {
2025-04-23 03:48:16 +08:00
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;
}
2025-03-06 04:05:03 +08:00
}
2025-03-07 19:27:05 +08:00
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",
2025-03-20 04:56:31 +08:00
L"TEMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
L"TMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
2025-03-07 19:27:05 +08:00
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);
}
2025-03-09 00:06:37 +08:00
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);
}