add new API
This commit is contained in:
@@ -1450,71 +1450,81 @@ auto Api_LeaveCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
|
||||
printf("[*] LeaveCriticalSection: CS=0x%llx\n", lpCriticalSection);
|
||||
}
|
||||
|
||||
auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto GetStartupInfoHelper(void* sandbox, uc_engine* uc, uint64_t call_address, bool isWideChar) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpStartupInfo = 0;
|
||||
printf("[*] GetStartupInfoW start dump vmenv\n");
|
||||
// 获取参数
|
||||
// 获取 lpStartupInfo 参数 (A 和 W 版本通用)
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpStartupInfo
|
||||
// x64: 第一个参数在 RCX 寄存器
|
||||
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) {
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
STARTUPINFOW si = {0};
|
||||
else {
|
||||
// x86: 参数在栈上,返回地址之后
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uint32_t temp_startup_info = 0;
|
||||
uc_mem_read(uc, esp_address, &temp_startup_info, sizeof(uint32_t));
|
||||
lpStartupInfo = temp_startup_info;
|
||||
}
|
||||
if (lpStartupInfo == 0) {
|
||||
printf("[-] GetStartupInfo%c: lpStartupInfo is NULL. Aborting.\n", isWideChar ? 'W' : 'A');
|
||||
// 根据需要设置 LastError
|
||||
return;
|
||||
}
|
||||
uc_err err = UC_ERR_OK;
|
||||
size_t struct_size = 0;
|
||||
printf("[*] GetStartupInfo%c called. Populating STARTUPINFO%c at 0x%llx\n",
|
||||
isWideChar ? 'W' : 'A', isWideChar ? 'W' : 'A', lpStartupInfo);
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
if (isWideChar) {
|
||||
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));
|
||||
} else {
|
||||
STARTUPINFOW32 si = {0};
|
||||
si.cb = sizeof(STARTUPINFOW32);
|
||||
si.wShowWindow = SW_SHOWNORMAL; // 与你原有的 Api_GetStartupInfoW 保持一致
|
||||
// 其他字段保持为 nullptr/0
|
||||
struct_size = sizeof(STARTUPINFOW);
|
||||
err = uc_mem_write(uc, lpStartupInfo, &si, struct_size);
|
||||
}
|
||||
else {
|
||||
STARTUPINFOA si = { 0 }; // 标准 WinAPI STARTUPINFOA for x64
|
||||
si.cb = sizeof(STARTUPINFOA);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_SHOWNORMAL;
|
||||
si.lpDesktop = 0;
|
||||
si.lpTitle = 0;
|
||||
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 = 0;
|
||||
si.hStdInput = 0;
|
||||
si.hStdOutput = 0;
|
||||
si.hStdError = 0;
|
||||
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW32));
|
||||
// 其他字段保持为 nullptr/0
|
||||
struct_size = sizeof(STARTUPINFOA);
|
||||
err = uc_mem_write(uc, lpStartupInfo, &si, struct_size);
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] GetStartupInfoW: lpStartupInfo=0x%llx\n", lpStartupInfo);
|
||||
else {
|
||||
// x86 模式,使用 32 位结构体
|
||||
STARTUPINFOW32 si_32 = { 0 }; // 使用 STARTUPINFOW32 作为 32 位通用结构体模板
|
||||
si_32.cb = sizeof(STARTUPINFOW32); // 或 sizeof(STARTUPINFOA32) 如果你定义了它
|
||||
si_32.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si_32.wShowWindow = SW_SHOWNORMAL;
|
||||
// 其他字段保持为 0
|
||||
struct_size = sizeof(STARTUPINFOW32);
|
||||
err = uc_mem_write(uc, lpStartupInfo, &si_32, struct_size);
|
||||
}
|
||||
if (err != UC_ERR_OK) {
|
||||
printf("[-] GetStartupInfo%c: Failed to write STARTUPINFO%c to guest memory at 0x%llx, error: %s\n",
|
||||
isWideChar ? 'W' : 'A', isWideChar ? 'W' : 'A', lpStartupInfo, uc_strerror(err));
|
||||
// 根据需要设置 LastError
|
||||
}
|
||||
else {
|
||||
printf(" Populated %zu bytes.\n", struct_size);
|
||||
// 如果需要更详细的 dump,可以从模拟内存中读回并打印
|
||||
}
|
||||
// GetStartupInfoA/W 返回 void,所以不需要设置返回值寄存器
|
||||
}
|
||||
auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
GetStartupInfoHelper(sandbox, uc, address, true); // 调用通用辅助函数,并标记为宽字符版本
|
||||
}
|
||||
// 新增 GetStartupInfoA
|
||||
auto Api_GetStartupInfoA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
GetStartupInfoHelper(sandbox, uc, address, false); // 调用通用辅助函数,并标记为ANSI版本
|
||||
}
|
||||
|
||||
// 实现 GetStdHandle API
|
||||
@@ -2386,7 +2396,73 @@ auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&return_value);
|
||||
}
|
||||
|
||||
auto Api__initterm(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t table_start = 0;
|
||||
uint64_t table_end = 0;
|
||||
// 获取参数:函数表的起始地址和结束地址
|
||||
// _initterm 接收两个参数,与 _initterm_e 相同
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: 参数在RCX和RDX中
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &table_start);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &table_end);
|
||||
}
|
||||
else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 0x4; // 跳过返回地址
|
||||
uint32_t temp_start;
|
||||
uc_mem_read(uc, esp, &temp_start, sizeof(uint32_t));
|
||||
table_start = temp_start;
|
||||
esp += 0x4;
|
||||
uint32_t temp_end;
|
||||
uc_mem_read(uc, esp, &temp_end, sizeof(uint32_t));
|
||||
table_end = temp_end;
|
||||
}
|
||||
// 返回值,通常 _initterm 返回 void,但为保持与 _initterm_e 风格一致,
|
||||
// 我们也返回 int32_t,表示成功(0)。
|
||||
int32_t return_value = 0;
|
||||
// 遍历函数表并“调用”每个初始化函数
|
||||
printf("[*] _initterm: Initializing functions from 0x%llx to 0x%llx\n", table_start,
|
||||
table_end);
|
||||
// 只有当表的起始地址和结束地址有效且顺序正确时才进行处理
|
||||
if (table_start < table_end) {
|
||||
uint64_t current = table_start;
|
||||
uint64_t ptr_size = context->GetPeInfo()->isX64 ? 8 : 4; // 根据架构确定指针大小
|
||||
// 遍历函数表
|
||||
while (current < table_end) {
|
||||
uint64_t function_ptr = 0;
|
||||
// 读取当前表项中的函数指针
|
||||
uc_err err = uc_mem_read(uc, current, &function_ptr, ptr_size);
|
||||
if (err != UC_ERR_OK) {
|
||||
printf("[-] _initterm: Failed to read function pointer at 0x%llx, error: %s\n", current, uc_strerror(err));
|
||||
return_value = -1; // 模拟错误
|
||||
break;
|
||||
}
|
||||
// 非空函数指针才“调用”
|
||||
if (function_ptr != 0) {
|
||||
printf("[*] _initterm: Simulating call to initializer function at 0x%llx\n",
|
||||
function_ptr);
|
||||
// 在沙箱环境中,通常我们不会真正地跳转到并执行这些初始化函数,
|
||||
// 而是记录它们的调用。
|
||||
// 如果需要更深度的模拟,可以在这里使用 uc_emu_start
|
||||
// 来模拟执行这些函数,然后跳回当前位置。
|
||||
// 但对于多数初始化例程,简单的记录就足够了。
|
||||
// 例如:
|
||||
// uc_emu_start(uc, function_ptr, function_ptr + some_size, 0, 0);
|
||||
// 或
|
||||
// context->EmulateApi(uc, function_ptr, some_return_address, "CustomInitializer");
|
||||
}
|
||||
// 移动到下一个表项
|
||||
current += ptr_size;
|
||||
}
|
||||
}
|
||||
// 设置返回值
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&return_value);
|
||||
}
|
||||
auto Api__initterm_e(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t table_start = 0;
|
||||
|
||||
Reference in New Issue
Block a user