调不了了 终极大招了
This commit is contained in:
@@ -32,7 +32,7 @@ auto getPeInfo(std::string inputFilePath) -> std::shared_ptr<BasicPeInfo> {
|
|||||||
return sampleInfo;
|
return sampleInfo;
|
||||||
}
|
}
|
||||||
int main() {
|
int main() {
|
||||||
auto sampleInfo = getPeInfo("C:\\ConsoleApplication1.exe");
|
auto sampleInfo = getPeInfo("E:\\对战平台\\CrowAntiCheat\\CrowAntiCheat\\client\\Console_Test\\x64\\Release\\Console_Test.exe");
|
||||||
printf("input new file %s \n", sampleInfo->inputFilePath);
|
printf("input new file %s \n", sampleInfo->inputFilePath);
|
||||||
printf("is x64: %d\n", sampleInfo->isX64);
|
printf("is x64: %d\n", sampleInfo->isX64);
|
||||||
printf("is relocated: %d\n", sampleInfo->isRelocated);
|
printf("is relocated: %d\n", sampleInfo->isRelocated);
|
||||||
|
|||||||
@@ -399,8 +399,8 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
m_tebBase = TEB_BASE; // 进程TEB地址
|
m_tebBase = TEB_BASE; // 进程TEB地址
|
||||||
m_pebBase = PEB_BASE; // 进程PEB地址
|
m_pebBase = PEB_BASE; // 进程PEB地址
|
||||||
// stack
|
// stack
|
||||||
m_stackBase = this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32;
|
m_stackBase = AlignSize(this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32, 16);
|
||||||
m_stackSize = this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32;
|
m_stackSize = AlignSize(this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32, 16);
|
||||||
m_stackEnd = m_stackBase + m_stackSize;
|
m_stackEnd = m_stackBase + m_stackSize;
|
||||||
|
|
||||||
// heap
|
// heap
|
||||||
@@ -525,7 +525,6 @@ auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
|
|||||||
printf("map file to vm size: %llx\n", m_peInfo->peSize);
|
printf("map file to vm size: %llx\n", m_peInfo->peSize);
|
||||||
SetupVirtualMachine();
|
SetupVirtualMachine();
|
||||||
InitCommandLine(peInfo->inputFilePath);
|
InitCommandLine(peInfo->inputFilePath);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Sandbox::Run() -> void {
|
auto Sandbox::Run() -> void {
|
||||||
@@ -544,12 +543,16 @@ auto Sandbox::Run() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置寄存器
|
// 设置寄存器
|
||||||
uint64_t rsp = m_stackEnd - 128;
|
uint64_t rsp = m_stackEnd - 256;
|
||||||
err = uc_reg_write(m_ucEngine,
|
err = uc_reg_write(m_ucEngine,
|
||||||
m_peInfo->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP, &rsp);
|
m_peInfo->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP, &rsp);
|
||||||
if (err != UC_ERR_OK) {
|
if (err != UC_ERR_OK) {
|
||||||
throw std::runtime_error("Failed to write stack pointer");
|
throw std::runtime_error("Failed to write stack pointer");
|
||||||
}
|
}
|
||||||
|
uint64_t rbp =
|
||||||
|
rsp - (m_peInfo->isX64 ? sizeof(uint64_t) : sizeof(uint32_t));
|
||||||
|
uc_reg_write(m_ucEngine, m_peInfo->isX64 ? UC_X86_REG_RBP : UC_X86_REG_EBP,
|
||||||
|
&rbp);
|
||||||
|
|
||||||
// 设置入口点
|
// 设置入口点
|
||||||
uint64_t entryPoint = m_peInfo->RecImageBase + m_peInfo->entryPoint;
|
uint64_t entryPoint = m_peInfo->RecImageBase + m_peInfo->entryPoint;
|
||||||
@@ -610,10 +613,9 @@ auto Sandbox::Run() -> void {
|
|||||||
throw std::runtime_error("Failed to set entry point");
|
throw std::runtime_error("Failed to set entry point");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始执行
|
InitApiHooks();
|
||||||
std::cout << "Starting execution at " << std::hex << entryPoint
|
std::cout << "Starting execution at " << std::hex << entryPoint
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
InitApiHooks();
|
|
||||||
err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, 0, 0);
|
err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, 0, 0);
|
||||||
if (err != UC_ERR_OK) {
|
if (err != UC_ERR_OK) {
|
||||||
std::cerr << "Emulation error: " << uc_strerror(err) << std::endl;
|
std::cerr << "Emulation error: " << uc_strerror(err) << std::endl;
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
#define SF_MASK (1 << 7)
|
#define SF_MASK (1 << 7)
|
||||||
#define OF_MASK (1 << 11)
|
#define OF_MASK (1 << 11)
|
||||||
#define ALL_MASK (OF_MASK | SF_MASK | ZF_MASK | PF_MASK | CF_MASK)
|
#define ALL_MASK (OF_MASK | SF_MASK | ZF_MASK | PF_MASK | CF_MASK)
|
||||||
#define STACK_BASE_64 0x7ffffffde000
|
#define STACK_BASE_64 0x14A0000
|
||||||
#define STACK_BASE_32 0xfffdd000
|
#define STACK_BASE_32 0x14A0000
|
||||||
#define STACK_SIZE_64 0x40000
|
#define STACK_SIZE_64 0x40000
|
||||||
#define STACK_SIZE_32 0x21000
|
#define STACK_SIZE_32 0x40000
|
||||||
#define HEAP_ADDRESS_64 0x500000000
|
#define HEAP_ADDRESS_64 0x500000000
|
||||||
#define HEAP_SIZE_64 0x5000000
|
#define HEAP_SIZE_64 0x5000000
|
||||||
#define HEAP_ADDRESS_32 0x5000000
|
#define HEAP_ADDRESS_32 0x5000000
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "sandbox.h"
|
#include "sandbox.h"
|
||||||
|
#include "sandbox_callbacks.h"
|
||||||
std::string getDllNameFromApiSetMap(const std::string& apiSet);
|
std::string getDllNameFromApiSetMap(const std::string& apiSet);
|
||||||
auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
|
auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
-> void {
|
-> void {
|
||||||
@@ -1145,6 +1146,240 @@ auto Api_GetCPInfo(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
|||||||
&success);
|
&success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Api_MultiByteToWideChar(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
|
-> void {
|
||||||
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
|
uint32_t CodePage = 0;
|
||||||
|
uint32_t dwFlags = 0;
|
||||||
|
uint64_t lpMultiByteStr = 0;
|
||||||
|
int32_t cbMultiByte = 0;
|
||||||
|
uint64_t lpWideCharStr = 0;
|
||||||
|
int32_t cchWideChar = 0;
|
||||||
|
|
||||||
|
// 获取参数
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
uint64_t temp_codepage = 0;
|
||||||
|
uint64_t temp_flags = 0;
|
||||||
|
uint64_t temp_multibyte = 0;
|
||||||
|
uint64_t temp_cbmultibyte = 0;
|
||||||
|
|
||||||
|
// x64: rcx, rdx, r8, r9, [rsp+0x28], [rsp+0x30]
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R8, &temp_multibyte);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R9, &temp_cbmultibyte);
|
||||||
|
|
||||||
|
CodePage = static_cast<uint32_t>(temp_codepage);
|
||||||
|
dwFlags = static_cast<uint32_t>(temp_flags);
|
||||||
|
lpMultiByteStr = temp_multibyte;
|
||||||
|
cbMultiByte = static_cast<int32_t>(temp_cbmultibyte);
|
||||||
|
|
||||||
|
// 获取栈上的参数
|
||||||
|
uint64_t rsp = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||||
|
|
||||||
|
// 为了确保安全访问,先验证栈地址的有效性
|
||||||
|
if (rsp < 0x8000000000000000 || rsp + 0x40 > 0x8000000000010000) {
|
||||||
|
// 无效的栈地址
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(uc, UC_X86_REG_RAX, &result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取栈上的参数
|
||||||
|
uint64_t shadow_space = 0x20; // x64调用约定中的shadow space
|
||||||
|
uc_mem_read(uc, rsp + shadow_space + 0x8, &lpWideCharStr,
|
||||||
|
sizeof(uint64_t));
|
||||||
|
uc_mem_read(uc, rsp + shadow_space + 0x10, &cchWideChar,
|
||||||
|
sizeof(int32_t));
|
||||||
|
} 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, &CodePage, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x4, &dwFlags, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x8, &lpMultiByteStr, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0xC, &cbMultiByte, sizeof(int32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x10, &lpWideCharStr, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x14, &cchWideChar, sizeof(int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证参数
|
||||||
|
if (lpMultiByteStr == 0 || (lpWideCharStr == 0 && cchWideChar != 0)) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取源字符串
|
||||||
|
std::vector<char> srcBuffer;
|
||||||
|
if (cbMultiByte == -1) {
|
||||||
|
// 如果长度为-1,则源字符串以null结尾
|
||||||
|
char ch = 0;
|
||||||
|
size_t len = 0;
|
||||||
|
do {
|
||||||
|
if (uc_mem_read(uc, lpMultiByteStr + len, &ch, 1) != UC_ERR_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
srcBuffer.push_back(ch);
|
||||||
|
len++;
|
||||||
|
} while (ch != 0 && len < MAX_PATH); // 添加长度限制防止无限循环
|
||||||
|
|
||||||
|
if (len >= MAX_PATH) {
|
||||||
|
// 设置错误码
|
||||||
|
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbMultiByte = static_cast<int32_t>(len);
|
||||||
|
} else if (cbMultiByte > 0) {
|
||||||
|
// 使用指定长度,但添加安全检查
|
||||||
|
if (cbMultiByte > MAX_PATH) {
|
||||||
|
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcBuffer.resize(cbMultiByte);
|
||||||
|
if (uc_mem_read(uc, lpMultiByteStr, srcBuffer.data(), cbMultiByte) !=
|
||||||
|
UC_ERR_OK) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 无效的输入长度
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算所需的宽字符缓冲区大小
|
||||||
|
int result = MultiByteToWideChar(CodePage, dwFlags, srcBuffer.data(),
|
||||||
|
cbMultiByte, nullptr, 0);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
// 转换失败,获取错误码
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果只是查询所需缓冲区大小
|
||||||
|
if (lpWideCharStr == 0 || cchWideChar == 0) {
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查目标缓冲区大小是否足够
|
||||||
|
if (cchWideChar < result) {
|
||||||
|
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行实际转换
|
||||||
|
std::vector<wchar_t> wideBuffer(result);
|
||||||
|
if (MultiByteToWideChar(CodePage, dwFlags, srcBuffer.data(), cbMultiByte,
|
||||||
|
wideBuffer.data(), result) > 0) {
|
||||||
|
// 写入转换后的字符串到目标内存
|
||||||
|
if (uc_mem_write(uc, lpWideCharStr, wideBuffer.data(),
|
||||||
|
result * sizeof(wchar_t)) != UC_ERR_OK) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 转换失败
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"[*] MultiByteToWideChar: CodePage=%u, Flags=0x%x, Input=%p, "
|
||||||
|
"InputLen=%d, Output=%p, OutputLen=%d, Result=%d\n",
|
||||||
|
CodePage, dwFlags, (void*)lpMultiByteStr, cbMultiByte,
|
||||||
|
(void*)lpWideCharStr, cchWideChar, result);
|
||||||
|
|
||||||
|
uc_reg_write(uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
}
|
||||||
|
|
||||||
auto Sandbox::CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment* {
|
auto Sandbox::CreateHeapSegment(uint64_t base, size_t size) -> HeapSegment* {
|
||||||
auto segment = new HeapSegment();
|
auto segment = new HeapSegment();
|
||||||
segment->base = base;
|
segment->base = base;
|
||||||
@@ -1279,6 +1514,383 @@ auto Sandbox::InitCommandLine(std::string commandLine) -> void {
|
|||||||
(wCommandLine.length() + 1) * sizeof(wchar_t));
|
(wCommandLine.length() + 1) * sizeof(wchar_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Api_GetModuleFileNameW(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
|
-> void {
|
||||||
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
|
uint64_t hModule = 0;
|
||||||
|
uint64_t lpFilename = 0;
|
||||||
|
uint32_t nSize = 0;
|
||||||
|
|
||||||
|
// 获取参数
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
// x64: rcx = hModule, rdx = lpFilename, r8 = nSize
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RCX, &hModule);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RDX, &lpFilename);
|
||||||
|
uint64_t temp_size;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R8, &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_module = 0;
|
||||||
|
uint32_t temp_filename = 0;
|
||||||
|
uc_mem_read(uc, esp_address, &temp_module, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x4, &temp_filename, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x8, &nSize, sizeof(uint32_t));
|
||||||
|
hModule = temp_module;
|
||||||
|
lpFilename = temp_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t result = 0;
|
||||||
|
|
||||||
|
// 验证参数
|
||||||
|
if (lpFilename == 0 || nSize == 0) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring modulePath;
|
||||||
|
if (hModule == 0) {
|
||||||
|
// 如果hModule为NULL,返回主模块(PE文件)的路径
|
||||||
|
modulePath = std::wstring(context->GetPeInfo()->inputFilePath.begin(),
|
||||||
|
context->GetPeInfo()->inputFilePath.end());
|
||||||
|
} else {
|
||||||
|
// 在模块列表中查找对应模块
|
||||||
|
bool found = false;
|
||||||
|
for (const auto& module : context->GetModuleList()) {
|
||||||
|
if (module->base == hModule) {
|
||||||
|
// 构建完整的模块路径
|
||||||
|
char windowsPath[MAX_PATH];
|
||||||
|
GetWindowsDirectoryA(windowsPath, sizeof(windowsPath));
|
||||||
|
|
||||||
|
// 根据PE架构选择正确的系统目录
|
||||||
|
const std::string systemDir = context->GetPeInfo()->isX64
|
||||||
|
? "\\System32\\"
|
||||||
|
: "\\SysWOW64\\";
|
||||||
|
|
||||||
|
std::string fullPath =
|
||||||
|
std::string(windowsPath) + systemDir + module->name;
|
||||||
|
modulePath = std::wstring(fullPath.begin(), fullPath.end());
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
DWORD error = ERROR_MOD_NOT_FOUND;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
uc_reg_write(
|
||||||
|
uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查缓冲区大小是否足够
|
||||||
|
if (nSize < modulePath.length() + 1) {
|
||||||
|
// 缓冲区太小,返回所需大小
|
||||||
|
result = static_cast<uint32_t>(modulePath.length() + 1);
|
||||||
|
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 写入路径到缓冲区
|
||||||
|
if (uc_mem_write(uc, lpFilename, modulePath.c_str(),
|
||||||
|
(modulePath.length() + 1) * sizeof(wchar_t)) ==
|
||||||
|
UC_ERR_OK) {
|
||||||
|
result = static_cast<uint32_t>(modulePath.length());
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"[*] GetModuleFileNameW: Module=0x%llx, Buffer=0x%llx, Size=%u, "
|
||||||
|
"Result=%u, Path=%ls\n",
|
||||||
|
hModule, lpFilename, nSize, result, modulePath.c_str());
|
||||||
|
|
||||||
|
uc_reg_write(uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现 AreFileApisANSI API
|
||||||
|
auto Api_AreFileApisANSI(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
|
-> void {
|
||||||
|
// 默认返回TRUE,表示使用ANSI字符集
|
||||||
|
BOOL isAnsi = TRUE;
|
||||||
|
printf("[*] AreFileApisANSI: IsAnsi=%d\n", isAnsi);
|
||||||
|
|
||||||
|
// 返回结果
|
||||||
|
uc_reg_write(uc,
|
||||||
|
static_cast<Sandbox*>(sandbox)->GetPeInfo()->isX64
|
||||||
|
? UC_X86_REG_RAX
|
||||||
|
: UC_X86_REG_EAX,
|
||||||
|
&isAnsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
|
-> void {
|
||||||
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
|
uint32_t CodePage = 0;
|
||||||
|
uint32_t dwFlags = 0;
|
||||||
|
uint64_t lpWideCharStr = 0;
|
||||||
|
int32_t cchWideChar = 0;
|
||||||
|
uint64_t lpMultiByteStr = 0;
|
||||||
|
int32_t cbMultiByte = 0;
|
||||||
|
uint64_t lpDefaultChar = 0;
|
||||||
|
uint64_t lpUsedDefaultChar = 0;
|
||||||
|
|
||||||
|
// 获取参数
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
// x64: rcx, rdx, r8, r9, [rsp+0x28], [rsp+0x30], [rsp+0x38], [rsp+0x40]
|
||||||
|
uint64_t temp_codepage = 0;
|
||||||
|
uint64_t temp_flags = 0;
|
||||||
|
uint64_t temp_widechar = 0;
|
||||||
|
uint64_t temp_cchwidechar = 0;
|
||||||
|
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RCX, &temp_codepage);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RDX, &temp_flags);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R8, &temp_widechar);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R9, &temp_cchwidechar);
|
||||||
|
|
||||||
|
CodePage = static_cast<uint32_t>(temp_codepage);
|
||||||
|
dwFlags = static_cast<uint32_t>(temp_flags);
|
||||||
|
lpWideCharStr = temp_widechar;
|
||||||
|
cchWideChar = static_cast<int32_t>(temp_cchwidechar);
|
||||||
|
|
||||||
|
// 获取栈上的参数
|
||||||
|
uint64_t rsp = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
|
||||||
|
uint64_t shadow_space = 0x20;
|
||||||
|
|
||||||
|
uc_mem_read(uc, rsp + shadow_space + 0x8, &lpMultiByteStr,
|
||||||
|
sizeof(uint64_t));
|
||||||
|
uc_mem_read(uc, rsp + shadow_space + 0x10, &cbMultiByte,
|
||||||
|
sizeof(int32_t));
|
||||||
|
uc_mem_read(uc, rsp + shadow_space + 0x18, &lpDefaultChar,
|
||||||
|
sizeof(uint64_t));
|
||||||
|
uc_mem_read(uc, rsp + shadow_space + 0x20, &lpUsedDefaultChar,
|
||||||
|
sizeof(uint64_t));
|
||||||
|
} 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, &CodePage, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x4, &dwFlags, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x8, &lpWideCharStr, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0xC, &cchWideChar, sizeof(int32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x10, &lpMultiByteStr, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x14, &cbMultiByte, sizeof(int32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x18, &lpDefaultChar, sizeof(uint32_t));
|
||||||
|
uc_mem_read(uc, esp_address + 0x1C, &lpUsedDefaultChar,
|
||||||
|
sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 基本参数验证
|
||||||
|
if (lpWideCharStr == 0 || cchWideChar == 0) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取源宽字符串
|
||||||
|
std::vector<wchar_t> srcBuffer;
|
||||||
|
size_t actualWideLength = 0;
|
||||||
|
|
||||||
|
if (cchWideChar == -1) {
|
||||||
|
// 如果长度为-1,则源字符串以null结尾
|
||||||
|
wchar_t ch = 0;
|
||||||
|
do {
|
||||||
|
if (uc_mem_read(uc, lpWideCharStr + (actualWideLength * 2), &ch,
|
||||||
|
2) != UC_ERR_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
srcBuffer.push_back(ch);
|
||||||
|
actualWideLength++;
|
||||||
|
} while (ch != 0 && actualWideLength < MAX_PATH);
|
||||||
|
|
||||||
|
if (actualWideLength >= MAX_PATH) {
|
||||||
|
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 使用指定长度
|
||||||
|
if (cchWideChar > 0 && cchWideChar <= MAX_PATH) {
|
||||||
|
srcBuffer.resize(cchWideChar);
|
||||||
|
if (uc_mem_read(uc, lpWideCharStr, srcBuffer.data(),
|
||||||
|
cchWideChar * 2) != UC_ERR_OK) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX
|
||||||
|
: UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
actualWideLength = cchWideChar;
|
||||||
|
} else {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取默认字符和使用默认字符标志
|
||||||
|
char defaultChar = '?';
|
||||||
|
BOOL usedDefaultChar = FALSE;
|
||||||
|
if (lpDefaultChar != 0) {
|
||||||
|
uc_mem_read(uc, lpDefaultChar, &defaultChar, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算所需的多字节缓冲区大小
|
||||||
|
int requiredSize = WideCharToMultiByte(
|
||||||
|
CodePage, dwFlags, srcBuffer.data(), static_cast<int>(actualWideLength),
|
||||||
|
nullptr, 0, lpDefaultChar ? &defaultChar : nullptr,
|
||||||
|
lpUsedDefaultChar ? &usedDefaultChar : nullptr);
|
||||||
|
|
||||||
|
if (requiredSize == 0) {
|
||||||
|
// 获取并设置错误码
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果只是查询所需缓冲区大小
|
||||||
|
if (lpMultiByteStr == 0 || cbMultiByte == 0) {
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&requiredSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查目标缓冲区大小是否足够
|
||||||
|
if (cbMultiByte < requiredSize) {
|
||||||
|
DWORD error = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行实际转换
|
||||||
|
std::vector<char> multiByteBuffer(requiredSize);
|
||||||
|
int result = WideCharToMultiByte(
|
||||||
|
CodePage, dwFlags, srcBuffer.data(), static_cast<int>(actualWideLength),
|
||||||
|
multiByteBuffer.data(), requiredSize,
|
||||||
|
lpDefaultChar ? &defaultChar : nullptr,
|
||||||
|
lpUsedDefaultChar ? &usedDefaultChar : nullptr);
|
||||||
|
|
||||||
|
if (result > 0) {
|
||||||
|
// 写入转换后的字符串到目标内存
|
||||||
|
if (uc_mem_write(uc, lpMultiByteStr, multiByteBuffer.data(), result) !=
|
||||||
|
UC_ERR_OK) {
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果需要,写回使用默认字符标志
|
||||||
|
if (lpUsedDefaultChar != 0) {
|
||||||
|
uc_mem_write(uc, lpUsedDefaultChar, &usedDefaultChar, sizeof(BOOL));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 获取并设置错误码
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"[*] WideCharToMultiByte: CodePage=%u, Flags=0x%x, WideStr=%p, "
|
||||||
|
"WideLen=%d, MultiStr=%p, MultiLen=%d, Result=%d\n",
|
||||||
|
CodePage, dwFlags, (void*)lpWideCharStr, cchWideChar,
|
||||||
|
(void*)lpMultiByteStr, cbMultiByte, result);
|
||||||
|
|
||||||
|
uc_reg_write(uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
}
|
||||||
|
|
||||||
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};
|
||||||
@@ -1329,6 +1941,14 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
_fakeApi{.func = Api_GetCommandLineW, .paramCount = 0};
|
_fakeApi{.func = Api_GetCommandLineW, .paramCount = 0};
|
||||||
auto FakeApi_GetACP = _fakeApi{.func = Api_GetACP, .paramCount = 0};
|
auto FakeApi_GetACP = _fakeApi{.func = Api_GetACP, .paramCount = 0};
|
||||||
auto FakeApi_GetCPInfo = _fakeApi{.func = Api_GetCPInfo, .paramCount = 2};
|
auto FakeApi_GetCPInfo = _fakeApi{.func = Api_GetCPInfo, .paramCount = 2};
|
||||||
|
auto FakeApi_MultiByteToWideChar =
|
||||||
|
_fakeApi{.func = Api_MultiByteToWideChar, .paramCount = 6};
|
||||||
|
auto FakeApi_GetModuleFileNameW =
|
||||||
|
_fakeApi{.func = Api_GetModuleFileNameW, .paramCount = 3};
|
||||||
|
auto FakeApi_AreFileApisANSI =
|
||||||
|
_fakeApi{.func = Api_AreFileApisANSI, .paramCount = 0};
|
||||||
|
auto FakeApi_WideCharToMultiByte =
|
||||||
|
_fakeApi{.func = Api_WideCharToMultiByte, .paramCount = 8};
|
||||||
|
|
||||||
api_map = {
|
api_map = {
|
||||||
{"GetSystemTimeAsFileTime",
|
{"GetSystemTimeAsFileTime",
|
||||||
@@ -1370,13 +1990,21 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
{"GetCommandLineW",
|
{"GetCommandLineW",
|
||||||
std::make_shared<_fakeApi>(FakeApi_GetCommandLineW)},
|
std::make_shared<_fakeApi>(FakeApi_GetCommandLineW)},
|
||||||
{"GetACP", std::make_shared<_fakeApi>(FakeApi_GetACP)},
|
{"GetACP", std::make_shared<_fakeApi>(FakeApi_GetACP)},
|
||||||
{"GetCPInfo", std::make_shared<_fakeApi>(FakeApi_GetCPInfo)}};
|
{"GetCPInfo", std::make_shared<_fakeApi>(FakeApi_GetCPInfo)},
|
||||||
|
{"MultiByteToWideChar",
|
||||||
|
std::make_shared<_fakeApi>(FakeApi_MultiByteToWideChar)},
|
||||||
|
{"GetModuleFileNameW",
|
||||||
|
std::make_shared<_fakeApi>(FakeApi_GetModuleFileNameW)},
|
||||||
|
{"AreFileApisANSI",
|
||||||
|
std::make_shared<_fakeApi>(FakeApi_AreFileApisANSI)},
|
||||||
|
{"WideCharToMultiByte",
|
||||||
|
std::make_shared<_fakeApi>(FakeApi_WideCharToMultiByte)},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
||||||
std::string ApiName) -> void {
|
std::string ApiName) -> void {
|
||||||
auto it = api_map.find(ApiName);
|
auto it = api_map.find(ApiName);
|
||||||
if (it != api_map.end()) {
|
if (it != api_map.end()) {
|
||||||
// 调用API函数
|
|
||||||
it->second->func(this, uc, address);
|
it->second->func(this, uc, address);
|
||||||
|
|
||||||
// 获取参数数量
|
// 获取参数数量
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "sandbox_callbacks.h"
|
#include "sandbox_callbacks.h"
|
||||||
#define LOG_LEVEL 0
|
#define LOG_LEVEL 1
|
||||||
namespace sandboxCallbacks {
|
namespace sandboxCallbacks {
|
||||||
void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
||||||
void* userData) {
|
void* userData) {
|
||||||
@@ -46,6 +46,8 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
|||||||
instruction[0].mnemonic, instruction[0].op_str);
|
instruction[0].mnemonic, instruction[0].op_str);
|
||||||
}
|
}
|
||||||
cs_free(instruction, instructionCount);
|
cs_free(instruction, instructionCount);
|
||||||
|
|
||||||
|
dumpVmenv(uc, userData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +56,10 @@ void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
|||||||
auto* sandbox = static_cast<Sandbox*>(userData);
|
auto* sandbox = static_cast<Sandbox*>(userData);
|
||||||
if (!sandbox) return;
|
if (!sandbox) return;
|
||||||
|
|
||||||
uint64_t regRax, regRip;
|
uint64_t regRax, regRip, regRbp;
|
||||||
|
uc_reg_read(uc,
|
||||||
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RBP : UC_X86_REG_EBP,
|
||||||
|
®Rbp);
|
||||||
uc_reg_read(uc,
|
uc_reg_read(uc,
|
||||||
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
®Rax);
|
®Rax);
|
||||||
@@ -68,8 +73,9 @@ void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
|||||||
if (LOG_LEVEL > 0) {
|
if (LOG_LEVEL > 0) {
|
||||||
printf(
|
printf(
|
||||||
"[handleMemoryRead] Address: %p Size: %p Rax: %p Rip: %p Error: %d "
|
"[handleMemoryRead] Address: %p Size: %p Rax: %p Rip: %p Error: %d "
|
||||||
"ReadData: %p\n",
|
"ReadData: %p Rbp: %p\n",
|
||||||
address, size, regRax, regRip, readError, readAddress);
|
address, size, regRax, regRip, readError, readAddress, regRbp);
|
||||||
|
sandboxCallbacks::dumpVmenv(uc, sandbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void dumpVmenv(uc_engine* uc, void* userData) {
|
void dumpVmenv(uc_engine* uc, void* userData) {
|
||||||
@@ -81,6 +87,8 @@ void dumpVmenv(uc_engine* uc, void* userData) {
|
|||||||
uint64_t Rbp = 0;
|
uint64_t Rbp = 0;
|
||||||
uint64_t Rcx = 0;
|
uint64_t Rcx = 0;
|
||||||
uint64_t Rdx = 0;
|
uint64_t Rdx = 0;
|
||||||
|
uint64_t Eax = 0;
|
||||||
|
uint64_t Ecx = 0;
|
||||||
uc_reg_read(uc,
|
uc_reg_read(uc,
|
||||||
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP,
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RIP : UC_X86_REG_EIP,
|
||||||
&Rip);
|
&Rip);
|
||||||
@@ -99,8 +107,94 @@ void dumpVmenv(uc_engine* uc, void* userData) {
|
|||||||
uc_reg_read(uc,
|
uc_reg_read(uc,
|
||||||
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RDX : UC_X86_REG_EDX,
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RDX : UC_X86_REG_EDX,
|
||||||
&Rdx);
|
&Rdx);
|
||||||
printf("[dumpVmenv] Rip: %p Rax: %p Rsp: %p Rbp: %p Rcx: %p Rdx: %p\n", Rip,
|
uc_reg_read(uc,
|
||||||
Rax, Rsp, Rbp, Rcx, Rdx);
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_EAX : UC_X86_REG_EAX,
|
||||||
|
&Eax);
|
||||||
|
uc_reg_read(uc,
|
||||||
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_ECX : UC_X86_REG_ECX,
|
||||||
|
&Ecx);
|
||||||
|
printf(
|
||||||
|
"[dumpVmenv] Rip: %p Rax: %p Rsp: %p Rbp: %p Rcx: %p Rdx: %p Eax: "
|
||||||
|
"%08x Ecx: %08x\n",
|
||||||
|
Rip, Rax, Rsp, Rbp, Rcx, Rdx, Eax, Ecx);
|
||||||
|
|
||||||
|
// 打印16层栈内存
|
||||||
|
printf("\n[Stack Memory Dump (16 levels)]\n");
|
||||||
|
const int STACK_LEVELS = 16;
|
||||||
|
const int POINTER_SIZE = sandbox->GetPeInfo()->isX64 ? 8 : 4;
|
||||||
|
|
||||||
|
for (int i = 0; i < STACK_LEVELS; i++) {
|
||||||
|
uint64_t currentAddress = Rsp + (i * POINTER_SIZE);
|
||||||
|
uint64_t memValue = 0;
|
||||||
|
|
||||||
|
if (uc_mem_read(uc, currentAddress, &memValue, POINTER_SIZE) ==
|
||||||
|
UC_ERR_OK) {
|
||||||
|
printf("RSP+%02X [%p]: ", i * POINTER_SIZE, currentAddress);
|
||||||
|
// 按4字节分组显示十六进制
|
||||||
|
for (int j = 0; j < POINTER_SIZE; j += 4) {
|
||||||
|
uint32_t chunk;
|
||||||
|
size_t chunkSize = min(4, POINTER_SIZE - j);
|
||||||
|
if (uc_mem_read(uc, currentAddress + j, &chunk, chunkSize) ==
|
||||||
|
UC_ERR_OK) {
|
||||||
|
printf("%08X ", chunk);
|
||||||
|
} else {
|
||||||
|
printf("???????? ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示ASCII字符
|
||||||
|
printf("| ");
|
||||||
|
for (int j = 0; j < POINTER_SIZE; j++) {
|
||||||
|
uint8_t byte;
|
||||||
|
if (uc_mem_read(uc, currentAddress + j, &byte, 1) ==
|
||||||
|
UC_ERR_OK) {
|
||||||
|
printf("%c", (byte >= 32 && byte <= 126) ? byte : '.');
|
||||||
|
} else {
|
||||||
|
printf("?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
printf("RSP+%02X [%p]: Unable to read memory\n", i * POINTER_SIZE,
|
||||||
|
currentAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n[Frame Pointer Stack (16 levels)]\n");
|
||||||
|
uint64_t currentBp = Rbp;
|
||||||
|
for (int i = 0; i < STACK_LEVELS && currentBp != 0; i++) {
|
||||||
|
uint64_t nextBp = 0;
|
||||||
|
if (uc_mem_read(uc, currentBp, &nextBp, POINTER_SIZE) == UC_ERR_OK) {
|
||||||
|
printf("Frame %02d [%p]: ", i, currentBp);
|
||||||
|
// 按4字节分组显示十六进制
|
||||||
|
for (int j = 0; j < POINTER_SIZE; j += 4) {
|
||||||
|
uint32_t chunk;
|
||||||
|
size_t chunkSize = min(4, POINTER_SIZE - j);
|
||||||
|
if (uc_mem_read(uc, currentBp + j, &chunk, chunkSize) ==
|
||||||
|
UC_ERR_OK) {
|
||||||
|
printf("%08X ", chunk);
|
||||||
|
} else {
|
||||||
|
printf("???????? ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示ASCII字符
|
||||||
|
printf("| ");
|
||||||
|
for (int j = 0; j < POINTER_SIZE; j++) {
|
||||||
|
uint8_t byte;
|
||||||
|
if (uc_mem_read(uc, currentBp + j, &byte, 1) == UC_ERR_OK) {
|
||||||
|
printf("%c", (byte >= 32 && byte <= 126) ? byte : '.');
|
||||||
|
} else {
|
||||||
|
printf("?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
currentBp = nextBp;
|
||||||
|
} else {
|
||||||
|
printf("Frame %02d [%p]: Unable to read memory\n", i, currentBp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
||||||
int size, int64_t value, void* userData) {
|
int size, int64_t value, void* userData) {
|
||||||
|
|||||||
@@ -2,15 +2,14 @@
|
|||||||
#include "sandbox.h"
|
#include "sandbox.h"
|
||||||
namespace sandboxCallbacks {
|
namespace sandboxCallbacks {
|
||||||
void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
||||||
void* userData);
|
void* userData);
|
||||||
void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
void handleMemoryRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
||||||
int size, int64_t value, void* userData);
|
int size, int64_t value, void* userData);
|
||||||
void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type,
|
void handleMemoryUnmapRead(uc_engine* uc, uc_mem_type type, uint64_t address,
|
||||||
uint64_t address, int size, int64_t value,
|
int size, int64_t value, void* userData);
|
||||||
void* userData);
|
|
||||||
void handleMemoryWrite(uc_engine* uc, uc_mem_type type, uint64_t address,
|
void handleMemoryWrite(uc_engine* uc, uc_mem_type type, uint64_t address,
|
||||||
int size, int64_t value, void* userData);
|
int size, int64_t value, void* userData);
|
||||||
void handleSyscall(uc_engine* uc, void* userData);
|
void handleSyscall(uc_engine* uc, void* userData);
|
||||||
auto InitApiHooks() -> void;
|
auto InitApiHooks() -> void;
|
||||||
|
void dumpVmenv(uc_engine* uc, void* userData);
|
||||||
}; // namespace sandboxCallbacks
|
}; // namespace sandboxCallbacks
|
||||||
|
|||||||
Reference in New Issue
Block a user