aboutsummaryrefslogtreecommitdiff
path: root/unit-tests/elffile_tests.cc
diff options
context:
space:
mode:
Diffstat (limited to 'unit-tests/elffile_tests.cc')
-rw-r--r--unit-tests/elffile_tests.cc345
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