修复沙箱功能和API实现

- 在沙箱中添加了对CreateProcessW的支持,整合了CreateProcessA和CreateProcessW的共同逻辑
- 实现了URLDownloadToFileW函数,增加了对可疑URL的检测
- 更新了API钩子以支持新的API功能
- 改进了错误处理和日志记录,确保更好的调试信息输出
- 调整了主函数中的恶意软件扫描和沙箱功能调用顺序,确保恶意软件扫描优先执行
This commit is contained in:
huoji
2025-03-19 14:52:19 +08:00
parent c61773dfd8
commit 9b970ce8a2
7 changed files with 654 additions and 123 deletions

View File

@@ -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*>(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<uint32_t>(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<uint32_t>(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*>(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*>(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<uint32_t>(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*>(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;
}
}