fix up
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -55,6 +55,7 @@
|
|||||||
"xstddef": "cpp",
|
"xstddef": "cpp",
|
||||||
"xtr1common": "cpp",
|
"xtr1common": "cpp",
|
||||||
"xtree": "cpp",
|
"xtree": "cpp",
|
||||||
"xutility": "cpp"
|
"xutility": "cpp",
|
||||||
|
"functional": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,9 +32,8 @@ auto getPeInfo(std::string inputFilePath) -> std::shared_ptr<BasicPeInfo> {
|
|||||||
return sampleInfo;
|
return sampleInfo;
|
||||||
}
|
}
|
||||||
int main() {
|
int main() {
|
||||||
// auto sampleInfo =
|
auto sampleInfo = getPeInfo("z:\\Console_Test.exe");
|
||||||
// getPeInfo("E:\\对战平台\\CrowAntiCheat\\CrowAntiCheat\\client\\Console_Test\\x64\\Release\\Console_Test.exe");
|
// auto sampleInfo = getPeInfo("C:\\ConsoleApplication1.exe");
|
||||||
auto sampleInfo = getPeInfo("C:\\ConsoleApplication1.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);
|
||||||
@@ -42,6 +41,14 @@ int main() {
|
|||||||
auto sandbox = std::make_shared<Sandbox>();
|
auto sandbox = std::make_shared<Sandbox>();
|
||||||
sandbox->InitEnv(sampleInfo);
|
sandbox->InitEnv(sampleInfo);
|
||||||
sandbox->Run();
|
sandbox->Run();
|
||||||
|
auto [peBuffer, peSize] = sandbox->DumpPE();
|
||||||
|
|
||||||
|
if (peBuffer) {
|
||||||
|
printf("peBuffer: %p\n", peBuffer.get());
|
||||||
|
printf("peSize: %d\n", peSize);
|
||||||
|
peconv::dump_to_file("z:\\dumped_main.exe", peBuffer.get(), peSize);
|
||||||
|
}
|
||||||
|
peBuffer.release();
|
||||||
system("pause");
|
system("pause");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,10 +173,30 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建新模块
|
||||||
|
auto newModule = CreateModuleInfo(dllName, moduleBase, moduleBase);
|
||||||
|
|
||||||
|
m_moduleList.push_back(newModule);
|
||||||
|
printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule->name,
|
||||||
|
newModule->base, newModule->size);
|
||||||
|
uc_mem_map(m_ucEngine, newModule->base, newModule->size,
|
||||||
|
UC_PROT_READ | UC_PROT_EXEC);
|
||||||
|
uc_mem_write(m_ucEngine, newModule->base, (void*)moduleBase,
|
||||||
|
newModule->size);
|
||||||
|
if (peconv::relocate_module((BYTE*)moduleBase, newModule->size,
|
||||||
|
newModule->base) == false) {
|
||||||
|
throw std::runtime_error("Failed to relocate module");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase,
|
||||||
|
uint64_t bufferAddress)
|
||||||
|
-> std::shared_ptr<struct_moudle> {
|
||||||
// 解析PE头
|
// 解析PE头
|
||||||
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(moduleBase);
|
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(bufferAddress);
|
||||||
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
|
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
|
||||||
reinterpret_cast<LPBYTE>(moduleBase) + dosHeader->e_lfanew);
|
reinterpret_cast<LPBYTE>(bufferAddress) + dosHeader->e_lfanew);
|
||||||
|
|
||||||
// 获取区段对齐值
|
// 获取区段对齐值
|
||||||
DWORD sectionAlignment =
|
DWORD sectionAlignment =
|
||||||
@@ -191,7 +211,6 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void {
|
|||||||
sizeof(ntHeaders->FileHeader) +
|
sizeof(ntHeaders->FileHeader) +
|
||||||
ntHeaders->FileHeader.SizeOfOptionalHeader);
|
ntHeaders->FileHeader.SizeOfOptionalHeader);
|
||||||
|
|
||||||
// 创建新模块
|
|
||||||
struct_moudle newModule{};
|
struct_moudle newModule{};
|
||||||
strncpy(newModule.name, dllName, strlen(dllName));
|
strncpy(newModule.name, dllName, strlen(dllName));
|
||||||
newModule.base =
|
newModule.base =
|
||||||
@@ -216,9 +235,9 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void {
|
|||||||
protection |= UC_PROT_WRITE;
|
protection |= UC_PROT_WRITE;
|
||||||
|
|
||||||
// 计算区段大小
|
// 计算区段大小
|
||||||
auto sectionSize =
|
auto sectionSize = AlignToSectionAlignment(
|
||||||
AlignSize(max(section.Misc.VirtualSize, section.SizeOfRawData),
|
max(section.Misc.VirtualSize, section.SizeOfRawData),
|
||||||
sectionAlignment);
|
sectionAlignment);
|
||||||
|
|
||||||
// 创建区段信息
|
// 创建区段信息
|
||||||
moudle_section newSection{};
|
moudle_section newSection{};
|
||||||
@@ -233,17 +252,10 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void {
|
|||||||
std::cout << "[PE] " << dllName << " Section found: " << newSection.name
|
std::cout << "[PE] " << dllName << " Section found: " << newSection.name
|
||||||
<< '\n';
|
<< '\n';
|
||||||
}
|
}
|
||||||
m_moduleList.push_back(std::make_shared<struct_moudle>(newModule));
|
|
||||||
printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule.name,
|
return std::make_shared<struct_moudle>(newModule);
|
||||||
newModule.base, newModule.size);
|
|
||||||
uc_mem_map(m_ucEngine, newModule.base, newModule.size,
|
|
||||||
UC_PROT_READ | UC_PROT_EXEC);
|
|
||||||
uc_mem_write(m_ucEngine, newModule.base, (void*)moduleBase, newModule.size);
|
|
||||||
if (peconv::relocate_module((BYTE*)moduleBase, newModule.size,
|
|
||||||
newModule.base) == false) {
|
|
||||||
throw std::runtime_error("Failed to relocate module");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Sandbox::ResolveExport(uint64_t moduleBase)
|
auto Sandbox::ResolveExport(uint64_t moduleBase)
|
||||||
-> std::vector<std::shared_ptr<moudle_export>> {
|
-> std::vector<std::shared_ptr<moudle_export>> {
|
||||||
DWORD exportSize = 0;
|
DWORD exportSize = 0;
|
||||||
@@ -295,6 +307,9 @@ auto Sandbox::ResolveExport(uint64_t moduleBase)
|
|||||||
}
|
}
|
||||||
auto Sandbox::ResolveImportExports() -> void {
|
auto Sandbox::ResolveImportExports() -> void {
|
||||||
for (auto module : m_moduleList) {
|
for (auto module : m_moduleList) {
|
||||||
|
if (module->base == m_peInfo->RecImageBase) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const auto exports = ResolveExport(module->real_base);
|
const auto exports = ResolveExport(module->real_base);
|
||||||
for (const auto item : exports) {
|
for (const auto item : exports) {
|
||||||
printf("import export: [%s] %s => %llx\n", module->name, item->name,
|
printf("import export: [%s] %s => %llx\n", module->name, item->name,
|
||||||
@@ -388,8 +403,8 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
*/
|
*/
|
||||||
uint64_t m_KSharedUserDataBase = 0x7FFE0000;
|
uint64_t m_KSharedUserDataBase = 0x7FFE0000;
|
||||||
uint64_t m_KSharedUserDataEnd = 0x7FFE0FFF; // 0x7FFE2000
|
uint64_t m_KSharedUserDataEnd = 0x7FFE0FFF; // 0x7FFE2000
|
||||||
uint64_t m_KSharedUserDataSize =
|
uint64_t m_KSharedUserDataSize = AlignToSectionAlignment(
|
||||||
AlignSize(m_KSharedUserDataEnd - m_KSharedUserDataBase, PAGE_SIZE);
|
m_KSharedUserDataEnd - m_KSharedUserDataBase, PAGE_SIZE);
|
||||||
|
|
||||||
uc_mem_map(m_ucEngine, m_KSharedUserDataBase, m_KSharedUserDataSize,
|
uc_mem_map(m_ucEngine, m_KSharedUserDataBase, m_KSharedUserDataSize,
|
||||||
UC_PROT_READ);
|
UC_PROT_READ);
|
||||||
@@ -400,10 +415,10 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
m_pebBase = PEB_BASE; // 进程PEB地址
|
m_pebBase = PEB_BASE; // 进程PEB地址
|
||||||
m_envBlockBase = ENV_BLOCK_BASE; // 环境变量块地址
|
m_envBlockBase = ENV_BLOCK_BASE; // 环境变量块地址
|
||||||
// stack
|
// stack
|
||||||
m_stackBase =
|
m_stackBase = AlignToSectionAlignment(
|
||||||
AlignSize(this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32, 16);
|
this->m_peInfo->isX64 ? STACK_BASE_64 : STACK_BASE_32, 16);
|
||||||
m_stackSize =
|
m_stackSize = AlignToSectionAlignment(
|
||||||
AlignSize(this->m_peInfo->isX64 ? STACK_SIZE_64 : STACK_SIZE_32, 16);
|
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
|
||||||
@@ -415,8 +430,10 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
if (this->m_peInfo->isX64) {
|
if (this->m_peInfo->isX64) {
|
||||||
// 设置64位PEB
|
// 设置64位PEB
|
||||||
m_peb64.ImageBaseAddress = m_peInfo->RecImageBase;
|
m_peb64.ImageBaseAddress = m_peInfo->RecImageBase;
|
||||||
m_pebEnd = m_pebBase + AlignSize(sizeof(X64PEB), PAGE_SIZE);
|
m_pebEnd =
|
||||||
m_tebEnd = m_tebBase + AlignSize(sizeof(X64TEB), PAGE_SIZE);
|
m_pebBase + AlignToSectionAlignment(sizeof(X64PEB), PAGE_SIZE);
|
||||||
|
m_tebEnd =
|
||||||
|
m_tebBase + AlignToSectionAlignment(sizeof(X64TEB), PAGE_SIZE);
|
||||||
|
|
||||||
// 设置64位TEB
|
// 设置64位TEB
|
||||||
m_teb64.ClientId.UniqueProcess = GetCurrentProcessId();
|
m_teb64.ClientId.UniqueProcess = GetCurrentProcessId();
|
||||||
@@ -431,7 +448,8 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
// 设置GS基址结构
|
// 设置GS基址结构
|
||||||
m_gsBaseStruct.teb = m_tebBase;
|
m_gsBaseStruct.teb = m_tebBase;
|
||||||
m_gsBaseStruct.peb = m_pebBase;
|
m_gsBaseStruct.peb = m_pebBase;
|
||||||
uint64_t gsAllocSize = AlignSize(sizeof(struct_gs_base), PAGE_SIZE);
|
uint64_t gsAllocSize =
|
||||||
|
AlignToSectionAlignment(sizeof(struct_gs_base), PAGE_SIZE);
|
||||||
|
|
||||||
// 映射PEB到虚拟内存
|
// 映射PEB到虚拟内存
|
||||||
uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase,
|
uc_mem_map(m_ucEngine, m_pebBase, m_pebEnd - m_pebBase,
|
||||||
@@ -456,8 +474,10 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
} else {
|
} else {
|
||||||
// 设置32位PEB
|
// 设置32位PEB
|
||||||
m_peb32.ImageBaseAddress = static_cast<ULONG>(m_peInfo->RecImageBase);
|
m_peb32.ImageBaseAddress = static_cast<ULONG>(m_peInfo->RecImageBase);
|
||||||
m_pebEnd = m_pebBase + AlignSize(sizeof(X32PEB), PAGE_SIZE);
|
m_pebEnd =
|
||||||
m_tebEnd = m_tebBase + AlignSize(sizeof(X32TEB), PAGE_SIZE);
|
m_pebBase + AlignToSectionAlignment(sizeof(X32PEB), PAGE_SIZE);
|
||||||
|
m_tebEnd =
|
||||||
|
m_tebBase + AlignToSectionAlignment(sizeof(X32TEB), PAGE_SIZE);
|
||||||
|
|
||||||
// 设置32位TEB
|
// 设置32位TEB
|
||||||
m_teb32.ClientId.UniqueProcess = GetCurrentProcessId();
|
m_teb32.ClientId.UniqueProcess = GetCurrentProcessId();
|
||||||
@@ -491,7 +511,8 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr);
|
uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr);
|
||||||
}
|
}
|
||||||
// 映射新的内存区域
|
// 映射新的内存区域
|
||||||
size_t envSize = AlignSize(this->GetEnvStringsSize(), PAGE_SIZE);
|
size_t envSize =
|
||||||
|
AlignToSectionAlignment(this->GetEnvStringsSize(), PAGE_SIZE);
|
||||||
printf("env block size: %llx\n", envSize); // 添加调试输出
|
printf("env block size: %llx\n", envSize); // 添加调试输出
|
||||||
uc_err envErr = uc_mem_map(m_ucEngine, m_envBlockBase, envSize,
|
uc_err envErr = uc_mem_map(m_ucEngine, m_envBlockBase, envSize,
|
||||||
UC_PROT_READ | UC_PROT_WRITE);
|
UC_PROT_READ | UC_PROT_WRITE);
|
||||||
@@ -524,6 +545,13 @@ auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
|
|||||||
cs_close(&m_csHandle); // 清理已分配的capstone资源
|
cs_close(&m_csHandle); // 清理已分配的capstone资源
|
||||||
throw std::runtime_error("Failed to initialize Unicorn");
|
throw std::runtime_error("Failed to initialize Unicorn");
|
||||||
}
|
}
|
||||||
|
// 一定要确保他是第一个.
|
||||||
|
auto newModule =
|
||||||
|
CreateModuleInfo("huoji.exe", m_peInfo->RecImageBase,
|
||||||
|
reinterpret_cast<uint64_t>(m_peInfo->peBuffer));
|
||||||
|
_ASSERTE(m_moduleList.size() == 0);
|
||||||
|
m_moduleList.push_back(newModule);
|
||||||
|
|
||||||
ResoveImport();
|
ResoveImport();
|
||||||
ResolveImportExports();
|
ResolveImportExports();
|
||||||
|
|
||||||
@@ -702,3 +730,342 @@ auto Sandbox::GetEnvString() -> std::vector<wchar_t> {
|
|||||||
auto Sandbox::GetEnvStringsSize() -> size_t {
|
auto Sandbox::GetEnvStringsSize() -> size_t {
|
||||||
return GetEnvString().size() * sizeof(wchar_t);
|
return GetEnvString().size() * sizeof(wchar_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Sandbox::getVirtualMemorySize(BYTE* peBuffer) -> size_t {
|
||||||
|
if (!peBuffer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析PE头
|
||||||
|
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(peBuffer);
|
||||||
|
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(
|
||||||
|
reinterpret_cast<LPBYTE>(peBuffer) + dosHeader->e_lfanew);
|
||||||
|
// 获取区段头
|
||||||
|
auto* sectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||||
|
reinterpret_cast<PUCHAR>(ntHeaders) + sizeof(ntHeaders->Signature) +
|
||||||
|
sizeof(ntHeaders->FileHeader) +
|
||||||
|
ntHeaders->FileHeader.SizeOfOptionalHeader);
|
||||||
|
|
||||||
|
DWORD minOffset = UINT_MAX;
|
||||||
|
DWORD totalSize = 0;
|
||||||
|
|
||||||
|
// 遍历所有区段
|
||||||
|
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
|
||||||
|
const auto& section = sectionHeader[i];
|
||||||
|
|
||||||
|
// 查找最小虚拟地址偏移
|
||||||
|
if (section.VirtualAddress < minOffset) {
|
||||||
|
minOffset = section.VirtualAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 累加虚拟大小
|
||||||
|
totalSize += section.Misc.VirtualSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加最小偏移到总大小
|
||||||
|
totalSize += minOffset;
|
||||||
|
|
||||||
|
return static_cast<size_t>(totalSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Sandbox::DumpPE() -> std::pair<std::unique_ptr<BYTE[]>, size_t> {
|
||||||
|
// 查找目标模块 - 这里我们使用主模块(通常是被分析的可执行文件)
|
||||||
|
std::shared_ptr<struct_moudle> targetModule = nullptr;
|
||||||
|
for (const auto& module : m_moduleList) {
|
||||||
|
if (strcmp(module->name, "huoji.exe") == 0) {
|
||||||
|
targetModule = module;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetModule) {
|
||||||
|
throw std::runtime_error("No modules found to dump");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算虚拟内存大小
|
||||||
|
auto virtualMemorySize = getVirtualMemorySize(m_peInfo->peBuffer);
|
||||||
|
|
||||||
|
// 创建用于存储转储数据的缓冲区
|
||||||
|
auto resultBuffer = std::make_unique<BYTE[]>(virtualMemorySize);
|
||||||
|
|
||||||
|
// 从虚拟机内存中读取PE文件
|
||||||
|
uc_err err = uc_mem_read(m_ucEngine, m_peInfo->RecImageBase,
|
||||||
|
resultBuffer.get(), virtualMemorySize);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
throw std::runtime_error("Failed to read memory during PE dump: " +
|
||||||
|
std::string(uc_strerror(err)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保PE头部的签名有效
|
||||||
|
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(resultBuffer.get());
|
||||||
|
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
|
throw std::runtime_error("Invalid DOS signature in dumped PE");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(resultBuffer.get() +
|
||||||
|
dosHeader->e_lfanew);
|
||||||
|
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
|
throw std::runtime_error("Invalid NT signature in dumped PE");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前RIP/EIP作为新的入口点
|
||||||
|
uint64_t currentEntryPoint = 0;
|
||||||
|
if (this->GetCrossSectionExecution().size() > 0) {
|
||||||
|
currentEntryPoint = this->GetCrossSectionExecution()
|
||||||
|
[this->GetCrossSectionExecution().size() - 1] -
|
||||||
|
m_peInfo->RecImageBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
PIMAGE_SECTION_HEADER sectionHeaders = nullptr;
|
||||||
|
WORD numberOfSections = 0;
|
||||||
|
|
||||||
|
// 处理32位或64位PE文件
|
||||||
|
if (m_peInfo->isX64) {
|
||||||
|
auto* optHeader64 =
|
||||||
|
&reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)->OptionalHeader;
|
||||||
|
optHeader64->ImageBase = m_peInfo->RecImageBase;
|
||||||
|
if (currentEntryPoint != 0) {
|
||||||
|
// 修改入口点为当前执行位置
|
||||||
|
optHeader64->AddressOfEntryPoint =
|
||||||
|
static_cast<DWORD>(currentEntryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改SizeOfImage
|
||||||
|
optHeader64->SizeOfImage = static_cast<DWORD>(AlignToSectionAlignment(
|
||||||
|
virtualMemorySize, optHeader64->SectionAlignment));
|
||||||
|
|
||||||
|
// 修改DllCharacteristics以移除ASLR标记
|
||||||
|
optHeader64->DllCharacteristics &=
|
||||||
|
~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
|
||||||
|
|
||||||
|
// 获取区段头信息
|
||||||
|
sectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||||
|
reinterpret_cast<ULONG_PTR>(ntHeaders) +
|
||||||
|
sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) +
|
||||||
|
ntHeaders->FileHeader.SizeOfOptionalHeader);
|
||||||
|
numberOfSections = ntHeaders->FileHeader.NumberOfSections;
|
||||||
|
} else {
|
||||||
|
auto* optHeader32 =
|
||||||
|
&reinterpret_cast<PIMAGE_NT_HEADERS32>(ntHeaders)->OptionalHeader;
|
||||||
|
optHeader32->ImageBase = static_cast<DWORD>(m_peInfo->RecImageBase);
|
||||||
|
|
||||||
|
if (currentEntryPoint != 0) {
|
||||||
|
// 修改入口点为当前执行位置
|
||||||
|
optHeader32->AddressOfEntryPoint =
|
||||||
|
static_cast<DWORD>(currentEntryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改SizeOfImage
|
||||||
|
optHeader32->SizeOfImage = static_cast<DWORD>(AlignToSectionAlignment(
|
||||||
|
virtualMemorySize, optHeader32->SectionAlignment));
|
||||||
|
|
||||||
|
// 修改DllCharacteristics以移除ASLR标记
|
||||||
|
optHeader32->DllCharacteristics &=
|
||||||
|
~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
|
||||||
|
|
||||||
|
// 获取区段头信息
|
||||||
|
sectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||||
|
reinterpret_cast<ULONG_PTR>(ntHeaders) +
|
||||||
|
sizeof(ntHeaders->Signature) + sizeof(ntHeaders->FileHeader) +
|
||||||
|
ntHeaders->FileHeader.SizeOfOptionalHeader);
|
||||||
|
numberOfSections = ntHeaders->FileHeader.NumberOfSections;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新代码基址和大小
|
||||||
|
UpdateBaseOfCode(sectionHeaders, ntHeaders, numberOfSections,
|
||||||
|
static_cast<DWORD>(currentEntryPoint));
|
||||||
|
|
||||||
|
// 修复区段
|
||||||
|
FixSections(sectionHeaders, numberOfSections, virtualMemorySize);
|
||||||
|
|
||||||
|
// 创建一个ExportsMapper对象用于导入表修复
|
||||||
|
peconv::ExportsMapper exportsMap;
|
||||||
|
|
||||||
|
// 添加所有已加载模块到导出表映射中
|
||||||
|
for (const auto& module : m_moduleList) {
|
||||||
|
if (module->base == 0 || module->size == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建临时缓冲区以存储模块内容
|
||||||
|
std::unique_ptr<BYTE[]> moduleBuffer =
|
||||||
|
std::make_unique<BYTE[]>(module->size);
|
||||||
|
|
||||||
|
// 从虚拟机内存读取模块内容
|
||||||
|
uc_err readErr = uc_mem_read(m_ucEngine, module->base,
|
||||||
|
moduleBuffer.get(), module->size);
|
||||||
|
if (readErr != UC_ERR_OK) {
|
||||||
|
printf(
|
||||||
|
"Warning: Could not read module %s for exports mapping: %s\n",
|
||||||
|
module->name, uc_strerror(readErr));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加模块到导出表映射
|
||||||
|
exportsMap.add_to_lookup(module->name,
|
||||||
|
reinterpret_cast<HMODULE>(moduleBuffer.get()),
|
||||||
|
module->base);
|
||||||
|
}
|
||||||
|
//这里有一个严重的问题,就懒得处理了:
|
||||||
|
//壳里面吐出来的代码的导入表和壳的导入表不是同样一个.
|
||||||
|
//这个修的是壳的 导入表,所以导入表 修 不 全
|
||||||
|
//有个很简单的办法,需要搜索IAT结构,然后修改脱壳后的IAT的字段到壳的字段里面,然后再执行一次fix_imports
|
||||||
|
//懒得写了,家庭作业.自己完成
|
||||||
|
bool importsFixed = peconv::fix_imports(
|
||||||
|
resultBuffer.get(), virtualMemorySize, exportsMap, nullptr);
|
||||||
|
if (importsFixed) {
|
||||||
|
printf("PE file imports fixed successfully\n");
|
||||||
|
} else {
|
||||||
|
printf("Warning: Failed to fix PE file imports\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t out_size = 0;
|
||||||
|
|
||||||
|
// 重新计算校验和
|
||||||
|
if (m_peInfo->isX64) {
|
||||||
|
auto* optHeader64 =
|
||||||
|
&reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)->OptionalHeader;
|
||||||
|
optHeader64->CheckSum =
|
||||||
|
CalculateChecksum(resultBuffer.get(), virtualMemorySize);
|
||||||
|
} else {
|
||||||
|
auto* optHeader32 =
|
||||||
|
&reinterpret_cast<PIMAGE_NT_HEADERS32>(ntHeaders)->OptionalHeader;
|
||||||
|
optHeader32->CheckSum =
|
||||||
|
CalculateChecksum(resultBuffer.get(), virtualMemorySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"PE file dumped successfully from address: 0x%llx, size: %zu bytes\n",
|
||||||
|
m_peInfo->RecImageBase, virtualMemorySize);
|
||||||
|
printf("Entry point set to: 0x%llx (RVA: 0x%llx)\n",
|
||||||
|
m_peInfo->RecImageBase + currentEntryPoint, currentEntryPoint);
|
||||||
|
|
||||||
|
return {std::move(resultBuffer), virtualMemorySize};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复区段信息
|
||||||
|
void Sandbox::FixSections(PIMAGE_SECTION_HEADER sectionHeaders,
|
||||||
|
WORD numberOfSections, size_t virtualMemorySize) {
|
||||||
|
if (numberOfSections == 0 || sectionHeaders == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复每个区段的信息
|
||||||
|
for (WORD i = 0; i < numberOfSections - 1; i++) {
|
||||||
|
auto& currentSection = sectionHeaders[i];
|
||||||
|
auto& nextSection = sectionHeaders[i + 1];
|
||||||
|
|
||||||
|
// 修复大小,使之与下一个区段的起始地址对齐
|
||||||
|
currentSection.SizeOfRawData =
|
||||||
|
nextSection.VirtualAddress - currentSection.VirtualAddress;
|
||||||
|
currentSection.PointerToRawData = currentSection.VirtualAddress;
|
||||||
|
currentSection.Misc.VirtualSize = currentSection.SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复最后一个区段
|
||||||
|
auto& lastSection = sectionHeaders[numberOfSections - 1];
|
||||||
|
lastSection.SizeOfRawData =
|
||||||
|
static_cast<DWORD>(virtualMemorySize) - lastSection.VirtualAddress;
|
||||||
|
lastSection.PointerToRawData = lastSection.VirtualAddress;
|
||||||
|
lastSection.Misc.VirtualSize = lastSection.SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算校验和
|
||||||
|
DWORD Sandbox::CalculateChecksum(const BYTE* peBuffer, size_t size) {
|
||||||
|
DWORD sum = 0;
|
||||||
|
const DWORD* ptr = reinterpret_cast<const DWORD*>(peBuffer);
|
||||||
|
const DWORD count = static_cast<DWORD>(size / sizeof(DWORD));
|
||||||
|
|
||||||
|
// 获取校验和字段的偏移
|
||||||
|
const auto dosHeader = (PIMAGE_DOS_HEADER)(peBuffer);
|
||||||
|
const auto ntHeaders = (PIMAGE_NT_HEADERS)(peBuffer + dosHeader->e_lfanew);
|
||||||
|
DWORD checksumOffset = dosHeader->e_lfanew +
|
||||||
|
FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) +
|
||||||
|
FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum);
|
||||||
|
|
||||||
|
// 计算总和,跳过校验和字段本身
|
||||||
|
for (DWORD i = 0; i < count; i++) {
|
||||||
|
// 跳过校验和字段
|
||||||
|
if ((i * sizeof(DWORD)) == checksumOffset ||
|
||||||
|
(i * sizeof(DWORD)) == checksumOffset + sizeof(DWORD) - 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sum += ptr[i];
|
||||||
|
// 处理溢出
|
||||||
|
if (sum < ptr[i]) {
|
||||||
|
sum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 完成计算
|
||||||
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
sum = sum + static_cast<DWORD>(size);
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按区段对齐大小进行对齐
|
||||||
|
DWORD Sandbox::AlignToSectionAlignment(size_t size, DWORD alignment) {
|
||||||
|
return static_cast<DWORD>(((size + alignment - 1) / alignment) * alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新代码基址和代码大小
|
||||||
|
void Sandbox::UpdateBaseOfCode(PIMAGE_SECTION_HEADER sectionHeader,
|
||||||
|
PIMAGE_NT_HEADERS ntHeaders,
|
||||||
|
WORD numberOfSections, DWORD entryPoint) {
|
||||||
|
if (sectionHeader == nullptr || ntHeaders == nullptr ||
|
||||||
|
numberOfSections == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD baseOfCode = 0;
|
||||||
|
DWORD sizeOfCode = 0;
|
||||||
|
bool foundSection = false;
|
||||||
|
|
||||||
|
// 寻找包含入口点的区段
|
||||||
|
for (WORD i = 0; i < numberOfSections; i++) {
|
||||||
|
auto& section = sectionHeader[i];
|
||||||
|
if (entryPoint >= section.VirtualAddress &&
|
||||||
|
entryPoint < (section.VirtualAddress + section.Misc.VirtualSize)) {
|
||||||
|
baseOfCode = section.VirtualAddress;
|
||||||
|
sizeOfCode = section.Misc.VirtualSize;
|
||||||
|
foundSection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到包含入口点的区段,使用第一个可执行区段
|
||||||
|
if (!foundSection) {
|
||||||
|
for (WORD i = 0; i < numberOfSections; i++) {
|
||||||
|
auto& section = sectionHeader[i];
|
||||||
|
if (section.Characteristics & IMAGE_SCN_MEM_EXECUTE) {
|
||||||
|
baseOfCode = section.VirtualAddress;
|
||||||
|
sizeOfCode = section.Misc.VirtualSize;
|
||||||
|
foundSection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新NT头部信息
|
||||||
|
if (foundSection) {
|
||||||
|
if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
|
||||||
|
// 64位PE
|
||||||
|
auto* optHeader64 =
|
||||||
|
&reinterpret_cast<PIMAGE_NT_HEADERS64>(ntHeaders)
|
||||||
|
->OptionalHeader;
|
||||||
|
optHeader64->BaseOfCode = baseOfCode;
|
||||||
|
} else {
|
||||||
|
// 32位PE
|
||||||
|
auto* optHeader32 =
|
||||||
|
&reinterpret_cast<PIMAGE_NT_HEADERS32>(ntHeaders)
|
||||||
|
->OptionalHeader;
|
||||||
|
optHeader32->BaseOfCode = baseOfCode;
|
||||||
|
optHeader32->SizeOfCode = sizeOfCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -111,6 +111,46 @@ class Sandbox {
|
|||||||
auto SplitBlock(HeapBlock* block, size_t size) -> void;
|
auto SplitBlock(HeapBlock* block, size_t size) -> void;
|
||||||
auto GetEnvBlockBase() const -> uint64_t { return m_envBlockBase; }
|
auto GetEnvBlockBase() const -> uint64_t { return m_envBlockBase; }
|
||||||
std::map<uint64_t, HeapSegment*> m_heapSegments; // 堆段映射表
|
std::map<uint64_t, HeapSegment*> m_heapSegments; // 堆段映射表
|
||||||
|
auto GetHeapBlocks() const -> std::map<uint64_t, HeapSegment*> {
|
||||||
|
return m_heapSegments;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从内存中提取PE文件并修复重定位和导入表,返回原始PE的缓冲区
|
||||||
|
auto DumpPE() -> std::pair<std::unique_ptr<BYTE[]>, size_t>;
|
||||||
|
|
||||||
|
// 计算PE文件的虚拟内存大小
|
||||||
|
auto getVirtualMemorySize(BYTE* peBuffer) -> size_t;
|
||||||
|
|
||||||
|
// 修复PE区段信息
|
||||||
|
void FixSections(PIMAGE_SECTION_HEADER sectionHeader, WORD numberOfSections,
|
||||||
|
size_t virtualMemorySize);
|
||||||
|
|
||||||
|
// 更新代码基址和大小
|
||||||
|
void UpdateBaseOfCode(PIMAGE_SECTION_HEADER sectionHeader,
|
||||||
|
PIMAGE_NT_HEADERS ntHeaders, WORD numberOfSections,
|
||||||
|
DWORD entryPoint);
|
||||||
|
|
||||||
|
// 对齐到区段对齐值
|
||||||
|
DWORD AlignToSectionAlignment(size_t size, DWORD alignment);
|
||||||
|
|
||||||
|
// 计算PE校验和
|
||||||
|
DWORD CalculateChecksum(const BYTE* buffer, size_t size);
|
||||||
|
|
||||||
|
auto SetupVirtualMachine() -> void;
|
||||||
|
auto PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void;
|
||||||
|
auto processImportModule(const moudle_import* importModule) -> void;
|
||||||
|
auto GetCrossSectionExecution() -> std::vector<uint64_t> {
|
||||||
|
return m_crossSectionExecution;
|
||||||
|
}
|
||||||
|
auto GetLastExecuteSectionIndex() -> uint64_t {
|
||||||
|
return m_lastExecuteSectionIndex;
|
||||||
|
}
|
||||||
|
auto SetLastExecuteSectionIndex(uint64_t index) -> void {
|
||||||
|
m_lastExecuteSectionIndex = index;
|
||||||
|
}
|
||||||
|
auto SetCrossSectionExecution(uint64_t address) -> void {
|
||||||
|
return m_crossSectionExecution.push_back(address);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<BasicPeInfo> m_peInfo;
|
std::shared_ptr<BasicPeInfo> m_peInfo;
|
||||||
@@ -167,12 +207,14 @@ class Sandbox {
|
|||||||
L"USERPROFILE=C:\\Users\\User",
|
L"USERPROFILE=C:\\Users\\User",
|
||||||
L"windir=C:\\Windows"};
|
L"windir=C:\\Windows"};
|
||||||
auto ResoveImport() -> void;
|
auto ResoveImport() -> void;
|
||||||
auto SetupVirtualMachine() -> void;
|
|
||||||
auto PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void;
|
|
||||||
auto processImportModule(const moudle_import* importModule) -> void;
|
|
||||||
auto ResolveImportExports() -> void;
|
auto ResolveImportExports() -> void;
|
||||||
|
auto CreateModuleInfo(const char* dllName, uint64_t moduleBase,
|
||||||
|
uint64_t bufferAddress)
|
||||||
|
-> std::shared_ptr<struct_moudle>;
|
||||||
auto ResolveExport(uint64_t moduleBase)
|
auto ResolveExport(uint64_t moduleBase)
|
||||||
-> std::vector<std::shared_ptr<moudle_export>>;
|
-> std::vector<std::shared_ptr<moudle_export>>;
|
||||||
auto InitApiHooks() -> void;
|
auto InitApiHooks() -> void;
|
||||||
auto InitCommandLine(std::string commandLine) -> void;
|
auto InitCommandLine(std::string commandLine) -> void;
|
||||||
|
std::vector<uint64_t> m_crossSectionExecution; // 记录跨区段执行地址
|
||||||
|
uint64_t m_lastExecuteSectionIndex = 0; // 上次执行的区段索引
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2047,6 +2047,132 @@ auto Api_SetUnhandledExceptionFilter(void* sandbox, uc_engine* uc,
|
|||||||
&prev_filter);
|
&prev_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将Windows VirtualProtect保护标志转换为Unicorn内存保护标志
|
||||||
|
uint32_t WindowsToUnicornProtect(uint32_t windowsProtect) {
|
||||||
|
uint32_t unicornProtect = UC_PROT_NONE;
|
||||||
|
|
||||||
|
// 转换基本属性
|
||||||
|
if (windowsProtect & (PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ |
|
||||||
|
PAGE_EXECUTE_READWRITE)) {
|
||||||
|
unicornProtect |= UC_PROT_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (windowsProtect & (PAGE_READWRITE | PAGE_WRITECOPY |
|
||||||
|
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) {
|
||||||
|
unicornProtect |= UC_PROT_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (windowsProtect & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
|
||||||
|
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) {
|
||||||
|
unicornProtect |= UC_PROT_EXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有有效标志,至少给予读权限以防崩溃
|
||||||
|
if (unicornProtect == UC_PROT_NONE && windowsProtect != PAGE_NOACCESS) {
|
||||||
|
unicornProtect = UC_PROT_READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unicornProtect;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Api_VirtualProtect(void* sandbox, uc_engine* uc, uint64_t address)
|
||||||
|
-> void {
|
||||||
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
|
uint64_t lpAddress = 0;
|
||||||
|
uint64_t dwSize = 0;
|
||||||
|
uint32_t flNewProtect = 0;
|
||||||
|
uint64_t lpflOldProtect = 0;
|
||||||
|
|
||||||
|
// 获取参数
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
// x64: rcx = lpAddress, rdx = dwSize, r8 = flNewProtect, r9 =
|
||||||
|
// lpflOldProtect
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RCX, &lpAddress);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RDX, &dwSize);
|
||||||
|
uint64_t temp_protect;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R8, &temp_protect);
|
||||||
|
flNewProtect = static_cast<uint32_t>(temp_protect);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_R9, &lpflOldProtect);
|
||||||
|
} else {
|
||||||
|
// x86: 从栈上读取参数
|
||||||
|
uint32_t esp_address = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||||
|
esp_address += 0x4; // 跳过返回地址
|
||||||
|
|
||||||
|
uint32_t temp_address;
|
||||||
|
uc_mem_read(uc, esp_address, &temp_address, sizeof(uint32_t));
|
||||||
|
lpAddress = temp_address;
|
||||||
|
esp_address += 0x4;
|
||||||
|
|
||||||
|
uint32_t temp_size;
|
||||||
|
uc_mem_read(uc, esp_address, &temp_size, sizeof(uint32_t));
|
||||||
|
dwSize = temp_size;
|
||||||
|
esp_address += 0x4;
|
||||||
|
|
||||||
|
uc_mem_read(uc, esp_address, &flNewProtect, sizeof(uint32_t));
|
||||||
|
esp_address += 0x4;
|
||||||
|
|
||||||
|
uint32_t temp_old_protect;
|
||||||
|
uc_mem_read(uc, esp_address, &temp_old_protect, sizeof(uint32_t));
|
||||||
|
lpflOldProtect = temp_old_protect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查参数有效性
|
||||||
|
if (lpAddress == 0 || dwSize == 0 || lpflOldProtect == 0) {
|
||||||
|
uint64_t result = 0; // FALSE
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
// 设置错误码 - ERROR_INVALID_PARAMETER
|
||||||
|
DWORD error = ERROR_INVALID_PARAMETER;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查地址范围是否已映射
|
||||||
|
uint32_t unicornProtect = WindowsToUnicornProtect(flNewProtect);
|
||||||
|
uc_err err = uc_mem_protect(uc, lpAddress, dwSize, unicornProtect);
|
||||||
|
if (err != UC_ERR_OK) {
|
||||||
|
uint64_t result = 0; // FALSE
|
||||||
|
uc_reg_write(
|
||||||
|
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&result);
|
||||||
|
|
||||||
|
// 设置错误码 - ERROR_INVALID_ADDRESS
|
||||||
|
DWORD error = ERROR_INVALID_ADDRESS;
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
context->GetTeb64()->LastErrorValue = error;
|
||||||
|
} else {
|
||||||
|
context->GetTeb32()->LastErrorValue = error;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟的旧保护属性,这里简化为一个默认值
|
||||||
|
// 实际应用中,应该从内存映射表中获取
|
||||||
|
uint32_t oldProtect = PAGE_READWRITE;
|
||||||
|
|
||||||
|
// 写入旧保护值到lpflOldProtect指向的内存
|
||||||
|
uc_mem_write(uc, lpflOldProtect, &oldProtect, sizeof(uint32_t));
|
||||||
|
|
||||||
|
// 调试输出
|
||||||
|
printf(
|
||||||
|
"[*] VirtualProtect: Address=0x%llx, Size=0x%llx, WindowsProtect=0x%x, "
|
||||||
|
"UnicornProtect=0x%x, OldProtect=0x%x\n",
|
||||||
|
lpAddress, dwSize, flNewProtect, unicornProtect, oldProtect);
|
||||||
|
|
||||||
|
// 设置返回值为TRUE
|
||||||
|
uint64_t result = 1; // TRUE
|
||||||
|
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};
|
||||||
@@ -2113,6 +2239,8 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
_fakeApi{.func = Api_FreeEnvironmentStringsW, .paramCount = 1};
|
_fakeApi{.func = Api_FreeEnvironmentStringsW, .paramCount = 1};
|
||||||
auto FakeApi_SetUnhandledExceptionFilter =
|
auto FakeApi_SetUnhandledExceptionFilter =
|
||||||
_fakeApi{.func = Api_SetUnhandledExceptionFilter, .paramCount = 1};
|
_fakeApi{.func = Api_SetUnhandledExceptionFilter, .paramCount = 1};
|
||||||
|
auto FakeApi_VirtualProtect =
|
||||||
|
_fakeApi{.func = Api_VirtualProtect, .paramCount = 4};
|
||||||
|
|
||||||
api_map = {
|
api_map = {
|
||||||
{"GetSystemTimeAsFileTime",
|
{"GetSystemTimeAsFileTime",
|
||||||
@@ -2171,6 +2299,7 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
std::make_shared<_fakeApi>(FakeApi_FreeEnvironmentStringsW)},
|
std::make_shared<_fakeApi>(FakeApi_FreeEnvironmentStringsW)},
|
||||||
{"SetUnhandledExceptionFilter",
|
{"SetUnhandledExceptionFilter",
|
||||||
std::make_shared<_fakeApi>(FakeApi_SetUnhandledExceptionFilter)},
|
std::make_shared<_fakeApi>(FakeApi_SetUnhandledExceptionFilter)},
|
||||||
|
{"VirtualProtect", std::make_shared<_fakeApi>(FakeApi_VirtualProtect)},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "sandbox_callbacks.h"
|
#include "sandbox_callbacks.h"
|
||||||
#define LOG_LEVEL 1
|
#define LOG_LEVEL 0
|
||||||
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) {
|
||||||
@@ -24,6 +24,39 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
|
|||||||
uc_reg_read(uc,
|
uc_reg_read(uc,
|
||||||
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP,
|
sandbox->GetPeInfo()->isX64 ? UC_X86_REG_RSP : UC_X86_REG_ESP,
|
||||||
¤tRsp);
|
¤tRsp);
|
||||||
|
|
||||||
|
// 检查当前执行地址所在区段
|
||||||
|
int currentSectionIndex = -1;
|
||||||
|
for (size_t i = 0; i < sandbox->GetModuleList()[0]->sections.size(); i++) {
|
||||||
|
auto section = sandbox->GetModuleList()[0]->sections[i];
|
||||||
|
uint64_t sectionStart =
|
||||||
|
sandbox->GetPeInfo()->RecImageBase + section->base;
|
||||||
|
uint64_t sectionEnd = sectionStart + section->size;
|
||||||
|
|
||||||
|
if (address >= sectionStart && address < sectionEnd) {
|
||||||
|
currentSectionIndex = static_cast<int>(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果找到区段,并且与上次执行的区段不同,记录跨区段行为
|
||||||
|
if (currentSectionIndex >= 0 &&
|
||||||
|
sandbox->GetLastExecuteSectionIndex() != currentSectionIndex &&
|
||||||
|
sandbox->GetLastExecuteSectionIndex() != 0) {
|
||||||
|
printf(
|
||||||
|
"[!!!]detect cross section excute, from %d to %d,address: 0x%llx\n",
|
||||||
|
sandbox->GetLastExecuteSectionIndex(), currentSectionIndex,
|
||||||
|
address);
|
||||||
|
|
||||||
|
// 记录跨区段执行地址
|
||||||
|
sandbox->SetCrossSectionExecution(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新上次执行的区段
|
||||||
|
if (currentSectionIndex >= 0) {
|
||||||
|
sandbox->SetLastExecuteSectionIndex(currentSectionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto module : sandbox->GetModuleList()) {
|
for (auto module : sandbox->GetModuleList()) {
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user