2191 lines
78 KiB
C++
2191 lines
78 KiB
C++
#include "sandbox.h"
|
||
#include "sandbox_callbacks.h"
|
||
std::string getDllNameFromApiSetMap(const std::string& apiSet);
|
||
auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t return_params_address = 0;
|
||
LARGE_INTEGER data;
|
||
BOOL origin_return_value = QueryPerformanceCounter(&data);
|
||
if (context->GetPeInfo()->isX64) {
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &return_params_address);
|
||
} else {
|
||
uint64_t ebp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &ebp_address);
|
||
ebp_address += 0x4;
|
||
uc_mem_read(uc, ebp_address, &return_params_address, 0x4);
|
||
}
|
||
uc_mem_write(uc, return_params_address, &data, sizeof(LARGE_INTEGER));
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&origin_return_value);
|
||
}
|
||
auto Api_GetSystemTimeAsFileTime(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
uint64_t rcx;
|
||
FILETIME file_time;
|
||
GetSystemTimeAsFileTime(&file_time);
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
|
||
uc_mem_write(uc, rcx, &file_time, sizeof(FILETIME));
|
||
}
|
||
void Api_GetCurrentThreadId(void* sandbox, uc_engine* uc, uint64_t address) {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
if (context->GetPeInfo()->isX64) {
|
||
uc_reg_write(uc, UC_X86_REG_RAX,
|
||
&context->GetTeb64()->ClientId.UniqueThread);
|
||
} else {
|
||
uc_reg_write(uc, UC_X86_REG_RAX,
|
||
&context->GetTeb32()->ClientId.UniqueThread);
|
||
}
|
||
}
|
||
void Api_GetCurrentProcessId(void* sandbox, uc_engine* uc, uint64_t address) {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
if (context->GetPeInfo()->isX64) {
|
||
uc_reg_write(uc, UC_X86_REG_RAX,
|
||
&context->GetTeb64()->ClientId.UniqueProcess);
|
||
} else {
|
||
uc_reg_write(uc, UC_X86_REG_RAX,
|
||
&context->GetTeb32()->ClientId.UniqueProcess);
|
||
}
|
||
}
|
||
auto Api_LoadLibraryA(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t params_address = 0;
|
||
|
||
// 获取参数地址
|
||
if (context->GetPeInfo()->isX64) {
|
||
uc_reg_read(uc, UC_X86_REG_RCX, ¶ms_address);
|
||
} else {
|
||
uint64_t ebp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &ebp_address);
|
||
ebp_address += 0x4;
|
||
uc_mem_read(uc, ebp_address, ¶ms_address, 0x4);
|
||
}
|
||
|
||
uint64_t return_address = 0;
|
||
std::string module_name;
|
||
char buffer[MAX_PATH];
|
||
size_t i = 0;
|
||
|
||
// 读取模块名称
|
||
if (params_address != 0) {
|
||
do {
|
||
uint8_t byte;
|
||
uc_mem_read(uc, params_address + i, &byte, 1);
|
||
buffer[i] = byte;
|
||
i++;
|
||
} while (buffer[i - 1] != 0 && i < MAX_PATH);
|
||
|
||
if (i > 0 && i < MAX_PATH) {
|
||
module_name = std::string(buffer);
|
||
// 确保模块名以.dll结尾(不区分大小写)
|
||
if (module_name.length() > 4) {
|
||
std::string ext = module_name.substr(module_name.length() - 4);
|
||
if (_stricmp(ext.c_str(), ".dll") != 0) {
|
||
module_name += ".dll";
|
||
}
|
||
} else {
|
||
module_name += ".dll";
|
||
}
|
||
std::string fuck_up_api_ms = module_name;
|
||
if (fuck_up_api_ms.find("api-ms-") != std::string::npos) {
|
||
module_name = getDllNameFromApiSetMap(fuck_up_api_ms);
|
||
if (module_name.size() <= 1) __debugbreak();
|
||
}
|
||
|
||
// 从模块列表中查找对应模块
|
||
for (const auto& module : context->GetModuleList()) {
|
||
if (_stricmp((*module).name, module_name.c_str()) == 0) {
|
||
return_address = (*module).base;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
printf("[*] LoadLibraryA: Module=%s, Base=0x%llx\n", module_name.c_str(),
|
||
return_address);
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_address);
|
||
}
|
||
auto Api_LoadLibraryExW(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t module_name_address = 0;
|
||
uint64_t flags = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpLibFileName, r8 = dwFlags
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &module_name_address);
|
||
uc_reg_read(uc, UC_X86_REG_R8, &flags);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint64_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &module_name_address, 0x4);
|
||
esp_address += 0x8; // 跳过hFile参数
|
||
uc_mem_read(uc, esp_address, &flags, 0x4);
|
||
}
|
||
|
||
uint64_t return_address = 0;
|
||
std::wstring module_name;
|
||
wchar_t buffer[MAX_PATH];
|
||
size_t i = 0;
|
||
bool isApiSetMapMeme = false;
|
||
// 读取宽字符模块名称
|
||
if (module_name_address != 0) {
|
||
do {
|
||
uint16_t wchar;
|
||
uc_mem_read(uc, module_name_address + (i * 2), &wchar, 2);
|
||
buffer[i] = wchar;
|
||
i++;
|
||
} while (buffer[i - 1] != 0 && i < MAX_PATH);
|
||
|
||
if (i > 0 && i < MAX_PATH) {
|
||
module_name = std::wstring(buffer);
|
||
std::string ansi_name(module_name.begin(), module_name.end());
|
||
|
||
std::string fuck_up_api_ms = ansi_name;
|
||
if (ansi_name.length() > 4) {
|
||
std::string ext = ansi_name.substr(ansi_name.length() - 4);
|
||
if (_stricmp(ext.c_str(), ".dll") != 0) {
|
||
ansi_name += ".dll";
|
||
}
|
||
} else {
|
||
ansi_name += ".dll";
|
||
}
|
||
if (ansi_name.find("api-ms-") != std::string::npos) {
|
||
ansi_name = getDllNameFromApiSetMap(ansi_name);
|
||
isApiSetMapMeme = true;
|
||
// if (ansi_name.size() <= 1) __debugbreak();
|
||
}
|
||
|
||
// 从模块列表中查找对应模块
|
||
for (const auto& module : context->GetModuleList()) {
|
||
if (_stricmp((*module).name, ansi_name.c_str()) == 0) {
|
||
return_address = (*module).base;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
printf("[*] LoadLibraryExW: Module=%ls, Flags=0x%llx, Base=0x%llx\n",
|
||
module_name.c_str(), flags, return_address);
|
||
if (return_address == 0 && isApiSetMapMeme) {
|
||
// 找不到就不管他了,操
|
||
return_address = 0x1337;
|
||
}
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_address);
|
||
}
|
||
void Api_GetLastError(void* sandbox, uc_engine* uc, uint64_t address) {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
DWORD last_error = 0;
|
||
|
||
// 从TEB中获取LastError
|
||
if (context->GetPeInfo()->isX64) {
|
||
last_error = context->GetTeb64()->LastErrorValue;
|
||
} else {
|
||
last_error = context->GetTeb32()->LastErrorValue;
|
||
}
|
||
|
||
printf("[*] GetLastError: LastError=0x%x\n", last_error);
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&last_error);
|
||
}
|
||
auto Api_InitializeCriticalSectionAndSpinCount(void* sandbox, uc_engine* uc,
|
||
uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t lpCriticalSection = 0;
|
||
uint32_t dwSpinCount = 0;
|
||
BOOL success = TRUE; // 默认返回成功
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpCriticalSection, rdx = dwSpinCount
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||
uint64_t temp_spin_count = 0;
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_spin_count);
|
||
dwSpinCount = static_cast<uint32_t>(temp_spin_count);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_cs = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||
lpCriticalSection = temp_cs;
|
||
esp_address += 0x4;
|
||
uc_mem_read(uc, esp_address, &dwSpinCount, sizeof(uint32_t));
|
||
}
|
||
|
||
if (lpCriticalSection != 0) {
|
||
// 初始化关键段结构
|
||
RTL_CRITICAL_SECTION cs = {0};
|
||
cs.LockCount = -1; // 初始未锁定状态
|
||
cs.RecursionCount = 0; // 初始递归计数为0
|
||
cs.SpinCount = dwSpinCount; // 设置自旋计数
|
||
cs.OwningThread = 0; // 初始无拥有线程
|
||
cs.LockSemaphore = 0; // 初始信号量为0
|
||
|
||
// 写入初始化后的结构到目标内存
|
||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||
} else {
|
||
success = FALSE;
|
||
// 设置LastError
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
printf(
|
||
"[*] InitializeCriticalSectionAndSpinCount: CS=0x%llx, SpinCount=0x%x, "
|
||
"Success=%d\n",
|
||
lpCriticalSection, dwSpinCount, success);
|
||
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&success);
|
||
}
|
||
auto Api_TlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
DWORD tls_index = TLS_OUT_OF_INDEXES; // 默认返回失败值
|
||
|
||
// 获取TEB结构
|
||
if (context->GetPeInfo()->isX64) {
|
||
auto teb = context->GetTeb64();
|
||
// 在TLS槽中查找第一个可用的位置
|
||
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
|
||
if (teb->TlsSlots[i] == (void*)0x1337ffffff) {
|
||
teb->TlsSlots[i] = (void*)0; // 标记为已使用
|
||
tls_index = i;
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
auto teb = context->GetTeb32();
|
||
// 在TLS槽中查找第一个可用的位置
|
||
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
|
||
if (teb->TlsSlots[i] == 0x1337) {
|
||
teb->TlsSlots[i] = 0; // 标记为已使用
|
||
tls_index = i;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (tls_index == TLS_OUT_OF_INDEXES) {
|
||
// 设置LastError为没有可用的TLS索引
|
||
DWORD error = ERROR_NO_MORE_ITEMS;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
printf("[*] TlsAlloc: Allocated TLS Index=0x%x\n", tls_index);
|
||
|
||
// 返回分配的TLS索引
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&tls_index);
|
||
}
|
||
auto Api_TlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t dwTlsIndex = 0;
|
||
uint64_t lpTlsValue = 0;
|
||
BOOL success = FALSE;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = dwTlsIndex, rdx = lpTlsValue
|
||
uint64_t temp_index;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_index);
|
||
dwTlsIndex = static_cast<uint32_t>(temp_index);
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &lpTlsValue);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &dwTlsIndex, sizeof(uint32_t));
|
||
esp_address += 0x4;
|
||
uint32_t temp_value;
|
||
uc_mem_read(uc, esp_address, &temp_value, sizeof(uint32_t));
|
||
lpTlsValue = temp_value;
|
||
}
|
||
|
||
// 检查索引是否有效(小于64)
|
||
if (dwTlsIndex < 64) {
|
||
if (context->GetPeInfo()->isX64) {
|
||
auto teb = context->GetTeb64();
|
||
// 检查槽是否已分配(不为nullptr)
|
||
if (teb->TlsSlots[dwTlsIndex] != (void*)0x1337ffffff) {
|
||
teb->TlsSlots[dwTlsIndex] = (void*)lpTlsValue;
|
||
success = TRUE;
|
||
}
|
||
} else {
|
||
auto teb = context->GetTeb32();
|
||
// 检查槽是否已分配(不为0)
|
||
if (teb->TlsSlots[dwTlsIndex] != 0x1337) {
|
||
teb->TlsSlots[dwTlsIndex] = static_cast<uint32_t>(lpTlsValue);
|
||
success = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!success) {
|
||
// 设置LastError
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
printf("[*] TlsSetValue: Index=0x%x, Value=0x%llx, Success=%d\n",
|
||
dwTlsIndex, lpTlsValue, success);
|
||
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&success);
|
||
}
|
||
auto Api_DeleteCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t lpCriticalSection = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpCriticalSection
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_cs = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||
lpCriticalSection = temp_cs;
|
||
}
|
||
|
||
if (lpCriticalSection != 0) {
|
||
// 读取现有的关键段结构
|
||
RTL_CRITICAL_SECTION cs;
|
||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||
|
||
// 检查是否有线程仍在等待
|
||
if (cs.LockCount >= 0) {
|
||
// 有线程正在等待,设置错误
|
||
DWORD error = ERROR_SEM_IS_SET;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
// 清零内存,表示删除
|
||
memset(&cs, 0, sizeof(RTL_CRITICAL_SECTION));
|
||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||
}
|
||
|
||
printf("[*] DeleteCriticalSection: CS=0x%llx\n", lpCriticalSection);
|
||
}
|
||
|
||
auto Api_IsProcessorFeaturePresent(void* sandbox, uc_engine* uc,
|
||
uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t feature_number = 0;
|
||
BOOL is_supported = FALSE;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = FeatureNumber
|
||
uint64_t temp_feature;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_feature);
|
||
feature_number = static_cast<uint32_t>(temp_feature);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &feature_number, sizeof(uint32_t));
|
||
}
|
||
|
||
// 模拟一些常见的处理器特性
|
||
switch (feature_number) {
|
||
case PF_FLOATING_POINT_PRECISION_ERRATA: // 0
|
||
is_supported = FALSE;
|
||
break;
|
||
case PF_FLOATING_POINT_EMULATED: // 1
|
||
is_supported = FALSE;
|
||
break;
|
||
case PF_COMPARE_EXCHANGE_DOUBLE: // 2
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_MMX_INSTRUCTIONS_AVAILABLE: // 3
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_XMMI_INSTRUCTIONS_AVAILABLE: // 6
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_3DNOW_INSTRUCTIONS_AVAILABLE: // 7
|
||
is_supported = FALSE;
|
||
break;
|
||
case PF_RDTSC_INSTRUCTION_AVAILABLE: // 8
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_PAE_ENABLED: // 9
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_XMMI64_INSTRUCTIONS_AVAILABLE: // 10
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_SSE_DAZ_MODE_AVAILABLE: // 11
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_NX_ENABLED: // 12
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_SSE3_INSTRUCTIONS_AVAILABLE: // 13
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_COMPARE_EXCHANGE128: // 14
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_XSAVE_ENABLED: // 17
|
||
is_supported = TRUE;
|
||
break;
|
||
case PF_ARM_VFP_32_REGISTERS_AVAILABLE: // 18
|
||
is_supported = FALSE;
|
||
break;
|
||
default:
|
||
is_supported = FALSE;
|
||
break;
|
||
}
|
||
|
||
printf("[*] IsProcessorFeaturePresent: Feature=0x%x, Supported=%d\n",
|
||
feature_number, is_supported);
|
||
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&is_supported);
|
||
}
|
||
|
||
auto Api_GetProcAddress(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t moduleHandle = 0;
|
||
uint64_t functionNameAddr = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = hModule, rdx = lpProcName
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &moduleHandle);
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &functionNameAddr);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint64_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uint32_t temp_handle = 0;
|
||
uint32_t temp_name_addr = 0;
|
||
uc_mem_read(uc, esp_address, &temp_handle, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x4, &temp_name_addr, sizeof(uint32_t));
|
||
moduleHandle = temp_handle;
|
||
functionNameAddr = temp_name_addr;
|
||
}
|
||
|
||
uint64_t return_address = 0;
|
||
|
||
// 读取函数名
|
||
if (functionNameAddr == 0) {
|
||
__debugbreak();
|
||
}
|
||
// 通过名称查找
|
||
char functionName[256] = {0};
|
||
size_t i = 0;
|
||
do {
|
||
uint8_t byte;
|
||
uc_mem_read(uc, functionNameAddr + i, &byte, 1);
|
||
functionName[i] = byte;
|
||
i++;
|
||
} while (functionName[i - 1] != 0 && i < sizeof(functionName));
|
||
|
||
// 在模块列表中查找对应模块
|
||
for (const auto& module : context->GetModuleList()) {
|
||
if (module->base == moduleHandle) {
|
||
// 遍历导出函数查找对应名称
|
||
for (const auto& exp : module->export_function) {
|
||
// 使用 _stricmp 进行大小写不敏感的比较
|
||
if (_stricmp(exp->name, functionName) == 0) {
|
||
return_address = module->base + exp->function_address;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
printf("[*] GetProcAddress: Module=0x%llx, Function=%s, Address=0x%llx\n",
|
||
moduleHandle, functionName, return_address);
|
||
|
||
// 设置返回值
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_address);
|
||
}
|
||
|
||
auto Api_GetProcessHeap(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
// 返回默认堆句柄(使用堆基址作为句柄)
|
||
uint64_t heap_handle =
|
||
context->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
||
|
||
printf("[*] GetProcessHeap: Handle=0x%llx\n", heap_handle);
|
||
|
||
// 返回堆句柄
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&heap_handle);
|
||
}
|
||
|
||
// 实现HeapAlloc API
|
||
auto Api_HeapAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t hHeap = 0;
|
||
uint32_t dwFlags = 0;
|
||
uint64_t dwBytes = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = hHeap, rdx = dwFlags, r8 = dwBytes
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &hHeap);
|
||
uint64_t temp_flags;
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags);
|
||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||
uc_reg_read(uc, UC_X86_REG_R8, &dwBytes);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uint32_t temp_heap;
|
||
uc_mem_read(uc, esp_address, &temp_heap, sizeof(uint32_t));
|
||
hHeap = temp_heap;
|
||
esp_address += 0x4;
|
||
uc_mem_read(uc, esp_address, &dwFlags, sizeof(uint32_t));
|
||
esp_address += 0x4;
|
||
uint32_t temp_bytes;
|
||
uc_mem_read(uc, esp_address, &temp_bytes, sizeof(uint32_t));
|
||
dwBytes = temp_bytes;
|
||
}
|
||
|
||
// 检查堆句柄是否有效
|
||
uint64_t expected_handle =
|
||
context->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
||
if (hHeap != expected_handle) {
|
||
uint64_t null_ptr = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&null_ptr);
|
||
return;
|
||
}
|
||
|
||
// 获取或创建堆段
|
||
HeapSegment* segment = nullptr;
|
||
auto it = context->m_heapSegments.find(hHeap);
|
||
if (it == context->m_heapSegments.end()) {
|
||
segment = context->CreateHeapSegment(
|
||
hHeap, context->GetPeInfo()->isX64 ? HEAP_SIZE_64 : HEAP_SIZE_32);
|
||
context->m_heapSegments[hHeap] = segment;
|
||
} else {
|
||
segment = it->second;
|
||
}
|
||
|
||
// 分配内存
|
||
uint64_t allocated_address = context->AllocateFromSegment(segment, dwBytes);
|
||
|
||
printf(
|
||
"[*] HeapAlloc: Handle=0x%llx, Flags=0x%x, Size=0x%llx, "
|
||
"Address=0x%llx\n",
|
||
hHeap, dwFlags, dwBytes, allocated_address);
|
||
|
||
// 返回分配的地址
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&allocated_address);
|
||
}
|
||
|
||
// 实现HeapFree API
|
||
auto Api_HeapFree(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t hHeap = 0;
|
||
uint32_t dwFlags = 0;
|
||
uint64_t lpMem = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = hHeap, rdx = dwFlags, r8 = lpMem
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &hHeap);
|
||
uint64_t temp_flags;
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags);
|
||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||
uc_reg_read(uc, UC_X86_REG_R8, &lpMem);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uint32_t temp_heap;
|
||
uc_mem_read(uc, esp_address, &temp_heap, sizeof(uint32_t));
|
||
hHeap = temp_heap;
|
||
esp_address += 0x4;
|
||
uc_mem_read(uc, esp_address, &dwFlags, sizeof(uint32_t));
|
||
esp_address += 0x4;
|
||
uint32_t temp_mem;
|
||
uc_mem_read(uc, esp_address, &temp_mem, sizeof(uint32_t));
|
||
lpMem = temp_mem;
|
||
}
|
||
|
||
// 释放内存
|
||
bool success = context->FreeBlock(lpMem);
|
||
|
||
printf(
|
||
"[*] HeapFree: Handle=0x%llx, Flags=0x%x, Address=0x%llx, Success=%d\n",
|
||
hHeap, dwFlags, lpMem, success);
|
||
|
||
// 返回操作是否成功
|
||
uint64_t result = success ? 1 : 0;
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
}
|
||
|
||
// 实现TlsGetValue API
|
||
auto Api_TlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t dwTlsIndex = 0;
|
||
uint64_t return_value = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = dwTlsIndex
|
||
uint64_t temp_index;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_index);
|
||
dwTlsIndex = static_cast<uint32_t>(temp_index);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &dwTlsIndex, sizeof(uint32_t));
|
||
}
|
||
|
||
// 检查索引是否有效(小于64)
|
||
if (dwTlsIndex < 64) {
|
||
if (context->GetPeInfo()->isX64) {
|
||
auto teb = context->GetTeb64();
|
||
// 检查槽是否已分配(不为nullptr)
|
||
if (teb->TlsSlots[dwTlsIndex] != (void*)0x1337ffffff) {
|
||
return_value =
|
||
reinterpret_cast<uint64_t>(teb->TlsSlots[dwTlsIndex]);
|
||
} else {
|
||
// 槽未分配,设置LastError
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
teb->LastErrorValue = error;
|
||
}
|
||
} else {
|
||
auto teb = context->GetTeb32();
|
||
// 检查槽是否已分配(不为0)
|
||
if (teb->TlsSlots[dwTlsIndex] != 0x1337) {
|
||
return_value = teb->TlsSlots[dwTlsIndex];
|
||
} else {
|
||
// 槽未分配,设置LastError
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
teb->LastErrorValue = error;
|
||
}
|
||
}
|
||
} else {
|
||
// 索引无效,设置LastError
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
printf("[*] TlsGetValue: Index=0x%x, Value=0x%llx\n", dwTlsIndex,
|
||
return_value);
|
||
|
||
// 返回TLS槽中的值
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_value);
|
||
}
|
||
|
||
auto Api_SetLastError(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t dwErrCode = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = dwErrCode
|
||
uint64_t temp_error;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_error);
|
||
dwErrCode = static_cast<uint32_t>(temp_error);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &dwErrCode, sizeof(uint32_t));
|
||
}
|
||
|
||
// 设置LastError值
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = dwErrCode;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = dwErrCode;
|
||
}
|
||
|
||
printf("[*] SetLastError: Error=0x%x\n", dwErrCode);
|
||
}
|
||
|
||
auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t lpCriticalSection = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpCriticalSection
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_cs = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||
lpCriticalSection = temp_cs;
|
||
}
|
||
|
||
if (lpCriticalSection != 0) {
|
||
RTL_CRITICAL_SECTION cs;
|
||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||
|
||
// 获取当前线程ID
|
||
HANDLE currentThreadHandle = nullptr;
|
||
if (context->GetPeInfo()->isX64) {
|
||
currentThreadHandle =
|
||
(HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread;
|
||
} else {
|
||
currentThreadHandle =
|
||
(HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread;
|
||
}
|
||
|
||
// 如果当前线程已经拥有锁,增加递归计数
|
||
if (cs.OwningThread == currentThreadHandle) {
|
||
cs.RecursionCount++;
|
||
} else {
|
||
// 如果没有线程拥有锁,获取它
|
||
if (cs.LockCount == -1) {
|
||
cs.OwningThread = currentThreadHandle;
|
||
cs.RecursionCount = 1;
|
||
cs.LockCount = 0;
|
||
} else {
|
||
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
|
||
cs.OwningThread = currentThreadHandle;
|
||
cs.RecursionCount = 1;
|
||
cs.LockCount++;
|
||
}
|
||
}
|
||
|
||
// 写回更新后的关键段结构
|
||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||
}
|
||
|
||
printf("[*] EnterCriticalSection: CS=0x%llx\n", lpCriticalSection);
|
||
}
|
||
|
||
auto Api_LeaveCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t lpCriticalSection = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpCriticalSection
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_cs = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||
lpCriticalSection = temp_cs;
|
||
}
|
||
|
||
if (lpCriticalSection != 0) {
|
||
RTL_CRITICAL_SECTION cs;
|
||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||
|
||
// 获取当前线程ID
|
||
HANDLE currentThreadHandle = nullptr;
|
||
if (context->GetPeInfo()->isX64) {
|
||
currentThreadHandle =
|
||
(HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread;
|
||
} else {
|
||
currentThreadHandle =
|
||
(HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread;
|
||
}
|
||
|
||
// 检查当前线程是否拥有锁
|
||
if (cs.OwningThread == currentThreadHandle) {
|
||
cs.RecursionCount--;
|
||
if (cs.RecursionCount == 0) {
|
||
// 完全释放锁
|
||
cs.OwningThread = nullptr;
|
||
cs.LockCount = -1;
|
||
}
|
||
|
||
// 写回更新后的关键段结构
|
||
uc_mem_write(uc, lpCriticalSection, &cs,
|
||
sizeof(RTL_CRITICAL_SECTION));
|
||
}
|
||
}
|
||
|
||
printf("[*] LeaveCriticalSection: CS=0x%llx\n", lpCriticalSection);
|
||
}
|
||
|
||
auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t lpStartupInfo = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpStartupInfo
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &lpStartupInfo);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_info = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_info, sizeof(uint32_t));
|
||
lpStartupInfo = temp_info;
|
||
}
|
||
|
||
if (lpStartupInfo != 0) {
|
||
// 创建一个默认的 STARTUPINFOW 结构
|
||
STARTUPINFOW si = {0};
|
||
si.cb = sizeof(STARTUPINFOW);
|
||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||
si.wShowWindow = SW_SHOWNORMAL;
|
||
si.lpDesktop = nullptr;
|
||
si.lpTitle = nullptr;
|
||
si.dwX = 0;
|
||
si.dwY = 0;
|
||
si.dwXSize = 0;
|
||
si.dwYSize = 0;
|
||
si.dwXCountChars = 0;
|
||
si.dwYCountChars = 0;
|
||
si.dwFillAttribute = 0;
|
||
si.cbReserved2 = 0;
|
||
si.lpReserved2 = nullptr;
|
||
si.hStdInput = nullptr;
|
||
si.hStdOutput = nullptr;
|
||
si.hStdError = nullptr;
|
||
|
||
// 写入结构到目标内存
|
||
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW));
|
||
}
|
||
|
||
printf("[*] GetStartupInfoW: lpStartupInfo=0x%llx\n", lpStartupInfo);
|
||
}
|
||
|
||
// 实现 GetStdHandle API
|
||
auto Api_GetStdHandle(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
int32_t nStdHandle = 0;
|
||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = nStdHandle
|
||
uint64_t temp_handle;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_handle);
|
||
nStdHandle = static_cast<int32_t>(temp_handle);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &nStdHandle, sizeof(int32_t));
|
||
}
|
||
|
||
// 根据请求的标准句柄类型返回相应的句柄
|
||
switch ((unsigned long)nStdHandle) {
|
||
case STD_INPUT_HANDLE: // -10
|
||
handle = reinterpret_cast<HANDLE>(0x1000); // 模拟标准输入句柄
|
||
break;
|
||
case STD_OUTPUT_HANDLE: // -11
|
||
handle = reinterpret_cast<HANDLE>(0x2000); // 模拟标准输出句柄
|
||
break; // End of Selection
|
||
break;
|
||
case STD_ERROR_HANDLE: // -12
|
||
handle = reinterpret_cast<HANDLE>(0x3000); // 模拟标准错误句柄
|
||
break;
|
||
default:
|
||
handle = INVALID_HANDLE_VALUE;
|
||
// 设置错误码
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = ERROR_INVALID_PARAMETER;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = ERROR_INVALID_PARAMETER;
|
||
}
|
||
break;
|
||
}
|
||
|
||
printf("[*] GetStdHandle: Type=%d, Handle=0x%p\n", nStdHandle, handle);
|
||
|
||
// 返回句柄值
|
||
uint64_t return_value = reinterpret_cast<uint64_t>(handle);
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_value);
|
||
}
|
||
|
||
// 实现 GetFileType API
|
||
auto Api_GetFileType(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
HANDLE hFile = nullptr;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = hFile
|
||
uint64_t temp_handle;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_handle);
|
||
hFile = reinterpret_cast<HANDLE>(temp_handle);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_handle = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_handle, sizeof(uint32_t));
|
||
hFile = reinterpret_cast<HANDLE>(static_cast<uint64_t>(temp_handle));
|
||
}
|
||
|
||
DWORD file_type = FILE_TYPE_UNKNOWN;
|
||
|
||
// 根据标准句柄类型返回相应的文件类型
|
||
if (hFile == reinterpret_cast<HANDLE>(0x1000) || // STD_INPUT_HANDLE
|
||
hFile == reinterpret_cast<HANDLE>(0x2000) || // STD_OUTPUT_HANDLE
|
||
hFile == reinterpret_cast<HANDLE>(0x3000)) { // STD_ERROR_HANDLE
|
||
file_type = FILE_TYPE_CHAR; // 控制台句柄通常是字符设备
|
||
} else {
|
||
// 对于无效句柄,设置错误码
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = ERROR_INVALID_HANDLE;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = ERROR_INVALID_HANDLE;
|
||
}
|
||
file_type = FILE_TYPE_UNKNOWN;
|
||
}
|
||
|
||
printf("[*] GetFileType: Handle=0x%p, Type=0x%x\n", hFile, file_type);
|
||
|
||
// 返回文件类型
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&file_type);
|
||
}
|
||
|
||
// 实现 GetCommandLineA API
|
||
auto Api_GetCommandLineA(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
printf("[*] GetCommandLineA: CommandLine=%s\n", context->GetCommandLine());
|
||
|
||
// 返回命令行字符串的地址
|
||
uint64_t return_value = context->GetCommandLineAddress();
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_value);
|
||
}
|
||
|
||
// 实现 GetCommandLineW API
|
||
auto Api_GetCommandLineW(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
printf("[*] GetCommandLineW: CommandLine=%s\n", context->GetCommandLine());
|
||
|
||
// 返回宽字符命令行字符串的地址
|
||
uint64_t return_value = context->GetCommandLineWAddress();
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&return_value);
|
||
}
|
||
|
||
// 实现 GetACP API
|
||
auto Api_GetACP(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
// 返回默认的 ANSI 代码页 (936 - 简体中文)
|
||
uint32_t codepage = 936;
|
||
printf("[*] GetACP: CodePage=%u\n", codepage);
|
||
|
||
// 返回代码页值
|
||
uc_reg_write(uc,
|
||
static_cast<Sandbox*>(sandbox)->GetPeInfo()->isX64
|
||
? UC_X86_REG_RAX
|
||
: UC_X86_REG_EAX,
|
||
&codepage);
|
||
}
|
||
|
||
// 实现 GetCPInfo API
|
||
auto Api_GetCPInfo(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t codePage = 0;
|
||
uint64_t lpCPInfo = 0;
|
||
BOOL success = FALSE;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = CodePage, rdx = lpCPInfo
|
||
uint64_t temp_codepage;
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage);
|
||
codePage = static_cast<uint32_t>(temp_codepage);
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &lpCPInfo);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &codePage, sizeof(uint32_t));
|
||
esp_address += 0x4;
|
||
uint32_t temp_cpinfo;
|
||
uc_mem_read(uc, esp_address, &temp_cpinfo, sizeof(uint32_t));
|
||
lpCPInfo = temp_cpinfo;
|
||
}
|
||
|
||
if (lpCPInfo != 0) {
|
||
// 创建 CPINFO 结构
|
||
CPINFO cpInfo = {0};
|
||
|
||
// 根据代码页设置相应的信息
|
||
switch (codePage) {
|
||
case 936: // 简体中文 GBK
|
||
cpInfo.MaxCharSize = 2; // 最大字符大小为2字节
|
||
cpInfo.DefaultChar[0] = '?'; // 默认替换字符
|
||
cpInfo.DefaultChar[1] = '\0';
|
||
cpInfo.LeadByte[0] = 0x81; // 前导字节范围
|
||
cpInfo.LeadByte[1] = 0xFE;
|
||
cpInfo.LeadByte[2] = 0; // 结束标记
|
||
success = TRUE;
|
||
break;
|
||
|
||
case 437: // US ASCII
|
||
case 1252: // Western European
|
||
cpInfo.MaxCharSize = 1; // 单字节字符集
|
||
cpInfo.DefaultChar[0] = '?';
|
||
cpInfo.DefaultChar[1] = '\0';
|
||
cpInfo.LeadByte[0] = 0; // 无前导字节
|
||
success = TRUE;
|
||
break;
|
||
|
||
default:
|
||
// 不支持的代码页
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue =
|
||
ERROR_INVALID_PARAMETER;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue =
|
||
ERROR_INVALID_PARAMETER;
|
||
}
|
||
success = FALSE;
|
||
break;
|
||
}
|
||
|
||
if (success) {
|
||
// 写入 CPINFO 结构到目标内存
|
||
uc_mem_write(uc, lpCPInfo, &cpInfo, sizeof(CPINFO));
|
||
}
|
||
} else {
|
||
// 无效的指针参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = ERROR_INVALID_PARAMETER;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = ERROR_INVALID_PARAMETER;
|
||
}
|
||
success = FALSE;
|
||
}
|
||
|
||
printf("[*] GetCPInfo: CodePage=%u, lpCPInfo=0x%llx, Success=%d\n",
|
||
codePage, lpCPInfo, success);
|
||
|
||
// 返回操作是否成功
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&success);
|
||
}
|
||
|
||
auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t CodePage = 0;
|
||
uint32_t dwFlags = 0;
|
||
uint64_t lpMultiByteStr = 0;
|
||
int32_t cbMultiByte = 0;
|
||
uint64_t lpWideCharStr = 0;
|
||
int32_t cchWideChar = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
uint64_t temp_codepage = 0;
|
||
uint64_t temp_flags = 0;
|
||
uint64_t temp_multibyte = 0;
|
||
uint64_t temp_cbmultibyte = 0;
|
||
|
||
// x64: rcx, rdx, r8, r9, [rsp+0x28], [rsp+0x30]
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage);
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags);
|
||
uc_reg_read(uc, UC_X86_REG_R8, &temp_multibyte);
|
||
uc_reg_read(uc, UC_X86_REG_R9, &temp_cbmultibyte);
|
||
|
||
CodePage = static_cast<uint32_t>(temp_codepage);
|
||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||
lpMultiByteStr = temp_multibyte;
|
||
cbMultiByte = static_cast<int32_t>(temp_cbmultibyte);
|
||
|
||
// 获取栈上的参数
|
||
uint64_t rsp = 0;
|
||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||
|
||
// 为了确保安全访问,先验证栈地址的有效性
|
||
if (rsp < 0x8000000000000000 || rsp + 0x40 > 0x8000000000010000) {
|
||
// 无效的栈地址
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
int result = 0;
|
||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||
return;
|
||
}
|
||
|
||
// 读取栈上的参数
|
||
uint64_t shadow_space = 0x20; // x64调用约定中的shadow space
|
||
uc_mem_read(uc, rsp + shadow_space + 0x8, &lpWideCharStr,
|
||
sizeof(uint64_t));
|
||
uc_mem_read(uc, rsp + shadow_space + 0x10, &cchWideChar,
|
||
sizeof(int32_t));
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
|
||
uc_mem_read(uc, esp_address, &CodePage, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x4, &dwFlags, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x8, &lpMultiByteStr, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0xC, &cbMultiByte, sizeof(int32_t));
|
||
uc_mem_read(uc, esp_address + 0x10, &lpWideCharStr, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x14, &cchWideChar, sizeof(int32_t));
|
||
}
|
||
|
||
// 验证参数
|
||
if (lpMultiByteStr == 0 || (lpWideCharStr == 0 && cchWideChar != 0)) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 读取源字符串
|
||
std::vector<char> srcBuffer;
|
||
if (cbMultiByte == -1) {
|
||
// 如果长度为-1,则源字符串以null结尾
|
||
char ch = 0;
|
||
size_t len = 0;
|
||
do {
|
||
if (uc_mem_read(uc, lpMultiByteStr + len, &ch, 1) != UC_ERR_OK) {
|
||
break;
|
||
}
|
||
srcBuffer.push_back(ch);
|
||
len++;
|
||
} while (ch != 0 && len < MAX_PATH); // 添加长度限制防止无限循环
|
||
|
||
if (len >= MAX_PATH) {
|
||
// 设置错误码
|
||
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
cbMultiByte = static_cast<int32_t>(len);
|
||
} else if (cbMultiByte > 0) {
|
||
// 使用指定长度,但添加安全检查
|
||
if (cbMultiByte > MAX_PATH) {
|
||
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
srcBuffer.resize(cbMultiByte);
|
||
if (uc_mem_read(uc, lpMultiByteStr, srcBuffer.data(), cbMultiByte) !=
|
||
UC_ERR_OK) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
} else {
|
||
// 无效的输入长度
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 计算所需的宽字符缓冲区大小
|
||
int result = MultiByteToWideChar(CodePage, dwFlags, srcBuffer.data(),
|
||
cbMultiByte, nullptr, 0);
|
||
|
||
if (result == 0) {
|
||
// 转换失败,获取错误码
|
||
DWORD error = GetLastError();
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 如果只是查询所需缓冲区大小
|
||
if (lpWideCharStr == 0 || cchWideChar == 0) {
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 检查目标缓冲区大小是否足够
|
||
if (cchWideChar < result) {
|
||
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
result = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 执行实际转换
|
||
std::vector<wchar_t> wideBuffer(result);
|
||
if (MultiByteToWideChar(CodePage, dwFlags, srcBuffer.data(), cbMultiByte,
|
||
wideBuffer.data(), result) > 0) {
|
||
// 写入转换后的字符串到目标内存
|
||
if (uc_mem_write(uc, lpWideCharStr, wideBuffer.data(),
|
||
result * sizeof(wchar_t)) != UC_ERR_OK) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
result = 0;
|
||
}
|
||
} else {
|
||
// 转换失败
|
||
DWORD error = GetLastError();
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
result = 0;
|
||
}
|
||
|
||
printf(
|
||
"[*] MultiByteToWideChar: CodePage=%u, Flags=0x%x, Input=%p, "
|
||
"InputLen=%d, Output=%p, OutputLen=%d, Result=%d\n",
|
||
CodePage, dwFlags, (void*)lpMultiByteStr, cbMultiByte,
|
||
(void*)lpWideCharStr, cchWideChar, result);
|
||
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
}
|
||
|
||
auto Sandbox::CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment* {
|
||
auto segment = new HeapSegment();
|
||
segment->base = base;
|
||
segment->size = size;
|
||
|
||
// 创建初始空闲块
|
||
auto block = new HeapBlock();
|
||
block->address = base;
|
||
block->size = size;
|
||
block->is_free = true;
|
||
block->next = nullptr;
|
||
block->prev = nullptr;
|
||
|
||
segment->blocks = block;
|
||
return segment;
|
||
}
|
||
|
||
auto Sandbox::AllocateFromSegment(HeapSegment* segment, size_t size)
|
||
-> uint64_t {
|
||
// 对齐大小到16字节
|
||
size = (size + 15) & ~15;
|
||
|
||
// 查找合适的空闲块
|
||
HeapBlock* current = segment->blocks;
|
||
while (current != nullptr) {
|
||
if (current->is_free && current->size >= size) {
|
||
// 如果块太大,分割它
|
||
if (current->size > size + 32) { // 32字节为最小块大小
|
||
SplitBlock(current, size);
|
||
}
|
||
|
||
current->is_free = false;
|
||
return current->address;
|
||
}
|
||
current = current->next;
|
||
}
|
||
|
||
return 0; // 分配失败
|
||
}
|
||
|
||
auto Sandbox::FreeBlock(uint64_t address) -> bool {
|
||
// 查找包含此地址的堆段
|
||
HeapSegment* segment = FindHeapSegment(address);
|
||
if (!segment) return false;
|
||
|
||
// 查找对应的块
|
||
HeapBlock* current = segment->blocks;
|
||
while (current != nullptr) {
|
||
if (current->address == address) {
|
||
if (current->is_free) return false; // 已经是空闲的
|
||
|
||
current->is_free = true;
|
||
MergeBlocks(current); // 尝试合并相邻的空闲块
|
||
return true;
|
||
}
|
||
current = current->next;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
auto Sandbox::FindHeapSegment(uint64_t address) -> HeapSegment* {
|
||
for (auto& pair : m_heapSegments) {
|
||
HeapSegment* segment = pair.second;
|
||
if (address >= segment->base &&
|
||
address < segment->base + segment->size) {
|
||
return segment;
|
||
}
|
||
}
|
||
return nullptr;
|
||
}
|
||
|
||
auto Sandbox::MergeBlocks(HeapBlock* block) -> void {
|
||
// 与后一个块合并
|
||
if (block->next && block->next->is_free) {
|
||
block->size += block->next->size;
|
||
HeapBlock* temp = block->next;
|
||
block->next = temp->next;
|
||
if (block->next) {
|
||
block->next->prev = block;
|
||
}
|
||
delete temp;
|
||
}
|
||
|
||
// 与前一个块合并
|
||
if (block->prev && block->prev->is_free) {
|
||
block->prev->size += block->size;
|
||
block->prev->next = block->next;
|
||
if (block->next) {
|
||
block->next->prev = block->prev;
|
||
}
|
||
delete block;
|
||
}
|
||
}
|
||
|
||
auto Sandbox::SplitBlock(HeapBlock* block, size_t size) -> void {
|
||
size_t remaining_size = block->size - size;
|
||
block->size = size;
|
||
|
||
auto new_block = new HeapBlock();
|
||
new_block->address = block->address + size;
|
||
new_block->size = remaining_size;
|
||
new_block->is_free = true;
|
||
new_block->next = block->next;
|
||
new_block->prev = block;
|
||
|
||
if (block->next) {
|
||
block->next->prev = new_block;
|
||
}
|
||
block->next = new_block;
|
||
}
|
||
|
||
auto Sandbox::InitCommandLine(std::string commandLine) -> void {
|
||
// 设置默认的命令行字符串
|
||
m_commandLine = commandLine;
|
||
|
||
// 将ANSI命令行字符串写入模拟内存
|
||
uc_mem_map(m_ucEngine, CMDLINE_ADDRESS, PAGE_SIZE,
|
||
UC_PROT_READ | UC_PROT_WRITE);
|
||
uc_mem_write(m_ucEngine, CMDLINE_ADDRESS, m_commandLine.c_str(),
|
||
m_commandLine.length() + 1);
|
||
|
||
// 为宽字符命令行分配内存
|
||
uc_mem_map(m_ucEngine, CMDLINEW_ADDRESS, PAGE_SIZE,
|
||
UC_PROT_READ | UC_PROT_WRITE);
|
||
|
||
// 将ANSI字符串转换为宽字符字符串
|
||
std::wstring wCommandLine(m_commandLine.begin(), m_commandLine.end());
|
||
|
||
// 写入宽字符命令行字符串
|
||
uc_mem_write(m_ucEngine, CMDLINEW_ADDRESS, wCommandLine.c_str(),
|
||
(wCommandLine.length() + 1) * sizeof(wchar_t));
|
||
}
|
||
|
||
auto Api_GetModuleFileNameW(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t hModule = 0;
|
||
uint64_t lpFilename = 0;
|
||
uint32_t nSize = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = hModule, rdx = lpFilename, r8 = nSize
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &hModule);
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &lpFilename);
|
||
uint64_t temp_size;
|
||
uc_reg_read(uc, UC_X86_REG_R8, &temp_size);
|
||
nSize = static_cast<uint32_t>(temp_size);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uint32_t temp_module = 0;
|
||
uint32_t temp_filename = 0;
|
||
uc_mem_read(uc, esp_address, &temp_module, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x4, &temp_filename, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x8, &nSize, sizeof(uint32_t));
|
||
hModule = temp_module;
|
||
lpFilename = temp_filename;
|
||
}
|
||
|
||
uint32_t result = 0;
|
||
|
||
// 验证参数
|
||
if (lpFilename == 0 || nSize == 0) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
std::wstring modulePath;
|
||
if (hModule == 0) {
|
||
// 如果hModule为NULL,返回主模块(PE文件)的路径
|
||
modulePath = std::wstring(context->GetPeInfo()->inputFilePath.begin(),
|
||
context->GetPeInfo()->inputFilePath.end());
|
||
} else {
|
||
// 在模块列表中查找对应模块
|
||
bool found = false;
|
||
for (const auto& module : context->GetModuleList()) {
|
||
if (module->base == hModule) {
|
||
// 构建完整的模块路径
|
||
char windowsPath[MAX_PATH];
|
||
GetWindowsDirectoryA(windowsPath, sizeof(windowsPath));
|
||
|
||
// 根据PE架构选择正确的系统目录
|
||
const std::string systemDir = context->GetPeInfo()->isX64
|
||
? "\\System32\\"
|
||
: "\\SysWOW64\\";
|
||
|
||
std::string fullPath =
|
||
std::string(windowsPath) + systemDir + module->name;
|
||
modulePath = std::wstring(fullPath.begin(), fullPath.end());
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!found) {
|
||
DWORD error = ERROR_MOD_NOT_FOUND;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
uc_reg_write(
|
||
uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 检查缓冲区大小是否足够
|
||
if (nSize < modulePath.length() + 1) {
|
||
// 缓冲区太小,返回所需大小
|
||
result = static_cast<uint32_t>(modulePath.length() + 1);
|
||
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
} else {
|
||
// 写入路径到缓冲区
|
||
if (uc_mem_write(uc, lpFilename, modulePath.c_str(),
|
||
(modulePath.length() + 1) * sizeof(wchar_t)) ==
|
||
UC_ERR_OK) {
|
||
result = static_cast<uint32_t>(modulePath.length());
|
||
} else {
|
||
result = 0;
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
}
|
||
|
||
printf(
|
||
"[*] GetModuleFileNameW: Module=0x%llx, Buffer=0x%llx, Size=%u, "
|
||
"Result=%u, Path=%ls\n",
|
||
hModule, lpFilename, nSize, result, modulePath.c_str());
|
||
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
}
|
||
|
||
// 实现 AreFileApisANSI API
|
||
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
// 默认返回TRUE,表示使用ANSI字符集
|
||
BOOL isAnsi = TRUE;
|
||
printf("[*] AreFileApisANSI: IsAnsi=%d\n", isAnsi);
|
||
|
||
// 返回结果
|
||
uc_reg_write(uc,
|
||
static_cast<Sandbox*>(sandbox)->GetPeInfo()->isX64
|
||
? UC_X86_REG_RAX
|
||
: UC_X86_REG_EAX,
|
||
&isAnsi);
|
||
}
|
||
|
||
auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint32_t CodePage = 0;
|
||
uint32_t dwFlags = 0;
|
||
uint64_t lpWideCharStr = 0;
|
||
int32_t cchWideChar = 0;
|
||
uint64_t lpMultiByteStr = 0;
|
||
int32_t cbMultiByte = 0;
|
||
uint64_t lpDefaultChar = 0;
|
||
uint64_t lpUsedDefaultChar = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx, rdx, r8, r9, [rsp+0x28], [rsp+0x30], [rsp+0x38], [rsp+0x40]
|
||
uint64_t temp_codepage = 0;
|
||
uint64_t temp_flags = 0;
|
||
uint64_t temp_widechar = 0;
|
||
uint64_t temp_cchwidechar = 0;
|
||
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage);
|
||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags);
|
||
uc_reg_read(uc, UC_X86_REG_R8, &temp_widechar);
|
||
uc_reg_read(uc, UC_X86_REG_R9, &temp_cchwidechar);
|
||
|
||
CodePage = static_cast<uint32_t>(temp_codepage);
|
||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||
lpWideCharStr = temp_widechar;
|
||
cchWideChar = static_cast<int32_t>(temp_cchwidechar);
|
||
|
||
// 获取栈上的参数
|
||
uint64_t rsp = 0;
|
||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||
uint64_t shadow_space = 0x20;
|
||
|
||
uc_mem_read(uc, rsp + shadow_space + 0x8, &lpMultiByteStr,
|
||
sizeof(uint64_t));
|
||
uc_mem_read(uc, rsp + shadow_space + 0x10, &cbMultiByte,
|
||
sizeof(int32_t));
|
||
uc_mem_read(uc, rsp + shadow_space + 0x18, &lpDefaultChar,
|
||
sizeof(uint64_t));
|
||
uc_mem_read(uc, rsp + shadow_space + 0x20, &lpUsedDefaultChar,
|
||
sizeof(uint64_t));
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
|
||
uc_mem_read(uc, esp_address, &CodePage, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x4, &dwFlags, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x8, &lpWideCharStr, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0xC, &cchWideChar, sizeof(int32_t));
|
||
uc_mem_read(uc, esp_address + 0x10, &lpMultiByteStr, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x14, &cbMultiByte, sizeof(int32_t));
|
||
uc_mem_read(uc, esp_address + 0x18, &lpDefaultChar, sizeof(uint32_t));
|
||
uc_mem_read(uc, esp_address + 0x1C, &lpUsedDefaultChar,
|
||
sizeof(uint32_t));
|
||
}
|
||
|
||
// 基本参数验证
|
||
if (lpWideCharStr == 0 || cchWideChar == 0) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 读取源宽字符串
|
||
std::vector<wchar_t> srcBuffer;
|
||
size_t actualWideLength = 0;
|
||
|
||
if (cchWideChar == -1) {
|
||
// 如果长度为-1,则源字符串以null结尾
|
||
wchar_t ch = 0;
|
||
do {
|
||
if (uc_mem_read(uc, lpWideCharStr + (actualWideLength * 2), &ch,
|
||
2) != UC_ERR_OK) {
|
||
break;
|
||
}
|
||
srcBuffer.push_back(ch);
|
||
actualWideLength++;
|
||
} while (ch != 0 && actualWideLength < MAX_PATH);
|
||
|
||
if (actualWideLength >= MAX_PATH) {
|
||
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
} else {
|
||
// 使用指定长度
|
||
if (cchWideChar > 0 && cchWideChar <= MAX_PATH) {
|
||
srcBuffer.resize(cchWideChar);
|
||
if (uc_mem_read(uc, lpWideCharStr, srcBuffer.data(),
|
||
cchWideChar * 2) != UC_ERR_OK) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX
|
||
: UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
actualWideLength = cchWideChar;
|
||
} else {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 读取默认字符和使用默认字符标志
|
||
char defaultChar = '?';
|
||
BOOL usedDefaultChar = FALSE;
|
||
if (lpDefaultChar != 0) {
|
||
uc_mem_read(uc, lpDefaultChar, &defaultChar, 1);
|
||
}
|
||
|
||
// 计算所需的多字节缓冲区大小
|
||
int requiredSize = WideCharToMultiByte(
|
||
CodePage, dwFlags, srcBuffer.data(), static_cast<int>(actualWideLength),
|
||
nullptr, 0, lpDefaultChar ? &defaultChar : nullptr,
|
||
lpUsedDefaultChar ? &usedDefaultChar : nullptr);
|
||
|
||
if (requiredSize == 0) {
|
||
// 获取并设置错误码
|
||
DWORD error = GetLastError();
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 如果只是查询所需缓冲区大小
|
||
if (lpMultiByteStr == 0 || cbMultiByte == 0) {
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&requiredSize);
|
||
return;
|
||
}
|
||
|
||
// 检查目标缓冲区大小是否足够
|
||
if (cbMultiByte < requiredSize) {
|
||
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
int result = 0;
|
||
uc_reg_write(
|
||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
return;
|
||
}
|
||
|
||
// 执行实际转换
|
||
std::vector<char> multiByteBuffer(requiredSize);
|
||
int result = WideCharToMultiByte(
|
||
CodePage, dwFlags, srcBuffer.data(), static_cast<int>(actualWideLength),
|
||
multiByteBuffer.data(), requiredSize,
|
||
lpDefaultChar ? &defaultChar : nullptr,
|
||
lpUsedDefaultChar ? &usedDefaultChar : nullptr);
|
||
|
||
if (result > 0) {
|
||
// 写入转换后的字符串到目标内存
|
||
if (uc_mem_write(uc, lpMultiByteStr, multiByteBuffer.data(), result) !=
|
||
UC_ERR_OK) {
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
result = 0;
|
||
}
|
||
|
||
// 如果需要,写回使用默认字符标志
|
||
if (lpUsedDefaultChar != 0) {
|
||
uc_mem_write(uc, lpUsedDefaultChar, &usedDefaultChar, sizeof(BOOL));
|
||
}
|
||
} else {
|
||
// 获取并设置错误码
|
||
DWORD error = GetLastError();
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
printf(
|
||
"[*] WideCharToMultiByte: CodePage=%u, Flags=0x%x, WideStr=%p, "
|
||
"WideLen=%d, MultiStr=%p, MultiLen=%d, Result=%d\n",
|
||
CodePage, dwFlags, (void*)lpWideCharStr, cchWideChar,
|
||
(void*)lpMultiByteStr, cbMultiByte, result);
|
||
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&result);
|
||
}
|
||
|
||
// 实现 InitializeSListHead API
|
||
auto Api_InitializeSListHead(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t ListHead = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = ListHead
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &ListHead);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_listhead = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_listhead, sizeof(uint32_t));
|
||
ListHead = temp_listhead;
|
||
}
|
||
|
||
if (ListHead != 0) {
|
||
if (context->GetPeInfo()->isX64) {
|
||
// 64位系统的SLIST_HEADER结构 (16字节对齐)
|
||
struct SLIST_HEADER64 {
|
||
union {
|
||
struct {
|
||
ULONGLONG Alignment;
|
||
ULONGLONG Region;
|
||
} DUMMYSTRUCTNAME;
|
||
struct {
|
||
ULONGLONG Depth : 16;
|
||
ULONGLONG Sequence : 48;
|
||
ULONGLONG Reserved : 4;
|
||
ULONGLONG NextEntry : 60;
|
||
} HeaderX64;
|
||
};
|
||
} header = {0};
|
||
|
||
// 初始化Depth和Sequence为0
|
||
header.HeaderX64.Depth = 0;
|
||
header.HeaderX64.Sequence = 0;
|
||
header.HeaderX64.Reserved = 0;
|
||
header.HeaderX64.NextEntry = 0;
|
||
|
||
// 写入初始化的结构
|
||
uc_mem_write(uc, ListHead, &header, sizeof(SLIST_HEADER64));
|
||
} else {
|
||
// 32位系统的SLIST_HEADER结构 (8字节)
|
||
struct SLIST_HEADER32 {
|
||
union {
|
||
ULONGLONG Alignment;
|
||
struct {
|
||
SLIST_ENTRY* Next;
|
||
WORD Depth;
|
||
WORD Sequence;
|
||
} Header32;
|
||
};
|
||
} header = {0};
|
||
|
||
// 初始化Next、Depth和Sequence为0
|
||
header.Header32.Next = nullptr;
|
||
header.Header32.Depth = 0;
|
||
header.Header32.Sequence = 0;
|
||
|
||
// 写入初始化的结构
|
||
uc_mem_write(uc, ListHead, &header, sizeof(SLIST_HEADER32));
|
||
}
|
||
}
|
||
|
||
printf("[*] InitializeSListHead: ListHead=0x%llx\n", ListHead);
|
||
}
|
||
|
||
// 实现 GetEnvironmentStringsW API
|
||
auto Api_GetEnvironmentStringsW(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t envBlock = context->GetEnvBlockBase();
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&envBlock);
|
||
}
|
||
|
||
// 实现 FreeEnvironmentStringsW API
|
||
auto Api_FreeEnvironmentStringsW(void* sandbox, uc_engine* uc, uint64_t address)
|
||
-> void {
|
||
auto context = static_cast<Sandbox*>(sandbox);
|
||
uint64_t lpszEnvironmentBlock = 0;
|
||
|
||
// 获取参数
|
||
if (context->GetPeInfo()->isX64) {
|
||
// x64: rcx = lpszEnvironmentBlock
|
||
uc_reg_read(uc, UC_X86_REG_RCX, &lpszEnvironmentBlock);
|
||
} else {
|
||
// x86: 从栈上读取参数
|
||
uint32_t esp_address = 0;
|
||
uint32_t temp_block = 0;
|
||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||
esp_address += 0x4; // 跳过返回地址
|
||
uc_mem_read(uc, esp_address, &temp_block, sizeof(uint32_t));
|
||
lpszEnvironmentBlock = temp_block;
|
||
}
|
||
|
||
// 检查传入的地址是否是我们之前分配的环境块地址
|
||
BOOL success = (lpszEnvironmentBlock == context->GetEnvBlockBase());
|
||
|
||
if (!success) {
|
||
// 如果地址无效,设置错误码
|
||
DWORD error = ERROR_INVALID_PARAMETER;
|
||
if (context->GetPeInfo()->isX64) {
|
||
context->GetTeb64()->LastErrorValue = error;
|
||
} else {
|
||
context->GetTeb32()->LastErrorValue = error;
|
||
}
|
||
}
|
||
|
||
printf("[*] FreeEnvironmentStringsW: Block=0x%llx, Success=%d\n",
|
||
lpszEnvironmentBlock, success);
|
||
|
||
// 返回操作是否成功
|
||
uc_reg_write(uc,
|
||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||
&success);
|
||
}
|
||
|
||
auto Sandbox::InitApiHooks() -> void {
|
||
auto FakeApi_GetSystemTimeAsFileTime =
|
||
_fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1};
|
||
auto FakeApi_GetCurrentThreadId =
|
||
_fakeApi{.func = Api_GetCurrentThreadId, .paramCount = 0};
|
||
auto FakeApi_GetCurrentProcessId =
|
||
_fakeApi{.func = Api_GetCurrentProcessId, .paramCount = 0};
|
||
auto FakeApi_QueryPerformanceCounter =
|
||
_fakeApi{.func = Api_QueryPerformanceCounter, .paramCount = 1};
|
||
auto FakeApi_LoadLibraryA =
|
||
_fakeApi{.func = Api_LoadLibraryA, .paramCount = 1};
|
||
auto FakeApi_LoadLibraryExW =
|
||
_fakeApi{.func = Api_LoadLibraryExW, .paramCount = 3};
|
||
auto FakeApi_GetLastError =
|
||
_fakeApi{.func = Api_GetLastError, .paramCount = 0};
|
||
auto FakeApi_InitializeCriticalSectionAndSpinCount = _fakeApi{
|
||
.func = Api_InitializeCriticalSectionAndSpinCount, .paramCount = 2};
|
||
auto FakeApi_TlsAlloc = _fakeApi{.func = Api_TlsAlloc, .paramCount = 0};
|
||
auto FakeApi_TlsSetValue =
|
||
_fakeApi{.func = Api_TlsSetValue, .paramCount = 2};
|
||
auto FakeApi_DeleteCriticalSection =
|
||
_fakeApi{.func = Api_DeleteCriticalSection, .paramCount = 1};
|
||
auto FakeApi_IsProcessorFeaturePresent =
|
||
_fakeApi{.func = Api_IsProcessorFeaturePresent, .paramCount = 1};
|
||
auto FakeApi_GetProcAddress =
|
||
_fakeApi{.func = Api_GetProcAddress, .paramCount = 2};
|
||
auto FakeApi_GetProcessHeap =
|
||
_fakeApi{.func = Api_GetProcessHeap, .paramCount = 0};
|
||
auto FakeApi_HeapAlloc = _fakeApi{.func = Api_HeapAlloc, .paramCount = 3};
|
||
auto FakeApi_HeapFree = _fakeApi{.func = Api_HeapFree, .paramCount = 3};
|
||
auto FakeApi_TlsGetValue =
|
||
_fakeApi{.func = Api_TlsGetValue, .paramCount = 1};
|
||
auto FakeApi_SetLastError =
|
||
_fakeApi{.func = Api_SetLastError, .paramCount = 1};
|
||
auto FakeApi_EnterCriticalSection =
|
||
_fakeApi{.func = Api_EnterCriticalSection, .paramCount = 1};
|
||
auto FakeApi_LeaveCriticalSection =
|
||
_fakeApi{.func = Api_LeaveCriticalSection, .paramCount = 1};
|
||
auto FakeApi_GetStartupInfoW =
|
||
_fakeApi{.func = Api_GetStartupInfoW, .paramCount = 1};
|
||
auto FakeApi_GetStdHandle =
|
||
_fakeApi{.func = Api_GetStdHandle, .paramCount = 1};
|
||
auto FakeApi_GetFileType =
|
||
_fakeApi{.func = Api_GetFileType, .paramCount = 1};
|
||
auto FakeApi_GetCommandLineA =
|
||
_fakeApi{.func = Api_GetCommandLineA, .paramCount = 0};
|
||
auto FakeApi_GetCommandLineW =
|
||
_fakeApi{.func = Api_GetCommandLineW, .paramCount = 0};
|
||
auto FakeApi_GetACP = _fakeApi{.func = Api_GetACP, .paramCount = 0};
|
||
auto FakeApi_GetCPInfo = _fakeApi{.func = Api_GetCPInfo, .paramCount = 2};
|
||
auto FakeApi_MultiByteToWideChar =
|
||
_fakeApi{.func = Api_MultiByteToWideChar, .paramCount = 6};
|
||
auto FakeApi_GetModuleFileNameW =
|
||
_fakeApi{.func = Api_GetModuleFileNameW, .paramCount = 3};
|
||
auto FakeApi_AreFileApisANSI =
|
||
_fakeApi{.func = Api_AreFileApisANSI, .paramCount = 0};
|
||
auto FakeApi_WideCharToMultiByte =
|
||
_fakeApi{.func = Api_WideCharToMultiByte, .paramCount = 8};
|
||
auto FakeApi_InitializeSListHead =
|
||
_fakeApi{.func = Api_InitializeSListHead, .paramCount = 1};
|
||
auto FakeApi_GetEnvironmentStringsW =
|
||
_fakeApi{.func = Api_GetEnvironmentStringsW, .paramCount = 0};
|
||
auto FakeApi_FreeEnvironmentStringsW =
|
||
_fakeApi{.func = Api_FreeEnvironmentStringsW, .paramCount = 1};
|
||
|
||
api_map = {
|
||
{"GetSystemTimeAsFileTime",
|
||
std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)},
|
||
{"GetCurrentThreadId",
|
||
std::make_shared<_fakeApi>(FakeApi_GetCurrentThreadId)},
|
||
{"GetCurrentProcessId",
|
||
std::make_shared<_fakeApi>(FakeApi_GetCurrentProcessId)},
|
||
{"QueryPerformanceCounter",
|
||
std::make_shared<_fakeApi>(FakeApi_QueryPerformanceCounter)},
|
||
{"LoadLibraryA", std::make_shared<_fakeApi>(FakeApi_LoadLibraryA)},
|
||
{"LoadLibraryExW", std::make_shared<_fakeApi>(FakeApi_LoadLibraryExW)},
|
||
{"GetLastError", std::make_shared<_fakeApi>(FakeApi_GetLastError)},
|
||
{"InitializeCriticalSectionAndSpinCount",
|
||
std::make_shared<_fakeApi>(
|
||
FakeApi_InitializeCriticalSectionAndSpinCount)},
|
||
{"DeleteCriticalSection",
|
||
std::make_shared<_fakeApi>(FakeApi_DeleteCriticalSection)},
|
||
{"TlsAlloc", std::make_shared<_fakeApi>(FakeApi_TlsAlloc)},
|
||
{"TlsSetValue", std::make_shared<_fakeApi>(FakeApi_TlsSetValue)},
|
||
{"IsProcessorFeaturePresent",
|
||
std::make_shared<_fakeApi>(FakeApi_IsProcessorFeaturePresent)},
|
||
{"GetProcAddress", std::make_shared<_fakeApi>(FakeApi_GetProcAddress)},
|
||
{"GetProcessHeap", std::make_shared<_fakeApi>(FakeApi_GetProcessHeap)},
|
||
{"HeapAlloc", std::make_shared<_fakeApi>(FakeApi_HeapAlloc)},
|
||
{"HeapFree", std::make_shared<_fakeApi>(FakeApi_HeapFree)},
|
||
{"TlsGetValue", std::make_shared<_fakeApi>(FakeApi_TlsGetValue)},
|
||
{"SetLastError", std::make_shared<_fakeApi>(FakeApi_SetLastError)},
|
||
{"EnterCriticalSection",
|
||
std::make_shared<_fakeApi>(FakeApi_EnterCriticalSection)},
|
||
{"LeaveCriticalSection",
|
||
std::make_shared<_fakeApi>(FakeApi_LeaveCriticalSection)},
|
||
{"GetStartupInfoW",
|
||
std::make_shared<_fakeApi>(FakeApi_GetStartupInfoW)},
|
||
{"GetStdHandle", std::make_shared<_fakeApi>(FakeApi_GetStdHandle)},
|
||
{"GetFileType", std::make_shared<_fakeApi>(FakeApi_GetFileType)},
|
||
{"GetCommandLineA",
|
||
std::make_shared<_fakeApi>(FakeApi_GetCommandLineA)},
|
||
{"GetCommandLineW",
|
||
std::make_shared<_fakeApi>(FakeApi_GetCommandLineW)},
|
||
{"GetACP", std::make_shared<_fakeApi>(FakeApi_GetACP)},
|
||
{"GetCPInfo", std::make_shared<_fakeApi>(FakeApi_GetCPInfo)},
|
||
{"MultiByteToWideChar",
|
||
std::make_shared<_fakeApi>(FakeApi_MultiByteToWideChar)},
|
||
{"GetModuleFileNameW",
|
||
std::make_shared<_fakeApi>(FakeApi_GetModuleFileNameW)},
|
||
{"AreFileApisANSI",
|
||
std::make_shared<_fakeApi>(FakeApi_AreFileApisANSI)},
|
||
{"WideCharToMultiByte",
|
||
std::make_shared<_fakeApi>(FakeApi_WideCharToMultiByte)},
|
||
{"InitializeSListHead",
|
||
std::make_shared<_fakeApi>(FakeApi_InitializeSListHead)},
|
||
{"GetEnvironmentStringsW",
|
||
std::make_shared<_fakeApi>(FakeApi_GetEnvironmentStringsW)},
|
||
{"FreeEnvironmentStringsW",
|
||
std::make_shared<_fakeApi>(FakeApi_FreeEnvironmentStringsW)},
|
||
};
|
||
}
|
||
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
||
std::string ApiName) -> void {
|
||
auto it = api_map.find(ApiName);
|
||
if (it != api_map.end()) {
|
||
it->second->func(this, uc, address);
|
||
|
||
// 获取参数数量
|
||
int paramCount = it->second->paramCount;
|
||
|
||
// 获取当前的栈指针
|
||
uint64_t rsp;
|
||
uc_reg_read(uc,
|
||
this->GetPeInfo()->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP,
|
||
&rsp);
|
||
|
||
// 从栈上读取返回地址
|
||
uint64_t return_address;
|
||
if (this->GetPeInfo()->isX64) { // 64位系统
|
||
// 读取8字节的返回地址
|
||
uc_mem_read(uc, rsp, &return_address, 8);
|
||
|
||
// x64下,前4个参数通过寄存器传递,超过的部分通过栈传递
|
||
// int stack_params = (paramCount > 4) ? (paramCount - 4) : 0;
|
||
// 调整栈指针:每个参数8字节 + 返回地址8字节
|
||
// rsp += (stack_params * 8) + 8;
|
||
rsp += 8;
|
||
// 设置RIP为返回地址
|
||
uc_reg_write(uc, UC_X86_REG_RIP, &return_address);
|
||
} else { // 32位系统
|
||
// 读取4字节的返回地址
|
||
uint32_t return_address_32;
|
||
uc_mem_read(uc, rsp, &return_address_32, 4);
|
||
|
||
// x86下,所有参数都通过栈传递
|
||
// 调整栈指针:每个参数4字节 + 返回地址4字节
|
||
rsp += (paramCount * 4) + 4;
|
||
|
||
// 设置EIP为返回地址
|
||
uc_reg_write(uc, UC_X86_REG_EIP, &return_address_32);
|
||
}
|
||
|
||
// 更新栈指针,使用正确的寄存器
|
||
uc_reg_write(uc,
|
||
this->GetPeInfo()->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP,
|
||
&rsp);
|
||
return;
|
||
}
|
||
printf("ApiName: %s not found\n", ApiName.c_str());
|
||
uc_emu_stop(uc);
|
||
return;
|
||
}
|