diff options
Diffstat (limited to 'unit-tests/elffile_tests.cc')
-rw-r--r-- | unit-tests/elffile_tests.cc | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/unit-tests/elffile_tests.cc b/unit-tests/elffile_tests.cc new file mode 100644 index 0000000..6304838 --- /dev/null +++ b/unit-tests/elffile_tests.cc @@ -0,0 +1,345 @@ +#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/elffile.h" +#include "../core/lin_runtime32.so.inc" +#include "../core/lin_runtime64.so.inc" + +#ifdef ELFFileTest_TestOpen1 +TEST(ELFFileTest, TestOpen1) +{ + ELFFile mf(NULL); + ISectionList *segl; + ELFSectionList *secl; + //ELFSymbolList *syml; + IImportList *impl; + + ASSERT_EQ(osSuccess, mf.Open("test-binaries/Project1-linux-x64", true)); + // Check architectures. + EXPECT_EQ(1ul, mf.count()); + ELFArchitecture &arch = *mf.item(0); + EXPECT_EQ("amd64", arch.name()); + EXPECT_EQ("ELF", arch.owner()->format_name()); + EXPECT_EQ(0x4007F0ull, arch.entry_point()); + // Check segments were read. + segl = arch.segment_list(); + struct seg { const char *name; uint32_t mt; } segs[] = { + {".interp", mtReadable} // IDA не показывает + ,{".init", mtReadable | mtExecutable} + ,{".plt", mtReadable | mtExecutable} + ,{".text", mtReadable | mtExecutable} + ,{".fini", mtReadable | mtExecutable} + ,{".rodata", mtReadable} + ,{".eh_frame_hdr", mtReadable} + ,{".eh_frame", mtReadable} + //,{".init_array", mtReadable | mtWritable} - IDA + //,{".fini_array", mtReadable | mtWritable} - IDA + ,{".jcr", mtReadable | mtWritable} + ,{".got", mtReadable | mtWritable} + ,{".got.plt", mtReadable | mtWritable} + ,{".data", mtReadable | mtWritable} + ,{".bss", mtReadable | mtWritable} + //,{"extern"} - IDA + }; + ASSERT_EQ(_countof(segs), segl->count()); + for(size_t i = 0; i < _countof(segs); i++) + { + EXPECT_EQ(segs[i].name, segl->item(i)->name()) << "i=" << i; + EXPECT_EQ(segs[i].mt, segl->item(i)->memory_type()) << "i=" << i; + } + // Check sections were read. + secl = arch.section_list(); + ASSERT_EQ(0ul, secl->count()); + //EXPECT_EQ("sn", secl->item(0)->name()); + // Check symbols. + /*syml = arch.symbol_list(); + ASSERT_EQ(syml->count(), 129ul); + EXPECT_EQ(syml->item(0)->name() + .compare("/Users/macuser/work2/ios-test2/ios-test2/"), 0);*/ + // Check imports. + impl = arch.import_list(); + ASSERT_EQ(3ul, impl->count()); + //Why [0].is_sdk == false? + EXPECT_EQ("libVMProtectSDK64.so", impl->item(0)->name()); + EXPECT_EQ(0ul, impl->item(0)->count()); + EXPECT_EQ("libc.so.6", impl->item(1)->name()); + EXPECT_EQ(0ul, impl->item(1)->count()); + EXPECT_EQ("", impl->item(2)->name()); + const char *fnames[] = { + "__gmon_start__" + ,"_Jv_RegisterClasses" + ,"puts" + ,"__libc_start_main" + ,"VMProtectDecryptStringA" + ,"fgets" + ,"_ITM_deregisterTMCloneTable" + ,"_ITM_registerTMCloneTable" + ,"atoi" + ,"__stack_chk_fail" + ,"VMProtectBegin" + ,"VMProtectEnd" + ,"__gmon_start__" + ,"_Jv_RegisterClasses" + ,"puts@@GLIBC_2.2.5" + ,"__libc_start_main@@GLIBC_2.2.5" + ,"VMProtectDecryptStringA" + ,"fgets@@GLIBC_2.2.5" + ,"_ITM_deregisterTMCloneTable" + ,"_ITM_registerTMCloneTable" + ,"atoi@@GLIBC_2.2.5" + ,"__stack_chk_fail@@GLIBC_2.4" + ,"VMProtectBegin" + ,"VMProtectEnd"}; + EXPECT_EQ(_countof(fnames), impl->item(2)->count()); + for(size_t i = 0; i < _countof(fnames); i++) + { + EXPECT_EQ(fnames[i], impl->item(2)->item(i)->name()) << "i=" << i; + } + mf.Close(); + EXPECT_EQ(mf.count(), 0ul); +} +#endif + +TEST(ELFFileTest, TestOpen2) +{ + ELFFile mf(NULL); + ISectionList *segl; + ELFSectionList *secl; + //ELFSymbolList *syml; + IImportList *impl; + IExportList *expl; + + ASSERT_EQ(mf.Open("test-binaries/Project1-linux-x86", true), osSuccess); + // Check architectures. + ASSERT_EQ(mf.count(), 1ul); + ELFArchitecture &arch = *mf.item(0); + EXPECT_EQ(arch.name().compare("i386"), 0); + EXPECT_EQ(arch.owner()->format_name().compare("ELF"), 0); + EXPECT_EQ(arch.entry_point(), 0x80485E0ULL); + // Check segments were read. + segl = arch.segment_list(); + /*ASSERT_EQ(segl->count(), 4ul); + EXPECT_EQ(segl->item(0)->name().compare("__PAGEZERO"), 0); + EXPECT_EQ(segl->item(0)->memory_type(), mtNone); + EXPECT_EQ(segl->item(1)->name().compare("__TEXT"), 0); + EXPECT_EQ((int)segl->item(1)->memory_type(), (mtReadable | mtExecutable)); + EXPECT_EQ(segl->item(2)->name().compare("__DATA"), 0); + EXPECT_EQ((int)segl->item(2)->memory_type(), (mtReadable | mtWritable)); + EXPECT_EQ(segl->item(3)->name().compare("__LINKEDIT"), 0); + EXPECT_EQ(segl->item(3)->memory_type(), mtReadable);*/ + // Check sections were read. + secl = arch.section_list(); + /*ASSERT_EQ(secl->count(), 10ul); + EXPECT_EQ(secl->item(0)->name().compare("__text"), 0); + EXPECT_EQ(secl->item(1)->name().compare("__stubs"), 0); + EXPECT_EQ(secl->item(2)->name().compare("__stub_helper"), 0); + EXPECT_EQ(secl->item(3)->name().compare("__cstring"), 0); + EXPECT_EQ(secl->item(4)->name().compare("__unwind_info"), 0); + EXPECT_EQ(secl->item(5)->name().compare("__eh_frame"), 0); + EXPECT_EQ(secl->item(6)->name().compare("__dyld"), 0); + EXPECT_EQ(secl->item(7)->name().compare("__got"), 0); + EXPECT_EQ(secl->item(8)->name().compare("__la_symbol_ptr"), 0); + EXPECT_EQ(secl->item(9)->name().compare("__data"), 0); + // Check symbols. + syml = arch.symbol_list(); + ASSERT_EQ(syml->count(), 57ul); + EXPECT_EQ(syml->item(2)->name() + .compare("/Users/mac/Library/Developer/Xcode/DerivedData/hello-flxnqzrlabvwqrdcesuuqdaabhfa/Build/Intermediates/hello.build/Release/hello.build/Objects-normal/x86_64/main.o"), 0);*/ + // Check imports. + impl = arch.import_list(); + /*ASSERT_EQ(impl->count(), 3ul); + EXPECT_EQ(impl->item(0)->name().compare("/usr/lib/libstdc++.6.dylib"), 0); + EXPECT_EQ(impl->item(1)->name().compare("/usr/lib/libgcc_s.1.dylib"), 0); + EXPECT_EQ(impl->item(2)->name().compare("/usr/lib/libSystem.B.dylib"), 0);*/ + // Check exports. + expl = arch.export_list(); + /*ASSERT_EQ(expl->count(), 5ul); + EXPECT_EQ(expl->item(0)->name().compare("_NXArgc"), 0); + EXPECT_EQ(expl->item(1)->name().compare("_NXArgv"), 0); + EXPECT_EQ(expl->item(2)->name().compare("___progname"), 0); + EXPECT_EQ(expl->item(3)->name().compare("_environ"), 0); + EXPECT_EQ(expl->item(4)->name().compare("start"), 0); + EXPECT_EQ(expl->item(4)->address(), 0x100000c04ULL);*/ + mf.Close(); + EXPECT_EQ(mf.count(), 0ul); +} + +/*TEST(ELFFileTest, OpenSharedLib) +{ + ELFFile mf(NULL); + + EXPECT_EQ(mf.Open("test-binaries/macos-dll-test1-i386", foRead), osSuccess); + // Check architectures. + ASSERT_EQ(mf.count(), 1ul); + ELFArchitecture &arch = *mf.item(0); + // Check exports. + IExportList *exp = arch.export_list(); + EXPECT_EQ(exp->name().compare("@executable_path/hello_lib_cpp.dylib"), 0); + ASSERT_EQ(exp->count(), 1ul); + EXPECT_EQ(exp->item(0)->name().compare("__ZN13hello_lib_cpp10HelloWorldEPKc"), 0); + EXPECT_EQ(exp->item(0)->forwarded_name().compare(""), 0); + EXPECT_EQ(exp->item(0)->address(), 0x00000deaull); + // Check fixups. + IFixupList *fixup_list = arch.fixup_list(); + ASSERT_EQ(fixup_list->count(), 23ul); + EXPECT_EQ(fixup_list->item(0)->address(), 0x00000e84ull); + EXPECT_EQ(fixup_list->item(0)->type(), ftHighLow); + EXPECT_EQ(fixup_list->item(22)->address(), 0x00001034ull); + EXPECT_EQ(fixup_list->item(22)->type(), ftHighLow); + mf.Close(); + EXPECT_EQ(mf.count(), 0ul); +}*/ + +TEST(ELFFileTest, Clone) +{ + ELFFile mf(NULL); + + ASSERT_EQ(mf.Open("test-binaries/Project1-linux-x64", foRead), osSuccess); + ELFFile *f = mf.Clone(mf.file_name().c_str()); + ASSERT_EQ(mf.count(), f->count()); + ELFArchitecture &src = *mf.item(0); + ELFArchitecture &dst = *f->item(0); + 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.command_list()->count(), dst.command_list()->count()); + EXPECT_EQ(src.segment_list()->count(), dst.segment_list()->count()); + EXPECT_EQ(src.section_list()->count(), dst.section_list()->count()); + //EXPECT_EQ(src.symbol_list()->count(), dst.symbol_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()); + //std::string symbol_name = src.indirect_symbol_list()->item(1)->symbol()->name(); + //av std::string segment_name = src.section_list()->item(0)->parent()->name(); + mf.Close(); + //EXPECT_EQ(dst.indirect_symbol_list()->item(1)->symbol()->name().compare(symbol_name), 0); + //av EXPECT_EQ(dst.section_list()->item(0)->parent()->name().compare(segment_name), 0); + delete f; +} + +TEST(ELFFileTest, Runtime_x32) +{ + ELFFile file(NULL); + + ASSERT_TRUE(file.OpenResource(lin_runtime32_so_file, sizeof(lin_runtime32_so_file), true)); + ASSERT_EQ(file.count(), 1ul); + ELFArchitecture *arch = file.item(0); + Buffer buffer(&lin_runtime32_so_code[0]); + arch->ReadFromBuffer(buffer); + EXPECT_EQ(arch->export_list()->count(), 21ul); + EXPECT_GT(arch->function_list()->count(), 0ul); +} + +TEST(ELFFileTest, Runtime_x64) +{ + ELFFile file(NULL); + + ASSERT_TRUE(file.OpenResource(lin_runtime64_so_file, sizeof(lin_runtime64_so_file), true)); + ASSERT_EQ(file.count(), 1ul); + ELFArchitecture *arch = file.item(0); + Buffer buffer(&lin_runtime64_so_code[0]); + arch->ReadFromBuffer(buffer); + EXPECT_EQ(arch->export_list()->count(), 21ul); + EXPECT_GT(arch->function_list()->count(), 0ul); +} + +#ifdef __unix__ +#ifndef DEMO +static bool execFile(const std::string &fileName, DWORD &exitCode) +{ + exitCode = 0xFFFFFFF; + int ret = system(fileName.c_str()); + if (ret != -1) + { + exitCode = DWORD(ret); + return true; + } + return false; +} + +/* +// exc.cpp: +// clang++ -std=c++11 -target x86_64-linux-gnu -o exc-linux-x64 exc.cpp -L../bin -lVMProtectSDK64 -I ../sdk +// clang++ -std=c++11 -target i386-linux-gnu -o exc-linux-x86 exc.cpp -L../bin -lVMProtectSDK32 -I ../sdk +#include <stdio.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"); +} + +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"); + + return 0; +} +*/ + +TEST(ELFFileTest, EXC_x32) +{ + ELFFile pf(NULL); + ASSERT_EQ(pf.Open("test-binaries/exc-linux-x86", foRead), osSuccess); + ELFArchitecture *arch = pf.item(0); + arch->function_list()->AddByAddress(0x08048940, ctVirtualization, 0, true, NULL); // main + arch->function_list()->AddByAddress(0x08048890, ctUltra, 0, true, NULL); // try1 + std::string file_name = pf.file_name() + "_vmp"; + ELFFile *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); +} + +TEST(ELFFileTest, EXC_x64) +{ + ELFFile pf(NULL); + ASSERT_EQ(pf.Open("test-binaries/exc-linux-x64", foRead), osSuccess); + ELFArchitecture *arch = pf.item(0); + arch->function_list()->AddByAddress(0x0000000000400B80, ctVirtualization, 0, true, NULL); // main + arch->function_list()->AddByAddress(0x0000000000400AE0, ctUltra, 0, true, NULL); // try1 + std::string file_name = pf.file_name() + "_vmp"; + ELFFile *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 // DEMO +#endif // __unix__
\ No newline at end of file |