diff --git a/ai_anti_malware/head.h b/ai_anti_malware/head.h index f99b4c4..0cc949c 100644 --- a/ai_anti_malware/head.h +++ b/ai_anti_malware/head.h @@ -1,5 +1,5 @@ #pragma once -#define LOG_LEVEL 0 +#define LOG_LEVEL 1 #define _CRT_SECURE_NO_WARNINGS #include diff --git a/ai_anti_malware/native_struct.h b/ai_anti_malware/native_struct.h index 5301b1a..6144e84 100644 --- a/ai_anti_malware/native_struct.h +++ b/ai_anti_malware/native_struct.h @@ -1000,6 +1000,10 @@ struct moudle_import { void* function_callback; bool is_delayed_import; }; +struct moudle_import_ordinal { + uint64_t function_address; + uint64_t ordinal; +}; struct moudle_section { char name[9]; ULONG base; diff --git a/ai_anti_malware/sandbox.cpp b/ai_anti_malware/sandbox.cpp index 22c0dc2..208374b 100644 --- a/ai_anti_malware/sandbox.cpp +++ b/ai_anti_malware/sandbox.cpp @@ -103,9 +103,11 @@ class ImportResolver : public peconv::t_function_resolver { class cListImportNames : public peconv::ImportThunksCallback { public: cListImportNames(BYTE* _modulePtr, size_t _moduleSize, - std::vector>& name_to_addr) + std::vector>& name_to_addr, + std::vector>& name_to_ordinal) : ImportThunksCallback(_modulePtr, _moduleSize), - nameToAddr(name_to_addr) {} + nameToAddr(name_to_addr), + ordinalImportFunc(name_to_ordinal) {} virtual bool processThunks(LPSTR lib_name, ULONG_PTR origFirstThunkPtr, ULONG_PTR firstThunkPtr) { @@ -148,10 +150,19 @@ class cListImportNames : public peconv::ImportThunksCallback { import_data->is_delayed_import = false; nameToAddr.push_back(import_data); } + else { + auto importFunc = std::make_shared(); + T_FIELD raw_ordinal = desc->u1.Ordinal & (~ordinal_flag); + + importFunc->function_address = call_via_rva; + importFunc->ordinal = raw_ordinal; + ordinalImportFunc.push_back(importFunc); + } return true; } std::vector>& nameToAddr; + std::vector>& ordinalImportFunc; }; class cFixImprot : public peconv::t_function_resolver { public: @@ -455,8 +466,7 @@ 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); + cListImportNames importCallback(static_cast(m_peInfo->peBuffer), m_peInfo->peSize, m_impFuncDict, m_impFuncOrdinalDict); if (!peconv::process_import_table(static_cast(m_peInfo->peBuffer), m_peInfo->peSize, &importCallback)) { diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index f67d63d..128b447 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -275,6 +275,8 @@ class Sandbox { std::vector> m_impFuncDict; std::vector> m_exportFuncDict; std::vector> m_moduleList; + std::vector> m_impFuncOrdinalDict; + std::map> api_map; std::string m_commandLine; // 存储命令行字符串 // 创建一些基本的环境变量 diff --git a/ai_anti_malware/sandbox_api_com.cpp b/ai_anti_malware/sandbox_api_com.cpp index e6e91b9..7c08c13 100644 --- a/ai_anti_malware/sandbox_api_com.cpp +++ b/ai_anti_malware/sandbox_api_com.cpp @@ -4,179 +4,274 @@ #include #include "sandbox_api_com.h" -// COM 初始化状态跟踪 -static bool g_comInitialized = false; -// 计划任务COM组件具体实现 -class TaskServiceImpl : public TaskServiceSimulator { - private: - ULONG m_refCount = 1; - - public: - HRESULT QueryInterface(REFIID riid, void** ppv) override { - // 这里只模拟基本的ITaskService接口 - *ppv = this; - AddRef(); - return S_OK; - } - - ULONG AddRef() override { return ++m_refCount; } - - ULONG Release() override { - ULONG ref = --m_refCount; - if (ref == 0) { - delete this; - } - return ref; - } - - HRESULT Connect(VARIANT ServerName, VARIANT User, VARIANT Domain, - VARIANT Password) override { - // 模拟连接成功 - return S_OK; - } - - HRESULT GetFolder(BSTR path, ITaskFolder** ppFolder) override { - // 模拟获取文件夹成功 - *ppFolder = nullptr; // 实际使用时需要创建ITaskFolder实现 - return S_OK; - } - - HRESULT NewTask(DWORD flags, ITaskDefinition** ppDefinition) override { - // 模拟创建新任务成功 - *ppDefinition = nullptr; // 实际使用时需要创建ITaskDefinition实现 - return S_OK; - } -}; - -// COM 组件工厂实现 -bool ComObjectFactory::IsTaskSchedulerCLSID(const CLSID& clsid) { - // 检查是否是Task Scheduler 2.0 的CLSID - static const CLSID CLSID_TaskScheduler = { - 0x0f87369f, - 0xa4e5, - 0x4cfc, - {0xbd, 0x3e, 0x73, 0xe6, 0x15, 0x45, 0x72, 0xdd}}; - - return IsEqualCLSID(clsid, CLSID_TaskScheduler); -} - -ComObjectSimulator* ComObjectFactory::CreateInstance(const CLSID& clsid) { - if (IsTaskSchedulerCLSID(clsid)) { - return new TaskServiceImpl(); - } - return nullptr; +// 自定义函数:将GUID转换为字符串 +void GUIDToString(const GUID& guid, char* str, size_t size) { + // GUID格式: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} + snprintf(str, size, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], + guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], + guid.Data4[6], guid.Data4[7]); } // COM API 实现 void Api_CoInitializeEx(void* sandbox, uc_engine* uc, uint64_t address) { - Sandbox* sb = static_cast(sandbox); + auto context = static_cast(sandbox); + uint64_t pvReserved = 0; + uint32_t dwCoInit = 0; // 获取参数 - uint32_t pvReserved = 0; - uint32_t dwCoInit = 0; - uc_mem_read(uc, address + 4, &pvReserved, sizeof(pvReserved)); - uc_mem_read(uc, address + 8, &dwCoInit, sizeof(dwCoInit)); + if (context->GetPeInfo()->isX64) { + // x64: rcx = pvReserved, rdx = dwCoInit + uc_reg_read(uc, UC_X86_REG_RCX, &pvReserved); + uc_reg_read(uc, UC_X86_REG_RDX, &dwCoInit); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 - // 设置COM初始化状态 - g_comInitialized = true; + uint32_t temp_reserved; + uint32_t temp_coinit; + uc_mem_read(uc, esp_address, &temp_reserved, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &temp_coinit, sizeof(uint32_t)); + pvReserved = temp_reserved; + dwCoInit = temp_coinit; + } - // 返回成功 - uc_reg_write(uc, UC_X86_REG_EAX, &(uint32_t){S_OK}); + // 打印日志 + printf("[*] CoInitializeEx: pvReserved=0x%llx, dwCoInit=0x%x\n", pvReserved, + dwCoInit); + + // 返回S_OK (0) + uint32_t result = 0; // S_OK = 0 + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); } void Api_CoCreateInstance(void* sandbox, uc_engine* uc, uint64_t address) { - Sandbox* sb = static_cast(sandbox); - - if (!g_comInitialized) { - uint32_t result = CO_E_NOTINITIALIZED; - uc_reg_write(uc, UC_X86_REG_EAX, &result); - return; - } + auto context = static_cast(sandbox); + uint64_t rclsid = 0; // REFCLSID + uint64_t pUnkOuter = 0; // LPUNKNOWN + uint32_t dwClsContext = 0; // DWORD + uint64_t riid = 0; // REFIID + uint64_t ppv = 0; // LPVOID* // 获取参数 - CLSID rclsid; - uint32_t pUnkOuter = 0; - uint32_t dwClsContext = 0; - IID riid; - uint32_t ppv = 0; + if (context->GetPeInfo()->isX64) { + // x64: rcx = rclsid, rdx = pUnkOuter, r8 = dwClsContext, r9 = riid + uc_reg_read(uc, UC_X86_REG_RCX, &rclsid); + uc_reg_read(uc, UC_X86_REG_RDX, &pUnkOuter); + uint64_t temp_context; + uc_reg_read(uc, UC_X86_REG_R8, &temp_context); + dwClsContext = static_cast(temp_context); + uc_reg_read(uc, UC_X86_REG_R9, &riid); - uc_mem_read(uc, address + 4, &rclsid, sizeof(rclsid)); - uc_mem_read(uc, address + 20, &pUnkOuter, sizeof(pUnkOuter)); - uc_mem_read(uc, address + 24, &dwClsContext, sizeof(dwClsContext)); - uc_mem_read(uc, address + 28, &riid, sizeof(riid)); - uc_mem_read(uc, address + 44, &ppv, sizeof(ppv)); + // 从栈上读取最后一个参数 + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uc_mem_read(uc, rsp + 0x28, &ppv, sizeof(uint64_t)); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 - // 创建COM对象 - ComObjectSimulator* obj = ComObjectFactory::CreateInstance(rclsid); - if (obj == nullptr) { - uint32_t result = CLASS_E_CLASSNOTAVAILABLE; - uc_reg_write(uc, UC_X86_REG_EAX, &result); - return; + uint32_t temp_params[5]; // 所有参数都是32位的 + for (int i = 0; i < 5; i++) { + uc_mem_read(uc, esp_address + (i * 4), &temp_params[i], + sizeof(uint32_t)); + } + + rclsid = temp_params[0]; + pUnkOuter = temp_params[1]; + dwClsContext = temp_params[2]; + riid = temp_params[3]; + ppv = temp_params[4]; } - // 写入对象指针 - uint32_t objPtr = reinterpret_cast(obj); - uc_mem_write(uc, ppv, &objPtr, sizeof(objPtr)); + // 读取并打印CLSID + CLSID clsid; + if (rclsid != 0) { + uc_mem_read(uc, rclsid, &clsid, sizeof(CLSID)); - uint32_t result = S_OK; - uc_reg_write(uc, UC_X86_REG_EAX, &result); + // 将CLSID转换为字符串并打印 + char clsidStr[40] = {0}; + GUIDToString(clsid, clsidStr, sizeof(clsidStr)); + + printf("[*] CoCreateInstance: CLSID=%s, Context=0x%x\n", clsidStr, + dwClsContext); + + // 也打印IID (接口ID) + if (riid != 0) { + IID iid; + uc_mem_read(uc, riid, &iid, sizeof(IID)); + char iidStr[40] = {0}; + GUIDToString(iid, iidStr, sizeof(iidStr)); + printf("[*] CoCreateInstance: IID=%s\n", iidStr); + } + } else { + printf("[*] CoCreateInstance: CLSID=NULL, Context=0x%x\n", + dwClsContext); + } + + // 创建一个假的接口指针 + uint64_t fake_interface = 0xABABABABAB; + + + // 如果ppv有效,将fake_interface写入ppv指向的位置 + if (ppv != 0) { + if (context->GetPeInfo()->isX64) { + uc_mem_write(uc, ppv, &fake_interface, sizeof(uint64_t)); + } else { + uint32_t interface_32 = static_cast(fake_interface); + uc_mem_write(uc, (uint32_t)ppv, &interface_32, sizeof(uint32_t)); + } + } + + // 返回S_OK (0) + uint32_t result = 0; // S_OK = 0 + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); } void Api_VariantInit(void* sandbox, uc_engine* uc, uint64_t address) { - Sandbox* sb = static_cast(sandbox); + auto context = static_cast(sandbox); + uint64_t pvarg = 0; // 指向VARIANT的指针 - // 获取VARIANT指针 - uint32_t pvarg = 0; - uc_mem_read(uc, address + 4, &pvarg, sizeof(pvarg)); + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = pvarg + uc_reg_read(uc, UC_X86_REG_RCX, &pvarg); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 - // 初始化VARIANT结构体 - VARIANT v; - VariantInit(&v); + uint32_t temp_pvarg; + uc_mem_read(uc, esp_address, &temp_pvarg, sizeof(uint32_t)); + pvarg = temp_pvarg; + } - // 写回初始化后的VARIANT - uc_mem_write(uc, pvarg, &v, sizeof(VARIANT)); + // 检查pvarg是否有效 + if (pvarg != 0) { + // 初始化VARIANT结构体为VT_EMPTY + VARTYPE vt = VT_EMPTY; + uc_mem_write(uc, pvarg, &vt, sizeof(VARTYPE)); - uint32_t result = S_OK; - uc_reg_write(uc, UC_X86_REG_EAX, &result); + // 清零VARIANT结构体的其余部分 + uint8_t zeros[14] = {0}; // VARIANT结构体大小为16字节,前2字节为vt + uc_mem_write(uc, pvarg + sizeof(VARTYPE), zeros, sizeof(zeros)); + } + + printf("[*] VariantInit: pvarg=0x%llx\n", pvarg); } void Api_VariantClear(void* sandbox, uc_engine* uc, uint64_t address) { - Sandbox* sb = static_cast(sandbox); + auto context = static_cast(sandbox); + uint64_t pvarg = 0; // 指向VARIANT的指针 - // 获取VARIANT指针 - uint32_t pvarg = 0; - uc_mem_read(uc, address + 4, &pvarg, sizeof(pvarg)); + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = pvarg + uc_reg_read(uc, UC_X86_REG_RCX, &pvarg); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 - // 读取VARIANT结构体 - VARIANT v; - uc_mem_read(uc, pvarg, &v, sizeof(VARIANT)); + uint32_t temp_pvarg; + uc_mem_read(uc, esp_address, &temp_pvarg, sizeof(uint32_t)); + pvarg = temp_pvarg; + } - // 清理VARIANT - VariantClear(&v); + // 检查pvarg是否有效 + if (pvarg != 0) { + // 读取当前的VARIANT类型 + VARTYPE vt; + uc_mem_read(uc, pvarg, &vt, sizeof(VARTYPE)); - // 写回清理后的VARIANT - uc_mem_write(uc, pvarg, &v, sizeof(VARIANT)); + // 将类型重置为VT_EMPTY并清零其余部分 + vt = VT_EMPTY; + uc_mem_write(uc, pvarg, &vt, sizeof(VARTYPE)); - uint32_t result = S_OK; - uc_reg_write(uc, UC_X86_REG_EAX, &result); + uint8_t zeros[14] = {0}; + uc_mem_write(uc, pvarg + sizeof(VARTYPE), zeros, sizeof(zeros)); + } + + // 返回S_OK + uint32_t result = 0; // S_OK + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + + printf("[*] VariantClear: pvarg=0x%llx\n", pvarg); } void Api_SysAllocString(void* sandbox, uc_engine* uc, uint64_t address) { - Sandbox* sb = static_cast(sandbox); + auto context = static_cast(sandbox); + uint64_t psz = 0; // 源字符串指针 - // 获取字符串指针 - uint32_t psz = 0; - uc_mem_read(uc, address + 4, &psz, sizeof(psz)); + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = psz + uc_reg_read(uc, UC_X86_REG_RCX, &psz); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 - // 读取字符串 - wchar_t buffer[MAX_PATH]; - uc_mem_read(uc, psz, buffer, sizeof(buffer)); + uint32_t temp_psz; + uc_mem_read(uc, esp_address, &temp_psz, sizeof(uint32_t)); + psz = temp_psz; + } - // 分配BSTR - BSTR bstr = SysAllocString(buffer); + uint64_t bstr_ptr = 0; + + // 如果源字符串有效 + if (psz != 0) { + // 计算源字符串长度 + size_t len = 0; + wchar_t wch; + do { + uc_mem_read(uc, psz + (len * sizeof(wchar_t)), &wch, + sizeof(wchar_t)); + len++; + } while (wch != 0 && len < 1024); // 设置一个合理的最大长度限制 + len--; // 不包括null终止符 + + // 为BSTR分配内存:4字节长度 + 字符串内容 + 终止符 + size_t bstr_size = sizeof(uint32_t) + (len + 1) * sizeof(wchar_t); + bstr_ptr = context->AllocateMemory(bstr_size); + + if (bstr_ptr != 0) { + // 写入字符串长度(字节数) + uint32_t byte_len = static_cast(len * sizeof(wchar_t)); + uc_mem_write(uc, bstr_ptr, &byte_len, sizeof(uint32_t)); + + // 写入字符串内容 + uint64_t string_offset = bstr_ptr + sizeof(uint32_t); + uc_mem_write(uc, string_offset, (void*)psz, byte_len); + + // 添加终止符 + wchar_t null_char = 0; + uc_mem_write(uc, string_offset + byte_len, &null_char, + sizeof(wchar_t)); + + // BSTR指针指向字符串内容,不包括长度前缀 + bstr_ptr = string_offset; + } + } // 返回BSTR指针 - uint32_t result = reinterpret_cast(bstr); - uc_reg_write(uc, UC_X86_REG_EAX, &result); + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &bstr_ptr); + + printf("[*] SysAllocString: psz=0x%llx, result=0x%llx\n", psz, bstr_ptr); } diff --git a/ai_anti_malware/sandbox_api_com.h b/ai_anti_malware/sandbox_api_com.h index 7f2551e..bfc3a3a 100644 --- a/ai_anti_malware/sandbox_api_com.h +++ b/ai_anti_malware/sandbox_api_com.h @@ -1,52 +1,11 @@ #pragma once #include #include -#include #include "sandbox.h" -// 辅助函数声明 -void read_from_unicorn(uc_engine* uc, uint64_t address, void* buffer, - size_t size); -void write_to_unicorn(uc_engine* uc, uint64_t address, const void* buffer, - size_t size); -void set_return_value(uc_engine* uc, uint32_t value); - -// COM 组件接口定义 -struct ITaskService; -struct ITaskFolder; -struct ITaskDefinition; -struct IRegisteredTask; - -// COM 组件模拟器基类 -class ComObjectSimulator { - public: - virtual ~ComObjectSimulator() = default; - virtual HRESULT QueryInterface(REFIID riid, void** ppv) = 0; - virtual ULONG AddRef() = 0; - virtual ULONG Release() = 0; -}; - -// 计划任务COM组件模拟器 -class TaskServiceSimulator : public ComObjectSimulator { - public: - virtual HRESULT Connect(VARIANT ServerName, VARIANT User, VARIANT Domain, - VARIANT Password) = 0; - virtual HRESULT GetFolder(BSTR path, ITaskFolder** ppFolder) = 0; - virtual HRESULT NewTask(DWORD flags, ITaskDefinition** ppDefinition) = 0; -}; - // COM API 模拟函数声明 void Api_CoInitializeEx(void* sandbox, uc_engine* uc, uint64_t address); void Api_CoCreateInstance(void* sandbox, uc_engine* uc, uint64_t address); void Api_VariantInit(void* sandbox, uc_engine* uc, uint64_t address); void Api_VariantClear(void* sandbox, uc_engine* uc, uint64_t address); -void Api_SysAllocString(void* sandbox, uc_engine* uc, uint64_t address); - -// COM 组件工厂 -class ComObjectFactory { - public: - static ComObjectSimulator* CreateInstance(const CLSID& clsid); - - private: - static bool IsTaskSchedulerCLSID(const CLSID& clsid); -}; \ No newline at end of file +void Api_SysAllocString(void* sandbox, uc_engine* uc, uint64_t address); \ No newline at end of file diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index 5170a5c..4fc6f72 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -1,6 +1,7 @@ #include "sandbox.h" #include "sandbox_callbacks.h" #include "sandbox_api_winhttp.h" +#include "sandbox_api_com.h" #include auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address) @@ -1362,6 +1363,17 @@ auto Sandbox::InitApiHooks() -> void { auto FakeApi__initterm_e = _fakeApi{.func = Api__initterm_e, .paramCount = 2}; auto FakeApi_getenv = _fakeApi{.func = Api_getenv, .paramCount = 1}; + // 添加COM API + auto FakeApi_CoInitializeEx = + _fakeApi{.func = Api_CoInitializeEx, .paramCount = 2}; + auto FakeApi_CoCreateInstance = + _fakeApi{.func = Api_CoCreateInstance, .paramCount = 5}; + auto FakeApi_VariantInit = + _fakeApi{.func = Api_VariantInit, .paramCount = 1}; + auto FakeApi_VariantClear = + _fakeApi{.func = Api_VariantClear, .paramCount = 1}; + auto FakeApi_SysAllocString = + _fakeApi{.func = Api_SysAllocString, .paramCount = 1}; api_map = { {"GetSystemTimeAsFileTime", @@ -1499,6 +1511,12 @@ auto Sandbox::InitApiHooks() -> void { {"GetStringTypeW", std::make_shared<_fakeApi>(FakeApi_GetStringTypeW)}, {"LCMapStringW", std::make_shared<_fakeApi>(FakeApi_LCMapStringW)}, {"getenv", std::make_shared<_fakeApi>(FakeApi_getenv)}, + {"CoInitializeEx", std::make_shared<_fakeApi>(FakeApi_CoInitializeEx)}, + {"CoCreateInstance", + std::make_shared<_fakeApi>(FakeApi_CoCreateInstance)}, + {"VariantInit", std::make_shared<_fakeApi>(FakeApi_VariantInit)}, + {"VariantClear", std::make_shared<_fakeApi>(FakeApi_VariantClear)}, + {"SysAllocString", std::make_shared<_fakeApi>(FakeApi_SysAllocString)}, }; } auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,