update
This commit is contained in:
@@ -4,179 +4,274 @@
|
||||
#include <tlhelp32.h>
|
||||
#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*>(sandbox);
|
||||
auto context = static_cast<Sandbox*>(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*>(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*>(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<uint32_t>(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<uint32_t>(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<uint32_t>(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*>(sandbox);
|
||||
auto context = static_cast<Sandbox*>(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*>(sandbox);
|
||||
auto context = static_cast<Sandbox*>(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*>(sandbox);
|
||||
auto context = static_cast<Sandbox*>(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<uint32_t>(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<uint32_t>(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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user