├── Tests ├── Test RDTSC │ ├── test_rdtsc.exe │ └── test_rdtsc.cpp ├── Test VirtualAlloc │ ├── TestVirtualAlloc.exe │ └── TestVirtualAlloc.cpp └── Test GetTickCount & Sleep │ ├── GetTickCountTest.exe │ └── GetTickCountTest.cpp ├── unpacker.h ├── Unpackers ├── heuristics │ ├── pushad_popad_heuristic.h │ ├── pushad_popad_heuristic.cpp │ ├── w_xor_x_heuristic.h │ └── w_xor_x_heuristic.cpp ├── memory_movement_detection.h ├── generic_instrumentation.h ├── run_pe_detector.h ├── generic_instrumentation.cpp ├── memory_movement_detection.cpp └── run_pe_detector.cpp ├── common.h ├── makefile ├── anti-methods ├── anti-methods.h └── anti-methods.cpp ├── PE ├── data_directory_header.h ├── import_entry.h ├── builder.h ├── nt_header.h ├── section_header.h ├── import_entry.cpp ├── dos_header.h ├── data_directory_header.cpp ├── import.h ├── optional_header.h ├── nt_header.cpp ├── proc_info.h ├── import.cpp ├── binary.h ├── section_header.cpp ├── structures_and_enums.h └── dos_header.cpp ├── ANBU.sln ├── utils.h ├── makefile.rules ├── md5.h ├── README.md ├── utils.cpp ├── unpacker.cpp ├── .gitignore ├── MyPinTool.vcxproj.filters ├── md5.cpp └── MyPinTool.vcxproj /Tests/Test RDTSC/test_rdtsc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fare9/ANBU/HEAD/Tests/Test RDTSC/test_rdtsc.exe -------------------------------------------------------------------------------- /Tests/Test VirtualAlloc/TestVirtualAlloc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fare9/ANBU/HEAD/Tests/Test VirtualAlloc/TestVirtualAlloc.exe -------------------------------------------------------------------------------- /Tests/Test GetTickCount & Sleep/GetTickCountTest.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fare9/ANBU/HEAD/Tests/Test GetTickCount & Sleep/GetTickCountTest.exe -------------------------------------------------------------------------------- /Tests/Test VirtualAlloc/TestVirtualAlloc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | int main() 5 | { 6 | LPVOID allocated_memory = VirtualAlloc(NULL, 1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 7 | 8 | if (allocated_memory) 9 | { 10 | memset(allocated_memory, 0, 1000); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /unpacker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #ifndef UNPACKER_H 5 | #define UNPACKER_H 6 | 7 | #include "common.h" 8 | #include "memory_movement_detection.h" 9 | #include "run_pe_detector.h" 10 | #include "binary.h" 11 | #include "proc_info.h" 12 | #include "utils.h" 13 | 14 | void usage(); 15 | 16 | #endif -------------------------------------------------------------------------------- /Tests/Test GetTickCount & Sleep/GetTickCountTest.cpp: -------------------------------------------------------------------------------- 1 | // GetTickCountTest.cpp : Este archivo contiene la función "main". La ejecución del programa comienza y termina ahí. 2 | // 3 | 4 | #include 5 | #include 6 | int main() 7 | { 8 | printf("GetTickCount() = 0x%x\n", GetTickCount()); 9 | printf("GetTickCount() = 0x%x\n", GetTickCount()); 10 | printf("Do Sleep of 10 seconds\n"); 11 | Sleep(10000); 12 | printf("GetTickCount() = 0x%x\n", GetTickCount()); 13 | } -------------------------------------------------------------------------------- /Unpackers/heuristics/pushad_popad_heuristic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef PUSHAD_POPAD_HEURISTIC_H 4 | #define PUSHAD_POPAD_HEURISTIC_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | 9 | class pushad_popad_heuristic_t 10 | { 11 | public: 12 | pushad_popad_heuristic_t(); 13 | ~pushad_popad_heuristic_t() = default; 14 | 15 | void check_pushad_popad(INS instruction); 16 | bool pushad_popad_detected(); 17 | bool pushad_popad_finished(); 18 | 19 | private: 20 | bool pushad_flag = false; 21 | bool popad_flag = false; 22 | }; 23 | 24 | #endif // !PUSHAD_POPAD_HEURISTIC_H 25 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef COMMON_H 4 | #define COMMON_H 5 | 6 | #include "pin.H" 7 | 8 | namespace WINDOWS { 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "Winternl.h" 14 | #include "Intsafe.h" 15 | } 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | 29 | typedef struct _write_memory 30 | { 31 | ADDRINT address; 32 | size_t size; 33 | std::vector data; 34 | } write_memory_t; 35 | 36 | 37 | #endif // COMMON_H 38 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /Unpackers/memory_movement_detection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef MEMORY_MOVEMENT_DETECTION_H 4 | #define MEMORY_MOVEMENT_DETECTION_H 5 | 6 | #include "common.h" 7 | #include "generic_instrumentation.h" 8 | #include "w_xor_x_heuristic.h" 9 | #include "pushad_popad_heuristic.h" 10 | #include "utils.h" 11 | #include "proc_info.h" 12 | 13 | // PE Headers 14 | #include "binary.h" 15 | 16 | 17 | 18 | /******************* unpacker funcionts *******************/ 19 | void fini(); 20 | 21 | void instrument_mem_cflow(INS ins, void *v); 22 | void queue_memwrite(ADDRINT ins_addr, ADDRINT addr); 23 | void log_memwrite(ADDRINT ins_addr, UINT32 size); 24 | void check_indirect_ctransfer(ADDRINT ip, ADDRINT target, BOOL taken); 25 | bool dump_to_file(ADDRINT target); 26 | 27 | #endif // !MEMORY_MOVEMENT_DETECTION_H 28 | -------------------------------------------------------------------------------- /anti-methods/anti-methods.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef ANTI_METHODS_H 4 | #define ANTI_METHODS_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | 9 | /****************************** 10 | * INSTRUMENTATION CODE 11 | *******************************/ 12 | void hook_functions(IMG img, VOID *v); 13 | void hook_instructions(INS ins, void *v); 14 | 15 | 16 | /****************************** 17 | * HOOKS 18 | *******************************/ 19 | WINDOWS::BOOL WINAPI MyIsDebuggerPresent(); 20 | void MySleep(WINDOWS::DWORD dwMilliseconds); 21 | WINDOWS::DWORD WINAPI MyGetTickCount(); 22 | WINDOWS::ULONGLONG WINAPI MyGetTickCount64(); 23 | void MyRDTSC(ADDRINT *gax, ADDRINT *gdx); 24 | WINDOWS::BOOL MyProcess32First(WINDOWS::HANDLE hSnapshot, WINDOWS::LPPROCESSENTRY32 lppe); 25 | WINDOWS::BOOL MyProcess32Next(WINDOWS::HANDLE hSnapshot, WINDOWS::LPPROCESSENTRY32 lppe); 26 | 27 | 28 | #endif // !ANTI_METHODS_H 29 | -------------------------------------------------------------------------------- /Unpackers/heuristics/pushad_popad_heuristic.cpp: -------------------------------------------------------------------------------- 1 | #include "pushad_popad_heuristic.h" 2 | 3 | /************* EXTERN VARIABLES *************/ 4 | extern FILE* logfile; // log file handler 5 | 6 | pushad_popad_heuristic_t::pushad_popad_heuristic_t() : pushad_flag(false), 7 | popad_flag(false) 8 | { 9 | } 10 | 11 | 12 | void pushad_popad_heuristic_t::check_pushad_popad(INS instruction) 13 | { 14 | std::string ins = INS_Disassemble(instruction); 15 | 16 | if (ins.compare("pushad ") == 0) 17 | { 18 | ANBU::LOGGER_INFO(logfile, "Pushad detected\n"); 19 | this->pushad_flag = true; 20 | } 21 | else if (ins.compare("popad ") == 0) 22 | { 23 | ANBU::LOGGER_INFO(logfile, "Popad detected\n"); 24 | this->popad_flag = true; 25 | } 26 | } 27 | 28 | 29 | bool pushad_popad_heuristic_t::pushad_popad_detected() 30 | { 31 | return this->pushad_flag; 32 | } 33 | 34 | 35 | bool pushad_popad_heuristic_t::pushad_popad_finished() 36 | { 37 | return (this->pushad_flag && this->popad_flag); 38 | } 39 | -------------------------------------------------------------------------------- /PE/data_directory_header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef DATA_DIRECTORY_HEADER_H 4 | #define DATA_DIRECTORY_HEADER_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "structures_and_enums.h" 9 | 10 | namespace pe_parser 11 | { 12 | 13 | class data_directory_header_t 14 | { 15 | public: 16 | 17 | std::map directory_names; 18 | 19 | data_directory_header_t(const pe_data_directory *header, DATA_DIRECTORY type); 20 | ~data_directory_header_t() = default; 21 | 22 | // getters 23 | pe_data_directory data_directory(void) const; 24 | uint32_t RVA(void) const; 25 | uint32_t size(void) const; 26 | DATA_DIRECTORY type(void) const; 27 | // setters 28 | void RVA(uint32_t rva); 29 | void size(uint32_t size); 30 | void type(DATA_DIRECTORY type); 31 | 32 | bool dump_directories(FILE *output_file); 33 | 34 | private: 35 | uint32_t rva_; 36 | uint32_t size_; 37 | DATA_DIRECTORY type_; 38 | }; 39 | } 40 | 41 | #endif // !DATA_DIRECTORY_HEADER_H 42 | -------------------------------------------------------------------------------- /Tests/Test RDTSC/test_rdtsc.cpp: -------------------------------------------------------------------------------- 1 | // test_rdtsc.cpp : Este archivo contiene la función "main". La ejecución del programa comienza y termina ahí. 2 | // 3 | 4 | #include "pch.h" 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | uint64_t rdtsc = 0; 11 | uint32_t low_value = 0, high_value = 0; 12 | 13 | printf("[!] RDTSC test\n"); 14 | 15 | __asm 16 | { 17 | rdtsc; 18 | mov low_value, eax; 19 | mov high_value, edx; 20 | } 21 | 22 | rdtsc = (uint64_t)((((uint64_t)high_value) << 32) | (uint64_t)low_value); 23 | printf("[+] First rdtsc executed\n"); 24 | printf("\t[+] Low value: 0x%x\n", low_value); 25 | printf("\t[+] High value: 0x%x\n", high_value); 26 | printf("\t[+] RDTSC value: 0x%llx\n", rdtsc); 27 | 28 | printf("[!] Execute some instructions\n"); 29 | int a = 2, b = 4, c = 2, d = 6; 30 | a += b; 31 | b *= c; 32 | c /= d; 33 | d %= a; 34 | 35 | __asm 36 | { 37 | rdtsc; 38 | mov low_value, eax; 39 | mov high_value, edx; 40 | } 41 | 42 | rdtsc = (uint64_t)((((uint64_t)high_value) << 32) | (uint64_t)low_value); 43 | printf("[+] Second rdtsc executed\n"); 44 | printf("\t[+] Low value: 0x%x\n", low_value); 45 | printf("\t[+] High value: 0x%x\n", high_value); 46 | printf("\t[+] RDTSC value: 0x%llx\n", rdtsc); 47 | 48 | getchar(); 49 | } -------------------------------------------------------------------------------- /ANBU.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.329 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyPinTool", "MyPinTool.vcxproj", "{639EF517-FCFC-408E-9500-71F0DC0458DB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.ActiveCfg = Debug|x64 17 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.Build.0 = Debug|x64 18 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x86.ActiveCfg = Debug|Win32 19 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x86.Build.0 = Debug|Win32 20 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.ActiveCfg = Release|x64 21 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.Build.0 = Release|x64 22 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x86.ActiveCfg = Release|Win32 23 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C88F9DD1-C2C0-4090-83BF-84524DBCFF80} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /PE/import_entry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef IMPORTENTRY_H 3 | #define IMPORTENTRY_H 4 | 5 | #include "common.h" 6 | #include "utils.h" 7 | #include "structures_and_enums.h" 8 | 9 | class import_entry_t 10 | { 11 | public: 12 | import_entry_t(void); 13 | import_entry_t(uint64_t data, const std::string& name = ""); 14 | import_entry_t(const std::string& name); 15 | import_entry_t(const import_entry_t&); 16 | ~import_entry_t(void); 17 | 18 | //! @brief ``True`` if ordinal is used 19 | bool is_ordinal(void) const; 20 | 21 | //! @brief ordinal value 22 | uint16_t ordinal(void) const; 23 | 24 | //! @see ImportEntry::data 25 | uint64_t hint_name_rva(void) const; 26 | 27 | //! @brief Index into the Export::entries 28 | uint16_t hint(void) const; 29 | 30 | //! @brief Value of the current entry in the Import Address Table. 31 | //! It should match the lookup table value 32 | uint64_t iat_value(void) const; 33 | 34 | //! @brief Import name if not ordinal 35 | const std::string& name(void) const; 36 | 37 | //! @brief Raw value 38 | uint64_t data(void) const; 39 | 40 | //! @brief **Original** address of the entry in the Import Address Table 41 | uint64_t iat_address(void) const; 42 | 43 | 44 | 45 | void name(const std::string& name); 46 | void data(uint64_t data); 47 | 48 | bool dump_import_entry(FILE *output_file); 49 | 50 | private: 51 | uint64_t data_; 52 | std::string name_; 53 | uint16_t hint_; 54 | uint64_t iat_value_; 55 | uint64_t rva_; 56 | PE_TYPE type_; 57 | }; 58 | 59 | #endif // !IMPORTENTRY_H 60 | -------------------------------------------------------------------------------- /Unpackers/generic_instrumentation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef GENERIC_INSTRUMENTATION_H 4 | #define GENERIC_INSTRUMENTATION_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "proc_info.h" 9 | #include "binary.h" 10 | #include "anti-methods.h" 11 | 12 | /****** Structures used for monitoring functions ******/ 13 | typedef struct function_struct_t_ 14 | { 15 | function_struct_t_() : is_ordinal(false), function_ordinal(0), function_address(0), function_destination(0) {} 16 | bool is_ordinal; 17 | uint16_t function_ordinal; 18 | std::string function_name; 19 | ADDRINT function_address; 20 | ADDRINT function_destination; 21 | } function_struct_t; 22 | 23 | typedef struct dll_import_struct_t_ 24 | { 25 | dll_import_struct_t_() : dll_address(0) {} 26 | std::string dll_nameA; 27 | std::wstring dll_nameW; 28 | ADDRINT dll_address; 29 | std::vector functions; 30 | } dll_import_struct_t; 31 | 32 | 33 | /***** INSTRUMENTATION FUNCTIONS *****/ 34 | void get_addresses_from_images(IMG img, VOID *v); 35 | 36 | void hook_loadlibrarya_before(const char* dll_name); 37 | void hook_loadlibrary_after(ADDRINT dll_address); 38 | 39 | void hook_loadlibraryw_before(const wchar_t* dll_name); 40 | 41 | void hook_getmodulehandlea_before(const char* dll_name); 42 | void hook_getmodulehandlew_before(const wchar_t* dll_name); 43 | 44 | void hook_getprocaddress_before(ADDRINT dll_address, const char* function_name); 45 | void hook_getprocaddress_after(ADDRINT function_address); 46 | 47 | #endif // !GENERIC_INSTRUMENTATION_H 48 | -------------------------------------------------------------------------------- /PE/builder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef MEMORY_DUMPER_H 4 | #define MEMORY_DUMPER_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "structures_and_enums.h" 9 | 10 | #include "binary.h" 11 | #include "generic_instrumentation.h" 12 | 13 | class builder_t 14 | /*** 15 | * Class to parse and dump a PE file from memory to 16 | * disk. Some of things I had to include comparing 17 | * with other dumpers is the use of the function 18 | * PE_SafeCopy to get the data. 19 | */ 20 | { 21 | public: 22 | builder_t(ADDRINT jump_target, binary_t* binary); 23 | builder_t(std::vector file_base_in_vector, binary_t* binary); 24 | ~builder_t(); 25 | 26 | bool dump_pe_to_file(const std::string& file_name); 27 | bool dump_runpe_to_file(const std::string& file_name, std::vector file_data, ADDRINT base_address); 28 | 29 | //! @brief Construct a ``jmp [address] @ from``. 30 | //! 31 | //! It is used when patching import table 32 | std::vector build_jmp(uint64_t from, uint64_t address); 33 | 34 | //! @brief Rebuild Import Table 35 | void build_import_table(void); 36 | private: 37 | /**** Private dump functions ****/ 38 | bool dump_headers(); 39 | bool dump_sections(); 40 | void clean_list(); 41 | 42 | binary_t* binary_; 43 | FILE* dumped_file; 44 | ADDRINT address_code_to_dump; 45 | ADDRINT base_address_to_dump; 46 | ADDRINT base_address_name; 47 | IMG img_to_dump; 48 | uint8_t* dos_stub; 49 | bool dump_correct; 50 | bool mem_dumper_correct; 51 | std::vector data_from_vector; 52 | }; 53 | 54 | #endif // !MEMORY_DUMPER_H 55 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef UTILS_H 3 | #define UTILS_H 4 | 5 | #include "common.h" 6 | 7 | namespace ANBU 8 | { 9 | void LOGGER(FILE *file_to_dump, const char *format, ...); 10 | void LOGGER(const char *format, ...); 11 | void LOGGER_INFO(FILE *file_to_dump, const char *format, ...); 12 | void LOGGER_INFO(const char *format, ...); 13 | void LOGGER_ERROR(FILE *file_to_dump, const char *format, ...); 14 | void LOGGER_ERROR(const char *format, ...); 15 | 16 | void LOGGER(FILE *file_to_dump, const wchar_t *format, ...); 17 | void LOGGER(const wchar_t *format, ...); 18 | void LOGGER_INFO(FILE *file_to_dump, const wchar_t *format, ...); 19 | void LOGGER_INFO(const wchar_t *format, ...); 20 | void LOGGER_ERROR(FILE *file_to_dump, const wchar_t *format, ...); 21 | void LOGGER_ERROR(const wchar_t *format, ...); 22 | 23 | std::string replace_string(std::string str, const string& from, const string& to); 24 | } 25 | 26 | namespace LIEF 27 | { 28 | uint64_t align(uint64_t value, uint64_t align_on); 29 | 30 | template 31 | inline constexpr T round(T x) { 32 | return static_cast(round(x)); 33 | } 34 | 35 | template<> 36 | inline uint64_t round(uint64_t x) { 37 | //From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 38 | x--; 39 | x |= x >> 1; // handle 2 bit numbers 40 | x |= x >> 2; // handle 4 bit numbers 41 | x |= x >> 4; // handle 8 bit numbers 42 | x |= x >> 8; // handle 16 bit numbers 43 | x |= x >> 16; // handle 32 bit numbers 44 | x |= x >> 32; // handle 64 bit numbers 45 | x++; 46 | return x; 47 | } 48 | 49 | 50 | } 51 | 52 | #endif // !UTILS_H 53 | -------------------------------------------------------------------------------- /PE/nt_header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NT_HEADER_H 4 | #define NT_HEADER_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "structures_and_enums.h" 9 | 10 | 11 | namespace pe_parser 12 | { 13 | class nt_header_t 14 | { 15 | public: 16 | 17 | nt_header_t(pe_header * header); 18 | ~nt_header_t() = default; 19 | 20 | // getters 21 | pe_header nt_header(void) const; 22 | const uint32_t signature(void) const; 23 | MACHINE_TYPES machine(void) const; 24 | uint16_t numberof_sections(void) const; 25 | uint32_t time_date_stamp(void) const; 26 | uint32_t pointerto_symbol_table(void) const; 27 | uint32_t numberof_symbols(void) const; 28 | uint16_t sizeof_optional_header(void) const; 29 | HEADER_CHARACTERISTICS characteristics(void) const; 30 | // setters 31 | void machine(MACHINE_TYPES type); 32 | void numberof_sections(uint16_t nbOfSections); 33 | void time_date_stamp(uint32_t timestamp); 34 | void pointerto_symbol_table(uint32_t pointerToSymbol); 35 | void numberof_symbols(uint32_t nbOfSymbols); 36 | void sizeof_optional_header(uint16_t sizeOfOptionalHdr); 37 | void characteristics(HEADER_CHARACTERISTICS characteristics); 38 | void signature(const uint32_t sig); 39 | 40 | bool has_characteristic(HEADER_CHARACTERISTICS c) const; 41 | bool is_pe_header_correct(); 42 | bool dump_nt_header(FILE *file_to_dump); 43 | private: 44 | uint32_t signature_; 45 | MACHINE_TYPES machine_; 46 | uint16_t numberOfSections_; 47 | uint32_t timeDateStamp_; 48 | uint32_t pointerToSymbolTable_; 49 | uint32_t numberOfSymbols_; 50 | uint16_t sizeOfOptionalHeader_; 51 | HEADER_CHARACTERISTICS characteristics_; 52 | 53 | bool pe_header_correct; 54 | }; 55 | } 56 | 57 | #endif // !NT_HEADER_H 58 | -------------------------------------------------------------------------------- /Unpackers/heuristics/w_xor_x_heuristic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef W_XOR_X_HEURISTIC_H 3 | #define W_XOR_X_HEURISTIC_H 4 | 5 | #include "common.h" 6 | #include "utils.h" 7 | 8 | class w_xor_x_heuristic_t 9 | { 10 | public: 11 | /*** 12 | * Structure to track memory activity 13 | * we will log written or executed bytes 14 | * from memory. For that reason 15 | * we record the type of memory access (write or execute) 16 | * and the value of written bytes 17 | */ 18 | typedef struct mem_access 19 | { 20 | mem_access() : w(false), x(false), val(0) {} 21 | mem_access(bool ww, bool xx, unsigned char v) : w(ww), x(xx), val(v) {} 22 | bool w; 23 | bool x; 24 | unsigned char val; 25 | } mem_access_t; 26 | 27 | /*** 28 | * In the unpacking process, we will need to cluster 29 | * adjacent memory bytes to know which memory dump. 30 | * For that is this structure, we will record the 31 | * base address, the size and the access permission 32 | */ 33 | typedef struct mem_cluster 34 | { 35 | mem_cluster() : base(0), size(0), w(false), x(false) {} 36 | mem_cluster(ADDRINT b, unsigned long s, bool ww, bool xx) 37 | : base(b), size(s), w(ww), x(xx) {} 38 | ADDRINT base; 39 | unsigned long size; 40 | bool w; 41 | bool x; 42 | } mem_cluster_t; 43 | 44 | w_xor_x_heuristic_t() = default; 45 | ~w_xor_x_heuristic_t() = default; 46 | 47 | void set_shadow_memory_as_writable(ADDRINT target); 48 | void set_shadow_memory_as_executable(ADDRINT target); 49 | void set_shadow_memory_value(ADDRINT target, unsigned char val); 50 | 51 | bool is_shadow_memory_writable(ADDRINT target); 52 | bool is_shadow_memory_executable(ADDRINT target); 53 | 54 | void set_cluster(ADDRINT target, bool dump); 55 | bool in_cluster(ADDRINT target); 56 | 57 | 58 | 59 | private: 60 | 61 | void add_cluster_to_clusters_list(mem_cluster_t c); 62 | void dump_cluster_to_file(mem_cluster_t c, ADDRINT entry); 63 | 64 | std::map shadow_mem; // map memory addresses with memory 65 | // access permissions. 66 | std::vector clusters; // vector to store all the unpacked memory 67 | // clusters found 68 | }; 69 | 70 | #endif // !W_XOR_X_HEURISTIC_H 71 | -------------------------------------------------------------------------------- /PE/section_header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef SECTION_HEADER_H 4 | #define SECTION_HEADER_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "structures_and_enums.h" 9 | 10 | namespace pe_parser 11 | { 12 | class section_header_t 13 | { 14 | public: 15 | 16 | section_header_t(const pe_section* header); 17 | section_header_t(const std::vector& data, const pe_section* header); 18 | ~section_header_t() = default; 19 | 20 | // getters 21 | pe_section section_header(void) const; 22 | std::vector content(void) const; 23 | std::vector& content_ref(void); 24 | const char* name(void) const; 25 | uint32_t virtual_size(void) const; 26 | uint32_t virtual_address(void) const; 27 | uint32_t sizeof_raw_data(void) const; 28 | uint32_t pointerto_raw_data(void) const; 29 | uint32_t pointerto_relocation(void) const; 30 | uint32_t pointerto_line_numbers(void) const; 31 | uint16_t numberof_relocations(void) const; 32 | uint16_t numberof_line_numbers(void) const; 33 | uint32_t characteristics(void) const; 34 | // setters 35 | void content(const std::vector& data); 36 | void name(const std::string& name); 37 | void virtual_address(uint32_t virtualAddress); 38 | void virtual_size(uint32_t virtualSize); 39 | void pointerto_raw_data(uint32_t pointerToRawData); 40 | void pointerto_relocation(uint32_t pointerToRelocation); 41 | void pointerto_line_numbers(uint32_t pointerToLineNumbers); 42 | void numberof_relocations(uint16_t numberOfRelocations); 43 | void numberof_line_numbers(uint16_t numberOfLineNumbers); 44 | void sizeof_raw_data(uint32_t sizeOfRawData); 45 | void characteristics(uint32_t characteristics); 46 | 47 | bool has_characteristic(SECTION_CHARACTERISTICS c) const; 48 | void add_characteristic(SECTION_CHARACTERISTICS characteristic); 49 | void remove_characteristic(SECTION_CHARACTERISTICS characteristic); 50 | 51 | bool dump_sections(FILE *output_file); 52 | 53 | private: 54 | std::string name_; 55 | uint32_t virtualSize_; 56 | uint32_t virtual_address_; 57 | uint32_t size_; 58 | uint32_t offset_; 59 | uint32_t pointerToRelocations_; 60 | uint32_t pointerToLineNumbers_; 61 | uint16_t numberOfRelocations_; 62 | uint16_t numberOfLineNumbers_; 63 | uint32_t characteristics_; 64 | 65 | std::vector content_; 66 | }; 67 | } 68 | 69 | #endif // !SECTION_HEADER_H 70 | -------------------------------------------------------------------------------- /PE/import_entry.cpp: -------------------------------------------------------------------------------- 1 | #include "import_entry.h" 2 | 3 | import_entry_t::import_entry_t(const import_entry_t&) = default; 4 | 5 | 6 | import_entry_t::~import_entry_t(void) = default; 7 | 8 | 9 | import_entry_t::import_entry_t(void) : 10 | data_{ 0 }, 11 | name_{ "" }, 12 | hint_{ 0 }, 13 | iat_value_{ 0 }, 14 | rva_{ 0 }, 15 | type_{PE_TYPE::pe32_k} 16 | {} 17 | 18 | 19 | import_entry_t::import_entry_t(uint64_t data, const std::string& name) : 20 | data_{ data }, 21 | name_{ name }, 22 | hint_{ 0 }, 23 | iat_value_{ 0 }, 24 | rva_{ 0 }, 25 | type_{PE_TYPE::pe32_k} 26 | {} 27 | 28 | import_entry_t::import_entry_t(const std::string& name) : 29 | import_entry_t{ 0, name } 30 | {} 31 | 32 | bool import_entry_t::is_ordinal(void) const 33 | { 34 | // See: https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-idata-section 35 | const uint64_t ORDINAL_MASK = this->type_ == PE_TYPE::pe32_k ? 0x80000000 : 0x8000000000000000; 36 | bool ordinal_bit_is_set = static_cast(this->data_ & ORDINAL_MASK); 37 | 38 | // Check that bit 31 / 63 is set 39 | if (!ordinal_bit_is_set) 40 | return false; 41 | 42 | // Check that bits 30-15 / 62-15 are set to 0. 43 | uint64_t val = (this->data_ & ~ORDINAL_MASK) >> 15; 44 | 45 | if (val != 0) 46 | return false; 47 | 48 | return true; 49 | } 50 | 51 | 52 | uint16_t import_entry_t::ordinal(void) const 53 | { 54 | if (!this->is_ordinal()) 55 | return -1; 56 | 57 | return static_cast(this->data_ & 0xFFFF); 58 | } 59 | 60 | 61 | uint16_t import_entry_t::hint(void) const 62 | { 63 | return this->hint_; 64 | } 65 | 66 | 67 | uint64_t import_entry_t::iat_value(void) const 68 | { 69 | return this->iat_value_; 70 | } 71 | 72 | 73 | uint64_t import_entry_t::hint_name_rva(void) const 74 | { 75 | return this->data(); 76 | } 77 | 78 | 79 | const std::string& import_entry_t::name(void) const 80 | { 81 | return this->name_; 82 | } 83 | 84 | 85 | uint64_t import_entry_t::data(void) const 86 | { 87 | return this->data_; 88 | } 89 | 90 | 91 | uint64_t import_entry_t::iat_address(void) const 92 | { 93 | return this->rva_; 94 | } 95 | 96 | 97 | void import_entry_t::name(const std::string& name) 98 | { 99 | this->name_ = name; 100 | } 101 | 102 | 103 | void import_entry_t::data(uint64_t data) 104 | { 105 | this->data_ = data; 106 | } 107 | 108 | 109 | bool import_entry_t::dump_import_entry(FILE *output_file) 110 | { 111 | ANBU::LOGGER(output_file, "%s\n", this->name().c_str()); 112 | ANBU::LOGGER(output_file, "%llu\n", this->data()); 113 | ANBU::LOGGER(output_file, "%llu\n", this->iat_value()); 114 | ANBU::LOGGER(output_file, "%x\n", this->hint()); 115 | 116 | return true; 117 | } -------------------------------------------------------------------------------- /makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Unpacker 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines the tools which will be run during the the tests, and were not already defined in 26 | # TEST_TOOL_ROOTS. 27 | TOOL_ROOTS := 28 | 29 | # This defines the static analysis tools which will be run during the the tests. They should not 30 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 31 | # TEST_ROOTS. 32 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 33 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 34 | # of an application or dll. Pin itself is not used when this tool runs. 35 | SA_TOOL_ROOTS := 36 | 37 | # This defines all the applications that will be run during the tests. 38 | APP_ROOTS := 39 | 40 | # This defines any additional object files that need to be compiled. 41 | OBJECT_ROOTS := 42 | 43 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 44 | DLL_ROOTS := 45 | 46 | # This defines any static libraries (archives), that need to be built. 47 | LIB_ROOTS := 48 | 49 | ###### Define the sanity subset ###### 50 | 51 | # This defines the list of tests that should run in sanity. It should include all the tests listed in 52 | # TEST_TOOL_ROOTS and TEST_ROOTS excluding only unstable tests. 53 | SANITY_SUBSET := $(TEST_TOOL_ROOTS) $(TEST_ROOTS) 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /PE/dos_header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef DOS_HEADER_H 4 | #define DOS_HEADER_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "structures_and_enums.h" 9 | 10 | namespace pe_parser 11 | { 12 | 13 | class dos_header_t 14 | { 15 | public: 16 | 17 | 18 | dos_header_t(const pe_dos_header* dos_header_address); 19 | ~dos_header_t() = default; 20 | 21 | // getters 22 | pe_dos_header dos_header(void) const; 23 | uint16_t magic(void) const; 24 | uint16_t used_bytes_in_the_last_page(void) const; 25 | uint16_t file_size_in_pages(void) const; 26 | uint16_t numberof_relocation(void) const; 27 | uint16_t header_size_in_paragraphs(void) const; 28 | uint16_t minimum_extra_paragraphs(void) const; 29 | uint16_t maximum_extra_paragraphs(void) const; 30 | uint16_t initial_relative_ss(void) const; 31 | uint16_t initial_sp(void) const; 32 | uint16_t checksum(void) const; 33 | uint16_t initial_ip(void) const; 34 | uint16_t initial_relative_cs(void) const; 35 | uint16_t addressof_relocation_table(void) const; 36 | uint16_t overlay_number(void) const; 37 | uint16_t reserved(size_t field) const; 38 | uint16_t oem_id(void) const; 39 | uint16_t oem_info(void) const; 40 | uint16_t reserved2(size_t field) const; 41 | uint32_t addressof_new_exeheader(void) const; 42 | // setters 43 | void magic(uint16_t magic); 44 | void used_bytes_in_the_last_page(uint16_t usedBytesInTheLastPage); 45 | void file_size_in_pages(uint16_t fileSizeInPages); 46 | void numberof_relocation(uint16_t numberOfRelocation); 47 | void header_size_in_paragraphs(uint16_t headerSizeInParagraphs); 48 | void minimum_extra_paragraphs(uint16_t minimumExtraParagraphs); 49 | void maximum_extra_paragraphs(uint16_t maximumExtraParagraphs); 50 | void initial_relative_ss(uint16_t initialRelativeSS); 51 | void initial_sp(uint16_t initialSP); 52 | void checksum(uint16_t checksum); 53 | void initial_ip(uint16_t initialIP); 54 | void initial_relative_cs(uint16_t initialRelativeCS); 55 | void addressof_relocation_table(uint16_t addressOfRelocationTable); 56 | void overlay_number(uint16_t overlayNumber); 57 | void reserved(const uint16_t* reserved); 58 | void oem_id(uint16_t oEMid); 59 | void oem_info(uint16_t oEMinfo); 60 | void reserved2(const uint16_t* reserved2); 61 | void addressof_new_exeheader(uint32_t addressOfNewExeHeader); 62 | 63 | 64 | bool check_dos_header(); 65 | bool dump_dos_header(FILE *file_to_dump); 66 | private: 67 | uint16_t magic_; 68 | uint16_t usedBytesInTheLastPage_; 69 | uint16_t fileSizeInPages_; 70 | uint16_t numberOfRelocation_; 71 | uint16_t headerSizeInParagraphs_; 72 | uint16_t minimumExtraParagraphs_; 73 | uint16_t maximumExtraParagraphs_; 74 | uint16_t initialRelativeSS_; 75 | uint16_t initialSP_; 76 | uint16_t checksum_; 77 | uint16_t initialIP_; 78 | uint16_t initialRelativeCS_; 79 | uint16_t addressOfRelocationTable_; 80 | uint16_t overlayNumber_; 81 | uint16_t reserved_[4]; 82 | uint16_t oEMid_; 83 | uint16_t oEMinfo_; 84 | uint16_t reserved2_[10]; 85 | uint32_t addressOfNewExeHeader_; 86 | 87 | bool dos_header_correct; 88 | }; 89 | } 90 | 91 | #endif // !DOS_HEADER_H -------------------------------------------------------------------------------- /Unpackers/run_pe_detector.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * RunPE detector By Jurriaan Bremer 3 | */ 4 | #pragma once 5 | 6 | 7 | #ifndef RUN_PE_DETECTOR_H 8 | #define RUN_PE_DETECTOR_H 9 | 10 | #include "common.h" 11 | #include "utils.h" 12 | #include "binary.h" 13 | #include "proc_info.h" 14 | #include "md5.h" 15 | #include "data_directory_header.h" 16 | 17 | #define USHORT WINDOWS::USHORT 18 | #define ULONG WINDOWS::ULONG 19 | typedef wchar_t *PWCH; 20 | typedef char *PCHAR; 21 | #define HANDLE WINDOWS::HANDLE 22 | #define PHANDLE WINDOWS::PHANDLE 23 | #define HMODULE WINDOWS::HMODULE 24 | typedef void *PVOID; 25 | #define RTL_MAX_DRIVE_LETTERS 32 26 | 27 | typedef struct _STRING 28 | { 29 | USHORT Length; 30 | USHORT MaximumLength; 31 | PCHAR Buffer; 32 | } STRING, *PSTRING, ANSI_STRING, *PANSI_STRING, OEM_STRING, *POEM_STRING; 33 | 34 | typedef struct _UNICODE_STRING { 35 | USHORT Length; 36 | USHORT MaximumLength; 37 | PWCH Buffer; 38 | } UNICODE_STRING, *PUNICODE_STRING; 39 | 40 | typedef struct _OBJECT_ATTRIBUTES { 41 | ULONG Length; 42 | HANDLE RootDirectory; 43 | PUNICODE_STRING ObjectName; 44 | ULONG Attributes; 45 | PVOID SecurityDescriptor; 46 | PVOID SecurityQualityOfService; 47 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 48 | 49 | typedef struct _CURDIR { 50 | UNICODE_STRING DosPath; 51 | HANDLE Handle; 52 | } CURDIR, *PCURDIR; 53 | 54 | typedef struct _RTL_DRIVE_LETTER_CURDIR { 55 | USHORT Flags; 56 | USHORT Length; 57 | ULONG TimeStamp; 58 | STRING DosPath; 59 | } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; 60 | 61 | typedef struct _RTL_USER_PROCESS_PARAMETERS { 62 | ULONG MaximumLength; 63 | ULONG Length; 64 | 65 | ULONG Flags; 66 | ULONG DebugFlags; 67 | 68 | HANDLE ConsoleHandle; 69 | ULONG ConsoleFlags; 70 | HANDLE StandardInput; 71 | HANDLE StandardOutput; 72 | HANDLE StandardError; 73 | 74 | CURDIR CurrentDirectory; 75 | UNICODE_STRING DllPath; 76 | UNICODE_STRING ImagePathName; 77 | UNICODE_STRING CommandLine; 78 | PVOID Environment; 79 | 80 | ULONG StartingX; 81 | ULONG StartingY; 82 | ULONG CountX; 83 | ULONG CountY; 84 | ULONG CountCharsX; 85 | ULONG CountCharsY; 86 | ULONG FillAttribute; 87 | 88 | ULONG WindowFlags; 89 | ULONG ShowWindowFlags; 90 | UNICODE_STRING WindowTitle; 91 | UNICODE_STRING DesktopInfo; 92 | UNICODE_STRING ShellInfo; 93 | UNICODE_STRING RuntimeData; 94 | RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; 95 | 96 | ULONG EnvironmentSize; 97 | ULONG EnvironmentVersion; 98 | } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; 99 | 100 | typedef struct _syscall_t 101 | { 102 | ADDRINT syscall_number; 103 | union 104 | { 105 | ADDRINT args[16]; 106 | struct 107 | { 108 | ADDRINT arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7; 109 | }; 110 | }; 111 | } syscall_t; 112 | 113 | void enum_syscalls(); 114 | unsigned long syscall_name_to_number(const char *name); 115 | void init_common_syscalls(); 116 | void syscall_get_arguments(CONTEXT *ctx, SYSCALL_STANDARD std, int count, ...); 117 | void syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v); 118 | void syscall_exit(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v); 119 | bool compare_by_address(const write_memory_t& a, const write_memory_t& b); 120 | #endif // !RUN_PE_DETECTOR_H 121 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | /* MD5 2 | converted to C++ class by Frank Thilo (thilo@unix-ag.org) 3 | for bzflag (http://www.bzflag.org) 4 | 5 | based on: 6 | 7 | md5.h and md5.c 8 | reference implementation of RFC 1321 9 | 10 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 11 | rights reserved. 12 | 13 | License to copy and use this software is granted provided that it 14 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 15 | Algorithm" in all material mentioning or referencing this software 16 | or this function. 17 | 18 | License is also granted to make and use derivative works provided 19 | that such works are identified as "derived from the RSA Data 20 | Security, Inc. MD5 Message-Digest Algorithm" in all material 21 | mentioning or referencing the derived work. 22 | 23 | RSA Data Security, Inc. makes no representations concerning either 24 | the merchantability of this software or the suitability of this 25 | software for any particular purpose. It is provided "as is" 26 | without express or implied warranty of any kind. 27 | 28 | These notices must be retained in any copies of any part of this 29 | documentation and/or software. 30 | 31 | */ 32 | 33 | #ifndef BZF_MD5_H 34 | #define BZF_MD5_H 35 | 36 | #include "common.h" 37 | 38 | 39 | // a small class for calculating MD5 hashes of strings or byte arrays 40 | // it is not meant to be fast or secure 41 | // 42 | // usage: 1) feed it blocks of uchars with update() 43 | // 2) finalize() 44 | // 3) get hexdigest() string 45 | // or 46 | // MD5(std::string).hexdigest() 47 | // 48 | // assumes that char is 8 bit and int is 32 bit 49 | class MD5 50 | { 51 | public: 52 | typedef unsigned int size_type; // must be 32bit 53 | 54 | MD5(); 55 | MD5(const std::string& text); 56 | void update(const unsigned char *buf, size_type length); 57 | void update(const char *buf, size_type length); 58 | MD5& finalize(); 59 | std::string hexdigest() const; 60 | friend std::ostream& operator<<(std::ostream&, MD5 md5); 61 | 62 | private: 63 | void init(); 64 | typedef unsigned char uint1; // 8bit 65 | typedef unsigned int uint4; // 32bit 66 | enum { blocksize = 64 }; // VC6 won't eat a const static int here 67 | 68 | void transform(const uint1 block[blocksize]); 69 | static void decode(uint4 output[], const uint1 input[], size_type len); 70 | static void encode(uint1 output[], const uint4 input[], size_type len); 71 | 72 | bool finalized; 73 | uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk 74 | uint4 count[2]; // 64bit counter for number of bits (lo, hi) 75 | uint4 state[4]; // digest so far 76 | uint1 digest[16]; // the result 77 | 78 | // low level logic operations 79 | static inline uint4 F(uint4 x, uint4 y, uint4 z); 80 | static inline uint4 G(uint4 x, uint4 y, uint4 z); 81 | static inline uint4 H(uint4 x, uint4 y, uint4 z); 82 | static inline uint4 I(uint4 x, uint4 y, uint4 z); 83 | static inline uint4 rotate_left(uint4 x, int n); 84 | static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 85 | static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 86 | static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 87 | static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); 88 | }; 89 | 90 | 91 | std::string md5(const std::string str); 92 | 93 | #endif -------------------------------------------------------------------------------- /PE/data_directory_header.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "data_directory_header.h" 3 | 4 | /************* EXTERN VARIABLES *************/ 5 | extern FILE *logfile; // log file handler 6 | 7 | namespace pe_parser 8 | { 9 | 10 | data_directory_header_t::data_directory_header_t(const pe_data_directory *header, DATA_DIRECTORY type) : 11 | rva_ { header->RelativeVirtualAddress }, 12 | size_ { header->Size }, 13 | type_ { type } 14 | { 15 | /* I couldn't initialize the map with as many values, so I do it in the constructor */ 16 | directory_names[DATA_DIRECTORY::export_table_k] = "Export Table"; 17 | directory_names[DATA_DIRECTORY::import_table_k] = "Import Table"; 18 | directory_names[DATA_DIRECTORY::resource_table_k] = "Resource Table"; 19 | directory_names[DATA_DIRECTORY::exception_table_k] = "Exception Table"; 20 | directory_names[DATA_DIRECTORY::certificate_table_k] = "Certificate Table"; 21 | directory_names[DATA_DIRECTORY::base_relocation_table_k] = "Base Relocation Table"; 22 | directory_names[DATA_DIRECTORY::debug_k] = "Debug"; 23 | directory_names[DATA_DIRECTORY::architecture_k] = "Architecture"; 24 | directory_names[DATA_DIRECTORY::global_ptr_k] = "Global Ptr"; 25 | directory_names[DATA_DIRECTORY::tls_table_k] = "TLS Table"; 26 | directory_names[DATA_DIRECTORY::load_config_table_k] = "Load Config Table"; 27 | directory_names[DATA_DIRECTORY::bound_import_k] = "Bound Import"; 28 | directory_names[DATA_DIRECTORY::iat_k] = "IAT"; 29 | directory_names[DATA_DIRECTORY::delay_import_descriptor_k] = "Delay Import Descriptor"; 30 | directory_names[DATA_DIRECTORY::clr_runtime_header_k] = "CLR Runtime Header"; 31 | directory_names[DATA_DIRECTORY::reserved_k] = "Reserved"; 32 | } 33 | 34 | 35 | pe_data_directory data_directory_header_t::data_directory(void) const 36 | { 37 | /* 38 | * This part corresponds to LIEF project: 39 | Builder& Builder::operator<<(const DataDirectory& data_directory) { 40 | 41 | pe_data_directory header; 42 | 43 | header.RelativeVirtualAddress = data_directory.RVA(); 44 | header.Size = data_directory.size(); 45 | 46 | this->ios_.write(reinterpret_cast(&header), sizeof(pe_data_directory)); 47 | return *this; 48 | } 49 | */ 50 | pe_data_directory data_directory; 51 | 52 | data_directory.RelativeVirtualAddress = this->rva_; 53 | data_directory.Size = this->size_; 54 | 55 | return data_directory; 56 | } 57 | 58 | 59 | uint32_t data_directory_header_t::RVA(void) const 60 | { 61 | return this->rva_; 62 | } 63 | 64 | 65 | uint32_t data_directory_header_t::size(void) const 66 | { 67 | return this->size_; 68 | } 69 | 70 | 71 | DATA_DIRECTORY data_directory_header_t::type(void) const 72 | { 73 | return this->type_; 74 | } 75 | 76 | 77 | void data_directory_header_t::RVA(uint32_t rva) 78 | { 79 | this->rva_ = rva; 80 | } 81 | 82 | 83 | void data_directory_header_t::size(uint32_t size) 84 | { 85 | this->size_ = size; 86 | } 87 | 88 | 89 | void data_directory_header_t::type(DATA_DIRECTORY type) 90 | { 91 | this->type_ = type; 92 | } 93 | 94 | 95 | bool data_directory_header_t::dump_directories(FILE *output_file) 96 | { 97 | ANBU::LOGGER(output_file, "\t+Name: %s\n", directory_names[this->type()].c_str()); 98 | ANBU::LOGGER(output_file, "\t+Virtual Address: 0x%x\n", this->RVA()); 99 | ANBU::LOGGER(output_file, "\t+Size: 0x%x\n", this->size()); 100 | 101 | return true; 102 | } 103 | } -------------------------------------------------------------------------------- /Unpackers/heuristics/w_xor_x_heuristic.cpp: -------------------------------------------------------------------------------- 1 | #include "w_xor_x_heuristic.h" 2 | 3 | /************* EXTERN VARIABLES *************/ 4 | extern FILE* logfile; 5 | 6 | void w_xor_x_heuristic_t::set_shadow_memory_as_writable(ADDRINT target) 7 | { 8 | shadow_mem[target].w = true; 9 | } 10 | 11 | 12 | void w_xor_x_heuristic_t::set_shadow_memory_as_executable(ADDRINT target) 13 | { 14 | shadow_mem[target].x = true; 15 | } 16 | 17 | 18 | void w_xor_x_heuristic_t::set_shadow_memory_value(ADDRINT target, unsigned char val) 19 | { 20 | shadow_mem[target].val = val; 21 | } 22 | 23 | 24 | bool w_xor_x_heuristic_t::is_shadow_memory_writable(ADDRINT target) 25 | { 26 | if (shadow_mem.find(target) != shadow_mem.end()) 27 | { 28 | return shadow_mem[target].w; 29 | } 30 | return false; 31 | } 32 | 33 | 34 | bool w_xor_x_heuristic_t::is_shadow_memory_executable(ADDRINT target) 35 | { 36 | if (shadow_mem.find(target) != shadow_mem.end()) 37 | { 38 | return shadow_mem[target].x; 39 | } 40 | return false; 41 | } 42 | 43 | 44 | void w_xor_x_heuristic_t::set_cluster(ADDRINT target, bool dump) 45 | { 46 | mem_cluster_t c; 47 | 48 | ADDRINT addr, base; 49 | unsigned long size; 50 | bool w, x; 51 | std::map::iterator i, j; 52 | 53 | j = shadow_mem.find(target); 54 | assert(j != shadow_mem.end()); 55 | 56 | base = target; 57 | w = false; 58 | x = false; 59 | 60 | for (i = j; ; i--) 61 | { 62 | addr = i->first; 63 | 64 | if (addr == base) 65 | { 66 | if (i->second.w) 67 | w = true; 68 | if (i->second.x) 69 | x = true; 70 | base--; 71 | } 72 | else 73 | { 74 | base++; 75 | break; 76 | } 77 | 78 | if (i == shadow_mem.begin()) 79 | { 80 | base++; 81 | break; 82 | } 83 | } 84 | 85 | size = target - base; 86 | for (i = j; i != shadow_mem.end(); i++) 87 | { 88 | addr = i->first; 89 | if (addr == base + size) 90 | { 91 | if (i->second.w) 92 | w = true; 93 | if (i->second.x) 94 | x = true; 95 | size++; 96 | } 97 | else 98 | { 99 | break; 100 | } 101 | } 102 | 103 | c.base = base; 104 | c.size = size; 105 | c.w = w; 106 | c.x = x; 107 | 108 | this->add_cluster_to_clusters_list(c); 109 | 110 | if (dump) 111 | this->dump_cluster_to_file(c, target); 112 | } 113 | 114 | 115 | bool w_xor_x_heuristic_t::in_cluster(ADDRINT target) 116 | /* 117 | * Function to check target address is inside of 118 | * any memory cluster. 119 | */ 120 | { 121 | mem_cluster_t *c; 122 | 123 | for (unsigned i = 0; i < clusters.size(); i++) 124 | { 125 | c = &clusters[i]; 126 | 127 | if (c->base <= target && 128 | target < c->base + c->size) 129 | { 130 | return true; 131 | } 132 | } 133 | 134 | return false; 135 | } 136 | 137 | 138 | void w_xor_x_heuristic_t::add_cluster_to_clusters_list(mem_cluster_t c) 139 | { 140 | clusters.push_back(c); 141 | } 142 | 143 | 144 | void w_xor_x_heuristic_t::dump_cluster_to_file(mem_cluster_t c, ADDRINT entry) 145 | { 146 | FILE *f; 147 | char buf[256]; 148 | 149 | ANBU::LOGGER_INFO("Extracting unpacked region 0x%x %c%c entry 0x%x\n", 150 | (uintptr_t)c.base, c.w ? 'w' : '-', c.x ? 'x' : '-', (uintptr_t)entry); 151 | 152 | snprintf(buf, sizeof(buf), "unpacked.0x%x-0x%x_entry-0x%x", 153 | (uintptr_t)c.base, (uintptr_t)(c.base + c.size), (uintptr_t)entry); 154 | 155 | f = fopen(buf, "wb"); 156 | if (!f) 157 | { 158 | ANBU::LOGGER_ERROR(logfile, "Failed to open file '%s' for writing\n", buf); 159 | } 160 | else 161 | { 162 | for (ADDRINT i = c.base; i < c.base + c.size; i++) 163 | { 164 | if (fwrite((const void*)&shadow_mem[i].val, 1, 1, f) != 1) 165 | { 166 | ANBU::LOGGER_ERROR(logfile, "Failed to write unpacked byte 0x%x to file '%s'\n", (unsigned int)i, buf); 167 | } 168 | } 169 | 170 | fclose(f); 171 | } 172 | } -------------------------------------------------------------------------------- /PE/import.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef IMPORT_H 3 | #define IMPORT_H 4 | 5 | #include "common.h" 6 | #include "utils.h" 7 | #include "structures_and_enums.h" 8 | #include "import_entry.h" 9 | #include "data_directory_header.h" 10 | 11 | /* 12 | using imports_t = std::vector; 13 | using it_imports = ref_iterator; 14 | using it_const_imports = const_ref_iterator; 15 | 16 | using import_entries_t = std::vector; 17 | using it_import_entries = ref_iterator; 18 | using it_const_import_entries = const_ref_iterator; 19 | */ 20 | 21 | class lief_import_t 22 | { 23 | public: 24 | lief_import_t(const pe_import *import); 25 | lief_import_t(const std::string& name); 26 | lief_import_t(void); 27 | ~lief_import_t(void); 28 | 29 | lief_import_t(const lief_import_t& other); 30 | lief_import_t& operator=(lief_import_t other); 31 | void swap(lief_import_t& other); 32 | 33 | uint32_t forwarder_chain(void) const; 34 | uint32_t timedatestamp(void) const; 35 | 36 | //! @brief Return a vector of @link PE::ImportEntry Import entries @endlink 37 | std::vector entries(void); 38 | void entries(std::vector); 39 | //! @brief Return the relative virtual address of the import address table (`IAT`) 40 | // 41 | //! @warning 42 | //! This address could be change when re-building the binary 43 | //! 44 | uint32_t import_address_table_rva(void) const; 45 | 46 | //! @brief Return the relative virtual address of the import lookup table 47 | //! 48 | //! @warning 49 | //! This address could be change when re-building the binary 50 | //! 51 | uint32_t import_lookup_table_rva(void) const; 52 | 53 | //! @brief Return the Function's RVA from the import address table (`IAT`) 54 | //! 55 | //! @warning 56 | //! This address could be change when re-building the binary 57 | //! 58 | uint32_t get_function_rva_from_iat(const std::string& function) const; 59 | 60 | 61 | //! @brief Return the imported function with the given name 62 | import_entry_t* get_entry(const std::string& name); 63 | const import_entry_t* get_entry(const std::string& name) const; 64 | 65 | //! @brief Return the library's name 66 | //! 67 | //! e.g. `kernel32.dll` 68 | const std::string& name(void) const; 69 | void name(const std::string& name); 70 | 71 | 72 | //! @brief Return the @link PE::DataDirectory Data directory@endlink associated. 73 | //! It should be the one at index PE::DATA_DIRECTORY::IMPORT_TABLE 74 | //! 75 | pe_parser::data_directory_header_t* directory(void); 76 | const pe_parser::data_directory_header_t* directory(void) const; 77 | 78 | //! @brief Return the @link PE::DataDirectory Data directory@endlink associated. 79 | //! It should be the one at index PE::DATA_DIRECTORY::IAT 80 | //! 81 | pe_parser::data_directory_header_t* iat_directory(void); 82 | const pe_parser::data_directory_header_t* iat_directory(void) const; 83 | 84 | 85 | //! @brief Add a function 86 | import_entry_t& add_entry(const import_entry_t& entry); 87 | 88 | 89 | //! @brief Add a function from name 90 | import_entry_t& add_entry(const std::string& name); 91 | 92 | void import_lookup_table_rva(uint32_t rva); 93 | void import_address_table_rva(uint32_t rva); 94 | 95 | bool dump_import(FILE *output_file); 96 | 97 | 98 | private: 99 | std::vector entries_; 100 | pe_parser::data_directory_header_t* directory_; 101 | pe_parser::data_directory_header_t* iat_directory_; 102 | uint32_t import_lookup_table_RVA_; 103 | uint32_t timedatestamp_; 104 | uint32_t forwarder_chain_; 105 | uint32_t name_RVA_; 106 | uint32_t import_address_table_RVA_; 107 | std::string name_; 108 | PE_TYPE type_; 109 | }; 110 | 111 | 112 | #endif // !IMPORT_H 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ANBU 2 | *Automatic New Binary Unpacker with PIN DBI Framework* 3 | This project is considered more an academic project than something professional or company software, I have it as a way for me to learn about how to use PIN and how to implement interesting things with it, so pull request are welcome. 4 | 5 | ## First of All: Compiling ANBU 6 | 7 | To compile ANBU you need to download PIN, and you can download it from here: [Intel PIN][1]. Once you have PIN on your system, you have to copy ANBU folder on /source/tools/ path, also you can create another folder instead of "tools" I created one called "unpackers". Once you have the path /source/tools or unpackers/ANBU, you can open ANBU.sln file with Visual Studio, in my case I use Visual Studio 2017. To compile I do nothing special more than compile the project I compile on "Release" for "x86" (I haven't tested or programmed ANBU for x64 for the moment). And that's all, you'll have ANBU.dll on your release folder. 8 | 9 | ## Testing ANBU 10 | 11 | ANBU doesn't have any special flag to use for the moment so you can run ANBU as any PIN tool: 12 | 13 | ```shell 14 | pin -t ANBU.dll -- program_to_unpack.exe 15 | ``` 16 | 17 | Also there's a flag to modify output file name with log. 18 | 19 | ## Unpacked code 20 | 21 | ANBU dumps two different things, one of the things ANBU dumps are memory chunks that appears from unpacking process, this is not a PE file it's only a binary file with written and executed code (can be a complete section or only a chunk from unpacking process), after the unpacking process ANBU will try to dump the unpacked PE file with a new section of imports (called ".F9" I don't have much imagination). For the process a file log is created and updated during the execution. 22 | 23 | ## Packers tested 24 | 25 | I'm not professional on this, but I give some examples to the people who wanna try ANBU those are: 26 | 27 | - UPX 28 | - AHPack 29 | - MEW 30 | - EZIP 31 | - FSG 32 | - Mpress 33 | - Aspack 34 | - pokecrypt 35 | - Basic RunPE 36 | - Test 37 | 38 | Test folder is where I save some code tests for testing ANBU, so for example you can find here the test for timing hooks. 39 | 40 | ## Issues 41 | 42 | - A friend has discovered an issue I had when I was compiling PIN with all this stuff of WINDOWS. I had a problem compiling, so I modified Windows.h from PIN (/extras/crt/include/Windows.h). What I did was to comment the next line: 43 | 44 | ```Cpp 45 | #include WINDOWS_H_PATH 46 | ``` 47 | 48 | And I wrote the next thing: 49 | 50 | ```Cpp 51 | //#include WINDOWS_H_PATH 52 | #include 53 | ``` 54 | 55 | ## Changelog 56 | 57 | ### Version 0.7 58 | 59 | - some packers unpacked and tests done for reliability and stability of the tool. 60 | - Adapted Lief code for PE parsing and PE reconstruction. 61 | - Included ProcInfo from Arancino, improved speed in instrumentation avoiding instructions from known libraries. 62 | - Added new support of some unpackers. 63 | 64 | ## ToDO 65 | 66 | - Next version should include some new heuristic to detect Microsoft Visual Studio OEP trace. 67 | - Include a way to unpack crypters by saving decrypted code. 68 | 69 | ## Special thanks to 70 | 71 | - [MZ IAT][2]: For helping me with testing, and also discover an issue. 72 | - [Hasherezade][3]: For her blogpost about Visual Studio PIN projects compiling. 73 | - [Joxean Koret][4]: For his blogpost about unpacking with PIN. 74 | - [Jurrian Bremer][5]: For his RunPE unpacking module. 75 | - [Arancino Project][6]: For their heuristics ideas and dynamic protection framework. 76 | - [Dennis Andriesse][7]: For his book Practical Binary Analysis which helped me to start this project. 77 | - [LIEF Project and Romain Thomas][8]: For his project and the permission to use LIEF code for parser and builder. 78 | 79 | [1]: "Intel PIN download link" 80 | [2]: "MZ IAT Twitter" 81 | [3]: "Hasherezade Twitter" 82 | [4]: "Joxean Koret Twitter" 83 | [5]: "Jurrian Bremer Twitter" 84 | [6]: "Arancino Project" 85 | [7]: "Dennis Andriesse webpage" 86 | [8]: "Lief Project" -------------------------------------------------------------------------------- /anti-methods/anti-methods.cpp: -------------------------------------------------------------------------------- 1 | #include "anti-methods.h" 2 | 3 | /************* EXTERN VARIABLES *************/ 4 | extern FILE* logfile; // log file handler 5 | extern uint64_t tick_counts_per_millisecond; 6 | 7 | /************* VARIABLES FOR ANTI-* STUFF ***/ 8 | static uint32_t rdtsc = 0; 9 | static WINDOWS::SYSTEMTIME local_time = { 0 }; 10 | static WINDOWS::SYSTEMTIME system_time = { 0 }; 11 | 12 | /****************************** 13 | * INSTRUMENTATION CODE 14 | *******************************/ 15 | 16 | void hook_functions(IMG img, VOID *v) 17 | { 18 | RTN isdebuggerpresent; 19 | RTN sleep; 20 | RTN gettickcount; 21 | RTN gettickcount64; 22 | RTN process32first; 23 | RTN process32next; 24 | 25 | isdebuggerpresent = RTN_FindByName(img, "IsDebuggerPresent"); 26 | if (RTN_Valid(isdebuggerpresent)) 27 | { 28 | ANBU::LOGGER_INFO(logfile, "Replacing IsDebuggerPresent for anti IsDebuggerPresent\n"); 29 | RTN_Replace(isdebuggerpresent, AFUNPTR(MyIsDebuggerPresent)); 30 | } 31 | 32 | sleep = RTN_FindByName(img, "Sleep"); 33 | if (RTN_Valid(sleep)) 34 | { 35 | ANBU::LOGGER_INFO(logfile, "Replacing Sleep for anti Sleep\n"); 36 | RTN_Replace(sleep, AFUNPTR(MySleep)); 37 | } 38 | 39 | gettickcount = RTN_FindByName(img, "GetTickCount"); 40 | if (RTN_Valid(gettickcount)) 41 | { 42 | ANBU::LOGGER_INFO(logfile, "Replacing GetTickCount for anti GetTickCount\n"); 43 | RTN_Replace(gettickcount, AFUNPTR(MyGetTickCount)); 44 | } 45 | 46 | gettickcount64 = RTN_FindByName(img, "GetTickCount64"); 47 | if (RTN_Valid(gettickcount64)) 48 | { 49 | ANBU::LOGGER_INFO(logfile, "Replacing GetTickCount64 for anti GetTickCount64\n"); 50 | RTN_Replace(gettickcount64, AFUNPTR(MyGetTickCount64)); 51 | } 52 | 53 | process32first = RTN_FindByName(img, "Process32First"); 54 | if (RTN_Valid(process32first)) 55 | { 56 | ANBU::LOGGER_INFO(logfile, "Replacing Process32First for anti Process32First\n"); 57 | RTN_Replace(process32first, AFUNPTR(MyProcess32First)); 58 | } 59 | 60 | process32next = RTN_FindByName(img, "Process32Next"); 61 | if (RTN_Valid(process32next)) 62 | { 63 | ANBU::LOGGER_INFO(logfile, "Replacing Process32Next for anti Process32Next\n"); 64 | RTN_Replace(process32next, AFUNPTR(MyProcess32Next)); 65 | } 66 | } 67 | 68 | void hook_instructions(INS ins, void *v) 69 | { 70 | if (INS_IsRDTSC(ins)) 71 | { 72 | INS_InsertPredicatedCall( 73 | ins, 74 | IPOINT_AFTER, 75 | AFUNPTR(MyRDTSC), 76 | IARG_REG_REFERENCE, REG_GAX, 77 | IARG_REG_REFERENCE, REG_GDX, 78 | IARG_END 79 | ); 80 | } 81 | } 82 | 83 | /****************************** 84 | * HOOKS 85 | *******************************/ 86 | 87 | WINDOWS::BOOL WINAPI MyIsDebuggerPresent() 88 | { 89 | return FALSE; 90 | } 91 | 92 | WINDOWS::DWORD WINAPI MyGetTickCount() 93 | { 94 | if (!rdtsc) 95 | { 96 | rdtsc = WINDOWS::GetTickCount(); 97 | } 98 | else 99 | { 100 | rdtsc++; 101 | } 102 | 103 | return rdtsc; 104 | } 105 | 106 | WINDOWS::ULONGLONG WINAPI MyGetTickCount64() 107 | { 108 | return (WINDOWS::ULONGLONG)MyGetTickCount(); 109 | } 110 | 111 | void MySleep(WINDOWS::DWORD dwMilliseconds) 112 | { 113 | if (!rdtsc) 114 | { 115 | rdtsc = MyGetTickCount(); 116 | } 117 | 118 | rdtsc += (uint32_t)tick_counts_per_millisecond * dwMilliseconds; 119 | 120 | ANBU::LOGGER_INFO(logfile, "Sleep Avoided\n"); 121 | return; 122 | } 123 | 124 | /* 125 | * Fixed function thanks to: https://reverseengineering.stackexchange.com/questions/17830/intel-pin-tracerpin-adding-modification-of-registers 126 | */ 127 | void MyRDTSC(ADDRINT *gax, ADDRINT *gdx) 128 | { 129 | ADDRINT new_value = MyGetTickCount(); 130 | 131 | *gax = new_value; 132 | *gdx = (ADDRINT)0; 133 | 134 | return; 135 | } 136 | 137 | WINDOWS::BOOL MyProcess32First(WINDOWS::HANDLE hSnapshot, WINDOWS::LPPROCESSENTRY32 lppe) 138 | { 139 | WINDOWS::BOOL function_return = WINDOWS::Process32First(hSnapshot, lppe); 140 | 141 | if (strcmp(lppe->szExeFile, "pin.exe") == 0) 142 | { 143 | function_return = WINDOWS::Process32Next(hSnapshot, lppe); 144 | } 145 | 146 | return function_return; 147 | } 148 | 149 | WINDOWS::BOOL MyProcess32Next(WINDOWS::HANDLE hSnapshot, WINDOWS::LPPROCESSENTRY32 lppe) 150 | { 151 | WINDOWS::BOOL function_return = WINDOWS::Process32Next(hSnapshot, lppe); 152 | 153 | if (strcmp(lppe->szExeFile, "pin.exe") == 0) 154 | { 155 | function_return = WINDOWS::Process32Next(hSnapshot, lppe); 156 | } 157 | 158 | return function_return; 159 | } -------------------------------------------------------------------------------- /utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | namespace ANBU 4 | { 5 | 6 | void LOGGER(FILE *file_to_dump, const char *format, ...) 7 | { 8 | va_list argptr; 9 | va_start(argptr, format); 10 | 11 | if (file_to_dump) 12 | { 13 | vfprintf(file_to_dump, format, argptr); 14 | } 15 | 16 | vfprintf(stderr, format, argptr); 17 | vfprintf(stdout, format, argptr); 18 | 19 | va_end(argptr); 20 | } 21 | 22 | 23 | void LOGGER(const char *format, ...) 24 | { 25 | va_list argptr; 26 | va_start(argptr, format); 27 | 28 | vfprintf(stderr, format, argptr); 29 | vfprintf(stdout, format, argptr); 30 | 31 | va_end(argptr); 32 | } 33 | 34 | 35 | void LOGGER_INFO(FILE *file_to_dump, const char *format, ...) 36 | { 37 | va_list argptr; 38 | va_start(argptr, format); 39 | 40 | if (file_to_dump) 41 | { 42 | fprintf(file_to_dump, "[INFO] "); 43 | vfprintf(file_to_dump, format, argptr); 44 | } 45 | fprintf(stderr, "[INFO] "); 46 | vfprintf(stderr, format, argptr); 47 | fprintf(stdout, "[INFO] "); 48 | vfprintf(stdout, format, argptr); 49 | 50 | va_end(argptr); 51 | } 52 | 53 | 54 | void LOGGER_INFO(const char *format, ...) 55 | { 56 | va_list argptr; 57 | va_start(argptr, format); 58 | 59 | fprintf(stderr, "[INFO] "); 60 | vfprintf(stderr, format, argptr); 61 | fprintf(stdout, "[INFO] "); 62 | vfprintf(stdout, format, argptr); 63 | 64 | va_end(argptr); 65 | } 66 | 67 | 68 | void LOGGER_ERROR(FILE *file_to_dump, const char *format, ...) 69 | { 70 | va_list argptr; 71 | va_start(argptr, format); 72 | 73 | if (file_to_dump) 74 | { 75 | fprintf(file_to_dump, "[ERROR] "); 76 | vfprintf(file_to_dump, format, argptr); 77 | } 78 | 79 | fprintf(stderr, "[ERROR] "); 80 | vfprintf(stderr, format, argptr); 81 | fprintf(stdout, "[ERROR] "); 82 | vfprintf(stdout, format, argptr); 83 | 84 | va_end(argptr); 85 | } 86 | 87 | 88 | void LOGGER_ERROR(const char *format, ...) 89 | { 90 | va_list argptr; 91 | va_start(argptr, format); 92 | 93 | fprintf(stderr, "[ERROR] "); 94 | vfprintf(stderr, format, argptr); 95 | fprintf(stdout, "[ERROR] "); 96 | vfprintf(stdout, format, argptr); 97 | 98 | va_end(argptr); 99 | } 100 | 101 | 102 | void LOGGER(FILE *file_to_dump, const wchar_t *format, ...) 103 | { 104 | va_list argptr; 105 | va_start(argptr, format); 106 | 107 | if (file_to_dump) 108 | { 109 | vfwprintf(file_to_dump, format, argptr); 110 | } 111 | 112 | vfwprintf(stderr, format, argptr); 113 | vfwprintf(stdout, format, argptr); 114 | 115 | va_end(argptr); 116 | } 117 | 118 | 119 | void LOGGER(const wchar_t *format, ...) 120 | { 121 | va_list argptr; 122 | va_start(argptr, format); 123 | 124 | vfwprintf(stderr, format, argptr); 125 | vfwprintf(stdout, format, argptr); 126 | 127 | va_end(argptr); 128 | } 129 | 130 | 131 | void LOGGER_INFO(FILE *file_to_dump, const wchar_t *format, ...) 132 | { 133 | va_list argptr; 134 | va_start(argptr, format); 135 | 136 | if (file_to_dump) 137 | { 138 | fwprintf(file_to_dump, L"[INFO] "); 139 | vfwprintf(file_to_dump, format, argptr); 140 | } 141 | 142 | fwprintf(stderr, L"[INFO] "); 143 | vfwprintf(stderr, format, argptr); 144 | fwprintf(stdout, L"[INFO] "); 145 | vfwprintf(stdout, format, argptr); 146 | 147 | va_end(argptr); 148 | } 149 | 150 | 151 | void LOGGER_INFO(const wchar_t *format, ...) 152 | { 153 | va_list argptr; 154 | va_start(argptr, format); 155 | 156 | fwprintf(stderr, L"[INFO] "); 157 | vfwprintf(stderr, format, argptr); 158 | fwprintf(stdout, L"[INFO] "); 159 | vfwprintf(stdout, format, argptr); 160 | 161 | va_end(argptr); 162 | } 163 | 164 | 165 | void LOGGER_ERROR(FILE *file_to_dump, const wchar_t *format, ...) 166 | { 167 | va_list argptr; 168 | va_start(argptr, format); 169 | 170 | if (file_to_dump) 171 | { 172 | fwprintf(file_to_dump, L"[ERROR] "); 173 | vfwprintf(file_to_dump, format, argptr); 174 | } 175 | fwprintf(stderr, L"[ERROR] "); 176 | vfwprintf(stderr, format, argptr); 177 | fwprintf(stdout, L"[ERROR] "); 178 | vfwprintf(stdout, format, argptr); 179 | 180 | va_end(argptr); 181 | } 182 | 183 | 184 | void LOGGER_ERROR(const wchar_t *format, ...) 185 | { 186 | va_list argptr; 187 | va_start(argptr, format); 188 | 189 | fwprintf(stderr, L"[ERROR] "); 190 | vfwprintf(stderr, format, argptr); 191 | fwprintf(stdout, L"[ERROR] "); 192 | vfwprintf(stdout, format, argptr); 193 | 194 | va_end(argptr); 195 | } 196 | 197 | 198 | std::string replace_string(std::string str, const string& from, const string& to) 199 | { 200 | size_t start_pos = 0; 201 | while ((start_pos = str.find(from, start_pos)) != std::string::npos) { 202 | str.replace(start_pos, from.length(), to); 203 | start_pos += to.length(); // Handles case where 'to' is a substring of 'from' 204 | } 205 | return str; 206 | } 207 | } 208 | 209 | namespace LIEF 210 | { 211 | uint64_t align(uint64_t value, uint64_t align_on) 212 | { 213 | if ((align_on > 0) && (value % align_on) > 0) { 214 | return value + (align_on - (value % align_on)); 215 | } 216 | else { 217 | return value; 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /PE/optional_header.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef OPTIONAL_HEADER_H 4 | #define OPTIONAL_HEADER_H 5 | 6 | #include "common.h" 7 | #include "utils.h" 8 | #include "structures_and_enums.h" 9 | 10 | namespace pe_parser 11 | { 12 | class optional_header_t 13 | { 14 | public: 15 | 16 | optional_header_t(const pe32_optional_header *header); 17 | optional_header_t(const pe64_optional_header *header); 18 | ~optional_header_t() = default; 19 | 20 | // getters 21 | pe32_optional_header optional_header_pe32(); 22 | pe64_optional_header optional_header_pe64(); 23 | PE_TYPE magic(void) const; 24 | uint8_t major_linker_version(void) const; 25 | uint8_t minor_linker_version(void) const; 26 | uint32_t sizeof_code(void) const; 27 | uint32_t sizeof_initialized_data(void) const; 28 | uint32_t sizeof_uninitialized_data(void) const; 29 | uint32_t addressof_entrypoint(void) const; 30 | uint32_t baseof_code(void) const; 31 | uint32_t baseof_data(void) const; 32 | uint64_t imagebase(void) const; 33 | uint32_t section_alignment(void) const; 34 | uint32_t file_alignment(void) const; 35 | uint16_t major_operating_system_version(void) const; 36 | uint16_t minor_operating_system_version(void) const; 37 | uint16_t major_image_version(void) const; 38 | uint16_t minor_image_version(void) const; 39 | uint16_t major_subsystem_version(void) const; 40 | uint16_t minor_subsystem_version(void) const; 41 | uint32_t win32_version_value(void) const; 42 | uint32_t sizeof_image(void) const; 43 | uint32_t sizeof_headers(void) const; 44 | uint32_t checksum(void) const; 45 | SUBSYSTEM subsystem(void) const; 46 | DLL_CHARACTERISTICS dll_characteristics(void) const; 47 | uint64_t sizeof_stack_reserve(void) const; 48 | uint64_t sizeof_stack_commit(void) const; 49 | uint64_t sizeof_heap_reserve(void) const; 50 | uint64_t sizeof_heap_commit(void) const; 51 | uint32_t loader_flags(void) const; 52 | uint32_t numberof_rva_and_size(void) const; 53 | bool has(DLL_CHARACTERISTICS c) const; 54 | // setters 55 | void add(DLL_CHARACTERISTICS c); 56 | void remove(DLL_CHARACTERISTICS c); 57 | 58 | void magic(PE_TYPE magic); 59 | void major_linker_version(uint8_t majorLinkerVersion); 60 | void minor_linker_version(uint8_t minorLinkerVersion); 61 | void sizeof_code(uint32_t sizeOfCode); 62 | void sizeof_initialized_data(uint32_t sizeOfInitializedData); 63 | void sizeof_uninitialized_data(uint32_t sizeOfUninitializedData); 64 | void addressof_entrypoint(uint32_t addressOfEntryPoint); 65 | void baseof_code(uint32_t baseOfCode); 66 | void baseof_data(uint32_t baseOfData); 67 | void imagebase(uint64_t imageBase); 68 | void section_alignment(uint32_t sectionAlignment); 69 | void file_alignment(uint32_t fileAlignment); 70 | void major_operating_system_version(uint16_t majorOperatingSystemVersion); 71 | void minor_operating_system_version(uint16_t minorOperatingSystemVersion); 72 | void major_image_version(uint16_t majorImageVersion); 73 | void minor_image_version(uint16_t minorImageVersion); 74 | void major_subsystem_version(uint16_t majorSubsystemVersion); 75 | void minor_subsystem_version(uint16_t minorSubsystemVersion); 76 | void win32_version_value(uint32_t win32VersionValue); 77 | void sizeof_image(uint32_t sizeOfImage); 78 | void sizeof_headers(uint32_t sizeOfHeaders); 79 | void checksum(uint32_t checkSum); 80 | void subsystem(SUBSYSTEM subsystem); 81 | void dll_characteristics(DLL_CHARACTERISTICS DLLCharacteristics); 82 | void sizeof_stack_reserve(uint64_t sizeOfStackReserve); 83 | void sizeof_stack_commit(uint64_t sizeOfStackCommit); 84 | void sizeof_heap_reserve(uint64_t sizeOfHeapReserve); 85 | void sizeof_heap_commit(uint64_t sizeOfHeapCommit); 86 | void loader_flags(uint32_t loaderFlags); 87 | void numberof_rva_and_size(uint32_t numberOfRvaAndSize); 88 | 89 | bool is_64_bit_binary(); 90 | bool dump_optional_image(FILE *output_file); 91 | size_t get_optional_header_size(); 92 | private: 93 | 94 | PE_TYPE magic_; 95 | uint8_t majorLinkerVersion_; 96 | uint8_t minorLinkerVersion_; 97 | uint32_t sizeOfCode_; 98 | uint32_t sizeOfInitializedData_; 99 | uint32_t sizeOfUninitializedData_; 100 | uint32_t addressOfEntryPoint_; // RVA 101 | uint32_t baseOfCode_; // RVA 102 | uint32_t baseOfData_; //Not present in PE32+ 103 | uint64_t imageBase_; 104 | uint32_t sectionAlignment_; 105 | uint32_t fileAlignment_; 106 | uint16_t majorOperatingSystemVersion_; 107 | uint16_t minorOperatingSystemVersion_; 108 | uint16_t majorImageVersion_; 109 | uint16_t minorImageVersion_; 110 | uint16_t majorSubsystemVersion_; 111 | uint16_t minorSubsystemVersion_; 112 | uint32_t win32VersionValue_; 113 | uint32_t sizeOfImage_; 114 | uint32_t sizeOfHeaders_; 115 | uint32_t checkSum_; 116 | SUBSYSTEM subsystem_; 117 | DLL_CHARACTERISTICS DLLCharacteristics_; 118 | uint64_t sizeOfStackReserve_; 119 | uint64_t sizeOfStackCommit_; 120 | uint64_t sizeOfHeapReserve_; 121 | uint64_t sizeOfHeapCommit_; 122 | uint32_t loaderFlags_; 123 | uint32_t numberOfRvaAndSize_; 124 | 125 | 126 | bool optional_header_correct; 127 | bool is_64_bit; 128 | }; 129 | } 130 | 131 | #endif // !OPTIONAL_HEADER_H 132 | -------------------------------------------------------------------------------- /unpacker.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile: make PIN_ROOT="" 3 | */ 4 | #include "unpacker.h" 5 | 6 | 7 | 8 | FILE* logfile; // log file handler 9 | binary_t* pe_file; 10 | uint64_t tick_counts_per_millisecond = 0; // more or less ticks per millisecond 11 | proc_info_t* proc_info = proc_info_t::get_instance(); 12 | std::string unpacked_file_name; 13 | std::string import_section_name; 14 | /* 15 | * KNOB class to create arguments with PIN 16 | * on this case, we will create an argument 17 | * string for the user if wants to save 18 | * logs in a file. 19 | */ 20 | KNOB KnobLogFile( 21 | KNOB_MODE_WRITEONCE, 22 | "pintool", 23 | "l", // command accepted (-l) 24 | "unpacker.log", // value of the command, log file name 25 | "log file" 26 | ); 27 | /* 28 | * argument to activate the Debug mode 29 | */ 30 | KNOB KnobDebugFile( 31 | KNOB_MODE_WRITEONCE, 32 | "pintool", 33 | "d", // command accepted (-d) 34 | "false", 35 | "start debug mode" 36 | ); 37 | /* 38 | * argument for giving a name to the 39 | * output unpacked file 40 | */ 41 | KNOB KnobUnpackedFileName( 42 | KNOB_MODE_WRITEONCE, 43 | "pintool", 44 | "n", // command accepted (-n) 45 | "", 46 | "unpacked file name" 47 | ); 48 | /* 49 | * argument for giving a name to the 50 | * import section 51 | */ 52 | KNOB KnobImportSectionName( 53 | KNOB_MODE_WRITEONCE, 54 | "pintool", 55 | "i", // command accepted (-i) 56 | ".F9", // default value 57 | "import section name" 58 | ); 59 | 60 | 61 | /* 62 | * PIN Exception handler function 63 | */ 64 | EXCEPT_HANDLING_RESULT ExceptionHandler(THREADID tid, EXCEPTION_INFO *pExceptInfo, PHYSICAL_CONTEXT *pPhysCtxt, VOID *v) 65 | { 66 | EXCEPTION_CODE c = PIN_GetExceptionCode(pExceptInfo); 67 | EXCEPTION_CLASS cl = PIN_GetExceptionClass(c); 68 | 69 | ANBU::LOGGER_ERROR(logfile, "Exception class: 0x%x\n", (unsigned int)cl); 70 | ANBU::LOGGER_ERROR(logfile, "Exception string: %s\n", PIN_ExceptionToString(pExceptInfo).c_str()); 71 | 72 | return EHR_CONTINUE_SEARCH; 73 | } 74 | 75 | int main(int argc, char *argv[]) 76 | { 77 | WINDOWS::DWORD tick_count1, tick_count2; 78 | 79 | /* 80 | * As we will use symbols... 81 | */ 82 | PIN_InitSymbols(); 83 | /* 84 | * Function to initialize the Pintool 85 | * always called before almost any other PIN 86 | * function (only PIN_InitSymbols can be before) 87 | */ 88 | if (PIN_Init(argc, argv)) 89 | { 90 | usage(); 91 | return 1; 92 | } 93 | 94 | if (strcmp(KnobDebugFile.Value().c_str(), "true") == 0) 95 | { 96 | DEBUG_MODE debug; 97 | debug._type = DEBUG_CONNECTION_TYPE_TCP_SERVER; 98 | debug._options = DEBUG_MODE_OPTION_STOP_AT_ENTRY; 99 | PIN_SetDebugMode(&debug); 100 | } 101 | 102 | // open log file to append 103 | ANBU::LOGGER_INFO("File name: %s\n", KnobLogFile.Value().c_str()); 104 | logfile = fopen(KnobLogFile.Value().c_str(), "w"); 105 | if (!logfile) 106 | { 107 | ANBU::LOGGER_ERROR("Failed to open '%s'\n", KnobLogFile.Value().c_str()); 108 | return 1; 109 | } 110 | 111 | // name for unpacked file 112 | unpacked_file_name = KnobUnpackedFileName.Value(); 113 | 114 | // import section name 115 | import_section_name = KnobImportSectionName.Value(); 116 | 117 | if (import_section_name.size() > 8) 118 | { 119 | ANBU::LOGGER_ERROR("Name cannot be greater than 8 characters"); 120 | return -1; 121 | } 122 | 123 | PIN_AddInternalExceptionHandler(ExceptionHandler, NULL); 124 | 125 | ANBU::LOGGER(logfile,"+--<<< ANBU by F9 >>>>--+\n"); 126 | ANBU::LOGGER(logfile, "------ unpacking binary ------\n"); 127 | 128 | enum_syscalls(); 129 | 130 | init_common_syscalls(); 131 | 132 | syscall_t sc[256] = { 0 }; 133 | /* 134 | * Add instrumentation function for Syscalls entry and exit 135 | */ 136 | PIN_AddSyscallEntryFunction(&syscall_entry, &sc); 137 | PIN_AddSyscallExitFunction(&syscall_exit, &sc); 138 | 139 | 140 | /* 141 | * Add instrumentation function at Instruction tracer level 142 | * in opposite to TRACE instrumentation, this goes to an 143 | * instruction granularity. 144 | */ 145 | INS_AddInstrumentFunction(instrument_mem_cflow, NULL); 146 | 147 | /* 148 | * Add instrumentation for IMG loading. 149 | */ 150 | IMG_AddInstrumentFunction(get_addresses_from_images, NULL); 151 | 152 | /* 153 | * Add instrumentation for anti-anti-stuff. 154 | */ 155 | tick_count1 = WINDOWS::GetTickCount(); 156 | WINDOWS::Sleep(1); 157 | tick_count2 = WINDOWS::GetTickCount(); 158 | tick_counts_per_millisecond = tick_count2 - tick_count1; 159 | IMG_AddInstrumentFunction(hook_functions, NULL); 160 | INS_AddInstrumentFunction(hook_instructions, NULL); 161 | 162 | proc_info->add_proc_addresses(); 163 | /* 164 | * RUN the program and never return 165 | */ 166 | PIN_StartProgram(); 167 | 168 | return 1; 169 | } 170 | 171 | 172 | void usage() 173 | { 174 | ANBU::LOGGER_ERROR("Parameters error, please check next help line(s)\n"); 175 | ANBU::LOGGER("pin -t [-l ] -- application\n"); 176 | ANBU::LOGGER("Commands: \n"); 177 | ANBU::LOGGER("\t+ -t (MANDATORY): necessary flag for PIN to specify a pintool\n"); 178 | ANBU::LOGGER("\t+ -l (OPTIONAL): specify name for a log file\n"); 179 | ANBU::LOGGER("\t+ -d true (OPTIONAL): start debug mode\n"); 180 | ANBU::LOGGER("\t+ -n (OPTIONAL): name for unpacked file\n"); 181 | ANBU::LOGGER("\n"); 182 | } -------------------------------------------------------------------------------- /PE/nt_header.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "nt_header.h" 3 | 4 | namespace pe_parser 5 | { 6 | nt_header_t::nt_header_t(pe_header * header) : 7 | signature_(header->signature), 8 | machine_(static_cast(header->Machine)), 9 | numberOfSections_(header->NumberOfSections), 10 | timeDateStamp_(header->TimeDateStamp), 11 | pointerToSymbolTable_(header->PointerToSymbolTable), 12 | numberOfSymbols_(header->NumberOfSymbols), 13 | sizeOfOptionalHeader_(header->SizeOfOptionalHeader), 14 | characteristics_(static_cast(header->Characteristics)) 15 | 16 | { 17 | if (signature_ != correct_pe_signature_k) 18 | pe_header_correct = false; 19 | } 20 | 21 | bool nt_header_t::is_pe_header_correct() 22 | { 23 | return pe_header_correct; 24 | } 25 | 26 | bool nt_header_t::has_characteristic(HEADER_CHARACTERISTICS c) const { 27 | return (this->characteristics_ & c) != HEADER_CHARACTERISTICS::IMAGE_FILE_INVALID_k; 28 | } 29 | 30 | /******** GETTERS *********/ 31 | pe_header nt_header_t::nt_header(void) const 32 | { 33 | /* 34 | * This part corresponds to LIEF builder: 35 | Builder& Builder::operator<<(const Header& bHeader) { 36 | VLOG(VDEBUG) << "Building standard Header" << std::endl; 37 | // Standard Header 38 | pe_header header; 39 | header.Machine = static_cast(bHeader.machine()); 40 | header.NumberOfSections = static_cast(this->sections_.size()); 41 | //TODO: use current 42 | header.TimeDateStamp = static_cast(bHeader.time_date_stamp()); 43 | header.PointerToSymbolTable = static_cast(bHeader.pointerto_symbol_table()); 44 | header.NumberOfSymbols = static_cast(bHeader.numberof_symbols()); 45 | //TODO: Check 46 | header.SizeOfOptionalHeader = static_cast(bHeader.sizeof_optional_header()); 47 | header.Characteristics = static_cast(bHeader.characteristics()); 48 | 49 | const Header::signature_t& signature = this->header_.signature(); 50 | std::copy(std::begin(signature), std::end(signature), std::begin(header.signature)); 51 | 52 | const uint32_t address_next_header = this->dos_header().addressof_new_exeheader(); 53 | 54 | this->ios_.seekp(address_next_header); 55 | this->ios_.write(reinterpret_cast(&header), sizeof(pe_header)); 56 | return *this; 57 | } 58 | */ 59 | pe_header nt_header; 60 | 61 | nt_header.signature = this->signature_; 62 | nt_header.Machine = this->machine_; 63 | nt_header.NumberOfSections = this->numberOfSections_; 64 | nt_header.TimeDateStamp = this->timeDateStamp_; 65 | nt_header.PointerToSymbolTable = this->pointerToSymbolTable_; 66 | nt_header.NumberOfSymbols = this->numberOfSymbols_; 67 | nt_header.SizeOfOptionalHeader = this->sizeOfOptionalHeader_; 68 | nt_header.Characteristics = this->characteristics_; 69 | 70 | return nt_header; 71 | } 72 | 73 | 74 | const uint32_t nt_header_t::signature(void) const 75 | { 76 | return this->signature_; 77 | } 78 | 79 | 80 | MACHINE_TYPES nt_header_t::machine(void) const 81 | { 82 | return this->machine_; 83 | } 84 | 85 | 86 | uint16_t nt_header_t::numberof_sections(void) const 87 | { 88 | return this->numberOfSections_; 89 | } 90 | 91 | 92 | uint32_t nt_header_t::time_date_stamp(void) const 93 | { 94 | return this->timeDateStamp_; 95 | } 96 | 97 | 98 | uint32_t nt_header_t::pointerto_symbol_table(void) const 99 | { 100 | return this->pointerToSymbolTable_; 101 | } 102 | 103 | 104 | uint32_t nt_header_t::numberof_symbols(void) const 105 | { 106 | return this->numberOfSymbols_; 107 | } 108 | 109 | 110 | uint16_t nt_header_t::sizeof_optional_header(void) const 111 | { 112 | return this->sizeOfOptionalHeader_; 113 | } 114 | 115 | 116 | HEADER_CHARACTERISTICS nt_header_t::characteristics(void) const 117 | { 118 | return this->characteristics_; 119 | } 120 | /******** SETTERS *********/ 121 | void nt_header_t::machine(MACHINE_TYPES type) 122 | { 123 | this->machine_ = type; 124 | } 125 | 126 | 127 | void nt_header_t::numberof_sections(uint16_t nbOfSections) 128 | { 129 | this->numberOfSections_ = nbOfSections; 130 | } 131 | 132 | 133 | void nt_header_t::time_date_stamp(uint32_t timestamp) 134 | { 135 | this->timeDateStamp_ = timestamp; 136 | } 137 | 138 | 139 | void nt_header_t::pointerto_symbol_table(uint32_t pointerToSymbol) 140 | { 141 | this->pointerToSymbolTable_ = pointerToSymbol; 142 | } 143 | 144 | 145 | void nt_header_t::numberof_symbols(uint32_t nbOfSymbols) 146 | { 147 | this->numberOfSymbols_ = nbOfSymbols; 148 | } 149 | 150 | 151 | void nt_header_t::sizeof_optional_header(uint16_t sizeOfOptionalHdr) 152 | { 153 | this->sizeOfOptionalHeader_ = sizeOfOptionalHdr; 154 | } 155 | 156 | 157 | void nt_header_t::characteristics(HEADER_CHARACTERISTICS characteristics) 158 | { 159 | this->characteristics_ = characteristics; 160 | } 161 | 162 | 163 | void nt_header_t::signature(const uint32_t sig) 164 | { 165 | this->signature_ = sig; 166 | } 167 | 168 | 169 | bool nt_header_t::dump_nt_header(FILE *file_to_dump) 170 | { 171 | if (!pe_header_correct) 172 | return false; 173 | ANBU::LOGGER(file_to_dump, "================== DUMP NT HEADER ===================\n"); 174 | ANBU::LOGGER(file_to_dump, "\t+Signature: 0x%x\n", signature_); 175 | ANBU::LOGGER(file_to_dump, "\t+Machine: 0x%x\n", machine_); 176 | ANBU::LOGGER(file_to_dump, "\t+Number Of Sections: 0x%x\n", numberOfSections_); 177 | ANBU::LOGGER(file_to_dump, "\t+TimeDateStamp: 0x%x\n", timeDateStamp_); 178 | ANBU::LOGGER(file_to_dump, "\t+Pointer to Symbol Table: 0x%x\n", pointerToSymbolTable_); 179 | ANBU::LOGGER(file_to_dump, "\t+Number of symbols: 0x%x\n", numberOfSymbols_); 180 | ANBU::LOGGER(file_to_dump, "\t+Size of optional header: 0x%x\n", sizeOfOptionalHeader_); 181 | ANBU::LOGGER(file_to_dump, "\t+Characteristics: 0x%x\n", characteristics_); 182 | 183 | return true; 184 | } 185 | } -------------------------------------------------------------------------------- /PE/proc_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef PROC_INFO_H 3 | #define PROC_INFO_H 4 | 5 | #include "common.h" 6 | #include "utils.h" 7 | 8 | 9 | #define MAX_STACK_SIZE 0x100000 10 | #define TEB_SIZE 0xFE0 11 | #define KUSER_SHARED_DATA_ADDRESS 0x7FFE0000 12 | #define KUSER_SHARED_DATA_SIZE 0x3E0 13 | 14 | 15 | typedef struct PEB { 16 | WINDOWS::BYTE padding1[2]; 17 | WINDOWS::BYTE BeingDebugged; 18 | WINDOWS::BYTE padding2[53]; 19 | WINDOWS::PVOID ApiSetMap; 20 | WINDOWS::BYTE padding3[16]; 21 | WINDOWS::PVOID ReadOnlySharedMemoryBase; 22 | WINDOWS::BYTE padding4[8]; 23 | WINDOWS::PVOID AnsiCodePageData; 24 | WINDOWS::BYTE padding5[52]; 25 | WINDOWS::PVOID ProcessHeaps; 26 | WINDOWS::PVOID GdiSharedHandleTable; 27 | WINDOWS::BYTE padding6[336]; 28 | WINDOWS::PVOID pShimData; 29 | WINDOWS::BYTE padding7[12]; 30 | WINDOWS::PVOID ActivationContextData; 31 | WINDOWS::BYTE padding8[4]; 32 | WINDOWS::PVOID SystemDefaultActivationContextData; 33 | WINDOWS::BYTE padding9[52]; 34 | WINDOWS::PVOID pContextData; 35 | WINDOWS::BYTE padding10[4]; 36 | }PEB; 37 | 38 | 39 | struct memory_range_t 40 | { 41 | ADDRINT start_address; 42 | ADDRINT end_address; 43 | }; 44 | 45 | 46 | // Struct that will track library loaded at program startup 47 | struct library_item_t 48 | { 49 | ADDRINT start_address; 50 | ADDRINT end_address; 51 | std::string name; 52 | }; 53 | 54 | 55 | struct heap_zone_t 56 | { 57 | ADDRINT begin; 58 | ADDRINT end; 59 | uint32_t size; 60 | uint32_t version; 61 | }; 62 | 63 | 64 | class proc_info_t 65 | { 66 | public: 67 | 68 | proc_info_t(); 69 | ~proc_info_t(); 70 | 71 | // singleton 72 | static proc_info_t* get_instance(); 73 | 74 | // Setters 75 | void add_proc_addresses(); 76 | void first_instruction(ADDRINT first_instruction); 77 | void prev_ip(ADDRINT prev_ip); 78 | void main_img_address(ADDRINT start_address, ADDRINT end_addr); 79 | void proc_name(std::string name); 80 | 81 | // Getters 82 | ADDRINT first_instruction(); 83 | ADDRINT prev_ip(); 84 | std::string proc_name(); 85 | std::vector get_jmp_black_list(); 86 | ADDRINT get_pin_vm_start(); 87 | ADDRINT get_pin_vm_end(); 88 | std::map get_heap_map(); 89 | std::map get_dumped_hz(); 90 | 91 | // debug 92 | void print_start_context(); 93 | void print_curr_context(); 94 | void print_heap_list(); 95 | 96 | // helper 97 | void insert_heap_zone(std::string hz_data_md5, heap_zone_t heap_zone); 98 | void insert_dumped_heap_zone(std::string hz_data_md5, std::string hz_bin_path); 99 | void delete_heap_zone(std::string md5_to_remove); 100 | bool search_heap_map(ADDRINT ip); 101 | heap_zone_t* get_heap_zone_by_index(size_t index); 102 | std::vector get_while_list_heap(); 103 | void insert_in_jmp_black_list(ADDRINT ip); 104 | bool is_inside_jmp_black_list(ADDRINT ip); 105 | 106 | //Whitelisted memory (functions for FakeMemoryReader) 107 | //PEB 108 | void print_peb_information(); 109 | bool is_peb_address(ADDRINT addr); 110 | void process_not_being_debugged(); 111 | //TEB 112 | bool is_teb_address(ADDRINT addr); 113 | void add_thread_teb_address(); 114 | //Stack 115 | bool is_stack_address(ADDRINT addr); 116 | void add_thread_stack_address(ADDRINT addr); 117 | //Library 118 | bool is_library_instruction(ADDRINT addr); 119 | bool is_known_library_instruction(ADDRINT addr); 120 | void add_library(const string name, ADDRINT start_addr, ADDRINT end_addr); 121 | bool is_lib_item_duplicate(uint32_t address, std::vector libraries); 122 | 123 | bool get_memory_range(ADDRINT address, memory_range_t& range); 124 | bool add_process_heap_and_check_address(ADDRINT address); 125 | 126 | //Memory mapped files 127 | bool is_mapped_file_address(ADDRINT addr); 128 | void add_mapped_files_address(ADDRINT start_addr); 129 | void set_current_mapped_files(); 130 | void print_mapped_file_address(); 131 | 132 | //Generic Address 133 | bool is_generic_memory_address(ADDRINT address); 134 | void print_white_listed_addr(); 135 | 136 | //Process Fingerprint 137 | bool is_interesting_process(unsigned int pin); 138 | private: 139 | static proc_info_t* instance; 140 | ADDRINT first_instruction_; 141 | ADDRINT prev_ip_; 142 | std::vector interesting_processes_name; 143 | std::vector interesting_processes_pid; 144 | std::vector stacks; // Set of Stack 145 | memory_range_t main_img; 146 | std::vector tebs; 147 | std::vector generic_memory_ranges; 148 | std::vector mapped_files; 149 | PEB* peb; 150 | std::map heap_map; 151 | std::vector white_list_heap; 152 | std::map heap_map_dumped; 153 | std::vector addr_jmp_blacklist; 154 | std::vector known_libraries; 155 | std::vector unknown_libraries; 156 | 157 | std::string full_proc_name_; 158 | std::string proc_name_; 159 | // Enumerate whitelisted memory helpers 160 | // return the memory_range_t in which the address is mapped 161 | bool is_known_library(const std::string name, ADDRINT start_addr, ADDRINT end_addr); 162 | void add_peb_address(); 163 | void add_context_data_address(); 164 | void add_shared_memory_address(); 165 | void add_code_page_data_address(); 166 | void add_pshim_data_address(); 167 | void add_api_set_map_address(); 168 | void add_kuser_shared_data_address(); 169 | // Library Helpers 170 | std::string lib_to_string(library_item_t lib); 171 | }; 172 | 173 | #endif // !PROC_INFO_H 174 | -------------------------------------------------------------------------------- /PE/import.cpp: -------------------------------------------------------------------------------- 1 | #include "import.h" 2 | 3 | lief_import_t::~lief_import_t(void) = default; 4 | 5 | 6 | lief_import_t::lief_import_t(const lief_import_t& other) : 7 | entries_{ other.entries_ }, 8 | directory_{ nullptr }, 9 | iat_directory_{ nullptr }, 10 | import_lookup_table_RVA_{ other.import_lookup_table_RVA_ }, 11 | timedatestamp_{ other.timedatestamp_ }, 12 | forwarder_chain_{ other.forwarder_chain_ }, 13 | name_RVA_{ other.name_RVA_ }, 14 | import_address_table_RVA_{ other.import_address_table_RVA_ }, 15 | name_{ other.name_ }, 16 | type_{ other.type_ } 17 | {} 18 | 19 | lief_import_t& lief_import_t::operator=(lief_import_t other) 20 | { 21 | this->swap(other); 22 | return *this; 23 | } 24 | 25 | void lief_import_t::swap(lief_import_t& other) 26 | { 27 | std::swap(this->entries_, other.entries_); 28 | std::swap(this->directory_, other.directory_); 29 | std::swap(this->iat_directory_, other.iat_directory_); 30 | std::swap(this->import_lookup_table_RVA_, other.import_lookup_table_RVA_); 31 | std::swap(this->timedatestamp_, other.timedatestamp_); 32 | std::swap(this->forwarder_chain_, other.forwarder_chain_); 33 | std::swap(this->name_RVA_, other.name_RVA_); 34 | std::swap(this->import_address_table_RVA_, other.import_address_table_RVA_); 35 | std::swap(this->name_, other.name_); 36 | std::swap(this->type_, other.type_); 37 | } 38 | 39 | 40 | lief_import_t::lief_import_t(void) : 41 | entries_{}, 42 | directory_{ nullptr }, 43 | iat_directory_{ nullptr }, 44 | import_lookup_table_RVA_{ 0 }, 45 | timedatestamp_{ 0 }, 46 | forwarder_chain_{ 0 }, 47 | name_RVA_{ 0 }, 48 | import_address_table_RVA_{ 0 }, 49 | name_{ "" }, 50 | type_{ PE_TYPE::pe32_k } // Arbitrary value 51 | {} 52 | 53 | 54 | lief_import_t::lief_import_t(const pe_import *import) : 55 | entries_{}, 56 | directory_{ nullptr }, 57 | iat_directory_{ nullptr }, 58 | import_lookup_table_RVA_(import->ImportLookupTableRVA), 59 | timedatestamp_(import->TimeDateStamp), 60 | forwarder_chain_(import->ForwarderChain), 61 | name_RVA_(import->NameRVA), 62 | import_address_table_RVA_(import->ImportAddressTableRVA), 63 | name_{ "" }, 64 | type_{ PE_TYPE::pe32_k } // Arbitrary value 65 | {} 66 | 67 | lief_import_t::lief_import_t(const std::string& name) : 68 | entries_{}, 69 | directory_{ nullptr }, 70 | iat_directory_{ nullptr }, 71 | import_lookup_table_RVA_{ 0 }, 72 | timedatestamp_{ 0 }, 73 | forwarder_chain_{ 0 }, 74 | name_RVA_{ 0 }, 75 | name_{ name }, 76 | type_{ PE_TYPE::pe32_k } // Arbitrary value 77 | {} 78 | 79 | const import_entry_t* lief_import_t::get_entry(const std::string& name) const 80 | { 81 | for (size_t i = 0; i < this->entries_.size(); i++) 82 | { 83 | if (this->entries_.at(i).name() == name) 84 | { 85 | return &entries_.at(i); 86 | } 87 | } 88 | 89 | ANBU::LOGGER_ERROR("Unable to find entry '%s'\n", name.c_str()); 90 | return nullptr; 91 | } 92 | 93 | 94 | import_entry_t* lief_import_t::get_entry(const std::string& name) 95 | { 96 | return const_cast(static_cast(this)->get_entry(name)); 97 | } 98 | 99 | 100 | std::vector lief_import_t::entries(void) 101 | { 102 | return this->entries_; 103 | } 104 | 105 | 106 | void lief_import_t::entries(std::vector entries) 107 | { 108 | this->entries_ = entries; 109 | } 110 | 111 | 112 | uint32_t lief_import_t::import_address_table_rva(void) const 113 | { 114 | return this->import_address_table_RVA_; 115 | } 116 | 117 | 118 | uint32_t lief_import_t::import_lookup_table_rva(void) const 119 | { 120 | return this->import_lookup_table_RVA_; 121 | } 122 | 123 | 124 | uint32_t lief_import_t::get_function_rva_from_iat(const std::string& function) const 125 | { 126 | int64_t idx = -1; 127 | 128 | for (size_t i = 0; this->entries_.size(); i++) 129 | { 130 | if (this->entries_.at(i).name() == function) 131 | { 132 | idx = static_cast(i); 133 | break; 134 | } 135 | } 136 | 137 | if (idx == -1) 138 | { 139 | ANBU::LOGGER_ERROR("Function not found\n"); 140 | return -1; 141 | } 142 | 143 | if (this->type_ == PE_TYPE::pe32_k) 144 | return static_cast(idx * sizeof(uint32_t)); 145 | else 146 | return static_cast(idx * sizeof(uint64_t)); 147 | } 148 | 149 | 150 | const std::string& lief_import_t::name(void) const 151 | { 152 | return this->name_; 153 | } 154 | 155 | 156 | void lief_import_t::name(const std::string& name) 157 | { 158 | this->name_ = name; 159 | } 160 | 161 | 162 | const pe_parser::data_directory_header_t* lief_import_t::directory(void) const 163 | { 164 | if (this->directory_ != nullptr) 165 | return this->directory_; 166 | else 167 | return nullptr; 168 | } 169 | 170 | 171 | pe_parser::data_directory_header_t* lief_import_t::directory(void) 172 | { 173 | return const_cast(static_cast(this)->directory()); 174 | } 175 | 176 | 177 | const pe_parser::data_directory_header_t* lief_import_t::iat_directory(void) const 178 | { 179 | if (this->iat_directory_ != nullptr) 180 | return this->iat_directory_; 181 | else 182 | return nullptr; 183 | } 184 | 185 | 186 | pe_parser::data_directory_header_t* lief_import_t::iat_directory(void) 187 | { 188 | return const_cast(static_cast(this)->iat_directory()); 189 | } 190 | 191 | 192 | void lief_import_t::import_lookup_table_rva(uint32_t rva) 193 | { 194 | this->import_lookup_table_RVA_ = rva; 195 | } 196 | 197 | 198 | void lief_import_t::import_address_table_rva(uint32_t rva) 199 | { 200 | this->import_address_table_RVA_ = rva; 201 | } 202 | 203 | 204 | import_entry_t& lief_import_t::add_entry(const import_entry_t& entry) 205 | { 206 | this->entries_.push_back(entry); 207 | return this->entries_.back(); 208 | } 209 | 210 | 211 | import_entry_t& lief_import_t::add_entry(const std::string& name) { 212 | this->entries_.push_back(import_entry_t(name)); 213 | return this->entries_.back(); 214 | } 215 | 216 | 217 | uint32_t lief_import_t::forwarder_chain(void) const 218 | { 219 | return this->forwarder_chain_; 220 | } 221 | 222 | 223 | uint32_t lief_import_t::timedatestamp(void) const 224 | { 225 | return this->timedatestamp_; 226 | } 227 | 228 | 229 | bool lief_import_t::dump_import(FILE *output_file) 230 | { 231 | ANBU::LOGGER(output_file, "%s\n", this->name_.c_str()); 232 | ANBU::LOGGER(output_file, "%s\n", this->import_lookup_table_RVA_); 233 | ANBU::LOGGER(output_file, "%x\n", this->import_address_table_RVA_); 234 | ANBU::LOGGER(output_file, "%x\n", this->forwarder_chain_); 235 | ANBU::LOGGER(output_file, "%x\n", this->timedatestamp_); 236 | 237 | for (size_t i = 0; i < this->entries_.size(); i++) 238 | this->entries_.at(i).dump_import_entry(output_file); 239 | 240 | return true; 241 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | 332 | # Examples (not to upload) 333 | examples/ -------------------------------------------------------------------------------- /PE/binary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef PE_FILE_H 4 | #define PE_FILE_H 5 | 6 | #include "common.h" 7 | #include "dos_header.h" 8 | #include "nt_header.h" 9 | #include "optional_header.h" 10 | #include "data_directory_header.h" 11 | #include "section_header.h" 12 | 13 | 14 | #include "import.h" 15 | #include "import_entry.h" 16 | #include "utils.h" 17 | 18 | 19 | class binary_t 20 | { 21 | public: 22 | binary_t(std::vector* buffer); 23 | binary_t(ADDRINT binary_address); 24 | binary_t(IMG binary_img); 25 | ~binary_t(); 26 | 27 | //! @brief Return `PE32` or `PE32+` 28 | PE_TYPE type(void) const; 29 | bool parse(void); 30 | bool analyze_binary(void); 31 | bool has_section_changed_entropy(ADDRINT address_of_section); 32 | bool on_pe_file(ADDRINT address); 33 | 34 | //! @brief Convert Relative Virtual Address to offset 35 | //! 36 | //! We try to get the get section wich hold the given 37 | //! `RVA` and convert it to offset. If the section 38 | //! does not exist, we assume that `RVA` = `offset` 39 | uint64_t rva_to_offset(uint64_t RVA); 40 | 41 | //! @brief Convert Virtual address to offset 42 | uint64_t va_to_offset(uint64_t VA); 43 | 44 | 45 | //! @brief Find the section associated with the `offset` 46 | pe_parser::section_header_t* section_from_offset(uint64_t offset); 47 | 48 | //! @brief Find the section associated with the `virtual address` 49 | pe_parser::section_header_t* section_from_rva(uint64_t virtual_address); 50 | 51 | 52 | // getters 53 | pe_parser::dos_header_t* dos_header(void); 54 | uint8_t* dos_stub(void); 55 | pe_parser::nt_header_t* nt_coff_header(void); 56 | pe_parser::optional_header_t* optional_header(void); 57 | 58 | bool has(DATA_DIRECTORY index); 59 | uint64_t realign_pe(); 60 | 61 | //! @brief Compute the size of all headers 62 | uint32_t sizeof_headers(void) const; 63 | 64 | //! @brief Compute the binary's virtual size. 65 | //! It should match with OptionalHeader::sizeof_image 66 | uint64_t virtual_size(void) const; 67 | 68 | // ========================== 69 | // Methods to manage data directories 70 | // ========================== 71 | std::vector data_directory(void); 72 | 73 | pe_parser::data_directory_header_t* data_directory(DATA_DIRECTORY index); 74 | 75 | void data_directory(std::vector data_directory_header); 76 | 77 | // ========================== 78 | // Methods to manage sections 79 | // ========================== 80 | std::vector section_table_header(void); 81 | 82 | void section_table_header(std::vector sections); 83 | //! @brief Return binary's section from its name 84 | //! 85 | //! @param[in] name Name of the Section 86 | pe_parser::section_header_t* get_section( std::string& name) ; 87 | 88 | //! @brief Return the section associated with import table 89 | pe_parser::section_header_t* import_section(void) ; 90 | 91 | //! @brief Delete the section with the given name 92 | //! 93 | //! @param[in] name Name of section to delete 94 | void remove_section(std::string& name); 95 | 96 | //! Remove the given section 97 | void remove(pe_parser::section_header_t* section); 98 | 99 | //! @brief Add a section to the binary and return the section added. 100 | pe_parser::section_header_t* add_section(pe_parser::section_header_t* section); 101 | 102 | //! @brief Make space between the last section header and the beginning of the 103 | //! content of first section 104 | void make_space_for_new_section(void); 105 | 106 | 107 | // ========================= 108 | // Methods to manage Imports 109 | // ========================= 110 | bool has_imports(void) const; 111 | 112 | //! @brief return binary's @link PE::Import imports @endlink 113 | std::vector imports(void); 114 | void imports(std::vector imports); 115 | 116 | //! @brief Returns the PE::Import from the given name 117 | //! 118 | //! @param[in] import_name Name of the import 119 | lief_import_t* get_import(const std::string& import_name); 120 | const lief_import_t* get_import(const std::string& import_name) const; 121 | 122 | //! @brief ``True`` if the binary import the given library name 123 | //! 124 | //! @param[in] import_name Name of the import 125 | bool has_import(const std::string& import_name) const; 126 | 127 | //! @brief Add the function @p function of the library @p library 128 | //! 129 | //! @param[in] library library name of the function 130 | //! @param[in] function function's name from the library to import 131 | import_entry_t* add_import_function(const std::string& library, const std::string& function); 132 | 133 | //! @brief add an imported library (i.e. `DLL`) to the binary 134 | lief_import_t* add_library(const std::string& name); 135 | 136 | //! @brief Remove the library with the given `name` 137 | void remove_library(const std::string& name); 138 | 139 | //! @brief Remove all libraries in the binary 140 | void remove_all_libraries(void); 141 | 142 | //! @brief Try to predict the RVA of the function `function` in the import library `library` 143 | //! 144 | //! @warning 145 | //! The value could be chang if imports change 146 | //! 147 | //! @note 148 | //! It should be used with: 149 | //! LIEF::PE::Builder::build_imports set to ``true`` 150 | //! 151 | //! @param[in] library Library name in which the function is located 152 | //! @param[in] function Function name 153 | //! @return The address of the function (``IAT``) in the new import table 154 | uint32_t predict_function_rva(const std::string& library, const std::string& function); 155 | 156 | 157 | //! @brief Reconstruct the binary object and write it in `filename` 158 | //! 159 | //! Rebuild a PE binary from the current Binary object. 160 | //! When rebuilding, import table and relocations are not rebuilt. 161 | bool write(const std::string& filename, ADDRINT target); 162 | 163 | bool write(const std::string& filename, std::vector file_base_in_vector, std::vector file_data); 164 | private: 165 | float calculate_entropy_section(pe_parser::section_header_t section); 166 | bool calculate_initial_entropy(void); 167 | bool parse_headers(void); 168 | bool parse_dos_stub(void); 169 | bool parse_data_directories(void); 170 | bool parse_sections(void); 171 | bool entropy_higher_than_HE(uint32_t entropy); 172 | bool entropy_lower_than_LE(uint32_t entropy); 173 | 174 | const float entropy_threshold = 10.0; 175 | 176 | PE_TYPE type_; 177 | ADDRINT binary_base_address; 178 | IMG binary_img; 179 | bool binary_is_okay; 180 | bool headers_are_correct; 181 | bool has_imports_; 182 | int32_t available_sections_space_; 183 | 184 | 185 | float* initial_entropies = nullptr; 186 | 187 | 188 | 189 | 190 | pe_parser::dos_header_t* dos_header_ = nullptr; 191 | uint8_t* dos_stub_ = nullptr; 192 | pe_parser::nt_header_t* nt_coff_header_ = nullptr; 193 | pe_parser::optional_header_t* optional_header_ = nullptr; 194 | std::vector data_directory_header_; 195 | std::vector section_table_header_; 196 | std::vector imports_; 197 | }; 198 | 199 | 200 | #endif // !PE_FILE_H 201 | -------------------------------------------------------------------------------- /MyPinTool.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {b8dd2600-7302-4aa7-a99d-1607cd3cd4fb} 14 | txt;doc;html 15 | 16 | 17 | {421eac3f-63e7-4fc9-86c7-bb842b147d6f} 18 | 19 | 20 | {645a29ac-ac0a-4094-bc2a-89d585670d8c} 21 | 22 | 23 | {925e0009-bb38-4404-af38-ca8e7a471cd0} 24 | 25 | 26 | {1b13d684-e6da-4760-9616-74e7087214ca} 27 | 28 | 29 | {299b4aac-6ced-4f65-baa5-4b76bf4cd6f4} 30 | 31 | 32 | {a919ab3a-2f56-4b60-94b5-33accf3d11ef} 33 | 34 | 35 | {345ba0ef-70e5-451c-b935-a63a6afc26bf} 36 | 37 | 38 | {92b119b2-ea87-41b3-8d9b-689b3e3c0e28} 39 | 40 | 41 | {6478e994-26a8-42c8-b255-dce0d43c88b9} 42 | 43 | 44 | {bbc166f3-9fb0-4ce8-8be5-3a59533d15e5} 45 | 46 | 47 | {f25e4a37-8747-4226-9342-d282947d8b66} 48 | 49 | 50 | {a6b7fa07-a68e-45d6-83df-9d4b9aa94b0c} 51 | 52 | 53 | 54 | 55 | Documents 56 | 57 | 58 | Documents 59 | 60 | 61 | Documents 62 | 63 | 64 | 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files\Unpacking 74 | 75 | 76 | Header Files\PE\parser 77 | 78 | 79 | Header Files\Unpacking 80 | 81 | 82 | Header Files\PE\parser 83 | 84 | 85 | Header Files\PE\parser 86 | 87 | 88 | Header Files\PE\parser 89 | 90 | 91 | Header Files\PE\parser 92 | 93 | 94 | Header Files\Unpacking 95 | 96 | 97 | Header Files\anti-anti 98 | 99 | 100 | Header Files\Unpacking\heuristics 101 | 102 | 103 | Header Files\Unpacking\heuristics 104 | 105 | 106 | Header Files\PE 107 | 108 | 109 | Header Files\PE\fixer 110 | 111 | 112 | Header Files 113 | 114 | 115 | Header Files\PE\fixer 116 | 117 | 118 | Header Files\PE\fixer 119 | 120 | 121 | Header Files\PE 122 | 123 | 124 | Header Files\PE 125 | 126 | 127 | Header Files 128 | 129 | 130 | 131 | 132 | Source Files 133 | 134 | 135 | Source Files\Unpacking 136 | 137 | 138 | Source Files\PE\parser 139 | 140 | 141 | Source Files\Unpacking 142 | 143 | 144 | Source Files\PE\parser 145 | 146 | 147 | Source Files\PE\parser 148 | 149 | 150 | Source Files\PE\parser 151 | 152 | 153 | Source Files\PE\parser 154 | 155 | 156 | Source Files\Unpacking 157 | 158 | 159 | Source Files\anti-anti 160 | 161 | 162 | Source Files\Unpacking\heuristics 163 | 164 | 165 | Source Files\Unpacking\heuristics 166 | 167 | 168 | Source Files\PE 169 | 170 | 171 | Source Files\PE\fixer 172 | 173 | 174 | Source Files 175 | 176 | 177 | Source Files\PE\fixer 178 | 179 | 180 | Source Files\PE\fixer 181 | 182 | 183 | Source Files\PE 184 | 185 | 186 | Source Files 187 | 188 | 189 | -------------------------------------------------------------------------------- /PE/section_header.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "section_header.h" 3 | 4 | /************* EXTERN VARIABLES *************/ 5 | extern FILE *logfile; // log file handler 6 | 7 | 8 | namespace pe_parser 9 | { 10 | section_header_t::section_header_t(const pe_section* header) : 11 | virtualSize_{ header->VirtualSize }, 12 | pointerToRelocations_{ header->PointerToRelocations }, 13 | pointerToLineNumbers_{ header->PointerToLineNumbers }, 14 | numberOfRelocations_{ header->NumberOfRelocations }, 15 | numberOfLineNumbers_{ header->NumberOfLineNumbers }, 16 | characteristics_{ header->Characteristics } 17 | { 18 | this->name_ = std::string(header->Name, sizeof(header->Name)).c_str(); 19 | this->virtual_address_ = header->VirtualAddress; 20 | this->size_ = header->SizeOfRawData; 21 | this->offset_ = header->PointerToRawData; 22 | 23 | } 24 | 25 | section_header_t::section_header_t(const std::vector& data, const pe_section* header) : 26 | virtualSize_{ header->VirtualSize }, 27 | pointerToRelocations_{ header->PointerToRelocations }, 28 | pointerToLineNumbers_{ header->PointerToLineNumbers }, 29 | numberOfRelocations_{ header->NumberOfRelocations }, 30 | numberOfLineNumbers_{ header->NumberOfLineNumbers }, 31 | characteristics_{ header->Characteristics } 32 | { 33 | this->name_ = std::string(header->Name, sizeof(header->Name)).c_str(); 34 | this->virtual_address_ = header->VirtualAddress; 35 | this->size_ = data.size(); 36 | this->offset_ = header->PointerToRawData; 37 | this->content_ = data; 38 | } 39 | 40 | /********* GETTERS ***********/ 41 | pe_section section_header_t::section_header(void) const 42 | { 43 | /* 44 | * This part corresponds to the first part of this function: 45 | Builder& Builder::operator<<(const Section& section) { 46 | 47 | pe_section header; 48 | std::fill( 49 | reinterpret_cast(&header), 50 | reinterpret_cast(&header) + sizeof(pe_section), 51 | 0); 52 | 53 | header.VirtualAddress = static_cast(section.virtual_address()); 54 | header.VirtualSize = static_cast(section.virtual_size()); 55 | header.SizeOfRawData = static_cast(section.size()); 56 | header.PointerToRawData = static_cast(section.pointerto_raw_data()); 57 | header.PointerToRelocations = static_cast(section.pointerto_relocation()); 58 | header.PointerToLineNumbers = static_cast(section.pointerto_line_numbers()); 59 | header.NumberOfRelocations = static_cast(section.numberof_relocations()); 60 | header.NumberOfLineNumbers = static_cast(section.numberof_line_numbers()); 61 | header.Characteristics = static_cast(section.characteristics()); 62 | const char* name = section.name().c_str(); 63 | */ 64 | pe_section section_header; 65 | 66 | strncpy(section_header.Name, this->name_.c_str(), 8); 67 | section_header.VirtualSize = this->virtualSize_; 68 | section_header.VirtualAddress = this->virtual_address_; 69 | section_header.SizeOfRawData = this->size_; 70 | section_header.PointerToRawData = this->offset_; 71 | section_header.PointerToRelocations = this->pointerToRelocations_; 72 | section_header.PointerToLineNumbers = this->pointerToLineNumbers_; 73 | section_header.NumberOfRelocations = this->numberOfRelocations_; 74 | section_header.NumberOfLineNumbers = this->numberOfLineNumbers_; 75 | section_header.Characteristics = static_cast(this->characteristics_); 76 | 77 | return section_header; 78 | } 79 | 80 | 81 | std::vector section_header_t::content(void) const 82 | { 83 | return this->content_; 84 | } 85 | 86 | 87 | std::vector& section_header_t::content_ref(void) 88 | { 89 | return this->content_; 90 | } 91 | 92 | 93 | const char* section_header_t::name(void) const 94 | { 95 | return this->name_.c_str(); 96 | } 97 | 98 | 99 | uint32_t section_header_t::virtual_size(void) const 100 | { 101 | return this->virtualSize_; 102 | } 103 | 104 | 105 | uint32_t section_header_t::virtual_address(void) const 106 | { 107 | return this->virtual_address_; 108 | } 109 | 110 | 111 | uint32_t section_header_t::sizeof_raw_data(void) const 112 | { 113 | return this->size_; 114 | } 115 | 116 | 117 | uint32_t section_header_t::pointerto_raw_data(void) const 118 | { 119 | return this->offset_; 120 | } 121 | 122 | 123 | uint32_t section_header_t::pointerto_relocation(void) const 124 | { 125 | return this->pointerToRelocations_; 126 | } 127 | 128 | 129 | uint32_t section_header_t::pointerto_line_numbers(void) const 130 | { 131 | return this->pointerToLineNumbers_; 132 | } 133 | 134 | 135 | uint16_t section_header_t::numberof_relocations(void) const 136 | { 137 | return this->numberOfRelocations_; 138 | } 139 | 140 | 141 | uint16_t section_header_t::numberof_line_numbers(void) const 142 | { 143 | return this->numberOfLineNumbers_; 144 | } 145 | 146 | 147 | uint32_t section_header_t::characteristics(void) const 148 | { 149 | return this->characteristics_; 150 | } 151 | 152 | 153 | /************ SETTERS *************/ 154 | void section_header_t::content(const std::vector& data) 155 | { 156 | this->content_ = data; 157 | } 158 | 159 | void section_header_t::name(const std::string& name) 160 | { 161 | if (name.size() > NameSize) { 162 | return; 163 | } 164 | this->name_ = name; 165 | } 166 | 167 | void section_header_t::virtual_address(uint32_t virtualAddress) 168 | { 169 | this->virtual_address_ = virtualAddress; 170 | } 171 | 172 | void section_header_t::virtual_size(uint32_t virtualSize) 173 | { 174 | this->virtualSize_ = virtualSize; 175 | } 176 | 177 | 178 | void section_header_t::pointerto_raw_data(uint32_t pointerToRawData) 179 | { 180 | this->offset_ = pointerToRawData; 181 | } 182 | 183 | 184 | void section_header_t::pointerto_relocation(uint32_t pointerToRelocation) 185 | { 186 | this->pointerToRelocations_ = pointerToRelocation; 187 | } 188 | 189 | 190 | void section_header_t::pointerto_line_numbers(uint32_t pointerToLineNumbers) 191 | { 192 | this->pointerToLineNumbers_ = pointerToLineNumbers; 193 | } 194 | 195 | 196 | void section_header_t::numberof_relocations(uint16_t numberOfRelocations) 197 | { 198 | this->numberOfRelocations_ = numberOfRelocations; 199 | } 200 | 201 | 202 | void section_header_t::numberof_line_numbers(uint16_t numberOfLineNumbers) 203 | { 204 | this->numberOfLineNumbers_ = numberOfLineNumbers; 205 | } 206 | 207 | 208 | void section_header_t::sizeof_raw_data(uint32_t sizeOfRawData) 209 | { 210 | this->size_ = sizeOfRawData; 211 | } 212 | 213 | 214 | void section_header_t::characteristics(uint32_t characteristics) 215 | { 216 | this->characteristics_ = characteristics; 217 | } 218 | 219 | 220 | void section_header_t::remove_characteristic(SECTION_CHARACTERISTICS characteristic) 221 | { 222 | this->characteristics_ &= ~static_cast(characteristic); 223 | } 224 | 225 | 226 | void section_header_t::add_characteristic(SECTION_CHARACTERISTICS characteristic) 227 | { 228 | this->characteristics_ |= static_cast(characteristic); 229 | } 230 | 231 | 232 | bool section_header_t::has_characteristic(SECTION_CHARACTERISTICS c) const 233 | { 234 | return (this->characteristics_ & static_cast(c)) > 0; 235 | } 236 | 237 | 238 | bool section_header_t::dump_sections(FILE *output_file) 239 | { 240 | ANBU::LOGGER(output_file, "\t+Name: %s\n", name_.c_str()); 241 | ANBU::LOGGER(output_file, "\t+Virtual Size: 0x%x\n", this->virtualSize_); 242 | ANBU::LOGGER(output_file, "\t+Virtual Address: 0x%x\n", this->virtual_address_); 243 | ANBU::LOGGER(output_file, "\t+Pointer to Raw Data: 0x%x\n", this->offset_); 244 | ANBU::LOGGER(output_file, "\t+Size of Raw Data: 0x%x\n", this->size_); 245 | ANBU::LOGGER(output_file, "\t+Pointer to relocations: 0x%x\n", this->pointerToRelocations_); 246 | ANBU::LOGGER(output_file, "\t+Pointer to line numbers: 0x%x\n", this->pointerToLineNumbers_); 247 | ANBU::LOGGER(output_file, "\t+Number of relocations: 0x%x\n", this->numberOfRelocations_); 248 | ANBU::LOGGER(output_file, "\t+Number of line numbers: 0x%x\n", this->numberOfLineNumbers_); 249 | ANBU::LOGGER(output_file, "\t+Characteristics: 0x%x\n", this->characteristics_); 250 | 251 | return true; 252 | } 253 | 254 | } -------------------------------------------------------------------------------- /Unpackers/generic_instrumentation.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "generic_instrumentation.h" 3 | 4 | #ifdef MAKEINTRESOURCEA 5 | #undef MAKEINTRESOURCEA 6 | #endif // MAKEINTRESOURCEA 7 | 8 | 9 | #define MAKEINTRESOURCEA(i) ((WINDOWS::LPSTR)((WINDOWS::ULONG_PTR)((WINDOWS::WORD)(i)))) 10 | 11 | /************* EXTERN VARIABLES *************/ 12 | extern FILE* logfile; // log file handler 13 | extern binary_t* pe_file; 14 | extern proc_info_t* proc_info; 15 | /************* VARIABLES USED FOR MONITORING BINARY *************/ 16 | ADDRINT main_base_address; 17 | dll_import_struct_t* aux = nullptr; 18 | std::vector dll_imports; 19 | bool check_first_thunk = false; 20 | 21 | const char* saved_dll_nameA = nullptr; 22 | const wchar_t* saved_dll_nameW = nullptr; 23 | 24 | 25 | 26 | void get_addresses_from_images(IMG img, VOID *v) 27 | { 28 | RTN loadlibraryA; 29 | RTN loadlibraryW; 30 | RTN getmodulehandleA; 31 | RTN getmodulehandleW; 32 | RTN getprocaddress; 33 | 34 | ANBU::LOGGER_INFO(logfile, "IMG Loaded: %s\n", IMG_Name(img).c_str()); 35 | 36 | ADDRINT start_addr = IMG_LowAddress(img); 37 | ADDRINT end_addr = IMG_HighAddress(img); 38 | const std::string name = IMG_Name(img); 39 | 40 | if (IMG_IsMainExecutable(img)) 41 | /* 42 | * Check if the loaded executable is the main one 43 | * in that case record the base address. 44 | */ 45 | { 46 | main_base_address = IMG_StartAddress(img); 47 | pe_file = new binary_t(main_base_address); 48 | pe_file->analyze_binary(); 49 | ANBU::LOGGER_INFO(logfile, "Binary Base Address: 0x%x\n", main_base_address); 50 | 51 | proc_info->process_not_being_debugged(); 52 | proc_info->print_peb_information(); 53 | 54 | proc_info->proc_name(name); 55 | proc_info->main_img_address(start_addr, end_addr); 56 | proc_info->first_instruction(IMG_Entry(img)); 57 | return; 58 | } 59 | else 60 | { 61 | // if it's not the main executable we add it as a library, 62 | // and it will be categorized as known or unknown 63 | proc_info->add_library(name, start_addr, end_addr); 64 | } 65 | 66 | loadlibraryA = RTN_FindByName(img, "LoadLibraryA"); 67 | 68 | if (RTN_Valid(loadlibraryA)) 69 | { 70 | RTN_Open(loadlibraryA); 71 | 72 | ANBU::LOGGER_INFO("Inserting callbacks for: %s\n", RTN_Name(loadlibraryA).c_str()); 73 | 74 | RTN_InsertCall(loadlibraryA, 75 | IPOINT_BEFORE, 76 | (AFUNPTR)hook_loadlibrarya_before, 77 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 78 | IARG_END 79 | ); 80 | 81 | RTN_InsertCall(loadlibraryA, 82 | IPOINT_AFTER, 83 | (AFUNPTR)hook_loadlibrary_after, 84 | IARG_FUNCRET_EXITPOINT_VALUE, 85 | IARG_END); 86 | 87 | RTN_Close(loadlibraryA); 88 | } 89 | 90 | loadlibraryW = RTN_FindByName(img, "LoadLibraryW"); 91 | 92 | if (RTN_Valid(loadlibraryW)) 93 | { 94 | RTN_Open(loadlibraryW); 95 | 96 | ANBU::LOGGER_INFO("Inserting callbacks for: %s\n", RTN_Name(loadlibraryW).c_str()); 97 | 98 | RTN_InsertCall(loadlibraryW, 99 | IPOINT_BEFORE, 100 | (AFUNPTR)hook_loadlibraryw_before, 101 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 102 | IARG_END 103 | ); 104 | 105 | RTN_InsertCall(loadlibraryW, 106 | IPOINT_AFTER, 107 | (AFUNPTR)hook_loadlibrary_after, 108 | IARG_FUNCRET_EXITPOINT_VALUE, 109 | IARG_END); 110 | 111 | RTN_Close(loadlibraryW); 112 | } 113 | 114 | getmodulehandleA = RTN_FindByName(img, "GetModuleHandleA"); 115 | 116 | if (RTN_Valid(getmodulehandleA)) 117 | { 118 | RTN_Open(getmodulehandleA); 119 | 120 | ANBU::LOGGER_INFO("Inserting callbacks for: %s\n", RTN_Name(getmodulehandleA).c_str()); 121 | 122 | RTN_InsertCall(getmodulehandleA, 123 | IPOINT_BEFORE, 124 | (AFUNPTR)hook_getmodulehandlea_before, 125 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 126 | IARG_END 127 | ); 128 | 129 | RTN_InsertCall(getmodulehandleA, 130 | IPOINT_AFTER, 131 | (AFUNPTR)hook_loadlibrary_after, 132 | IARG_FUNCRET_EXITPOINT_VALUE, 133 | IARG_END); 134 | 135 | RTN_Close(getmodulehandleA); 136 | } 137 | 138 | getmodulehandleW = RTN_FindByName(img, "GetModuleHandleW"); 139 | 140 | if (RTN_Valid(getmodulehandleW)) 141 | { 142 | RTN_Open(getmodulehandleW); 143 | 144 | ANBU::LOGGER_INFO("Inserting callbacks for: %s\n", RTN_Name(getmodulehandleW).c_str()); 145 | 146 | RTN_InsertCall(getmodulehandleW, 147 | IPOINT_BEFORE, 148 | (AFUNPTR)hook_getmodulehandlew_before, 149 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 150 | IARG_END 151 | ); 152 | 153 | RTN_InsertCall(getmodulehandleW, 154 | IPOINT_AFTER, 155 | (AFUNPTR)hook_loadlibrary_after, 156 | IARG_FUNCRET_EXITPOINT_VALUE, 157 | IARG_END); 158 | 159 | RTN_Close(getmodulehandleW); 160 | } 161 | 162 | getprocaddress = RTN_FindByName(img, "GetProcAddress"); 163 | 164 | if (RTN_Valid(getprocaddress)) 165 | { 166 | RTN_Open(getprocaddress); 167 | 168 | ANBU::LOGGER_INFO("Inserting callbacks for: %s\n", RTN_Name(getprocaddress).c_str()); 169 | 170 | RTN_InsertCall(getprocaddress, 171 | IPOINT_BEFORE, 172 | (AFUNPTR)hook_getprocaddress_before, 173 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 174 | IARG_FUNCARG_ENTRYPOINT_VALUE, 1, 175 | IARG_END 176 | ); 177 | 178 | RTN_InsertCall(getprocaddress, 179 | IPOINT_AFTER, 180 | (AFUNPTR)hook_getprocaddress_after, 181 | IARG_FUNCRET_EXITPOINT_VALUE, 182 | IARG_END); 183 | 184 | RTN_Close(getprocaddress); 185 | } 186 | 187 | return; 188 | } 189 | 190 | void hook_loadlibrarya_before(const char* dll_name) 191 | { 192 | check_first_thunk = false; // close the check of the first thunk copy 193 | 194 | saved_dll_nameA = dll_name; 195 | } 196 | 197 | void hook_getmodulehandlea_before(const char* dll_name) 198 | { 199 | check_first_thunk = false; // close the check of the first thunk copy 200 | 201 | saved_dll_nameA = dll_name; 202 | } 203 | 204 | void hook_loadlibraryw_before(const wchar_t* dll_name) 205 | { 206 | check_first_thunk = false; // close the check of the first thunk copy 207 | 208 | saved_dll_nameW = dll_name; 209 | } 210 | 211 | void hook_getmodulehandlew_before(const wchar_t* dll_name) 212 | { 213 | check_first_thunk = false; // close the check of the first thunk copy 214 | 215 | saved_dll_nameW = dll_name; 216 | } 217 | 218 | void hook_loadlibrary_after(ADDRINT dll_address) 219 | { 220 | if (dll_address != NULL) 221 | { 222 | if (saved_dll_nameA != nullptr) 223 | { 224 | if (aux == nullptr // if aux is equals to nullptr 225 | || strcmp(aux->dll_nameA.c_str(), saved_dll_nameA) != 0) 226 | { 227 | aux = new dll_import_struct_t(); 228 | aux->dll_nameA = saved_dll_nameA; 229 | dll_imports.push_back(aux); 230 | 231 | ANBU::LOGGER_INFO(logfile, "LoadLibraryA dll name: %s\n", saved_dll_nameA); 232 | 233 | aux->dll_address = dll_address; 234 | 235 | ANBU::LOGGER_INFO(logfile, "LoadLibrary returned: 0x%x\n", dll_address); 236 | } 237 | } 238 | else if (saved_dll_nameW != nullptr) 239 | { 240 | if (aux == nullptr 241 | || wcscmp(aux->dll_nameW.c_str(), saved_dll_nameW) != 0) 242 | { 243 | aux = new dll_import_struct_t(); 244 | aux->dll_nameW = saved_dll_nameW; 245 | dll_imports.push_back(aux); 246 | 247 | ANBU::LOGGER_INFO(logfile, L"LoadLibraryW dll name: %S\n", saved_dll_nameW); 248 | 249 | aux->dll_address = dll_address; 250 | 251 | ANBU::LOGGER_INFO(logfile, "LoadLibrary returned: 0x%x\n", dll_address); 252 | } 253 | } 254 | saved_dll_nameA = nullptr; 255 | saved_dll_nameW = nullptr; 256 | } 257 | } 258 | 259 | void hook_getprocaddress_before(ADDRINT dll_address, const char* function_name) 260 | { 261 | check_first_thunk = false; 262 | 263 | // Create a new function 264 | if (aux) 265 | { 266 | function_struct_t func; 267 | const char *filename; 268 | 269 | if ((uintptr_t)function_name <= 0xFFFF) // it is ordinal 270 | { 271 | func.function_ordinal = (uint16_t)((uintptr_t)function_name & 0xFFFF); 272 | func.is_ordinal = true; 273 | } 274 | else 275 | { 276 | func.function_name = function_name; 277 | func.is_ordinal = false; 278 | } 279 | 280 | PIN_LockClient(); 281 | 282 | if (func.is_ordinal) 283 | { 284 | if ((aux->dll_nameA.size() != 0 && (WINDOWS::GetProcAddress(WINDOWS::GetModuleHandleA(aux->dll_nameA.c_str()), MAKEINTRESOURCE(function_name)) == NULL) || 285 | (aux->dll_nameW.size() != 0 && (WINDOWS::GetProcAddress(WINDOWS::GetModuleHandleW(aux->dll_nameW.c_str()), MAKEINTRESOURCE(function_name)) == NULL)))) 286 | { 287 | filename = strrchr(IMG_Name(IMG_FindByAddress(dll_address)).c_str(), '\\'); 288 | 289 | if (filename == NULL) 290 | filename = IMG_Name(IMG_FindByAddress(dll_address)).c_str(); 291 | else 292 | filename++; 293 | 294 | aux->dll_nameA = filename; 295 | aux->dll_nameW.erase(); 296 | } 297 | } 298 | else 299 | { 300 | if ((aux->dll_nameA.size() != 0 && (WINDOWS::GetProcAddress(WINDOWS::GetModuleHandleA(aux->dll_nameA.c_str()), function_name) == NULL) || 301 | (aux->dll_nameW.size() != 0 && (WINDOWS::GetProcAddress(WINDOWS::GetModuleHandleW(aux->dll_nameW.c_str()), function_name) == NULL)))) 302 | { 303 | filename = strrchr(IMG_Name(IMG_FindByAddress(dll_address)).c_str(), '\\'); 304 | 305 | if (filename == NULL) 306 | filename = IMG_Name(IMG_FindByAddress(dll_address)).c_str(); 307 | else 308 | filename++; 309 | 310 | aux->dll_nameA = filename; 311 | aux->dll_nameW.erase(); 312 | } 313 | } 314 | 315 | aux->functions.push_back(func); 316 | if (func.is_ordinal) 317 | { 318 | ANBU::LOGGER_INFO(logfile, "Dll 0x%x(%s), function 0x%x\n", dll_address, IMG_Name(IMG_FindByAddress(dll_address)).c_str(), func.function_ordinal); 319 | } 320 | else 321 | { 322 | ANBU::LOGGER_INFO(logfile, "Dll 0x%x(%s), function %s\n", dll_address, IMG_Name(IMG_FindByAddress(dll_address)).c_str(), function_name); 323 | } 324 | PIN_UnlockClient(); 325 | 326 | } 327 | } 328 | 329 | void hook_getprocaddress_after(ADDRINT function_address) 330 | { 331 | if (aux) 332 | { 333 | check_first_thunk = true; 334 | 335 | ANBU::LOGGER_INFO(logfile, "GetProcAddress returned: 0x%x\n", function_address); 336 | 337 | // add the function address to the last function 338 | aux->functions.at( 339 | aux->functions.size() - 1 340 | ).function_address = function_address; 341 | } 342 | } -------------------------------------------------------------------------------- /PE/structures_and_enums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef STRUCTURES_AND_ENUMS_H 4 | #define STRUCTURES_AND_ENUMS_H 5 | 6 | 7 | /// @brief The Import Directory Table. 8 | /// 9 | /// There is a single array of these and one entry per imported DLL. 10 | struct pe_import 11 | { 12 | uint32_t ImportLookupTableRVA; 13 | uint32_t TimeDateStamp; 14 | uint32_t ForwarderChain; 15 | uint32_t NameRVA; 16 | uint32_t ImportAddressTableRVA; 17 | }; 18 | 19 | // values 20 | static const uint16_t mz_signature = 0x5a4d; // MZ in little-endian 21 | 22 | 23 | static const uint32_t correct_pe_signature_k = 0x4550; // PE in little-endian 24 | 25 | 26 | static const int32_t MaxNumberOfSections16 = 65279; 27 | 28 | 29 | static const uint32_t NameSize = 8; 30 | 31 | // enums 32 | enum MACHINE_TYPES { 33 | IMAGE_FILE_MACHINE_UNKNOWN_k = 0x0, 34 | IMAGE_FILE_MACHINE_AM33_k = 0x1d3, 35 | IMAGE_FILE_MACHINE_AMD64_k = 0x8664, 36 | IMAGE_FILE_MACHINE_ARM_k = 0x1c0, 37 | IMAGE_FILE_MACHINE_ARM64_k = 0xaa64, 38 | IMAGE_FILE_MACHINE_ARMNT_k = 0x1c4, 39 | IMAGE_FILE_MACHINE_EBC_k = 0xebc, 40 | IMAGE_FILE_MACHINE_I386_k = 0x014C, 41 | IMAGE_FILE_MACHINE_IA64_k = 0x0200, 42 | IMAGE_FILE_MACHINE_M32R_k = 0x9041, 43 | IMAGE_FILE_MACHINE_MIPS16_k = 0x266, 44 | IMAGE_FILE_MACHINE_MIPSFPU_k = 0x366, 45 | IMAGE_FILE_MACHINE_MIPSFPU16_k = 0x466, 46 | IMAGE_FILE_MACHINE_POWERPC_k = 0x1f0, 47 | IMAGE_FILE_MACHINE_POWERPCFP_k = 0x1f1, 48 | IMAGE_FILE_MACHINE_R4000_k = 0x166, 49 | IMAGE_FILE_MACHINE_RISCV32_k = 0x5032, 50 | IMAGE_FILE_MACHINE_RISCV64_k = 0x5064, 51 | IMAGE_FILE_MACHINE_RISCV128_k = 0x5128, 52 | IMAGE_FILE_MACHINE_SH3_k = 0x1a2, 53 | IMAGE_FILE_MACHINE_SH3DSP_k = 0x1a3, 54 | IMAGE_FILE_MACHINE_SH4_k = 0x1a6, 55 | IMAGE_FILE_MACHINE_SH5_k = 0x1a8, 56 | IMAGE_FILE_MACHINE_THUMB_k = 0x1c2, 57 | IMAGE_FILE_MACHINE_WCEMIPSV2_k = 0x169 58 | }; 59 | 60 | 61 | enum HEADER_CHARACTERISTICS 62 | { 63 | IMAGE_FILE_INVALID_k = 0x0000, 64 | IMAGE_FILE_RELOCS_STRIPPED_k = 0x0001, 65 | IMAGE_FILE_EXECUTABLE_IMAGE_k = 0x0002, 66 | IMAGE_FILE_LINE_NUMS_STRIPPED_k = 0x0004, 67 | IMAGE_FILE_LOCAL_SYMS_STRIPPED_k = 0x0008, 68 | IMAGE_FILE_AGGRESSIVE_WS_TRIM_k = 0x0010, 69 | IMAGE_FILE_LARGE_ADDRESS_AWARE_k = 0x0020, 70 | RESERVED_CHARACTERISTIC_k = 0x0040, 71 | IMAGE_FILE_BYTES_REVERSED_LO_k = 0x0080, 72 | IMAGE_FILE_32BIT_MACHINE_k = 0x0100, 73 | IMAGE_FILE_DEBUG_STRIPPED_k = 0x0200, 74 | IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP_k = 0x0400, 75 | IMAGE_FILE_NET_RUN_FROM_SWAP_k = 0x0800, 76 | IMAGE_FILE_SYSTEM_k = 0x1000, 77 | IMAGE_FILE_DLL_k = 0x2000, 78 | IMAGE_FILE_UP_SYSTEM_ONLY_k = 0x4000, 79 | IMAGE_FILE_BYTES_REVERSED_HI_k = 0x8000 80 | }; 81 | 82 | 83 | enum class PE_TYPE : uint16_t 84 | { 85 | rom_image_k = 0x107, 86 | pe32_k = 0x10B, 87 | pe64_k = 0x20B 88 | }; 89 | 90 | 91 | enum class SUBSYSTEM : uint16_t 92 | { 93 | IMAGE_SUBSYSTEM_UNKNOWN_k = 0, 94 | IMAGE_SUBSYSTEM_NATIVE_k = 1, 95 | IMAGE_SUBSYSTEM_WINDOWS_GUI_k = 2, 96 | IMAGE_SUBSYSTEM_WINDOWS_CUI_k = 3, 97 | IMAGE_SUBSYSTEM_OS2_CUI_k = 5, 98 | IMAGE_SUBSYSTEM_POSIX_CUI_k = 7, 99 | IMAGE_SUBSYSTEM_NATIVE_WINDOWS_k = 8, 100 | IMAGE_SUBSYSTEM_WINDOWS_CE_GUI_k = 9, 101 | IMAGE_SUBSYSTEM_EFI_APPLICATION_k = 10, 102 | IMAGE_SUBSYSTEM_EFI_BOOT__k = 11, 103 | IMAGE_SUBSYSTEM_EFI_RUNTIME__k = 12, 104 | IMAGE_SUBSYSTEM_EFI_ROM_k = 13, 105 | IMAGE_SUBSYSTEM_XBOX_k = 14, 106 | IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION_k = 16 107 | }; 108 | 109 | 110 | enum class DLL_CHARACTERISTICS : uint16_t 111 | { 112 | RESERVED_DLL_CHARACTERISTICS_1_k = 0x0001, 113 | RESERVED_DLL_CHARACTERISTICS_2_k = 0x0002, 114 | RESERVED_DLL_CHARACTERISTICS_4_k = 0x0004, 115 | RESERVED_DLL_CHARACTERISTICS_8_k = 0x0008, 116 | IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA_k = 0x0020, 117 | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE_k = 0x0040, 118 | IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY_k = 0x0080, 119 | IMAGE_DLLCHARACTERISTICS_NX_COMPAT_k = 0x0100, 120 | IMAGE_DLLCHARACTERISTICS_NO_ISOLATION_k = 0x0200, 121 | IMAGE_DLLCHARACTERISTICS_NO_SEH_k = 0x0400, 122 | IMAGE_DLLCHARACTERISTICS_NO_BIND_k = 0x0800, 123 | IMAGE_DLLCHARACTERISTICS_APPCONTAINER_k = 0x1000, 124 | IMAGE_DLLCHARACTERISTICS_WDM_DRIVER_k = 0x2000, 125 | IMAGE_DLLCHARACTERISTICS_GUARD_CF_k = 0x4000, 126 | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE_k = 0x8000 127 | }; 128 | 129 | 130 | enum class DATA_DIRECTORY : size_t 131 | { 132 | export_table_k = 0, 133 | import_table_k, 134 | resource_table_k, 135 | exception_table_k, 136 | certificate_table_k, 137 | base_relocation_table_k, 138 | debug_k, 139 | architecture_k, 140 | global_ptr_k, 141 | tls_table_k, 142 | load_config_table_k, 143 | bound_import_k, 144 | iat_k, 145 | delay_import_descriptor_k, 146 | clr_runtime_header_k, 147 | reserved_k 148 | }; 149 | 150 | 151 | enum class SECTION_CHARACTERISTICS : uint32_t 152 | { 153 | RESERVED_SECTION_FLAG_0_k = 0x00000000, 154 | RESERVED_SECTION_FLAG_1_k = 0x00000001, 155 | RESERVED_SECTION_FLAG_2_k = 0x00000002, 156 | RESERVED_SECTION_FLAG_4_k = 0x00000004, 157 | RESERVED_SECTION_FLAG_10_k = 0x00000010, 158 | RESERVED_SECTION_FLAG_400_k = 0x00000400, 159 | IMAGE_SCN_TYPE_NO_PAD_k = 0x00000008, 160 | IMAGE_SCN_CNT_CODE_k = 0x00000020, 161 | IMAGE_SCN_CNT_INITIALIZED_DATA_k = 0x00000040, 162 | IMAGE_SCN_CNT_UNINITIALIZED_DATA_k = 0x00000080, 163 | IMAGE_SCN_LNK_OTHER_k = 0x00000100, 164 | IMAGE_SCN_LNK_INFO_k = 0x00000200, 165 | IMAGE_SCN_LNK_REMOVE_k = 0x00000800, 166 | IMAGE_SCN_LNK_COMDAT_k = 0x00001000, 167 | IMAGE_SCN_GPREL_k = 0x00008000, 168 | IMAGE_SCN_MEM_PURGEABLE_k = 0x00020000, 169 | IMAGE_SCN_MEM_16BIT_k = 0x00020000, 170 | IMAGE_SCN_MEM_LOCKED_k = 0x00040000, 171 | IMAGE_SCN_MEM_PRELOAD_k = 0x00080000, 172 | IMAGE_SCN_ALIGN_1BYTES_k = 0x00100000, 173 | IMAGE_SCN_ALIGN_2BYTES_k = 0x00200000, 174 | IMAGE_SCN_ALIGN_4BYTES_k = 0x00300000, 175 | IMAGE_SCN_ALIGN_8BYTES_k = 0x00400000, 176 | IMAGE_SCN_ALIGN_16BYTES_k = 0x00500000, 177 | IMAGE_SCN_ALIGN_32BYTES_k = 0x00600000, 178 | IMAGE_SCN_ALIGN_64BYTES_k = 0x00700000, 179 | IMAGE_SCN_ALIGN_128BYTES_k = 0x00800000, 180 | IMAGE_SCN_ALIGN_256BYTES_k = 0x00900000, 181 | IMAGE_SCN_ALIGN_512BYTES_k = 0x00A00000, 182 | IMAGE_SCN_ALIGN_1024BYTES_k = 0x00B00000, 183 | IMAGE_SCN_ALIGN_2048BYTES_k = 0x00C00000, 184 | IMAGE_SCN_ALIGN_4096BYTES_k = 0x00D00000, 185 | IMAGE_SCN_ALIGN_8192BYTES_k = 0x00E00000, 186 | IMAGE_SCN_LNK_NRELOC_OVFL_k = 0x01000000, 187 | IMAGE_SCN_MEM_DISCARDABLE_k = 0x02000000, 188 | IMAGE_SCN_MEM_NOT_CACHED_k = 0x04000000, 189 | IMAGE_SCN_MEM_NOT_PAGED_k = 0x08000000, 190 | IMAGE_SCN_MEM_SHARED_k = 0x10000000, 191 | IMAGE_SCN_MEM_EXECUTE_k = 0x20000000, 192 | IMAGE_SCN_MEM_READ_k = 0x40000000, 193 | IMAGE_SCN_MEM_WRITE_k = 0x80000000 194 | }; 195 | 196 | 197 | #pragma pack(push,1) 198 | struct pe_dos_header 199 | { 200 | uint16_t Magic; 201 | uint16_t UsedBytesInTheLastPage; 202 | uint16_t FileSizeInPages; 203 | uint16_t NumberOfRelocationItems; 204 | uint16_t HeaderSizeInParagraphs; 205 | uint16_t MinimumExtraParagraphs; 206 | uint16_t MaximumExtraParagraphs; 207 | uint16_t InitialRelativeSS; 208 | uint16_t InitialSP; 209 | uint16_t Checksum; 210 | uint16_t InitialIP; 211 | uint16_t InitialRelativeCS; 212 | uint16_t AddressOfRelocationTable; 213 | uint16_t OverlayNumber; 214 | uint16_t Reserved[4]; 215 | uint16_t OEMid; 216 | uint16_t OEMinfo; 217 | uint16_t Reserved2[10]; 218 | uint32_t AddressOfNewExeHeader; 219 | }; 220 | 221 | 222 | struct pe_header 223 | { 224 | uint32_t signature; 225 | uint16_t Machine; 226 | uint16_t NumberOfSections; 227 | uint32_t TimeDateStamp; 228 | uint32_t PointerToSymbolTable; 229 | uint32_t NumberOfSymbols; 230 | uint16_t SizeOfOptionalHeader; 231 | uint16_t Characteristics; 232 | }; 233 | 234 | 235 | struct pe64_optional_header 236 | { 237 | uint16_t Magic; 238 | uint8_t MajorLinkerVersion; 239 | uint8_t MinorLinkerVersion; 240 | uint32_t SizeOfCode; 241 | uint32_t SizeOfInitializedData; 242 | uint32_t SizeOfUninitializedData; 243 | uint32_t AddressOfEntryPoint; // RVA 244 | uint32_t BaseOfCode; // RVA 245 | //uint32_t BaseOfData; // RVA 246 | uint64_t ImageBase; 247 | uint32_t SectionAlignment; 248 | uint32_t FileAlignment; 249 | uint16_t MajorOperatingSystemVersion; 250 | uint16_t MinorOperatingSystemVersion; 251 | uint16_t MajorImageVersion; 252 | uint16_t MinorImageVersion; 253 | uint16_t MajorSubsystemVersion; 254 | uint16_t MinorSubsystemVersion; 255 | uint32_t Win32VersionValue; 256 | uint32_t SizeOfImage; 257 | uint32_t SizeOfHeaders; 258 | uint32_t CheckSum; 259 | uint16_t Subsystem; 260 | uint16_t DLLCharacteristics; 261 | uint64_t SizeOfStackReserve; 262 | uint64_t SizeOfStackCommit; 263 | uint64_t SizeOfHeapReserve; 264 | uint64_t SizeOfHeapCommit; 265 | uint32_t LoaderFlags; 266 | uint32_t NumberOfRvaAndSize; 267 | }; 268 | 269 | 270 | struct pe32_optional_header 271 | { 272 | uint16_t Magic; 273 | uint8_t MajorLinkerVersion; 274 | uint8_t MinorLinkerVersion; 275 | uint32_t SizeOfCode; 276 | uint32_t SizeOfInitializedData; 277 | uint32_t SizeOfUninitializedData; 278 | uint32_t AddressOfEntryPoint; // RVA 279 | uint32_t BaseOfCode; // RVA 280 | uint32_t BaseOfData; // RVA 281 | uint32_t ImageBase; 282 | uint32_t SectionAlignment; 283 | uint32_t FileAlignment; 284 | uint16_t MajorOperatingSystemVersion; 285 | uint16_t MinorOperatingSystemVersion; 286 | uint16_t MajorImageVersion; 287 | uint16_t MinorImageVersion; 288 | uint16_t MajorSubsystemVersion; 289 | uint16_t MinorSubsystemVersion; 290 | uint32_t Win32VersionValue; 291 | uint32_t SizeOfImage; 292 | uint32_t SizeOfHeaders; 293 | uint32_t CheckSum; 294 | uint16_t Subsystem; 295 | uint16_t DLLCharacteristics; 296 | uint32_t SizeOfStackReserve; 297 | uint32_t SizeOfStackCommit; 298 | uint32_t SizeOfHeapReserve; 299 | uint32_t SizeOfHeapCommit; 300 | uint32_t LoaderFlags; 301 | uint32_t NumberOfRvaAndSize; 302 | }; 303 | 304 | 305 | struct pe_data_directory 306 | { 307 | uint32_t RelativeVirtualAddress; 308 | uint32_t Size; 309 | }; 310 | 311 | 312 | struct pe_section { 313 | char Name[8]; 314 | uint32_t VirtualSize; 315 | uint32_t VirtualAddress; 316 | uint32_t SizeOfRawData; 317 | uint32_t PointerToRawData; 318 | uint32_t PointerToRelocations; 319 | uint32_t PointerToLineNumbers; 320 | uint16_t NumberOfRelocations; 321 | uint16_t NumberOfLineNumbers; 322 | uint32_t Characteristics; 323 | }; 324 | #pragma pack(pop) 325 | 326 | 327 | 328 | #endif // !STRUCTURES_AND_ENUMS_H 329 | -------------------------------------------------------------------------------- /Unpackers/memory_movement_detection.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "memory_movement_detection.h" 3 | 4 | /************* EXTERN VARIABLES *************/ 5 | extern FILE* logfile; // log file handler 6 | extern ADDRINT main_base_address; // main base address of binary, to start 7 | // reading PE file 8 | extern std::vector dll_imports; 9 | extern bool check_first_thunk; 10 | extern binary_t* pe_file; 11 | extern std::string unpacked_file_name; 12 | extern proc_info_t* proc_info; 13 | /******************* Data for the unpacker *******************/ 14 | ADDRINT saved_addr; // temporary variable needed for storing state between 15 | // two analysis routines 16 | bool any_import_resolved = false; 17 | 18 | bool header_modified = false; 19 | 20 | w_xor_x_heuristic_t w_xor_x_heuristic; 21 | 22 | pushad_popad_heuristic_t pushad_popad_heuristic; 23 | /******************* Variables for dump *******************/ 24 | lief_import_t* library; 25 | import_entry_t* function; 26 | 27 | 28 | /******************* Functions for the unpacker *******************/ 29 | 30 | void fini() 31 | /* 32 | * Function that will be executed at the end 33 | * of the execution or when PIN detachs from 34 | * the process. 35 | */ 36 | { 37 | ANBU::LOGGER(logfile, "------ unpacking complete ------\n"); 38 | 39 | // save final log and close file 40 | ANBU::LOGGER(logfile, "------ end log ------\n"); 41 | fclose(logfile); 42 | } 43 | 44 | void instrument_mem_cflow(INS ins, void *v) 45 | /* 46 | * Function to instrument each instruction 47 | * we will use this function to record the 48 | * written memory, and the jumps to those 49 | * memory. 50 | */ 51 | { 52 | if (INS_IsMemoryWrite(ins) 53 | && INS_hasKnownMemorySize(ins)) 54 | { 55 | // this first three callbacks will be used for tracking memory writes 56 | 57 | INS_InsertPredicatedCall( 58 | ins, 59 | IPOINT_BEFORE, 60 | (AFUNPTR)queue_memwrite, 61 | IARG_INST_PTR, 62 | IARG_MEMORYWRITE_EA, 63 | IARG_END 64 | ); 65 | 66 | 67 | // For REP instructions 68 | 69 | // if no more REPs, execute next instruction 70 | if (INS_HasFallThrough(ins)) 71 | { 72 | INS_InsertPredicatedCall( 73 | ins, 74 | IPOINT_AFTER, 75 | (AFUNPTR)log_memwrite, 76 | IARG_INST_PTR, 77 | IARG_MEMORYWRITE_SIZE, 78 | IARG_END 79 | ); 80 | } 81 | 82 | // check if it is REP or another kind of branch or call instruction to copy 83 | if (INS_IsBranchOrCall(ins)) 84 | { 85 | INS_InsertPredicatedCall( 86 | ins, 87 | IPOINT_TAKEN_BRANCH, 88 | (AFUNPTR)log_memwrite, 89 | IARG_INST_PTR, 90 | IARG_MEMORYWRITE_SIZE, 91 | IARG_END 92 | ); 93 | } 94 | } 95 | 96 | // check if jumped to unpacked code 97 | if ((INS_IsDirectBranch(ins) || INS_IsIndirectBranchOrCall(ins)) 98 | && INS_OperandCount(ins) > 0) 99 | { 100 | INS_InsertCall( 101 | ins, 102 | IPOINT_BEFORE, 103 | (AFUNPTR)check_indirect_ctransfer, 104 | IARG_INST_PTR, 105 | IARG_BRANCH_TARGET_ADDR, 106 | IARG_BRANCH_TAKEN, 107 | IARG_END 108 | ); 109 | } 110 | 111 | pushad_popad_heuristic.check_pushad_popad(ins); 112 | } 113 | 114 | void queue_memwrite(ADDRINT ins_addr, ADDRINT addr) 115 | /* 116 | * Function which will save for a moment the address 117 | * of the instruction which will copy memory. 118 | * This is necessary as only before of the instruction 119 | * execution is possible to record the address 120 | */ 121 | { 122 | if (proc_info->is_known_library_instruction(ins_addr)) 123 | return; 124 | saved_addr = addr; 125 | } 126 | 127 | void log_memwrite(ADDRINT ins_addr, UINT32 size) 128 | /* 129 | * Function to log in shared_mem the address and the size of 130 | * copied data from a copy instruction 131 | */ 132 | { 133 | ADDRINT addr = saved_addr; 134 | unsigned char aux; 135 | 136 | if (proc_info->is_known_library_instruction(ins_addr)) 137 | return; 138 | 139 | for (ADDRINT i = addr; i < addr + size; i++) 140 | { 141 | w_xor_x_heuristic.set_shadow_memory_as_writable(i); 142 | PIN_SafeCopy((VOID*)&aux, (const void*)i, 1); 143 | w_xor_x_heuristic.set_shadow_memory_value(i, aux); 144 | } 145 | 146 | if (!header_modified && 147 | (addr >= main_base_address && 148 | addr < main_base_address + sizeof(pe_dos_header)) 149 | ) 150 | { 151 | header_modified = true; 152 | } 153 | 154 | // check if is writing an API to memory 155 | // only will be executed after a GetProcAddress 156 | if (check_first_thunk && size == sizeof(ADDRINT) && pe_file->on_pe_file(addr)) 157 | { 158 | ADDRINT api_write; 159 | PIN_SafeCopy((VOID*)&api_write, (const VOID*)addr, sizeof(ADDRINT)); 160 | 161 | for (size_t i = 0; i < dll_imports.size(); i++) 162 | { 163 | for (size_t j = 0; j < dll_imports.at(i)->functions.size(); j++) 164 | { 165 | if (dll_imports.at(i)->functions.at(j).function_address == api_write) // check which API is writing 166 | { 167 | any_import_resolved = true; 168 | 169 | PIN_LockClient(); 170 | dll_imports.at(i)->functions.at(j).function_destination = addr; 171 | PIN_UnlockClient(); 172 | 173 | ANBU::LOGGER_INFO(logfile, "API %s (0x%x) written to: 0x%x\n", 174 | dll_imports.at(i)->functions.at(j).function_name.c_str(), 175 | dll_imports.at(i)->functions.at(j).function_address, 176 | dll_imports.at(i)->functions.at(j).function_destination); 177 | } 178 | } 179 | } 180 | 181 | check_first_thunk = false; 182 | } 183 | } 184 | 185 | void check_indirect_ctransfer(ADDRINT ip, ADDRINT target, BOOL taken) 186 | /* 187 | * Function to detect the jump to the OEP and dump the unpacked code. 188 | * we will use the shadow_mem to detect if a memory was used as a target 189 | * of a copy, we will taint that memory as possible OEP. 190 | */ 191 | { 192 | if (!taken) 193 | return; 194 | 195 | if (proc_info->is_known_library_instruction(ip)) 196 | return; 197 | 198 | w_xor_x_heuristic.set_shadow_memory_as_executable(target); 199 | 200 | /* 201 | * Pushad & popad heuristic detection 202 | */ 203 | if (pushad_popad_heuristic.pushad_popad_detected() && !pushad_popad_heuristic.pushad_popad_finished()) 204 | return; 205 | else if (pushad_popad_heuristic.pushad_popad_detected() && 206 | pushad_popad_heuristic.pushad_popad_finished() && 207 | w_xor_x_heuristic.is_shadow_memory_writable(target)) 208 | { 209 | PIN_LockClient(); 210 | if (dump_to_file(target)) 211 | { 212 | PIN_UnlockClient(); 213 | 214 | fini(); 215 | 216 | PIN_ExitProcess(0); 217 | } 218 | PIN_UnlockClient(); 219 | } 220 | 221 | /* 222 | * w+x heuristic detection 223 | */ 224 | if (w_xor_x_heuristic.is_shadow_memory_writable(target) && !w_xor_x_heuristic.in_cluster(target)) 225 | { 226 | ANBU::LOGGER_INFO(logfile, "Jumped to the address: 0x%x, written before\n", target); 227 | 228 | w_xor_x_heuristic.set_cluster(target, true); 229 | 230 | if (pe_file->has_section_changed_entropy(target) && any_import_resolved) 231 | { 232 | PIN_LockClient(); 233 | if (dump_to_file(target)) 234 | { 235 | PIN_UnlockClient(); 236 | 237 | fini(); 238 | 239 | PIN_ExitProcess(0); 240 | } 241 | PIN_UnlockClient(); 242 | } 243 | } 244 | } 245 | 246 | bool dump_to_file(ADDRINT target) 247 | { 248 | if (header_modified) 249 | pe_file->parse(); 250 | 251 | auto sections = pe_file->section_table_header(); 252 | 253 | for (size_t i = 0; i < sections.size(); i++) 254 | { 255 | sections[i].pointerto_raw_data(sections[i].virtual_address()); 256 | sections[i].sizeof_raw_data(sections[i].virtual_size()); 257 | } 258 | 259 | pe_file->section_table_header(sections); 260 | 261 | /* 262 | * go through the APIs 263 | */ 264 | for (size_t i = 0; i < dll_imports.size(); i++) 265 | { 266 | // check if the dll to insert is inside of the unpacked zone 267 | // if not, go fuck off 268 | if (dll_imports.at(i)->dll_nameA.size() != 0) 269 | { 270 | ANBU::LOGGER_INFO(logfile, "Adding to the import DLL: %s\n", dll_imports.at(i)->dll_nameA.c_str()); 271 | library = pe_file->add_library(dll_imports.at(i)->dll_nameA.c_str()); 272 | } 273 | else 274 | { 275 | ANBU::LOGGER_INFO(logfile, L"Adding to the import DLL: %S\n", dll_imports.at(i)->dll_nameW.c_str()); 276 | char* dll_nameA = (char*)calloc(1, wcslen(dll_imports.at(i)->dll_nameW.c_str()) + 1); 277 | wcstombs(dll_nameA, dll_imports.at(i)->dll_nameW.c_str(), wcslen(dll_imports.at(i)->dll_nameW.c_str()) + 1); 278 | library = pe_file->add_library(dll_nameA); 279 | } 280 | ADDRINT first_thunk = 0; 281 | 282 | for (size_t j = 0; j < dll_imports.at(i)->functions.size(); j++) 283 | { 284 | if (!pe_file->on_pe_file(dll_imports.at(i)->functions.at(j).function_destination)) 285 | continue; 286 | 287 | if (dll_imports.at(i)->functions.at(j).is_ordinal) 288 | { 289 | if (dll_imports.at(i)->functions.at(j).function_ordinal > 0xFFFF) 290 | continue; 291 | 292 | ANBU::LOGGER_INFO(logfile, "Adding to the import Function: 0%x\n", dll_imports.at(i)->functions.at(j).function_ordinal); 293 | const uint64_t ORDINAL_MASK = pe_file->type() == PE_TYPE::pe32_k ? 0x80000000 : 0x8000000000000000; 294 | function = &library->add_entry(import_entry_t( ORDINAL_MASK | dll_imports.at(i)->functions.at(j).function_ordinal,"" )); 295 | } 296 | else 297 | { 298 | if (dll_imports.at(i)->functions.at(j).function_name.size() == 0 || dll_imports.at(i)->functions.at(j).function_name.size() > 256) 299 | continue; 300 | 301 | ANBU::LOGGER_INFO(logfile, "Adding to the import Function: %s\n", dll_imports.at(i)->functions.at(j).function_name.c_str()); 302 | function = &library->add_entry(dll_imports.at(i)->functions.at(j).function_name); 303 | } 304 | 305 | if (first_thunk == 0) 306 | first_thunk = dll_imports.at(i)->functions.at(j).function_destination; 307 | else if (dll_imports.at(i)->functions.at(j).function_destination < first_thunk) 308 | first_thunk = dll_imports.at(i)->functions.at(j).function_destination; 309 | } 310 | if (first_thunk == 0x0) 311 | continue; 312 | 313 | first_thunk -= IMG_StartAddress(IMG_FindByAddress(first_thunk)); 314 | library->import_address_table_rva(first_thunk); 315 | } 316 | 317 | ANBU::LOGGER_INFO(logfile, "Dumping to file\n"); 318 | 319 | char file_name[MAX_PATH]; 320 | if (unpacked_file_name.size() != 0) 321 | snprintf(file_name, sizeof(file_name) - 1, "%s", unpacked_file_name.c_str()); 322 | else 323 | snprintf(file_name, sizeof(file_name) - 1, "file.base-0x%x.entry-0x%x.bin", (uintptr_t)main_base_address, (uintptr_t)(target - main_base_address)); 324 | 325 | if (!pe_file->write(file_name, target)) 326 | { 327 | ANBU::LOGGER_ERROR(logfile, "Error dumping the file\n"); 328 | 329 | return false; 330 | } 331 | 332 | return true; 333 | } -------------------------------------------------------------------------------- /md5.cpp: -------------------------------------------------------------------------------- 1 | /* MD5 2 | converted to C++ class by Frank Thilo (thilo@unix-ag.org) 3 | for bzflag (http://www.bzflag.org) 4 | 5 | based on: 6 | 7 | md5.h and md5.c 8 | reference implemantion of RFC 1321 9 | 10 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 11 | rights reserved. 12 | 13 | License to copy and use this software is granted provided that it 14 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 15 | Algorithm" in all material mentioning or referencing this software 16 | or this function. 17 | 18 | License is also granted to make and use derivative works provided 19 | that such works are identified as "derived from the RSA Data 20 | Security, Inc. MD5 Message-Digest Algorithm" in all material 21 | mentioning or referencing the derived work. 22 | 23 | RSA Data Security, Inc. makes no representations concerning either 24 | the merchantability of this software or the suitability of this 25 | software for any particular purpose. It is provided "as is" 26 | without express or implied warranty of any kind. 27 | 28 | These notices must be retained in any copies of any part of this 29 | documentation and/or software. 30 | 31 | */ 32 | 33 | /* interface header */ 34 | #include "md5.h" 35 | 36 | 37 | // Constants for MD5Transform routine. 38 | #define S11 7 39 | #define S12 12 40 | #define S13 17 41 | #define S14 22 42 | #define S21 5 43 | #define S22 9 44 | #define S23 14 45 | #define S24 20 46 | #define S31 4 47 | #define S32 11 48 | #define S33 16 49 | #define S34 23 50 | #define S41 6 51 | #define S42 10 52 | #define S43 15 53 | #define S44 21 54 | 55 | /////////////////////////////////////////////// 56 | 57 | // F, G, H and I are basic MD5 functions. 58 | inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { 59 | return x & y | ~x&z; 60 | } 61 | 62 | inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { 63 | return x & z | y & ~z; 64 | } 65 | 66 | inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { 67 | return x ^ y^z; 68 | } 69 | 70 | inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { 71 | return y ^ (x | ~z); 72 | } 73 | 74 | // rotate_left rotates x left n bits. 75 | inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { 76 | return (x << n) | (x >> (32 - n)); 77 | } 78 | 79 | // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 80 | // Rotation is separate from addition to prevent recomputation. 81 | inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 82 | a = rotate_left(a + F(b, c, d) + x + ac, s) + b; 83 | } 84 | 85 | inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 86 | a = rotate_left(a + G(b, c, d) + x + ac, s) + b; 87 | } 88 | 89 | inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 90 | a = rotate_left(a + H(b, c, d) + x + ac, s) + b; 91 | } 92 | 93 | inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { 94 | a = rotate_left(a + I(b, c, d) + x + ac, s) + b; 95 | } 96 | 97 | ////////////////////////////////////////////// 98 | 99 | // default ctor, just initailize 100 | MD5::MD5() 101 | { 102 | init(); 103 | } 104 | 105 | ////////////////////////////////////////////// 106 | 107 | // nifty shortcut ctor, compute MD5 for string and finalize it right away 108 | MD5::MD5(const std::string &text) 109 | { 110 | init(); 111 | update(text.c_str(), text.length()); 112 | finalize(); 113 | } 114 | 115 | ////////////////////////////// 116 | 117 | void MD5::init() 118 | { 119 | finalized = false; 120 | 121 | count[0] = 0; 122 | count[1] = 0; 123 | 124 | // load magic initialization constants. 125 | state[0] = 0x67452301; 126 | state[1] = 0xefcdab89; 127 | state[2] = 0x98badcfe; 128 | state[3] = 0x10325476; 129 | } 130 | 131 | ////////////////////////////// 132 | 133 | // decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. 134 | void MD5::decode(uint4 output[], const uint1 input[], size_type len) 135 | { 136 | for (unsigned int i = 0, j = 0; j < len; i++, j += 4) 137 | output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) | 138 | (((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24); 139 | } 140 | 141 | 142 | ////////////////////////////// 143 | 144 | // encodes input (uint4) into output (unsigned char). Assumes len is 145 | // a multiple of 4. 146 | void MD5::encode(uint1 output[], const uint4 input[], size_type len) 147 | { 148 | for (size_type i = 0, j = 0; j < len; i++, j += 4) { 149 | output[j] = input[i] & 0xff; 150 | output[j + 1] = (input[i] >> 8) & 0xff; 151 | output[j + 2] = (input[i] >> 16) & 0xff; 152 | output[j + 3] = (input[i] >> 24) & 0xff; 153 | } 154 | } 155 | 156 | 157 | ////////////////////////////// 158 | 159 | // apply MD5 algo on a block 160 | void MD5::transform(const uint1 block[blocksize]) 161 | { 162 | uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 163 | decode(x, block, blocksize); 164 | 165 | /* Round 1 */ 166 | FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ 167 | FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ 168 | FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ 169 | FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ 170 | FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ 171 | FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ 172 | FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ 173 | FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ 174 | FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ 175 | FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ 176 | FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 177 | FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 178 | FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 179 | FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 180 | FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 181 | FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 182 | 183 | /* Round 2 */ 184 | GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ 185 | GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ 186 | GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 187 | GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ 188 | GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ 189 | GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 190 | GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 191 | GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ 192 | GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ 193 | GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 194 | GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ 195 | GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ 196 | GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 197 | GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ 198 | GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ 199 | GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 200 | 201 | /* Round 3 */ 202 | HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ 203 | HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ 204 | HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 205 | HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 206 | HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ 207 | HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ 208 | HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ 209 | HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 210 | HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 211 | HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ 212 | HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ 213 | HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ 214 | HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ 215 | HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 216 | HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 217 | HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ 218 | 219 | /* Round 4 */ 220 | II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ 221 | II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ 222 | II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 223 | II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ 224 | II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 225 | II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ 226 | II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 227 | II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ 228 | II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ 229 | II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 230 | II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ 231 | II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 232 | II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ 233 | II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 234 | II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ 235 | II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ 236 | 237 | state[0] += a; 238 | state[1] += b; 239 | state[2] += c; 240 | state[3] += d; 241 | 242 | // Zeroize sensitive information. 243 | memset(x, 0, sizeof x); 244 | } 245 | 246 | ////////////////////////////// 247 | 248 | // MD5 block update operation. Continues an MD5 message-digest 249 | // operation, processing another message block 250 | void MD5::update(const unsigned char input[], size_type length) 251 | { 252 | // compute number of bytes mod 64 253 | size_type index = count[0] / 8 % blocksize; 254 | 255 | // Update number of bits 256 | if ((count[0] += (length << 3)) < (length << 3)) 257 | count[1]++; 258 | count[1] += (length >> 29); 259 | 260 | // number of bytes we need to fill in buffer 261 | size_type firstpart = 64 - index; 262 | 263 | size_type i; 264 | 265 | // transform as many times as possible. 266 | if (length >= firstpart) 267 | { 268 | // fill buffer first, transform 269 | memcpy(&buffer[index], input, firstpart); 270 | transform(buffer); 271 | 272 | // transform chunks of blocksize (64 bytes) 273 | for (i = firstpart; i + blocksize <= length; i += blocksize) 274 | transform(&input[i]); 275 | 276 | index = 0; 277 | } 278 | else 279 | i = 0; 280 | 281 | // buffer remaining input 282 | memcpy(&buffer[index], &input[i], length - i); 283 | } 284 | 285 | ////////////////////////////// 286 | 287 | // for convenience provide a verson with signed char 288 | void MD5::update(const char input[], size_type length) 289 | { 290 | update((const unsigned char*)input, length); 291 | } 292 | 293 | ////////////////////////////// 294 | 295 | // MD5 finalization. Ends an MD5 message-digest operation, writing the 296 | // the message digest and zeroizing the context. 297 | MD5& MD5::finalize() 298 | { 299 | static unsigned char padding[64] = { 300 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 301 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 303 | }; 304 | 305 | if (!finalized) { 306 | // Save number of bits 307 | unsigned char bits[8]; 308 | encode(bits, count, 8); 309 | 310 | // pad out to 56 mod 64. 311 | size_type index = count[0] / 8 % 64; 312 | size_type padLen = (index < 56) ? (56 - index) : (120 - index); 313 | update(padding, padLen); 314 | 315 | // Append length (before padding) 316 | update(bits, 8); 317 | 318 | // Store state in digest 319 | encode(digest, state, 16); 320 | 321 | // Zeroize sensitive information. 322 | memset(buffer, 0, sizeof buffer); 323 | memset(count, 0, sizeof count); 324 | 325 | finalized = true; 326 | } 327 | 328 | return *this; 329 | } 330 | 331 | 332 | 333 | 334 | ////////////////////////////// 335 | 336 | // return hex representation of digest as string 337 | std::string MD5::hexdigest() const 338 | { 339 | if (!finalized) 340 | return ""; 341 | 342 | char buf[33]; 343 | for (int i = 0; i < 16; i++) 344 | sprintf(buf + i * 2, "%02x", digest[i]); 345 | buf[32] = 0; 346 | 347 | return std::string(buf); 348 | } 349 | 350 | ////////////////////////////// 351 | 352 | std::ostream& operator<<(std::ostream& out, MD5 md5) 353 | { 354 | return out << md5.hexdigest(); 355 | } 356 | 357 | 358 | ////////////////////////////// 359 | 360 | std::string md5(const std::string str) 361 | { 362 | MD5 md5 = MD5(str); 363 | 364 | return md5.hexdigest(); 365 | } -------------------------------------------------------------------------------- /PE/dos_header.cpp: -------------------------------------------------------------------------------- 1 | #include "dos_header.h" 2 | 3 | namespace pe_parser 4 | { 5 | dos_header_t::dos_header_t(const pe_dos_header* dos_header_address) : 6 | magic_{ dos_header_address->Magic }, 7 | usedBytesInTheLastPage_{ dos_header_address->UsedBytesInTheLastPage }, 8 | fileSizeInPages_{ dos_header_address->FileSizeInPages }, 9 | numberOfRelocation_{ dos_header_address->NumberOfRelocationItems }, 10 | headerSizeInParagraphs_{ dos_header_address->HeaderSizeInParagraphs }, 11 | minimumExtraParagraphs_{ dos_header_address->MinimumExtraParagraphs }, 12 | maximumExtraParagraphs_{ dos_header_address->MaximumExtraParagraphs }, 13 | initialRelativeSS_{ dos_header_address->InitialRelativeSS }, 14 | initialSP_{ dos_header_address->InitialSP }, 15 | checksum_{ dos_header_address->Checksum }, 16 | initialIP_{ dos_header_address->InitialIP }, 17 | initialRelativeCS_{ dos_header_address->InitialRelativeCS }, 18 | addressOfRelocationTable_{ dos_header_address->AddressOfRelocationTable }, 19 | overlayNumber_{ dos_header_address->OverlayNumber }, 20 | oEMid_{ dos_header_address->OEMid }, 21 | oEMinfo_{ dos_header_address->OEMinfo }, 22 | addressOfNewExeHeader_{ dos_header_address->AddressOfNewExeHeader } 23 | { 24 | size_t copied_size, size_to_copy = sizeof(dos_header_address->Reserved); 25 | dos_header_correct = true; 26 | 27 | copied_size = PIN_SafeCopy((VOID*)&this->reserved_, (const VOID*)dos_header_address->Reserved, size_to_copy); 28 | 29 | if (copied_size != size_to_copy) 30 | { 31 | dos_header_correct = false; 32 | return; 33 | } 34 | 35 | size_to_copy = sizeof(dos_header_address->Reserved2); 36 | 37 | copied_size = PIN_SafeCopy((VOID*)&this->reserved2_, (const VOID*)dos_header_address->Reserved2, size_to_copy); 38 | 39 | if (copied_size != size_to_copy) 40 | { 41 | dos_header_correct = false; 42 | return; 43 | } 44 | 45 | if (magic_ != mz_signature) 46 | dos_header_correct = false; 47 | } 48 | 49 | bool dos_header_t::check_dos_header() 50 | { 51 | return dos_header_correct; 52 | } 53 | 54 | /******** GETTERS *********/ 55 | pe_dos_header dos_header_t::dos_header(void) const 56 | { 57 | /* 58 | * This part corresponds to LIEF builder: 59 | Builder& Builder::operator<<(const DosHeader& dos_header) { 60 | 61 | pe_dos_header dosHeader; 62 | dosHeader.Magic = static_cast(dos_header.magic()); 63 | dosHeader.UsedBytesInTheLastPage = static_cast(dos_header.used_bytes_in_the_last_page()); 64 | dosHeader.FileSizeInPages = static_cast(dos_header.file_size_in_pages()); 65 | dosHeader.NumberOfRelocationItems = static_cast(dos_header.numberof_relocation()); 66 | dosHeader.HeaderSizeInParagraphs = static_cast(dos_header.header_size_in_paragraphs()); 67 | dosHeader.MinimumExtraParagraphs = static_cast(dos_header.minimum_extra_paragraphs()); 68 | dosHeader.MaximumExtraParagraphs = static_cast(dos_header.maximum_extra_paragraphs()); 69 | dosHeader.InitialRelativeSS = static_cast(dos_header.initial_relative_ss()); 70 | dosHeader.InitialSP = static_cast(dos_header.initial_sp()); 71 | dosHeader.Checksum = static_cast(dos_header.checksum()); 72 | dosHeader.InitialIP = static_cast(dos_header.initial_ip()); 73 | dosHeader.InitialRelativeCS = static_cast(dos_header.initial_relative_cs()); 74 | dosHeader.AddressOfRelocationTable = static_cast(dos_header.addressof_relocation_table()); 75 | dosHeader.OverlayNumber = static_cast(dos_header.overlay_number()); 76 | dosHeader.OEMid = static_cast(dos_header.oem_id()); 77 | dosHeader.OEMinfo = static_cast(dos_header.oem_info()); 78 | dosHeader.AddressOfNewExeHeader = static_cast(dos_header.addressof_new_exeheader()); 79 | 80 | const DosHeader::reserved_t& reserved = dos_header.reserved(); 81 | const DosHeader::reserved2_t& reserved2 = dos_header.reserved2(); 82 | 83 | std::copy(std::begin(reserved), std::end(reserved), std::begin(dosHeader.Reserved)); 84 | std::copy(std::begin(reserved2), std::end(reserved2), std::begin(dosHeader.Reserved2)); 85 | 86 | this->ios_.seekp(0); 87 | this->ios_.write(reinterpret_cast(&dosHeader), sizeof(pe_dos_header)); 88 | if (this->dos_stub().size() > 0 and this->build_dos_stub_) { 89 | 90 | if (sizeof(pe_dos_header) + this->dos_stub().size() > dos_header.addressof_new_exeheader()) { 91 | LOG(WARNING) << "Inconsistent 'addressof_new_exeheader' (0x" << std::hex << dos_header.addressof_new_exeheader(); 92 | } 93 | this->ios_.write(this->dos_stub()); 94 | } 95 | 96 | return *this; 97 | } 98 | */ 99 | pe_dos_header dos_header; 100 | 101 | dos_header.Magic = this->magic_; 102 | dos_header.UsedBytesInTheLastPage = this->usedBytesInTheLastPage_; 103 | dos_header.FileSizeInPages = this->fileSizeInPages_; 104 | dos_header.NumberOfRelocationItems = this->numberOfRelocation_; 105 | dos_header.HeaderSizeInParagraphs = this->headerSizeInParagraphs_; 106 | dos_header.MinimumExtraParagraphs = this->minimumExtraParagraphs_; 107 | dos_header.MaximumExtraParagraphs = this->maximumExtraParagraphs_; 108 | dos_header.InitialRelativeSS = this->initialRelativeSS_; 109 | dos_header.InitialSP = this->initialSP_; 110 | dos_header.Checksum = this->checksum_; 111 | dos_header.InitialIP = this->initialIP_; 112 | dos_header.InitialRelativeCS = this->initialRelativeCS_; 113 | dos_header.AddressOfRelocationTable = this->addressOfRelocationTable_; 114 | dos_header.OverlayNumber = this->overlayNumber_; 115 | 116 | memcpy(dos_header.Reserved, this->reserved_, 4); 117 | 118 | dos_header.OEMid = this->oEMid_; 119 | dos_header.OEMinfo = this->oEMinfo_; 120 | 121 | memcpy(dos_header.Reserved2, this->reserved2_, 10); 122 | 123 | dos_header.AddressOfNewExeHeader = this->addressOfNewExeHeader_; 124 | 125 | return dos_header; 126 | } 127 | 128 | 129 | uint16_t dos_header_t::magic(void) const 130 | { 131 | return this->magic_; 132 | } 133 | 134 | 135 | uint16_t dos_header_t::used_bytes_in_the_last_page(void) const 136 | { 137 | return this->usedBytesInTheLastPage_; 138 | } 139 | 140 | 141 | uint16_t dos_header_t::file_size_in_pages(void) const 142 | { 143 | return this->fileSizeInPages_; 144 | } 145 | 146 | 147 | uint16_t dos_header_t::numberof_relocation(void) const 148 | { 149 | return this->numberOfRelocation_; 150 | } 151 | 152 | 153 | uint16_t dos_header_t::header_size_in_paragraphs(void) const 154 | { 155 | return this->headerSizeInParagraphs_; 156 | } 157 | 158 | 159 | uint16_t dos_header_t::minimum_extra_paragraphs(void) const 160 | { 161 | return this->minimumExtraParagraphs_; 162 | } 163 | 164 | 165 | uint16_t dos_header_t::maximum_extra_paragraphs(void) const 166 | { 167 | return this->maximumExtraParagraphs_; 168 | } 169 | 170 | 171 | uint16_t dos_header_t::initial_relative_ss(void) const 172 | { 173 | return this->initialRelativeSS_; 174 | } 175 | 176 | 177 | uint16_t dos_header_t::initial_sp(void) const 178 | { 179 | return this->initialSP_; 180 | } 181 | 182 | 183 | uint16_t dos_header_t::checksum(void) const 184 | { 185 | return this->checksum_; 186 | } 187 | 188 | 189 | uint16_t dos_header_t::initial_ip(void) const 190 | { 191 | return this->initialIP_; 192 | } 193 | 194 | 195 | uint16_t dos_header_t::initial_relative_cs(void) const 196 | { 197 | return this->initialRelativeCS_; 198 | } 199 | 200 | 201 | uint16_t dos_header_t::addressof_relocation_table(void) const 202 | { 203 | return this->addressOfRelocationTable_; 204 | } 205 | 206 | 207 | uint16_t dos_header_t::overlay_number(void) const 208 | { 209 | return this->overlayNumber_; 210 | } 211 | 212 | 213 | uint16_t dos_header_t::reserved(size_t field) const 214 | { 215 | if (field >= 4) 216 | return 0; 217 | return this->reserved_[field]; 218 | } 219 | 220 | 221 | uint16_t dos_header_t::oem_id(void) const 222 | { 223 | return this->oEMid_; 224 | } 225 | 226 | 227 | uint16_t dos_header_t::oem_info(void) const 228 | { 229 | return this->oEMinfo_; 230 | } 231 | 232 | 233 | uint16_t dos_header_t::reserved2(size_t field) const 234 | { 235 | if (field >= 10) 236 | return 0; 237 | 238 | return this->reserved2_[field]; 239 | } 240 | 241 | 242 | uint32_t dos_header_t::addressof_new_exeheader(void) const 243 | { 244 | return this->addressOfNewExeHeader_; 245 | } 246 | 247 | /********** Setters *************/ 248 | void dos_header_t::magic(uint16_t magic) { 249 | this->magic_ = magic; 250 | } 251 | 252 | 253 | void dos_header_t::used_bytes_in_the_last_page(uint16_t usedBytesInTheLastPage) { 254 | this->usedBytesInTheLastPage_ = usedBytesInTheLastPage; 255 | } 256 | 257 | 258 | void dos_header_t::file_size_in_pages(uint16_t fileSizeInPages) { 259 | this->fileSizeInPages_ = fileSizeInPages; 260 | } 261 | 262 | 263 | void dos_header_t::numberof_relocation(uint16_t numberOfRelocation) { 264 | this->numberOfRelocation_ = numberOfRelocation; 265 | } 266 | 267 | 268 | void dos_header_t::header_size_in_paragraphs(uint16_t headerSizeInParagraphs) { 269 | this->headerSizeInParagraphs_ = headerSizeInParagraphs; 270 | } 271 | 272 | 273 | void dos_header_t::minimum_extra_paragraphs(uint16_t minimumExtraParagraphs) { 274 | this->minimumExtraParagraphs_ = minimumExtraParagraphs; 275 | } 276 | 277 | 278 | void dos_header_t::maximum_extra_paragraphs(uint16_t maximumExtraParagraphs) { 279 | this->maximumExtraParagraphs_ = maximumExtraParagraphs; 280 | } 281 | 282 | 283 | void dos_header_t::initial_relative_ss(uint16_t initialRelativeSS) { 284 | this->initialRelativeSS_ = initialRelativeSS; 285 | } 286 | 287 | 288 | void dos_header_t::initial_sp(uint16_t initialSP) { 289 | this->initialSP_ = initialSP; 290 | } 291 | 292 | 293 | void dos_header_t::checksum(uint16_t checksum) { 294 | this->checksum_ = checksum; 295 | } 296 | 297 | 298 | void dos_header_t::initial_ip(uint16_t initialIP) { 299 | this->initialIP_ = initialIP; 300 | } 301 | 302 | 303 | void dos_header_t::initial_relative_cs(uint16_t initialRelativeCS) { 304 | this->initialRelativeCS_ = initialRelativeCS; 305 | } 306 | 307 | 308 | void dos_header_t::addressof_relocation_table(uint16_t addressOfRelocationTable) { 309 | this->addressOfRelocationTable_ = addressOfRelocationTable; 310 | } 311 | 312 | 313 | void dos_header_t::overlay_number(uint16_t overlayNumber) { 314 | this->overlayNumber_ = overlayNumber; 315 | } 316 | 317 | 318 | void dos_header_t::reserved(const uint16_t* reserved) { 319 | size_t i; 320 | 321 | for (i = 0; i < 4; i++) 322 | this->reserved_[i] = reserved[i]; 323 | } 324 | 325 | 326 | void dos_header_t::oem_id(uint16_t oEMid) { 327 | this->oEMid_ = oEMid; 328 | } 329 | 330 | 331 | void dos_header_t::oem_info(uint16_t oEMinfo) { 332 | this->oEMinfo_ = oEMinfo; 333 | } 334 | 335 | 336 | void dos_header_t::reserved2(const uint16_t* reserved2) { 337 | size_t i; 338 | 339 | for (i = 0; i < 10; i++) 340 | this->reserved2_[i] = reserved2[i]; 341 | } 342 | 343 | 344 | void dos_header_t::addressof_new_exeheader(uint32_t addressOfNewExeHeader) { 345 | this->addressOfNewExeHeader_ = addressOfNewExeHeader; 346 | } 347 | 348 | 349 | bool dos_header_t::dump_dos_header(FILE *file_to_dump) 350 | { 351 | if (!dos_header_correct) 352 | return false; 353 | ANBU::LOGGER(file_to_dump, "================== DUMP DOS HEADER ===================\n"); 354 | ANBU::LOGGER(file_to_dump, "\t+Magic: 0x%x\n", magic_); 355 | ANBU::LOGGER(file_to_dump, "\t+Used Bytes In The LastPage: 0x%x\n", usedBytesInTheLastPage_); 356 | ANBU::LOGGER(file_to_dump, "\t+File Size In Pages: 0x%x\n", fileSizeInPages_); 357 | ANBU::LOGGER(file_to_dump, "\t+Number Of Relocation: 0x%x\n", numberOfRelocation_); 358 | ANBU::LOGGER(file_to_dump, "\t+Header Size In Paragraphs: 0x%x\n", headerSizeInParagraphs_); 359 | ANBU::LOGGER(file_to_dump, "\t+Minimum Extra Paragraphs: 0x%x\n", minimumExtraParagraphs_); 360 | ANBU::LOGGER(file_to_dump, "\t+Maximum Extra Paragraphs: 0x%x\n", maximumExtraParagraphs_); 361 | ANBU::LOGGER(file_to_dump, "\t+Initial Relative SS: 0x%x\n", initialRelativeSS_); 362 | ANBU::LOGGER(file_to_dump, "\t+Initial SP: 0x%x\n", initialSP_); 363 | ANBU::LOGGER(file_to_dump, "\t+Checksum: 0x%x\n", checksum_); 364 | ANBU::LOGGER(file_to_dump, "\t+Initial IP: 0x%x\n", initialIP_); 365 | ANBU::LOGGER(file_to_dump, "\t+Initial Relative CS: 0x%x\n", initialRelativeCS_); 366 | ANBU::LOGGER(file_to_dump, "\t+Address Of Relocation Table: 0x%x\n", addressOfRelocationTable_); 367 | ANBU::LOGGER(file_to_dump, "\t+Overlay Number: 0x%x\n", overlayNumber_); 368 | ANBU::LOGGER(file_to_dump, "\t+OEM id: 0x%x\n", oEMid_); 369 | ANBU::LOGGER(file_to_dump, "\t+OEM info: 0x%x\n", oEMinfo_); 370 | ANBU::LOGGER(file_to_dump, "\t+Address Of New Exe Header: 0x%x\n", addressOfNewExeHeader_); 371 | 372 | return true; 373 | } 374 | } -------------------------------------------------------------------------------- /Unpackers/run_pe_detector.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "run_pe_detector.h" 3 | 4 | /************* EXTERN VARIABLES *************/ 5 | extern FILE* logfile; // log file handler 6 | extern std::string unpacked_file_name; 7 | /********************** VARIABLES ****************************/ 8 | 9 | // Array for syscalls names one by one 10 | std::map g_syscall_names; 11 | // Addresses of syscalls 12 | ADDRINT SYS_NtCreateUserProcess, 13 | SYS_NtWriteVirtualMemory, 14 | SYS_NtResumeThread; 15 | ADDRINT SYS_NtDuplicateObject, 16 | SYS_NtOpenThread, 17 | SYS_NtDelayExecution; 18 | ADDRINT SYS_NtOpenProcess, 19 | SYS_NtCreateProcess, 20 | SYS_NtCreateProcessEx; 21 | ADDRINT SYS_NtAllocateVirtualMemory, 22 | SYS_NtUnmapViewOfSection, 23 | SYS_NtMapViewOfSection, 24 | SYS_NtRequestWaitReplyPortHook; 25 | 26 | ADDRINT entry_point; 27 | 28 | map> process_data; 29 | write_memory_t* write_mem = nullptr; 30 | 31 | int g_process_handle_count = 0; 32 | int g_thread_handle_count = 0; 33 | HANDLE g_process_handle[256] = { 0 }; 34 | HANDLE g_thread_handle[256] = { 0 }; 35 | 36 | // code from rreat library 37 | void enum_syscalls() 38 | { 39 | // as this is the beginning of execution under a 40 | // sandbox environment take ntdll is correct 41 | HMODULE image = WINDOWS::GetModuleHandle("ntdll.dll"); 42 | WINDOWS::PIMAGE_DOS_HEADER dos_header = (WINDOWS::PIMAGE_DOS_HEADER) image; 43 | WINDOWS::PIMAGE_NT_HEADERS nt_header = (WINDOWS::PIMAGE_NT_HEADERS) ((WINDOWS::LONG)dos_header + dos_header->e_lfanew); 44 | WINDOWS::PIMAGE_DATA_DIRECTORY data_directory = (WINDOWS::PIMAGE_DATA_DIRECTORY)(&nt_header->OptionalHeader.DataDirectory); 45 | WINDOWS::PIMAGE_EXPORT_DIRECTORY export_directory = (WINDOWS::PIMAGE_EXPORT_DIRECTORY)((WINDOWS::LONG)dos_header + data_directory->VirtualAddress); 46 | 47 | 48 | WINDOWS::PDWORD address_of_names = (WINDOWS::PDWORD)((WINDOWS::LONG)dos_header + export_directory->AddressOfNames); 49 | WINDOWS::PDWORD address_of_functions = (WINDOWS::PDWORD)((WINDOWS::LONG)dos_header + export_directory->AddressOfFunctions); 50 | WINDOWS::PWORD address_of_name_ordinals = (WINDOWS::PWORD)((WINDOWS::LONG)dos_header + export_directory->AddressOfNameOrdinals); 51 | size_t number_of_names = MIN(export_directory->NumberOfFunctions, export_directory->NumberOfNames); 52 | 53 | ANBU::LOGGER(logfile, "<------------------- Getting syscalls ------------------->\n"); 54 | for (size_t i = 0; i < number_of_names; i++) 55 | { 56 | const char *name = (const char *)((WINDOWS::LONG)dos_header + address_of_names[i]); 57 | WINDOWS::PBYTE addr = (WINDOWS::PBYTE)((WINDOWS::LONG)dos_header + address_of_functions[address_of_name_ordinals[i]]); 58 | 59 | if (!memcmp(name, "Zw", 2) || !memcmp(name, "Nt", 2)) 60 | { 61 | /* 62 | * Check for the next instructions: 63 | * mov eax, syscall_number ; mov ecx, some_value 64 | * mov eax, syscall_number ; xor ecx, ecx 65 | * mov eax, syscall_number ; mov edx, 0x7ffe0300 66 | */ 67 | if (*addr == 0xb8 && 68 | (addr[5] == 0xb9 || 69 | addr[5] == 0x33 || 70 | addr[5] == 0xba)) 71 | { 72 | // get syscall number from code 73 | unsigned long syscall_number = *(WINDOWS::PDWORD)(addr + 1); 74 | ANBU::LOGGER_INFO(logfile, "Saved syscall 0x%x(%s)\n", syscall_number, name); 75 | g_syscall_names[syscall_number] = name; 76 | } 77 | } 78 | } 79 | ANBU::LOGGER(logfile, "<-------------------------------------->\n"); 80 | } 81 | 82 | 83 | unsigned long syscall_name_to_number(const char *name) 84 | { 85 | for (size_t i = 0; i < g_syscall_names.size(); i++) 86 | { 87 | if (g_syscall_names[i] != NULL && 88 | // avoid Nt or Zw 89 | !strcmp(g_syscall_names[i] + 2, name + 2)) 90 | return i; 91 | } 92 | ANBU::LOGGER_ERROR("The syscall %s was not found\n", name); 93 | return 0; 94 | } 95 | 96 | 97 | void init_common_syscalls() 98 | { 99 | /****** Function used to create process suspended ******/ 100 | SYS_NtCreateUserProcess = syscall_name_to_number("NtCreateUserProcess"); 101 | SYS_NtCreateProcess = syscall_name_to_number("NtCreateProcess"); 102 | SYS_NtCreateProcessEx = syscall_name_to_number("NtCreateProcessEx"); 103 | /****** Function to write new content on new process ******/ 104 | SYS_NtWriteVirtualMemory = syscall_name_to_number("NtWriteVirtualMemory"); 105 | /****** Function to restart execution of suspended process ******/ 106 | SYS_NtResumeThread = syscall_name_to_number("NtResumeThread"); 107 | /****** Function to open processes or threads *******/ 108 | SYS_NtOpenProcess = syscall_name_to_number("NtOpenProcess"); 109 | SYS_NtOpenThread = syscall_name_to_number("NtOpenThread"); 110 | /****** Function to allocate memory in remote or local process ******/ 111 | SYS_NtAllocateVirtualMemory = syscall_name_to_number("NtAllocateVirtualMemory"); 112 | /****** Other functions *******/ 113 | SYS_NtUnmapViewOfSection = syscall_name_to_number("NtUnmapViewOfSection"); 114 | SYS_NtMapViewOfSection = syscall_name_to_number("NtMapViewOfSection"); 115 | SYS_NtRequestWaitReplyPortHook = syscall_name_to_number("NtRequestWaitReplyPortHook"); 116 | SYS_NtDuplicateObject = syscall_name_to_number("NtDuplicateObject"); 117 | SYS_NtDelayExecution = syscall_name_to_number("NtDelayExecution"); 118 | } 119 | 120 | 121 | void syscall_get_arguments(CONTEXT *ctx, SYSCALL_STANDARD std, int count, ...) 122 | { 123 | va_list args; 124 | va_start(args, count); 125 | 126 | for (int i = 0; i < count; i++) 127 | { 128 | int index = va_arg(args, int); 129 | ADDRINT *ptr = va_arg(args, ADDRINT *); 130 | *ptr = PIN_GetSyscallArgument(ctx, std, index); 131 | } 132 | 133 | va_end(args); 134 | } 135 | 136 | 137 | void syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 138 | { 139 | OBJECT_ATTRIBUTES* object_attributes; 140 | RTL_USER_PROCESS_PARAMETERS* process_parameters; 141 | unsigned long syscall_number; 142 | map>::iterator it; 143 | binary_t* binary_; 144 | size_t index_base_address; 145 | 146 | // get the syscall number 147 | syscall_number = PIN_GetSyscallNumber(ctx, std); 148 | index_base_address = -1; 149 | 150 | // if the syscall is not in our list, you can leave 151 | if (g_syscall_names.find(syscall_number) != g_syscall_names.end()) 152 | { 153 | const char *name = g_syscall_names[syscall_number]; 154 | 155 | syscall_t *sc = &((syscall_t *)v)[thread_id]; 156 | sc->syscall_number = syscall_number; 157 | 158 | if (syscall_number == SYS_NtCreateUserProcess) 159 | { 160 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 161 | 162 | ULONG create_thread_flags; 163 | 164 | syscall_get_arguments(ctx, std, 4, 0, &sc->arg0, 1, &sc->arg1, 8, &process_parameters, 7, &create_thread_flags); 165 | 166 | ANBU::LOGGER_INFO(logfile, "Image_name: %S\ncommand_line: %S\n", 167 | process_parameters->ImagePathName.Buffer, 168 | process_parameters->CommandLine.Buffer); 169 | ANBU::LOGGER_INFO(logfile, "Process_flags: 0x%x\nthread_flags: 0x%x\n", 170 | PIN_GetSyscallArgument(ctx, std, 6), 171 | PIN_GetSyscallArgument(ctx, std, 7)); 172 | } 173 | else if (syscall_number == SYS_NtCreateProcess || 174 | syscall_number == SYS_NtCreateProcessEx) 175 | { 176 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 177 | syscall_get_arguments(ctx, std, 2, 0, &sc->arg0, 2, &object_attributes); 178 | 179 | if (object_attributes != NULL && 180 | object_attributes->ObjectName != NULL) 181 | { 182 | ANBU::LOGGER_INFO(logfile, L"Process execute image_name: %S\n", object_attributes->ObjectName->Buffer); 183 | } 184 | } 185 | else if (syscall_number == SYS_NtWriteVirtualMemory) 186 | { 187 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 188 | 189 | HANDLE process_handle; 190 | char *base_address, *buffer; 191 | 192 | syscall_get_arguments(ctx, std, 5, 0, &process_handle, 1, &base_address, 2, &buffer, 3, &sc->arg3, 4, &sc->arg4); 193 | 194 | ANBU::LOGGER_INFO(logfile, "Process Handle: 0x%x\nBase Address to write: 0x%x\nBuffer with data to write: 0x%x\nSize: 0x%x\n", (unsigned int)process_handle, (unsigned int)base_address, (unsigned int)buffer, (unsigned int)sc->arg3); 195 | 196 | write_mem = new write_memory_t(); 197 | 198 | write_mem->address = (ADDRINT)base_address; 199 | write_mem->size = (size_t)sc->arg3; 200 | 201 | write_mem->data.resize((size_t)sc->arg3); 202 | 203 | if (PIN_SafeCopy(write_mem->data.begin(), (const VOID*)buffer, (size_t)sc->arg3) != (size_t)sc->arg3) 204 | { 205 | ANBU::LOGGER_ERROR(logfile, "Not possible to read from 0x%x\n", (unsigned int)buffer); 206 | 207 | PIN_ExitProcess(-1); 208 | exit(-1); 209 | } 210 | process_data[process_handle].push_back(*write_mem); 211 | } 212 | else if (syscall_number == SYS_NtResumeThread) 213 | { 214 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 215 | 216 | WINDOWS::TerminateThread(g_thread_handle[0], 0); 217 | WINDOWS::TerminateProcess(g_process_handle[0], 0); 218 | 219 | ANBU::LOGGER_INFO(logfile, "Finished runPE process... Dumping\n"); 220 | 221 | for (it = process_data.begin(); it != process_data.end(); it++) 222 | { 223 | ANBU::LOGGER_INFO(logfile, "Dumping file for process handle: 0x%x\n", (unsigned int)it->first); 224 | 225 | for (size_t index_vector = 0; index_vector < it->second.size(); index_vector++) 226 | { 227 | // discover which one could be the index of the base address 228 | PIN_LockClient(); 229 | binary_ = new binary_t(&it->second.at(index_vector).data); 230 | 231 | if (binary_->analyze_binary()) 232 | { 233 | index_base_address = index_vector; 234 | break; 235 | } 236 | 237 | delete binary_; 238 | } 239 | 240 | if (index_base_address == -1) 241 | { 242 | PIN_UnlockClient(); 243 | ANBU::LOGGER_ERROR(logfile, "Not found base memory in process with handle: 0x%x\n", (unsigned int)it->first); 244 | 245 | delete binary_; 246 | continue; 247 | } 248 | 249 | char file_name[MAX_PATH]; 250 | if (unpacked_file_name.size() != 0) 251 | snprintf(file_name, sizeof(file_name) - 1, "%s", unpacked_file_name.c_str()); 252 | else 253 | snprintf(file_name, sizeof(file_name) - 1, "file.base-0x%x.entry.bin", (uintptr_t)binary_->optional_header()->imagebase()); 254 | 255 | if(!binary_->write(file_name, it->second.at(index_base_address).data, it->second)) 256 | { 257 | ANBU::LOGGER_ERROR(logfile, "Not possible to dump process with handle: 0x%x\n", (unsigned int)it->first); 258 | } 259 | else 260 | { 261 | ANBU::LOGGER_INFO(logfile, "Success dumping process with handle %x and base 0x%x", (unsigned int)it->first, (unsigned int)it->second.at(index_base_address).address); 262 | } 263 | 264 | PIN_UnlockClient(); 265 | delete binary_; 266 | } 267 | 268 | exit(0); 269 | } 270 | else if (syscall_number == SYS_NtDuplicateObject) 271 | { 272 | ANBU::LOGGER_ERROR("DuplicateHandle() not implemented yet!\n"); 273 | } 274 | else if (syscall_number == SYS_NtOpenThread) 275 | { 276 | ANBU::LOGGER_ERROR("OpenThread() not implemented yet!\n"); 277 | } 278 | else if (syscall_number == SYS_NtOpenProcess) 279 | { 280 | ANBU::LOGGER_ERROR("OpenProcess() not implemented yet!\n"); 281 | } 282 | else if (syscall_number == SYS_NtDelayExecution) 283 | { 284 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 285 | WINDOWS::LARGE_INTEGER *delay_interval; 286 | syscall_get_arguments(ctx, std, 1, 1, &delay_interval); 287 | if (delay_interval->QuadPart != 0) 288 | { 289 | ANBU::LOGGER_INFO(logfile, "Skipped Sleep(%d)\n", (int)-delay_interval->QuadPart / 10000); 290 | } 291 | delay_interval->QuadPart = 0; // modify!!! 292 | } 293 | else if (syscall_number == SYS_NtUnmapViewOfSection) 294 | { 295 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 296 | 297 | syscall_get_arguments(ctx, std, 2, 0, &sc->arg0, 1, &sc->arg1); 298 | 299 | ANBU::LOGGER_INFO(logfile, "Unmaped section 0x%x in process handle %x\n", (unsigned int)sc->arg0, (unsigned int)sc->arg1); 300 | } 301 | else if (syscall_number == SYS_NtAllocateVirtualMemory) 302 | { 303 | ANBU::LOGGER_INFO(logfile, "Syscall called 0x%x(%s) thread 0x%x \n", syscall_number, name, thread_id); 304 | 305 | ADDRINT address_to_allocate; 306 | WINDOWS::SIZE_T size_to_allocate; 307 | syscall_get_arguments(ctx, std, 3, 0, &sc->arg0, 1, &sc->arg1, 3, &sc->arg2); 308 | 309 | PIN_SafeCopy((VOID*)&address_to_allocate, (const VOID*)sc->arg1, sizeof(ADDRINT)); 310 | PIN_SafeCopy((VOID*)&size_to_allocate, (const VOID*)sc->arg2, sizeof(WINDOWS::SIZE_T)); 311 | 312 | ANBU::LOGGER_INFO(logfile, "Allocated memory address 0x%x, with size 0x%x, in process handle %x\n", (unsigned int)address_to_allocate, 313 | (unsigned int)size_to_allocate, 314 | (unsigned int)sc->arg0); 315 | } 316 | } 317 | } 318 | 319 | 320 | void syscall_exit(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 321 | { 322 | syscall_t *sc = &((syscall_t*)v)[thread_id]; 323 | proc_info_t* proc_info = proc_info_t::get_instance(); 324 | 325 | 326 | if (sc->syscall_number == SYS_NtCreateUserProcess) 327 | { 328 | g_process_handle[g_process_handle_count++] = *(HANDLE*)sc->arg0; 329 | g_thread_handle[g_thread_handle_count++] = *(HANDLE*)sc->arg1; 330 | } 331 | else if (sc->syscall_number == SYS_NtCreateProcess || 332 | sc->syscall_number == SYS_NtCreateProcessEx) 333 | { 334 | g_process_handle[g_process_handle_count++] = *(HANDLE*)sc->arg0; 335 | } 336 | else if (sc->syscall_number == SYS_NtAllocateVirtualMemory) 337 | { 338 | heap_zone_t hz; 339 | WINDOWS::PVOID base_address_pointer = reinterpret_cast(sc->arg1); 340 | 341 | if (base_address_pointer == nullptr) 342 | return; 343 | 344 | WINDOWS::PSIZE_T region_size_address = reinterpret_cast(sc->arg2); 345 | 346 | if (region_size_address == nullptr) 347 | return; 348 | 349 | ADDRINT heap_address = *(reinterpret_cast(base_address_pointer)); 350 | WINDOWS::SIZE_T region_size = *(reinterpret_cast(region_size_address)); 351 | 352 | hz.begin = heap_address; 353 | hz.size = region_size; 354 | hz.end = region_size + heap_address; 355 | hz.version = 0; 356 | 357 | char heap_key_address[30]; 358 | char heap_key_size[30]; 359 | 360 | snprintf(heap_key_address, 30, "%x", heap_address); 361 | snprintf(heap_key_size, 30, "%x", region_size); 362 | 363 | std::string heap_key = heap_key_address; 364 | heap_key += heap_key_size; 365 | 366 | std::string hz_md5 = md5(heap_key); 367 | 368 | ANBU::LOGGER_INFO("NtAllocateVirtualMemoryHook insert in Heap Zone %08x -> %08x MD5(begin_addr+end_addr): %s\n", hz.begin, hz.end, hz_md5.c_str()); 369 | proc_info->insert_heap_zone(hz_md5, hz); 370 | } 371 | else if (sc->syscall_number == SYS_NtMapViewOfSection) 372 | { 373 | WINDOWS::PVOID *pbase_address = reinterpret_cast(sc->arg2); 374 | 375 | if (pbase_address == nullptr) 376 | return; 377 | 378 | ADDRINT base_address = *(reinterpret_cast(pbase_address)); 379 | 380 | proc_info->add_mapped_files_address(base_address); 381 | } 382 | else if (sc->syscall_number == SYS_NtRequestWaitReplyPortHook) 383 | { 384 | //The NtRequestWaitReplyPortHook allocates 4 memory pages of type MEM_MAPPED so we need to rescan the memory after it has been performed 385 | ANBU::LOGGER_INFO("Found a NtRequestWaitReplyPort\n"); 386 | proc_info->set_current_mapped_files(); 387 | } 388 | } 389 | 390 | 391 | bool compare_by_address(const write_memory_t& a, const write_memory_t& b) 392 | { 393 | return a.address < b.address; 394 | } -------------------------------------------------------------------------------- /MyPinTool.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {639EF517-FCFC-408E-9500-71F0DC0458DB} 23 | MyPinTool 24 | Win32Proj 25 | 10.0.17763.0 26 | ANBU 27 | 28 | 29 | 30 | DynamicLibrary 31 | MultiByte 32 | true 33 | v141 34 | false 35 | 36 | 37 | DynamicLibrary 38 | MultiByte 39 | v141 40 | false 41 | 42 | 43 | DynamicLibrary 44 | MultiByte 45 | true 46 | v141 47 | 48 | 49 | DynamicLibrary 50 | MultiByte 51 | v141 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | <_ProjectFileVersion>10.0.40219.1 71 | $(ProjectDir)$(Configuration)\ 72 | $(Configuration)\ 73 | false 74 | false 75 | $(ProjectDir)$(Platform)\$(Configuration)\ 76 | $(Platform)\$(Configuration)\ 77 | false 78 | false 79 | $(ProjectDir)$(Configuration)\ 80 | $(Configuration)\ 81 | false 82 | false 83 | $(ProjectDir)$(Platform)\$(Configuration)\ 84 | $(Platform)\$(Configuration)\ 85 | false 86 | false 87 | AllRules.ruleset 88 | 89 | 90 | AllRules.ruleset 91 | 92 | 93 | AllRules.ruleset 94 | 95 | 96 | AllRules.ruleset 97 | 98 | 99 | 100 | 101 | 102 | /GR- /GS- /EHs- /EHa- /FP:strict /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 103 | Disabled 104 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-ia32\include;..\..\..\extras\components\include;..\..\..\extras\stlport\include;..\..\..\extras;..\..\..\extras\libstdc++\include;..\..\..\extras\crt\include;..\..\..\extras\crt;..\..\..\extras\crt\include\arch-x86;..\..\..\extras\crt\include\kernel\uapi;..\..\..\extras\crt\include\kernel\uapi\asm-x86;F:\Projects\PINTalk\pin\source\tools\Generic_Unpacker;F:\Projects\PINTalk\pin\source\tools\Generic_Unpacker\PE;F:\Projects\PINTalk\pin\source\tools\Generic_Unpacker\Unpackers;%(AdditionalIncludeDirectories) 105 | TARGET_IA32;HOST_IA32;TARGET_WINDOWS;WIN32;__PIN__=1;PIN_CRT=1;__i386__;_WINDOWS_H_PATH_ 106 | false 107 | 108 | 109 | Default 110 | MultiThreaded 111 | false 112 | true 113 | NotSet 114 | false 115 | 116 | 117 | Level3 118 | ProgramDatabase 119 | 4530;%(DisableSpecificWarnings) 120 | 121 | 122 | /export:main %(AdditionalOptions) 123 | pin.lib;xed.lib;pinvm.lib;kernel32.lib;stlport-static.lib;m-static.lib;c-static.lib;os-apis.lib;ntdll-32.lib 124 | ..\..\..\ia32\lib;..\..\..\ia32\lib-ext;..\..\..\extras\xed-ia32\lib;..\..\..\ia32\runtime\pincrt;%(AdditionalLibraryDirectories) 125 | true 126 | %(IgnoreSpecificDefaultLibraries) 127 | true 128 | NotSet 129 | false 130 | Ptrace_DllMainCRTStartup%4012 131 | 0x55000000 132 | MachineX86 133 | true 134 | 135 | 136 | 137 | 138 | X64 139 | 140 | 141 | /GR- /GS- /EHs- /EHa- /FP:strict /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 142 | Disabled 143 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-intel64\include;..\..\..\extras\components\include;..\..\..\extras\stlport\include;..\..\..\extras;..\..\..\extras\libstdc++\include;..\..\..\extras\crt\include;..\..\..\extras\crt;..\..\..\extras\crt\include\arch-x86_64;..\..\..\extras\crt\include\kernel\uapi;..\..\..\extras\crt\include\kernel\uapi\asm-x86;%(AdditionalIncludeDirectories) 144 | TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;WIN32;__PIN__=1;PIN_CRT=1;__LP64__ 145 | false 146 | 147 | 148 | Default 149 | MultiThreaded 150 | false 151 | true 152 | false 153 | 154 | 155 | Level3 156 | ProgramDatabase 157 | 4530;%(DisableSpecificWarnings) 158 | 159 | 160 | /export:main %(AdditionalOptions) 161 | pin.lib;xed.lib;pinvm.lib;kernel32.lib;stlport-static.lib;m-static.lib;c-static.lib;os-apis.lib;ntdll-64.lib 162 | ..\..\..\intel64\lib;..\..\..\intel64\lib-ext;..\..\..\extras\xed-intel64\lib;..\..\..\intel64\runtime\pincrt;%(AdditionalLibraryDirectories) 163 | true 164 | %(IgnoreSpecificDefaultLibraries) 165 | true 166 | NotSet 167 | false 168 | Ptrace_DllMainCRTStartup 169 | 0xC5000000 170 | MachineX64 171 | true 172 | 173 | 174 | 175 | 176 | /GR- /GS- /EHs- /EHa- /FP:strict /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 177 | false 178 | false 179 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-ia32\include\xed;..\..\..\extras\components\include;..\..\..\extras\stlport\include;..\..\..\extras;..\..\..\extras\libstdc++\include;..\..\..\extras\crt\include;..\..\..\extras\crt;..\..\..\extras\crt\include\arch-x86;..\..\..\extras\crt\include\kernel\uapi;..\..\..\extras\crt\include\kernel\uapi\asm-x86;.;.\PE;.\Unpackers;.\anti-methods;.\Unpackers\heuristics;%(AdditionalIncludeDirectories) 180 | TARGET_IA32;HOST_IA32;TARGET_WINDOWS;WIN32;__PIN__=1;PIN_CRT=1;__i386__;_WINDOWS_H_PATH_ 181 | false 182 | 183 | 184 | Default 185 | MultiThreaded 186 | false 187 | true 188 | NotSet 189 | false 190 | 191 | 192 | Level3 193 | ProgramDatabase 194 | 4530;%(DisableSpecificWarnings) 195 | Disabled 196 | 197 | 198 | /export:main %(AdditionalOptions) 199 | pin.lib;xed.lib;pinvm.lib;kernel32.lib;stlport-static.lib;m-static.lib;c-static.lib;os-apis.lib;ntdll-32.lib;crtbeginS.obj 200 | ..\..\..\ia32\lib;..\..\..\ia32\lib-ext;..\..\..\extras\xed-ia32\lib;..\..\..\ia32\runtime\pincrt;%(AdditionalLibraryDirectories) 201 | true 202 | %(IgnoreSpecificDefaultLibraries) 203 | true 204 | NotSet 205 | true 206 | 207 | 208 | 209 | 210 | Ptrace_DllMainCRTStartup%4012 211 | 0x55000000 212 | MachineX86 213 | false 214 | 215 | 216 | 217 | 218 | X64 219 | 220 | 221 | /GR- /GS- /EHs- /EHa- /FP:strict /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 222 | false 223 | false 224 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-intel64\include;..\..\..\extras\components\include;..\..\..\extras\stlport\include;..\..\..\extras;..\..\..\extras\libstdc++\include;..\..\..\extras\crt\include;..\..\..\extras\crt;..\..\..\extras\crt\include\arch-x86_64;..\..\..\extras\crt\include\kernel\uapi;..\..\..\extras\crt\include\kernel\uapi\asm-x86;%(AdditionalIncludeDirectories) 225 | TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;WIN32;__PIN__=1;PIN_CRT=1;__LP64__ 226 | false 227 | 228 | 229 | Default 230 | MultiThreaded 231 | false 232 | true 233 | false 234 | 235 | 236 | Level3 237 | 238 | 239 | 4530;%(DisableSpecificWarnings) 240 | 241 | 242 | /export:main %(AdditionalOptions) 243 | pin.lib;xed.lib;pinvm.lib;kernel32.lib;stlport-static.lib;m-static.lib;c-static.lib;os-apis.lib;ntdll-64.lib 244 | ..\..\..\intel64\lib;..\..\..\intel64\lib-ext;..\..\..\extras\xed-intel64\lib;..\..\..\intel64\runtime\pincrt;%(AdditionalLibraryDirectories) 245 | true 246 | %(IgnoreSpecificDefaultLibraries) 247 | true 248 | NotSet 249 | true 250 | 251 | 252 | 253 | 254 | Ptrace_DllMainCRTStartup 255 | 0xC5000000 256 | MachineX64 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | --------------------------------------------------------------------------------