添加沙箱功能和API钩子支持
- 在沙箱中实现了新的功能,包括内存分配和API钩子初始化 - 更新了沙箱类,增加了对WFP引擎的支持 - 添加了多个API的实现,如GetLastError、InitializeCriticalSection等 - 修改了主函数以使用新的沙箱功能,替换了恶意软件扫描功能 - 更新了项目文件以包含新的源文件和API实现 - 改进了错误处理和日志记录功能
This commit is contained in:
19
.vscode/c_cpp_properties.json
vendored
Normal file
19
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
"UNICODE",
|
||||
"_UNICODE"
|
||||
],
|
||||
"compilerPath": "E:/Program Files/LLVM/bin/clang++.exe",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++23"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
@@ -39,6 +39,7 @@ auto getPeInfo(std::string inputFilePath) -> std::shared_ptr<BasicPeInfo> {
|
||||
sampleInfo->RecImageBase +
|
||||
(sampleInfo->isX64 ? sampleInfo->ntHead64->OptionalHeader.SizeOfImage
|
||||
: sampleInfo->ntHead32->OptionalHeader.SizeOfImage);
|
||||
sampleInfo->isDll = peconv::is_module_dll((BYTE*)sampleInfo->peBuffer);
|
||||
printf("Debug - Memory mapping parameters:\n");
|
||||
printf("RecImageBase: 0x%llx\n", sampleInfo->RecImageBase);
|
||||
printf("peSize: 0x%llx\n", sampleInfo->peSize);
|
||||
@@ -310,9 +311,29 @@ auto doMalwareScan(int argc, char* argv[]) -> void {
|
||||
auto sampleType = scanner.DetectMalware(filePath);
|
||||
printf("sample type: %d \n", sampleType);
|
||||
}
|
||||
int doSandbox(int argc, char* argv[]) {
|
||||
/*
|
||||
if (argc < 3) {
|
||||
std::cout << "用法: " << argv[0] << " <文件路径> <地址>" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::string filePath = argv[1];
|
||||
*/
|
||||
std::string filePath = "C:\\mso.dll";
|
||||
|
||||
auto peInfo = getPeInfo(filePath);
|
||||
if (peInfo == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
Sandbox se;
|
||||
se.InitEnv(peInfo);
|
||||
se.Run(0x180003980);
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char* argv[]) {
|
||||
// doMl(argc, argv);
|
||||
// doPredict(argc, argv);
|
||||
doMalwareScan(argc, argv);
|
||||
// doMalwareScan(argc, argv);
|
||||
doSandbox(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,9 +174,13 @@
|
||||
<ClCompile Include="ml.cpp" />
|
||||
<ClCompile Include="sandbox.cpp" />
|
||||
<ClCompile Include="sandbox_api_emu.cpp" />
|
||||
<ClCompile Include="sandbox_api_file.cpp" />
|
||||
<ClCompile Include="sandbox_api_process.cpp" />
|
||||
<ClCompile Include="sandbox_api_regs.cpp" />
|
||||
<ClCompile Include="sandbox_api_stl.cpp" />
|
||||
<ClCompile Include="sandbox_api_wfp.cpp" />
|
||||
<ClCompile Include="sandbox_api_winhttp.cpp" />
|
||||
<ClCompile Include="sandbox_api_wlan.cpp" />
|
||||
<ClCompile Include="sandbox_callbacks.cpp" />
|
||||
<ClCompile Include="sandbox_malware_check.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
<Filter Include="头文件\machine_learning">
|
||||
<UniqueIdentifier>{65a79261-ea29-4842-b41c-7983eddbdc85}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="源文件\sandbox\apis">
|
||||
<UniqueIdentifier>{44f6b6b6-64fa-44ff-b7fa-af7f7294a3f2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ai_anti_malware.cpp">
|
||||
@@ -120,9 +123,6 @@
|
||||
<ClCompile Include="sandbox_callbacks.cpp">
|
||||
<Filter>源文件\sandbox</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_emu.cpp">
|
||||
<Filter>源文件\sandbox</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ml.cpp">
|
||||
<Filter>源文件\machine_learning</Filter>
|
||||
</ClCompile>
|
||||
@@ -132,14 +132,29 @@
|
||||
<ClCompile Include="sandbox_malware_check.cpp">
|
||||
<Filter>源文件\sandbox</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_winhttp.cpp">
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_emu.cpp">
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_process.cpp">
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_regs.cpp">
|
||||
<Filter>源文件\sandbox</Filter>
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_stl.cpp">
|
||||
<Filter>源文件\sandbox</Filter>
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_winhttp.cpp">
|
||||
<Filter>源文件\sandbox</Filter>
|
||||
<ClCompile Include="sandbox_api_file.cpp">
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_wlan.cpp">
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sandbox_api_wfp.cpp">
|
||||
<Filter>源文件\sandbox\apis</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -3,21 +3,23 @@
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <iostream>
|
||||
#include <iostream>
|
||||
#include <winternl.h>
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <ntstatus.h>
|
||||
#include <ctime>
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "unicorn/include/unicorn/unicorn.h"
|
||||
#include "capstone/include/capstone/capstone.h"
|
||||
#pragma comment(lib, "unicorn/unicorn.lib")
|
||||
#pragma comment(lib, "capstone/capstone.lib")
|
||||
#include "libpeconv/include/peconv.h"
|
||||
#include "native_struct.h"
|
||||
#include "tiny_wfp_structs.h"
|
||||
struct BasicPeInfo {
|
||||
std::string inputFilePath;
|
||||
bool isX64;
|
||||
@@ -29,6 +31,7 @@ struct BasicPeInfo {
|
||||
size_t peSize;
|
||||
PIMAGE_NT_HEADERS ntHead64;
|
||||
PIMAGE_NT_HEADERS32 ntHead32;
|
||||
bool isDll;
|
||||
};
|
||||
#include "sandbox.h"
|
||||
#include "ml.h"
|
||||
@@ -2,6 +2,28 @@
|
||||
|
||||
#include "sandbox_callbacks.h"
|
||||
|
||||
// 在文件开头添加AllocateMemory函数的声明
|
||||
auto Sandbox::AllocateMemory(size_t size) -> uint64_t {
|
||||
// 使用一个简单的内存分配策略
|
||||
static uint64_t next_address = 0x60000000; // 起始地址
|
||||
uint64_t allocated_address = next_address;
|
||||
|
||||
// 对齐到4KB
|
||||
size = (size + 0xFFF) & ~0xFFF;
|
||||
|
||||
// 分配内存
|
||||
uc_err err = uc_mem_map(m_ucEngine, allocated_address, size, UC_PROT_ALL);
|
||||
if (err != UC_ERR_OK) {
|
||||
printf("[!] Failed to allocate memory at 0x%llx: %u\n",
|
||||
allocated_address, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 更新下一个可用地址
|
||||
next_address += size + 0x1000; // 添加一个页面的间隔
|
||||
return allocated_address;
|
||||
}
|
||||
|
||||
std::string getDllNameFromApiSetMap(const std::string& apiSet) {
|
||||
const std::wstring wApiSet(apiSet.begin(), apiSet.end());
|
||||
|
||||
@@ -174,9 +196,19 @@ class cFixImprot : public peconv::t_function_resolver {
|
||||
private:
|
||||
Sandbox* m_sandbox; // Sandbox实例的指针
|
||||
};
|
||||
Sandbox::Sandbox() {}
|
||||
Sandbox::Sandbox() {
|
||||
m_ucEngine = nullptr;
|
||||
m_peInfo = nullptr;
|
||||
m_nextWfpEngineHandle = (HANDLE)0x1000; // 初始化WFP引擎句柄
|
||||
}
|
||||
|
||||
Sandbox::~Sandbox() {
|
||||
// 清理WFP引擎资源
|
||||
for (auto& pair : m_wfpEngines) {
|
||||
delete pair.second;
|
||||
}
|
||||
m_wfpEngines.clear();
|
||||
|
||||
// 1. 先清理高层资源
|
||||
m_crossSectionExecution.clear();
|
||||
envStrings.clear();
|
||||
@@ -631,7 +663,7 @@ auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
|
||||
InitCommandLine(peInfo->inputFilePath);
|
||||
}
|
||||
|
||||
auto Sandbox::Run() -> void {
|
||||
auto Sandbox::Run(uint64_t address) -> void {
|
||||
// 初始化堆栈
|
||||
uc_err err = uc_mem_map(m_ucEngine, m_stackBase, m_stackSize,
|
||||
UC_PROT_READ | UC_PROT_WRITE);
|
||||
@@ -659,7 +691,7 @@ auto Sandbox::Run() -> void {
|
||||
&rbp);
|
||||
|
||||
// 设置入口点
|
||||
uint64_t entryPoint = m_peInfo->RecImageBase + m_peInfo->entryPoint;
|
||||
uint64_t entryPoint = (m_peInfo->RecImageBase + m_peInfo->entryPoint);
|
||||
|
||||
// 添加钩子
|
||||
uc_hook hook_code, hook_mem, hook_mem_unmap, hook_mem_write, hook_syscall;
|
||||
@@ -708,7 +740,7 @@ auto Sandbox::Run() -> void {
|
||||
if (err != UC_ERR_OK) {
|
||||
throw std::runtime_error("Failed to add syscall hook");
|
||||
}
|
||||
|
||||
auto customIP = address;
|
||||
// 设置EIP/RIP
|
||||
err = uc_reg_write(m_ucEngine,
|
||||
m_peInfo->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP,
|
||||
@@ -718,11 +750,26 @@ auto Sandbox::Run() -> void {
|
||||
}
|
||||
|
||||
InitApiHooks();
|
||||
|
||||
std::cout << "Starting execution at " << std::hex << entryPoint
|
||||
<< std::endl;
|
||||
uint64_t timeout = 60 * 1000 * 1000;
|
||||
// 1.入口点是必须跑的
|
||||
if (m_peInfo->isDll) {
|
||||
// 给rcx和rdx设置dll应该设置的
|
||||
auto dll_fdwReason = 1;
|
||||
uc_reg_write(m_ucEngine, UC_X86_REG_RCX, &m_peInfo->RecImageBase);
|
||||
uc_reg_write(m_ucEngine, UC_X86_REG_RDX, &dll_fdwReason);
|
||||
}
|
||||
err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, timeout, 0);
|
||||
std::cerr << "Emulation error: " << uc_strerror(err) << std::endl;
|
||||
// 2. 有自定义地址 再跑自定义地址
|
||||
std::cerr << "Entry Point Emulation error: " << uc_strerror(err)
|
||||
<< std::endl;
|
||||
if (address != 0) {
|
||||
err = uc_emu_start(m_ucEngine, address, m_peInfo->imageEnd, timeout, 0);
|
||||
std::cerr << "Custom Emulation error: " << uc_strerror(err)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
auto Sandbox::GetEnvString() -> std::vector<wchar_t> {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include "head.h"
|
||||
#include <WinInet.h>
|
||||
#include <wininet.h>
|
||||
#define PAGE_SIZE 0x1000
|
||||
#define CF_MASK (1 << 0)
|
||||
#define PF_MASK (1 << 2)
|
||||
@@ -87,12 +85,21 @@ struct InternetHandleInfo {
|
||||
class Sandbox {
|
||||
friend class cFixImprot; // 声明cFixImprot为友元类
|
||||
public:
|
||||
// WFP引擎相关结构体
|
||||
struct FakeWFPEngine {
|
||||
bool isOpen;
|
||||
std::vector<FWPM_PROVIDER0> providers;
|
||||
std::vector<FWPM_FILTER0> filters;
|
||||
};
|
||||
|
||||
Sandbox();
|
||||
~Sandbox();
|
||||
std::map<uint64_t, size_t>
|
||||
process_enum_state; // 用于跟踪每个句柄的枚举状态
|
||||
|
||||
// Public methods
|
||||
auto InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void;
|
||||
auto Run() -> void;
|
||||
auto Run(uint64_t address = 0) -> void;
|
||||
auto GetCapstoneHandle() const -> csh { return m_csHandle; }
|
||||
auto GetUnicornHandle() const -> uc_engine* { return m_ucEngine; }
|
||||
auto GetPeInfo() const -> std::shared_ptr<BasicPeInfo> { return m_peInfo; }
|
||||
@@ -115,6 +122,9 @@ class Sandbox {
|
||||
auto GetEnvStringsSize() -> size_t;
|
||||
auto InitCommandLine() -> void;
|
||||
|
||||
// 内存分配相关的方法
|
||||
auto AllocateMemory(size_t size) -> uint64_t;
|
||||
|
||||
// 堆管理相关的公共方法
|
||||
auto CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment*;
|
||||
auto AllocateFromSegment(HeapSegment* segment, size_t size) -> uint64_t;
|
||||
@@ -213,6 +223,16 @@ class Sandbox {
|
||||
}
|
||||
std::vector<std::string> ApiCallList;
|
||||
|
||||
// WFP引擎相关方法
|
||||
auto GetWfpEngines() -> std::map<HANDLE, FakeWFPEngine*>& {
|
||||
return m_wfpEngines;
|
||||
}
|
||||
auto GetNextWfpEngineHandle() -> HANDLE {
|
||||
auto handle = m_nextWfpEngineHandle;
|
||||
m_nextWfpEngineHandle = (HANDLE)((uint64_t)m_nextWfpEngineHandle + 1);
|
||||
return handle;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<BasicPeInfo> m_peInfo;
|
||||
uint64_t m_gsBase;
|
||||
@@ -302,4 +322,106 @@ class Sandbox {
|
||||
auto UpdateLdrLinks(const LDR_DATA_TABLE_ENTRY& entry,
|
||||
uint64_t entryAddress, X64_PEB_LDR_DATA& ldrData)
|
||||
-> void;
|
||||
|
||||
// WFP引擎相关成员
|
||||
std::map<HANDLE, FakeWFPEngine*> m_wfpEngines;
|
||||
HANDLE m_nextWfpEngineHandle;
|
||||
};
|
||||
std::string getDllNameFromApiSetMap(const std::string& apiSet);
|
||||
void Api_GetLastError(void* sandbox, uc_engine* uc, uint64_t address);
|
||||
auto Api_InitializeCriticalSectionAndSpinCount(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void;
|
||||
auto Api_InitializeCriticalSectionEx(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void;
|
||||
auto Api_IsProcessorFeaturePresent(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void;
|
||||
auto Api_DeleteCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_TlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_TlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api___set_app_type(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api___p__fmode(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_RegOpenKeyExW(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_RegCloseKey(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_InitializeSListHead(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetEnvironmentStringsW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_FreeEnvironmentStringsW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetProcessHeap(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_HeapAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_HeapFree(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_TlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_SetLastError(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
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_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;
|
||||
auto Api_GetCommandLineA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetCommandLineW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetACP(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_GetCPInfo(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_SHGetKnownFolderPath(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_EncodePointer(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_CreateToolhelp32Snapshot(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void;
|
||||
auto Api_Process32FirstW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_VirtualQuery(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_GetModuleHandleW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetModuleHandleA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto GetModuleHandleInternal(void* sandbox, const std::wstring& moduleName)
|
||||
-> HMODULE;
|
||||
auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_WlanOpenHandle(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_WlanEnumInterfaces(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_WlanGetProfileList(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_WlanFreeMemory(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_WlanCloseHandle(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_ReadFile(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_CreatePipe(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_CloseHandle(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_RtlFormatCurrentUserKeyPath(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void;
|
||||
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_GetCurrentProcess(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetCurrentThread(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_OpenProcessToken(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetTokenInformation(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
|
||||
// WFP API函数声明
|
||||
auto Api_FwpmEngineOpen0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_FwpmProviderAdd0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_FwpmFilterAdd0(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_FwpmEngineClose0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
@@ -1,47 +1,7 @@
|
||||
#include "sandbox.h"
|
||||
#include "sandbox_callbacks.h"
|
||||
#include "sandbox_api_winhttp.h"
|
||||
std::string getDllNameFromApiSetMap(const std::string& apiSet);
|
||||
auto Api_RegOpenKeyExW(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_RegCloseKey(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_InitializeSListHead(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
;
|
||||
auto Api_GetEnvironmentStringsW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
;
|
||||
auto Api_FreeEnvironmentStringsW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetProcessHeap(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_HeapAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_HeapFree(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_TlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_SetLastError(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
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_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;
|
||||
auto Api_GetCommandLineA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetCommandLineW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_GetACP(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_GetCPInfo(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_SHGetKnownFolderPath(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void;
|
||||
auto Api_EncodePointer(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||
|
||||
#include <tlhelp32.h>
|
||||
auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
@@ -89,6 +49,21 @@ void Api_GetCurrentProcessId(void* sandbox, uc_engine* uc, uint64_t address) {
|
||||
&context->GetTeb32()->ClientId.UniqueProcess);
|
||||
}
|
||||
}
|
||||
auto Api_GetCurrentThread(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
|
||||
// GetCurrentThread 总是返回伪句柄值 -1 (0xFFFFFFFF)
|
||||
uint64_t pseudo_handle = static_cast<uint64_t>(-1);
|
||||
|
||||
// 根据架构写入返回值
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&pseudo_handle);
|
||||
|
||||
printf("[*] GetCurrentThread called, returning pseudo-handle 0x%llx\n",
|
||||
pseudo_handle);
|
||||
}
|
||||
auto Api_LoadLibraryA(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t params_address = 0;
|
||||
@@ -224,380 +199,6 @@ auto Api_LoadLibraryExW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&return_address);
|
||||
}
|
||||
void Api_GetLastError(void* sandbox, uc_engine* uc, uint64_t address) {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
DWORD last_error = 0;
|
||||
|
||||
// 从TEB中获取LastError
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
last_error = context->GetTeb64()->LastErrorValue;
|
||||
} else {
|
||||
last_error = context->GetTeb32()->LastErrorValue;
|
||||
}
|
||||
|
||||
printf("[*] GetLastError: LastError=0x%x\n", last_error);
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&last_error);
|
||||
}
|
||||
auto Api_InitializeCriticalSectionAndSpinCount(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpCriticalSection = 0;
|
||||
uint32_t dwSpinCount = 0;
|
||||
BOOL success = TRUE; // 默认返回成功
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpCriticalSection, rdx = dwSpinCount
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||||
uint64_t temp_spin_count = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_spin_count);
|
||||
dwSpinCount = static_cast<uint32_t>(temp_spin_count);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uint32_t temp_cs = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||||
lpCriticalSection = temp_cs;
|
||||
esp_address += 0x4;
|
||||
uc_mem_read(uc, esp_address, &dwSpinCount, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (lpCriticalSection != 0) {
|
||||
// 初始化关键段结构
|
||||
RTL_CRITICAL_SECTION cs = {0};
|
||||
cs.LockCount = -1; // 初始未锁定状态
|
||||
cs.RecursionCount = 0; // 初始递归计数为0
|
||||
cs.SpinCount = dwSpinCount; // 设置自旋计数
|
||||
cs.OwningThread = 0; // 初始无拥有线程
|
||||
cs.LockSemaphore = 0; // 初始信号量为0
|
||||
|
||||
// 写入初始化后的结构到目标内存
|
||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
} else {
|
||||
success = FALSE;
|
||||
// 设置LastError
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf(
|
||||
"[*] InitializeCriticalSectionAndSpinCount: CS=0x%llx, SpinCount=0x%x, "
|
||||
"Success=%d\n",
|
||||
lpCriticalSection, dwSpinCount, success);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&success);
|
||||
}
|
||||
|
||||
auto Api_InitializeCriticalSectionEx(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpCriticalSection = 0;
|
||||
uint32_t dwSpinCount = 0;
|
||||
uint32_t dwFlags = 0;
|
||||
BOOL success = TRUE; // 默认返回成功
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpCriticalSection, rdx = dwSpinCount, r8 = dwFlags
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||||
uint64_t temp_spin_count = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_spin_count);
|
||||
dwSpinCount = static_cast<uint32_t>(temp_spin_count);
|
||||
uint64_t temp_flags = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &temp_flags);
|
||||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uint32_t temp_cs = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||||
lpCriticalSection = temp_cs;
|
||||
esp_address += 0x4;
|
||||
uc_mem_read(uc, esp_address, &dwSpinCount, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
uc_mem_read(uc, esp_address, &dwFlags, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (lpCriticalSection != 0) {
|
||||
// 初始化关键段结构
|
||||
RTL_CRITICAL_SECTION cs = {0};
|
||||
cs.LockCount = -1; // 初始未锁定状态
|
||||
cs.RecursionCount = 0; // 初始递归计数为0
|
||||
cs.SpinCount = dwSpinCount; // 设置自旋计数
|
||||
cs.OwningThread = 0; // 初始无拥有线程
|
||||
cs.LockSemaphore = 0; // 初始信号量为0
|
||||
|
||||
// 处理特殊标志
|
||||
// CRITICAL_SECTION_FLAG_NO_DEBUG_INFO = 0x01000000
|
||||
// CRITICAL_SECTION_FLAG_DYNAMIC_SPIN = 0x02000000
|
||||
// CRITICAL_SECTION_FLAG_STATIC_INIT = 0x04000000
|
||||
// CRITICAL_SECTION_FLAG_RESOURCE_TYPE = 0x08000000
|
||||
// CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO = 0x10000000
|
||||
|
||||
// 写入初始化后的结构到目标内存
|
||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
} else {
|
||||
success = FALSE;
|
||||
// 设置LastError
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf(
|
||||
"[*] InitializeCriticalSectionEx: CS=0x%llx, SpinCount=0x%x, "
|
||||
"Flags=0x%x, "
|
||||
"Success=%d\n",
|
||||
lpCriticalSection, dwSpinCount, dwFlags, success);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&success);
|
||||
}
|
||||
|
||||
auto Api_TlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
DWORD tls_index = TLS_OUT_OF_INDEXES; // 默认返回失败值
|
||||
|
||||
// 获取TEB结构
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
auto teb = context->GetTeb64();
|
||||
// 在TLS槽中查找第一个可用的位置
|
||||
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
|
||||
if (teb->TlsSlots[i] == (void*)0x1337ffffff) {
|
||||
teb->TlsSlots[i] = (void*)0; // 标记为已使用
|
||||
tls_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto teb = context->GetTeb32();
|
||||
// 在TLS槽中查找第一个可用的位置
|
||||
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
|
||||
if (teb->TlsSlots[i] == 0x1337) {
|
||||
teb->TlsSlots[i] = 0; // 标记为已使用
|
||||
tls_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tls_index == TLS_OUT_OF_INDEXES) {
|
||||
// 设置LastError为没有可用的TLS索引
|
||||
DWORD error = ERROR_NO_MORE_ITEMS;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] TlsAlloc: Allocated TLS Index=0x%x\n", tls_index);
|
||||
|
||||
// 返回分配的TLS索引
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&tls_index);
|
||||
}
|
||||
auto Api_TlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint32_t dwTlsIndex = 0;
|
||||
uint64_t lpTlsValue = 0;
|
||||
BOOL success = FALSE;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = dwTlsIndex, rdx = lpTlsValue
|
||||
uint64_t temp_index;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_index);
|
||||
dwTlsIndex = static_cast<uint32_t>(temp_index);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lpTlsValue);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &dwTlsIndex, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
uint32_t temp_value;
|
||||
uc_mem_read(uc, esp_address, &temp_value, sizeof(uint32_t));
|
||||
lpTlsValue = temp_value;
|
||||
}
|
||||
|
||||
// 检查索引是否有效(小于64)
|
||||
if (dwTlsIndex < 64) {
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
auto teb = context->GetTeb64();
|
||||
// 检查槽是否已分配(不为nullptr)
|
||||
if (teb->TlsSlots[dwTlsIndex] != (void*)0x1337ffffff) {
|
||||
teb->TlsSlots[dwTlsIndex] = (void*)lpTlsValue;
|
||||
success = TRUE;
|
||||
}
|
||||
} else {
|
||||
auto teb = context->GetTeb32();
|
||||
// 检查槽是否已分配(不为0)
|
||||
if (teb->TlsSlots[dwTlsIndex] != 0x1337) {
|
||||
teb->TlsSlots[dwTlsIndex] = static_cast<uint32_t>(lpTlsValue);
|
||||
success = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// 设置LastError
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] TlsSetValue: Index=0x%x, Value=0x%llx, Success=%d\n",
|
||||
dwTlsIndex, lpTlsValue, success);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&success);
|
||||
}
|
||||
auto Api_DeleteCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpCriticalSection = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpCriticalSection
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uint32_t temp_cs = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||||
lpCriticalSection = temp_cs;
|
||||
}
|
||||
|
||||
if (lpCriticalSection != 0) {
|
||||
// 读取现有的关键段结构
|
||||
RTL_CRITICAL_SECTION cs;
|
||||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
|
||||
// 检查是否有线程仍在等待
|
||||
if (cs.LockCount >= 0) {
|
||||
// 有线程正在等待,设置错误
|
||||
DWORD error = ERROR_SEM_IS_SET;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
// 清零内存,表示删除
|
||||
memset(&cs, 0, sizeof(RTL_CRITICAL_SECTION));
|
||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
}
|
||||
|
||||
printf("[*] DeleteCriticalSection: CS=0x%llx\n", lpCriticalSection);
|
||||
}
|
||||
|
||||
auto Api_IsProcessorFeaturePresent(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint32_t feature_number = 0;
|
||||
BOOL is_supported = FALSE;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = FeatureNumber
|
||||
uint64_t temp_feature;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_feature);
|
||||
feature_number = static_cast<uint32_t>(temp_feature);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &feature_number, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 模拟一些常见的处理器特性
|
||||
switch (feature_number) {
|
||||
case PF_FLOATING_POINT_PRECISION_ERRATA: // 0
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
case PF_FLOATING_POINT_EMULATED: // 1
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
case PF_COMPARE_EXCHANGE_DOUBLE: // 2
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_MMX_INSTRUCTIONS_AVAILABLE: // 3
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_XMMI_INSTRUCTIONS_AVAILABLE: // 6
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_3DNOW_INSTRUCTIONS_AVAILABLE: // 7
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
case PF_RDTSC_INSTRUCTION_AVAILABLE: // 8
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_PAE_ENABLED: // 9
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_XMMI64_INSTRUCTIONS_AVAILABLE: // 10
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_SSE_DAZ_MODE_AVAILABLE: // 11
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_NX_ENABLED: // 12
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_SSE3_INSTRUCTIONS_AVAILABLE: // 13
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_COMPARE_EXCHANGE128: // 14
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_XSAVE_ENABLED: // 17
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_ARM_VFP_32_REGISTERS_AVAILABLE: // 18
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
default:
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("[*] IsProcessorFeaturePresent: Feature=0x%x, Supported=%d\n",
|
||||
feature_number, is_supported);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&is_supported);
|
||||
}
|
||||
|
||||
auto Api_GetProcAddress(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
@@ -1038,83 +639,6 @@ auto Api_VirtualProtect(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
&result);
|
||||
}
|
||||
|
||||
auto Api___set_app_type(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
int32_t appType = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = appType
|
||||
uint64_t temp_type;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_type);
|
||||
appType = static_cast<int32_t>(temp_type);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &appType, sizeof(int32_t));
|
||||
}
|
||||
|
||||
// 简单地返回0表示成功
|
||||
int32_t result = 0;
|
||||
printf("[*] __set_app_type: AppType=%d\n", appType);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
}
|
||||
|
||||
auto Api___p__fmode(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto sb = static_cast<Sandbox*>(sandbox);
|
||||
|
||||
// 检查是否已经创建了 _fmode 变量
|
||||
static uint64_t fmode_address = 0;
|
||||
static int32_t fmode_value = 0; // 默认为文本模式 (_O_TEXT)
|
||||
|
||||
if (fmode_address == 0) {
|
||||
// 为 _fmode 变量分配内存
|
||||
// 使用特定堆地址,与其他 API 一致
|
||||
uint64_t heap_handle =
|
||||
sb->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
||||
|
||||
// 在堆上分配空间
|
||||
HeapSegment* segment = nullptr;
|
||||
auto it = sb->m_heapSegments.find(heap_handle);
|
||||
if (it != sb->m_heapSegments.end()) {
|
||||
segment = it->second;
|
||||
} else {
|
||||
// 创建新的堆段
|
||||
segment = sb->CreateHeapSegment(heap_handle, 0x10000);
|
||||
sb->m_heapSegments[heap_handle] = segment;
|
||||
}
|
||||
|
||||
if (segment) {
|
||||
fmode_address = sb->AllocateFromSegment(segment, sizeof(int32_t));
|
||||
if (fmode_address) {
|
||||
// 初始化 _fmode 为文本模式
|
||||
uc_mem_write(uc, fmode_address, &fmode_value, sizeof(int32_t));
|
||||
printf(
|
||||
"[*] __p__fmode: Allocated _fmode at 0x%llx with value "
|
||||
"%d\n",
|
||||
fmode_address, fmode_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 返回 _fmode 变量的地址
|
||||
printf("[*] __p__fmode: Returning address 0x%llx\n", fmode_address);
|
||||
|
||||
// 设置返回值
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &fmode_address);
|
||||
} else {
|
||||
uint32_t eax = static_cast<uint32_t>(fmode_address);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &eax);
|
||||
}
|
||||
}
|
||||
|
||||
auto Api_Sleep(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t milliseconds;
|
||||
@@ -1134,242 +658,7 @@ auto Api_Sleep(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
// 打印日志
|
||||
printf("Sleep API called with %u milliseconds\n", milliseconds);
|
||||
}
|
||||
// 内部实现函数,处理实际的模块句柄获取逻辑
|
||||
auto GetModuleHandleInternal(void* sandbox, const std::wstring& moduleName)
|
||||
-> HMODULE {
|
||||
auto* sb = static_cast<Sandbox*>(sandbox);
|
||||
|
||||
// 如果模块名为空,返回当前进程的基址
|
||||
if (moduleName.empty()) {
|
||||
return reinterpret_cast<HMODULE>(sb->GetPeInfo()->RecImageBase);
|
||||
}
|
||||
|
||||
// 在已加载的模块中查找
|
||||
for (const auto& module : sb->GetModuleList()) {
|
||||
std::string currentModuleNameA = module->name;
|
||||
std::wstring currentModuleName =
|
||||
std::wstring(currentModuleNameA.begin(), currentModuleNameA.end());
|
||||
if (_wcsicmp(currentModuleName.c_str(), moduleName.c_str()) == 0) {
|
||||
return reinterpret_cast<HMODULE>(module->base);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// GetModuleHandleA的实现
|
||||
auto Api_GetModuleHandleA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto* sb = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t esp = 0, rsp = 0;
|
||||
HMODULE result = nullptr;
|
||||
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
// 获取第一个参数 (rcx)
|
||||
uint64_t moduleNamePtr;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &moduleNamePtr);
|
||||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||
|
||||
std::string moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取ANSI字符串
|
||||
char ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + i, &ch, 1) != UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 转换为宽字符
|
||||
std::wstring wModuleName;
|
||||
if (!moduleName.empty()) {
|
||||
wModuleName = std::wstring(moduleName.begin(), moduleName.end());
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, wModuleName);
|
||||
|
||||
// 设置返回值
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
|
||||
} else {
|
||||
// 32位实现
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
uint32_t moduleNamePtr;
|
||||
uc_mem_read(uc, esp + 4, &moduleNamePtr, sizeof(moduleNamePtr));
|
||||
|
||||
std::string moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取ANSI字符串
|
||||
char ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + i, &ch, 1) != UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 转换为宽字符
|
||||
std::wstring wModuleName;
|
||||
if (!moduleName.empty()) {
|
||||
wModuleName = std::wstring(moduleName.begin(), moduleName.end());
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, wModuleName);
|
||||
|
||||
// 设置返回值
|
||||
uint32_t result32 = reinterpret_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = result ? 0 : ERROR_MOD_NOT_FOUND;
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
sb->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
sb->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
// GetModuleHandleW的实现
|
||||
auto Api_GetModuleHandleW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto* sb = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t esp = 0, rsp = 0;
|
||||
HMODULE result = nullptr;
|
||||
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
// 获取第一个参数 (rcx)
|
||||
uint64_t moduleNamePtr;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &moduleNamePtr);
|
||||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||
|
||||
std::wstring moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取宽字符串
|
||||
wchar_t ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + (i * 2), &ch, 2) !=
|
||||
UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, moduleName);
|
||||
|
||||
// 设置返回值
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
|
||||
} else {
|
||||
// 32位实现
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
uint32_t moduleNamePtr;
|
||||
uc_mem_read(uc, esp + 4, &moduleNamePtr, sizeof(moduleNamePtr));
|
||||
|
||||
std::wstring moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取宽字符串
|
||||
wchar_t ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + (i * 2), &ch, 2) !=
|
||||
UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, moduleName);
|
||||
|
||||
// 设置返回值
|
||||
uint32_t result32 = reinterpret_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = result ? 0 : ERROR_MOD_NOT_FOUND;
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
sb->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
sb->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
auto Api_VirtualQuery(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto* context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpAddress = 0;
|
||||
uint64_t lpBuffer = 0;
|
||||
uint32_t dwLength = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// 64位参数获取
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpAddress);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lpBuffer);
|
||||
uint64_t temp_length = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &temp_length);
|
||||
dwLength = static_cast<uint32_t>(temp_length);
|
||||
} else {
|
||||
// 32位参数获取
|
||||
uint32_t esp = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 0x4; // 跳过返回地址
|
||||
|
||||
uint32_t temp_address = 0;
|
||||
uint32_t temp_buffer = 0;
|
||||
uc_mem_read(uc, esp, &temp_address, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x4, &temp_buffer, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x8, &dwLength, sizeof(uint32_t));
|
||||
|
||||
lpAddress = temp_address;
|
||||
lpBuffer = temp_buffer;
|
||||
}
|
||||
|
||||
// 构造MEMORY_BASIC_INFORMATION结构
|
||||
MEMORY_BASIC_INFORMATION mbi = {};
|
||||
mbi.BaseAddress =
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(lpAddress));
|
||||
mbi.AllocationBase = mbi.BaseAddress;
|
||||
mbi.AllocationProtect = PAGE_EXECUTE_READWRITE; // 默认保护属性
|
||||
mbi.RegionSize = 0x1000; // 默认页大小
|
||||
mbi.State = MEM_COMMIT;
|
||||
mbi.Protect = PAGE_EXECUTE_READWRITE;
|
||||
mbi.Type = MEM_PRIVATE;
|
||||
|
||||
// 写入查询结果
|
||||
uint64_t return_value = 0;
|
||||
if (lpBuffer != 0 && dwLength >= sizeof(MEMORY_BASIC_INFORMATION)) {
|
||||
uc_mem_write(uc, lpBuffer, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
return_value = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
}
|
||||
|
||||
// 设置返回值
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &return_value);
|
||||
} else {
|
||||
uint32_t return_value_32 = static_cast<uint32_t>(return_value);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &return_value_32);
|
||||
}
|
||||
}
|
||||
auto Sandbox::InitApiHooks() -> void {
|
||||
auto FakeApi_GetSystemTimeAsFileTime =
|
||||
_fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1};
|
||||
@@ -1377,6 +666,8 @@ auto Sandbox::InitApiHooks() -> void {
|
||||
_fakeApi{.func = Api_GetCurrentThreadId, .paramCount = 0};
|
||||
auto FakeApi_GetCurrentProcessId =
|
||||
_fakeApi{.func = Api_GetCurrentProcessId, .paramCount = 0};
|
||||
auto FakeApi_GetCurrentThread =
|
||||
_fakeApi{.func = Api_GetCurrentThread, .paramCount = 0};
|
||||
auto FakeApi_QueryPerformanceCounter =
|
||||
_fakeApi{.func = Api_QueryPerformanceCounter, .paramCount = 1};
|
||||
auto FakeApi_LoadLibraryA =
|
||||
@@ -1468,6 +759,48 @@ auto Sandbox::InitApiHooks() -> void {
|
||||
_fakeApi{.func = Api_GetModuleHandleW, .paramCount = 1};
|
||||
auto FakeApi_VirtualQuery =
|
||||
_fakeApi{.func = Api_VirtualQuery, .paramCount = 3};
|
||||
auto FakeApi_Process32FirstW =
|
||||
_fakeApi{.func = Api_Process32FirstW, .paramCount = 2};
|
||||
auto FakeApi_CreateToolhelp32Snapshot =
|
||||
_fakeApi{.func = Api_CreateToolhelp32Snapshot, .paramCount = 2};
|
||||
auto FakeApi_Process32NextW =
|
||||
_fakeApi{.func = Api_Process32NextW, .paramCount = 2};
|
||||
auto FakeApi_CloseHandle =
|
||||
_fakeApi{.func = Api_CloseHandle, .paramCount = 1};
|
||||
auto FakeApi_RtlFormatCurrentUserKeyPath =
|
||||
_fakeApi{.func = Api_RtlFormatCurrentUserKeyPath, .paramCount = 1};
|
||||
auto FakeApi_FlsSetValue =
|
||||
_fakeApi{.func = Api_FlsSetValue, .paramCount = 2};
|
||||
auto FakeApi_CreatePipe = _fakeApi{.func = Api_CreatePipe, .paramCount = 4};
|
||||
auto FakeApi_CreateProcessA =
|
||||
_fakeApi{.func = Api_CreateProcessA, .paramCount = 10};
|
||||
auto FakeApi_ReadFile = _fakeApi{.func = Api_ReadFile, .paramCount = 5};
|
||||
auto FakeApi_WlanOpenHandle =
|
||||
_fakeApi{.func = Api_WlanOpenHandle, .paramCount = 4};
|
||||
auto FakeApi_WlanEnumInterfaces =
|
||||
_fakeApi{.func = Api_WlanEnumInterfaces, .paramCount = 3};
|
||||
auto FakeApi_WlanGetProfileList =
|
||||
_fakeApi{.func = Api_WlanGetProfileList, .paramCount = 4};
|
||||
auto FakeApi_WlanFreeMemory =
|
||||
_fakeApi{.func = Api_WlanFreeMemory, .paramCount = 1};
|
||||
auto FakeApi_WlanCloseHandle =
|
||||
_fakeApi{.func = Api_WlanCloseHandle, .paramCount = 2};
|
||||
auto FakeApi_GetCurrentProcess =
|
||||
_fakeApi{.func = Api_GetCurrentProcess, .paramCount = 0};
|
||||
auto FakeApi_OpenProcessToken =
|
||||
_fakeApi{.func = Api_OpenProcessToken, .paramCount = 3};
|
||||
auto FakeApi_GetTokenInformation =
|
||||
_fakeApi{.func = Api_GetTokenInformation, .paramCount = 5};
|
||||
// 添加WFP相关API
|
||||
auto FakeApi_FwpmEngineOpen0 =
|
||||
_fakeApi{.func = Api_FwpmEngineOpen0, .paramCount = 5};
|
||||
auto FakeApi_FwpmProviderAdd0 =
|
||||
_fakeApi{.func = Api_FwpmProviderAdd0, .paramCount = 3};
|
||||
auto FakeApi_FwpmFilterAdd0 =
|
||||
_fakeApi{.func = Api_FwpmFilterAdd0, .paramCount = 4};
|
||||
auto FakeApi_FwpmEngineClose0 =
|
||||
_fakeApi{.func = Api_FwpmEngineClose0, .paramCount = 1};
|
||||
|
||||
api_map = {
|
||||
{"GetSystemTimeAsFileTime",
|
||||
std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)},
|
||||
@@ -1475,6 +808,8 @@ auto Sandbox::InitApiHooks() -> void {
|
||||
std::make_shared<_fakeApi>(FakeApi_GetCurrentThreadId)},
|
||||
{"GetCurrentProcessId",
|
||||
std::make_shared<_fakeApi>(FakeApi_GetCurrentProcessId)},
|
||||
{"GetCurrentThread",
|
||||
std::make_shared<_fakeApi>(FakeApi_GetCurrentThread)},
|
||||
{"QueryPerformanceCounter",
|
||||
std::make_shared<_fakeApi>(FakeApi_QueryPerformanceCounter)},
|
||||
{"LoadLibraryA", std::make_shared<_fakeApi>(FakeApi_LoadLibraryA)},
|
||||
@@ -1550,6 +885,40 @@ auto Sandbox::InitApiHooks() -> void {
|
||||
{"GetModuleHandleW",
|
||||
std::make_shared<_fakeApi>(FakeApi_GetModuleHandleW)},
|
||||
{"VirtualQuery", std::make_shared<_fakeApi>(FakeApi_VirtualQuery)},
|
||||
{"Process32FirstW",
|
||||
std::make_shared<_fakeApi>(FakeApi_Process32FirstW)},
|
||||
{"CreateToolhelp32Snapshot",
|
||||
std::make_shared<_fakeApi>(FakeApi_CreateToolhelp32Snapshot)},
|
||||
{"Process32NextW", std::make_shared<_fakeApi>(FakeApi_Process32NextW)},
|
||||
{"CloseHandle", std::make_shared<_fakeApi>(FakeApi_CloseHandle)},
|
||||
{"RtlFormatCurrentUserKeyPath",
|
||||
std::make_shared<_fakeApi>(FakeApi_RtlFormatCurrentUserKeyPath)},
|
||||
{"FlsSetValue", std::make_shared<_fakeApi>(FakeApi_FlsSetValue)},
|
||||
{"CreatePipe", std::make_shared<_fakeApi>(FakeApi_CreatePipe)},
|
||||
{"CreateProcessA", std::make_shared<_fakeApi>(FakeApi_CreateProcessA)},
|
||||
{"ReadFile", std::make_shared<_fakeApi>(FakeApi_ReadFile)},
|
||||
{"WlanOpenHandle", std::make_shared<_fakeApi>(FakeApi_WlanOpenHandle)},
|
||||
{"WlanEnumInterfaces",
|
||||
std::make_shared<_fakeApi>(FakeApi_WlanEnumInterfaces)},
|
||||
{"WlanGetProfileList",
|
||||
std::make_shared<_fakeApi>(FakeApi_WlanGetProfileList)},
|
||||
{"WlanFreeMemory", std::make_shared<_fakeApi>(FakeApi_WlanFreeMemory)},
|
||||
{"WlanCloseHandle",
|
||||
std::make_shared<_fakeApi>(FakeApi_WlanCloseHandle)},
|
||||
{"GetCurrentProcess",
|
||||
std::make_shared<_fakeApi>(FakeApi_GetCurrentProcess)},
|
||||
{"OpenProcessToken",
|
||||
std::make_shared<_fakeApi>(FakeApi_OpenProcessToken)},
|
||||
{"GetTokenInformation",
|
||||
std::make_shared<_fakeApi>(FakeApi_GetTokenInformation)},
|
||||
// 添加WFP相关API映射
|
||||
{"FwpmEngineOpen0",
|
||||
std::make_shared<_fakeApi>(FakeApi_FwpmEngineOpen0)},
|
||||
{"FwpmProviderAdd0",
|
||||
std::make_shared<_fakeApi>(FakeApi_FwpmProviderAdd0)},
|
||||
{"FwpmFilterAdd0", std::make_shared<_fakeApi>(FakeApi_FwpmFilterAdd0)},
|
||||
{"FwpmEngineClose0",
|
||||
std::make_shared<_fakeApi>(FakeApi_FwpmEngineClose0)},
|
||||
};
|
||||
}
|
||||
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
||||
@@ -1603,4 +972,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;
|
||||
}
|
||||
}
|
||||
|
||||
180
ai_anti_malware/sandbox_api_file.cpp
Normal file
180
ai_anti_malware/sandbox_api_file.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "sandbox.h"
|
||||
#include "sandbox_callbacks.h"
|
||||
#include "sandbox_api_winhttp.h"
|
||||
#include <tlhelp32.h>
|
||||
auto Api_ReadFile(void* sandbox, uc_engine* uc, uint64_t address) -> 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;
|
||||
}
|
||||
|
||||
// 检查句柄是否为之前CreatePipe创建的读管道
|
||||
bool success = false;
|
||||
uint32_t bytesRead = 0;
|
||||
|
||||
// 检查是否为之前CreatePipe创建的读管道句柄 (0x1338)
|
||||
if (hFile == 0x1338) {
|
||||
// 模拟管道数据读取 - 这里我们可以根据之前的CreateProcessA来生成数据
|
||||
// 生成一些模拟的ping命令输出数据
|
||||
std::string pingOutput =
|
||||
"Reply from 127.0.0.1: bytes=32 time<1ms TTL=45\r\n"
|
||||
"Reply from 127.0.0.1: bytes=32 time<1ms TTL=45\r\n"
|
||||
"Reply from 127.0.0.1: bytes=32 time<1ms TTL=45\r\n"
|
||||
"Reply from 127.0.0.1: bytes=32 time<1ms TTL=45\r\n\r\n"
|
||||
"Ping statistics for 127.0.0.1:\r\n"
|
||||
" Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),\r\n"
|
||||
"Approximate round trip times in milli-seconds:\r\n"
|
||||
" Minimum = 0ms, Maximum = 0ms, Average = 0ms\r\n";
|
||||
|
||||
// 确保不超过缓冲区大小
|
||||
bytesRead = min(static_cast<uint32_t>(pingOutput.length()),
|
||||
nNumberOfBytesToRead);
|
||||
|
||||
// 写入数据到缓冲区
|
||||
if (lpBuffer != 0 && bytesRead > 0) {
|
||||
uc_mem_write(uc, lpBuffer, pingOutput.c_str(), bytesRead);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 写入实际读取的字节数
|
||||
if (lpNumberOfBytesRead != 0) {
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_mem_write(uc, lpNumberOfBytesRead, &bytesRead, sizeof(uint32_t));
|
||||
} else {
|
||||
uc_mem_write(uc, lpNumberOfBytesRead, &bytesRead, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
printf(
|
||||
"[*] ReadFile: Handle=0x%llx, Buffer=0x%llx, BytesToRead=%u, "
|
||||
"BytesRead=%u, Success=%d\n",
|
||||
hFile, lpBuffer, nNumberOfBytesToRead, bytesRead, success);
|
||||
|
||||
// 设置返回值
|
||||
uint64_t result = success ? 1 : 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
// 如果失败,设置错误码
|
||||
if (!success) {
|
||||
DWORD error = ERROR_INVALID_HANDLE;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto Api_CreatePipe(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t hReadPipe = 0;
|
||||
uint64_t hWritePipe = 0;
|
||||
uint64_t lpPipeAttributes = 0;
|
||||
uint32_t nSize = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = hReadPipe, rdx = hWritePipe, r8 = lpPipeAttributes, r9 =
|
||||
// nSize
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &hReadPipe);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &hWritePipe);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &lpPipeAttributes);
|
||||
uint64_t temp_size;
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &temp_size);
|
||||
nSize = static_cast<uint32_t>(temp_size);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
|
||||
uint32_t temp_read_pipe;
|
||||
uint32_t temp_write_pipe;
|
||||
uint32_t temp_pipe_attributes;
|
||||
|
||||
uc_mem_read(uc, esp_address, &temp_read_pipe, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp_address + 0x4, &temp_write_pipe, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp_address + 0x8, &temp_pipe_attributes,
|
||||
sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp_address + 0xC, &nSize, sizeof(uint32_t));
|
||||
|
||||
hReadPipe = temp_read_pipe;
|
||||
hWritePipe = temp_write_pipe;
|
||||
lpPipeAttributes = temp_pipe_attributes;
|
||||
}
|
||||
|
||||
// 创建模拟的管道句柄
|
||||
uint64_t read_handle = 0x1338; // 使用特殊值作为读取句柄
|
||||
uint64_t write_handle = 0x1339; // 使用特殊值作为写入句柄
|
||||
|
||||
// 生成唯一的管道名称
|
||||
char pipeName[MAX_PATH];
|
||||
DWORD processId =
|
||||
context->GetPeInfo()->isX64
|
||||
? static_cast<DWORD>(context->GetTeb64()->ClientId.UniqueProcess)
|
||||
: static_cast<DWORD>(context->GetTeb32()->ClientId.UniqueProcess);
|
||||
|
||||
snprintf(pipeName, sizeof(pipeName),
|
||||
"\\\\.\\pipe\\sandbox_pipe_%lu_%llx_%llx", processId, read_handle,
|
||||
write_handle);
|
||||
|
||||
// 写入句柄到输出参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_mem_write(uc, hReadPipe, &read_handle, sizeof(uint64_t));
|
||||
uc_mem_write(uc, hWritePipe, &write_handle, sizeof(uint64_t));
|
||||
} else {
|
||||
uint32_t read_handle_32 = static_cast<uint32_t>(read_handle);
|
||||
uint32_t write_handle_32 = static_cast<uint32_t>(write_handle);
|
||||
uc_mem_write(uc, hReadPipe, &read_handle_32, sizeof(uint32_t));
|
||||
uc_mem_write(uc, hWritePipe, &write_handle_32, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 设置返回值为TRUE
|
||||
uint64_t result = 1;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf(
|
||||
"[*] CreatePipe: Name=%s, ReadHandle=0x%llx, WriteHandle=0x%llx, "
|
||||
"Size=%u\n",
|
||||
pipeName, read_handle, write_handle, nSize);
|
||||
}
|
||||
784
ai_anti_malware/sandbox_api_process.cpp
Normal file
784
ai_anti_malware/sandbox_api_process.cpp
Normal file
@@ -0,0 +1,784 @@
|
||||
#include "sandbox.h"
|
||||
#include "sandbox_callbacks.h"
|
||||
#include "sandbox_api_winhttp.h"
|
||||
#include <tlhelp32.h>
|
||||
|
||||
// 内部实现函数,处理实际的模块句柄获取逻辑
|
||||
auto GetModuleHandleInternal(void* sandbox, const std::wstring& moduleName)
|
||||
-> HMODULE {
|
||||
auto* sb = static_cast<Sandbox*>(sandbox);
|
||||
|
||||
// 如果模块名为空,返回当前进程的基址
|
||||
if (moduleName.empty()) {
|
||||
return reinterpret_cast<HMODULE>(sb->GetPeInfo()->RecImageBase);
|
||||
}
|
||||
|
||||
// 在已加载的模块中查找
|
||||
for (const auto& module : sb->GetModuleList()) {
|
||||
std::string currentModuleNameA = module->name;
|
||||
std::wstring currentModuleName =
|
||||
std::wstring(currentModuleNameA.begin(), currentModuleNameA.end());
|
||||
if (_wcsicmp(currentModuleName.c_str(), moduleName.c_str()) == 0) {
|
||||
return reinterpret_cast<HMODULE>(module->base);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// GetModuleHandleA的实现
|
||||
auto Api_GetModuleHandleA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto* sb = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t esp = 0, rsp = 0;
|
||||
HMODULE result = nullptr;
|
||||
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
// 获取第一个参数 (rcx)
|
||||
uint64_t moduleNamePtr;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &moduleNamePtr);
|
||||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||
|
||||
std::string moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取ANSI字符串
|
||||
char ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + i, &ch, 1) != UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 转换为宽字符
|
||||
std::wstring wModuleName;
|
||||
if (!moduleName.empty()) {
|
||||
wModuleName = std::wstring(moduleName.begin(), moduleName.end());
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, wModuleName);
|
||||
|
||||
// 设置返回值
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
|
||||
} else {
|
||||
// 32位实现
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
uint32_t moduleNamePtr;
|
||||
uc_mem_read(uc, esp + 4, &moduleNamePtr, sizeof(moduleNamePtr));
|
||||
|
||||
std::string moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取ANSI字符串
|
||||
char ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + i, &ch, 1) != UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 转换为宽字符
|
||||
std::wstring wModuleName;
|
||||
if (!moduleName.empty()) {
|
||||
wModuleName = std::wstring(moduleName.begin(), moduleName.end());
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, wModuleName);
|
||||
|
||||
// 设置返回值
|
||||
uint32_t result32 = reinterpret_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = result ? 0 : ERROR_MOD_NOT_FOUND;
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
sb->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
sb->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
// GetModuleHandleW的实现
|
||||
auto Api_GetModuleHandleW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto* sb = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t esp = 0, rsp = 0;
|
||||
HMODULE result = nullptr;
|
||||
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
// 获取第一个参数 (rcx)
|
||||
uint64_t moduleNamePtr;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &moduleNamePtr);
|
||||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||
|
||||
std::wstring moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取宽字符串
|
||||
wchar_t ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + (i * 2), &ch, 2) !=
|
||||
UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, moduleName);
|
||||
|
||||
// 设置返回值
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
|
||||
} else {
|
||||
// 32位实现
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
uint32_t moduleNamePtr;
|
||||
uc_mem_read(uc, esp + 4, &moduleNamePtr, sizeof(moduleNamePtr));
|
||||
|
||||
std::wstring moduleName;
|
||||
if (moduleNamePtr != 0) {
|
||||
// 读取宽字符串
|
||||
wchar_t ch;
|
||||
size_t i = 0;
|
||||
do {
|
||||
if (uc_mem_read(uc, moduleNamePtr + (i * 2), &ch, 2) !=
|
||||
UC_ERR_OK) {
|
||||
break;
|
||||
}
|
||||
if (ch == 0) break;
|
||||
moduleName += ch;
|
||||
i++;
|
||||
} while (i < MAX_PATH);
|
||||
}
|
||||
|
||||
// 获取模块句柄
|
||||
result = GetModuleHandleInternal(sandbox, moduleName);
|
||||
|
||||
// 设置返回值
|
||||
uint32_t result32 = reinterpret_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = result ? 0 : ERROR_MOD_NOT_FOUND;
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
sb->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
sb->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
auto Api_VirtualQuery(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto* context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpAddress = 0;
|
||||
uint64_t lpBuffer = 0;
|
||||
uint32_t dwLength = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// 64位参数获取
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpAddress);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lpBuffer);
|
||||
uint64_t temp_length = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &temp_length);
|
||||
dwLength = static_cast<uint32_t>(temp_length);
|
||||
} else {
|
||||
// 32位参数获取
|
||||
uint32_t esp = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 0x4; // 跳过返回地址
|
||||
|
||||
uint32_t temp_address = 0;
|
||||
uint32_t temp_buffer = 0;
|
||||
uc_mem_read(uc, esp, &temp_address, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x4, &temp_buffer, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x8, &dwLength, sizeof(uint32_t));
|
||||
|
||||
lpAddress = temp_address;
|
||||
lpBuffer = temp_buffer;
|
||||
}
|
||||
|
||||
// 构造MEMORY_BASIC_INFORMATION结构
|
||||
MEMORY_BASIC_INFORMATION mbi = {};
|
||||
mbi.BaseAddress =
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(lpAddress));
|
||||
mbi.AllocationBase = mbi.BaseAddress;
|
||||
mbi.AllocationProtect = PAGE_EXECUTE_READWRITE; // 默认保护属性
|
||||
mbi.RegionSize = 0x1000; // 默认页大小
|
||||
mbi.State = MEM_COMMIT;
|
||||
mbi.Protect = PAGE_EXECUTE_READWRITE;
|
||||
mbi.Type = MEM_PRIVATE;
|
||||
|
||||
// 写入查询结果
|
||||
uint64_t return_value = 0;
|
||||
if (lpBuffer != 0 && dwLength >= sizeof(MEMORY_BASIC_INFORMATION)) {
|
||||
uc_mem_write(uc, lpBuffer, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
return_value = sizeof(MEMORY_BASIC_INFORMATION);
|
||||
}
|
||||
|
||||
// 设置返回值
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &return_value);
|
||||
} else {
|
||||
uint32_t return_value_32 = static_cast<uint32_t>(return_value);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &return_value_32);
|
||||
}
|
||||
}
|
||||
|
||||
auto Api_Process32FirstW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto* context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t hSnapshot = 0;
|
||||
uint64_t lppe = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = hSnapshot, rdx = lppe (LPPROCESSENTRY32W)
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &hSnapshot);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lppe);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 0x4; // 跳过返回地址
|
||||
uint32_t temp_handle;
|
||||
uint32_t temp_lppe;
|
||||
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x4, &temp_lppe, sizeof(uint32_t));
|
||||
hSnapshot = temp_handle;
|
||||
lppe = temp_lppe;
|
||||
}
|
||||
|
||||
// 验证句柄
|
||||
bool success = false;
|
||||
if (hSnapshot == 0x1337) { // 我们在CreateToolhelp32Snapshot中使用的魔数
|
||||
// 读取结构体大小
|
||||
DWORD structSize = 0;
|
||||
if (uc_mem_read(uc, lppe, &structSize, sizeof(DWORD)) == UC_ERR_OK) {
|
||||
if (structSize == sizeof(PROCESSENTRY32W)) {
|
||||
// 获取第一个进程信息(在我们的实现中是DingTalk.exe)
|
||||
PROCESSENTRY32W pe32 = {0};
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32W);
|
||||
pe32.th32ProcessID = 1001; // DingTalk的PID
|
||||
pe32.cntThreads = 1;
|
||||
pe32.th32ParentProcessID = 4; // 父进程是System
|
||||
pe32.pcPriClassBase = 8; // 正常优先级
|
||||
|
||||
// 设置进程名
|
||||
std::wstring procName = L"DingTalk.exe";
|
||||
wcscpy_s(pe32.szExeFile, procName.c_str());
|
||||
|
||||
// 写入进程信息到用户提供的缓冲区
|
||||
if (uc_mem_write(uc, lppe, &pe32, sizeof(PROCESSENTRY32W)) ==
|
||||
UC_ERR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] Process32FirstW: Handle=0x%llx, Buffer=0x%llx, Success=%d\n",
|
||||
hSnapshot, lppe, success);
|
||||
|
||||
// 设置返回值
|
||||
uint64_t result = success ? 1 : 0;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
} else {
|
||||
uint32_t result32 = static_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = success ? 0 : ERROR_NO_MORE_FILES;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
auto Api_CreateToolhelp32Snapshot(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto* context = static_cast<Sandbox*>(sandbox);
|
||||
uint32_t dwFlags = 0;
|
||||
uint32_t th32ProcessID = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = dwFlags, rdx = th32ProcessID
|
||||
uint64_t temp_flags;
|
||||
uint64_t temp_pid;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_flags);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_pid);
|
||||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||||
th32ProcessID = static_cast<uint32_t>(temp_pid);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp, &dwFlags, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x4, &th32ProcessID, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 创建一个假的句柄值
|
||||
uint64_t handle = 0x1337;
|
||||
|
||||
// 如果请求进程列表快照,初始化进程枚举状态
|
||||
if (dwFlags & TH32CS_SNAPPROCESS) {
|
||||
// 初始化进程枚举状态为-1,这样Process32First会返回第一个进程
|
||||
context->process_enum_state[handle] = -1;
|
||||
|
||||
// 清除错误码
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = 0;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf(
|
||||
"[*] CreateToolhelp32Snapshot: Flags=0x%x, ProcessID=0x%x, "
|
||||
"Handle=0x%llx\n",
|
||||
dwFlags, th32ProcessID, handle);
|
||||
|
||||
// 返回句柄
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &handle);
|
||||
} else {
|
||||
uint32_t handle32 = static_cast<uint32_t>(handle);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &handle32);
|
||||
}
|
||||
}
|
||||
auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto* context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t hSnapshot = 0;
|
||||
uint64_t lppe = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = hSnapshot, rdx = lppe (LPPROCESSENTRY32W)
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &hSnapshot);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lppe);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 0x4; // 跳过返回地址
|
||||
uint32_t temp_handle;
|
||||
uint32_t temp_lppe;
|
||||
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp + 0x4, &temp_lppe, sizeof(uint32_t));
|
||||
hSnapshot = temp_handle;
|
||||
lppe = temp_lppe;
|
||||
}
|
||||
|
||||
// 验证句柄
|
||||
bool success = false;
|
||||
if (hSnapshot == 0x1337) { // 我们在CreateToolhelp32Snapshot中使用的魔数
|
||||
// 读取结构体大小
|
||||
DWORD structSize = 0;
|
||||
if (uc_mem_read(uc, lppe, &structSize, sizeof(DWORD)) == UC_ERR_OK) {
|
||||
if (structSize == sizeof(PROCESSENTRY32W)) {
|
||||
// 获取当前进程索引
|
||||
size_t currentIndex = 0;
|
||||
auto it = context->process_enum_state.find(hSnapshot);
|
||||
if (it != context->process_enum_state.end()) {
|
||||
currentIndex = it->second;
|
||||
currentIndex++; // 移动到下一个进程
|
||||
}
|
||||
|
||||
// 定义进程列表
|
||||
struct ProcessInfo {
|
||||
const wchar_t* name;
|
||||
uint32_t pid;
|
||||
uint32_t parentPid;
|
||||
};
|
||||
|
||||
ProcessInfo processes[] = {
|
||||
{L"DingTalk.exe", 1001, 4}, // 钉钉
|
||||
{L"Lanxin.exe", 1002, 4}, // 蓝信
|
||||
{L"QQ.exe", 1003, 4}, // QQ
|
||||
{L"Feishu.exe", 1004, 4}, // 飞书
|
||||
{L"explorer.exe", 1005, 4}, // Windows 资源管理器
|
||||
{L"svchost.exe", 1006, 4}, // 系统服务宿主进程
|
||||
{L"System", 4, 0}, // 系统进程
|
||||
{L"smss.exe", 376, 4}, // 会话管理器
|
||||
{L"csrss.exe", 648, 376}, // 客户端服务器运行时子系统
|
||||
{L"winlogon.exe", 672, 376}, // Windows 登录进程
|
||||
};
|
||||
|
||||
const size_t processCount =
|
||||
sizeof(processes) / sizeof(processes[0]);
|
||||
|
||||
// 检查是否还有更多进程
|
||||
if (currentIndex < processCount) {
|
||||
// 填充进程信息
|
||||
PROCESSENTRY32W pe32 = {0};
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32W);
|
||||
pe32.th32ProcessID = processes[currentIndex].pid;
|
||||
pe32.th32ParentProcessID =
|
||||
processes[currentIndex].parentPid;
|
||||
pe32.cntThreads = 1;
|
||||
pe32.pcPriClassBase = 8; // 正常优先级
|
||||
|
||||
// 设置进程名
|
||||
wcscpy_s(pe32.szExeFile, processes[currentIndex].name);
|
||||
|
||||
// 写入进程信息到用户提供的缓冲区
|
||||
if (uc_mem_write(uc, lppe, &pe32,
|
||||
sizeof(PROCESSENTRY32W)) == UC_ERR_OK) {
|
||||
success = true;
|
||||
// 更新进程索引
|
||||
context->process_enum_state[hSnapshot] = currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] Process32NextW: Handle=0x%llx, Buffer=0x%llx, Success=%d\n",
|
||||
hSnapshot, lppe, success);
|
||||
|
||||
// 设置返回值
|
||||
uint64_t result = success ? 1 : 0;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
} else {
|
||||
uint32_t result32 = static_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = success ? 0 : ERROR_NO_MORE_FILES;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
auto Api_CreateProcessA(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpApplicationName = 0;
|
||||
uint64_t lpCommandLine = 0;
|
||||
uint64_t lpProcessInformation = 0;
|
||||
uint64_t lpStartupInfo = 0;
|
||||
|
||||
// 获取参数
|
||||
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(
|
||||
"[*] CreateProcessA 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(
|
||||
"[*] CreateProcessA Debug (x86): ESP=0x%x, AppNameAddr=0x%x, "
|
||||
"CmdLineAddr=0x%x\n",
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
// 确保字符串以 NULL 结尾
|
||||
buffer[i] = 0;
|
||||
|
||||
if (success) {
|
||||
applicationName = std::string(buffer);
|
||||
printf("[*] Read ApplicationName: %s (Length: %zu)\n", buffer,
|
||||
applicationName.length());
|
||||
}
|
||||
}
|
||||
|
||||
// 读取命令行
|
||||
std::string commandLine;
|
||||
if (lpCommandLine != 0) {
|
||||
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;
|
||||
}
|
||||
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 {
|
||||
HANDLE64 hProcess;
|
||||
HANDLE64 hThread;
|
||||
DWORD dwProcessId;
|
||||
DWORD dwThreadId;
|
||||
} pi;
|
||||
pi.hProcess = (HANDLE64)hProcess;
|
||||
pi.hThread = (HANDLE64)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;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
}
|
||||
|
||||
auto Api_GetCurrentProcess(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
|
||||
// GetCurrentProcess 总是返回伪句柄值 -1 (0xFFFFFFFF)
|
||||
uint64_t pseudo_handle = static_cast<uint64_t>(-1);
|
||||
|
||||
// 根据架构写入返回值
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&pseudo_handle);
|
||||
|
||||
printf("[*] GetCurrentProcess called, returning pseudo-handle 0x%llx\n",
|
||||
pseudo_handle);
|
||||
}
|
||||
|
||||
auto Api_OpenProcessToken(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t ProcessHandle = 0;
|
||||
uint32_t DesiredAccess = 0;
|
||||
uint64_t TokenHandle = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = ProcessHandle, rdx = DesiredAccess, r8 = TokenHandle
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &ProcessHandle);
|
||||
uint64_t temp_access;
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_access);
|
||||
DesiredAccess = static_cast<uint32_t>(temp_access);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &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));
|
||||
ProcessHandle = temp_handle;
|
||||
esp_address += 0x4;
|
||||
|
||||
uc_mem_read(uc, esp_address, &DesiredAccess, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
|
||||
uint32_t temp_token;
|
||||
uc_mem_read(uc, esp_address, &temp_token, sizeof(uint32_t));
|
||||
TokenHandle = temp_token;
|
||||
}
|
||||
|
||||
// 创建一个假的token句柄(使用一个非零值)
|
||||
uint64_t fake_token_handle = 0x1234;
|
||||
|
||||
// 将假的token句柄写入TokenHandle指向的内存
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// 返回TRUE
|
||||
uint64_t result = 1;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf(
|
||||
"[*] OpenProcessToken: ProcessHandle=0x%llx, DesiredAccess=0x%x, "
|
||||
"TokenHandle=0x%llx\n",
|
||||
ProcessHandle, DesiredAccess, fake_token_handle);
|
||||
}
|
||||
|
||||
auto Api_GetTokenInformation(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t TokenHandle = 0;
|
||||
uint32_t TokenInformationClass = 0;
|
||||
uint64_t TokenInformation = 0;
|
||||
uint32_t TokenInformationLength = 0;
|
||||
uint64_t ReturnLength = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx, rdx, r8, r9, [rsp+0x28]
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &TokenHandle);
|
||||
uint64_t temp_class;
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_class);
|
||||
TokenInformationClass = static_cast<uint32_t>(temp_class);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &TokenInformation);
|
||||
uint64_t temp_length;
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &temp_length);
|
||||
TokenInformationLength = static_cast<uint32_t>(temp_length);
|
||||
|
||||
uint64_t rsp;
|
||||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||
uc_mem_read(uc, rsp + 0x28, &ReturnLength, sizeof(uint64_t));
|
||||
} 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));
|
||||
TokenHandle = temp_handle;
|
||||
esp_address += 0x4;
|
||||
|
||||
uc_mem_read(uc, esp_address, &TokenInformationClass, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
|
||||
uint32_t temp_info;
|
||||
uc_mem_read(uc, esp_address, &temp_info, sizeof(uint32_t));
|
||||
TokenInformation = temp_info;
|
||||
esp_address += 0x4;
|
||||
|
||||
uc_mem_read(uc, esp_address, &TokenInformationLength, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
|
||||
uint32_t temp_return;
|
||||
uc_mem_read(uc, esp_address, &temp_return, sizeof(uint32_t));
|
||||
ReturnLength = temp_return;
|
||||
}
|
||||
|
||||
// 如果是TokenElevation类(20),返回TRUE表示进程有管理员权限
|
||||
if (TokenInformationClass == 20) { // TokenElevation
|
||||
uint32_t is_elevated = 1; // 1表示有管理员权限
|
||||
if (TokenInformation != 0 &&
|
||||
TokenInformationLength >= sizeof(uint32_t)) {
|
||||
uc_mem_write(uc, TokenInformation, &is_elevated, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 写入所需的缓冲区大小
|
||||
uint32_t required_size = sizeof(uint32_t);
|
||||
if (ReturnLength != 0) {
|
||||
uc_mem_write(uc, ReturnLength, &required_size, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
// 返回TRUE
|
||||
uint64_t result = 1;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf(
|
||||
"[*] GetTokenInformation: TokenHandle=0x%llx, Class=%d, Info=0x%llx, "
|
||||
"Length=%u\n",
|
||||
TokenHandle, TokenInformationClass, TokenInformation,
|
||||
TokenInformationLength);
|
||||
}
|
||||
@@ -1,6 +1,457 @@
|
||||
#include "sandbox.h"
|
||||
#include "sandbox_callbacks.h"
|
||||
|
||||
void Api_GetLastError(void* sandbox, uc_engine* uc, uint64_t address) {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
DWORD last_error = 0;
|
||||
|
||||
// 从TEB中获取LastError
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
last_error = context->GetTeb64()->LastErrorValue;
|
||||
} else {
|
||||
last_error = context->GetTeb32()->LastErrorValue;
|
||||
}
|
||||
|
||||
printf("[*] GetLastError: LastError=0x%x\n", last_error);
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&last_error);
|
||||
}
|
||||
auto Api_InitializeCriticalSectionAndSpinCount(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpCriticalSection = 0;
|
||||
uint32_t dwSpinCount = 0;
|
||||
BOOL success = TRUE; // 默认返回成功
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpCriticalSection, rdx = dwSpinCount
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||||
uint64_t temp_spin_count = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_spin_count);
|
||||
dwSpinCount = static_cast<uint32_t>(temp_spin_count);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uint32_t temp_cs = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||||
lpCriticalSection = temp_cs;
|
||||
esp_address += 0x4;
|
||||
uc_mem_read(uc, esp_address, &dwSpinCount, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (lpCriticalSection != 0) {
|
||||
// 初始化关键段结构
|
||||
RTL_CRITICAL_SECTION cs = {0};
|
||||
cs.LockCount = -1; // 初始未锁定状态
|
||||
cs.RecursionCount = 0; // 初始递归计数为0
|
||||
cs.SpinCount = dwSpinCount; // 设置自旋计数
|
||||
cs.OwningThread = 0; // 初始无拥有线程
|
||||
cs.LockSemaphore = 0; // 初始信号量为0
|
||||
|
||||
// 写入初始化后的结构到目标内存
|
||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
} else {
|
||||
success = FALSE;
|
||||
// 设置LastError
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf(
|
||||
"[*] InitializeCriticalSectionAndSpinCount: CS=0x%llx, SpinCount=0x%x, "
|
||||
"Success=%d\n",
|
||||
lpCriticalSection, dwSpinCount, success);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&success);
|
||||
}
|
||||
|
||||
auto Api_InitializeCriticalSectionEx(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpCriticalSection = 0;
|
||||
uint32_t dwSpinCount = 0;
|
||||
uint32_t dwFlags = 0;
|
||||
BOOL success = TRUE; // 默认返回成功
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpCriticalSection, rdx = dwSpinCount, r8 = dwFlags
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||||
uint64_t temp_spin_count = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &temp_spin_count);
|
||||
dwSpinCount = static_cast<uint32_t>(temp_spin_count);
|
||||
uint64_t temp_flags = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &temp_flags);
|
||||
dwFlags = static_cast<uint32_t>(temp_flags);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uint32_t temp_cs = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||||
lpCriticalSection = temp_cs;
|
||||
esp_address += 0x4;
|
||||
uc_mem_read(uc, esp_address, &dwSpinCount, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
uc_mem_read(uc, esp_address, &dwFlags, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (lpCriticalSection != 0) {
|
||||
// 初始化关键段结构
|
||||
RTL_CRITICAL_SECTION cs = {0};
|
||||
cs.LockCount = -1; // 初始未锁定状态
|
||||
cs.RecursionCount = 0; // 初始递归计数为0
|
||||
cs.SpinCount = dwSpinCount; // 设置自旋计数
|
||||
cs.OwningThread = 0; // 初始无拥有线程
|
||||
cs.LockSemaphore = 0; // 初始信号量为0
|
||||
|
||||
// 处理特殊标志
|
||||
// CRITICAL_SECTION_FLAG_NO_DEBUG_INFO = 0x01000000
|
||||
// CRITICAL_SECTION_FLAG_DYNAMIC_SPIN = 0x02000000
|
||||
// CRITICAL_SECTION_FLAG_STATIC_INIT = 0x04000000
|
||||
// CRITICAL_SECTION_FLAG_RESOURCE_TYPE = 0x08000000
|
||||
// CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO = 0x10000000
|
||||
|
||||
// 写入初始化后的结构到目标内存
|
||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
} else {
|
||||
success = FALSE;
|
||||
// 设置LastError
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf(
|
||||
"[*] InitializeCriticalSectionEx: CS=0x%llx, SpinCount=0x%x, "
|
||||
"Flags=0x%x, "
|
||||
"Success=%d\n",
|
||||
lpCriticalSection, dwSpinCount, dwFlags, success);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&success);
|
||||
}
|
||||
|
||||
auto Api_TlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
DWORD tls_index = TLS_OUT_OF_INDEXES; // 默认返回失败值
|
||||
|
||||
// 获取TEB结构
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
auto teb = context->GetTeb64();
|
||||
// 在TLS槽中查找第一个可用的位置
|
||||
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
|
||||
if (teb->TlsSlots[i] == (void*)0x1337ffffff) {
|
||||
teb->TlsSlots[i] = (void*)0; // 标记为已使用
|
||||
tls_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto teb = context->GetTeb32();
|
||||
// 在TLS槽中查找第一个可用的位置
|
||||
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
|
||||
if (teb->TlsSlots[i] == 0x1337) {
|
||||
teb->TlsSlots[i] = 0; // 标记为已使用
|
||||
tls_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tls_index == TLS_OUT_OF_INDEXES) {
|
||||
// 设置LastError为没有可用的TLS索引
|
||||
DWORD error = ERROR_NO_MORE_ITEMS;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] TlsAlloc: Allocated TLS Index=0x%x\n", tls_index);
|
||||
|
||||
// 返回分配的TLS索引
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&tls_index);
|
||||
}
|
||||
auto Api_TlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint32_t dwTlsIndex = 0;
|
||||
uint64_t lpTlsValue = 0;
|
||||
BOOL success = FALSE;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = dwTlsIndex, rdx = lpTlsValue
|
||||
uint64_t temp_index;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_index);
|
||||
dwTlsIndex = static_cast<uint32_t>(temp_index);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lpTlsValue);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &dwTlsIndex, sizeof(uint32_t));
|
||||
esp_address += 0x4;
|
||||
uint32_t temp_value;
|
||||
uc_mem_read(uc, esp_address, &temp_value, sizeof(uint32_t));
|
||||
lpTlsValue = temp_value;
|
||||
}
|
||||
|
||||
// 检查索引是否有效(小于64)
|
||||
if (dwTlsIndex < 64) {
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
auto teb = context->GetTeb64();
|
||||
// 检查槽是否已分配(不为nullptr)
|
||||
if (teb->TlsSlots[dwTlsIndex] != (void*)0x1337ffffff) {
|
||||
teb->TlsSlots[dwTlsIndex] = (void*)lpTlsValue;
|
||||
success = TRUE;
|
||||
}
|
||||
} else {
|
||||
auto teb = context->GetTeb32();
|
||||
// 检查槽是否已分配(不为0)
|
||||
if (teb->TlsSlots[dwTlsIndex] != 0x1337) {
|
||||
teb->TlsSlots[dwTlsIndex] = static_cast<uint32_t>(lpTlsValue);
|
||||
success = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// 设置LastError
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] TlsSetValue: Index=0x%x, Value=0x%llx, Success=%d\n",
|
||||
dwTlsIndex, lpTlsValue, success);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&success);
|
||||
}
|
||||
auto Api_DeleteCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t lpCriticalSection = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = lpCriticalSection
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &lpCriticalSection);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uint32_t temp_cs = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &temp_cs, sizeof(uint32_t));
|
||||
lpCriticalSection = temp_cs;
|
||||
}
|
||||
|
||||
if (lpCriticalSection != 0) {
|
||||
// 读取现有的关键段结构
|
||||
RTL_CRITICAL_SECTION cs;
|
||||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
|
||||
// 检查是否有线程仍在等待
|
||||
if (cs.LockCount >= 0) {
|
||||
// 有线程正在等待,设置错误
|
||||
DWORD error = ERROR_SEM_IS_SET;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
// 清零内存,表示删除
|
||||
memset(&cs, 0, sizeof(RTL_CRITICAL_SECTION));
|
||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
||||
}
|
||||
|
||||
printf("[*] DeleteCriticalSection: CS=0x%llx\n", lpCriticalSection);
|
||||
}
|
||||
|
||||
auto Api_IsProcessorFeaturePresent(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint32_t feature_number = 0;
|
||||
BOOL is_supported = FALSE;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = FeatureNumber
|
||||
uint64_t temp_feature;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_feature);
|
||||
feature_number = static_cast<uint32_t>(temp_feature);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &feature_number, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 模拟一些常见的处理器特性
|
||||
switch (feature_number) {
|
||||
case PF_FLOATING_POINT_PRECISION_ERRATA: // 0
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
case PF_FLOATING_POINT_EMULATED: // 1
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
case PF_COMPARE_EXCHANGE_DOUBLE: // 2
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_MMX_INSTRUCTIONS_AVAILABLE: // 3
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_XMMI_INSTRUCTIONS_AVAILABLE: // 6
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_3DNOW_INSTRUCTIONS_AVAILABLE: // 7
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
case PF_RDTSC_INSTRUCTION_AVAILABLE: // 8
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_PAE_ENABLED: // 9
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_XMMI64_INSTRUCTIONS_AVAILABLE: // 10
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_SSE_DAZ_MODE_AVAILABLE: // 11
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_NX_ENABLED: // 12
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_SSE3_INSTRUCTIONS_AVAILABLE: // 13
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_COMPARE_EXCHANGE128: // 14
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_XSAVE_ENABLED: // 17
|
||||
is_supported = TRUE;
|
||||
break;
|
||||
case PF_ARM_VFP_32_REGISTERS_AVAILABLE: // 18
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
default:
|
||||
is_supported = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("[*] IsProcessorFeaturePresent: Feature=0x%x, Supported=%d\n",
|
||||
feature_number, is_supported);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&is_supported);
|
||||
}
|
||||
|
||||
auto Api___set_app_type(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
int32_t appType = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = appType
|
||||
uint64_t temp_type;
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &temp_type);
|
||||
appType = static_cast<int32_t>(temp_type);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uc_mem_read(uc, esp_address, &appType, sizeof(int32_t));
|
||||
}
|
||||
|
||||
// 简单地返回0表示成功
|
||||
int32_t result = 0;
|
||||
printf("[*] __set_app_type: AppType=%d\n", appType);
|
||||
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
}
|
||||
|
||||
auto Api___p__fmode(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto sb = static_cast<Sandbox*>(sandbox);
|
||||
|
||||
// 检查是否已经创建了 _fmode 变量
|
||||
static uint64_t fmode_address = 0;
|
||||
static int32_t fmode_value = 0; // 默认为文本模式 (_O_TEXT)
|
||||
|
||||
if (fmode_address == 0) {
|
||||
// 为 _fmode 变量分配内存
|
||||
// 使用特定堆地址,与其他 API 一致
|
||||
uint64_t heap_handle =
|
||||
sb->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
||||
|
||||
// 在堆上分配空间
|
||||
HeapSegment* segment = nullptr;
|
||||
auto it = sb->m_heapSegments.find(heap_handle);
|
||||
if (it != sb->m_heapSegments.end()) {
|
||||
segment = it->second;
|
||||
} else {
|
||||
// 创建新的堆段
|
||||
segment = sb->CreateHeapSegment(heap_handle, 0x10000);
|
||||
sb->m_heapSegments[heap_handle] = segment;
|
||||
}
|
||||
|
||||
if (segment) {
|
||||
fmode_address = sb->AllocateFromSegment(segment, sizeof(int32_t));
|
||||
if (fmode_address) {
|
||||
// 初始化 _fmode 为文本模式
|
||||
uc_mem_write(uc, fmode_address, &fmode_value, sizeof(int32_t));
|
||||
printf(
|
||||
"[*] __p__fmode: Allocated _fmode at 0x%llx with value "
|
||||
"%d\n",
|
||||
fmode_address, fmode_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 返回 _fmode 变量的地址
|
||||
printf("[*] __p__fmode: Returning address 0x%llx\n", fmode_address);
|
||||
|
||||
// 设置返回值
|
||||
if (sb->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &fmode_address);
|
||||
} else {
|
||||
uint32_t eax = static_cast<uint32_t>(fmode_address);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &eax);
|
||||
}
|
||||
}
|
||||
|
||||
// 实现 AreFileApisANSI API
|
||||
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
@@ -687,18 +1138,21 @@ auto Api_HeapAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
uc_mem_read(uc, esp_address, &temp_bytes, sizeof(uint32_t));
|
||||
dwBytes = temp_bytes;
|
||||
}
|
||||
|
||||
// 这里如果想检查有效,得先跑main,再跑其他的,浪费时间了,操
|
||||
|
||||
// 检查堆句柄是否有效
|
||||
/*
|
||||
uint64_t expected_handle =
|
||||
context->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
||||
if (hHeap != expected_handle) {
|
||||
uint64_t null_ptr = 0;
|
||||
hHeap = expected_handle;
|
||||
uc_reg_write(
|
||||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&null_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
// 获取或创建堆段
|
||||
HeapSegment* segment = nullptr;
|
||||
auto it = context->m_heapSegments.find(hHeap);
|
||||
@@ -1512,4 +1966,162 @@ auto Sandbox::AllocateFromSegment(HeapSegment* segment, size_t size)
|
||||
}
|
||||
|
||||
return 0; // 分配失败
|
||||
}
|
||||
}
|
||||
|
||||
auto Api_CloseHandle(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t handle = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = handle
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &handle);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp = 0;
|
||||
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));
|
||||
handle = temp_handle;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
// 如果是进程快照句柄 (0x1337),清理进程枚举状态
|
||||
if (handle == 0x1337) {
|
||||
auto it = context->process_enum_state.find(handle);
|
||||
if (it != context->process_enum_state.end()) {
|
||||
context->process_enum_state.erase(it);
|
||||
}
|
||||
}
|
||||
// 其他类型的句柄也返回成功
|
||||
// 实际应用中可能需要根据句柄类型进行不同的处理
|
||||
|
||||
printf("[*] CloseHandle: Handle=0x%llx, Success=%d\n", handle, success);
|
||||
|
||||
// 设置返回值
|
||||
uint64_t result = success ? 1 : 0;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||
} else {
|
||||
uint32_t result32 = static_cast<uint32_t>(result);
|
||||
uc_reg_write(uc, UC_X86_REG_EAX, &result32);
|
||||
}
|
||||
|
||||
// 设置错误码
|
||||
DWORD error = success ? 0 : ERROR_INVALID_HANDLE;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加RtlFormatCurrentUserKeyPath API实现
|
||||
auto Api_RtlFormatCurrentUserKeyPath(void* sandbox, uc_engine* uc,
|
||||
uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t keyPathBuffer = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = KeyPathBuffer
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &keyPathBuffer);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uint32_t temp_buffer;
|
||||
uc_mem_read(uc, esp_address, &temp_buffer, sizeof(uint32_t));
|
||||
keyPathBuffer = temp_buffer;
|
||||
}
|
||||
|
||||
// 构造当前用户的注册表路径
|
||||
// 同时在这里实现查询MCP服务器的功能
|
||||
wchar_t userKeyPath[256] =
|
||||
L"\\Registry\\User\\S-1-5-21-1234567890-1234567890-1234567890-1001";
|
||||
|
||||
// 模拟查询MCP服务器,这里可以根据需要实现实际的服务器查询
|
||||
// 例如可以修改userKeyPath或在日志中记录查询操作
|
||||
printf("[*] RtlFormatCurrentUserKeyPath: 正在查询MCP服务器获取用户SID\n");
|
||||
|
||||
// 将路径写入到提供的缓冲区
|
||||
if (keyPathBuffer != 0) {
|
||||
uc_mem_write(uc, keyPathBuffer, userKeyPath,
|
||||
(wcslen(userKeyPath) + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
// 返回NTSTATUS成功代码 (0x00000000 = STATUS_SUCCESS)
|
||||
uint64_t status = 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&status);
|
||||
|
||||
printf("[*] RtlFormatCurrentUserKeyPath: Buffer=0x%llx, Path=%ls\n",
|
||||
keyPathBuffer, userKeyPath);
|
||||
}
|
||||
|
||||
// 添加FlsSetValue API实现
|
||||
auto Api_FlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t dwFlsIndex = 0;
|
||||
uint64_t lpFlsData = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
// x64: rcx = dwFlsIndex, rdx = lpFlsData
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &dwFlsIndex);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &lpFlsData);
|
||||
} else {
|
||||
// x86: 从栈上读取参数
|
||||
uint32_t esp_address = 0;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||
esp_address += 0x4; // 跳过返回地址
|
||||
uint32_t temp_index;
|
||||
uint32_t temp_data;
|
||||
uc_mem_read(uc, esp_address, &temp_index, sizeof(uint32_t));
|
||||
uc_mem_read(uc, esp_address + 0x4, &temp_data, sizeof(uint32_t));
|
||||
dwFlsIndex = temp_index;
|
||||
lpFlsData = temp_data;
|
||||
}
|
||||
|
||||
// 模拟FLS存储操作,类似于TLS存储
|
||||
bool success = false;
|
||||
if (dwFlsIndex < 64) { // 使用与TLS相同的槽位大小
|
||||
// 存储数据到模拟的FLS槽中(复用TLS槽)
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
auto teb = context->GetTeb64();
|
||||
if (teb->TlsSlots[dwFlsIndex] != (void*)0x1337ffffff) {
|
||||
teb->TlsSlots[dwFlsIndex] = (void*)lpFlsData;
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
auto teb = context->GetTeb32();
|
||||
if (teb->TlsSlots[dwFlsIndex] != 0x1337) {
|
||||
teb->TlsSlots[dwFlsIndex] = static_cast<uint32_t>(lpFlsData);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("[*] FlsSetValue: Index=%llu, Data=0x%llx, Success=%d\n", dwFlsIndex,
|
||||
lpFlsData, success);
|
||||
|
||||
// 设置返回值
|
||||
uint64_t result = success ? 1 : 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
// 如果失败,设置错误码
|
||||
if (!success) {
|
||||
DWORD error = ERROR_INVALID_PARAMETER;
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
context->GetTeb64()->LastErrorValue = error;
|
||||
} else {
|
||||
context->GetTeb32()->LastErrorValue = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
220
ai_anti_malware/sandbox_api_wfp.cpp
Normal file
220
ai_anti_malware/sandbox_api_wfp.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
#include "sandbox.h"
|
||||
#include "sandbox_callbacks.h"
|
||||
#include <fwpmu.h>
|
||||
|
||||
// FwpmEngineOpen0 API模拟
|
||||
auto Api_FwpmEngineOpen0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t serverName = 0;
|
||||
uint64_t authnService = 0;
|
||||
uint64_t authIdentity = 0;
|
||||
uint64_t session = 0;
|
||||
uint64_t engineHandle = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &serverName);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &authnService);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &authIdentity);
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &session);
|
||||
uint64_t rsp;
|
||||
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||
uc_mem_read(uc, rsp + 0x28, &engineHandle, sizeof(engineHandle));
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4; // 跳过返回地址
|
||||
uint32_t temp;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
serverName = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
authnService = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
authIdentity = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
session = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
engineHandle = temp;
|
||||
}
|
||||
|
||||
// 创建新的WFP引擎实例
|
||||
auto engine = new Sandbox::FakeWFPEngine();
|
||||
engine->isOpen = true;
|
||||
HANDLE handle = context->GetNextWfpEngineHandle();
|
||||
context->GetWfpEngines()[handle] = engine;
|
||||
|
||||
// 写回引擎句柄
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_mem_write(uc, engineHandle, &handle, sizeof(handle));
|
||||
} else {
|
||||
uint32_t handle32 = (uint32_t)(uint64_t)handle;
|
||||
uc_mem_write(uc, engineHandle, &handle32, sizeof(handle32));
|
||||
}
|
||||
|
||||
// 返回成功
|
||||
uint64_t result = ERROR_SUCCESS;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] FwpmEngineOpen0: Handle=0x%llx\n", (uint64_t)handle);
|
||||
}
|
||||
|
||||
// FwpmProviderAdd0 API模拟
|
||||
auto Api_FwpmProviderAdd0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t engineHandle = 0;
|
||||
uint64_t provider = 0;
|
||||
uint64_t sd = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &engineHandle);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &provider);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &sd);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
engineHandle = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
provider = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
sd = temp;
|
||||
}
|
||||
|
||||
// 检查引擎句柄是否有效
|
||||
auto& engines = context->GetWfpEngines();
|
||||
auto it = engines.find((HANDLE)engineHandle);
|
||||
if (it == engines.end()) {
|
||||
uint64_t result = ERROR_INVALID_HANDLE;
|
||||
uc_reg_write(
|
||||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加提供者
|
||||
FWPM_PROVIDER0 providerData;
|
||||
uc_mem_read(uc, provider, &providerData, sizeof(FWPM_PROVIDER0));
|
||||
it->second->providers.push_back(providerData);
|
||||
|
||||
// 返回成功
|
||||
uint64_t result = ERROR_SUCCESS;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] FwpmProviderAdd0: Handle=0x%llx\n", engineHandle);
|
||||
}
|
||||
|
||||
// FwpmFilterAdd0 API模拟
|
||||
auto Api_FwpmFilterAdd0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t engineHandle = 0;
|
||||
uint64_t filter = 0;
|
||||
uint64_t sd = 0;
|
||||
uint64_t id = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &engineHandle);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &filter);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &sd);
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &id);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
engineHandle = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
filter = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
sd = temp;
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
id = temp;
|
||||
}
|
||||
|
||||
// 检查引擎句柄是否有效
|
||||
auto& engines = context->GetWfpEngines();
|
||||
auto it = engines.find((HANDLE)engineHandle);
|
||||
if (it == engines.end()) {
|
||||
uint64_t result = ERROR_INVALID_HANDLE;
|
||||
uc_reg_write(
|
||||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加过滤器
|
||||
FWPM_FILTER0 filterData;
|
||||
uc_mem_read(uc, filter, &filterData, sizeof(FWPM_FILTER0));
|
||||
it->second->filters.push_back(filterData);
|
||||
|
||||
// 生成并写回过滤器ID
|
||||
static uint64_t nextFilterId = 1;
|
||||
uint64_t filterId = nextFilterId++;
|
||||
if (id != 0) {
|
||||
uc_mem_write(uc, id, &filterId, sizeof(filterId));
|
||||
}
|
||||
|
||||
// 返回成功
|
||||
uint64_t result = ERROR_SUCCESS;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] FwpmFilterAdd0: Handle=0x%llx, FilterId=0x%llx\n", engineHandle,
|
||||
filterId);
|
||||
}
|
||||
|
||||
// FwpmEngineClose0 API模拟
|
||||
auto Api_FwpmEngineClose0(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t engineHandle = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &engineHandle);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp;
|
||||
uc_mem_read(uc, esp, &temp, sizeof(temp));
|
||||
engineHandle = temp;
|
||||
}
|
||||
|
||||
// 检查并关闭引擎
|
||||
auto& engines = context->GetWfpEngines();
|
||||
auto it = engines.find((HANDLE)engineHandle);
|
||||
if (it != engines.end()) {
|
||||
delete it->second;
|
||||
engines.erase(it);
|
||||
}
|
||||
|
||||
// 返回成功
|
||||
uint64_t result = ERROR_SUCCESS;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] FwpmEngineClose0: Handle=0x%llx\n", engineHandle);
|
||||
}
|
||||
286
ai_anti_malware/sandbox_api_wlan.cpp
Normal file
286
ai_anti_malware/sandbox_api_wlan.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
#include "sandbox.h"
|
||||
#include "sandbox_callbacks.h"
|
||||
#include "sandbox_api_winhttp.h"
|
||||
#include <tlhelp32.h>
|
||||
|
||||
// WLAN API 实现
|
||||
auto Api_WlanOpenHandle(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t dwClientVersion = 0;
|
||||
uint64_t pReserved = 0;
|
||||
uint64_t pdwNegotiatedVersion = 0;
|
||||
uint64_t phClientHandle = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &dwClientVersion);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &pReserved);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &pdwNegotiatedVersion);
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &phClientHandle);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uc_mem_read(uc, esp, &dwClientVersion, sizeof(uint32_t));
|
||||
esp += 4;
|
||||
uint32_t temp_reserved;
|
||||
uc_mem_read(uc, esp, &temp_reserved, sizeof(uint32_t));
|
||||
pReserved = temp_reserved;
|
||||
esp += 4;
|
||||
uint32_t temp_version;
|
||||
uc_mem_read(uc, esp, &temp_version, sizeof(uint32_t));
|
||||
pdwNegotiatedVersion = temp_version;
|
||||
esp += 4;
|
||||
uint32_t temp_handle;
|
||||
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
|
||||
phClientHandle = temp_handle;
|
||||
}
|
||||
|
||||
// 修改常量定义
|
||||
uint32_t negotiatedVersion = 2; // 返回请求的版本
|
||||
uint64_t clientHandle = 0x13370000; // 使用有效的十六进制常量
|
||||
|
||||
// 写入协商版本
|
||||
if (pdwNegotiatedVersion != 0) {
|
||||
uc_mem_write(uc, pdwNegotiatedVersion, &negotiatedVersion,
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 写入客户端句柄
|
||||
if (phClientHandle != 0) {
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_mem_write(uc, phClientHandle, &clientHandle, sizeof(uint64_t));
|
||||
} else {
|
||||
uint32_t handle32 = static_cast<uint32_t>(clientHandle);
|
||||
uc_mem_write(uc, phClientHandle, &handle32, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
// 返回成功(0)
|
||||
uint64_t result = 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] WlanOpenHandle: Version=%u, Handle=0x%llx\n", negotiatedVersion,
|
||||
clientHandle);
|
||||
}
|
||||
|
||||
auto Api_WlanEnumInterfaces(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t hClientHandle = 0;
|
||||
uint64_t pReserved = 0;
|
||||
uint64_t ppInterfaceList = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &hClientHandle);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &pReserved);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &ppInterfaceList);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp_handle;
|
||||
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
|
||||
hClientHandle = temp_handle;
|
||||
esp += 4;
|
||||
uint32_t temp_reserved;
|
||||
uc_mem_read(uc, esp, &temp_reserved, sizeof(uint32_t));
|
||||
pReserved = temp_reserved;
|
||||
esp += 4;
|
||||
uint32_t temp_list;
|
||||
uc_mem_read(uc, esp, &temp_list, sizeof(uint32_t));
|
||||
ppInterfaceList = temp_list;
|
||||
}
|
||||
|
||||
// 修改句柄检查
|
||||
if (hClientHandle != 0x13370000) {
|
||||
uint64_t result = 1; // ERROR_INVALID_HANDLE
|
||||
uc_reg_write(
|
||||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
return;
|
||||
}
|
||||
|
||||
// 分配内存用于接口列表
|
||||
uint64_t interfaceListAddr = context->AllocateMemory(1024); // 足够大的空间
|
||||
|
||||
// 创建一个模拟的WLAN接口列表
|
||||
struct WLAN_INTERFACE_INFO {
|
||||
GUID InterfaceGuid;
|
||||
WCHAR strInterfaceDescription[256];
|
||||
DWORD isState;
|
||||
};
|
||||
|
||||
struct WLAN_INTERFACE_INFO_LIST {
|
||||
DWORD dwNumberOfItems;
|
||||
DWORD dwIndex;
|
||||
WLAN_INTERFACE_INFO InterfaceInfo[1];
|
||||
};
|
||||
|
||||
WLAN_INTERFACE_INFO_LIST interfaceList = {0};
|
||||
interfaceList.dwNumberOfItems = 1;
|
||||
interfaceList.dwIndex = 0;
|
||||
|
||||
// 创建一个假的GUID
|
||||
GUID fakeGuid = {0x12345678,
|
||||
0x1234,
|
||||
0x1234,
|
||||
{0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}};
|
||||
interfaceList.InterfaceInfo[0].InterfaceGuid = fakeGuid;
|
||||
|
||||
// 设置接口描述
|
||||
const wchar_t* description = L"Simulated Wi-Fi Adapter";
|
||||
wcscpy_s(interfaceList.InterfaceInfo[0].strInterfaceDescription,
|
||||
description);
|
||||
interfaceList.InterfaceInfo[0].isState = 1; // connected
|
||||
|
||||
// 写入接口列表
|
||||
uc_mem_write(uc, interfaceListAddr, &interfaceList,
|
||||
sizeof(WLAN_INTERFACE_INFO_LIST));
|
||||
|
||||
// 写入接口列表指针
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_mem_write(uc, ppInterfaceList, &interfaceListAddr, sizeof(uint64_t));
|
||||
} else {
|
||||
uint32_t addr32 = static_cast<uint32_t>(interfaceListAddr);
|
||||
uc_mem_write(uc, ppInterfaceList, &addr32, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 返回成功(0)
|
||||
uint64_t result = 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] WlanEnumInterfaces: Handle=0x%llx, InterfaceList=0x%llx\n",
|
||||
hClientHandle, interfaceListAddr);
|
||||
}
|
||||
|
||||
auto Api_WlanGetProfileList(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t hClientHandle = 0;
|
||||
uint64_t pInterfaceGuid = 0;
|
||||
uint64_t pReserved = 0;
|
||||
uint64_t ppProfileList = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &hClientHandle);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &pInterfaceGuid);
|
||||
uc_reg_read(uc, UC_X86_REG_R8, &pReserved);
|
||||
uc_reg_read(uc, UC_X86_REG_R9, &ppProfileList);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp_values[4];
|
||||
uc_mem_read(uc, esp, temp_values, sizeof(uint32_t) * 4);
|
||||
hClientHandle = temp_values[0];
|
||||
pInterfaceGuid = temp_values[1];
|
||||
pReserved = temp_values[2];
|
||||
ppProfileList = temp_values[3];
|
||||
}
|
||||
|
||||
// 分配内存用于配置文件列表
|
||||
uint64_t profileListAddr = context->AllocateMemory(1024);
|
||||
|
||||
// 创建模拟的配置文件列表
|
||||
struct WLAN_PROFILE_INFO {
|
||||
WCHAR strProfileName[256];
|
||||
DWORD dwFlags;
|
||||
};
|
||||
|
||||
struct WLAN_PROFILE_INFO_LIST {
|
||||
DWORD dwNumberOfItems;
|
||||
DWORD dwIndex;
|
||||
WLAN_PROFILE_INFO ProfileInfo[1];
|
||||
};
|
||||
|
||||
WLAN_PROFILE_INFO_LIST profileList = {0};
|
||||
profileList.dwNumberOfItems = 1;
|
||||
profileList.dwIndex = 0;
|
||||
|
||||
// 设置一个模拟的配置文件
|
||||
const wchar_t* profileName = L"Home Network";
|
||||
wcscpy_s(profileList.ProfileInfo[0].strProfileName, profileName);
|
||||
profileList.ProfileInfo[0].dwFlags = 1;
|
||||
|
||||
// 写入配置文件列表
|
||||
uc_mem_write(uc, profileListAddr, &profileList,
|
||||
sizeof(WLAN_PROFILE_INFO_LIST));
|
||||
|
||||
// 写入配置文件列表指针
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_mem_write(uc, ppProfileList, &profileListAddr, sizeof(uint64_t));
|
||||
} else {
|
||||
uint32_t addr32 = static_cast<uint32_t>(profileListAddr);
|
||||
uc_mem_write(uc, ppProfileList, &addr32, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// 返回成功(0)
|
||||
uint64_t result = 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] WlanGetProfileList: Handle=0x%llx, ProfileList=0x%llx\n",
|
||||
hClientHandle, profileListAddr);
|
||||
}
|
||||
|
||||
auto Api_WlanFreeMemory(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t pMemory = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &pMemory);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp_memory;
|
||||
uc_mem_read(uc, esp, &temp_memory, sizeof(uint32_t));
|
||||
pMemory = temp_memory;
|
||||
}
|
||||
|
||||
// 实际上我们不需要释放内存,因为这是在模拟环境中
|
||||
printf("[*] WlanFreeMemory: Memory=0x%llx\n", pMemory);
|
||||
}
|
||||
|
||||
auto Api_WlanCloseHandle(void* sandbox, uc_engine* uc, uint64_t address)
|
||||
-> void {
|
||||
auto context = static_cast<Sandbox*>(sandbox);
|
||||
uint64_t hClientHandle = 0;
|
||||
uint64_t pReserved = 0;
|
||||
|
||||
// 获取参数
|
||||
if (context->GetPeInfo()->isX64) {
|
||||
uc_reg_read(uc, UC_X86_REG_RCX, &hClientHandle);
|
||||
uc_reg_read(uc, UC_X86_REG_RDX, &pReserved);
|
||||
} else {
|
||||
uint32_t esp;
|
||||
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||
esp += 4;
|
||||
uint32_t temp_handle;
|
||||
uc_mem_read(uc, esp, &temp_handle, sizeof(uint32_t));
|
||||
hClientHandle = temp_handle;
|
||||
esp += 4;
|
||||
uint32_t temp_reserved;
|
||||
uc_mem_read(uc, esp, &temp_reserved, sizeof(uint32_t));
|
||||
pReserved = temp_reserved;
|
||||
}
|
||||
|
||||
// 返回成功(0)
|
||||
uint64_t result = 0;
|
||||
uc_reg_write(uc,
|
||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||
&result);
|
||||
|
||||
printf("[*] WlanCloseHandle: Handle=0x%llx\n", hClientHandle);
|
||||
}
|
||||
@@ -5,6 +5,7 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
||||
uint64_t currentRip = 0;
|
||||
uint64_t currentRsp = 0;
|
||||
uint64_t currentRax = 0;
|
||||
static uint64_t lastRip = 0;
|
||||
auto* sandbox = static_cast<Sandbox*>(userData);
|
||||
if (!sandbox) return;
|
||||
|
||||
@@ -61,12 +62,15 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
||||
for (auto item : module->export_function) {
|
||||
const auto vmAddress = module->base + item->function_address;
|
||||
if (vmAddress == currentRip) {
|
||||
printf("[%s] call function %s at file address: %llx\n",
|
||||
module->name, item->name, address);
|
||||
printf(
|
||||
"[%s] call function %s at file address: %llx lastRip: "
|
||||
"%llx\n",
|
||||
module->name, item->name, address, lastRip);
|
||||
sandbox->EmulateApi(uc, vmAddress, currentRip, item->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
lastRip = currentRip;
|
||||
if (LOG_LEVEL > 0) {
|
||||
// 使用Capstone反汇编
|
||||
cs_insn* instruction;
|
||||
|
||||
3
ai_anti_malware/tiny_wfp_structs.h
Normal file
3
ai_anti_malware/tiny_wfp_structs.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
#include "head.h"
|
||||
#include <fwpmtypes.h>
|
||||
Reference in New Issue
Block a user