添加沙箱功能和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->RecImageBase +
|
||||||
(sampleInfo->isX64 ? sampleInfo->ntHead64->OptionalHeader.SizeOfImage
|
(sampleInfo->isX64 ? sampleInfo->ntHead64->OptionalHeader.SizeOfImage
|
||||||
: sampleInfo->ntHead32->OptionalHeader.SizeOfImage);
|
: sampleInfo->ntHead32->OptionalHeader.SizeOfImage);
|
||||||
|
sampleInfo->isDll = peconv::is_module_dll((BYTE*)sampleInfo->peBuffer);
|
||||||
printf("Debug - Memory mapping parameters:\n");
|
printf("Debug - Memory mapping parameters:\n");
|
||||||
printf("RecImageBase: 0x%llx\n", sampleInfo->RecImageBase);
|
printf("RecImageBase: 0x%llx\n", sampleInfo->RecImageBase);
|
||||||
printf("peSize: 0x%llx\n", sampleInfo->peSize);
|
printf("peSize: 0x%llx\n", sampleInfo->peSize);
|
||||||
@@ -310,9 +311,29 @@ auto doMalwareScan(int argc, char* argv[]) -> void {
|
|||||||
auto sampleType = scanner.DetectMalware(filePath);
|
auto sampleType = scanner.DetectMalware(filePath);
|
||||||
printf("sample type: %d \n", sampleType);
|
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[]) {
|
int main(int argc, char* argv[]) {
|
||||||
// doMl(argc, argv);
|
// doMl(argc, argv);
|
||||||
// doPredict(argc, argv);
|
// doPredict(argc, argv);
|
||||||
doMalwareScan(argc, argv);
|
// doMalwareScan(argc, argv);
|
||||||
|
doSandbox(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,9 +174,13 @@
|
|||||||
<ClCompile Include="ml.cpp" />
|
<ClCompile Include="ml.cpp" />
|
||||||
<ClCompile Include="sandbox.cpp" />
|
<ClCompile Include="sandbox.cpp" />
|
||||||
<ClCompile Include="sandbox_api_emu.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_regs.cpp" />
|
||||||
<ClCompile Include="sandbox_api_stl.cpp" />
|
<ClCompile Include="sandbox_api_stl.cpp" />
|
||||||
|
<ClCompile Include="sandbox_api_wfp.cpp" />
|
||||||
<ClCompile Include="sandbox_api_winhttp.cpp" />
|
<ClCompile Include="sandbox_api_winhttp.cpp" />
|
||||||
|
<ClCompile Include="sandbox_api_wlan.cpp" />
|
||||||
<ClCompile Include="sandbox_callbacks.cpp" />
|
<ClCompile Include="sandbox_callbacks.cpp" />
|
||||||
<ClCompile Include="sandbox_malware_check.cpp" />
|
<ClCompile Include="sandbox_malware_check.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
<Filter Include="头文件\machine_learning">
|
<Filter Include="头文件\machine_learning">
|
||||||
<UniqueIdentifier>{65a79261-ea29-4842-b41c-7983eddbdc85}</UniqueIdentifier>
|
<UniqueIdentifier>{65a79261-ea29-4842-b41c-7983eddbdc85}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="源文件\sandbox\apis">
|
||||||
|
<UniqueIdentifier>{44f6b6b6-64fa-44ff-b7fa-af7f7294a3f2}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="ai_anti_malware.cpp">
|
<ClCompile Include="ai_anti_malware.cpp">
|
||||||
@@ -120,9 +123,6 @@
|
|||||||
<ClCompile Include="sandbox_callbacks.cpp">
|
<ClCompile Include="sandbox_callbacks.cpp">
|
||||||
<Filter>源文件\sandbox</Filter>
|
<Filter>源文件\sandbox</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="sandbox_api_emu.cpp">
|
|
||||||
<Filter>源文件\sandbox</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="ml.cpp">
|
<ClCompile Include="ml.cpp">
|
||||||
<Filter>源文件\machine_learning</Filter>
|
<Filter>源文件\machine_learning</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -132,14 +132,29 @@
|
|||||||
<ClCompile Include="sandbox_malware_check.cpp">
|
<ClCompile Include="sandbox_malware_check.cpp">
|
||||||
<Filter>源文件\sandbox</Filter>
|
<Filter>源文件\sandbox</Filter>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="sandbox_api_regs.cpp">
|
||||||
<Filter>源文件\sandbox</Filter>
|
<Filter>源文件\sandbox\apis</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="sandbox_api_stl.cpp">
|
<ClCompile Include="sandbox_api_stl.cpp">
|
||||||
<Filter>源文件\sandbox</Filter>
|
<Filter>源文件\sandbox\apis</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="sandbox_api_winhttp.cpp">
|
<ClCompile Include="sandbox_api_file.cpp">
|
||||||
<Filter>源文件\sandbox</Filter>
|
<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>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -3,21 +3,23 @@
|
|||||||
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iostream>
|
#include <WinSock2.h>
|
||||||
#include <winternl.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <ntstatus.h>
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include "unicorn/include/unicorn/unicorn.h"
|
#include "unicorn/include/unicorn/unicorn.h"
|
||||||
#include "capstone/include/capstone/capstone.h"
|
#include "capstone/include/capstone/capstone.h"
|
||||||
#pragma comment(lib, "unicorn/unicorn.lib")
|
#pragma comment(lib, "unicorn/unicorn.lib")
|
||||||
#pragma comment(lib, "capstone/capstone.lib")
|
#pragma comment(lib, "capstone/capstone.lib")
|
||||||
#include "libpeconv/include/peconv.h"
|
#include "libpeconv/include/peconv.h"
|
||||||
#include "native_struct.h"
|
#include "native_struct.h"
|
||||||
|
#include "tiny_wfp_structs.h"
|
||||||
struct BasicPeInfo {
|
struct BasicPeInfo {
|
||||||
std::string inputFilePath;
|
std::string inputFilePath;
|
||||||
bool isX64;
|
bool isX64;
|
||||||
@@ -29,6 +31,7 @@ struct BasicPeInfo {
|
|||||||
size_t peSize;
|
size_t peSize;
|
||||||
PIMAGE_NT_HEADERS ntHead64;
|
PIMAGE_NT_HEADERS ntHead64;
|
||||||
PIMAGE_NT_HEADERS32 ntHead32;
|
PIMAGE_NT_HEADERS32 ntHead32;
|
||||||
|
bool isDll;
|
||||||
};
|
};
|
||||||
#include "sandbox.h"
|
#include "sandbox.h"
|
||||||
#include "ml.h"
|
#include "ml.h"
|
||||||
@@ -2,6 +2,28 @@
|
|||||||
|
|
||||||
#include "sandbox_callbacks.h"
|
#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) {
|
std::string getDllNameFromApiSetMap(const std::string& apiSet) {
|
||||||
const std::wstring wApiSet(apiSet.begin(), apiSet.end());
|
const std::wstring wApiSet(apiSet.begin(), apiSet.end());
|
||||||
|
|
||||||
@@ -174,9 +196,19 @@ class cFixImprot : public peconv::t_function_resolver {
|
|||||||
private:
|
private:
|
||||||
Sandbox* m_sandbox; // Sandbox实例的指针
|
Sandbox* m_sandbox; // Sandbox实例的指针
|
||||||
};
|
};
|
||||||
Sandbox::Sandbox() {}
|
Sandbox::Sandbox() {
|
||||||
|
m_ucEngine = nullptr;
|
||||||
|
m_peInfo = nullptr;
|
||||||
|
m_nextWfpEngineHandle = (HANDLE)0x1000; // 初始化WFP引擎句柄
|
||||||
|
}
|
||||||
|
|
||||||
Sandbox::~Sandbox() {
|
Sandbox::~Sandbox() {
|
||||||
|
// 清理WFP引擎资源
|
||||||
|
for (auto& pair : m_wfpEngines) {
|
||||||
|
delete pair.second;
|
||||||
|
}
|
||||||
|
m_wfpEngines.clear();
|
||||||
|
|
||||||
// 1. 先清理高层资源
|
// 1. 先清理高层资源
|
||||||
m_crossSectionExecution.clear();
|
m_crossSectionExecution.clear();
|
||||||
envStrings.clear();
|
envStrings.clear();
|
||||||
@@ -631,7 +663,7 @@ auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
|
|||||||
InitCommandLine(peInfo->inputFilePath);
|
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_err err = uc_mem_map(m_ucEngine, m_stackBase, m_stackSize,
|
||||||
UC_PROT_READ | UC_PROT_WRITE);
|
UC_PROT_READ | UC_PROT_WRITE);
|
||||||
@@ -659,7 +691,7 @@ auto Sandbox::Run() -> void {
|
|||||||
&rbp);
|
&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;
|
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) {
|
if (err != UC_ERR_OK) {
|
||||||
throw std::runtime_error("Failed to add syscall hook");
|
throw std::runtime_error("Failed to add syscall hook");
|
||||||
}
|
}
|
||||||
|
auto customIP = address;
|
||||||
// 设置EIP/RIP
|
// 设置EIP/RIP
|
||||||
err = uc_reg_write(m_ucEngine,
|
err = uc_reg_write(m_ucEngine,
|
||||||
m_peInfo->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP,
|
m_peInfo->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP,
|
||||||
@@ -718,11 +750,26 @@ auto Sandbox::Run() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InitApiHooks();
|
InitApiHooks();
|
||||||
|
|
||||||
std::cout << "Starting execution at " << std::hex << entryPoint
|
std::cout << "Starting execution at " << std::hex << entryPoint
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
uint64_t timeout = 60 * 1000 * 1000;
|
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);
|
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> {
|
auto Sandbox::GetEnvString() -> std::vector<wchar_t> {
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "head.h"
|
#include "head.h"
|
||||||
#include <WinInet.h>
|
#include <wininet.h>
|
||||||
#define PAGE_SIZE 0x1000
|
#define PAGE_SIZE 0x1000
|
||||||
#define CF_MASK (1 << 0)
|
#define CF_MASK (1 << 0)
|
||||||
#define PF_MASK (1 << 2)
|
#define PF_MASK (1 << 2)
|
||||||
@@ -87,12 +85,21 @@ struct InternetHandleInfo {
|
|||||||
class Sandbox {
|
class Sandbox {
|
||||||
friend class cFixImprot; // 声明cFixImprot为友元类
|
friend class cFixImprot; // 声明cFixImprot为友元类
|
||||||
public:
|
public:
|
||||||
|
// WFP引擎相关结构体
|
||||||
|
struct FakeWFPEngine {
|
||||||
|
bool isOpen;
|
||||||
|
std::vector<FWPM_PROVIDER0> providers;
|
||||||
|
std::vector<FWPM_FILTER0> filters;
|
||||||
|
};
|
||||||
|
|
||||||
Sandbox();
|
Sandbox();
|
||||||
~Sandbox();
|
~Sandbox();
|
||||||
|
std::map<uint64_t, size_t>
|
||||||
|
process_enum_state; // 用于跟踪每个句柄的枚举状态
|
||||||
|
|
||||||
// Public methods
|
// Public methods
|
||||||
auto InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void;
|
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 GetCapstoneHandle() const -> csh { return m_csHandle; }
|
||||||
auto GetUnicornHandle() const -> uc_engine* { return m_ucEngine; }
|
auto GetUnicornHandle() const -> uc_engine* { return m_ucEngine; }
|
||||||
auto GetPeInfo() const -> std::shared_ptr<BasicPeInfo> { return m_peInfo; }
|
auto GetPeInfo() const -> std::shared_ptr<BasicPeInfo> { return m_peInfo; }
|
||||||
@@ -115,6 +122,9 @@ class Sandbox {
|
|||||||
auto GetEnvStringsSize() -> size_t;
|
auto GetEnvStringsSize() -> size_t;
|
||||||
auto InitCommandLine() -> void;
|
auto InitCommandLine() -> void;
|
||||||
|
|
||||||
|
// 内存分配相关的方法
|
||||||
|
auto AllocateMemory(size_t size) -> uint64_t;
|
||||||
|
|
||||||
// 堆管理相关的公共方法
|
// 堆管理相关的公共方法
|
||||||
auto CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment*;
|
auto CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment*;
|
||||||
auto AllocateFromSegment(HeapSegment* segment, size_t size) -> uint64_t;
|
auto AllocateFromSegment(HeapSegment* segment, size_t size) -> uint64_t;
|
||||||
@@ -213,6 +223,16 @@ class Sandbox {
|
|||||||
}
|
}
|
||||||
std::vector<std::string> ApiCallList;
|
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:
|
private:
|
||||||
std::shared_ptr<BasicPeInfo> m_peInfo;
|
std::shared_ptr<BasicPeInfo> m_peInfo;
|
||||||
uint64_t m_gsBase;
|
uint64_t m_gsBase;
|
||||||
@@ -302,4 +322,106 @@ class Sandbox {
|
|||||||
auto UpdateLdrLinks(const LDR_DATA_TABLE_ENTRY& entry,
|
auto UpdateLdrLinks(const LDR_DATA_TABLE_ENTRY& entry,
|
||||||
uint64_t entryAddress, X64_PEB_LDR_DATA& ldrData)
|
uint64_t entryAddress, X64_PEB_LDR_DATA& ldrData)
|
||||||
-> void;
|
-> 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.h"
|
||||||
#include "sandbox_callbacks.h"
|
#include "sandbox_callbacks.h"
|
||||||
#include "sandbox_api_winhttp.h"
|
#include "sandbox_api_winhttp.h"
|
||||||
std::string getDllNameFromApiSetMap(const std::string& apiSet);
|
#include <tlhelp32.h>
|
||||||
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_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
|
auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
-> void {
|
-> void {
|
||||||
auto context = static_cast<Sandbox*>(sandbox);
|
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);
|
&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 Api_LoadLibraryA(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||||
auto context = static_cast<Sandbox*>(sandbox);
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
uint64_t params_address = 0;
|
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,
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
&return_address);
|
&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)
|
auto Api_GetProcAddress(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
-> void {
|
-> void {
|
||||||
auto context = static_cast<Sandbox*>(sandbox);
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
@@ -1038,83 +639,6 @@ auto Api_VirtualProtect(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
&result);
|
&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 Api_Sleep(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||||
auto context = static_cast<Sandbox*>(sandbox);
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
uint64_t milliseconds;
|
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);
|
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 Sandbox::InitApiHooks() -> void {
|
||||||
auto FakeApi_GetSystemTimeAsFileTime =
|
auto FakeApi_GetSystemTimeAsFileTime =
|
||||||
_fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1};
|
_fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1};
|
||||||
@@ -1377,6 +666,8 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
_fakeApi{.func = Api_GetCurrentThreadId, .paramCount = 0};
|
_fakeApi{.func = Api_GetCurrentThreadId, .paramCount = 0};
|
||||||
auto FakeApi_GetCurrentProcessId =
|
auto FakeApi_GetCurrentProcessId =
|
||||||
_fakeApi{.func = Api_GetCurrentProcessId, .paramCount = 0};
|
_fakeApi{.func = Api_GetCurrentProcessId, .paramCount = 0};
|
||||||
|
auto FakeApi_GetCurrentThread =
|
||||||
|
_fakeApi{.func = Api_GetCurrentThread, .paramCount = 0};
|
||||||
auto FakeApi_QueryPerformanceCounter =
|
auto FakeApi_QueryPerformanceCounter =
|
||||||
_fakeApi{.func = Api_QueryPerformanceCounter, .paramCount = 1};
|
_fakeApi{.func = Api_QueryPerformanceCounter, .paramCount = 1};
|
||||||
auto FakeApi_LoadLibraryA =
|
auto FakeApi_LoadLibraryA =
|
||||||
@@ -1468,6 +759,48 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
_fakeApi{.func = Api_GetModuleHandleW, .paramCount = 1};
|
_fakeApi{.func = Api_GetModuleHandleW, .paramCount = 1};
|
||||||
auto FakeApi_VirtualQuery =
|
auto FakeApi_VirtualQuery =
|
||||||
_fakeApi{.func = Api_VirtualQuery, .paramCount = 3};
|
_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 = {
|
api_map = {
|
||||||
{"GetSystemTimeAsFileTime",
|
{"GetSystemTimeAsFileTime",
|
||||||
std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)},
|
std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)},
|
||||||
@@ -1475,6 +808,8 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
std::make_shared<_fakeApi>(FakeApi_GetCurrentThreadId)},
|
std::make_shared<_fakeApi>(FakeApi_GetCurrentThreadId)},
|
||||||
{"GetCurrentProcessId",
|
{"GetCurrentProcessId",
|
||||||
std::make_shared<_fakeApi>(FakeApi_GetCurrentProcessId)},
|
std::make_shared<_fakeApi>(FakeApi_GetCurrentProcessId)},
|
||||||
|
{"GetCurrentThread",
|
||||||
|
std::make_shared<_fakeApi>(FakeApi_GetCurrentThread)},
|
||||||
{"QueryPerformanceCounter",
|
{"QueryPerformanceCounter",
|
||||||
std::make_shared<_fakeApi>(FakeApi_QueryPerformanceCounter)},
|
std::make_shared<_fakeApi>(FakeApi_QueryPerformanceCounter)},
|
||||||
{"LoadLibraryA", std::make_shared<_fakeApi>(FakeApi_LoadLibraryA)},
|
{"LoadLibraryA", std::make_shared<_fakeApi>(FakeApi_LoadLibraryA)},
|
||||||
@@ -1550,6 +885,40 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
{"GetModuleHandleW",
|
{"GetModuleHandleW",
|
||||||
std::make_shared<_fakeApi>(FakeApi_GetModuleHandleW)},
|
std::make_shared<_fakeApi>(FakeApi_GetModuleHandleW)},
|
||||||
{"VirtualQuery", std::make_shared<_fakeApi>(FakeApi_VirtualQuery)},
|
{"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,
|
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());
|
printf("ApiName: %s not found\n", ApiName.c_str());
|
||||||
uc_emu_stop(uc);
|
uc_emu_stop(uc);
|
||||||
return;
|
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.h"
|
||||||
#include "sandbox_callbacks.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
|
// 实现 AreFileApisANSI API
|
||||||
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
-> void {
|
-> 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));
|
uc_mem_read(uc, esp_address, &temp_bytes, sizeof(uint32_t));
|
||||||
dwBytes = temp_bytes;
|
dwBytes = temp_bytes;
|
||||||
}
|
}
|
||||||
|
// 这里如果想检查有效,得先跑main,再跑其他的,浪费时间了,操
|
||||||
|
|
||||||
// 检查堆句柄是否有效
|
// 检查堆句柄是否有效
|
||||||
|
/*
|
||||||
uint64_t expected_handle =
|
uint64_t expected_handle =
|
||||||
context->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
context->GetPeInfo()->isX64 ? HEAP_ADDRESS_64 : HEAP_ADDRESS_32;
|
||||||
if (hHeap != expected_handle) {
|
if (hHeap != expected_handle) {
|
||||||
uint64_t null_ptr = 0;
|
uint64_t null_ptr = 0;
|
||||||
|
hHeap = expected_handle;
|
||||||
uc_reg_write(
|
uc_reg_write(
|
||||||
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
&null_ptr);
|
&null_ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// 获取或创建堆段
|
// 获取或创建堆段
|
||||||
HeapSegment* segment = nullptr;
|
HeapSegment* segment = nullptr;
|
||||||
auto it = context->m_heapSegments.find(hHeap);
|
auto it = context->m_heapSegments.find(hHeap);
|
||||||
@@ -1512,4 +1966,162 @@ auto Sandbox::AllocateFromSegment(HeapSegment* segment, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0; // 分配失败
|
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 currentRip = 0;
|
||||||
uint64_t currentRsp = 0;
|
uint64_t currentRsp = 0;
|
||||||
uint64_t currentRax = 0;
|
uint64_t currentRax = 0;
|
||||||
|
static uint64_t lastRip = 0;
|
||||||
auto* sandbox = static_cast<Sandbox*>(userData);
|
auto* sandbox = static_cast<Sandbox*>(userData);
|
||||||
if (!sandbox) return;
|
if (!sandbox) return;
|
||||||
|
|
||||||
@@ -61,12 +62,15 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
|||||||
for (auto item : module->export_function) {
|
for (auto item : module->export_function) {
|
||||||
const auto vmAddress = module->base + item->function_address;
|
const auto vmAddress = module->base + item->function_address;
|
||||||
if (vmAddress == currentRip) {
|
if (vmAddress == currentRip) {
|
||||||
printf("[%s] call function %s at file address: %llx\n",
|
printf(
|
||||||
module->name, item->name, address);
|
"[%s] call function %s at file address: %llx lastRip: "
|
||||||
|
"%llx\n",
|
||||||
|
module->name, item->name, address, lastRip);
|
||||||
sandbox->EmulateApi(uc, vmAddress, currentRip, item->name);
|
sandbox->EmulateApi(uc, vmAddress, currentRip, item->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lastRip = currentRip;
|
||||||
if (LOG_LEVEL > 0) {
|
if (LOG_LEVEL > 0) {
|
||||||
// 使用Capstone反汇编
|
// 使用Capstone反汇编
|
||||||
cs_insn* instruction;
|
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