aboutsummaryrefslogtreecommitdiff
path: root/unit-tests/pefile_tests.cc
diff options
context:
space:
mode:
Diffstat (limited to 'unit-tests/pefile_tests.cc')
-rw-r--r--unit-tests/pefile_tests.cc553
1 files changed, 553 insertions, 0 deletions
diff --git a/unit-tests/pefile_tests.cc b/unit-tests/pefile_tests.cc
new file mode 100644
index 0000000..f6d14f0
--- /dev/null
+++ b/unit-tests/pefile_tests.cc
@@ -0,0 +1,553 @@
+#include "../runtime/common.h"
+#include "../runtime/crypto.h"
+#include "../core/objects.h"
+#include "../core/osutils.h"
+#include "../core/streams.h"
+#include "../core/core.h"
+#include "../core/files.h"
+#include "../core/processors.h"
+#include "../core/pefile.h"
+#include "../core/packer.h"
+#include "../third-party/lzma/LzmaDecode.h"
+
+#ifdef DEMO
+ #include "../core/win_runtime32demo.dll.inc"
+ #include "../core/win_runtime64demo.dll.inc"
+#else
+ #include "../core/win_runtime32.dll.inc"
+ #include "../core/win_runtime64.dll.inc"
+#endif
+
+#ifdef VMP_GNU
+ #include <stdlib.h>
+#endif
+
+TEST(PEFileTest, OpenEXE)
+{
+ // Test: read header of Win32/Intel file. Read should finish successfully.
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
+ // Check architectures.
+ ASSERT_EQ(pf.count(), 1ul);
+ PEArchitecture *arch = pf.arch_pe();
+ EXPECT_EQ(arch->name().compare("i386"), 0);
+ EXPECT_EQ(arch->owner()->format_name().compare("PE"), 0);
+ EXPECT_EQ(arch->cpu_address_size(), osDWord);
+ EXPECT_EQ(arch->image_base(), 0x400000ull);
+ EXPECT_EQ(arch->entry_point(), 0x401000ull);
+ // Check segments.
+ ISectionList *segment_list = arch->segment_list();
+ ASSERT_EQ(segment_list->count(), 3ul);
+ EXPECT_EQ(segment_list->item(0)->name().compare(".text"), 0);
+ EXPECT_EQ(segment_list->item(1)->name().compare(".rdata"), 0);
+ EXPECT_EQ(segment_list->item(2)->name().compare(".data"), 0);
+ EXPECT_EQ((int)segment_list->item(0)->memory_type(), (mtReadable | mtExecutable));
+ EXPECT_EQ((int)segment_list->item(1)->memory_type(), mtReadable);
+ EXPECT_EQ((int)segment_list->item(2)->memory_type(), (mtReadable | mtWritable));
+ // Check imports.
+ IImportList *imp = arch->import_list();
+ ASSERT_EQ(imp->count(), 3ul);
+ EXPECT_EQ(imp->item(0)->name().compare("user32.dll"), 0);
+ ASSERT_EQ(imp->item(0)->count(), 6ul);
+ EXPECT_EQ(imp->item(0)->item(0)->name().compare("SetFocus"), 0);
+ EXPECT_EQ(imp->item(0)->item(0)->address(), 0x402028ull);
+ EXPECT_EQ(imp->item(0)->item(1)->name().compare("MessageBoxA"), 0);
+ EXPECT_EQ(imp->item(0)->item(1)->address(), 0x40202cull);
+ EXPECT_EQ(imp->item(0)->item(2)->name().compare("GetDlgItemTextA"), 0);
+ EXPECT_EQ(imp->item(0)->item(2)->address(), 0x402030ull);
+ EXPECT_EQ(imp->item(0)->item(3)->name().compare("GetDlgItem"), 0);
+ EXPECT_EQ(imp->item(0)->item(3)->address(), 0x402034ull);
+ EXPECT_EQ(imp->item(0)->item(4)->name().compare("EndDialog"), 0);
+ EXPECT_EQ(imp->item(0)->item(4)->address(), 0x402038ull);
+ EXPECT_EQ(imp->item(0)->item(5)->name().compare("DialogBoxIndirectParamA"), 0);
+ EXPECT_EQ(imp->item(0)->item(5)->address(), 0x40203cull);
+ EXPECT_EQ(imp->item(1)->name().compare("kernel32.dll"), 0);
+ ASSERT_EQ(imp->item(1)->count(), 5ul);
+ EXPECT_EQ(imp->item(1)->item(0)->name().compare("MultiByteToWideChar"), 0);
+ EXPECT_EQ(imp->item(1)->item(0)->address(), 0x402010ull);
+ EXPECT_EQ(imp->item(1)->item(1)->name().compare("GlobalFree"), 0);
+ EXPECT_EQ(imp->item(1)->item(1)->address(), 0x402014ull);
+ EXPECT_EQ(imp->item(1)->item(2)->name().compare("ExitProcess"), 0);
+ EXPECT_EQ(imp->item(1)->item(2)->address(), 0x402018ull);
+ EXPECT_EQ(imp->item(1)->item(3)->name().compare("GetModuleHandleA"), 0);
+ EXPECT_EQ(imp->item(1)->item(3)->address(), 0x40201cull);
+ EXPECT_EQ(imp->item(1)->item(4)->name().compare("GlobalAlloc"), 0);
+ EXPECT_EQ(imp->item(1)->item(4)->address(), 0x402020ull);
+ EXPECT_EQ(imp->item(2)->name().compare("VMProtectSDK32.dll"), 0);
+ ASSERT_EQ(imp->item(2)->count(), 3ul);
+ EXPECT_EQ(imp->item(2)->item(0)->name().compare("VMProtectDecryptStringA"), 0);
+ EXPECT_EQ(imp->item(2)->item(0)->address(), 0x402000ull);
+ EXPECT_EQ(imp->item(2)->item(1)->name().compare("VMProtectEnd"), 0);
+ EXPECT_EQ(imp->item(2)->item(1)->address(), 0x402004ull);
+ EXPECT_EQ(imp->item(2)->item(2)->name().compare("VMProtectBegin"), 0);
+ EXPECT_EQ(imp->item(2)->item(2)->address(), 0x402008ull);
+ // Check fixups.
+ IFixupList *fixup_list = arch->fixup_list();
+ EXPECT_EQ(fixup_list->count(), 0ul);
+ // Check resources.
+ IResourceList *resource_list = arch->resource_list();
+ EXPECT_EQ(resource_list->count(), 0ul);
+ // Check lists were cleared.
+ pf.Close();
+ EXPECT_EQ(pf.count(), 0ul);
+}
+
+TEST(PEFileTest, OpenDLL)
+{
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-dll-test1-i386", foRead), osSuccess);
+ // Check architectures.
+ ASSERT_EQ(pf.count(), 1ul);
+ PEArchitecture *arch = pf.arch_pe();
+ // Check exports.
+ IExportList *exp = arch->export_list();
+ EXPECT_EQ(exp->name().compare("ShimEng.dll"), 0);
+ ASSERT_EQ(exp->count(), 11ul);
+ EXPECT_EQ(exp->item(0)->name().compare("SE_DllLoaded"), 0);
+ EXPECT_EQ(exp->item(0)->forwarded_name().compare("APPHELP.SE_DllLoaded"), 0);
+ EXPECT_EQ(exp->item(0)->address(), 0x3ff31257ull);
+ EXPECT_EQ(exp->item(10)->name().compare("SE_ProcessDying"), 0);
+ EXPECT_EQ(exp->item(10)->forwarded_name().compare("APPHELP.SE_ProcessDying"), 0);
+ EXPECT_EQ(exp->item(10)->address(), 0x3ff31358ull);
+ // Check fixups.
+ IFixupList *fixup_list = arch->fixup_list();
+ ASSERT_EQ(fixup_list->count(), 12ul);
+ EXPECT_EQ(fixup_list->item(0)->address(), 0x3ff3103aull);
+ EXPECT_EQ(fixup_list->item(0)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(1)->address(), 0x3ff31042ull);
+ EXPECT_EQ(fixup_list->item(1)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(2)->address(), 0x3ff3104dull);
+ EXPECT_EQ(fixup_list->item(2)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(3)->address(), 0x3ff31089ull);
+ EXPECT_EQ(fixup_list->item(3)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(4)->address(), 0x3ff310a2ull);
+ EXPECT_EQ(fixup_list->item(4)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(5)->address(), 0x3FF310AEull);
+ EXPECT_EQ(fixup_list->item(5)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(6)->address(), 0x3FF310B6ull);
+ EXPECT_EQ(fixup_list->item(6)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(7)->address(), 0x3FF310BEull);
+ EXPECT_EQ(fixup_list->item(7)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(8)->address(), 0x3FF310CAull);
+ EXPECT_EQ(fixup_list->item(8)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(9)->address(), 0x3FF310E0ull);
+ EXPECT_EQ(fixup_list->item(9)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(10)->address(), 0x3FF310E8ull);
+ EXPECT_EQ(fixup_list->item(10)->type(), ftHighLow);
+ EXPECT_EQ(fixup_list->item(11)->address(), 0x3ff310f0ull);
+ EXPECT_EQ(fixup_list->item(11)->type(), ftHighLow);
+ // Check resources.
+ IResourceList *resource_list = arch->resource_list();
+ ASSERT_EQ(resource_list->count(), 1ul);
+ EXPECT_EQ(resource_list->item(0)->type(), rtVersionInfo);
+ ASSERT_EQ(resource_list->item(0)->count(), 1ul);
+ EXPECT_EQ(resource_list->item(0)->item(0)->name(), "1");
+ EXPECT_EQ(resource_list->item(0)->item(0)->count(), 1ul);
+ EXPECT_EQ(resource_list->item(0)->item(0)->item(0)->name(), "1033");
+ EXPECT_EQ(resource_list->item(0)->item(0)->item(0)->address(), 0x3ff33060ull);
+ EXPECT_EQ(resource_list->item(0)->item(0)->item(0)->size(), 0x3acul);
+ // Check lists were cleared.
+ pf.Close();
+ EXPECT_EQ(pf.count(), 0ul);
+}
+
+TEST(PEFileTest, Clone)
+{
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-app-test1-i386", foRead), osSuccess);
+ PEFile *f = pf.Clone(pf.file_name().c_str());
+ EXPECT_EQ(pf.count(), f->count());
+ PEArchitecture &src = *pf.arch_pe();
+ PEArchitecture &dst = *f->arch_pe();
+ EXPECT_EQ(src.owner()->format_name().compare(dst.owner()->format_name()), 0);
+ EXPECT_EQ(src.name().compare(dst.name()), 0);
+ EXPECT_EQ(src.cpu_address_size(), dst.cpu_address_size());
+ EXPECT_EQ(src.entry_point(), dst.entry_point());
+ EXPECT_EQ(src.command_list()->count(), dst.command_list()->count());
+ EXPECT_EQ(src.segment_list()->count(), dst.segment_list()->count());
+ EXPECT_EQ(src.import_list()->count(), dst.import_list()->count());
+ EXPECT_EQ(src.fixup_list()->count(), dst.fixup_list()->count());
+ EXPECT_EQ(src.export_list()->count(), dst.export_list()->count());
+ EXPECT_EQ(src.resource_list()->count(), dst.resource_list()->count());
+ delete f;
+}
+
+TEST(PEFileTest, Runtime_x32)
+{
+ PEFile file(NULL);
+
+ ASSERT_TRUE(file.OpenResource(win_runtime32_dll_file, sizeof(win_runtime32_dll_file), true));
+ ASSERT_EQ(file.count(), 1ul);
+ PEArchitecture *arch = file.arch_pe();
+ Buffer buffer(&win_runtime32_dll_code[0]);
+ arch->ReadFromBuffer(buffer);
+ EXPECT_GT(arch->export_list()->count(), 0ul);
+ EXPECT_GT(arch->function_list()->count(), 0ul);
+}
+
+TEST(PEFileTest, Runtime_x64)
+{
+ PEFile file(NULL);
+
+ ASSERT_TRUE(file.OpenResource(win_runtime64_dll_file, sizeof(win_runtime64_dll_file), true));
+ ASSERT_EQ(file.count(), 1ul);
+ PEArchitecture *arch = file.arch_pe();
+ Buffer buffer(&win_runtime64_dll_code[0]);
+ arch->ReadFromBuffer(buffer);
+ EXPECT_GT(arch->export_list()->count(), 0ul);
+ EXPECT_GT(arch->function_list()->count(), 0ul);
+}
+
+TEST(PEFileTest, Compile_x32)
+{
+ PEFile pf(NULL);
+ size_t i;
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-app-delphi-i386", foRead), osSuccess);
+ PEArchitecture *arch = pf.arch_pe();
+ for (i = 0; i < arch->map_function_list()->count(); i++) {
+ MapFunction *map_function = arch->map_function_list()->item(i);
+ if (map_function->type() == otString || map_function->type() == otAPIMarker || map_function->type() == otMarker)
+ arch->function_list()->AddByAddress(map_function->address(), ctVirtualization, 0, true, NULL);
+ }
+ ASSERT_EQ(arch->function_list()->count(), 4ul);
+ std::string file_name = pf.file_name()+".exe";
+ PEFile *f = pf.Clone(file_name.c_str());
+ CompileOptions options;
+ options.flags = cpMaximumProtection;
+ options.section_name = ".vmp";
+ ASSERT_TRUE(f->Compile(options));
+ delete f;
+ PEFile pf2(NULL);
+ ASSERT_EQ(pf2.Open(file_name.c_str(), foRead | foHeaderOnly), osSuccess);
+ ASSERT_EQ(pf2.count(), pf.count());
+ PEArchitecture &src = *pf.arch_pe();
+ PEArchitecture &dst = *pf2.arch_pe();
+ for (i = 0; i < src.fixup_list()->count(); i++) {
+ IFixup *src_fixup = src.fixup_list()->item(i);
+ IFixup *dst_fixup = src.fixup_list()->GetFixupByAddress(src_fixup->address());
+ EXPECT_EQ(src_fixup->address(), dst_fixup->address());
+ EXPECT_EQ(src_fixup->type(), dst_fixup->type());
+ EXPECT_EQ(src_fixup->size(), dst_fixup->size());
+ }
+ if (options.flags & cpResourceProtection) {
+ EXPECT_EQ(dst.resource_list()->count(), 4ul);
+ } else {
+ EXPECT_EQ(src.resource_list()->count(), dst.resource_list()->count());
+ for (i = 0; i < src.resource_list()->count(); i++) {
+ PEResource *src_resource = src.resource_list()->item(i);
+ PEResource *dst_resource = dst.resource_list()->item(i);
+ EXPECT_EQ(src_resource->count(), dst_resource->count());
+ EXPECT_EQ(src_resource->address(), dst_resource->address());
+ EXPECT_EQ(src_resource->size(), dst_resource->size());
+ EXPECT_EQ(src_resource->type(), dst_resource->type());
+ EXPECT_EQ(src_resource->name(), dst_resource->name());
+ }
+ }
+ // check AV buffer
+ ASSERT_EQ(dst.segment_list()->count(), 13ul);
+ ASSERT_TRUE(dst.AddressSeek(dst.segment_list()->item(10)->address()));
+ uint32_t sum = 0;
+ for (i = 0; i < 64; i++) {
+ sum += dst.ReadDWord();
+ }
+ EXPECT_EQ(sum, 0xB7896EB5);
+ // delete file from disk
+ pf2.Close();
+ remove(file_name.c_str());
+}
+
+TEST(PEFileTest, Compile_DLL)
+{
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-dll-test1-i386", foRead), osSuccess);
+ std::string file_name = pf.file_name()+".dll";
+ PEFile *f = pf.Clone(file_name.c_str());
+ CompileOptions options;
+ options.flags = cpPack;
+ options.section_name = ".vmp";
+ ASSERT_TRUE(f->Compile(options));
+ delete f;
+ PEFile pf2(NULL);
+ ASSERT_EQ(pf2.Open(file_name.c_str(), foRead | foHeaderOnly), osSuccess);
+ ASSERT_EQ(pf2.count(), pf.count());
+ PEArchitecture &src = *pf.arch_pe();
+ PEArchitecture &dst = *pf2.arch_pe();
+ size_t i;
+ for (i = 0; i < src.fixup_list()->count(); i++) {
+ IFixup *src_fixup = src.fixup_list()->item(i);
+ IFixup *dst_fixup = src.fixup_list()->GetFixupByAddress(src_fixup->address());
+ EXPECT_EQ(src_fixup->address(), dst_fixup->address());
+ EXPECT_EQ(src_fixup->type(), dst_fixup->type());
+ EXPECT_EQ(src_fixup->size(), dst_fixup->size());
+ }
+ ASSERT_EQ(src.resource_list()->count(), dst.resource_list()->count());
+ for (i = 0; i < src.resource_list()->count(); i++) {
+ PEResource *src_resource = src.resource_list()->item(i);
+ PEResource *dst_resource = dst.resource_list()->item(i);
+ EXPECT_EQ(src_resource->count(), dst_resource->count());
+ EXPECT_EQ(src_resource->address(), dst_resource->address());
+ EXPECT_EQ(src_resource->size(), dst_resource->size());
+ EXPECT_EQ(src_resource->type(), dst_resource->type());
+ EXPECT_EQ(src_resource->name(), dst_resource->name());
+ }
+ ASSERT_EQ(src.export_list()->count(), dst.export_list()->count());
+ for (i = 0; i < src.export_list()->count(); i++) {
+ PEExport *src_export = src.export_list()->item(i);
+ PEExport *dst_export = dst.export_list()->item(i);
+ EXPECT_EQ(src_export->name(), dst_export->name());
+ EXPECT_EQ(src_export->ordinal(), dst_export->ordinal());
+ if (src_export->forwarded_name().empty()) {
+ EXPECT_EQ(src_export->address(), dst_export->address());
+ } else {
+ EXPECT_EQ(src_export->forwarded_name(), dst_export->forwarded_name());
+ }
+ }
+ // check AV buffer
+ ASSERT_EQ(dst.segment_list()->count(), 7ul);
+ ASSERT_TRUE(dst.AddressSeek(dst.segment_list()->item(4)->address()));
+ uint32_t sum = 0;
+ for (i = 0; i < 64; i++) {
+ sum += dst.ReadDWord();
+ }
+ EXPECT_EQ(sum, 0xB7896EB5);
+ // delete file from disk
+ pf2.Close();
+ remove(file_name.c_str());
+}
+
+TEST(PEFileTest, Compile_x64)
+{
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win64-app-msvc-amd64", foRead), osSuccess);
+ PEArchitecture *arch = pf.arch_pe();
+ size_t i;
+ for (i = 0; i < arch->map_function_list()->count(); i++) {
+ MapFunction *map_function = arch->map_function_list()->item(i);
+ if (map_function->type() == otString)
+ arch->function_list()->AddByAddress(map_function->address(), ctVirtualization, 0, true, NULL);
+ }
+ ASSERT_EQ(arch->function_list()->count(), 2ul);
+ std::string file_name = pf.file_name()+".exe";
+ PEFile *f = pf.Clone(file_name.c_str());
+ CompileOptions options;
+ options.flags = cpMaximumProtection;
+ options.section_name = ".vmp";
+ ASSERT_TRUE(f->Compile(options));
+ delete f;
+ PEFile pf2(NULL);
+ ASSERT_EQ(pf2.Open(file_name.c_str(), foRead | foHeaderOnly), osSuccess);
+ ASSERT_EQ(pf2.count(), pf.count());
+ PEArchitecture &src = *pf.arch_pe();
+ PEArchitecture &dst = *pf2.arch_pe();
+ for (i = 0; i < src.fixup_list()->count(); i++) {
+ IFixup *src_fixup = src.fixup_list()->item(i);
+ IFixup *dst_fixup = src.fixup_list()->GetFixupByAddress(src_fixup->address());
+ EXPECT_EQ(src_fixup->address(), dst_fixup->address());
+ EXPECT_EQ(src_fixup->type(), dst_fixup->type());
+ EXPECT_EQ(src_fixup->size(), dst_fixup->size());
+ }
+ if (options.flags & cpResourceProtection) {
+ EXPECT_EQ(dst.resource_list()->count(), 1ul);
+ } else {
+ ASSERT_EQ(src.resource_list()->count(), dst.resource_list()->count());
+ for (i = 0; i < src.resource_list()->count(); i++) {
+ PEResource *src_resource = src.resource_list()->item(i);
+ PEResource *dst_resource = dst.resource_list()->item(i);
+ EXPECT_EQ(src_resource->count(), dst_resource->count());
+ EXPECT_EQ(src_resource->address(), dst_resource->address());
+ EXPECT_EQ(src_resource->size(), dst_resource->size());
+ EXPECT_EQ(src_resource->type(), dst_resource->type());
+ EXPECT_EQ(src_resource->name(), dst_resource->name());
+ }
+ }
+ // check AV buffer
+ ASSERT_EQ(dst.segment_list()->count(), 9ul);
+ ASSERT_TRUE(dst.AddressSeek(dst.segment_list()->item(6)->address()));
+ uint32_t sum = 0;
+ for (i = 0; i < 64; i++) {
+ sum += dst.ReadDWord();
+ }
+ EXPECT_EQ(sum, 0xB7896EB5);
+ // delete file from disk
+ pf2.Close();
+ remove(file_name.c_str());
+}
+
+TEST(PEFileTest, Pack)
+{
+ PEFile pf(NULL);
+
+ ASSERT_EQ(pf.Open("test-binaries/win32-app-delphi-i386", foRead), osSuccess);
+ PEArchitecture *arch = pf.arch_pe();
+ PESegment *section = arch->segment_list()->item(0);
+ Data data, props;
+ Packer packer;
+ size_t data_size = static_cast<size_t>(section->physical_size());
+ ASSERT_TRUE(packer.WriteProps(&props));
+ ASSERT_TRUE(arch->AddressSeek(section->address()));
+ ASSERT_TRUE(packer.Code(arch, data_size, &data));
+ Byte *dst = new Byte[data_size];
+
+ CLzmaDecoderState state;
+ EXPECT_EQ(LzmaDecodeProperties(&state.Properties, props.data(), (unsigned)props.size()), LZMA_RESULT_OK);
+ state.Probs = (CProb *)new Byte[LzmaGetNumProbs(&state.Properties) * sizeof(CProb)];
+ SizeT src_processed_size;
+ SizeT dst_processed_size;
+ EXPECT_EQ(LzmaDecode(&state, data.data(), -1, &src_processed_size, dst, -1, &dst_processed_size), LZMA_RESULT_OK);
+ delete [] state.Probs;
+ ASSERT_EQ(dst_processed_size, data_size);
+
+ arch->AddressSeek(section->address());
+ for (size_t i = 0; i < data_size; i++) {
+ EXPECT_EQ(dst[i], arch->ReadByte());
+ }
+ delete [] dst;
+}
+
+TEST(PEFileTest, CalcCheckSum)
+{
+ uint32_t sum;
+ ASSERT_TRUE(os::FileGetCheckSum("test-binaries/win32-app-delphi-i386", &sum));
+ EXPECT_EQ(sum, 0x000e4490ul);
+ ASSERT_TRUE(os::FileGetCheckSum("test-binaries/win64-app-msvc-amd64", &sum));
+ EXPECT_EQ(sum, 0x0000b8c9ul);
+}
+
+#ifndef DEMO
+#ifndef __APPLE__
+static bool execFile(const std::string &fileName, DWORD &exitCode)
+{
+ exitCode = 0xFFFFFFF;
+#ifdef VMP_GNU
+ int ret = system(("wine " + fileName).c_str());
+ if (ret != -1)
+ {
+ exitCode = DWORD(ret);
+ return true;
+ }
+ return false;
+#else
+ PROCESS_INFORMATION processInformation = { };
+ STARTUPINFOW startupInfo = { };
+ startupInfo.cb = sizeof(startupInfo);
+ os::unicode_string unicodeName = os::FromUTF8(fileName);
+
+ BOOL result = CreateProcessW(NULL, const_cast<wchar_t *>(unicodeName.c_str()),
+ NULL, NULL, FALSE,
+ NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
+ NULL, NULL, &startupInfo, &processInformation);
+
+ if (!result)
+ return false;
+
+ WaitForSingleObject(processInformation.hProcess, 10000);
+ result = GetExitCodeProcess(processInformation.hProcess, &exitCode);
+ if (exitCode == STILL_ACTIVE)
+ TerminateProcess(processInformation.hProcess, 0xFFFFFFFF);
+ CloseHandle(processInformation.hProcess);
+ CloseHandle(processInformation.hThread);
+
+ return (result && (exitCode != STILL_ACTIVE));
+#endif
+}
+
+/* seh.cpp:
+#include <windows.h>
+#include "VMProtectSDK.h"
+
+__declspec(noinline) void try1()
+{
+ printf("try 1\n");
+ try {
+ throw 1;
+ }
+ catch (int) {
+ printf("catch 1\n");
+ throw;
+ }
+ printf("end 1\n\n");
+}
+
+__declspec(noinline) void try2()
+{
+ printf("try 2\n");
+ PEXCEPTION_POINTERS info = NULL;
+ __try {
+ if (*reinterpret_cast<char *>(0xFACE) == 0)
+ return;
+ }
+ __except (info = GetExceptionInformation(), EXCEPTION_EXECUTE_HANDLER) {
+ printf("throw at %p\n", info->ExceptionRecord->ExceptionAddress);
+ }
+ printf("end 2\n\n");
+}
+
+int main()
+{
+ if (VMProtectIsDebuggerPresent(true))
+ printf("debugger detected\n");
+ if (VMProtectIsVirtualMachinePresent())
+ printf("virtual machine detected\n");
+
+ printf("try main\n");
+ try {
+ try1();
+ }
+ catch (...) {
+ printf("catch main\n");
+ }
+ printf("end main\n");
+ try2();
+
+ return 0;
+}
+*/
+
+TEST(PEFileTest, SEH_x32)
+{
+ PEFile pf(NULL);
+ ASSERT_EQ(pf.Open("test-binaries/seh-x86", foRead), osSuccess);
+ PEArchitecture *arch = pf.arch_pe();
+ arch->function_list()->AddByAddress(0x00401130, ctVirtualization, 0, true, NULL); // main
+ arch->function_list()->AddByAddress(0x00401000, ctUltra, 0, true, NULL); // try1
+ arch->function_list()->AddByAddress(0x00401070, ctMutation, 0, true, NULL); // try2
+ std::string file_name = pf.file_name() + ".exe";
+ PEFile *f = pf.Clone(file_name.c_str());
+ CompileOptions options;
+ options.flags = cpMaximumProtection;
+ options.section_name = ".vmp";
+ ASSERT_TRUE(f->Compile(options));
+ delete f;
+ DWORD ret;
+ ASSERT_TRUE(execFile(file_name, ret));
+ ASSERT_EQ(ret, 0u);
+}
+#endif
+#ifndef VMP_GNU
+TEST(PEFileTest, SEH_x64)
+{
+ PEFile pf(NULL);
+ ASSERT_EQ(pf.Open("test-binaries/seh-x64", foRead), osSuccess);
+ PEArchitecture *arch = pf.arch_pe();
+ arch->function_list()->AddByAddress(0x00000001400010A0, ctVirtualization, 0, true, NULL); // main
+ arch->function_list()->AddByAddress(0x0000000140001000, ctUltra, 0, true, NULL); // try1
+ arch->function_list()->AddByAddress(0x0000000140001040, ctMutation, 0, true, NULL); // try2
+ std::string file_name = pf.file_name() + ".exe";
+ PEFile *f = pf.Clone(file_name.c_str());
+ CompileOptions options;
+ options.flags = cpMaximumProtection;
+ options.section_name = ".vmp";
+ ASSERT_TRUE(f->Compile(options));
+ delete f;
+ DWORD ret;
+ ASSERT_TRUE(execFile(file_name, ret));
+ ASSERT_EQ(ret, 0u);
+}
+#endif
+#endif