diff --git a/ai_anti_malware/ai_anti_malware.cpp b/ai_anti_malware/ai_anti_malware.cpp index 1f7e897..67621e7 100644 --- a/ai_anti_malware/ai_anti_malware.cpp +++ b/ai_anti_malware/ai_anti_malware.cpp @@ -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; } diff --git a/ai_anti_malware/head.h b/ai_anti_malware/head.h index 6fb874e..54a3b50 100644 --- a/ai_anti_malware/head.h +++ b/ai_anti_malware/head.h @@ -1,5 +1,5 @@ #pragma once -#define LOG_LEVEL 0 +#define LOG_LEVEL 4 #define _CRT_SECURE_NO_WARNINGS #include diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 720e88a..926e0f7 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -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; diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index 28c6c9e..2e51f42 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -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); + // 调用真实的 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, diff --git a/ai_anti_malware/sandbox_api_stl.cpp b/ai_anti_malware/sandbox_api_stl.cpp index 4810ee9..12508f6 100644 --- a/ai_anti_malware/sandbox_api_stl.cpp +++ b/ai_anti_malware/sandbox_api_stl.cpp @@ -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); 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); + 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); uint64_t table_start = 0;