add new API
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define LOG_LEVEL 0
|
||||
#define LOG_LEVEL 4
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <iostream>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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