add new API

This commit is contained in:
huoji
2025-05-22 17:37:52 +08:00
parent fd9cb016e1
commit db8082d04a
5 changed files with 167 additions and 59 deletions

View File

@@ -383,5 +383,13 @@ int main(int argc, char* argv[]) {
printf("result: %d \n", result);
//DetectMalwareInDirectory(filePath);
*/
auto peInfo = getPeInfo("x");
if (peInfo == nullptr) {
return 0;
}
Sandbox se;
se.InitEnv(peInfo);
se.Run(0x7880);
//se.Run();
return 0;
}

View File

@@ -1,5 +1,5 @@
#pragma once
#define LOG_LEVEL 0
#define LOG_LEVEL 4
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>

View File

@@ -405,6 +405,8 @@ auto Api_LeaveCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
-> void;
auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
-> void;
auto Api_GetStartupInfoA(void* sandbox, uc_engine* uc, uint64_t address)
-> void;
auto Api_GetStdHandle(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_GetFileType(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_HeapCreate(void* sandbox, uc_engine* uc, uint64_t address) -> void;
@@ -471,6 +473,7 @@ auto Api_TlsFree(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_FlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api__initterm_e(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api__initterm(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_GetStringTypeW(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address) -> void;

View File

@@ -858,7 +858,19 @@ auto Api_AdjustTokenPrivileges(void* sandbox, uc_engine* uc, uint64_t address)
context->GetTeb32()->LastErrorValue = error;
}
}
auto Api_GetTickCount(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
// 调用真实的 Windows API 获取当前系统启动以来的毫秒数
DWORD tick_count = GetTickCount();
// 将结果写入模拟器的返回值寄存器
// GetTickCount 返回的是 DWORD (32位),因此无论 x64 还是 x86都写入 EAX
// 在 x64 架构中EAX 是 RAX 的低 32 位
uint32_t result = tick_count;
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
printf("[*] GetTickCount called, returning 0x%x (%u)\n", tick_count, tick_count);
}
auto Sandbox::InitApiHooks() -> void {
auto FakeApi_GetSystemTimeAsFileTime =
_fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1};
@@ -903,6 +915,8 @@ auto Sandbox::InitApiHooks() -> void {
_fakeApi{.func = Api_LeaveCriticalSection, .paramCount = 1};
auto FakeApi_GetStartupInfoW =
_fakeApi{.func = Api_GetStartupInfoW, .paramCount = 1};
auto FakeApi_GetStartupInfoA =
_fakeApi{ .func = Api_GetStartupInfoA, .paramCount = 1 };
auto FakeApi_GetStdHandle =
_fakeApi{.func = Api_GetStdHandle, .paramCount = 1};
auto FakeApi_GetFileType =
@@ -1038,13 +1052,15 @@ auto Sandbox::InitApiHooks() -> void {
// *** 新增 LCMapStringEx ***
auto FakeApi_LCMapStringEx =
_fakeApi{.func = Api_LCMapStringEx, .paramCount = 9}; // LCMapStringEx 有 9 个参数
auto FakeApi_GetTickCount = _fakeApi{ .func = Api_GetTickCount, .paramCount = 0 }; // !!! 新增行 !!!
// 添加文件操作相关API
auto FakeApi_CreateFileW = _fakeApi{.func = Api_CreateFileW, .paramCount = 7};
auto FakeApi_ReadFileA = _fakeApi{.func = Api_ReadFileA, .paramCount = 5};
auto FakeApi_ReadFileW = _fakeApi{.func = Api_ReadFileW, .paramCount = 5};
auto FakeApi_CloseFile = _fakeApi{.func = Api_CloseFile, .paramCount = 1};
auto FakeApi__initterm =
_fakeApi{ .func = Api__initterm, .paramCount = 2 }; // 新增行
api_map = {
{"GetSystemTimeAsFileTime",
std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)},
@@ -1082,6 +1098,8 @@ auto Sandbox::InitApiHooks() -> void {
std::make_shared<_fakeApi>(FakeApi_LeaveCriticalSection)},
{"GetStartupInfoW",
std::make_shared<_fakeApi>(FakeApi_GetStartupInfoW)},
{"GetStartupInfoA",
std::make_shared<_fakeApi>(FakeApi_GetStartupInfoA)},
{"GetStdHandle", std::make_shared<_fakeApi>(FakeApi_GetStdHandle)},
{"GetFileType", std::make_shared<_fakeApi>(FakeApi_GetFileType)},
{"GetCommandLineA",
@@ -1176,6 +1194,7 @@ auto Sandbox::InitApiHooks() -> void {
{"TlsFree", std::make_shared<_fakeApi>(FakeApi_TlsFree)},
{"FlsAlloc", std::make_shared<_fakeApi>(FakeApi_FlsAlloc)},
{"FlsGetValue", std::make_shared<_fakeApi>(FakeApi_FlsGetValue)},
{"_initterm", std::make_shared<_fakeApi>(FakeApi__initterm) }, // 新增行
{"_initterm_e", std::make_shared<_fakeApi>(FakeApi__initterm_e)},
{"GetStringTypeW", std::make_shared<_fakeApi>(FakeApi_GetStringTypeW)},
{"LCMapStringW", std::make_shared<_fakeApi>(FakeApi_LCMapStringW)},
@@ -1194,6 +1213,8 @@ auto Sandbox::InitApiHooks() -> void {
{"ReadFileA", std::make_shared<_fakeApi>(FakeApi_ReadFileA)},
{"ReadFileW", std::make_shared<_fakeApi>(FakeApi_ReadFileW)},
{"CloseFile", std::make_shared<_fakeApi>(FakeApi_CloseFile)},
{ "GetTickCount", std::make_shared<_fakeApi>(FakeApi_GetTickCount) }, // !!! 新增行 !!!
};
}
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,

View File

@@ -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;