diff --git a/ai_anti_malware/ai_anti_malware.cpp b/ai_anti_malware/ai_anti_malware.cpp index 5b260bb..f525406 100644 --- a/ai_anti_malware/ai_anti_malware.cpp +++ b/ai_anti_malware/ai_anti_malware.cpp @@ -313,29 +313,26 @@ auto doMalwareScan(int argc, char* argv[]) -> void { } int doSandbox(int argc, char* argv[]) { + if (argc < 3) { + std::cout << "用法: " << argv[0] << " <文件路径> <地址>" << std::endl; + return; + } - //if (argc < 3) { - // std::cout << "用法: " << argv[0] << " <文件路径> <地址>" << std::endl; - // return; - //} - //std::string filePath = argv[1]; - - std::string filePath = "Z:\\mso.dll"; - + std::string filePath = argv[1]; auto peInfo = getPeInfo(filePath); if (peInfo == nullptr) { return 0; } Sandbox se; se.InitEnv(peInfo); - se.Run(0x180003980); + // se.Run(0x180003980); return 0; } int main(int argc, char* argv[]) { // doMl(argc, argv); // doPredict(argc, argv); - //doMalwareScan(argc, argv); - doSandbox(argc, argv); + doMalwareScan(argc, argv); + // doSandbox(argc, argv); return 0; } diff --git a/ai_anti_malware/sandbox.h b/ai_anti_malware/sandbox.h index 3dc5941..0d40d4d 100644 --- a/ai_anti_malware/sandbox.h +++ b/ai_anti_malware/sandbox.h @@ -408,6 +408,7 @@ auto Api_FlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_CreateFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_WriteFile(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_CreateProcessA(void* sandbox, uc_engine* uc, uint64_t address) -> void; +auto Api_CreateProcessW(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_GetCurrentProcess(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_GetCurrentThread(void* sandbox, uc_engine* uc, uint64_t address) diff --git a/ai_anti_malware/sandbox_api_emu.cpp b/ai_anti_malware/sandbox_api_emu.cpp index 0e95ac6..c39e836 100644 --- a/ai_anti_malware/sandbox_api_emu.cpp +++ b/ai_anti_malware/sandbox_api_emu.cpp @@ -659,6 +659,256 @@ auto Api_Sleep(void* sandbox, uc_engine* uc, uint64_t address) -> void { printf("Sleep API called with %u milliseconds\n", milliseconds); } +auto Api_OpenThreadToken(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint64_t ThreadHandle = 0; + uint64_t DesiredAccess = 0; + uint64_t OpenAsSelf = 0; + uint64_t TokenHandle = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = ThreadHandle, rdx = DesiredAccess, r8 = OpenAsSelf, r9 = + // TokenHandle + uc_reg_read(uc, UC_X86_REG_RCX, &ThreadHandle); + uc_reg_read(uc, UC_X86_REG_RDX, &DesiredAccess); + uint64_t temp_open_as_self; + uc_reg_read(uc, UC_X86_REG_R8, &temp_open_as_self); + OpenAsSelf = static_cast(temp_open_as_self); + uc_reg_read(uc, UC_X86_REG_R9, &TokenHandle); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + + uint32_t temp_handle; + uc_mem_read(uc, esp_address, &temp_handle, sizeof(uint32_t)); + ThreadHandle = temp_handle; + esp_address += 0x4; + + uc_mem_read(uc, esp_address, &DesiredAccess, sizeof(uint32_t)); + esp_address += 0x4; + + uc_mem_read(uc, esp_address, &OpenAsSelf, sizeof(uint32_t)); + esp_address += 0x4; + + uint32_t temp_token_handle; + uc_mem_read(uc, esp_address, &temp_token_handle, sizeof(uint32_t)); + TokenHandle = temp_token_handle; + } + + // 创建一个模拟的令牌句柄 + uint64_t fake_token_handle = 0x1234; // 使用一个假的令牌句柄 + + // 将令牌句柄写入输出参数 + if (TokenHandle != 0) { + if (context->GetPeInfo()->isX64) { + uc_mem_write(uc, TokenHandle, &fake_token_handle, sizeof(uint64_t)); + } else { + uint32_t token_handle_32 = static_cast(fake_token_handle); + uc_mem_write(uc, TokenHandle, &token_handle_32, sizeof(uint32_t)); + } + } + + printf( + "[*] OpenThreadToken: ThreadHandle=0x%llx, DesiredAccess=0x%x, " + "OpenAsSelf=%d, TokenHandle=0x%llx\n", + ThreadHandle, DesiredAccess, OpenAsSelf, fake_token_handle); + + // 设置返回值为TRUE + uint64_t result = 1; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} +auto Api_LookupPrivilegeValueA(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint64_t lpSystemName = 0; + uint64_t lpName = 0; + uint64_t lpLuid = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + uc_reg_read(uc, UC_X86_REG_RCX, &lpSystemName); + uc_reg_read(uc, UC_X86_REG_RDX, &lpName); + uc_reg_read(uc, UC_X86_REG_R8, &lpLuid); + } else { + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; + + uint32_t temp_system_name, temp_name, temp_luid; + uc_mem_read(uc, esp_address, &temp_system_name, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &temp_name, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x8, &temp_luid, sizeof(uint32_t)); + + lpSystemName = temp_system_name; + lpName = temp_name; + lpLuid = temp_luid; + } + + // 读取权限名称 + char privName[256] = {0}; + if (lpName != 0) { + size_t i = 0; + do { + uint8_t byte; + uc_mem_read(uc, lpName + i, &byte, 1); + privName[i] = byte; + i++; + } while (privName[i - 1] != 0 && i < sizeof(privName)); + } + + // 模拟LUID结构 + LUID luid = {0}; + if (strcmp(privName, "SeDebugPrivilege") == 0) { + luid.LowPart = 20; // SeDebugPrivilege的典型LUID值 + luid.HighPart = 0; + } + + // 写入LUID到输出参数 + if (lpLuid != 0) { + uc_mem_write(uc, lpLuid, &luid, sizeof(LUID)); + } + + printf("[*] LookupPrivilegeValueA: SystemName=%s, Name=%s\n", + lpSystemName ? "Local" : "NULL", privName); + + // 返回TRUE + uint64_t result = 1; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} + +auto Api_AdjustTokenPrivileges(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint64_t TokenHandle = 0; + uint64_t DisableAllPrivileges = 0; + uint64_t NewState = 0; + uint32_t BufferLength = 0; + uint64_t PreviousState = 0; + uint64_t ReturnLength = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + uc_reg_read(uc, UC_X86_REG_RCX, &TokenHandle); + uc_reg_read(uc, UC_X86_REG_RDX, &DisableAllPrivileges); + uc_reg_read(uc, UC_X86_REG_R8, &NewState); + uint64_t temp_length; + uc_reg_read(uc, UC_X86_REG_R9, &temp_length); + BufferLength = static_cast(temp_length); + // 从栈上获取剩余参数 + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uc_mem_read(uc, rsp + 0x28, &PreviousState, sizeof(uint64_t)); + uc_mem_read(uc, rsp + 0x30, &ReturnLength, sizeof(uint64_t)); + } else { + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; + + uint32_t temp_values[6]; + for (int i = 0; i < 6; i++) { + uc_mem_read(uc, esp_address + (i * 4), &temp_values[i], + sizeof(uint32_t)); + } + + TokenHandle = temp_values[0]; + DisableAllPrivileges = temp_values[1]; + NewState = temp_values[2]; + BufferLength = temp_values[3]; + PreviousState = temp_values[4]; + ReturnLength = temp_values[5]; + } + + printf("[*] AdjustTokenPrivileges: TokenHandle=0x%llx, DisableAll=%d\n", + TokenHandle, (int)DisableAllPrivileges); + + // 返回TRUE + uint64_t result = 1; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + + // 设置ERROR_NOT_ALL_ASSIGNED + DWORD error = ERROR_NOT_ALL_ASSIGNED; // 1300 + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } +} +auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint64_t lpPathName = 0; + uint64_t lpSecurityAttributes = 0; + + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = lpPathName, rdx = lpSecurityAttributes + uc_reg_read(uc, UC_X86_REG_RCX, &lpPathName); + uc_reg_read(uc, UC_X86_REG_RDX, &lpSecurityAttributes); + } else { + // x86: 从栈上读取参数 + uint32_t esp_address = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp_address); + esp_address += 0x4; // 跳过返回地址 + + uint32_t temp_path_name, temp_security_attr; + uc_mem_read(uc, esp_address, &temp_path_name, sizeof(uint32_t)); + uc_mem_read(uc, esp_address + 0x4, &temp_security_attr, + sizeof(uint32_t)); + + lpPathName = temp_path_name; + lpSecurityAttributes = temp_security_attr; + } + + // 读取目录路径 + wchar_t pathBuffer[MAX_PATH] = {0}; + if (lpPathName != 0) { + size_t i = 0; + do { + uint16_t wchar; + uc_mem_read(uc, lpPathName + (i * 2), &wchar, 2); + pathBuffer[i] = wchar; + i++; + } while (pathBuffer[i - 1] != 0 && i < MAX_PATH); + } + + // 将宽字符转换为常规字符串用于日志输出 + std::wstring widePath(pathBuffer); + std::string path(widePath.begin(), widePath.end()); + + // 在实际的实现中,可能需要检查目录是否已存在 + // 这里简单地返回成功,不实际创建目录 + bool success = true; + + // 输出日志 + printf("[*] CreateDirectoryW: Path=%s, Result=%s\n", path.c_str(), + success ? "TRUE" : "FALSE"); + + // 设置返回值 + uint64_t result = success ? 1 : 0; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); + + // 如果失败,可以设置LastError + if (!success) { + DWORD error = ERROR_PATH_NOT_FOUND; // 或其他适当的错误代码 + if (context->GetPeInfo()->isX64) { + context->GetTeb64()->LastErrorValue = error; + } else { + context->GetTeb32()->LastErrorValue = error; + } + } +} auto Sandbox::InitApiHooks() -> void { auto FakeApi_GetSystemTimeAsFileTime = _fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1}; @@ -774,6 +1024,8 @@ auto Sandbox::InitApiHooks() -> void { auto FakeApi_CreatePipe = _fakeApi{.func = Api_CreatePipe, .paramCount = 4}; auto FakeApi_CreateProcessA = _fakeApi{.func = Api_CreateProcessA, .paramCount = 10}; + auto FakeApi_CreateProcessW = + _fakeApi{.func = Api_CreateProcessW, .paramCount = 10}; auto FakeApi_ReadFile = _fakeApi{.func = Api_ReadFile, .paramCount = 5}; auto FakeApi_WlanOpenHandle = _fakeApi{.func = Api_WlanOpenHandle, .paramCount = 4}; @@ -800,7 +1052,16 @@ auto Sandbox::InitApiHooks() -> void { _fakeApi{.func = Api_FwpmFilterAdd0, .paramCount = 4}; auto FakeApi_FwpmEngineClose0 = _fakeApi{.func = Api_FwpmEngineClose0, .paramCount = 1}; - + auto FakeApi_OpenThreadToken = + _fakeApi{.func = Api_OpenThreadToken, .paramCount = 4}; + auto FakeApi_LookupPrivilegeValueA = + _fakeApi{.func = Api_LookupPrivilegeValueA, .paramCount = 3}; + auto FakeApi_AdjustTokenPrivileges = + _fakeApi{.func = Api_AdjustTokenPrivileges, .paramCount = 6}; + auto FakeApi_CreateDirectoryW = + _fakeApi{.func = Api_CreateDirectoryW, .paramCount = 2}; + auto FakeApi_URLDownloadToFileW = + _fakeApi{.func = Api_URLDownloadToFileW, .paramCount = 5}; api_map = { {"GetSystemTimeAsFileTime", std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)}, @@ -896,6 +1157,7 @@ auto Sandbox::InitApiHooks() -> void { {"FlsSetValue", std::make_shared<_fakeApi>(FakeApi_FlsSetValue)}, {"CreatePipe", std::make_shared<_fakeApi>(FakeApi_CreatePipe)}, {"CreateProcessA", std::make_shared<_fakeApi>(FakeApi_CreateProcessA)}, + {"CreateProcessW", std::make_shared<_fakeApi>(FakeApi_CreateProcessW)}, {"ReadFile", std::make_shared<_fakeApi>(FakeApi_ReadFile)}, {"WlanOpenHandle", std::make_shared<_fakeApi>(FakeApi_WlanOpenHandle)}, {"WlanEnumInterfaces", @@ -911,6 +1173,8 @@ auto Sandbox::InitApiHooks() -> void { std::make_shared<_fakeApi>(FakeApi_OpenProcessToken)}, {"GetTokenInformation", std::make_shared<_fakeApi>(FakeApi_GetTokenInformation)}, + {"OpenThreadToken", + std::make_shared<_fakeApi>(FakeApi_OpenThreadToken)}, // 添加WFP相关API映射 {"FwpmEngineOpen0", std::make_shared<_fakeApi>(FakeApi_FwpmEngineOpen0)}, @@ -919,6 +1183,18 @@ auto Sandbox::InitApiHooks() -> void { {"FwpmFilterAdd0", std::make_shared<_fakeApi>(FakeApi_FwpmFilterAdd0)}, {"FwpmEngineClose0", std::make_shared<_fakeApi>(FakeApi_FwpmEngineClose0)}, + {"LookupPrivilegeValueA", + std::make_shared<_fakeApi>(FakeApi_LookupPrivilegeValueA)}, + {"AdjustTokenPrivileges", + std::make_shared<_fakeApi>(FakeApi_AdjustTokenPrivileges)}, + {"LookupPrivilegeValueA", + std::make_shared<_fakeApi>(FakeApi_LookupPrivilegeValueA)}, + {"AdjustTokenPrivileges", + std::make_shared<_fakeApi>(FakeApi_AdjustTokenPrivileges)}, + {"CreateDirectoryW", + std::make_shared<_fakeApi>(FakeApi_CreateDirectoryW)}, + {"URLDownloadToFileW", + std::make_shared<_fakeApi>(FakeApi_URLDownloadToFileW)}, }; } auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, @@ -974,4 +1250,4 @@ auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip, printf("ApiName: %s not found\n", ApiName.c_str()); uc_emu_stop(uc); return; -} +} \ No newline at end of file diff --git a/ai_anti_malware/sandbox_api_process.cpp b/ai_anti_malware/sandbox_api_process.cpp index 11a3487..93e2aa8 100644 --- a/ai_anti_malware/sandbox_api_process.cpp +++ b/ai_anti_malware/sandbox_api_process.cpp @@ -474,6 +474,211 @@ auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address) } } +// 内部函数,用于处理CreateProcessA和CreateProcessW的共同逻辑 +auto CreateProcessInternal(void* sandbox, uc_engine* uc, + uint64_t lpApplicationName, uint64_t lpCommandLine, + uint64_t lpProcessInformation, + uint64_t lpStartupInfo, bool isWideChar) -> bool { + auto* context = static_cast(sandbox); + std::string applicationName; + std::wstring wApplicationName; + std::string commandLine; + std::wstring wCommandLine; + + // 读取应用程序名称 + if (lpApplicationName != 0) { + if (isWideChar) { + // 读取宽字符应用程序名称 + wchar_t buffer[MAX_PATH] = {0}; + size_t i = 0; + bool success = true; + + do { + wchar_t ch; + uc_err err = + uc_mem_read(uc, lpApplicationName + (i * 2), &ch, 2); + if (err != UC_ERR_OK) { + printf( + "[!] Error reading wide application name at address " + "0x%llx: %u\n", + lpApplicationName + (i * 2), err); + success = false; + break; + } + if (ch == 0) break; + buffer[i] = ch; + i++; + } while (i < MAX_PATH - 1); + + // 确保字符串以 NULL 结尾 + buffer[i] = 0; + + if (success) { + wApplicationName = std::wstring(buffer); + // 转换为ANSI以便于日志记录 + std::string ansiAppName(wApplicationName.begin(), + wApplicationName.end()); + printf("[*] Read Wide ApplicationName: %s (Length: %zu)\n", + ansiAppName.c_str(), wApplicationName.length()); + } + } else { + // 读取ANSI应用程序名称 + char buffer[MAX_PATH] = {0}; + size_t i = 0; + bool success = true; + + do { + uint8_t byte; + uc_err err = uc_mem_read(uc, lpApplicationName + i, &byte, 1); + if (err != UC_ERR_OK) { + printf( + "[!] Error reading application name at address 0x%llx: " + "%u\n", + lpApplicationName + i, err); + success = false; + break; + } + if (byte == 0) break; + buffer[i] = byte; + i++; + } while (i < MAX_PATH - 1); + + // 确保字符串以 NULL 结尾 + buffer[i] = 0; + + if (success) { + applicationName = std::string(buffer); + printf("[*] Read ANSI ApplicationName: %s (Length: %zu)\n", + buffer, applicationName.length()); + // 转换为宽字符 + wApplicationName = std::wstring(applicationName.begin(), + applicationName.end()); + } + } + } + + // 读取命令行 + if (lpCommandLine != 0) { + if (isWideChar) { + // 读取宽字符命令行 + wchar_t buffer[MAX_PATH] = {0}; + size_t i = 0; + bool success = true; + + do { + wchar_t ch; + uc_err err = uc_mem_read(uc, lpCommandLine + (i * 2), &ch, 2); + if (err != UC_ERR_OK) { + printf( + "[!] Error reading wide command line at address " + "0x%llx: %u\n", + lpCommandLine + (i * 2), err); + success = false; + break; + } + if (ch == 0) break; + buffer[i] = ch; + i++; + } while (i < MAX_PATH - 1); + + // 确保字符串以 NULL 结尾 + buffer[i] = 0; + + if (success) { + wCommandLine = std::wstring(buffer); + // 转换为ANSI以便于日志记录 + std::string ansiCmdLine(wCommandLine.begin(), + wCommandLine.end()); + printf("[*] Read Wide CommandLine: %s (Length: %zu)\n", + ansiCmdLine.c_str(), wCommandLine.length()); + } + } else { + // 读取ANSI命令行 + char buffer[MAX_PATH] = {0}; + size_t i = 0; + bool success = true; + + do { + uint8_t byte; + uc_err err = uc_mem_read(uc, lpCommandLine + i, &byte, 1); + if (err != UC_ERR_OK) { + printf( + "[!] Error reading command line at address 0x%llx: " + "%u\n", + lpCommandLine + i, err); + success = false; + break; + } + if (byte == 0) break; + buffer[i] = byte; + i++; + } while (i < MAX_PATH - 1); + + // 确保字符串以 NULL 结尾 + buffer[i] = 0; + + if (success) { + commandLine = std::string(buffer); + printf("[*] Read ANSI CommandLine: %s (Length: %zu)\n", buffer, + commandLine.length()); + // 转换为宽字符 + wCommandLine = + std::wstring(commandLine.begin(), commandLine.end()); + } + } + } + + // 记录调用信息 + if (isWideChar) { + std::string ansiAppName(wApplicationName.begin(), + wApplicationName.end()); + std::string ansiCmdLine(wCommandLine.begin(), wCommandLine.end()); + printf("[*] CreateProcessW: ApplicationName=%s, CommandLine=%s\n", + ansiAppName.empty() ? "(null)" : ansiAppName.c_str(), + ansiCmdLine.empty() ? "(null)" : ansiCmdLine.c_str()); + } else { + printf("[*] CreateProcessA: ApplicationName=%s, CommandLine=%s\n", + applicationName.empty() ? "(null)" : applicationName.c_str(), + commandLine.empty() ? "(null)" : commandLine.c_str()); + } + + // 模拟创建进程,设置进程和线程ID + DWORD processId = 0x1234; + DWORD threadId = 0x5678; + HANDLE hProcess = (HANDLE)0x1340; + HANDLE hThread = (HANDLE)0x1341; + + // 写入进程信息 + if (lpProcessInformation != 0) { + if (context->GetPeInfo()->isX64) { + struct PROCESS_INFORMATION64 { + HANDLE hProcess; + HANDLE hThread; + DWORD dwProcessId; + DWORD dwThreadId; + } pi; + pi.hProcess = (HANDLE)hProcess; + pi.hThread = (HANDLE)hThread; + pi.dwProcessId = processId; + pi.dwThreadId = threadId; + uc_mem_write(uc, lpProcessInformation, &pi, sizeof(pi)); + printf("[*] Wrote process info (x64) to 0x%llx\n", + lpProcessInformation); + } else { + PROCESS_INFORMATION pi; + pi.hProcess = hProcess; + pi.hThread = hThread; + pi.dwProcessId = processId; + pi.dwThreadId = threadId; + uc_mem_write(uc, lpProcessInformation, &pi, sizeof(pi)); + printf("[*] Wrote process info (x86) to 0x%llx\n", + lpProcessInformation); + } + } + + return true; +} + auto Api_CreateProcessA(void* sandbox, uc_engine* uc, uint64_t address) -> void { auto context = static_cast(sandbox); @@ -521,109 +726,73 @@ auto Api_CreateProcessA(void* sandbox, uc_engine* uc, uint64_t address) esp, temp_app_name, temp_cmd_line); } - // 读取应用程序名称 - std::string applicationName; - if (lpApplicationName != 0) { - // 增加大小检测以避免内存溢出 - char buffer[MAX_PATH] = {0}; - size_t i = 0; - bool success = true; + // 调用内部函数处理共同逻辑 + bool success = + CreateProcessInternal(sandbox, uc, lpApplicationName, lpCommandLine, + lpProcessInformation, lpStartupInfo, false); - do { - uint8_t byte; - uc_err err = uc_mem_read(uc, lpApplicationName + i, &byte, 1); - if (err != UC_ERR_OK) { - printf( - "[!] Error reading application name at address 0x%llx: " - "%u\n", - lpApplicationName + i, err); - success = false; - break; - } - buffer[i] = byte; - i++; - } while (buffer[i - 1] != 0 && i < MAX_PATH - 1); + // 返回结果 + uint64_t result = success ? 1 : 0; + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &result); +} - // 确保字符串以 NULL 结尾 - buffer[i] = 0; +// CreateProcessW的实现 +auto Api_CreateProcessW(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + uint64_t lpApplicationName = 0; + uint64_t lpCommandLine = 0; + uint64_t lpProcessInformation = 0; + uint64_t lpStartupInfo = 0; - if (success) { - applicationName = std::string(buffer); - printf("[*] Read ApplicationName: %s (Length: %zu)\n", buffer, - applicationName.length()); - } + // 获取参数 + if (context->GetPeInfo()->isX64) { + // x64: rcx = lpApplicationName, rdx = lpCommandLine + uc_reg_read(uc, UC_X86_REG_RCX, &lpApplicationName); + uc_reg_read(uc, UC_X86_REG_RDX, &lpCommandLine); + // 从栈上获取 PROCESS_INFORMATION 和 STARTUPINFO + uint64_t rsp; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + rsp += 0x28; // 跳过前4个参数的影子空间 + uc_mem_read(uc, rsp + 0x20, &lpProcessInformation, sizeof(uint64_t)); + uc_mem_read(uc, rsp + 0x18, &lpStartupInfo, sizeof(uint64_t)); + + printf( + "[*] CreateProcessW Debug (x64): AppNameAddr=0x%llx, " + "CmdLineAddr=0x%llx\n", + lpApplicationName, lpCommandLine); + } else { + // x86: 从栈上读取参数 + uint32_t esp; + uc_reg_read(uc, UC_X86_REG_ESP, &esp); + esp += 0x4; // 跳过返回地址 + uint32_t temp_app_name, temp_cmd_line, temp_proc_info, + temp_startup_info; + uc_mem_read(uc, esp, &temp_app_name, sizeof(uint32_t)); + uc_mem_read(uc, esp + 0x4, &temp_cmd_line, sizeof(uint32_t)); + // 修正x86下的参数读取偏移,使用实际结构的偏移量 + uc_mem_read(uc, esp + 0x24, &temp_proc_info, sizeof(uint32_t)); + uc_mem_read(uc, esp + 0x1C, &temp_startup_info, sizeof(uint32_t)); + lpApplicationName = temp_app_name; + lpCommandLine = temp_cmd_line; + lpProcessInformation = temp_proc_info; + lpStartupInfo = temp_startup_info; + + printf( + "[*] CreateProcessW Debug (x86): ESP=0x%x, AppNameAddr=0x%x, " + "CmdLineAddr=0x%x\n", + esp, temp_app_name, temp_cmd_line); } - // 读取命令行 - std::string commandLine; - if (lpCommandLine != 0) { - char buffer[MAX_PATH] = {0}; - size_t i = 0; - bool success = true; + // 调用内部函数处理共同逻辑 + bool success = + CreateProcessInternal(sandbox, uc, lpApplicationName, lpCommandLine, + lpProcessInformation, lpStartupInfo, true); - do { - uint8_t byte; - uc_err err = uc_mem_read(uc, lpCommandLine + i, &byte, 1); - if (err != UC_ERR_OK) { - printf("[!] Error reading command line at address 0x%llx: %u\n", - lpCommandLine + i, err); - success = false; - break; - } - buffer[i] = byte; - i++; - } while (buffer[i - 1] != 0 && i < MAX_PATH - 1); - - // 确保字符串以 NULL 结尾 - buffer[i] = 0; - - if (success) { - commandLine = std::string(buffer); - printf("[*] Read CommandLine: %s (Length: %zu)\n", buffer, - commandLine.length()); - } - } - - printf("[*] CreateProcessA: ApplicationName=%s, CommandLine=%s\n", - applicationName.empty() ? "(null)" : applicationName.c_str(), - commandLine.empty() ? "(null)" : commandLine.c_str()); - - // 模拟创建进程,设置进程和线程ID - DWORD processId = 0x1234; - DWORD threadId = 0x5678; - HANDLE hProcess = (HANDLE)0x1340; - HANDLE hThread = (HANDLE)0x1341; - - // 写入进程信息 - if (lpProcessInformation != 0) { - if (context->GetPeInfo()->isX64) { - struct PROCESS_INFORMATION64 { - HANDLE hProcess; - HANDLE hThread; - DWORD dwProcessId; - DWORD dwThreadId; - } pi; - pi.hProcess = (HANDLE)hProcess; - pi.hThread = (HANDLE)hThread; - pi.dwProcessId = processId; - pi.dwThreadId = threadId; - uc_mem_write(uc, lpProcessInformation, &pi, sizeof(pi)); - printf("[*] Wrote process info (x64) to 0x%llx\n", - lpProcessInformation); - } else { - PROCESS_INFORMATION pi; - pi.hProcess = hProcess; - pi.hThread = hThread; - pi.dwProcessId = processId; - pi.dwThreadId = threadId; - uc_mem_write(uc, lpProcessInformation, &pi, sizeof(pi)); - printf("[*] Wrote process info (x86) to 0x%llx\n", - lpProcessInformation); - } - } - - // 返回成功 - uint64_t result = 1; + // 返回结果 + uint64_t result = success ? 1 : 0; uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); diff --git a/ai_anti_malware/sandbox_api_stl.cpp b/ai_anti_malware/sandbox_api_stl.cpp index 4e9c83a..07bfad0 100644 --- a/ai_anti_malware/sandbox_api_stl.cpp +++ b/ai_anti_malware/sandbox_api_stl.cpp @@ -1726,16 +1726,6 @@ auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address) 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, @@ -1783,9 +1773,9 @@ auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address) } srcBuffer.push_back(ch); len++; - } while (ch != 0 && len < MAX_PATH); // 添加长度限制防止无限循环 + } while (ch != 0 && len < 2 * 1024); // 添加长度限制防止无限循环 - if (len >= MAX_PATH) { + if (len >= 2 * 1024) { // 设置错误码 DWORD error = ERROR_INSUFFICIENT_BUFFER; if (context->GetPeInfo()->isX64) { @@ -1922,7 +1912,7 @@ auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address) "InputLen=%d, Output=%p, OutputLen=%d, Result=%d\n", CodePage, dwFlags, (void*)lpMultiByteStr, cbMultiByte, (void*)lpWideCharStr, cchWideChar, result); - + printf("MultiByteToWideChar pre cover string: %s\n", srcBuffer.data()); uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &result); diff --git a/ai_anti_malware/sandbox_api_winhttp.cpp b/ai_anti_malware/sandbox_api_winhttp.cpp index 78f935f..7c8cf14 100644 --- a/ai_anti_malware/sandbox_api_winhttp.cpp +++ b/ai_anti_malware/sandbox_api_winhttp.cpp @@ -347,4 +347,100 @@ auto Api_InternetReadFile(void* sandbox, uc_engine* uc, uint64_t address) uc_reg_write(uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, &returnValue); +} + +auto Api_URLDownloadToFileW(void* sandbox, uc_engine* uc, uint64_t address) + -> void { + auto context = static_cast(sandbox); + + // 获取参数 + uint64_t pCaller = 0; // LPUNKNOWN pCaller + uint64_t szURL = 0; // LPCWSTR szURL + uint64_t szFileName = 0; // LPCWSTR szFileName + uint64_t dwReserved = 0; // DWORD dwReserved + uint64_t lpfnCB = 0; // LPBINDSTATUSCALLBACK lpfnCB + + // 根据x86或x64架构读取参数 + if (context->GetPeInfo()->isX64) { + uc_reg_read(uc, UC_X86_REG_RCX, &pCaller); + uc_reg_read(uc, UC_X86_REG_RDX, &szURL); + uc_reg_read(uc, UC_X86_REG_R8, &szFileName); + uc_reg_read(uc, UC_X86_REG_R9, &dwReserved); + + uint64_t rsp = 0; + uc_reg_read(uc, UC_X86_REG_RSP, &rsp); + uc_mem_read(uc, rsp + 0x28, &lpfnCB, sizeof(lpfnCB)); + } else { + uint32_t esp = 0; + uc_reg_read(uc, UC_X86_REG_ESP, &esp); + + uint32_t param_addr = esp + 4; + uc_mem_read(uc, param_addr, &pCaller, sizeof(uint32_t)); + + param_addr += 4; + uc_mem_read(uc, param_addr, &szURL, sizeof(uint32_t)); + + param_addr += 4; + uc_mem_read(uc, param_addr, &szFileName, sizeof(uint32_t)); + + param_addr += 4; + uc_mem_read(uc, param_addr, &dwReserved, sizeof(uint32_t)); + + param_addr += 4; + uc_mem_read(uc, param_addr, &lpfnCB, sizeof(uint32_t)); + } + + // 将此行为标记为可能的恶意行为 + context->SetMalwareAnalysisType(MalwareAnalysisType::kMalware); + + // 读取URL (宽字符) + std::wstring wUrlString; + if (szURL != 0) { + wchar_t buffer[1024] = {0}; + uc_mem_read(uc, szURL, buffer, sizeof(buffer) - sizeof(wchar_t)); + wUrlString = buffer; + + // 转换为UTF-8字符串用于日志记录 + std::string urlString(wUrlString.begin(), wUrlString.end()); + printf("[URLDownloadToFileW] URL: %s\n", urlString.c_str()); + + // 记录到API调用列表 + context->ApiCallList.push_back("URLDownloadToFileW: " + urlString); + } + + // 读取文件名 (宽字符) + std::wstring wFileNameString; + if (szFileName != 0) { + wchar_t buffer[1024] = {0}; + uc_mem_read(uc, szFileName, buffer, sizeof(buffer) - sizeof(wchar_t)); + wFileNameString = buffer; + + // 转换为UTF-8字符串用于日志记录 + std::string fileNameString(wFileNameString.begin(), + wFileNameString.end()); + printf("[URLDownloadToFileW] File name: %s\n", fileNameString.c_str()); + } + + // 检查URL是否包含可疑内容 + const std::vector suspiciousUrlPatterns = { + L"http://", L"https://", L"ftp://", L".exe", L".dll", L".bat", + L".ps1", L".vbs", L".js", L".cmd", L".msi", L".hta"}; + + for (const auto& pattern : suspiciousUrlPatterns) { + if (wUrlString.find(pattern) != std::wstring::npos) { + context->SetMalwareAnalysisType(MalwareAnalysisType::kMalware); +#if LOG_LEVEL >= 1 + std::string patternString(pattern.begin(), pattern.end()); + printf("[!!!] Malicious URL pattern detected: %s\n", + patternString.c_str()); +#endif + break; + } + } + + // 模拟下载成功 + uint32_t returnValue = S_OK; // 0 表示成功 + uc_reg_write(uc, + context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX, + &returnValue); } \ No newline at end of file diff --git a/ai_anti_malware/sandbox_api_winhttp.h b/ai_anti_malware/sandbox_api_winhttp.h index 7a843e2..c680f68 100644 --- a/ai_anti_malware/sandbox_api_winhttp.h +++ b/ai_anti_malware/sandbox_api_winhttp.h @@ -8,4 +8,6 @@ auto Api_InternetOpenUrlA(void* sandbox, uc_engine* uc, uint64_t address) auto Api_InternetCloseHandle(void* sandbox, uc_engine* uc, uint64_t address) -> void; auto Api_InternetReadFile(void* sandbox, uc_engine* uc, uint64_t address) + -> void; +auto Api_URLDownloadToFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void; \ No newline at end of file