Files
awesome_anti_virus_engine/ai_anti_malware/sandbox_api_files.cpp
2025-04-25 16:08:22 +08:00

295 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "sandbox.h"
#include "sandbox_callbacks.h"
#include <fstream>
// 文件句柄信息结构体
struct FileHandleInfo {
uint64_t handle; // 文件句柄
std::string path; // 文件路径
std::vector<char> content; // 文件内容
size_t currentPosition; // 当前读取位置
bool isValid; // 是否有效
};
// 在Sandbox类中添加文件句柄表
std::map<uint64_t, FileHandleInfo*> Sandbox::m_fileHandles;
// 生成唯一的文件句柄
uint64_t Sandbox::GenerateFileHandle() {
static uint64_t nextHandle = 0x2000; // 起始值,避免与特殊句柄冲突
return nextHandle++;
}
// 获取文件句柄信息
FileHandleInfo* Sandbox::GetFileHandleInfo(uint64_t handle) {
auto it = m_fileHandles.find(handle);
if (it != m_fileHandles.end()) {
return it->second;
}
return nullptr;
}
// CreateFileW API实现
auto Api_CreateFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint64_t lpFileName = 0;
uint64_t dwDesiredAccess = 0;
uint64_t dwShareMode = 0;
uint64_t lpSecurityAttributes = 0;
uint64_t dwCreationDisposition = 0;
uint64_t dwFlagsAndAttributes = 0;
uint64_t hTemplateFile = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = lpFileName, rdx = dwDesiredAccess, r8 = dwShareMode, r9 = lpSecurityAttributes
uc_reg_read(uc, UC_X86_REG_RCX, &lpFileName);
uc_reg_read(uc, UC_X86_REG_RDX, &dwDesiredAccess);
uint64_t temp_share_mode;
uc_reg_read(uc, UC_X86_REG_R8, &temp_share_mode);
dwShareMode = static_cast<uint32_t>(temp_share_mode);
uc_reg_read(uc, UC_X86_REG_R9, &lpSecurityAttributes);
// 从栈上读取其他参数
uint64_t rsp;
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
uc_mem_read(uc, rsp + 0x28, &dwCreationDisposition, sizeof(uint32_t));
uc_mem_read(uc, rsp + 0x30, &dwFlagsAndAttributes, sizeof(uint32_t));
uc_mem_read(uc, rsp + 0x38, &hTemplateFile, sizeof(uint64_t));
} else {
// x86: 从栈上读取参数
uint32_t esp;
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
esp += 0x4; // 跳过返回地址
uint32_t temp_values[7];
for (int i = 0; i < 7; i++) {
uc_mem_read(uc, esp + (i * 4), &temp_values[i], sizeof(uint32_t));
}
lpFileName = temp_values[0];
dwDesiredAccess = temp_values[1];
dwShareMode = temp_values[2];
lpSecurityAttributes = temp_values[3];
dwCreationDisposition = temp_values[4];
dwFlagsAndAttributes = temp_values[5];
hTemplateFile = temp_values[6];
}
// 读取文件名
std::wstring filename;
if (lpFileName != 0) {
wchar_t buffer[MAX_PATH] = {0};
size_t i = 0;
do {
wchar_t wch;
uc_mem_read(uc, lpFileName + (i * 2), &wch, sizeof(wchar_t));
buffer[i] = wch;
i++;
} while (buffer[i - 1] != 0 && i < MAX_PATH);
if (i > 0 && i < MAX_PATH) {
filename = buffer;
}
}
// 将宽字符串转换为窄字符串,用于日志和内部存储
std::string ansiFilename(filename.begin(), filename.end());
// 创建文件句柄信息
auto fileHandleInfo = new FileHandleInfo();
fileHandleInfo->path = ansiFilename;
fileHandleInfo->currentPosition = 0;
fileHandleInfo->isValid = true;
// 读取实际文件内容(如果存在)
std::ifstream file(ansiFilename, std::ios::binary | std::ios::ate);
if (file.is_open()) {
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
fileHandleInfo->content.resize(size);
if (size > 0) {
file.read(fileHandleInfo->content.data(), size);
}
file.close();
} else {
// 文件不存在或无法打开
if (dwCreationDisposition == CREATE_NEW ||
dwCreationDisposition == CREATE_ALWAYS ||
dwCreationDisposition == OPEN_ALWAYS) {
// 创建空文件
fileHandleInfo->content.clear();
} else {
// 返回无效句柄
delete fileHandleInfo;
uint64_t invalidHandle = (uint64_t)INVALID_HANDLE_VALUE;
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&invalidHandle);
// 设置错误码
DWORD error = ERROR_FILE_NOT_FOUND;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
return;
}
}
// 生成唯一的文件句柄
uint64_t fileHandle = context->GenerateFileHandle();
fileHandleInfo->handle = fileHandle;
// 添加到文件句柄表
context->m_fileHandles[fileHandle] = fileHandleInfo;
printf("[*] CreateFileW: File=%ls, Access=0x%x, Share=0x%x, Create=0x%x, Handle=0x%llx\n",
filename.c_str(), dwDesiredAccess, dwShareMode, dwCreationDisposition, fileHandle);
// 返回文件句柄
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&fileHandle);
}
// ReadFileA API实现
auto Api_ReadFileA(void* sandbox, uc_engine* uc, uint64_t address) -> void {
Api_ReadFile(sandbox, uc, address, false);
}
// ReadFileW API实现
auto Api_ReadFileW(void* sandbox, uc_engine* uc, uint64_t address) -> void {
Api_ReadFile(sandbox, uc, address, true);
}
// 统一的ReadFile实现
auto Api_ReadFile(void* sandbox, uc_engine* uc, uint64_t address, bool isWideChar) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint64_t hFile = 0;
uint64_t lpBuffer = 0;
uint32_t nNumberOfBytesToRead = 0;
uint64_t lpNumberOfBytesRead = 0;
uint64_t lpOverlapped = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = hFile, rdx = lpBuffer, r8 = nNumberOfBytesToRead, r9 = lpNumberOfBytesRead
uc_reg_read(uc, UC_X86_REG_RCX, &hFile);
uc_reg_read(uc, UC_X86_REG_RDX, &lpBuffer);
uint64_t temp_bytes_to_read;
uc_reg_read(uc, UC_X86_REG_R8, &temp_bytes_to_read);
nNumberOfBytesToRead = static_cast<uint32_t>(temp_bytes_to_read);
uc_reg_read(uc, UC_X86_REG_R9, &lpNumberOfBytesRead);
// 从栈上读取lpOverlapped参数
uint64_t rsp;
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
uc_mem_read(uc, rsp + 0x28, &lpOverlapped, sizeof(uint64_t));
} else {
// x86: 从栈上读取参数
uint32_t esp;
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
esp += 0x4; // 跳过返回地址
uint32_t temp_handle, temp_buffer, temp_bytes_read, temp_overlapped;
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
uc_mem_read(uc, esp + 0x4, &temp_buffer, sizeof(uint32_t));
uc_mem_read(uc, esp + 0x8, &nNumberOfBytesToRead, sizeof(uint32_t));
uc_mem_read(uc, esp + 0xC, &temp_bytes_read, sizeof(uint32_t));
uc_mem_read(uc, esp + 0x10, &temp_overlapped, sizeof(uint32_t));
hFile = temp_handle;
lpBuffer = temp_buffer;
lpNumberOfBytesRead = temp_bytes_read;
lpOverlapped = temp_overlapped;
}
// 从文件句柄表中查找句柄信息
auto fileInfo = context->GetFileHandleInfo(hFile);
bool success = false;
uint32_t bytesRead = 0;
if (fileInfo && fileInfo->isValid) {
// 计算实际可读取的字节数
size_t availableBytes = fileInfo->content.size() - fileInfo->currentPosition;
bytesRead = (nNumberOfBytesToRead < availableBytes) ? nNumberOfBytesToRead : (uint32_t)availableBytes;
if (bytesRead > 0) {
// 读取数据
uc_mem_write(uc, lpBuffer,
fileInfo->content.data() + fileInfo->currentPosition,
bytesRead);
// 更新当前位置
fileInfo->currentPosition += bytesRead;
success = true;
} else {
// 没有更多数据可读
success = true; // 返回TRUE但是bytesRead为0
}
} else {
// 设置错误码
DWORD error = ERROR_INVALID_HANDLE;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
}
// 写入实际读取的字节数
if (lpNumberOfBytesRead != 0) {
uc_mem_write(uc, lpNumberOfBytesRead, &bytesRead, sizeof(uint32_t));
}
// 设置返回值
uint64_t result = success ? TRUE : FALSE;
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
const char* apiName = isWideChar ? "ReadFileW" : "ReadFileA";
printf("[*] %s: Handle=0x%llx, Buffer=0x%llx, BytesToRead=%u, BytesRead=%u, Result=%s\n",
apiName, hFile, lpBuffer, nNumberOfBytesToRead, bytesRead,
success ? "TRUE" : "FALSE");
}
// CloseFile API实现
auto Api_CloseFile(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint64_t hFile = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
uc_reg_read(uc, UC_X86_REG_RCX, &hFile);
} else {
uint32_t esp;
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
esp += 0x4; // 跳过返回地址
uint32_t temp_handle;
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
hFile = temp_handle;
}
// 在文件句柄表中查找并释放资源
auto it = context->m_fileHandles.find(hFile);
bool success = false;
if (it != context->m_fileHandles.end() && it->second) {
delete it->second;
context->m_fileHandles.erase(it);
success = true;
}
// 设置返回值
uint64_t result = success ? TRUE : FALSE;
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
printf("[*] CloseFile: Handle=0x%llx, Result=%s\n",
hFile, success ? "TRUE" : "FALSE");
}