├── ThreadMapper.cpp ├── install32_64 ├── excluded.txt ├── stop_offsets.txt ├── .gitignore ├── dll_load32.exe ├── dll_load64.exe ├── kdb_check.exe ├── pe_check.exe ├── syscall_extract.exe ├── params.txt ├── delete_menu.reg ├── README.md ├── sudo.vbs ├── add_menu.reg ├── TinyTracer.ini ├── pin_attach.bat ├── tiny_runner.sh ├── run_me.bat └── run_me_benchmark.bat ├── TrackReturns.cpp ├── .gitignore ├── ExportsInfo.h ├── move_dlls.bat ├── AntiVm.h ├── PinLocker.h ├── TinyTracer.h ├── AntiDebug.h ├── TrackReturns.h ├── ModuleInfo.h ├── makefile ├── make_linux.sh ├── DisasmCache.h ├── .appveyor.yml ├── ProcessInfo.h ├── Util.h ├── makefile.rules ├── TraceLog.h ├── ProcessInfo.cpp ├── ModuleInfo.cpp ├── FuncWatch.cpp ├── EvasionWatch.h ├── EvasionWatch.cpp ├── Util.cpp ├── TraceLog.cpp ├── FuncWatch.h ├── README.md ├── ExportsInfo.cpp ├── mini_pe.h ├── ThreadMapper.h ├── Settings.h ├── Crc.h ├── Settings.cpp ├── AntiVm.cpp ├── LICENSE.txt ├── TinyTracer_Pin3.25.vcxproj └── TinyTracer.vcxproj /ThreadMapper.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /install32_64/excluded.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /install32_64/stop_offsets.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /install32_64/.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.so 3 | *.bak 4 | syscalls.txt 5 | -------------------------------------------------------------------------------- /TrackReturns.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/tiny_tracer/HEAD/TrackReturns.cpp -------------------------------------------------------------------------------- /install32_64/dll_load32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/tiny_tracer/HEAD/install32_64/dll_load32.exe -------------------------------------------------------------------------------- /install32_64/dll_load64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/tiny_tracer/HEAD/install32_64/dll_load64.exe -------------------------------------------------------------------------------- /install32_64/kdb_check.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/tiny_tracer/HEAD/install32_64/kdb_check.exe -------------------------------------------------------------------------------- /install32_64/pe_check.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/tiny_tracer/HEAD/install32_64/pe_check.exe -------------------------------------------------------------------------------- /install32_64/syscall_extract.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/tiny_tracer/HEAD/install32_64/syscall_extract.exe -------------------------------------------------------------------------------- /install32_64/params.txt: -------------------------------------------------------------------------------- 1 | kernel32;LoadLibraryW;1 2 | kernel32;LoadLibraryA;1 3 | kernel32;GetProcAddress;2 4 | advapi32;RegQueryValueW;3 5 | kernel32;CreateFileW;6 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | *.opensdf 3 | *.sdf 4 | *.suo 5 | *.sln 6 | *.user 7 | *.bak 8 | x64/ 9 | Release 10 | Debug 11 | obj-ia32 12 | obj-intel64 13 | */my_paths.h 14 | -------------------------------------------------------------------------------- /ExportsInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | #include 5 | #include 6 | 7 | namespace ExportsInfo 8 | { 9 | size_t addFromFile(IMG& img); 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /install32_64/delete_menu.reg: -------------------------------------------------------------------------------- 1 | REGEDIT4 2 | 3 | [-HKEY_CLASSES_ROOT\*\shell\PIN_run] 4 | 5 | [-HKEY_CLASSES_ROOT\exefile\shell\PIN_run] 6 | 7 | [-HKEY_CLASSES_ROOT\dllfile\shell\PIN_run] 8 | 9 | [-HKEY_CLASSES_ROOT\exefile\shell\PIN_run_admin] 10 | 11 | [-HKEY_CLASSES_ROOT\dllfile\shell\PIN_run_admin] -------------------------------------------------------------------------------- /move_dlls.bat: -------------------------------------------------------------------------------- 1 | rem First, compile the 32 and 64 bit version of TinyTracer (in a Release mode). Then, you can use this script to copy them into the directory with the run_me.bat (default: install32_64). 2 | set INSTALL_DIR=install32_64 3 | move Release\TinyTracer.dll %INSTALL_DIR%\TinyTracer32.dll 4 | move x64\Release\TinyTracer.dll %INSTALL_DIR%\TinyTracer64.dll 5 | pause -------------------------------------------------------------------------------- /AntiVm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | //* ==================================================================== */ 6 | // Prototypes 7 | /* ===================================================================== */ 8 | namespace AntiVm { 9 | VOID MonitorAntiVmFunctions(IMG Image); 10 | VOID MonitorSyscallEntry(THREADID tid, const CHAR* name, const CONTEXT* ctxt, SYSCALL_STANDARD std, const ADDRINT Address); 11 | VOID MonitorSyscallExit(THREADID tid, const CHAR* name, const CONTEXT* ctxt, SYSCALL_STANDARD std, const ADDRINT Address); 12 | VOID InstrumentCPUIDCheck(INS ins); 13 | }; 14 | -------------------------------------------------------------------------------- /PinLocker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | /*! 6 | * A locker class. 7 | */ 8 | class PinLocker 9 | { 10 | public: 11 | PinLocker() 12 | { 13 | PIN_LockClient(); 14 | } 15 | 16 | ~PinLocker() 17 | { 18 | PIN_UnlockClient(); 19 | } 20 | }; 21 | 22 | //--- 23 | 24 | class PinDataLock 25 | { 26 | public: 27 | PinDataLock(PIN_LOCK* lock) 28 | : m_lock(lock) 29 | { 30 | PIN_GetLock(m_lock, PIN_GetTid()); 31 | } 32 | 33 | ~PinDataLock() 34 | { 35 | PIN_ReleaseLock(m_lock); 36 | } 37 | 38 | private: 39 | PIN_LOCK* m_lock; 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /TinyTracer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | #include "TraceLog.h" 6 | #include "Settings.h" 7 | #include 8 | 9 | extern Settings m_Settings; 10 | extern TraceLog traceLog; 11 | 12 | enum class WatchedType { 13 | NOT_WATCHED = 0, 14 | WATCHED_MY_MODULE, 15 | WATCHED_SHELLCODE 16 | }; 17 | 18 | WatchedType isWatchedAddress(const ADDRINT Address); 19 | std::wstring paramToStr(VOID* arg1); 20 | size_t getReadableMemSize(VOID* ptr); 21 | BOOL isValidReadPtr(VOID* arg1); 22 | BOOL fetchInterruptID(const ADDRINT Address, int& intID); 23 | 24 | VOID LogMsgAtAddress(const WatchedType wType, const ADDRINT Address, const char* label, const char* msg, const char* link=nullptr); 25 | -------------------------------------------------------------------------------- /AntiDebug.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | //* ==================================================================== */ 6 | // Prototypes 7 | /* ===================================================================== */ 8 | namespace AntiDbg { 9 | VOID WatchMemoryAccess(ADDRINT addr, UINT32 size, const ADDRINT insAddr); 10 | VOID WatchThreadStart(THREADID threadid, CONTEXT* ctxt, INT32 flags, VOID* v); 11 | VOID WatchCompareSoftBrk(ADDRINT Address, UINT64 immVal); 12 | VOID MonitorAntiDbgFunctions(IMG Image); 13 | VOID MonitorSyscallEntry(const THREADID tid, const CHAR* name, const CONTEXT* ctxt, SYSCALL_STANDARD std, const ADDRINT Address); 14 | VOID InterruptCheck(const CONTEXT* ctxt); 15 | VOID InstrumentFlagsCheck(INS ins); 16 | }; 17 | -------------------------------------------------------------------------------- /TrackReturns.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | /* ===================================================================== */ 5 | // Utilities for tracking API/system calls and returns 6 | /* ===================================================================== */ 7 | 8 | namespace RetTracker 9 | { 10 | VOID InitTracker(); 11 | 12 | VOID InitTrackerForThread(THREADID tid); 13 | 14 | VOID LogCallDetails(const ADDRINT Address, const CHAR* name, uint32_t argCount, 15 | VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, 16 | VOID* arg5, VOID* arg6, VOID* arg7, VOID* arg8, 17 | VOID* arg9, VOID* arg10, VOID* arg11 18 | ); 19 | 20 | VOID HandleFunctionReturn(const THREADID tid, const ADDRINT returnIp, const ADDRINT rawRetVal); 21 | }; 22 | -------------------------------------------------------------------------------- /ModuleInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | #include 6 | 7 | #define UNKNOWN_ADDR ~ADDRINT(0) 8 | 9 | struct s_module { 10 | std::string name; 11 | ADDRINT start; 12 | ADDRINT end; 13 | bool is_valid; 14 | }; 15 | 16 | bool init_section(s_module §ion, const ADDRINT &ImageBase, const SEC &sec); 17 | 18 | const s_module* get_by_addr(ADDRINT Address, std::map &modules); 19 | 20 | std::string get_func_at(ADDRINT callAddr, ADDRINT&diff); 21 | 22 | ADDRINT get_mod_base(ADDRINT Address); 23 | 24 | ADDRINT get_base(ADDRINT Address); 25 | 26 | ADDRINT addr_to_rva(ADDRINT Address); 27 | 28 | ADDRINT query_region_base(ADDRINT memoryAddr); 29 | 30 | std::string get_unmangled_name(RTN rtn); 31 | 32 | RTN find_by_unmangled_name(IMG img, const CHAR* fName); 33 | 34 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2004-2013 Intel Corporation. 3 | # SPDX-License-Identifier: MIT 4 | # 5 | 6 | ############################################################## 7 | # 8 | # DO NOT EDIT THIS FILE! 9 | # 10 | ############################################################## 11 | 12 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 13 | ifdef PIN_ROOT 14 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 15 | else 16 | CONFIG_ROOT := ../Config 17 | endif 18 | include $(CONFIG_ROOT)/makefile.config 19 | include makefile.rules 20 | include $(TOOLS_ROOT)/Config/makefile.default.rules 21 | 22 | ############################################################## 23 | # 24 | # DO NOT EDIT THIS FILE! 25 | # 26 | ############################################################## 27 | -------------------------------------------------------------------------------- /install32_64/README.md: -------------------------------------------------------------------------------- 1 | # Installation on Windows 2 | 3 | 0. Put the compiled tools in this directory, renamed accordingly: 4 | - TinyTracer32.dll (32-bit build) 5 | - TinyTracer64.dll (64-bit build) 6 | 1. Edit the run_me.bat: 7 | - Replace PIN_DIR (default: C:\pin) with your own path to the Pin directory. 8 | - Replace PIN_TOOLS_DIR (default: C:\pin\source\tools\tiny_tracer\install32_64\) with the path to the folder containing this bundle (scripts, tools + other utils). 9 | 2. Edit add_menu.reg and replace the path to the run_me.bat with its actual path (in your PIN_TOOLS_DIR). 10 | 3. Run add_menu.reg to add the Pin tool to the context menu 11 | 4. Now you can trace any EXE by clicking "Run with PIN" from the context menu. 12 | 5. Whenever you want to uninstall it, just run "delete_menu.reg" 13 | 14 | # Installation on Linux 15 | 16 | Read the instructions inside `tiny_runner.sh` 17 | -------------------------------------------------------------------------------- /install32_64/sudo.vbs: -------------------------------------------------------------------------------- 1 | 'sudo.vbs by @waaaaRapy: https://gist.github.com/waaaaRapy/10463764 2 | 3 | Option Explicit 4 | If WScript.Arguments.Count = 0 Then 5 | WScript.Echo "Usage: sudo program [arg1 arg2 ...]" & vbCrLf & _ 6 | "Run `program` with paramators as root in new console window" 7 | Else 8 | Dim ShellApp, WshShell 9 | Dim cmd, varg, i 10 | Set WshShell = CreateObject("WScript.Shell") 11 | cmd = WshShell.ExpandEnvironmentStrings("%COMSPEC%") 12 | 'Build paramator 13 | varg = "/C CD " & WshShell.CurrentDirectory & " & " 14 | For i = 0 To WScript.Arguments.Count - 1 15 | varg = varg & " " & """" & WScript.Arguments(i) & """" 16 | Next 17 | varg = varg & " & PAUSE" 18 | 'run cmd /C ... as root 19 | Set ShellApp = CreateObject("Shell.Application") 20 | ShellApp.ShellExecute cmd, varg, "", "runas" 21 | End If 22 | -------------------------------------------------------------------------------- /make_linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make all TARGET=ia32 4 | make all TARGET=intel64 5 | 6 | TT_32=./obj-ia32/TinyTracer32.so 7 | TT_64=./obj-intel64/TinyTracer64.so 8 | 9 | APP_TYPE32=$(file "$TT_32") 10 | APP_TYPE64=$(file "$TT_64") 11 | 12 | if [[ $APP_TYPE64 == *"ELF 64-bit"* ]]; 13 | then 14 | echo "[+] 64 bit build ok." 15 | cp "$TT_64" ./install32_64/TinyTracer64.so 16 | if [[ $? == 0 ]]; 17 | then 18 | echo "[+] 64 bit install ok." 19 | else 20 | echo "ERROR: 64 bit install failed." 21 | fi 22 | else 23 | echo "ERROR: Could not build the 64-bit TinyTracer" 24 | fi 25 | 26 | if [[ $APP_TYPE32 == *"ELF 32-bit"* ]]; 27 | then 28 | echo "[+] 32 bit build ok." 29 | cp "$TT_32" ./install32_64/TinyTracer32.so 30 | if [[ $? == 0 ]]; 31 | then 32 | echo "[+] 32 bit install ok." 33 | else 34 | echo "ERROR: 32 bit install failed." 35 | fi 36 | else 37 | echo "ERROR: Could not build the 32-bit TinyTracer" 38 | fi 39 | 40 | -------------------------------------------------------------------------------- /install32_64/add_menu.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_CLASSES_ROOT\exefile\shell\PIN_run] 4 | @="Run with PIN (Tiny Tracer)" 5 | 6 | [HKEY_CLASSES_ROOT\exefile\shell\PIN_run\command] 7 | @="\"C:\\pin\\source\\tools\\tiny_tracer\\install32_64\\run_me.bat\" \"%1\" \"exe\" \"U\"" 8 | 9 | [HKEY_CLASSES_ROOT\dllfile\shell\PIN_run] 10 | @="Run with PIN (Tiny Tracer)" 11 | 12 | [HKEY_CLASSES_ROOT\dllfile\shell\PIN_run\command] 13 | @="\"C:\\pin\\source\\tools\\tiny_tracer\\install32_64\\run_me.bat\" \"%1\" \"dll\" \"U\"" 14 | 15 | [HKEY_CLASSES_ROOT\exefile\shell\PIN_run_admin] 16 | @="Run with PIN (Tiny Tracer) - as Administrator" 17 | 18 | [HKEY_CLASSES_ROOT\exefile\shell\PIN_run_admin\command] 19 | @="\"C:\\pin\\source\\tools\\tiny_tracer\\install32_64\\run_me.bat\" \"%1\" \"exe\" \"A\"" 20 | 21 | [HKEY_CLASSES_ROOT\dllfile\shell\PIN_run_admin] 22 | @="Run with PIN (Tiny Tracer) - as Administrator" 23 | 24 | [HKEY_CLASSES_ROOT\dllfile\shell\PIN_run_admin\command] 25 | @="\"C:\\pin\\source\\tools\\tiny_tracer\\install32_64\\run_me.bat\" \"%1\" \"dll\" \"A\"" 26 | -------------------------------------------------------------------------------- /DisasmCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Crc.h" 8 | 9 | //---- 10 | 11 | struct DisasmCache 12 | { 13 | static uint64_t calcChecks(const std::string& _disasm) 14 | { 15 | uint64_t init = 0; 16 | return crc64(init, (unsigned char*)_disasm.c_str(), _disasm.length()); 17 | } 18 | 19 | DisasmCache() {} 20 | 21 | ~DisasmCache() { 22 | for (auto itr = disasmLines.begin(); itr != disasmLines.end(); ++itr) { 23 | char* buf = itr->second; 24 | if (buf) free(buf); 25 | } 26 | } 27 | 28 | const char* get(uint32_t crc32) 29 | { 30 | auto itr = disasmLines.find(crc32); 31 | if (itr == disasmLines.end()) { 32 | return nullptr; 33 | } 34 | return disasmLines[crc32]; 35 | } 36 | 37 | const char* put(const std::string& _disasm) 38 | { 39 | auto checks = calcChecks(_disasm); 40 | auto infoPtr = get(checks); 41 | if (infoPtr) { 42 | return infoPtr; 43 | } 44 | const size_t len = _disasm.length(); 45 | char *buf = (char*)::malloc(len + 1); 46 | ::memcpy(buf, _disasm.c_str(), len); 47 | buf[len] = 0; 48 | disasmLines[checks] = buf; 49 | return disasmLines[checks]; 50 | } 51 | 52 | //--- 53 | std::map disasmLines; 54 | }; 55 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - Visual Studio 2022 3 | 4 | platform: 5 | - x64 6 | - x86 7 | 8 | branches: 9 | only: 10 | - master 11 | 12 | configuration: 13 | - Release 14 | 15 | build: 16 | verbosity: detailed 17 | 18 | environment: 19 | projName: $(APPVEYOR_PROJECT_SLUG) 20 | buildPlatform: $(PLATFORM) 21 | artifactName: $(APPVEYOR_PROJECT_NAME)-$(APPVEYOR_REPO_COMMIT)-$(PLATFORM) 22 | 23 | install: 24 | - cd .. 25 | - curl -fsS -o pin.zip https://software.intel.com/sites/landingpage/pintool/downloads/pin-external-3.31-98869-gfa6f126a8-msvc-windows.zip 26 | - 7z x pin.zip 27 | - cd pin-external-3.31-98869-gfa6f126a8-msvc-windows 28 | - cd source 29 | - cd tools 30 | - cp -r ../../../%projName% ./ 31 | - cd %projName% 32 | 33 | build_script: 34 | - ps: $PlatformToolset = "v143" 35 | - ps: (Get-Content TinyTracer.vcxproj) | %{$_ -replace "v110", $PlatformToolset} | Set-Content TinyTracer.vcxproj 36 | - ps: msbuild TinyTracer.vcxproj "/p:platform=$env:platform;configuration=$env:configuration" 37 | 38 | after_build: 39 | - mkdir C:\projects\%projName%\install32_64\%artifactName% 40 | - if [%buildPlatform%]==[x64] ( cp x64\Release\TinyTracer.dll C:\projects\%projName%\install32_64\%artifactName%\TinyTracer64.dll ) 41 | - if [%buildPlatform%]==[x86] ( cp Release\TinyTracer.dll C:\projects\%projName%\install32_64\%artifactName%\TinyTracer32.dll ) 42 | 43 | artifacts: 44 | - path: install32_64\%artifactName% 45 | 46 | -------------------------------------------------------------------------------- /ProcessInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | #include 6 | #include "ModuleInfo.h" 7 | 8 | class ProcessInfo 9 | { 10 | public: 11 | 12 | 13 | ProcessInfo() 14 | : m_myPid(0), isInit(false) 15 | { 16 | } 17 | 18 | bool init(std::string app) 19 | { 20 | if (isInit) { 21 | return false; // already initialized 22 | } 23 | m_AnalysedApp = app; 24 | m_myPid = 0; //UNKNOWN 25 | isInit = true; 26 | myModuleBase = UNKNOWN_ADDR; 27 | return true; 28 | } 29 | 30 | bool addModule(IMG Image); 31 | 32 | const s_module* getSecByAddr(ADDRINT Address) 33 | { 34 | return get_by_addr(Address, m_Sections); 35 | } 36 | 37 | bool isMyAddress(ADDRINT Address) 38 | { 39 | if (Address == UNKNOWN_ADDR) { 40 | return false; 41 | } 42 | IMG myImg = IMG_FindByAddress(myModuleBase); 43 | IMG otherImg = IMG_FindByAddress(Address); 44 | if (!IMG_Valid(myImg) || !IMG_Valid(otherImg)) { 45 | return false; 46 | } 47 | if (IMG_LoadOffset(myImg) == IMG_LoadOffset(otherImg)) { 48 | return true; 49 | } 50 | return false; 51 | } 52 | 53 | /** 54 | Saves the transition between sections witing the target module. 55 | \param Rva : current RVA witin the target module 56 | \return : true if the section changed, false otherwise 57 | */ 58 | const bool updateTracedModuleSection(ADDRINT Rva); 59 | 60 | bool isMyImg(IMG Image) const; 61 | 62 | protected: 63 | 64 | void addModuleSections(IMG Image, ADDRINT ImageBase); 65 | 66 | std::map m_Sections; 67 | ADDRINT myModuleBase; 68 | 69 | std::string m_AnalysedApp; 70 | INT m_myPid; 71 | bool isInit; 72 | }; 73 | 74 | -------------------------------------------------------------------------------- /Util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define IS_PRINTABLE(c) (c >= 0x20 && c < 0x7f) 11 | #define IS_ENDLINE(c) (c == 0x0A || c == 0xD) 12 | 13 | #define MAX_DWORD 0xffffffff 14 | #define MAX_WORD 0xffff 15 | 16 | #ifndef PAGE_SIZE 17 | #define PAGE_SIZE 0x1000 18 | #endif 19 | 20 | #if defined(WIN32) || defined(_WIN32) 21 | #define PATH_SEPARATOR "\\" 22 | #else 23 | #define PATH_SEPARATOR "/" 24 | #endif 25 | 26 | 27 | namespace util { 28 | std::wstring hexdump(const uint8_t* in_buf, const size_t max_size); 29 | 30 | size_t getAsciiLen(const char *inp, size_t maxInp); 31 | size_t getAsciiLenW(const wchar_t *inp, size_t maxInp); 32 | 33 | std::string getDllName(const std::string& str); 34 | 35 | bool iequals(const std::string& a, const std::string& b); 36 | size_t splitList(const std::string &sline, const char delimiter, std::vector &args); 37 | 38 | // trim from both ends (in place) 39 | void trim(std::string &s); 40 | 41 | int loadInt(const std::string &str, bool as_hex = false); 42 | 43 | std::string stripQuotes(const std::string& str); 44 | 45 | // compare strings, ignore case 46 | bool isStrEqualI(const std::string& str1, const std::string& str2); 47 | 48 | inline void wstr_to_str(const wchar_t* c, char* buf, const size_t bufSize) 49 | { 50 | size_t i; 51 | for (i = 0; i < bufSize; i++) { 52 | buf[i] = c[i]; 53 | if (c[i] == 0) break; 54 | } 55 | } 56 | 57 | std::string getDirectory(const std::string& filepath); 58 | std::string getFilename(const std::string& filepath); 59 | std::string makePath(const std::string& outDir, const std::string& module_name, const std::string& ext); 60 | }; 61 | -------------------------------------------------------------------------------- /install32_64/TinyTracer.ini: -------------------------------------------------------------------------------- 1 | ENABLE_SHORT_LOGGING=True 2 | USE_DEBUG_SYMBOLS=False 3 | FOLLOW_SHELLCODES=1 4 | ;FOLLOW_SHELLCODES: 5 | ; 0 : trace only the main target module 6 | ; 1 : follow only the first shellcode called from the main module 7 | ; 2 : follow also the shellcodes called recursively from the the original shellcode 8 | ; 3 : follow any shellcodes 9 | FOLLOW_CHILDPROCESSES=False 10 | TRACE_RDTSC=False 11 | TRACE_INT=False 12 | TRACE_SYSCALL=True 13 | LOG_SECTIONS_TRANSITIONS=True 14 | LOG_SHELLCODES_TRANSITIONS=True 15 | LOG_INDIRECT_CALLS=False 16 | HEXDUMP_SIZE=8 17 | HOOK_SLEEP=False 18 | SLEEP_TIME=10 19 | STOP_OFFSET_TIME=30 20 | ;STOP_OFFSET_TIME (dec): 21 | ; For how many seconds the execution should pause on a stop offset (defined by stop_offsets.txt) 22 | DISASM_CTX=False 23 | ;DISASM_CTX: 24 | ; When in disasm mode: show the registers changed by every instruction 25 | DISASM_DEPTH=3 26 | ;DISASM_DEPTH 27 | ; 0 : disabled (the file *.disasm_range.csv will be ignored) 28 | ; 1 : only instructions within the linear range will be traced 29 | ; 2 : follow into the calls and log transitions outside of the scope 30 | ; 3 : follow the new threads created by the traced range 31 | ANTIDEBUG=0 32 | ;ANTIDEBUG: (Windows only) 33 | ; 0 : Disabled 34 | ; 1 : Standard 35 | ; 2 : Deep (may lead to some false positives) 36 | ANTIVM=0 37 | ;ANTIVM: (Windows only) 38 | ; 0 : Disabled 39 | ; 1 : Standard 40 | ; Settings for ANTIVM enabled: 41 | EMULATE_HYPERV=False 42 | ; Settings for ANTIDEBUG enabled: 43 | EMULATE_SINGLE_STEP=True 44 | ;EMULATE_SINGLE_STEP: 45 | ; On True: when the trap flag was set, throw the SINGLE_STEP exception 46 | ; On False: the trap flag will be removed and ignored (no exception) 47 | LOG_RETURN_VALUE=False 48 | FOLLOW_ARGS_RETURN=False 49 | PARSE_EXPORTS=False 50 | ;PARSE_EXPORTS: 51 | ; Enable manual exports parsing on module load (from a file). Helpful if in-memory headers were corrupt. 52 | VOLUME_ID=0 53 | ;VOLUME_ID(hex) (Windows only) 54 | ; If set, the value will be used as VolumeSerialNumber 55 | -------------------------------------------------------------------------------- /makefile.rules: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2012-2020 Intel Corporation. 3 | # SPDX-License-Identifier: MIT 4 | # 5 | 6 | ############################################################## 7 | # 8 | # This file includes all the test targets as well as all the 9 | # non-default build rules and test recipes. 10 | # 11 | ############################################################## 12 | 13 | # TinyTracer-specific configuration to generate proper DLL name. 14 | ifeq ($(TARGET),intel64) 15 | BITNESS := 64 16 | else 17 | BITNESS := 32 18 | endif 19 | 20 | 21 | ############################################################## 22 | # 23 | # Test targets 24 | # 25 | ############################################################## 26 | 27 | ###### Place all generic definitions here ###### 28 | 29 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 30 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 31 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 32 | TEST_TOOL_ROOTS := TinyTracer$(BITNESS) 33 | 34 | 35 | ############################################################## 36 | # 37 | # Build rules 38 | # 39 | ############################################################## 40 | 41 | # This section contains the build rules for all binaries that have special build rules. 42 | # See makefile.default.rules for the default build rules. 43 | 44 | ifeq ($(TARGET), WIN32) 45 | EVASION_CHECKS=$(OBJDIR)AntiDebug$(OBJ_SUFFIX) $(OBJDIR)AntiVm$(OBJ_SUFFIX) $(OBJDIR)EvasionWatch$(OBJ_SUFFIX) 46 | EXPORTS_INFO=$(OBJDIR)ExportsInfo$(OBJ_SUFFIX) 47 | else 48 | EVASION_CHECKS= 49 | EXPORTS_INFO= 50 | endif 51 | 52 | $(OBJDIR)TinyTracer$(BITNESS)$(PINTOOL_SUFFIX): $(OBJDIR)Util$(OBJ_SUFFIX) $(OBJDIR)Settings$(OBJ_SUFFIX) $(OBJDIR)TraceLog$(OBJ_SUFFIX) \ 53 | $(OBJDIR)TinyTracer$(OBJ_SUFFIX) $(OBJDIR)ModuleInfo$(OBJ_SUFFIX) $(OBJDIR)ProcessInfo$(OBJ_SUFFIX) $(OBJDIR)FuncWatch$(OBJ_SUFFIX) \ 54 | $(OBJDIR)TrackReturns$(OBJ_SUFFIX) $(EVASION_CHECKS) $(EXPORTS_INFO) 55 | $(LINKER) $(TOOL_LDFLAGS) $(LINK_EXE)$@ $^ $(TOOL_LPATHS) $(TOOL_LIBS) 56 | 57 | -------------------------------------------------------------------------------- /TraceLog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | #include 5 | #include 6 | 7 | 8 | class TraceLog 9 | { 10 | public: 11 | static const char DELIMITER = ';'; 12 | 13 | TraceLog() 14 | { 15 | } 16 | 17 | ~TraceLog() 18 | { 19 | if (m_traceFile.is_open()) { 20 | m_traceFile.close(); 21 | } 22 | } 23 | 24 | void init(std::string fileName, bool is_short) 25 | { 26 | if (fileName.empty()) fileName = "output.txt"; 27 | m_logFileName = fileName; 28 | m_shortLog = is_short; 29 | createFile(); 30 | } 31 | 32 | void logCall(const ADDRINT prevModuleBase, const ADDRINT prevAddr, bool isRVA, const std::string &module, const std::string &func = ""); 33 | void logCall(const ADDRINT prevBase, const ADDRINT prevAddr, const ADDRINT calledPageBase, const ADDRINT callAddr); 34 | void logCallRet(const ADDRINT prevBase, const ADDRINT prevAddr, const ADDRINT retPageBase, const ADDRINT retAddr, const std::string &module, const std::string &func); 35 | void logSectionChange(const ADDRINT addr, std::string §ionName); 36 | void logNewSectionCalled(const ADDRINT addFrom, const std::string &prevSection, const std::string &currSection); 37 | void logIndirectCall(const ADDRINT prevModuleBase, const ADDRINT prevAddr, bool isRVA, const ADDRINT calledBase, const ADDRINT callRVA, const char* disasm); 38 | void logInstruction(const ADDRINT base, const ADDRINT rva, const std::string& mnem, const ADDRINT param); 39 | void logInstruction(const ADDRINT base, const ADDRINT rva, const std::string& mnem); 40 | void logSyscall(const ADDRINT base, const ADDRINT rva, const ADDRINT param, const std::string &funcName); 41 | 42 | void logLine(const std::string &str); 43 | 44 | protected: 45 | 46 | bool createFile() 47 | { 48 | if (m_traceFile.is_open()) { 49 | return true; 50 | } 51 | m_traceFile.open(m_logFileName.c_str()); 52 | if (m_traceFile.is_open()) { 53 | return true; 54 | } 55 | return false; 56 | } 57 | 58 | std::string m_logFileName; 59 | std::ofstream m_traceFile; 60 | bool m_shortLog; 61 | }; 62 | -------------------------------------------------------------------------------- /ProcessInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "ProcessInfo.h" 2 | #include 3 | #include 4 | #include 5 | 6 | std::string to_lowercase(const std::string &_str) 7 | { 8 | std::string str = _str; 9 | std::transform(str.begin(), str.end(), str.begin(), tolower); 10 | return str; 11 | } 12 | 13 | 14 | bool is_my_name(const std::string &module_name, const std::string &my_name) 15 | { 16 | std::string mod1 = to_lowercase(module_name); 17 | std::string mod2 = to_lowercase(my_name); 18 | if (mod1 == mod2) { 19 | return true; 20 | } 21 | std::size_t found1 = mod1.find_last_of("/\\"); 22 | if (found1 != std::string::npos) { 23 | mod1 = mod1.substr(found1+1); 24 | } 25 | std::size_t found2 = mod2.find_last_of("/\\"); 26 | if (found2 != std::string::npos) { 27 | mod2 = mod2.substr(found2+1); 28 | } 29 | 30 | if (mod1 == mod2) { 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | //---- 37 | void ProcessInfo::addModuleSections(IMG Image, ADDRINT ImageBase) 38 | { 39 | // enumerate sections within the analysed module 40 | for (SEC sec = IMG_SecHead(Image); SEC_Valid(sec); sec = SEC_Next(sec)) { 41 | s_module section; 42 | init_section(section, ImageBase, sec); 43 | m_Sections[section.start] = section; 44 | } 45 | } 46 | 47 | bool ProcessInfo::isMyImg(IMG Image) const 48 | { 49 | if (!IMG_Valid(Image)) return false; 50 | 51 | return is_my_name(IMG_Name(Image), m_AnalysedApp); 52 | } 53 | 54 | bool ProcessInfo::addModule(IMG Image) 55 | { 56 | // if this module is an object of observation, add its sections also 57 | if (m_myPid == 0 && is_my_name(IMG_Name(Image), m_AnalysedApp)) { 58 | m_myPid = PIN_GetPid(); 59 | myModuleBase = IMG_LoadOffset(Image); 60 | if (myModuleBase == 0) { 61 | myModuleBase = IMG_LowAddress(Image); 62 | } 63 | addModuleSections(Image, myModuleBase); 64 | } 65 | return true; 66 | } 67 | 68 | const bool ProcessInfo::updateTracedModuleSection(ADDRINT Rva) 69 | { 70 | // saved section (of the target module) 71 | static s_module* prevSec = nullptr; 72 | 73 | // current section of the target module (by RVA) 74 | const s_module* currSec = getSecByAddr(Rva); 75 | 76 | if (prevSec != currSec) { 77 | // update the stored section 78 | prevSec = const_cast(currSec); 79 | return true; 80 | } 81 | return false; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /install32_64/pin_attach.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem This script is to be used from the command line 3 | 4 | set TARGET_APP=%~1 5 | set TARGET_PID=%~2 6 | set TAG_FILE=%~3 7 | 8 | if "%TARGET_PID%"=="" goto display_args 9 | if "%TARGET_APP%"=="" goto display_args 10 | goto attach 11 | 12 | :display_args 13 | echo Attach TinyTracer to a process, and trace the selected module 14 | echo Required args: [target module path] [target pid] 15 | pause 16 | goto finish 17 | 18 | :attach 19 | echo PIN is trying to attach to the app: 20 | echo "%TARGET_APP%" 21 | 22 | rem PIN_DIR is your root directory of Intel Pin 23 | set PIN_DIR=C:\pin\ 24 | 25 | rem PIN_TOOLS_DIR is your directory with this script and the Pin Tools 26 | set PIN_TOOLS_DIR=C:\pin\source\tools\tiny_tracer\install32_64\ 27 | 28 | set PINTOOL32=%PIN_TOOLS_DIR%\TinyTracer32.dll 29 | set PINTOOL64=%PIN_TOOLS_DIR%\TinyTracer64.dll 30 | set PINTOOL=%PINTOOL32% 31 | 32 | rem TRACED_MODULE - by default it is the main module, but it can be also a DLL within the traced process 33 | set TRACED_MODULE=%TARGET_APP% 34 | 35 | if "%TAG_FILE%"=="" set TAG_FILE="%TRACED_MODULE%.tag" 36 | 37 | rem The ini file specifying the settings of the tracer 38 | set SETTINGS_FILE=%PIN_TOOLS_DIR%\TinyTracer.ini 39 | 40 | rem WATCH_BEFORE - a file with a list of functions which's parameters will be logged before execution 41 | rem The file must be a list of records in a format: [dll_name];[func_name];[parameters_count] 42 | set WATCH_BEFORE=%PIN_TOOLS_DIR%\params.txt 43 | 44 | rem SYSCALLS_TABLE - a CSV file, mapping syscall ID to a function name. Format: [syscallID:hex],[functionName] 45 | set SYSCALLS_TABLE=%PIN_TOOLS_DIR%\syscalls.txt 46 | 47 | rem List of functions that will be excluded from logging 48 | set EXCLUDED_FUNC=%PIN_TOOLS_DIR%\excluded.txt 49 | 50 | %PIN_TOOLS_DIR%\kdb_check.exe 51 | if NOT %errorlevel% EQU 0 ( 52 | echo Disable Kernel Mode Debugger before running the PIN tool! 53 | pause 54 | goto finish 55 | ) 56 | 57 | if NOT exist %SYSCALLS_TABLE% ( 58 | if exist %PIN_TOOLS_DIR%\syscall_extract.exe ( 59 | %PIN_TOOLS_DIR%\syscall_extract.exe %SYSCALLS_TABLE% 60 | ) 61 | ) 62 | 63 | %PIN_TOOLS_DIR%\pe_check.exe "%TARGET_APP%" 64 | if %errorlevel% == 32 ( 65 | echo 32bit selected 66 | set PINTOOL=%PINTOOL32% 67 | ) 68 | if %errorlevel% == 64 ( 69 | echo 64bit selected 70 | set PINTOOL=%PINTOOL64% 71 | ) 72 | 73 | rem The exports that you want to call from a dll, in format: [name1];[name2] or [#ordinal1];[#ordinal2] 74 | set DLL_EXPORTS="" 75 | 76 | echo Target module: "%TRACED_MODULE%" 77 | echo Tag file: %TAG_FILE% 78 | 79 | set EXE_CMD=%PIN_DIR%\pin.exe -pid %TARGET_PID% -t "%PINTOOL%" -m "%TRACED_MODULE%" -o %TAG_FILE% -s "%SETTINGS_FILE%" -l "%SYSCALLS_TABLE%" -b "%WATCH_BEFORE%" -x "%EXCLUDED_FUNC%" 80 | 81 | ;rem "Trace EXE" 82 | %EXE_CMD% 83 | 84 | if %ERRORLEVEL% EQU 0 echo [OK] PIN tracing finished: the traced application terminated. 85 | rem Pausing script after the application is executed is useful to see all eventual printed messages and for troubleshooting 86 | pause 87 | :finish 88 | -------------------------------------------------------------------------------- /ModuleInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "ModuleInfo.h" 2 | #include 3 | #include 4 | #include 5 | 6 | bool init_section(s_module §ion, const ADDRINT &ImageBase, const SEC &sec) 7 | { 8 | if (SEC_Address(sec) < ImageBase) { 9 | return false; 10 | } 11 | section.name = SEC_Name(sec); 12 | section.start = SEC_Address(sec) - ImageBase; 13 | section.end = section.start + SEC_Size(sec); 14 | return true; 15 | } 16 | 17 | const s_module* get_by_addr(ADDRINT Address, std::map &modules) 18 | { 19 | std::map::iterator bound = modules.upper_bound(Address); 20 | std::map::iterator itr = modules.begin(); 21 | 22 | for (; itr != bound; ++itr) { 23 | s_module &mod = itr->second; 24 | if (Address >= mod.start && Address < mod.end) { 25 | return &mod; 26 | } 27 | } 28 | return nullptr; 29 | } 30 | 31 | std::string get_func_at(ADDRINT callAddr, ADDRINT& diff) 32 | { 33 | IMG pImg = IMG_FindByAddress(callAddr); 34 | if (!IMG_Valid(pImg)) { 35 | std::ostringstream sstr; 36 | sstr << "[ " << callAddr << "]*"; 37 | return sstr.str(); 38 | } 39 | const ADDRINT base = IMG_LoadOffset(pImg); 40 | RTN rtn = RTN_FindByAddress(callAddr); 41 | if (!RTN_Valid(rtn)) { 42 | std::ostringstream sstr; 43 | sstr << "[ + " << (callAddr - base) << "]*"; 44 | return sstr.str(); 45 | } 46 | 47 | std::string name = get_unmangled_name(rtn); 48 | ADDRINT rtnAddr = RTN_Address(rtn); 49 | diff = callAddr - rtnAddr; 50 | return name; 51 | } 52 | 53 | ADDRINT get_mod_base(ADDRINT Address) 54 | { 55 | if (Address == UNKNOWN_ADDR) { 56 | return UNKNOWN_ADDR; 57 | } 58 | IMG img = IMG_FindByAddress(Address); 59 | if (IMG_Valid(img)) { 60 | ADDRINT base = IMG_LoadOffset(img); 61 | if (base == 0) { 62 | base = IMG_LowAddress(img); 63 | } 64 | return base; 65 | } 66 | return UNKNOWN_ADDR; 67 | } 68 | 69 | ADDRINT get_base(ADDRINT Address) 70 | { 71 | ADDRINT base = get_mod_base(Address); 72 | if (base != UNKNOWN_ADDR) { 73 | return base; 74 | } 75 | return query_region_base(Address); 76 | } 77 | 78 | ADDRINT addr_to_rva(ADDRINT Address) 79 | { 80 | ADDRINT base = get_base(Address); 81 | if (base == UNKNOWN_ADDR) { 82 | return Address; 83 | } 84 | return Address - base; 85 | } 86 | 87 | ADDRINT query_region_base(ADDRINT memoryAddr) 88 | { 89 | if (!memoryAddr || memoryAddr == UNKNOWN_ADDR) { 90 | return UNKNOWN_ADDR; 91 | } 92 | return GetPageOfAddr((ADDRINT)memoryAddr); 93 | } 94 | 95 | std::string get_unmangled_name(RTN rtn) 96 | { 97 | return PIN_UndecorateSymbolName(RTN_Name(rtn), UNDECORATION_NAME_ONLY); 98 | } 99 | 100 | RTN find_by_unmangled_name(IMG img, const CHAR* fName) 101 | { 102 | for (SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym)) { 103 | const std::string undFuncName = PIN_UndecorateSymbolName(SYM_Name(sym), UNDECORATION_NAME_ONLY); 104 | if (undFuncName == fName) { 105 | const ADDRINT offset = SYM_Value(sym); 106 | if (offset == UNKNOWN_ADDR) break; 107 | return RTN_FindByAddress(IMG_LowAddress(img) + offset); 108 | } 109 | } 110 | return RTN_Invalid(); 111 | } 112 | -------------------------------------------------------------------------------- /FuncWatch.cpp: -------------------------------------------------------------------------------- 1 | #include "FuncWatch.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Util.h" 8 | 9 | bool WFuncInfo::load(const std::string &sline, char delimiter) 10 | { 11 | std::vector args; 12 | util::splitList(sline, delimiter, args); 13 | if (args.size() < 2) return false; 14 | 15 | this->dllName = args[0]; 16 | this->funcName = args[1]; 17 | this->paramCount = 0; 18 | 19 | if (args.size() >= 3) { 20 | this->paramCount = util::loadInt(args[2]); 21 | } 22 | return true; 23 | } 24 | 25 | bool WFuncInfo::update(const WFuncInfo &func_info) 26 | { 27 | bool isUpdated = false; 28 | if (this->paramCount < func_info.paramCount) { 29 | this->paramCount = func_info.paramCount; 30 | isUpdated = true; 31 | } 32 | return isUpdated; 33 | } 34 | 35 | //--- 36 | 37 | std::string WSyscallInfo::formatSyscallName(int syscallID) 38 | { 39 | std::stringstream ss; 40 | ss << "SYSCALL:0x" << std::hex << (syscallID); 41 | return ss.str(); 42 | } 43 | 44 | bool WSyscallInfo::load(const std::string& sline, char delimiter) 45 | { 46 | std::vector args; 47 | util::splitList(sline, delimiter, args); 48 | if (args.size() < 3) return false; 49 | // Note: '<' and '>' are used to ensure this cannot overlap with a valid 50 | // file or library name. 51 | if (args[0] != "") return false; 52 | 53 | // Parse syscall ID as a hexadecimal number 54 | const int syscallId = util::loadInt(args[1], true); 55 | if (syscallId < 0) return false; 56 | 57 | this->syscallId = static_cast(syscallId); 58 | this->paramCount = util::loadInt(args[2]); 59 | 60 | return true; 61 | } 62 | 63 | bool WSyscallInfo::update(const WSyscallInfo& syscall_info) 64 | { 65 | bool isUpdated = false; 66 | if (this->paramCount < syscall_info.paramCount) { 67 | this->paramCount = syscall_info.paramCount; 68 | isUpdated = true; 69 | } 70 | return isUpdated; 71 | } 72 | 73 | //--- 74 | 75 | void FuncWatchList::appendSyscall(WSyscallInfo& syscall_info) 76 | { 77 | std::map::iterator it = syscalls.find(syscall_info.syscallId); 78 | if (it == syscalls.end()) { 79 | syscalls[syscall_info.syscallId] = syscall_info; 80 | } 81 | else { 82 | it->second.update(syscall_info); 83 | } 84 | } 85 | 86 | size_t FuncWatchList::loadList(const char* filename, FuncList* exclusions) 87 | { 88 | std::ifstream myfile(filename); 89 | if (!myfile.is_open()) { 90 | std::cerr << "Coud not open file: " << filename << std::endl; 91 | return 0; 92 | } 93 | const size_t MAX_LINE = 300; 94 | char line[MAX_LINE] = { 0 }; 95 | while (!myfile.eof()) { 96 | 97 | myfile.getline(line, MAX_LINE); 98 | const std::string str = line; 99 | if (!str.size() || str[0] == '#') { // skip empty lines and comments 100 | continue; 101 | } 102 | // Try to parse as a syscall 103 | WSyscallInfo syscall_info; 104 | if (syscall_info.load(str, FuncList::DELIM)) { 105 | appendSyscall(syscall_info); 106 | continue; 107 | } 108 | 109 | // Try to parse as a function 110 | WFuncInfo func_info; 111 | if (func_info.load(line, FuncList::DELIM)) { 112 | if (exclusions && exclusions->contains(func_info.dllName, func_info.funcName)) { 113 | //std::cout << ">> Skipping: " << func_info.funcName << std::endl; 114 | continue; 115 | } 116 | appendFunc(func_info); 117 | } 118 | } 119 | return funcs.size(); 120 | } 121 | -------------------------------------------------------------------------------- /EvasionWatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | #include "FuncWatch.h" 5 | #include 6 | 7 | //--- 8 | 9 | typedef enum { 10 | WATCH_DISABLED = 0, // Evasion detection is disabled 11 | WATCH_STANDARD = 1, // Track "standard" and easily identifiable techniques 12 | WATCH_DEEP = 2, // Track more techniques, may lead to false positives 13 | WATCH_OPTIONS_COUNT 14 | } t_watch_level; 15 | 16 | inline t_watch_level ConvertWatchLevel(int value) 17 | { 18 | if (value >= WATCH_OPTIONS_COUNT) { 19 | // choose the last option: 20 | return t_watch_level(WATCH_OPTIONS_COUNT - 1); 21 | } 22 | return (t_watch_level)value; 23 | } 24 | 25 | //--- 26 | 27 | struct FuncData 28 | { 29 | public: 30 | FuncData() : name(""), argsNum(0) { } 31 | 32 | FuncData(const std::string& _name, size_t _argsNum) : name(_name), argsNum(_argsNum) 33 | { 34 | ::memset(args, 0, sizeof(args)); 35 | } 36 | 37 | FuncData(const FuncData& other) 38 | { 39 | name = other.name; 40 | argsNum = other.argsNum; 41 | ::memcpy(args, other.args, sizeof(args)); 42 | } 43 | 44 | std::string name; 45 | size_t argsNum; 46 | VOID* args[5]; 47 | }; 48 | 49 | //--- 50 | 51 | inline VOID storeData(std::map& funcDataStorage, THREADID tid, const CHAR* name, uint32_t argCount, VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, VOID* arg5) 52 | { 53 | FuncData data(name, argCount); 54 | data.args[0] = arg1; 55 | data.args[1] = arg2; 56 | data.args[2] = arg3; 57 | data.args[3] = arg4; 58 | data.args[4] = arg5; 59 | funcDataStorage[tid] = data; 60 | } 61 | 62 | inline BOOL retrieveData(std::map& funcDataStorage, THREADID tid, const CHAR* name, FuncData& data) 63 | { 64 | FuncData& _data = funcDataStorage[tid]; 65 | if (_data.name != name) { 66 | return FALSE; 67 | } 68 | data = _data; 69 | return TRUE; 70 | } 71 | 72 | //--- 73 | 74 | typedef VOID EvasionWatchBeforeCallBack(const ADDRINT Address, const THREADID tid, const CHAR* name, uint32_t argCount, VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, VOID* arg5); 75 | 76 | typedef VOID EvasionWatchAfterCallBack(const ADDRINT Address, const THREADID tid, const CHAR* name, ADDRINT result); 77 | 78 | struct EvasionFuncInfo : public WFuncInfo 79 | { 80 | EvasionFuncInfo(const std::string& _dllName, const std::string& _funcName, const size_t _paramCount, EvasionWatchBeforeCallBack* _callbackB = nullptr, EvasionWatchAfterCallBack* _callbackA = nullptr, t_watch_level _type = WATCH_STANDARD) 81 | : WFuncInfo(_dllName, _funcName, _paramCount), 82 | callbackBefore(_callbackB), callbackAfter(_callbackA), type(_type) 83 | { 84 | } 85 | 86 | EvasionWatchBeforeCallBack* callbackBefore; 87 | EvasionWatchAfterCallBack* callbackAfter; 88 | t_watch_level type; 89 | }; 90 | 91 | //--- 92 | 93 | class EvasionWatch 94 | { 95 | public: 96 | static bool EvasionAddCallbackBefore(IMG Image, const char* fName, uint32_t argNum, EvasionWatchBeforeCallBack callback); 97 | static bool EvasionAddCallbackAfter(IMG Image, const char* fName, EvasionWatchAfterCallBack callback); 98 | 99 | EvasionWatch() : isInit(FALSE) { } 100 | 101 | virtual BOOL Init() = 0; 102 | EvasionFuncInfo* fetchFunctionInfo(const std::string& dllName, const std::string& funcName, t_watch_level maxLevel); 103 | EvasionFuncInfo* fetchSyscallFuncInfo(const std::string& funcName, t_watch_level maxLevel); 104 | 105 | size_t installCallbacks(IMG Image, EvasionWatchBeforeCallBack defaultCallbackBefore, t_watch_level maxLevel); 106 | FuncList watchedFuncs; 107 | 108 | protected: 109 | BOOL isInit; 110 | }; 111 | -------------------------------------------------------------------------------- /install32_64/tiny_runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | << 'MULTILINE-COMMENT' 4 | 5 | Linux runner for Tiny Tracer 6 | 1. Download the latest Intel Pin, and unpack it into your home directory, under the name "pin" 7 | 2. Compile tiny_tracer in both 64 and 32 bit version: 8 | + Make sure that tiny_tracer source is in ~/pin/source/tools/tiny_tracer 9 | + Go to tiny_tracer directory 10 | + Issue `make_linux.sh` to compile both 32-bit and 64-bit version. 11 | If everything went fine, you will obtain: `TinyTracer32.so` and: `TinyTracer64.so` in the `install32_64` directory. 12 | 3. Now you can use the current script (`tiny_runner.sh`) to run your apps via TinyTracer. 13 | 4. To make the script runnable from any directory, you can add a symbolic link to your local `bin` directory. Example: 14 | ln -s $HOME/pin/source/tools/tiny_tracer/install32_64/tiny_runner.sh ~/bin/tiny_runner.sh 15 | 5. Optionally, you can also create a link to the directory with `tiny_tracer` configuration, to have an easy access to them. For example: 16 | ln -s $HOME/pin/source/tools/tiny_tracer/install32_64/ $HOME/Desktop/install32_64 17 | MULTILINE-COMMENT 18 | 19 | echo "Linux runner for Tiny Tracer" 20 | echo "Usage: [target_module*]" 21 | echo "*-optional; default: target app's main module" 22 | 23 | if [ -z "$1" ]; then 24 | echo "ERROR: Target app not supplied." 25 | exit 26 | fi 27 | 28 | TARGET_APP=$1 29 | echo "PIN is trying to run the app: $TARGET_APP" 30 | 31 | # TRACED_MODULE - by default it is the main module, but it can be also a DLL within the traced process 32 | TRACED_MODULE=$TARGET_APP 33 | 34 | if [ -n "$2" ]; then 35 | TRACED_MODULE=$2 36 | fi 37 | 38 | TRACED_MODULE_BASENAME=$(basename "$TRACED_MODULE") 39 | 40 | if [ -z "$TRACED_MODULE_BASENAME" ]; then 41 | echo "ERROR: Invalid path to the traced module: $TRACED_MODULE" 42 | exit 43 | fi 44 | 45 | echo "Traced Module Name: $TRACED_MODULE_BASENAME"; 46 | 47 | #The arguments that you want to pass to the run executable 48 | EXE_ARGS="" 49 | 50 | OUT_PATH=$TARGET_APP".tag" 51 | 52 | # PIN_DIR is your root directory of Intel Pin 53 | PIN_DIR=$HOME"/pin/" 54 | 55 | #PIN_TOOLS_DIR is your directory with this script and the Pin Tools 56 | PIN_TOOLS_DIR=$PIN_DIR"/source/tools/tiny_tracer/install32_64/" 57 | 58 | # The ini file specifying the settings of the tracer 59 | SETTINGS_FILE=$PIN_TOOLS_DIR"/TinyTracer.ini" 60 | 61 | # WATCH_ARGS - a file with a list of functions which's parameters will be logged 62 | # The file must be a list of records in a format: `[module_name];[func_name];[parameters_count]` 63 | # or, in case of tracing syscalls: `;[syscallID:hex];[parameters_count]` (where "" is a constant keyword) 64 | WATCH_ARGS=$PIN_TOOLS_DIR"/params.txt" 65 | 66 | # List of functions that will be excluded from logging 67 | # The file must be a list of records in a format: `[dll_name];[func_name]` 68 | EXCLUDED_FUNC=$PIN_TOOLS_DIR"/excluded.txt" 69 | 70 | # List of stop offsets: RVAs of the traced module where the execution should pause 71 | STOP_OFFSETS=$PIN_TOOLS_DIR"/stop_offsets.txt" 72 | 73 | # SYSCALLS_TABLE - a CSV file, mapping syscall ID to a function name. Format: [syscallID:hex],[functionName] 74 | SYSCALLS_TABLE=$PIN_TOOLS_DIR"/linux_syscalls.txt" 75 | 76 | PINTOOL32=$PIN_TOOLS_DIR"/TinyTracer32.so" 77 | PINTOOL64=$PIN_TOOLS_DIR"/TinyTracer64.so" 78 | PINTOOL=$PINTOOL64 79 | 80 | APP_TYPE=$(file "$TARGET_APP") 81 | 82 | ELF_64="ELF 64-bit" 83 | ELF_32="ELF 32-bit" 84 | 85 | if [[ $APP_TYPE == *"$ELF_64"* ]]; 86 | then 87 | echo "The app is 64 bit." 88 | PINTOOL=$PINTOOL64 89 | elif [[ $APP_TYPE == *"$ELF_32"* ]]; 90 | then 91 | echo "The app is 32 bit." 92 | PINTOOL=$PINTOOL32 93 | else 94 | echo "ERROR: Not supported file type." 95 | exit 96 | fi 97 | 98 | $PIN_DIR/pin -t "$PINTOOL" -s "$SETTINGS_FILE" -b "$WATCH_ARGS" -x "$EXCLUDED_FUNC" -p "$STOP_OFFSETS" -m "$TRACED_MODULE_BASENAME" -o "$OUT_PATH" -l "$SYSCALLS_TABLE" -- "$TARGET_APP" $EXE_ARGS 99 | 100 | -------------------------------------------------------------------------------- /EvasionWatch.cpp: -------------------------------------------------------------------------------- 1 | #include "EvasionWatch.h" 2 | #include "Util.h" 3 | #include "TinyTracer.h" 4 | #include "ModuleInfo.h" 5 | 6 | bool EvasionWatch::EvasionAddCallbackBefore(IMG Image, const char* fName, uint32_t argNum, EvasionWatchBeforeCallBack callback) 7 | { 8 | if (!callback) return false; 9 | 10 | const size_t argMax = 5; 11 | if (argNum > argMax) argNum = argMax; 12 | 13 | RTN funcRtn = find_by_unmangled_name(Image, fName); 14 | if (RTN_Valid(funcRtn)) { 15 | RTN_Open(funcRtn); 16 | 17 | RTN_InsertCall(funcRtn, IPOINT_BEFORE, AFUNPTR(callback), 18 | IARG_RETURN_IP, 19 | IARG_THREAD_ID, 20 | IARG_ADDRINT, fName, 21 | IARG_UINT32, argNum, 22 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 23 | IARG_FUNCARG_ENTRYPOINT_VALUE, 1, 24 | IARG_FUNCARG_ENTRYPOINT_VALUE, 2, 25 | IARG_FUNCARG_ENTRYPOINT_VALUE, 3, 26 | IARG_FUNCARG_ENTRYPOINT_VALUE, 4, 27 | IARG_END 28 | ); 29 | 30 | RTN_Close(funcRtn); 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | bool EvasionWatch::EvasionAddCallbackAfter(IMG Image, const char* fName, EvasionWatchAfterCallBack callback) 37 | { 38 | if (!callback) return false; 39 | 40 | RTN funcRtn = find_by_unmangled_name(Image, fName); 41 | if (RTN_Valid(funcRtn)) { 42 | RTN_Open(funcRtn); 43 | 44 | RTN_InsertCall(funcRtn, IPOINT_AFTER, AFUNPTR(callback), 45 | IARG_RETURN_IP, 46 | IARG_THREAD_ID, 47 | IARG_ADDRINT, fName, 48 | IARG_FUNCRET_EXITPOINT_VALUE, 49 | IARG_END); 50 | 51 | RTN_Close(funcRtn); 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | // 58 | 59 | EvasionFuncInfo* EvasionWatch::fetchFunctionInfo(const std::string& dllName, const std::string& funcName, t_watch_level maxLevel) 60 | { 61 | for (size_t i = 0; i < watchedFuncs.funcs.size(); i++) { 62 | if (util::iequals(dllName, watchedFuncs.funcs[i].dllName)) { 63 | EvasionFuncInfo& wfunc = watchedFuncs.funcs[i]; 64 | if (wfunc.funcName != funcName) { 65 | continue; 66 | } 67 | if (wfunc.type > maxLevel) { 68 | continue; 69 | } 70 | return &wfunc; 71 | } 72 | } 73 | return nullptr; 74 | } 75 | 76 | EvasionFuncInfo* EvasionWatch::fetchSyscallFuncInfo(const std::string& funcName, t_watch_level maxLevel) 77 | { 78 | EvasionFuncInfo* wfunc = fetchFunctionInfo("ntdll", funcName, maxLevel); 79 | if (!wfunc) { 80 | wfunc = fetchFunctionInfo("win32u", funcName, maxLevel); 81 | } 82 | return wfunc; 83 | } 84 | 85 | size_t EvasionWatch::installCallbacks(IMG Image, EvasionWatchBeforeCallBack defaultCallback, t_watch_level maxLevel) 86 | { 87 | if (!isInit) { 88 | return 0; 89 | } 90 | 91 | // callbacks before: 92 | size_t added = 0; 93 | const std::string dllName = util::getDllName(IMG_Name(Image)); 94 | for (size_t i = 0; i < watchedFuncs.funcs.size(); i++) { 95 | if (util::iequals(dllName, watchedFuncs.funcs[i].dllName)) { 96 | EvasionFuncInfo& wfunc = watchedFuncs.funcs[i]; 97 | if (wfunc.type > maxLevel) { 98 | continue; 99 | } 100 | EvasionWatchBeforeCallBack* callbackBefore = wfunc.callbackBefore; 101 | if (!callbackBefore && !wfunc.callbackAfter) { 102 | callbackBefore = defaultCallback; 103 | } 104 | if (EvasionAddCallbackBefore(Image, wfunc.funcName.c_str(), wfunc.paramCount, callbackBefore)) { 105 | added++; 106 | } 107 | if (wfunc.callbackAfter) 108 | if (EvasionAddCallbackAfter(Image, wfunc.funcName.c_str(), wfunc.callbackAfter)) { 109 | added++; 110 | } 111 | } 112 | } 113 | 114 | // callbacks after: do not verify the DLL name, because the function can be proxied 115 | for (size_t i = 0; i < watchedFuncs.funcs.size(); i++) { 116 | 117 | EvasionFuncInfo& wfunc = watchedFuncs.funcs[i]; 118 | if (wfunc.type > maxLevel) { 119 | continue; 120 | } 121 | if (EvasionAddCallbackAfter(Image, wfunc.funcName.c_str(), wfunc.callbackAfter)) { 122 | added++; 123 | } 124 | 125 | } 126 | return added; 127 | } 128 | -------------------------------------------------------------------------------- /install32_64/run_me.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem This script is to be used from the context menu 3 | 4 | set TARGET_APP=%~1 5 | set PE_TYPE=%~2 6 | set IS_ADMIN=%~3 7 | 8 | if "%TARGET_APP%"=="" goto display_args 9 | if "%PE_TYPE%"=="" goto display_args 10 | goto run_it 11 | 12 | :display_args 13 | echo Run a process with TinyTracer, and trace the selected module 14 | echo It is recommended to run this script via installed context menu 15 | echo Required args: [target app] [pe type: dll or exe] 16 | pause 17 | goto finish 18 | 19 | :run_it 20 | echo PIN is trying to run the app: 21 | echo "%TARGET_APP%" 22 | 23 | rem PIN_DIR is your root directory of Intel Pin 24 | set PIN_DIR=C:\pin\ 25 | 26 | rem PIN_TOOLS_DIR is your directory with this script and the Pin Tools 27 | set PIN_TOOLS_DIR=C:\pin\source\tools\tiny_tracer\install32_64\ 28 | 29 | set PINTOOL32=%PIN_TOOLS_DIR%\TinyTracer32.dll 30 | set PINTOOL64=%PIN_TOOLS_DIR%\TinyTracer64.dll 31 | set PINTOOL=%PINTOOL32% 32 | 33 | rem TRACED_MODULE - by default it is the main module, but it can be also a DLL within the traced process 34 | set TRACED_MODULE=%TARGET_APP% 35 | 36 | set OUT_PATH="%TARGET_APP%.tag" 37 | 38 | rem The ini file specifying the settings of the tracer 39 | set SETTINGS_FILE=%PIN_TOOLS_DIR%\TinyTracer.ini 40 | 41 | rem WATCH_ARGS - a file with a list of functions which's parameters will be logged 42 | rem The file must be a list of records in a format: [dll_name];[func_name];[parameters_count] 43 | rem or, in case of tracing syscalls: ;[syscallID:hex];[parameters_count] (where "" is a constant keyword) 44 | set WATCH_ARGS=%PIN_TOOLS_DIR%\params.txt 45 | 46 | rem List of functions that will be excluded from logging 47 | rem The file must be a list of records in a format: [dll_name];[func_name] 48 | set EXCLUDED_FUNC=%PIN_TOOLS_DIR%\excluded.txt 49 | 50 | rem List of stop offsets: RVAs of the traced module where the execution should pause 51 | set STOP_OFFSETS=%PIN_TOOLS_DIR%\stop_offsets.txt 52 | 53 | rem SYSCALLS_TABLE - a CSV file, mapping syscall ID to a function name. Format: [syscallID:hex],[functionName] 54 | set SYSCALLS_TABLE=%PIN_TOOLS_DIR%\syscalls.txt 55 | 56 | set DLL_LOAD32=%PIN_TOOLS_DIR%\dll_load32.exe 57 | set DLL_LOAD64=%PIN_TOOLS_DIR%\dll_load64.exe 58 | 59 | if exist %PIN_TOOLS_DIR%\kdb_check.exe ( 60 | %PIN_TOOLS_DIR%\kdb_check.exe 61 | if NOT %errorlevel% EQU 0 ( 62 | echo Disable Kernel Mode Debugger before running the PIN tool! 63 | pause 64 | exit 65 | ) 66 | ) 67 | 68 | if NOT exist %SYSCALLS_TABLE% ( 69 | if exist %PIN_TOOLS_DIR%\syscall_extract.exe ( 70 | %PIN_TOOLS_DIR%\syscall_extract.exe %SYSCALLS_TABLE% 71 | ) 72 | ) 73 | 74 | %PIN_TOOLS_DIR%\pe_check.exe "%TARGET_APP%" 75 | if %errorlevel% == 32 ( 76 | echo 32bit selected 77 | set PINTOOL=%PINTOOL32% 78 | set DLL_LOAD=%DLL_LOAD32% 79 | ) 80 | if %errorlevel% == 64 ( 81 | echo 64bit selected 82 | set PINTOOL=%PINTOOL64% 83 | set DLL_LOAD=%DLL_LOAD64% 84 | ) 85 | 86 | rem The exports that you want to call from a dll, in format: [name1];[name2] or [#ordinal1];[#ordinal2] 87 | set DLL_EXPORTS="#1" 88 | 89 | rem The arguments that you want to pass to the run executable 90 | set EXE_ARGS="" 91 | 92 | echo Target module: "%TRACED_MODULE%" 93 | echo Out path: %OUT_PATH% 94 | if [%IS_ADMIN%] == [A] ( 95 | echo Elevation requested 96 | ) 97 | 98 | set ADMIN_CMD=%PIN_TOOLS_DIR%\sudo.vbs 99 | 100 | set DLL_CMD=%PIN_DIR%\pin.exe -follow_execv -t %PINTOOL% -m "%TRACED_MODULE%" -o %OUT_PATH% -s %SETTINGS_FILE% -b "%WATCH_ARGS%" -x "%EXCLUDED_FUNC%" -p "%STOP_OFFSETS%" -l "%SYSCALLS_TABLE%" -- "%DLL_LOAD%" "%TARGET_APP%" %DLL_EXPORTS% 101 | set EXE_CMD=%PIN_DIR%\pin.exe -follow_execv -t %PINTOOL% -m "%TRACED_MODULE%" -o %OUT_PATH% -s %SETTINGS_FILE% -b "%WATCH_ARGS%" -x "%EXCLUDED_FUNC%" -p "%STOP_OFFSETS%" -l "%SYSCALLS_TABLE%" -- "%TARGET_APP%" %EXE_ARGS% 102 | 103 | ;rem "Trace EXE" 104 | if [%PE_TYPE%] == [exe] ( 105 | if [%IS_ADMIN%] == [A] ( 106 | %ADMIN_CMD% %EXE_CMD% 107 | ) else ( 108 | %EXE_CMD% 109 | ) 110 | ) 111 | ;rem "Trace DLL" 112 | if [%PE_TYPE%] == [dll] ( 113 | if [%IS_ADMIN%] == [A] ( 114 | %ADMIN_CMD% %DLL_CMD% 115 | ) else ( 116 | %DLL_CMD% 117 | ) 118 | ) 119 | 120 | if [%IS_ADMIN%] == [A] ( 121 | rem In Admin mode, a new console should be created. Pause only if it failed, in order to display the error: 122 | if NOT %ERRORLEVEL% EQU 0 pause 123 | ) else ( 124 | if %ERRORLEVEL% EQU 0 echo [OK] PIN tracing finished: the traced application terminated. 125 | rem Pausing script after the application is executed is useful to see all eventual printed messages and for troubleshooting 126 | pause 127 | ) 128 | :finish 129 | -------------------------------------------------------------------------------- /Util.cpp: -------------------------------------------------------------------------------- 1 | #include "Util.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "pin.H" 8 | 9 | std::wstring util::hexdump(const uint8_t* in_buf, const size_t max_size) 10 | { 11 | std::wstringstream ss; 12 | for (size_t i = 0; i < max_size; i++) { 13 | if (!PIN_CheckReadAccess(const_cast(in_buf) + i)) { 14 | break; 15 | } 16 | if (IS_PRINTABLE(in_buf[i])) { 17 | ss << char(in_buf[i]); 18 | } 19 | else { 20 | ss << "\\x" << std::setfill(L'0') << std::setw(2) << std::hex << (unsigned int)in_buf[i]; 21 | } 22 | } 23 | return ss.str(); 24 | } 25 | 26 | namespace util { 27 | 28 | template 29 | size_t getStrLen(const CHAR_T* inp, size_t bytesMax) 30 | { 31 | const size_t maxInp = bytesMax / sizeof(CHAR_T); 32 | for (size_t i = 0; i < maxInp; i++) { 33 | if (!PIN_CheckReadAccess(const_cast(inp) + i)) { 34 | return 0; 35 | } 36 | const CHAR_T c = inp[i]; 37 | if (c == 0) return i; //end of string 38 | if (!IS_PRINTABLE(c) && !IS_ENDLINE(c)) return 0; 39 | } 40 | return 0; 41 | } 42 | }; 43 | 44 | size_t util::getAsciiLen(const char *inp, size_t maxInp) 45 | { 46 | return getStrLen(inp, maxInp); 47 | } 48 | 49 | size_t util::getAsciiLenW(const wchar_t *inp, size_t maxInp) 50 | { 51 | return getStrLen(inp, maxInp); 52 | } 53 | 54 | std::string util::getDllName(const std::string& str) 55 | { 56 | std::size_t len = str.length(); 57 | if (!len) return str; 58 | 59 | std::size_t found = str.find_last_of("/\\"); 60 | std::size_t ext = str.find_last_of("."); 61 | if (ext > len) ext = len; 62 | 63 | std::string name = str.substr(found + 1, ext - (found + 1)); 64 | std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c){ return std::tolower(c); }); 65 | return name; 66 | } 67 | 68 | bool util::iequals(const std::string& a, const std::string& b) 69 | { 70 | size_t aLen = a.size(); 71 | if (b.size() != aLen) return false; 72 | 73 | for (size_t i = 0; i < aLen; ++i) { 74 | if (tolower(a[i]) != tolower(b[i])) return false; 75 | } 76 | return true; 77 | } 78 | 79 | size_t util::splitList(const std::string &sline, const char delimiter, std::vector &args) 80 | { 81 | std::istringstream f(sline); 82 | std::string s; 83 | while (getline(f, s, delimiter)) { 84 | args.push_back(s); 85 | } 86 | return args.size(); 87 | } 88 | 89 | static inline void ltrim(std::string &s) 90 | { 91 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { 92 | return !std::isspace(ch); 93 | })); 94 | } 95 | 96 | static inline void rtrim(std::string &s) 97 | { 98 | s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { 99 | return !std::isspace(ch); 100 | }).base(), s.end()); 101 | } 102 | 103 | void util::trim(std::string &s) 104 | { 105 | ltrim(s); 106 | rtrim(s); 107 | } 108 | 109 | int util::loadInt(const std::string &str, bool as_hex) 110 | { 111 | int intVal = 0; 112 | 113 | std::stringstream ss; 114 | ss << (as_hex ? std::hex : std::dec) << str; 115 | ss >> intVal; 116 | 117 | return intVal; 118 | } 119 | 120 | std::string util::stripQuotes(const std::string& str) 121 | { 122 | std::string s = str; 123 | s.erase(std::remove(s.begin(), s.end(), '\"'), s.end()); 124 | return s; 125 | } 126 | 127 | bool util::isStrEqualI(const std::string &str1, const std::string &str2) 128 | { 129 | if (str1.length() != str2.length()) { 130 | return false; 131 | } 132 | for (size_t i = 0; i < str1.length(); i++) { 133 | if (tolower(str1[i]) != tolower(str2[i])) { 134 | return false; 135 | } 136 | } 137 | return true; 138 | } 139 | 140 | std::string util::getDirectory(const std::string& filepath) 141 | { 142 | size_t pos = filepath.find_last_of("/\\"); 143 | if (pos == std::string::npos || pos == filepath.length()) { 144 | return filepath; 145 | } 146 | return filepath.substr(0, pos); 147 | } 148 | 149 | std::string util::getFilename(const std::string& filepath) 150 | { 151 | size_t pos = filepath.find_last_of("/\\"); 152 | if (pos == std::string::npos || pos == filepath.length()) { 153 | return filepath; 154 | } 155 | return filepath.substr(pos + 1, filepath.length()); 156 | } 157 | 158 | std::string util::makePath(const std::string& outDir, const std::string& module_name, const std::string& ext) 159 | { 160 | std::string filename = util::getFilename(module_name); 161 | std::stringstream fnamestr; 162 | if (!outDir.empty()) { 163 | fnamestr << outDir << PATH_SEPARATOR; 164 | } 165 | fnamestr << filename << '.' << ext; 166 | return fnamestr.str(); 167 | } 168 | -------------------------------------------------------------------------------- /TraceLog.cpp: -------------------------------------------------------------------------------- 1 | #include "TraceLog.h" 2 | 3 | #include "Util.h" 4 | 5 | void TraceLog::logCall(const ADDRINT prevModuleBase, const ADDRINT prevAddr, bool isRVA, const std::string &module, const std::string &func) 6 | { 7 | if (!createFile()) return; 8 | ADDRINT rva = (isRVA) ? prevAddr : prevAddr - prevModuleBase; 9 | if (!isRVA) { 10 | m_traceFile << "> " << prevModuleBase << "+"; 11 | } 12 | m_traceFile << 13 | std::hex << rva 14 | << DELIMITER; 15 | 16 | if (!m_shortLog) { 17 | m_traceFile << "called: " 18 | << module; 19 | } 20 | else { 21 | m_traceFile << util::getDllName(module); 22 | } 23 | if (func.length() > 0) { 24 | m_traceFile << "." << func; 25 | } 26 | m_traceFile << std::endl; 27 | m_traceFile.flush(); 28 | } 29 | 30 | void TraceLog::logCall(const ADDRINT prevBase, const ADDRINT prevAddr, const ADDRINT calledPageBase, const ADDRINT callAddr) 31 | { 32 | if (!createFile()) return; 33 | if (prevBase) { 34 | m_traceFile << "> " << prevBase << "+"; 35 | } 36 | const ADDRINT rva = callAddr - calledPageBase; 37 | m_traceFile << 38 | std::hex << prevAddr 39 | << DELIMITER 40 | << "called: ?? [" << calledPageBase << "+" << rva << "]" 41 | << std::endl; 42 | m_traceFile.flush(); 43 | } 44 | 45 | void TraceLog::logCallRet(const ADDRINT prevBase, const ADDRINT prevAddr, const ADDRINT retPageBase, const ADDRINT retAddr, const std::string &module, const std::string &func) 46 | { 47 | if (!createFile()) return; 48 | 49 | ADDRINT retRva = retAddr; 50 | if (retPageBase) { 51 | retRva -= retPageBase; 52 | m_traceFile << "> " << retPageBase << "+"; 53 | } 54 | m_traceFile 55 | << std::hex << retRva 56 | << DELIMITER 57 | << "RET from: " 58 | << "[" << prevBase << "+" << prevAddr << "] -> " 59 | << util::getDllName(module); 60 | 61 | if (func.length() > 0) { 62 | m_traceFile << "." << func; 63 | } 64 | m_traceFile << std::endl; 65 | m_traceFile.flush(); 66 | } 67 | 68 | 69 | void TraceLog::logSectionChange(const ADDRINT prevAddr, std::string &name) 70 | { 71 | if (!createFile()) return; 72 | m_traceFile 73 | << std::hex << prevAddr 74 | << DELIMITER 75 | << "section: [" << name << "]" 76 | << std::endl; 77 | m_traceFile.flush(); 78 | } 79 | 80 | void TraceLog::logIndirectCall(const ADDRINT prevModuleBase, const ADDRINT prevAddr, bool isRVA, const ADDRINT calledBase, const ADDRINT calledRVA, const char* disasm) 81 | { 82 | if (!createFile()) return; 83 | ADDRINT rva = (isRVA) ? prevAddr : prevAddr - prevModuleBase; 84 | if (!isRVA) { 85 | m_traceFile << "> " << prevModuleBase << "+"; 86 | } 87 | m_traceFile << 88 | std::hex << rva 89 | << DELIMITER; 90 | if (disasm) { 91 | m_traceFile << "[" << disasm << "] "; 92 | } 93 | m_traceFile 94 | << "to: " << (calledBase + calledRVA) << " [" << calledBase << " + " << calledRVA << "]" 95 | << std::endl; 96 | } 97 | 98 | void TraceLog::logInstruction(const ADDRINT base, const ADDRINT rva, const std::string& mnem, const ADDRINT param) 99 | { 100 | if (!createFile()) return; 101 | if (base) { 102 | m_traceFile << "> " << std::hex << base << "+"; 103 | } 104 | m_traceFile 105 | << std::hex << rva 106 | << DELIMITER 107 | << mnem << ":" 108 | << std::hex << param 109 | << std::endl; 110 | m_traceFile.flush(); 111 | } 112 | 113 | void TraceLog::logInstruction(const ADDRINT base, const ADDRINT rva, const std::string& mnem) 114 | { 115 | if (!createFile()) return; 116 | if (base) { 117 | m_traceFile << "> " << std::hex << base << "+"; 118 | } 119 | m_traceFile 120 | << std::hex << rva 121 | << DELIMITER 122 | << mnem 123 | << std::endl; 124 | m_traceFile.flush(); 125 | } 126 | 127 | void TraceLog::logSyscall(const ADDRINT base, const ADDRINT rva, const ADDRINT param, const std::string& funcName) 128 | { 129 | if (!createFile()) return; 130 | if (base) { 131 | m_traceFile << "> " << std::hex << base << "+"; 132 | } 133 | m_traceFile 134 | << std::hex << rva 135 | << DELIMITER 136 | << "SYSCALL:0x" 137 | << std::hex << param; 138 | if (!funcName.empty()) { 139 | m_traceFile << "(" << funcName << ")"; 140 | } 141 | m_traceFile << std::endl; 142 | m_traceFile.flush(); 143 | } 144 | 145 | void TraceLog::logLine(const std::string &str) 146 | { 147 | if (!createFile()) return; 148 | 149 | m_traceFile 150 | << str 151 | << std::endl; 152 | m_traceFile.flush(); 153 | } 154 | 155 | void TraceLog::logNewSectionCalled(const ADDRINT prevAddr, const std::string &prevSection, const std::string &currSection) 156 | { 157 | createFile(); 158 | m_traceFile 159 | << std::hex << prevAddr 160 | << DELIMITER 161 | << "[" << prevSection << "] -> [" << currSection << "]" 162 | << std::endl; 163 | m_traceFile.flush(); 164 | } 165 | -------------------------------------------------------------------------------- /FuncWatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "Util.h" 13 | 14 | #define LIST_DELIMITER ';' 15 | 16 | struct RoutineInfo 17 | { 18 | RoutineInfo() : paramCount(0) {}; 19 | 20 | virtual bool load(const std::string& line, char delimiter) = 0; 21 | virtual bool isValid() const = 0; 22 | 23 | size_t paramCount; 24 | }; 25 | 26 | struct WFuncInfo : public RoutineInfo 27 | { 28 | WFuncInfo() : RoutineInfo() 29 | { 30 | } 31 | 32 | WFuncInfo(const std::string& _dllName, const std::string& _funcName, const size_t _paramCount) 33 | { 34 | this->dllName = _dllName; 35 | this->funcName = _funcName; 36 | this->paramCount = _paramCount; 37 | } 38 | 39 | WFuncInfo(const WFuncInfo& a) 40 | { 41 | this->dllName = a.dllName; 42 | this->funcName = a.funcName; 43 | this->paramCount = a.paramCount; 44 | } 45 | 46 | bool load(const std::string &line, char delimiter); 47 | 48 | bool update(const WFuncInfo &func_info); 49 | 50 | bool isValid() const 51 | { 52 | return dllName.length() > 0 && funcName.length() > 0; 53 | } 54 | 55 | std::string dllName; 56 | std::string funcName; 57 | }; 58 | 59 | struct WSyscallInfo : public RoutineInfo 60 | { 61 | static const uint32_t INVALID_SYSCALL = (-1); 62 | 63 | static std::string formatSyscallName(int syscallID); 64 | 65 | WSyscallInfo() : 66 | RoutineInfo(), 67 | syscallId(INVALID_SYSCALL) 68 | { 69 | } 70 | 71 | bool load(const std::string& line, char delimiter); 72 | 73 | bool update(const WSyscallInfo& syscall_info); 74 | 75 | bool isValid() const 76 | { 77 | return (syscallId != INVALID_SYSCALL); 78 | } 79 | 80 | uint32_t syscallId; 81 | }; 82 | 83 | //--- 84 | template 85 | class FuncList { 86 | public: 87 | static const char DELIM = LIST_DELIMITER; 88 | 89 | FuncList() 90 | { 91 | } 92 | 93 | ~FuncList() 94 | { 95 | } 96 | 97 | bool isEmpty() { return this->funcs.size() > 0 ? false : true; } 98 | 99 | bool contains(const std::string& dll_name, const std::string& func) 100 | { 101 | if (!dll_name.length() || !func.length()) return false; 102 | if (this->isEmpty()) return false; 103 | 104 | const std::string shortDll = util::getDllName(dll_name); 105 | for (auto itr = funcs.begin(); itr != funcs.end(); ++itr) { 106 | WFuncInfo_T& fInfo = *itr; 107 | if (util::iequals(fInfo.dllName, shortDll)) { 108 | if (fInfo.funcName == func) { 109 | //std::cout << "Excluded Func: " << shortDll << "." << func << "\n"; 110 | return true; 111 | } 112 | } 113 | } 114 | return false; 115 | } 116 | 117 | bool appendFunc(WFuncInfo_T& func_info) 118 | { 119 | if (!func_info.isValid()) { 120 | return false; 121 | } 122 | WFuncInfo_T* found = findFunc(func_info.dllName, func_info.funcName); 123 | if (!found) { 124 | funcs.push_back(func_info); 125 | } 126 | else { 127 | found->update(func_info); 128 | } 129 | return true; 130 | } 131 | 132 | 133 | size_t loadList(const char* filename) 134 | { 135 | std::ifstream myfile(filename); 136 | if (!myfile.is_open()) { 137 | std::cerr << "Coud not open file: " << filename << std::endl; 138 | return 0; 139 | } 140 | const size_t MAX_LINE = 300; 141 | char line[MAX_LINE] = { 0 }; 142 | while (!myfile.eof()) { 143 | myfile.getline(line, MAX_LINE); 144 | 145 | // Try to parse as a function 146 | WFuncInfo_T func_info; 147 | 148 | if (func_info.load(line, FuncList::DELIM)) { 149 | appendFunc(func_info); 150 | } 151 | } 152 | return funcs.size(); 153 | } 154 | 155 | std::vector funcs; 156 | 157 | protected: 158 | WFuncInfo_T* findFunc(const std::string& dllName, const std::string& funcName) 159 | { 160 | for (size_t i = 0; i < funcs.size(); i++) 161 | { 162 | WFuncInfo_T& info = funcs[i]; 163 | if (util::iequals(info.dllName, dllName) 164 | && util::iequals(info.funcName, funcName)) 165 | { 166 | return &info; 167 | } 168 | } 169 | return NULL; 170 | } 171 | }; 172 | 173 | //-- 174 | 175 | class FuncWatchList : public FuncList{ 176 | public: 177 | FuncWatchList() 178 | : FuncList() 179 | { 180 | } 181 | 182 | bool isEmpty() { return (this->funcs.size() + this->syscalls.size()) > 0 ? false : true; } 183 | 184 | size_t loadList(const char* filename, FuncList* exclusions); 185 | 186 | std::map syscalls; 187 | 188 | private: 189 | void appendSyscall(WSyscallInfo& syscall_info); 190 | }; 191 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny_tracer 2 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/f988180bfb4d45ebbe4764bde1058c2f)](https://app.codacy.com/gh/hasherezade/tiny_tracer/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) 3 | [![Commit activity](https://img.shields.io/github/commit-activity/m/hasherezade/tiny_tracer)](https://github.com/hasherezade/tiny_tracer/commits) 4 | [![Last Commit](https://img.shields.io/github/last-commit/hasherezade/tiny_tracer/master)](https://github.com/hasherezade/tiny_tracer/commits) 5 | [![Build status](https://ci.appveyor.com/api/projects/status/543ql60gxxuri9j2?svg=true)](https://ci.appveyor.com/project/hasherezade/tiny-tracer) 6 | 7 | [![GitHub release](https://img.shields.io/github/release/hasherezade/tiny_tracer.svg)](https://github.com/hasherezade/tiny_tracer/releases) 8 | [![GitHub release date](https://img.shields.io/github/release-date/hasherezade/tiny_tracer?color=blue)](https://github.com/hasherezade/tiny_tracer/releases) 9 | 10 | 11 | A Pin Tool for tracing: 12 | + API calls, including [input and output of selected functions](https://github.com/hasherezade/tiny_tracer/wiki/Tracing-function-input-and-output) 13 | + [defined local functions](https://github.com/hasherezade/tiny_tracer/wiki/Tracing-defined-local-functions) 14 | + selected instructions: [RDTSC](https://c9x.me/x86/html/file_module_x86_id_278.html), [CPUID](https://c9x.me/x86/html/file_module_x86_id_45.html), [INT](https://c9x.me/x86/html/file_module_x86_id_142.html) 15 | + [inline system calls, including parameters of selected syscalls](https://github.com/hasherezade/tiny_tracer/wiki/Tracing-syscalls) 16 | + transition between sections of the traced module (helpful in finding OEP of the packed module) 17 | + [executed instructions in defined code fragments](https://github.com/hasherezade/tiny_tracer/wiki/Tracing-with-disassembly) 18 | 19 | Evades some of the known [anti-debug](https://github.com/hasherezade/tiny_tracer/wiki/The-INI-file#antidebug) and [anti-VM](https://github.com/hasherezade/tiny_tracer/wiki/The-INI-file#antivm) techniques 20 | 21 | Generates a report in a `.tag` format (which can be [loaded into other analysis tools](https://github.com/hasherezade/tiny_tracer/wiki/Using-the-TAGs-with-disassemblers-and-debuggers)): 22 | 23 | ```txt 24 | RVA;traced event 25 | ``` 26 | i.e. 27 | 28 | ```txt 29 | 345c2;section: .text 30 | 58069;called: C:\Windows\SysWOW64\kernel32.dll.IsProcessorFeaturePresent 31 | 3976d;called: C:\Windows\SysWOW64\kernel32.dll.LoadLibraryExW 32 | 3983c;called: C:\Windows\SysWOW64\kernel32.dll.GetProcAddress 33 | 3999d;called: C:\Windows\SysWOW64\KernelBase.dll.InitializeCriticalSectionEx 34 | 398ac;called: C:\Windows\SysWOW64\KernelBase.dll.FlsAlloc 35 | 3995d;called: C:\Windows\SysWOW64\KernelBase.dll.FlsSetValue 36 | 49275;called: C:\Windows\SysWOW64\kernel32.dll.LoadLibraryExW 37 | 4934b;called: C:\Windows\SysWOW64\kernel32.dll.GetProcAddress 38 | ... 39 | ``` 40 | 41 | ## 🚧 How to build 42 | 43 | ### On Windows 44 | 45 | To compile the prepared project you need to use [Visual Studio >= 2012](https://visualstudio.microsoft.com/downloads/). It was tested with [Intel Pin 3.31](https://software.intel.com/en-us/articles/pin-a-binary-instrumentation-tool-downloads).
46 | Clone this repo into `\source\tools` that is inside your Pin root directory. Open the project in Visual Studio and build. Detailed description available [here](https://github.com/hasherezade/tiny_tracer/wiki/Installation#on-windows).
47 | To build with Intel Pin < 3.26 on Windows, use the appropriate legacy Visual Studio project. 48 | 49 | ### On Linux 50 | 51 | For now the support for Linux is experimental. Yet it is possible to build and use Tiny Tracer on Linux as well. Please refer [tiny_runner.sh](https://github.com/hasherezade/tiny_tracer/blob/master/install32_64/tiny_runner.sh) for more information. 52 | Detailed description available [here](https://github.com/hasherezade/tiny_tracer/wiki/Installation#on-linux). 53 | 54 | ## ⚙ Usage 55 | 56 | 📖 Details about the usage you will find on [the project's Wiki](https://github.com/hasherezade/tiny_tracer/wiki).
57 | 58 | ## 🛠 Helpers 59 | 60 | For automatic generation of [`params.txt` for API arguments tracing](https://github.com/hasherezade/tiny_tracer/wiki/Tracing-parameters-of-functions), try [IAT-Tracer](https://github.com/YoavLevi/IAT-Tracer) by [YoavLevi](https://github.com/YoavLevi) 61 | 62 | 63 | ## WARNINGS 64 | 65 | + In order for Pin to work correctly, Kernel Debugging must be **DISABLED**. 66 | + In [`install32_64`](https://github.com/hasherezade/tiny_tracer/tree/master/install32_64) you can find a utility that checks if Kernel Debugger is disabled (`kdb_check.exe`, [source](https://github.com/hasherezade/pe_utils/tree/master/kdb_check)), and it is used by the Tiny Tracer's `.bat` scripts. This utilty sometimes gets flagged as a malware by Windows Defender (it is a known false positive). If you encounter this issue, you may need to [exclude](https://support.microsoft.com/en-us/windows/add-an-exclusion-to-windows-security-811816c0-4dfd-af4a-47e4-c301afe13b26) the installation directory from Windows Defender scans. 67 | + Since the version 3.20 Pin has dropped a support for **old versions of Windows**. If you need to use the tool on Windows < 8, try to compile it with Pin 3.19. 68 | 69 | 70 | --- 71 | 72 | 🤔 Questions? Ideas? Join [Discussions](https://github.com/hasherezade/tiny_tracer/discussions)! 73 | 74 | --- 75 | -------------------------------------------------------------------------------- /install32_64/run_me_benchmark.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem This script is to be used from the context menu 3 | 4 | set TARGET_APP=%~1 5 | set PE_TYPE=%~2 6 | set IS_ADMIN=%~3 7 | 8 | if "%TARGET_APP%"=="" goto display_args 9 | if "%PE_TYPE%"=="" goto display_args 10 | goto run_it 11 | 12 | :display_args 13 | echo Run a process with TinyTracer, and trace the selected module 14 | echo It is recommended to run this script via installed context menu 15 | echo Required args: [target app] [pe type: dll or exe] 16 | pause 17 | goto finish 18 | 19 | :run_it 20 | echo PIN is trying to run the app: 21 | echo "%TARGET_APP%" 22 | 23 | rem PIN_DIR is your root directory of Intel Pin 24 | set PIN_DIR=C:\pin\ 25 | 26 | rem PIN_TOOLS_DIR is your directory with this script and the Pin Tools 27 | set PIN_TOOLS_DIR=C:\pin\source\tools\tiny_tracer\install32_64\ 28 | 29 | set PINTOOL32=%PIN_TOOLS_DIR%\TinyTracer32.dll 30 | set PINTOOL64=%PIN_TOOLS_DIR%\TinyTracer64.dll 31 | set PINTOOL=%PINTOOL32% 32 | 33 | rem TRACED_MODULE - by default it is the main module, but it can be also a DLL within the traced process 34 | set TRACED_MODULE=%TARGET_APP% 35 | 36 | set OUT_PATH="%TARGET_APP%.tag" 37 | 38 | rem The ini file specifying the settings of the tracer 39 | set SETTINGS_FILE=%PIN_TOOLS_DIR%\TinyTracer.ini 40 | 41 | rem WATCH_ARGS - a file with a list of functions which's parameters will be logged 42 | rem The file must be a list of records in a format: [dll_name];[func_name];[parameters_count] 43 | rem or, in case of tracing syscalls: ;[syscallID:hex];[parameters_count] (where "" is a constant keyword) 44 | set WATCH_ARGS=%PIN_TOOLS_DIR%\params.txt 45 | 46 | rem List of functions that will be excluded from logging 47 | rem The file must be a list of records in a format: [dll_name];[func_name] 48 | set EXCLUDED_FUNC=%PIN_TOOLS_DIR%\excluded.txt 49 | 50 | rem List of stop offsets: RVAs of the traced module where the execution should pause 51 | set STOP_OFFSETS=%PIN_TOOLS_DIR%\stop_offsets.txt 52 | 53 | rem SYSCALLS_TABLE - a CSV file, mapping syscall ID to a function name. Format: [syscallID:hex],[functionName] 54 | set SYSCALLS_TABLE=%PIN_TOOLS_DIR%\syscalls.txt 55 | 56 | set DLL_LOAD32=%PIN_TOOLS_DIR%\dll_load32.exe 57 | set DLL_LOAD64=%PIN_TOOLS_DIR%\dll_load64.exe 58 | 59 | if exist %PIN_TOOLS_DIR%\kdb_check.exe ( 60 | %PIN_TOOLS_DIR%\kdb_check.exe 61 | if NOT %errorlevel% EQU 0 ( 62 | echo Disable Kernel Mode Debugger before running the PIN tool! 63 | pause 64 | exit 65 | ) 66 | ) 67 | 68 | if NOT exist %SYSCALLS_TABLE% ( 69 | if exist %PIN_TOOLS_DIR%\syscall_extract.exe ( 70 | %PIN_TOOLS_DIR%\syscall_extract.exe %SYSCALLS_TABLE% 71 | ) 72 | ) 73 | 74 | %PIN_TOOLS_DIR%\pe_check.exe "%TARGET_APP%" 75 | if %errorlevel% == 32 ( 76 | echo 32bit selected 77 | set PINTOOL=%PINTOOL32% 78 | set DLL_LOAD=%DLL_LOAD32% 79 | ) 80 | if %errorlevel% == 64 ( 81 | echo 64bit selected 82 | set PINTOOL=%PINTOOL64% 83 | set DLL_LOAD=%DLL_LOAD64% 84 | ) 85 | 86 | rem The exports that you want to call from a dll, in format: [name1];[name2] or [#ordinal1];[#ordinal2] 87 | set DLL_EXPORTS="" 88 | 89 | rem The arguments that you want to pass to the run executable 90 | set EXE_ARGS="" 91 | 92 | echo Target module: "%TRACED_MODULE%" 93 | echo Tag file: %OUT_PATH% 94 | if [%IS_ADMIN%] == [A] ( 95 | echo Elevation requested 96 | ) 97 | 98 | set ADMIN_CMD=%PIN_TOOLS_DIR%\sudo.vbs 99 | 100 | set DLL_CMD=%PIN_DIR%\pin.exe -t %PINTOOL% -m "%TRACED_MODULE%" -o %OUT_PATH% -s %SETTINGS_FILE% -b "%WATCH_ARGS%" -x "%EXCLUDED_FUNC%" -p "%STOP_OFFSETS%" -l "%SYSCALLS_TABLE%" -- "%DLL_LOAD%" "%TARGET_APP%" %DLL_EXPORTS% 101 | set EXE_CMD=%PIN_DIR%\pin.exe -t %PINTOOL% -m "%TRACED_MODULE%" -o %OUT_PATH% -s %SETTINGS_FILE% -b "%WATCH_ARGS%" -x "%EXCLUDED_FUNC%" -p "%STOP_OFFSETS%" -l "%SYSCALLS_TABLE%" -- "%TARGET_APP%" %EXE_ARGS% 102 | 103 | set start=%time% 104 | 105 | ;rem "Trace EXE" 106 | if [%PE_TYPE%] == [exe] ( 107 | if [%IS_ADMIN%] == [A] ( 108 | %ADMIN_CMD% %EXE_CMD% 109 | ) else ( 110 | %EXE_CMD% 111 | ) 112 | ) 113 | ;rem "Trace DLL" 114 | if [%PE_TYPE%] == [dll] ( 115 | if [%IS_ADMIN%] == [A] ( 116 | %ADMIN_CMD% %DLL_CMD% 117 | ) else ( 118 | %DLL_CMD% 119 | ) 120 | ) 121 | 122 | set end=%time% 123 | 124 | set options="tokens=1-4 delims=:.," 125 | for /f %options% %%a in ("%start%") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100 126 | for /f %options% %%a in ("%end%") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 100 127 | 128 | set /a hours=%end_h%-%start_h% 129 | set /a mins=%end_m%-%start_m% 130 | set /a secs=%end_s%-%start_s% 131 | set /a ms=%end_ms%-%start_ms% 132 | if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms% 133 | if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs% 134 | if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins% 135 | if %hours% lss 0 set /a hours = 24%hours% 136 | if 1%ms% lss 100 set ms=0%ms% 137 | 138 | :: Mission accomplished 139 | set /a totalsecs = %hours%*3600 + %mins%*60 + %secs% 140 | echo command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total) 141 | 142 | if [%IS_ADMIN%] == [A] ( 143 | rem In Admin mode, a new console should be created. Pause only if it failed, in order to display the error: 144 | if NOT %ERRORLEVEL% EQU 0 pause 145 | ) else ( 146 | if %ERRORLEVEL% EQU 0 echo [OK] PIN tracing finished: the traced application terminated. 147 | rem Pausing script after the application is executed is useful to see all eventual printed messages and for troubleshooting 148 | pause 149 | ) 150 | :finish 151 | -------------------------------------------------------------------------------- /ExportsInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "ExportsInfo.h" 2 | 3 | #include "mini_pe.h" 4 | #include "ModuleInfo.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace ExportsInfo { 11 | 12 | inline bool validate_ptr(const void* buffer_bgn, size_t buffer_size, const void* field_bgn, size_t field_size) 13 | { 14 | if (buffer_bgn == nullptr || field_bgn == nullptr) { 15 | return false; 16 | } 17 | BYTE* _start = (BYTE*)buffer_bgn; 18 | BYTE* _field_start = (BYTE*)field_bgn; 19 | if (_field_start < _start) { 20 | return false; 21 | } 22 | size_t start_delta = (BYTE*)_field_start - (BYTE*)_start; 23 | size_t area_size = start_delta + field_size; 24 | if (area_size > buffer_size) { 25 | return false; 26 | } 27 | if (area_size < field_size || area_size < start_delta) { 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | inline bool manual_map(BYTE* image, size_t imgSize, BYTE* rawPE, size_t rawSize, PIMAGE_NT_HEADERS nt) 34 | { 35 | if (imgSize < nt->OptionalHeader.SizeOfHeaders || rawSize < nt->OptionalHeader.SizeOfHeaders) { 36 | return false; 37 | } 38 | ::memcpy(image, rawPE, nt->OptionalHeader.SizeOfHeaders); 39 | // map sections 40 | PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(nt); 41 | for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++) { 42 | if (!validate_ptr(rawPE, rawSize, §ion[i], sizeof(IMAGE_SECTION_HEADER))) { 43 | return false; 44 | } 45 | BYTE* vPtr = (BYTE*)(image)+section[i].VirtualAddress; 46 | BYTE* rPtr = (BYTE*)(rawPE)+section[i].PointerToRawData; 47 | const size_t secSize = section[i].SizeOfRawData; 48 | if (!validate_ptr(image, imgSize, vPtr, secSize) || 49 | !validate_ptr(rawPE, rawSize, rPtr, secSize)) 50 | { 51 | return false; 52 | } 53 | ::memcpy(vPtr, rPtr, secSize); 54 | } 55 | return true; 56 | } 57 | 58 | size_t loadPE(std::vector& buffer, std::vector& mapped) 59 | { 60 | BYTE* raw = (BYTE*)&buffer[0]; 61 | IMAGE_DOS_HEADER* dos = reinterpret_cast(raw); 62 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) { 63 | return 0; 64 | } 65 | IMAGE_NT_HEADERS* nt = reinterpret_cast(raw + dos->e_lfanew); 66 | if (nt->Signature != IMAGE_NT_SIGNATURE) { 67 | return 0; 68 | } 69 | 70 | size_t imgSize = nt->OptionalHeader.SizeOfImage; 71 | mapped.resize(imgSize); 72 | BYTE* image = (BYTE*)&mapped[0]; 73 | if (!manual_map(image, mapped.size(), raw, buffer.size(), nt)) { 74 | return 0; 75 | } 76 | return imgSize; 77 | } 78 | 79 | 80 | size_t fillExports(IMG& img, const ADDRINT base, BYTE* mem, size_t mem_size) 81 | { 82 | size_t count = 0; 83 | IMAGE_DOS_HEADER* dos = reinterpret_cast(mem); 84 | if (dos->e_magic != IMAGE_DOS_SIGNATURE) { 85 | return 0; 86 | } 87 | IMAGE_NT_HEADERS* nt = reinterpret_cast(mem + dos->e_lfanew); 88 | if (nt->Signature != IMAGE_NT_SIGNATURE) { 89 | return 0; 90 | } 91 | IMAGE_DATA_DIRECTORY exportDirEntry = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 92 | if (exportDirEntry.VirtualAddress == 0) return 0; 93 | 94 | IMAGE_EXPORT_DIRECTORY* exportDir = reinterpret_cast(mem + exportDirEntry.VirtualAddress); 95 | DWORD funcsListRVA = exportDir->AddressOfFunctions; 96 | DWORD funcNamesListRVA = exportDir->AddressOfNames; 97 | DWORD namesOrdsListRVA = exportDir->AddressOfNameOrdinals; 98 | DWORD namesCount = exportDir->NumberOfNames; 99 | 100 | for (DWORD i = 0; i < namesCount; i++) { 101 | DWORD* nameRVA = (DWORD*)((ADDRINT)mem + funcNamesListRVA + i * sizeof(DWORD)); 102 | WORD* nameIndex = (WORD*)((ADDRINT)mem + namesOrdsListRVA + i * sizeof(WORD)); 103 | DWORD* funcRVA = (DWORD*)((ADDRINT)mem + funcsListRVA + (*nameIndex) * sizeof(DWORD)); 104 | 105 | if (!validate_ptr(mem, mem_size, nameRVA, sizeof(DWORD)) || 106 | !validate_ptr(mem, mem_size, nameIndex, sizeof(WORD)) || 107 | !validate_ptr(mem, mem_size, funcRVA, sizeof(DWORD))) 108 | { 109 | break; 110 | } 111 | ADDRINT funcVA = base + (*funcRVA); 112 | const char* name = reinterpret_cast(mem + (*nameRVA)); 113 | if (!name || !validate_ptr(mem, mem_size, name, sizeof(char))) { 114 | continue; 115 | } 116 | RTN rtn = RTN_FindByAddress(funcVA); 117 | if (RTN_Address(rtn) != funcVA) { 118 | RTN_CreateAt(funcVA, name); 119 | } 120 | count++; 121 | } 122 | return count; 123 | } 124 | 125 | }; //ExportsInfo 126 | 127 | size_t ExportsInfo::addFromFile(IMG& img) 128 | { 129 | if (!IMG_Valid(img)) { 130 | return 0; 131 | } 132 | ADDRINT base = IMG_LoadOffset(img); 133 | if (base == 0) { 134 | base = IMG_LowAddress(img); 135 | } 136 | const std::string imagePath = IMG_Name(img); 137 | std::ifstream file(imagePath, std::ios::binary | std::ios::in); 138 | if (!file.is_open()) return 0; 139 | 140 | file.seekg(0, std::ios::end); 141 | 142 | const std::streamsize fileSize = file.tellg(); 143 | file.seekg(0, std::ios::beg); 144 | 145 | std::vector buffer(fileSize); 146 | bool isOk = file.read(&buffer[0], fileSize); 147 | file.close(); 148 | if (!isOk) return 0; 149 | 150 | std::vector mapped; 151 | if (!loadPE(buffer, mapped)) return 0; 152 | 153 | BYTE* mem = (BYTE*)&mapped[0]; 154 | return fillExports(img, base, mem, mapped.size()); 155 | } 156 | -------------------------------------------------------------------------------- /mini_pe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef uint8_t BYTE; 5 | typedef uint16_t WORD; 6 | typedef uint32_t DWORD; 7 | typedef uint32_t LONG; 8 | typedef uint64_t ULONGLONG; 9 | 10 | #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ 11 | #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 12 | 13 | #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b 14 | #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b 15 | 16 | #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory 17 | 18 | 19 | typedef struct _IMAGE_DOS_HEADER 20 | { 21 | WORD e_magic; 22 | WORD e_cblp; 23 | WORD e_cp; 24 | WORD e_crlc; 25 | WORD e_cparhdr; 26 | WORD e_minalloc; 27 | WORD e_maxalloc; 28 | WORD e_ss; 29 | WORD e_sp; 30 | WORD e_csum; 31 | WORD e_ip; 32 | WORD e_cs; 33 | WORD e_lfarlc; 34 | WORD e_ovno; 35 | WORD e_res[4]; 36 | WORD e_oemid; 37 | WORD e_oeminfo; 38 | WORD e_res2[10]; 39 | LONG e_lfanew; 40 | } IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER; 41 | 42 | 43 | typedef struct _IMAGE_FILE_HEADER { 44 | WORD Machine; 45 | WORD NumberOfSections; 46 | DWORD TimeDateStamp; 47 | DWORD PointerToSymbolTable; 48 | DWORD NumberOfSymbols; 49 | WORD SizeOfOptionalHeader; 50 | WORD Characteristics; 51 | } IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER; 52 | 53 | 54 | typedef struct _IMAGE_DATA_DIRECTORY { 55 | DWORD VirtualAddress; 56 | DWORD Size; 57 | } IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY; 58 | 59 | #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 60 | 61 | // 62 | // Optional header format. 63 | // 64 | 65 | typedef struct _IMAGE_OPTIONAL_HEADER { 66 | // 67 | // Standard fields. 68 | // 69 | 70 | WORD Magic; 71 | BYTE MajorLinkerVersion; 72 | BYTE MinorLinkerVersion; 73 | DWORD SizeOfCode; 74 | DWORD SizeOfInitializedData; 75 | DWORD SizeOfUninitializedData; 76 | DWORD AddressOfEntryPoint; 77 | DWORD BaseOfCode; 78 | DWORD BaseOfData; 79 | 80 | // 81 | // NT additional fields. 82 | // 83 | 84 | DWORD ImageBase; 85 | DWORD SectionAlignment; 86 | DWORD FileAlignment; 87 | WORD MajorOperatingSystemVersion; 88 | WORD MinorOperatingSystemVersion; 89 | WORD MajorImageVersion; 90 | WORD MinorImageVersion; 91 | WORD MajorSubsystemVersion; 92 | WORD MinorSubsystemVersion; 93 | DWORD Win32VersionValue; 94 | DWORD SizeOfImage; 95 | DWORD SizeOfHeaders; 96 | DWORD CheckSum; 97 | WORD Subsystem; 98 | WORD DllCharacteristics; 99 | DWORD SizeOfStackReserve; 100 | DWORD SizeOfStackCommit; 101 | DWORD SizeOfHeapReserve; 102 | DWORD SizeOfHeapCommit; 103 | DWORD LoaderFlags; 104 | DWORD NumberOfRvaAndSizes; 105 | IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 106 | } IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32; 107 | 108 | 109 | typedef struct _IMAGE_OPTIONAL_HEADER64 { 110 | WORD Magic; 111 | BYTE MajorLinkerVersion; 112 | BYTE MinorLinkerVersion; 113 | DWORD SizeOfCode; 114 | DWORD SizeOfInitializedData; 115 | DWORD SizeOfUninitializedData; 116 | DWORD AddressOfEntryPoint; 117 | DWORD BaseOfCode; 118 | ULONGLONG ImageBase; 119 | DWORD SectionAlignment; 120 | DWORD FileAlignment; 121 | WORD MajorOperatingSystemVersion; 122 | WORD MinorOperatingSystemVersion; 123 | WORD MajorImageVersion; 124 | WORD MinorImageVersion; 125 | WORD MajorSubsystemVersion; 126 | WORD MinorSubsystemVersion; 127 | DWORD Win32VersionValue; 128 | DWORD SizeOfImage; 129 | DWORD SizeOfHeaders; 130 | DWORD CheckSum; 131 | WORD Subsystem; 132 | WORD DllCharacteristics; 133 | ULONGLONG SizeOfStackReserve; 134 | ULONGLONG SizeOfStackCommit; 135 | ULONGLONG SizeOfHeapReserve; 136 | ULONGLONG SizeOfHeapCommit; 137 | DWORD LoaderFlags; 138 | DWORD NumberOfRvaAndSizes; 139 | IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 140 | } IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64; 141 | 142 | typedef struct _IMAGE_NT_HEADERS64 { 143 | DWORD Signature; 144 | IMAGE_FILE_HEADER FileHeader; 145 | IMAGE_OPTIONAL_HEADER64 OptionalHeader; 146 | } IMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS64; 147 | 148 | 149 | typedef struct _IMAGE_NT_HEADERS { 150 | DWORD Signature; 151 | IMAGE_FILE_HEADER FileHeader; 152 | IMAGE_OPTIONAL_HEADER32 OptionalHeader; 153 | } IMAGE_NT_HEADERS32, * PIMAGE_NT_HEADERS32; 154 | 155 | #ifdef _WIN64 156 | typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; 157 | typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; 158 | #else 159 | typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS; 160 | typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; 161 | #endif 162 | 163 | #define IMAGE_SIZEOF_SHORT_NAME 8 164 | 165 | typedef struct _IMAGE_SECTION_HEADER { 166 | BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 167 | union { 168 | DWORD PhysicalAddress; 169 | DWORD VirtualSize; 170 | } Misc; 171 | DWORD VirtualAddress; 172 | DWORD SizeOfRawData; 173 | DWORD PointerToRawData; 174 | DWORD PointerToRelocations; 175 | DWORD PointerToLinenumbers; 176 | WORD NumberOfRelocations; 177 | WORD NumberOfLinenumbers; 178 | DWORD Characteristics; 179 | } IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER; 180 | 181 | #define IMAGE_SIZEOF_SECTION_HEADER 40 182 | 183 | typedef struct _IMAGE_EXPORT_DIRECTORY { 184 | DWORD Characteristics; 185 | DWORD TimeDateStamp; 186 | WORD MajorVersion; 187 | WORD MinorVersion; 188 | DWORD Name; 189 | DWORD Base; 190 | DWORD NumberOfFunctions; 191 | DWORD NumberOfNames; 192 | DWORD AddressOfFunctions; // RVA from base of image 193 | DWORD AddressOfNames; // RVA from base of image 194 | DWORD AddressOfNameOrdinals; // RVA from base of image 195 | } IMAGE_EXPORT_DIRECTORY, * PIMAGE_EXPORT_DIRECTORY; 196 | 197 | #ifndef FIELD_OFFSET 198 | #define FIELD_OFFSET(type, field) ((LONG)(BYTE*)&(((type *)0)->field)) 199 | #define UFIELD_OFFSET(type, field) ((DWORD)(BYTE*)&(((type *)0)->field)) 200 | #endif 201 | 202 | 203 | // IMAGE_FIRST_SECTION doesn't need 32/64 versions since the file header is the same either way. 204 | 205 | #define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ 206 | ((BYTE*)(ntheader) + \ 207 | FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ 208 | ((ntheader))->FileHeader.SizeOfOptionalHeader \ 209 | )) 210 | -------------------------------------------------------------------------------- /ThreadMapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | #include "PinLocker.h" 6 | #include "Settings.h" 7 | 8 | #include 9 | #include 10 | 11 | class ThreadMapper 12 | { 13 | public: 14 | ThreadMapper() 15 | : m_LastTid(INVALID_THREADID) 16 | { 17 | PIN_InitLock(&m_Lock); 18 | } 19 | 20 | void setLastSpawningTid(const THREADID parentTid) 21 | { 22 | PinDataLock dLocker(&m_Lock); 23 | m_LastTid = parentTid; 24 | } 25 | 26 | void resetLastSpawningTid(const THREADID tid) 27 | { 28 | PinDataLock dLocker(&m_Lock); 29 | if (m_LastTid == tid) { 30 | m_LastTid = INVALID_THREADID; 31 | } 32 | } 33 | 34 | THREADID getLastSpawningTid() 35 | { 36 | PinDataLock dLocker(&m_Lock); 37 | return m_LastTid; 38 | } 39 | 40 | void eraseTid(const THREADID tid) 41 | { 42 | PinDataLock dLocker(&m_Lock); 43 | m_threadToParent.erase(tid); 44 | 45 | //erase thread from the mapping to OS thread: 46 | auto itr = m_PinTid_to_OsTid.find(tid); 47 | if (itr != m_PinTid_to_OsTid.end()) { 48 | m_OsTid_to_PinTid.erase(itr->second); 49 | m_PinTid_to_OsTid.erase(itr); 50 | } 51 | } 52 | 53 | void mapToOSTid(const THREADID tid, const OS_THREAD_ID os_tid) 54 | { 55 | PinDataLock dLocker(&m_Lock); 56 | m_PinTid_to_OsTid[tid] = os_tid; 57 | m_OsTid_to_PinTid[os_tid] = tid; 58 | } 59 | 60 | bool mapToParent(const THREADID tid) 61 | { 62 | PinDataLock dLocker(&m_Lock); 63 | if (m_LastTid == INVALID_THREADID) { 64 | return false; 65 | } 66 | #ifdef _DEBUG 67 | std::cout << std::dec << "[M] ParentThread: " << m_LastTid << " created: " << tid << std::endl; 68 | #endif //_DEBUG 69 | m_threadToParent[tid] = m_LastTid; 70 | m_LastTid = INVALID_THREADID; 71 | return true; 72 | } 73 | 74 | THREADID getParentTID(const THREADID tid) 75 | { 76 | PinDataLock dLocker(&m_Lock); 77 | THREADID parentTID = INVALID_THREADID; 78 | #ifdef _WIN32 79 | const auto parentItr = m_threadToParent.find(tid); 80 | if (parentItr != m_threadToParent.end()) { 81 | parentTID = parentItr->second; 82 | } 83 | #else 84 | const OS_THREAD_ID _parentTid = PIN_GetParentTid(); 85 | if (m_OsTid_to_PinTid.find(_parentTid) != m_OsTid_to_PinTid.end()) { 86 | parentTID = m_OsTid_to_PinTid[_parentTid]; 87 | } 88 | #endif 89 | return parentTID; 90 | } 91 | 92 | protected: 93 | PIN_LOCK m_Lock; 94 | THREADID m_LastTid; 95 | std::map m_threadToParent; 96 | std::map m_OsTid_to_PinTid; 97 | std::map m_PinTid_to_OsTid; 98 | }; 99 | 100 | /* ===================================================================== */ 101 | 102 | namespace TrackThreads 103 | { 104 | ThreadMapper g_ThreadMapper; 105 | 106 | VOID OnThreadStarted(const THREADID tid) 107 | { 108 | //map OS TID to the internal one 109 | TrackThreads::g_ThreadMapper.mapToOSTid(tid, PIN_GetTid()); 110 | #ifdef _WIN32 111 | g_ThreadMapper.mapToParent(tid); 112 | #endif //_WIN32 113 | } 114 | 115 | VOID OnThreadFinished(const THREADID tid) 116 | { 117 | g_ThreadMapper.eraseTid(tid); 118 | } 119 | 120 | THREADID GetParentTID(const THREADID tid) 121 | { 122 | return g_ThreadMapper.getParentTID(tid); 123 | } 124 | 125 | #ifdef _WIN32 126 | VOID Watch_NtCreateThread_before(const ADDRINT Address, const THREADID tid) 127 | { 128 | PinLocker locker; 129 | g_ThreadMapper.setLastSpawningTid(tid); 130 | #ifdef _DEBUG 131 | std::cout << "[!!!] Setting Parent Thread ID: " << std::dec << tid << std::endl; 132 | #endif //_DEBUG 133 | } 134 | 135 | VOID Watch_NtCreateThread_after(const ADDRINT Address, const THREADID tid, ADDRINT status) 136 | { 137 | PinLocker locker; 138 | #ifdef _DEBUG 139 | std::cout << "[!!!] Thread created by: TID: " << tid << " status: " << status << std::endl; 140 | #endif //_DEBUG 141 | if (status != 0) { 142 | g_ThreadMapper.resetLastSpawningTid(tid); 143 | } 144 | } 145 | 146 | VOID InstrumentCreateThreadRoutines(IMG Image) 147 | { 148 | if (!IMG_Valid(Image)) return; 149 | 150 | const std::string dllName = util::getDllName(IMG_Name(Image)); 151 | if (!util::iequals(dllName, "ntdll")) { 152 | return; 153 | } 154 | const size_t functionsCount = 3; 155 | static const char* functions[functionsCount] = { 156 | "NtCreateThread", 157 | "NtCreateThreadEx", 158 | "RtlCreateUserThread" 159 | }; 160 | for (size_t i = 0; i < functionsCount; i++) 161 | { 162 | const char* fName = functions[i]; 163 | const RTN funcRtn = find_by_unmangled_name(Image, fName); 164 | if (RTN_Valid(funcRtn)) { 165 | RTN_Open(funcRtn); 166 | 167 | RTN_InsertCall(funcRtn, IPOINT_BEFORE, AFUNPTR(Watch_NtCreateThread_before), 168 | IARG_RETURN_IP, 169 | IARG_THREAD_ID, 170 | 171 | IARG_END 172 | ); 173 | 174 | RTN_InsertCall(funcRtn, IPOINT_AFTER, AFUNPTR(Watch_NtCreateThread_after), 175 | IARG_RETURN_IP, 176 | IARG_THREAD_ID, 177 | IARG_FUNCRET_EXITPOINT_VALUE, //NTSTATUS 178 | IARG_END); 179 | RTN_Close(funcRtn); 180 | } 181 | } 182 | } 183 | 184 | //-- 185 | 186 | inline bool isCreateThreadSyscall(ADDRINT syscallNum) 187 | { 188 | static const size_t functionsCount = 2; 189 | static const char* functions[functionsCount] = { 190 | "NtCreateThread", 191 | "NtCreateThreadEx" 192 | }; 193 | 194 | if (syscallNum == UNKNOWN_ADDR) return false; //invalid 195 | syscallNum &= MAX_WORD; 196 | 197 | const std::string syscallFuncName = SyscallsTable::convertNameToNt(m_Settings.syscallsTable.getName(syscallNum)); 198 | if (!syscallFuncName.length()) return false; 199 | 200 | for (size_t i = 0; i < functionsCount; i++) { 201 | if (syscallFuncName.compare(functions[i]) == 0) { 202 | return true; 203 | } 204 | } 205 | return false; 206 | } 207 | 208 | VOID Watch_ThreadCreateSyscallBefore(THREADID tid, CONTEXT* ctxt, SYSCALL_STANDARD std, VOID* v) 209 | { 210 | PinLocker locker; 211 | 212 | const ADDRINT syscallNum = PIN_GetSyscallNumber(ctxt, std); 213 | if (!isCreateThreadSyscall(syscallNum)) return; 214 | g_ThreadMapper.setLastSpawningTid(tid); 215 | #ifdef _DEBUG 216 | std::cout << "S [!!!] Setting Parent Thread ID: " << std::dec << tid << std::endl; 217 | #endif //_DEBUG 218 | } 219 | 220 | VOID Watch_ThreadCreateSyscallAfter(THREADID tid, CONTEXT* ctxt, SYSCALL_STANDARD std, VOID* v) 221 | { 222 | PinLocker locker; 223 | 224 | const ADDRINT syscallNum = PIN_GetSyscallNumber(ctxt, std); 225 | if (!isCreateThreadSyscall(syscallNum)) return; 226 | 227 | const ADDRINT status = PIN_GetSyscallReturn(ctxt, std); 228 | #ifdef _DEBUG 229 | std::cout << "S [!!!] Thread created by: TID: " << tid << " status: " << status << std::endl; 230 | #endif //_DEBUG 231 | if (status != 0) { 232 | g_ThreadMapper.resetLastSpawningTid(tid); 233 | } 234 | } 235 | 236 | VOID InstrumentCreateThreadSyscalls() 237 | { 238 | PIN_AddSyscallEntryFunction(Watch_ThreadCreateSyscallBefore, NULL); 239 | PIN_AddSyscallExitFunction(Watch_ThreadCreateSyscallAfter, NULL); 240 | } 241 | #endif //_WIN32 242 | }; 243 | -------------------------------------------------------------------------------- /Settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "FuncWatch.h" 9 | #include "EvasionWatch.h" 10 | 11 | typedef enum { 12 | SHELLC_DO_NOT_FOLLOW = 0, // trace only the main target module 13 | SHELLC_FOLLOW_FIRST = 1, // follow only the first shellcode called from the main module 14 | SHELLC_FOLLOW_RECURSIVE = 2, // follow also the shellcodes called recursively from the the original shellcode 15 | SHELLC_FOLLOW_ANY = 3, // follow any shellcodes 16 | SHELLC_OPTIONS_COUNT 17 | } t_shellc_options; 18 | 19 | t_shellc_options ConvertShcOption(unsigned int value); 20 | 21 | //--- 22 | 23 | class SyscallsTable { 24 | public: 25 | static bool isSyscallFuncName(const std::string &name) 26 | { 27 | if (name.length() < 2) return false; 28 | if ((name[0] == 'Z' && name[1] == 'w') || 29 | (name[0] == 'N' && name[1] == 't' && name[2] >= 'A' && name[2] <= 'Z')) 30 | { 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | static bool isSyscallDll(const std::string& dllName) 37 | { 38 | if (util::iequals("ntdll", dllName) 39 | || util::iequals("win32u", dllName)) 40 | { 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | static std::string convertNameToNt(std::string funcName) 47 | { 48 | std::string prefix1("Nt"); 49 | std::string prefix2("Zw"); 50 | if (!funcName.compare(0, prefix2.size(), prefix2)) { 51 | funcName.replace(0, 2, prefix1); // replace with Nt prefix 52 | } 53 | return funcName; 54 | } 55 | 56 | size_t load(const std::string& file); 57 | std::string getName(int syscallID); 58 | size_t count() { return syscallToFuncName.size(); } 59 | 60 | protected: 61 | std::map syscallToFuncName; 62 | }; 63 | 64 | //--- 65 | 66 | struct StopOffset 67 | { 68 | ADDRINT rva; 69 | size_t times; 70 | 71 | StopOffset(ADDRINT _rva = 0, size_t _times = 0) 72 | : rva(_rva), times(_times) 73 | { 74 | } 75 | 76 | StopOffset(const StopOffset& other) 77 | { 78 | this->rva = other.rva; 79 | this->times = other.times; 80 | } 81 | 82 | StopOffset& operator=(const StopOffset& other) 83 | { 84 | this->rva = other.rva; 85 | this->times = other.times; 86 | return *this; 87 | } 88 | 89 | bool load(const std::string& sline, char delimiter); 90 | 91 | bool operator<(const StopOffset& other) const 92 | { 93 | return (this->rva < other.rva); 94 | } 95 | }; 96 | //--- 97 | 98 | struct DisasmRange 99 | { 100 | ADDRINT start; 101 | ADDRINT stop; 102 | std::string label; 103 | 104 | DisasmRange(ADDRINT _start, ADDRINT _stop, const std::string& _label="") 105 | : start(_start), stop(_stop), label(_label) 106 | { 107 | } 108 | 109 | bool isInRange(const ADDRINT& addr) const 110 | { 111 | if (addr == start || addr == stop) return true; 112 | return (addr >= start && addr <= stop) ? true : false; 113 | } 114 | 115 | DisasmRange& operator=(const DisasmRange& n) 116 | { 117 | this->start = n.start; 118 | this->stop = n.stop; 119 | this->label = n.label; 120 | return *this; 121 | } 122 | 123 | bool operator<(const DisasmRange& n) const 124 | { 125 | return start < n.start; 126 | } 127 | }; 128 | 129 | typedef enum disasm_status { 130 | DISASM_NONE = 0, 131 | DISASM_START = 1, 132 | DISASM_IN_RANGE = 2, 133 | DISASM_STOP = 3, 134 | COUNT_DISASM_STATUS 135 | } t_disasm_status; 136 | 137 | typedef enum { 138 | DISASM_DISABLED = 0, 139 | DISASM_OUTER = 1, 140 | DISASM_INNER = 2, 141 | DISASM_FOLLOW_THREADS = 3, 142 | DISASM_OPTIONS_COUNT 143 | } t_disasm_level; 144 | 145 | class Settings { 146 | 147 | public: 148 | static void stripComments(std::string& str); 149 | static size_t loadOffsetsList(const char* filename, std::set& offsetsList); 150 | static size_t loadCustomDefs(const char* filename, std::map &customDefs); 151 | static size_t loadDisasmRanges(const char* filename, std::set &disasmRanges); 152 | 153 | Settings() 154 | : followShellcode(SHELLC_FOLLOW_FIRST), 155 | followChildprocesses(false), 156 | traceRDTSC(false), 157 | traceINT(false), 158 | traceSYSCALL(true), 159 | logSectTrans(true), 160 | logShelcTrans(true), 161 | shortLogging(true), 162 | logIndirect(false), 163 | hexdumpSize(8), 164 | hookSleep(false), 165 | parseExports(false), 166 | sleepTime(0), 167 | stopOffsetTime(30), 168 | antidebug(WATCH_DISABLED), 169 | antivm(WATCH_DISABLED), 170 | useDebugSym(false), 171 | isHyperVSet(false), 172 | emulateSingleStep(true), 173 | disasmCtx(false), disasmDepth(DISASM_INNER), 174 | logReturn(false), followArgReturn(false), 175 | volumeID(0) 176 | { 177 | } 178 | 179 | bool loadINI(const std::string &filename); 180 | bool saveINI(const std::string &filename); 181 | 182 | size_t loadExcluded(const char* excludedList); 183 | 184 | t_shellc_options followShellcode; 185 | 186 | const t_disasm_status findInDisasmRange(const ADDRINT& addr, std::string* rangeLabel = nullptr) 187 | { 188 | for (auto itr = this->disasmRanges.begin(); itr != disasmRanges.end(); ++itr) { 189 | if (itr->isInRange(addr)) { 190 | if (rangeLabel) { 191 | (*rangeLabel) = itr->label; 192 | } 193 | if (itr->start == addr) { 194 | return DISASM_START; 195 | } 196 | if (itr->stop == addr) { 197 | return DISASM_STOP; 198 | } 199 | return DISASM_IN_RANGE; 200 | } 201 | } 202 | return DISASM_NONE; 203 | } 204 | 205 | bool followChildprocesses; // Follow Child Processes 206 | bool traceRDTSC; // Trace RDTSC 207 | bool traceINT; // trace INT 208 | bool traceSYSCALL; // Trace syscall instructions (i.e., syscall, int 2Eh, sysenter) 209 | bool logSectTrans; // watch transitions between sections 210 | bool logShelcTrans; // watch transitions between shellcodes 211 | bool shortLogging; // Use short call logging (without a full DLL path) 212 | bool logIndirect; 213 | size_t hexdumpSize; 214 | bool hookSleep; 215 | bool parseExports; 216 | size_t sleepTime; // Define the time that will be passed to the hooked sleep function (in miliseconds) 217 | size_t stopOffsetTime; // Sleep time at the stop offset (in seconds) 218 | t_watch_level antidebug; // Trace Anti-VM techniques, and bypasses some of them 219 | t_watch_level antivm; // Trace Anti-VM techniques, and bypasses some of them 220 | bool useDebugSym; 221 | bool isHyperVSet; // emulate HyperV via CPUID (it changes execution path of some protectors, i.e. VMProtect). Works when antivm is enabled. 222 | bool emulateSingleStep; // If the Trap Flag is set, throw a SINGLE_STEP exception emulating the typical behavior. Works when antidebug is enabled. 223 | bool disasmCtx; // show context in a disasm mode 224 | t_disasm_level disasmDepth; //in disasm mode: define how to follow the disasm range 225 | bool logReturn; // Log return value 226 | bool followArgReturn; // Log changes of args and returns ptr 227 | uint32_t volumeID; 228 | 229 | SyscallsTable syscallsTable; //Syscalls table: mapping the syscall ID to the function name 230 | FuncWatchList funcWatch; //List of functions, arguments of which are going to be logged 231 | FuncList excludedFuncs; //List of functions that will NOT be logged 232 | std::set excludedDll; //List of DLLs calls from which will NOT be logged 233 | std::set stopOffsets; //List of offsets at which the execution should pause 234 | std::map customDefs; 235 | std::set disasmRanges; 236 | }; 237 | -------------------------------------------------------------------------------- /Crc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // From: https://github.com/srned/baselib 3 | /* Redis uses the CRC64 variant with "Jones" coefficients and init value of 0. 4 | * 5 | * Specification of this CRC64 variant follows: 6 | * Name: crc-64-jones 7 | * Width: 64 bites 8 | * Poly: 0xad93d23594c935a9 9 | * Reflected In: True 10 | * Xor_In: 0xffffffffffffffff 11 | * Reflected_Out: True 12 | * Xor_Out: 0x0 13 | * Check("123456789"): 0xe9c6d914c4b8d9ca 14 | * 15 | * Copyright (c) 2012, Salvatore Sanfilippo 16 | * All rights reserved. 17 | * 18 | * Redistribution and use in source and binary forms, with or without 19 | * modification, are permitted provided that the following conditions are met: 20 | * 21 | * * Redistributions of source code must retain the above copyright notice, 22 | * this list of conditions and the following disclaimer. 23 | * * Redistributions in binary form must reproduce the above copyright 24 | * notice, this list of conditions and the following disclaimer in the 25 | * documentation and/or other materials provided with the distribution. 26 | * * Neither the name of Redis nor the names of its contributors may be used 27 | * to endorse or promote products derived from this software without 28 | * specific prior written permission. 29 | * 30 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 | * POSSIBILITY OF SUCH DAMAGE. */ 41 | 42 | #include 43 | 44 | static const uint64_t crc64_tab[256] = { 45 | UINT64_C(0x0000000000000000), UINT64_C(0x7ad870c830358979), 46 | UINT64_C(0xf5b0e190606b12f2), UINT64_C(0x8f689158505e9b8b), 47 | UINT64_C(0xc038e5739841b68f), UINT64_C(0xbae095bba8743ff6), 48 | UINT64_C(0x358804e3f82aa47d), UINT64_C(0x4f50742bc81f2d04), 49 | UINT64_C(0xab28ecb46814fe75), UINT64_C(0xd1f09c7c5821770c), 50 | UINT64_C(0x5e980d24087fec87), UINT64_C(0x24407dec384a65fe), 51 | UINT64_C(0x6b1009c7f05548fa), UINT64_C(0x11c8790fc060c183), 52 | UINT64_C(0x9ea0e857903e5a08), UINT64_C(0xe478989fa00bd371), 53 | UINT64_C(0x7d08ff3b88be6f81), UINT64_C(0x07d08ff3b88be6f8), 54 | UINT64_C(0x88b81eabe8d57d73), UINT64_C(0xf2606e63d8e0f40a), 55 | UINT64_C(0xbd301a4810ffd90e), UINT64_C(0xc7e86a8020ca5077), 56 | UINT64_C(0x4880fbd87094cbfc), UINT64_C(0x32588b1040a14285), 57 | UINT64_C(0xd620138fe0aa91f4), UINT64_C(0xacf86347d09f188d), 58 | UINT64_C(0x2390f21f80c18306), UINT64_C(0x594882d7b0f40a7f), 59 | UINT64_C(0x1618f6fc78eb277b), UINT64_C(0x6cc0863448deae02), 60 | UINT64_C(0xe3a8176c18803589), UINT64_C(0x997067a428b5bcf0), 61 | UINT64_C(0xfa11fe77117cdf02), UINT64_C(0x80c98ebf2149567b), 62 | UINT64_C(0x0fa11fe77117cdf0), UINT64_C(0x75796f2f41224489), 63 | UINT64_C(0x3a291b04893d698d), UINT64_C(0x40f16bccb908e0f4), 64 | UINT64_C(0xcf99fa94e9567b7f), UINT64_C(0xb5418a5cd963f206), 65 | UINT64_C(0x513912c379682177), UINT64_C(0x2be1620b495da80e), 66 | UINT64_C(0xa489f35319033385), UINT64_C(0xde51839b2936bafc), 67 | UINT64_C(0x9101f7b0e12997f8), UINT64_C(0xebd98778d11c1e81), 68 | UINT64_C(0x64b116208142850a), UINT64_C(0x1e6966e8b1770c73), 69 | UINT64_C(0x8719014c99c2b083), UINT64_C(0xfdc17184a9f739fa), 70 | UINT64_C(0x72a9e0dcf9a9a271), UINT64_C(0x08719014c99c2b08), 71 | UINT64_C(0x4721e43f0183060c), UINT64_C(0x3df994f731b68f75), 72 | UINT64_C(0xb29105af61e814fe), UINT64_C(0xc849756751dd9d87), 73 | UINT64_C(0x2c31edf8f1d64ef6), UINT64_C(0x56e99d30c1e3c78f), 74 | UINT64_C(0xd9810c6891bd5c04), UINT64_C(0xa3597ca0a188d57d), 75 | UINT64_C(0xec09088b6997f879), UINT64_C(0x96d1784359a27100), 76 | UINT64_C(0x19b9e91b09fcea8b), UINT64_C(0x636199d339c963f2), 77 | UINT64_C(0xdf7adabd7a6e2d6f), UINT64_C(0xa5a2aa754a5ba416), 78 | UINT64_C(0x2aca3b2d1a053f9d), UINT64_C(0x50124be52a30b6e4), 79 | UINT64_C(0x1f423fcee22f9be0), UINT64_C(0x659a4f06d21a1299), 80 | UINT64_C(0xeaf2de5e82448912), UINT64_C(0x902aae96b271006b), 81 | UINT64_C(0x74523609127ad31a), UINT64_C(0x0e8a46c1224f5a63), 82 | UINT64_C(0x81e2d7997211c1e8), UINT64_C(0xfb3aa75142244891), 83 | UINT64_C(0xb46ad37a8a3b6595), UINT64_C(0xceb2a3b2ba0eecec), 84 | UINT64_C(0x41da32eaea507767), UINT64_C(0x3b024222da65fe1e), 85 | UINT64_C(0xa2722586f2d042ee), UINT64_C(0xd8aa554ec2e5cb97), 86 | UINT64_C(0x57c2c41692bb501c), UINT64_C(0x2d1ab4dea28ed965), 87 | UINT64_C(0x624ac0f56a91f461), UINT64_C(0x1892b03d5aa47d18), 88 | UINT64_C(0x97fa21650afae693), UINT64_C(0xed2251ad3acf6fea), 89 | UINT64_C(0x095ac9329ac4bc9b), UINT64_C(0x7382b9faaaf135e2), 90 | UINT64_C(0xfcea28a2faafae69), UINT64_C(0x8632586aca9a2710), 91 | UINT64_C(0xc9622c4102850a14), UINT64_C(0xb3ba5c8932b0836d), 92 | UINT64_C(0x3cd2cdd162ee18e6), UINT64_C(0x460abd1952db919f), 93 | UINT64_C(0x256b24ca6b12f26d), UINT64_C(0x5fb354025b277b14), 94 | UINT64_C(0xd0dbc55a0b79e09f), UINT64_C(0xaa03b5923b4c69e6), 95 | UINT64_C(0xe553c1b9f35344e2), UINT64_C(0x9f8bb171c366cd9b), 96 | UINT64_C(0x10e3202993385610), UINT64_C(0x6a3b50e1a30ddf69), 97 | UINT64_C(0x8e43c87e03060c18), UINT64_C(0xf49bb8b633338561), 98 | UINT64_C(0x7bf329ee636d1eea), UINT64_C(0x012b592653589793), 99 | UINT64_C(0x4e7b2d0d9b47ba97), UINT64_C(0x34a35dc5ab7233ee), 100 | UINT64_C(0xbbcbcc9dfb2ca865), UINT64_C(0xc113bc55cb19211c), 101 | UINT64_C(0x5863dbf1e3ac9dec), UINT64_C(0x22bbab39d3991495), 102 | UINT64_C(0xadd33a6183c78f1e), UINT64_C(0xd70b4aa9b3f20667), 103 | UINT64_C(0x985b3e827bed2b63), UINT64_C(0xe2834e4a4bd8a21a), 104 | UINT64_C(0x6debdf121b863991), UINT64_C(0x1733afda2bb3b0e8), 105 | UINT64_C(0xf34b37458bb86399), UINT64_C(0x8993478dbb8deae0), 106 | UINT64_C(0x06fbd6d5ebd3716b), UINT64_C(0x7c23a61ddbe6f812), 107 | UINT64_C(0x3373d23613f9d516), UINT64_C(0x49aba2fe23cc5c6f), 108 | UINT64_C(0xc6c333a67392c7e4), UINT64_C(0xbc1b436e43a74e9d), 109 | UINT64_C(0x95ac9329ac4bc9b5), UINT64_C(0xef74e3e19c7e40cc), 110 | UINT64_C(0x601c72b9cc20db47), UINT64_C(0x1ac40271fc15523e), 111 | UINT64_C(0x5594765a340a7f3a), UINT64_C(0x2f4c0692043ff643), 112 | UINT64_C(0xa02497ca54616dc8), UINT64_C(0xdafce7026454e4b1), 113 | UINT64_C(0x3e847f9dc45f37c0), UINT64_C(0x445c0f55f46abeb9), 114 | UINT64_C(0xcb349e0da4342532), UINT64_C(0xb1eceec59401ac4b), 115 | UINT64_C(0xfebc9aee5c1e814f), UINT64_C(0x8464ea266c2b0836), 116 | UINT64_C(0x0b0c7b7e3c7593bd), UINT64_C(0x71d40bb60c401ac4), 117 | UINT64_C(0xe8a46c1224f5a634), UINT64_C(0x927c1cda14c02f4d), 118 | UINT64_C(0x1d148d82449eb4c6), UINT64_C(0x67ccfd4a74ab3dbf), 119 | UINT64_C(0x289c8961bcb410bb), UINT64_C(0x5244f9a98c8199c2), 120 | UINT64_C(0xdd2c68f1dcdf0249), UINT64_C(0xa7f41839ecea8b30), 121 | UINT64_C(0x438c80a64ce15841), UINT64_C(0x3954f06e7cd4d138), 122 | UINT64_C(0xb63c61362c8a4ab3), UINT64_C(0xcce411fe1cbfc3ca), 123 | UINT64_C(0x83b465d5d4a0eece), UINT64_C(0xf96c151de49567b7), 124 | UINT64_C(0x76048445b4cbfc3c), UINT64_C(0x0cdcf48d84fe7545), 125 | UINT64_C(0x6fbd6d5ebd3716b7), UINT64_C(0x15651d968d029fce), 126 | UINT64_C(0x9a0d8ccedd5c0445), UINT64_C(0xe0d5fc06ed698d3c), 127 | UINT64_C(0xaf85882d2576a038), UINT64_C(0xd55df8e515432941), 128 | UINT64_C(0x5a3569bd451db2ca), UINT64_C(0x20ed197575283bb3), 129 | UINT64_C(0xc49581ead523e8c2), UINT64_C(0xbe4df122e51661bb), 130 | UINT64_C(0x3125607ab548fa30), UINT64_C(0x4bfd10b2857d7349), 131 | UINT64_C(0x04ad64994d625e4d), UINT64_C(0x7e7514517d57d734), 132 | UINT64_C(0xf11d85092d094cbf), UINT64_C(0x8bc5f5c11d3cc5c6), 133 | UINT64_C(0x12b5926535897936), UINT64_C(0x686de2ad05bcf04f), 134 | UINT64_C(0xe70573f555e26bc4), UINT64_C(0x9ddd033d65d7e2bd), 135 | UINT64_C(0xd28d7716adc8cfb9), UINT64_C(0xa85507de9dfd46c0), 136 | UINT64_C(0x273d9686cda3dd4b), UINT64_C(0x5de5e64efd965432), 137 | UINT64_C(0xb99d7ed15d9d8743), UINT64_C(0xc3450e196da80e3a), 138 | UINT64_C(0x4c2d9f413df695b1), UINT64_C(0x36f5ef890dc31cc8), 139 | UINT64_C(0x79a59ba2c5dc31cc), UINT64_C(0x037deb6af5e9b8b5), 140 | UINT64_C(0x8c157a32a5b7233e), UINT64_C(0xf6cd0afa9582aa47), 141 | UINT64_C(0x4ad64994d625e4da), UINT64_C(0x300e395ce6106da3), 142 | UINT64_C(0xbf66a804b64ef628), UINT64_C(0xc5bed8cc867b7f51), 143 | UINT64_C(0x8aeeace74e645255), UINT64_C(0xf036dc2f7e51db2c), 144 | UINT64_C(0x7f5e4d772e0f40a7), UINT64_C(0x05863dbf1e3ac9de), 145 | UINT64_C(0xe1fea520be311aaf), UINT64_C(0x9b26d5e88e0493d6), 146 | UINT64_C(0x144e44b0de5a085d), UINT64_C(0x6e963478ee6f8124), 147 | UINT64_C(0x21c640532670ac20), UINT64_C(0x5b1e309b16452559), 148 | UINT64_C(0xd476a1c3461bbed2), UINT64_C(0xaeaed10b762e37ab), 149 | UINT64_C(0x37deb6af5e9b8b5b), UINT64_C(0x4d06c6676eae0222), 150 | UINT64_C(0xc26e573f3ef099a9), UINT64_C(0xb8b627f70ec510d0), 151 | UINT64_C(0xf7e653dcc6da3dd4), UINT64_C(0x8d3e2314f6efb4ad), 152 | UINT64_C(0x0256b24ca6b12f26), UINT64_C(0x788ec2849684a65f), 153 | UINT64_C(0x9cf65a1b368f752e), UINT64_C(0xe62e2ad306bafc57), 154 | UINT64_C(0x6946bb8b56e467dc), UINT64_C(0x139ecb4366d1eea5), 155 | UINT64_C(0x5ccebf68aecec3a1), UINT64_C(0x2616cfa09efb4ad8), 156 | UINT64_C(0xa97e5ef8cea5d153), UINT64_C(0xd3a62e30fe90582a), 157 | UINT64_C(0xb0c7b7e3c7593bd8), UINT64_C(0xca1fc72bf76cb2a1), 158 | UINT64_C(0x45775673a732292a), UINT64_C(0x3faf26bb9707a053), 159 | UINT64_C(0x70ff52905f188d57), UINT64_C(0x0a2722586f2d042e), 160 | UINT64_C(0x854fb3003f739fa5), UINT64_C(0xff97c3c80f4616dc), 161 | UINT64_C(0x1bef5b57af4dc5ad), UINT64_C(0x61372b9f9f784cd4), 162 | UINT64_C(0xee5fbac7cf26d75f), UINT64_C(0x9487ca0fff135e26), 163 | UINT64_C(0xdbd7be24370c7322), UINT64_C(0xa10fceec0739fa5b), 164 | UINT64_C(0x2e675fb4576761d0), UINT64_C(0x54bf2f7c6752e8a9), 165 | UINT64_C(0xcdcf48d84fe75459), UINT64_C(0xb71738107fd2dd20), 166 | UINT64_C(0x387fa9482f8c46ab), UINT64_C(0x42a7d9801fb9cfd2), 167 | UINT64_C(0x0df7adabd7a6e2d6), UINT64_C(0x772fdd63e7936baf), 168 | UINT64_C(0xf8474c3bb7cdf024), UINT64_C(0x829f3cf387f8795d), 169 | UINT64_C(0x66e7a46c27f3aa2c), UINT64_C(0x1c3fd4a417c62355), 170 | UINT64_C(0x935745fc4798b8de), UINT64_C(0xe98f353477ad31a7), 171 | UINT64_C(0xa6df411fbfb21ca3), UINT64_C(0xdc0731d78f8795da), 172 | UINT64_C(0x536fa08fdfd90e51), UINT64_C(0x29b7d047efec8728), 173 | }; 174 | 175 | uint64_t crc64(uint64_t crc, const unsigned char* s, uint64_t l) { 176 | uint64_t j; 177 | 178 | for (j = 0; j < l; j++) { 179 | uint8_t byte = s[j]; 180 | crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8); 181 | } 182 | return crc; 183 | } 184 | -------------------------------------------------------------------------------- /Settings.cpp: -------------------------------------------------------------------------------- 1 | #include "Settings.h" 2 | #include "Util.h" 3 | 4 | #include "FuncWatch.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define DELIM '=' 11 | 12 | #define KEY_FOLLOW_SHELLCODES "FOLLOW_SHELLCODES" 13 | #define KEY_FOLLOW_CHILDPROCESSES "FOLLOW_CHILDPROCESSES" 14 | #define KEY_LOG_RTDSC "TRACE_RDTSC" 15 | #define KEY_LOG_INT "TRACE_INT" 16 | #define KEY_LOG_SYSCALL "TRACE_SYSCALL" 17 | #define KEY_LOG_SECTIONS_TRANSITIONS "LOG_SECTIONS_TRANSITIONS" 18 | #define KEY_LOG_SHELLCODES_TRANSITIONS "LOG_SHELLCODES_TRANSITIONS" 19 | #define KEY_SHORT_LOGGING "ENABLE_SHORT_LOGGING" 20 | #define HEXDUMP_SIZE "HEXDUMP_SIZE" 21 | #define SLEEP_TIME "SLEEP_TIME" 22 | #define HOOK_SLEEP "HOOK_SLEEP" 23 | #define LOG_INDIRECT "LOG_INDIRECT_CALLS" 24 | #define KEY_ANTIDEBUG "ANTIDEBUG" 25 | #define KEY_ANTIVM "ANTIVM" 26 | #define KEY_USE_DEBUG_SYMBOLS "USE_DEBUG_SYMBOLS" 27 | #define KEY_HYPREV_SET "EMULATE_HYPERV" 28 | #define KEY_STOP_OFFSET_TIME "STOP_OFFSET_TIME" 29 | #define KEY_EMULATE_SINGLE_STEP "EMULATE_SINGLE_STEP" 30 | #define KEY_DISASM_CTX "DISASM_CTX" 31 | #define KEY_DISASM_DEPTH "DISASM_DEPTH" 32 | #define KEY_LOG_RETURN_VALUE "LOG_RETURN_VALUE" 33 | #define KEY_FOLLOW_ARGS_RETURN "FOLLOW_ARGS_RETURN" 34 | #define KEY_PARSE_EXPORTS "PARSE_EXPORTS" 35 | #define KEY_VOLUME_ID "VOLUME_ID" 36 | 37 | t_shellc_options ConvertShcOption(unsigned int value) 38 | { 39 | if (value >= SHELLC_OPTIONS_COUNT) { 40 | // choose the last option: 41 | return t_shellc_options(SHELLC_OPTIONS_COUNT - 1); 42 | } 43 | return (t_shellc_options)value; 44 | } 45 | 46 | t_disasm_level ConvertDisasmLevel(unsigned int value) 47 | { 48 | if (value >= DISASM_OPTIONS_COUNT) { 49 | // choose the last option: 50 | return t_disasm_level(DISASM_OPTIONS_COUNT - 1); 51 | } 52 | return (t_disasm_level)value; 53 | } 54 | //---- 55 | 56 | std::string SyscallsTable::getName(int syscallID) 57 | { 58 | auto found = syscallToFuncName.find(syscallID); 59 | if (found == syscallToFuncName.end()) { 60 | return ""; 61 | } 62 | return found->second; 63 | } 64 | 65 | size_t SyscallsTable::load(const std::string& filename) 66 | { 67 | std::ifstream myfile(util::stripQuotes(filename).c_str()); 68 | if (!myfile.is_open()) { 69 | return 0; 70 | } 71 | const size_t MAX_LINE = 300; 72 | char line[MAX_LINE] = { 0 }; 73 | 74 | while (!myfile.eof()) { 75 | myfile.getline(line, MAX_LINE); 76 | std::string lineStr = line; 77 | size_t found = lineStr.find_first_of(","); 78 | if (found != std::string::npos) { 79 | 80 | std::string numId = lineStr.substr(0, found); 81 | std::string funcName = lineStr.substr(found + 1); 82 | int syscallId = util::loadInt(numId, true); 83 | 84 | syscallToFuncName[syscallId] = funcName; 85 | } 86 | } 87 | myfile.close(); 88 | return syscallToFuncName.size(); 89 | } 90 | //---- 91 | 92 | bool StopOffset::load(const std::string& sline, char delimiter) 93 | { 94 | std::vector args; 95 | util::splitList(sline, delimiter, args); 96 | if (!args.size()) return false; 97 | 98 | this->rva = util::loadInt(args[0], true); 99 | if (!this->rva) { 100 | return false; 101 | } 102 | // optional argument: 103 | if (args.size() >= 2) { 104 | this->times = util::loadInt(args[1], false); 105 | } 106 | return true; 107 | } 108 | 109 | //--- 110 | 111 | bool loadBoolean(const std::string &str) 112 | { 113 | if (util::iequals(str, "True") || util::iequals(str, "on") || util::iequals(str, "yes")) { 114 | return true; 115 | } 116 | if (util::iequals(str, "False") || util::iequals(str, "off") || util::iequals(str, "no")) { 117 | return false; 118 | } 119 | const int val = util::loadInt(str); 120 | if (val == 0) return false; 121 | return true; 122 | } 123 | 124 | std::string booleanToStr(const bool &val) 125 | { 126 | return (val) ? "True" : "False"; 127 | } 128 | 129 | bool parseRange(const std::string &token, std::set& disasmRanges) 130 | { 131 | const char delim = ','; 132 | 133 | size_t rangeCount = 0; 134 | std::stringstream pairStream(token); 135 | std::string startHex, endHex; 136 | std::string rangeName; 137 | 138 | if (std::getline(pairStream, startHex, delim) && (std::getline(pairStream, endHex, delim) || std::getline(pairStream, endHex))) { 139 | rangeCount++; 140 | if (!std::getline(pairStream, rangeName)) { 141 | std::stringstream ss; 142 | ss << "Range_" << std::dec << rangeCount; 143 | rangeName = ss.str(); 144 | } 145 | int start = util::loadInt(startHex, true); 146 | if (start == 0) return false; 147 | int stop = util::loadInt(endHex, true); 148 | 149 | DisasmRange r(start, stop, rangeName); 150 | disasmRanges.insert(r); 151 | return true; 152 | } 153 | return false; 154 | } 155 | 156 | std::string rangesToStr(const std::set& disasmRanges) 157 | { 158 | std::stringstream ss; 159 | for (auto itr = disasmRanges.begin(); itr != disasmRanges.end(); ++itr) { 160 | ss << "[" << std::hex << itr->start << "," << itr->stop << "]"; 161 | } 162 | return ss.str(); 163 | } 164 | 165 | bool fillSettings(Settings &s, const std::string &line) 166 | { 167 | std::vector args; 168 | util::splitList(line, DELIM, args); 169 | 170 | if (args.size() < 2) { 171 | return false; 172 | } 173 | bool isFilled = false; 174 | std::string valName = args[0]; 175 | std::string valStr = args[1]; 176 | util::trim(valName); 177 | util::trim(valStr); 178 | 179 | if (util::iequals(valName, KEY_FOLLOW_SHELLCODES)) { 180 | const int val = util::loadInt(valStr); 181 | s.followShellcode = ConvertShcOption(val); 182 | isFilled = true; 183 | } 184 | if (util::iequals(valName, KEY_FOLLOW_CHILDPROCESSES)) { 185 | s.followChildprocesses = loadBoolean(valStr); 186 | isFilled = true; 187 | } 188 | if (util::iequals(valName, KEY_LOG_RTDSC)) { 189 | s.traceRDTSC = loadBoolean(valStr); 190 | isFilled = true; 191 | } 192 | if (util::iequals(valName, KEY_LOG_INT)) { 193 | s.traceINT = loadBoolean(valStr); 194 | isFilled = true; 195 | } 196 | if (util::iequals(valName, KEY_LOG_SYSCALL)) { 197 | s.traceSYSCALL = loadBoolean(valStr); 198 | isFilled = true; 199 | } 200 | if (util::iequals(valName, KEY_LOG_SECTIONS_TRANSITIONS)) { 201 | s.logSectTrans = loadBoolean(valStr); 202 | isFilled = true; 203 | } 204 | if (util::iequals(valName, KEY_LOG_SHELLCODES_TRANSITIONS)) { 205 | s.logShelcTrans = loadBoolean(valStr); 206 | isFilled = true; 207 | } 208 | if (util::iequals(valName, KEY_SHORT_LOGGING)) { 209 | s.shortLogging = loadBoolean(valStr); 210 | isFilled = true; 211 | } 212 | if (util::iequals(valName, HEXDUMP_SIZE)) { 213 | s.hexdumpSize = util::loadInt(valStr); 214 | isFilled = true; 215 | } 216 | if (util::iequals(valName, LOG_INDIRECT)) { 217 | s.logIndirect = loadBoolean(valStr); 218 | isFilled = true; 219 | } 220 | if (util::iequals(valName, HOOK_SLEEP)) { 221 | s.hookSleep = loadBoolean(valStr); 222 | isFilled = true; 223 | } 224 | if (util::iequals(valName, SLEEP_TIME)) { 225 | s.sleepTime = util::loadInt(valStr); 226 | isFilled = true; 227 | } 228 | if (util::iequals(valName, KEY_STOP_OFFSET_TIME)) { 229 | s.stopOffsetTime = util::loadInt(valStr); 230 | isFilled = true; 231 | } 232 | if (util::iequals(valName, KEY_ANTIDEBUG)) { 233 | const int val = util::loadInt(valStr); 234 | s.antidebug = ConvertWatchLevel(val); 235 | isFilled = true; 236 | } 237 | if (util::iequals(valName, KEY_ANTIVM)) { 238 | const int val = util::loadInt(valStr); 239 | s.antivm = ConvertWatchLevel(val); 240 | isFilled = true; 241 | } 242 | if (util::iequals(valName, KEY_USE_DEBUG_SYMBOLS)) { 243 | s.useDebugSym = loadBoolean(valStr); 244 | isFilled = true; 245 | } 246 | if (util::iequals(valName, KEY_HYPREV_SET)) { 247 | s.isHyperVSet = loadBoolean(valStr); 248 | isFilled = true; 249 | } 250 | if (util::iequals(valName, KEY_EMULATE_SINGLE_STEP)) { 251 | s.emulateSingleStep = loadBoolean(valStr); 252 | isFilled = true; 253 | } 254 | if (util::iequals(valName, KEY_DISASM_CTX)) { 255 | s.disasmCtx = loadBoolean(valStr); 256 | isFilled = true; 257 | } 258 | if (util::iequals(valName, KEY_DISASM_DEPTH)) { 259 | const int val = util::loadInt(valStr); 260 | s.disasmDepth = ConvertDisasmLevel(val); 261 | isFilled = true; 262 | } 263 | if (util::iequals(valName, KEY_LOG_RETURN_VALUE)) { 264 | s.logReturn = loadBoolean(valStr); 265 | isFilled = true; 266 | } 267 | if (util::iequals(valName, KEY_FOLLOW_ARGS_RETURN)) { 268 | s.followArgReturn = loadBoolean(valStr); 269 | isFilled = true; 270 | } 271 | if (util::iequals(valName, KEY_PARSE_EXPORTS)) { 272 | s.parseExports = loadBoolean(valStr); 273 | isFilled = true; 274 | } 275 | if (util::iequals(valName, KEY_VOLUME_ID)) { 276 | s.volumeID = util::loadInt(valStr, true); 277 | isFilled = true; 278 | } 279 | return isFilled; 280 | } 281 | 282 | void Settings::stripComments(std::string &str) 283 | { 284 | size_t found = str.find_first_of(";#"); 285 | if (found != std::string::npos) { 286 | str.resize(found); 287 | } 288 | } 289 | 290 | size_t Settings::loadOffsetsList(const char* filename, std::set& offsetsList) 291 | { 292 | std::ifstream myfile(filename); 293 | if (!myfile.is_open()) { 294 | std::cerr << "Failed to open file: " << filename << std::endl; 295 | return 0; 296 | } 297 | const size_t MAX_LINE = 300; 298 | char line[MAX_LINE] = { 0 }; 299 | while (!myfile.eof()) { 300 | myfile.getline(line, MAX_LINE); 301 | std::string str = line; 302 | if (!str.size() || str[0] == '#') { // skip empty lines and comments 303 | continue; 304 | } 305 | StopOffset so; 306 | if (so.load(str, LIST_DELIMITER)) { 307 | offsetsList.insert(so); 308 | } 309 | } 310 | return offsetsList.size(); 311 | } 312 | 313 | 314 | size_t Settings::loadCustomDefs(const char* filename, std::map& customDefs) 315 | { 316 | std::ifstream myfile(filename); 317 | if (!myfile.is_open()) { 318 | return 0; 319 | } 320 | const size_t MAX_LINE = 300; 321 | char line[MAX_LINE] = { 0 }; 322 | while (!myfile.eof()) { 323 | myfile.getline(line, MAX_LINE); 324 | std::string sline = line; 325 | util::trim(sline); 326 | if (!sline.size() || sline[0] == '#') { // skip empty lines and comments 327 | continue; 328 | } 329 | 330 | std::vector args; 331 | util::splitList(sline, ',', args); 332 | if (args.size() < 2) break; 333 | 334 | const ADDRINT rva = util::loadInt(args[0], true); 335 | std::string name = args[1]; 336 | customDefs[rva] = name; 337 | } 338 | return customDefs.size(); 339 | } 340 | 341 | size_t Settings::loadDisasmRanges(const char* filename, std::set& disasmRanges) 342 | { 343 | std::ifstream myfile(filename); 344 | if (!myfile.is_open()) { 345 | return 0; 346 | } 347 | const size_t MAX_LINE = 300; 348 | char line[MAX_LINE] = { 0 }; 349 | while (!myfile.eof()) { 350 | myfile.getline(line, MAX_LINE); 351 | std::string sline = line; 352 | util::trim(sline); 353 | if (!sline.size() || sline[0] == '#') { // skip empty lines and comments 354 | continue; 355 | } 356 | parseRange(sline, disasmRanges); 357 | } 358 | return disasmRanges.size(); 359 | } 360 | 361 | bool Settings::saveINI(const std::string &filename) 362 | { 363 | std::ofstream myfile(filename.c_str()); 364 | if (!myfile.is_open()) { 365 | return false; 366 | } 367 | myfile << KEY_FOLLOW_SHELLCODES << DELIM << this->followShellcode << "\r\n"; 368 | myfile << KEY_FOLLOW_CHILDPROCESSES << DELIM << this->followChildprocesses << "\r\n"; 369 | myfile << KEY_LOG_RTDSC << DELIM << booleanToStr(this->traceRDTSC) << "\r\n"; 370 | myfile << KEY_LOG_INT << DELIM << booleanToStr(this->traceINT) << "\r\n"; 371 | myfile << KEY_LOG_SYSCALL << DELIM << booleanToStr(this->traceSYSCALL) << "\r\n"; 372 | myfile << KEY_LOG_SECTIONS_TRANSITIONS << DELIM << booleanToStr(this->logSectTrans) << "\r\n"; 373 | myfile << KEY_LOG_SHELLCODES_TRANSITIONS << DELIM << booleanToStr(this->logShelcTrans) << "\r\n"; 374 | myfile << KEY_SHORT_LOGGING << DELIM << booleanToStr(this->shortLogging) << "\r\n"; 375 | myfile << KEY_USE_DEBUG_SYMBOLS << DELIM << booleanToStr(this->useDebugSym) << "\r\n"; 376 | myfile << HEXDUMP_SIZE << DELIM << std::dec << this->hexdumpSize << "\r\n"; 377 | myfile << HOOK_SLEEP << DELIM << std::dec << booleanToStr(this->hookSleep) << "\r\n"; 378 | myfile << SLEEP_TIME << DELIM << std::dec << this->sleepTime << "\r\n"; 379 | myfile << LOG_INDIRECT << DELIM << booleanToStr(this->logIndirect) << "\r\n"; 380 | myfile << KEY_ANTIDEBUG << DELIM << this->antidebug << "\r\n"; 381 | myfile << KEY_ANTIVM << DELIM << this->antivm << "\r\n"; 382 | myfile << KEY_HYPREV_SET << DELIM << booleanToStr(this->isHyperVSet) << "\r\n"; 383 | myfile << KEY_STOP_OFFSET_TIME << DELIM << std::dec << this->stopOffsetTime << "\r\n"; 384 | myfile << KEY_EMULATE_SINGLE_STEP << DELIM << std::dec << booleanToStr(this->emulateSingleStep) << "\r\n"; 385 | myfile << KEY_DISASM_CTX << DELIM << std::dec << booleanToStr(this->disasmCtx) << "\r\n"; 386 | myfile << KEY_DISASM_DEPTH << DELIM << std::dec << this->disasmDepth << "\r\n"; 387 | myfile << KEY_LOG_RETURN_VALUE << DELIM << std::dec << booleanToStr(this->logReturn) << "\r\n"; 388 | myfile << KEY_FOLLOW_ARGS_RETURN << DELIM << std::dec << booleanToStr(this->followArgReturn) << "\r\n"; 389 | myfile << KEY_PARSE_EXPORTS << DELIM << std::dec << booleanToStr(this->parseExports) << "\r\n"; 390 | myfile << KEY_VOLUME_ID << DELIM << std::hex << this->volumeID << "\r\n"; 391 | myfile.close(); 392 | return true; 393 | } 394 | 395 | bool Settings::loadINI(const std::string &filename) 396 | { 397 | std::ifstream myfile(filename.c_str()); 398 | if (!myfile.is_open()) { 399 | return false; 400 | } 401 | const size_t MAX_LINE = 300; 402 | char line[MAX_LINE] = { 0 }; 403 | bool filledAny = false; 404 | 405 | while (!myfile.eof()) { 406 | myfile.getline(line, MAX_LINE); 407 | std::string lineStr = line; 408 | stripComments(lineStr); 409 | 410 | if (fillSettings(*this, lineStr)) { 411 | filledAny = true; 412 | } 413 | } 414 | myfile.close(); 415 | return filledAny; 416 | } 417 | 418 | size_t Settings::loadExcluded(const char* excludedList) 419 | { 420 | this->excludedFuncs.loadList(excludedList); 421 | 422 | std::ifstream myfile(excludedList); 423 | if (!myfile.is_open()) { 424 | return 0; 425 | } 426 | size_t dllsCount = 0; 427 | const size_t MAX_LINE = 300; 428 | char line[MAX_LINE] = { 0 }; 429 | while (!myfile.eof()) { 430 | myfile.getline(line, MAX_LINE); 431 | 432 | if (strchr(line, LIST_DELIMITER) != nullptr) { 433 | continue; 434 | } 435 | this->excludedDll.insert(line); 436 | dllsCount++; 437 | } 438 | return dllsCount; 439 | } 440 | 441 | -------------------------------------------------------------------------------- /AntiVm.cpp: -------------------------------------------------------------------------------- 1 | #include "AntiVm.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ProcessInfo.h" 9 | #include "Util.h" 10 | #include "TraceLog.h" 11 | #include "Settings.h" 12 | #include "PinLocker.h" 13 | #include "TinyTracer.h" 14 | 15 | #include "EvasionWatch.h" 16 | 17 | #define ANTIVM_LABEL "[ANTIVM] --> " 18 | 19 | using namespace LEVEL_PINCLIENT; 20 | 21 | /* ================================================================== */ 22 | // Global variables used by AntiVm 23 | /* ================================================================== */ 24 | #define PATH_BUFSIZE 512 25 | #define WMI_NUMBER_CORES "NUMBEROFCORES" 26 | #define WMI_PROCESSOR "PROCESSORID" 27 | #define WMI_SIZE "SIZE" 28 | #define WMI_DEVICE_ID "DEVICEID" 29 | #define WMI_MAC_ADDRESS "MACADDRESS" 30 | #define WMI_TEMPERATURE "CURRENTTEMPERATURE" 31 | #define WMI_SERIAL "SERIALNUMBER" 32 | #define WMI_MODEL "MODEL" 33 | #define WMI_MANUFACTURER "MANUFACTURER" 34 | #define WMI_GPU_ADAPTER "ADAPTERCOMPATIBILITY" 35 | #define WMI_PRODUCT "PRODUCT" 36 | #define WMI_NAME "NAME" 37 | 38 | typedef VOID AntiVmCallBack(const ADDRINT addr, const CHAR* name, uint32_t argCount, VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, VOID* arg5, VOID* arg6); 39 | 40 | 41 | /* ================================================================== */ 42 | // Global variables used by AntiVm 43 | /* ================================================================== */ 44 | 45 | class AntiVmWatch : public EvasionWatch 46 | { 47 | public: 48 | AntiVmWatch() { Init(); } 49 | virtual BOOL Init(); 50 | }; 51 | 52 | AntiVmWatch m_AntiVm; 53 | 54 | namespace AntiVm { 55 | std::map m_funcData; 56 | }; // namespace AntiVm 57 | /* ==================================================================== */ 58 | // Log info with AntiVm label 59 | /* ==================================================================== */ 60 | 61 | VOID LogAntiVm(const WatchedType wType, const ADDRINT Address, const char* msg, const char* link = nullptr) 62 | { 63 | LogMsgAtAddress(wType, Address, ANTIVM_LABEL, msg, link); 64 | } 65 | 66 | /* ==================================================================== */ 67 | // Process API calls (related to AntiVm techniques) 68 | /* ==================================================================== */ 69 | 70 | VOID AntiVm_WmiQueries(const ADDRINT addr, const THREADID tid, const CHAR* name, uint32_t argCount, VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, VOID* arg5) 71 | { 72 | if (!argCount) return; 73 | 74 | PinLocker locker; 75 | const WatchedType wType = isWatchedAddress(addr); 76 | if (wType == WatchedType::NOT_WATCHED) return; 77 | 78 | const wchar_t* wmi_query = reinterpret_cast(arg2); 79 | if (!wmi_query) return; 80 | 81 | char wmi_query_field[PATH_BUFSIZE] = { 0 }; 82 | util::wstr_to_str(wmi_query, wmi_query_field, PATH_BUFSIZE); 83 | 84 | if (util::iequals(wmi_query_field, WMI_NUMBER_CORES) || util::iequals(wmi_query_field, WMI_PROCESSOR)) { 85 | return LogAntiVm(wType, addr, "^ WMI query - number of CPU cores", 86 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 87 | } 88 | else if (util::iequals(wmi_query_field, WMI_SIZE)) { 89 | return LogAntiVm(wType, addr, "^ WMI query - hard disk size", 90 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 91 | } 92 | else if (util::iequals(wmi_query_field, WMI_DEVICE_ID)) { 93 | return LogAntiVm(wType, addr, "^ WMI query - device ID", 94 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 95 | } 96 | else if (util::iequals(wmi_query_field, WMI_MAC_ADDRESS)) { 97 | return LogAntiVm(wType, addr, "^ WMI query - MAC address", 98 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 99 | } 100 | else if (util::iequals(wmi_query_field, WMI_TEMPERATURE)) { 101 | return LogAntiVm(wType, addr, "^ WMI query - system temperatures", 102 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 103 | } 104 | else if (util::iequals(wmi_query_field, WMI_SERIAL)) { 105 | return LogAntiVm(wType, addr, "^ WMI query - BIOS serial number", 106 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 107 | } 108 | else if (util::iequals(wmi_query_field, WMI_MODEL) || util::iequals(wmi_query_field, WMI_MANUFACTURER)) { 109 | return LogAntiVm(wType, addr, "^ WMI query - system model and/or manufacturer", 110 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 111 | } 112 | else if (util::iequals(wmi_query_field, WMI_GPU_ADAPTER)) { 113 | return LogAntiVm(wType, addr, "^ WMI query - video controller adapter", 114 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 115 | } 116 | else if (util::iequals(wmi_query_field, WMI_PRODUCT) || util::iequals(wmi_query_field, WMI_NAME)) { 117 | return LogAntiVm(wType, addr, "^ WMI query - system device names", 118 | "https://evasions.checkpoint.com/techniques/wmi.html#generic-wmi-queries"); 119 | } 120 | } 121 | 122 | /* ==================================================================== */ 123 | // Add to monitored functions all the API calls needed for AntiVM. 124 | /* ==================================================================== */ 125 | 126 | //Functions handles: 127 | 128 | VOID AntiVm_NtQuerySystemInformation(const ADDRINT Address, const THREADID tid, const CHAR* name, uint32_t argCount, VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, VOID* arg5, BOOL isAfter = FALSE) 129 | { 130 | if (!argCount) return; 131 | 132 | PinLocker locker; 133 | const WatchedType wType = isWatchedAddress(Address); 134 | if (wType == WatchedType::NOT_WATCHED) return; 135 | 136 | enum SystemInformationClass { 137 | SystemFirmwareTableInformation = 0x4C 138 | }; 139 | if (int((size_t)arg1) == SystemInformationClass::SystemFirmwareTableInformation) { 140 | if (!isAfter) { 141 | return LogAntiVm(wType, Address, "^ ntdll!NtQuerySystemInformation (SystemFirmwareTableInformation)", 142 | "https://revers.engineering/evading-trivial-acpi-checks/"); 143 | } 144 | else { 145 | std::stringstream ss; 146 | ss << "^ ntdll!NtQuerySystemInformation (SystemFirmwareTableInformation). Bypass: "; 147 | size_t buf_size = (size_t)arg3; 148 | if (PIN_CheckWriteAccess(arg2) && PIN_CheckWriteAccess((VOID*)((ADDRINT)arg2 + (buf_size - 1)))) { 149 | ::memset(arg2, 0, buf_size); 150 | ss << "OK"; 151 | } 152 | else { 153 | ss << "Failed"; 154 | } 155 | return LogAntiVm(wType, Address, ss.str().c_str()); 156 | } 157 | } 158 | } 159 | 160 | VOID AntiVm_NtQuerySystemInformation_before(const ADDRINT Address, const THREADID tid, const CHAR* name, uint32_t argCount, VOID* arg1, VOID* arg2, VOID* arg3, VOID* arg4, VOID* arg5) 161 | { 162 | storeData(AntiVm::m_funcData, tid, name, argCount, arg1, arg2, arg3, arg4, arg5); 163 | return AntiVm_NtQuerySystemInformation(Address, tid, name, argCount, arg1, arg2, arg3, arg4, arg5, FALSE); 164 | } 165 | 166 | VOID AntiVm_NtQuerySystemInformation_after(const ADDRINT Address, const THREADID tid, const CHAR* name, ADDRINT status) 167 | { 168 | if (status != 0) { 169 | return; // failed 170 | } 171 | FuncData data; 172 | if (!retrieveData(AntiVm::m_funcData, tid, name, data)) { 173 | return; 174 | } 175 | return AntiVm_NtQuerySystemInformation(Address, tid, name, data.argsNum, data.args[0], data.args[1], data.args[2], data.args[3], data.args[4], TRUE); 176 | } 177 | 178 | VOID AntiVm::MonitorSyscallEntry(THREADID tid, const CHAR* name, const CONTEXT* ctxt, SYSCALL_STANDARD std, const ADDRINT Address) 179 | { 180 | EvasionFuncInfo* wfunc = m_AntiVm.fetchSyscallFuncInfo(name, m_Settings.antivm); 181 | if (!wfunc) return; 182 | 183 | EvasionWatchBeforeCallBack* callback = wfunc->callbackBefore; 184 | if (!callback) { 185 | return; 186 | } 187 | 188 | const size_t argCount = wfunc->paramCount; 189 | const size_t args_max = 5; 190 | VOID* syscall_args[args_max] = { 0 }; 191 | 192 | for (size_t i = 0; i < args_max; i++) { 193 | if (i == argCount) break; 194 | syscall_args[i] = reinterpret_cast(PIN_GetSyscallArgument(ctxt, std, i)); 195 | } 196 | callback(Address, 197 | tid, 198 | name, argCount, 199 | syscall_args[0], 200 | syscall_args[1], 201 | syscall_args[2], 202 | syscall_args[3], 203 | syscall_args[4]); 204 | } 205 | 206 | VOID AntiVm::MonitorSyscallExit(THREADID tid, const CHAR* name, const CONTEXT* ctxt, SYSCALL_STANDARD std, const ADDRINT Address) 207 | { 208 | EvasionFuncInfo* wfunc = m_AntiVm.fetchSyscallFuncInfo(name, m_Settings.antivm); 209 | if (!wfunc) return; 210 | 211 | EvasionWatchAfterCallBack* callback = wfunc->callbackAfter; 212 | if (!callback) { 213 | return; 214 | } 215 | 216 | callback(Address, 217 | tid, 218 | name, 219 | PIN_GetContextReg(ctxt, REG_GAX) 220 | ); 221 | } 222 | 223 | //--- 224 | namespace AntiVm { 225 | std::map cpuidThreads; 226 | }; //namespace AntiVm 227 | 228 | 229 | namespace AntiVm 230 | { 231 | VOID CpuidCheck(CONTEXT* ctxt, THREADID tid) 232 | { 233 | PinLocker locker; 234 | 235 | const ADDRINT Address = (ADDRINT)PIN_GetContextReg(ctxt, REG_INST_PTR); 236 | 237 | const WatchedType wType = isWatchedAddress(Address); 238 | if (wType == WatchedType::NOT_WATCHED) return; 239 | 240 | ADDRINT opId = (ADDRINT)PIN_GetContextReg(ctxt, REG_GAX); 241 | cpuidThreads[tid] = opId; 242 | if (opId == 0x0) { 243 | return LogAntiVm(wType, Address, "CPUID - vendor check", 244 | "https://unprotect.it/technique/cpuid/"); 245 | } 246 | if (opId == 0x1) { 247 | return LogAntiVm(wType, Address, "CPUID - HyperVisor bit check", 248 | "https://unprotect.it/technique/cpuid/"); 249 | } 250 | if (opId == 0x80000002 || opId == 0x80000003 || opId == 0x80000004) { 251 | return LogAntiVm(wType, Address, "CPUID - brand check", 252 | "https://unprotect.it/technique/cpuid/"); 253 | } 254 | if (opId == 0x40000000) { 255 | return LogAntiVm(wType, Address, "CPUID - HyperVisor vendor check", 256 | "https://unprotect.it/technique/cpuid/"); 257 | } 258 | if (opId == 0x40000002) { 259 | return LogAntiVm(wType, Address, "CPUID - HyperVisor system identity"); 260 | } 261 | if (opId == 0x40000003) { 262 | return LogAntiVm(wType, Address, "CPUID - HyperVisor feature identification"); 263 | } 264 | } 265 | 266 | BOOL _AlterCpuidValue(CONTEXT* ctxt, THREADID tid, const REG reg, ADDRINT& regVal) 267 | { 268 | const BOOL isHyperVisorSet = m_Settings.isHyperVSet; 269 | BOOL isSet = FALSE; 270 | const ADDRINT Address = (ADDRINT)PIN_GetContextReg(ctxt, REG_INST_PTR); 271 | 272 | const WatchedType wType = isWatchedAddress(Address); 273 | if (wType == WatchedType::NOT_WATCHED) return FALSE; 274 | 275 | auto itr = cpuidThreads.find(tid); 276 | if (itr == cpuidThreads.end()) return FALSE; 277 | 278 | const ADDRINT opId = itr->second; 279 | std::stringstream ss; 280 | ss << "CPUID - HyperVisor res:" << std::hex; 281 | 282 | const ADDRINT prev = regVal; 283 | 284 | if (opId == 0x1) { 285 | if (reg == REG_GCX) { 286 | ss << " ECX: " << regVal; 287 | const ADDRINT hv_bit = (ADDRINT)0x1 << 31; 288 | if (isHyperVisorSet) { 289 | regVal |= hv_bit; //set bit 290 | } 291 | else { 292 | regVal &= ~hv_bit; //clear bit 293 | } 294 | isSet = TRUE; 295 | } 296 | } 297 | 298 | if (opId == 0x40000000) { 299 | if (reg == REG_GAX) { 300 | ss << " EAX: " << regVal; 301 | if (isHyperVisorSet) { 302 | regVal = 0x40000006; 303 | } else { 304 | regVal = 0xc1c; 305 | } 306 | } else if (reg == REG_GBX) { 307 | ss << " EBX: " << regVal; 308 | if (isHyperVisorSet) { 309 | regVal = 0x7263694d; 310 | } 311 | else { 312 | regVal = 0x14b4; 313 | } 314 | } else if (reg == REG_GCX) { 315 | ss << " ECX: " << regVal; 316 | if (isHyperVisorSet) { 317 | regVal = 0x666f736f; 318 | } 319 | else { 320 | regVal = 0x64; 321 | } 322 | } else if (reg == REG_GDX) { 323 | ss << " EDX: " << regVal; 324 | if (isHyperVisorSet) { 325 | regVal = 0x76482074; 326 | } 327 | else { 328 | regVal = 0; 329 | } 330 | } 331 | isSet = TRUE; 332 | } 333 | else if (opId == 0x40000003) { 334 | if (reg == REG_GAX) { 335 | ss << " EAX: " << regVal; 336 | if (isHyperVisorSet) { 337 | regVal = 0x3fff; 338 | } 339 | else { 340 | regVal = 0x14b4; 341 | } 342 | } else if (reg == REG_GBX) { 343 | ss << " EBX: " << regVal; 344 | if (isHyperVisorSet) { 345 | regVal = 0x2bb9ff; 346 | } 347 | else { 348 | regVal = 0x64; 349 | } 350 | } else if (reg == REG_GCX) { 351 | ss << " ECX: " << regVal; 352 | regVal = 0; 353 | } else if (reg == REG_GDX) { 354 | ss << " EDX: " << regVal; 355 | regVal = 0; 356 | } 357 | isSet = TRUE; 358 | } 359 | if (isSet && ss.str().length()) { 360 | if (prev != regVal) { 361 | ss << " -> " << regVal; 362 | } 363 | LogAntiVm(wType, Address, ss.str().c_str()); 364 | } 365 | return isSet; 366 | } 367 | 368 | ADDRINT AlterCpuidValue(CONTEXT* ctxt, THREADID tid, const REG reg) 369 | { 370 | PinLocker locker; 371 | ADDRINT regVal = PIN_GetContextReg(ctxt, reg); 372 | _AlterCpuidValue(ctxt, tid, reg, regVal); 373 | return regVal; 374 | } 375 | 376 | }; //namespace AntiVm 377 | 378 | 379 | VOID AntiVm::InstrumentCPUIDCheck(INS ins) 380 | { 381 | INS_InsertCall( 382 | ins, 383 | IPOINT_BEFORE, (AFUNPTR)AntiVm::CpuidCheck, 384 | IARG_CONTEXT, 385 | IARG_THREAD_ID, 386 | IARG_END 387 | ); 388 | 389 | INS_InsertCall( 390 | ins, 391 | IPOINT_AFTER, (AFUNPTR)AntiVm::AlterCpuidValue, 392 | IARG_CONTEXT, 393 | IARG_THREAD_ID, 394 | IARG_UINT32, REG_GAX, 395 | IARG_RETURN_REGS, 396 | REG_GAX, 397 | IARG_END 398 | ); 399 | 400 | INS_InsertCall( 401 | ins, 402 | IPOINT_AFTER, (AFUNPTR)AntiVm::AlterCpuidValue, 403 | IARG_CONTEXT, 404 | IARG_THREAD_ID, 405 | IARG_UINT32, REG_GBX, 406 | IARG_RETURN_REGS, 407 | REG_GBX, 408 | IARG_END 409 | ); 410 | 411 | INS_InsertCall( 412 | ins, 413 | IPOINT_AFTER, (AFUNPTR)AntiVm::AlterCpuidValue, 414 | IARG_CONTEXT, 415 | IARG_THREAD_ID, 416 | IARG_UINT32, REG_GCX, 417 | IARG_RETURN_REGS, 418 | REG_GCX, 419 | IARG_END 420 | ); 421 | 422 | INS_InsertCall( 423 | ins, 424 | IPOINT_AFTER, (AFUNPTR)AntiVm::AlterCpuidValue, 425 | IARG_CONTEXT, 426 | IARG_THREAD_ID, 427 | IARG_UINT32, REG_GDX, 428 | IARG_RETURN_REGS, 429 | REG_GDX, 430 | IARG_END 431 | ); 432 | } 433 | 434 | //--- 435 | 436 | BOOL AntiVmWatch::Init() 437 | { 438 | watchedFuncs.appendFunc(EvasionFuncInfo("ntdll", "NtQuerySystemInformation", 4, AntiVm_NtQuerySystemInformation_before, AntiVm_NtQuerySystemInformation_after)); 439 | // API needed to trace WMI queries: 440 | #ifdef _WIN64 441 | watchedFuncs.appendFunc(EvasionFuncInfo("fastprox", "?Get@CWbemObject@@UEAAJPEBGJPEAUtagVARIANT@@PEAJ2@Z", 5, AntiVm_WmiQueries)); 442 | #else 443 | watchedFuncs.appendFunc(EvasionFuncInfo("fastprox", "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z", 5, AntiVm_WmiQueries)); 444 | #endif 445 | isInit = TRUE; 446 | return isInit; 447 | } 448 | 449 | VOID AntiVm::MonitorAntiVmFunctions(IMG Image) 450 | { 451 | m_AntiVm.installCallbacks(Image, nullptr, m_Settings.antivm); 452 | } 453 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /TinyTracer_Pin3.25.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 | TinyTracer 24 | Win32Proj 25 | TinyTracer 26 | 27 | 28 | 29 | DynamicLibrary 30 | MultiByte 31 | true 32 | v110 33 | 34 | 35 | DynamicLibrary 36 | MultiByte 37 | v110 38 | 39 | 40 | DynamicLibrary 41 | MultiByte 42 | true 43 | v110 44 | 45 | 46 | DynamicLibrary 47 | MultiByte 48 | v110 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <_ProjectFileVersion>10.0.40219.1 68 | $(ProjectDir)$(Configuration)\ 69 | $(Configuration)\ 70 | false 71 | false 72 | $(ProjectDir)$(Platform)\$(Configuration)\ 73 | $(Platform)\$(Configuration)\ 74 | false 75 | false 76 | $(ProjectDir)$(Configuration)\ 77 | $(Configuration)\ 78 | false 79 | false 80 | $(ProjectDir)$(Platform)\$(Configuration)\ 81 | $(Platform)\$(Configuration)\ 82 | false 83 | false 84 | AllRules.ruleset 85 | 86 | 87 | AllRules.ruleset 88 | 89 | 90 | AllRules.ruleset 91 | 92 | 93 | AllRules.ruleset 94 | 95 | 96 | 97 | 98 | 99 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 100 | Disabled 101 | ..\..\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;%(AdditionalIncludeDirectories) 102 | TARGET_IA32;HOST_IA32;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__i386__ 103 | false 104 | 105 | 106 | Default 107 | MultiThreadedDLL 108 | false 109 | true 110 | NotSet 111 | false 112 | 113 | 114 | Level3 115 | ProgramDatabase 116 | 4530;%(DisableSpecificWarnings) 117 | 118 | 119 | /export:main %(AdditionalOptions) 120 | pin.lib;xed.lib;pincrt.lib;kernel32.lib;crtbeginS.obj 121 | ..\..\..\ia32\lib;..\..\..\ia32\lib-ext;..\..\..\extras\xed-ia32\lib;..\..\..\ia32\runtime\pincrt;%(AdditionalLibraryDirectories) 122 | true 123 | %(IgnoreSpecificDefaultLibraries) 124 | true 125 | NotSet 126 | false 127 | Ptrace_DllMainCRTStartup%4012 128 | 0x55000000 129 | MachineX86 130 | true 131 | false 132 | 133 | 134 | 135 | 136 | X64 137 | 138 | 139 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 140 | Disabled 141 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-intel64\include\xed;..\..\..\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) 142 | TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__LP64__ 143 | false 144 | 145 | 146 | Default 147 | MultiThreadedDLL 148 | false 149 | true 150 | false 151 | 152 | 153 | Level3 154 | ProgramDatabase 155 | 4530;%(DisableSpecificWarnings) 156 | 157 | 158 | /export:main %(AdditionalOptions) 159 | pin.lib;xed.lib;pincrt.lib;kernel32.lib;crtbeginS.obj 160 | ..\..\..\intel64\lib;..\..\..\intel64\lib-ext;..\..\..\extras\xed-intel64\lib;..\..\..\intel64\runtime\pincrt;%(AdditionalLibraryDirectories) 161 | true 162 | %(IgnoreSpecificDefaultLibraries) 163 | true 164 | NotSet 165 | false 166 | Ptrace_DllMainCRTStartup 167 | 0xC5000000 168 | MachineX64 169 | true 170 | 171 | 172 | 173 | 174 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 175 | false 176 | false 177 | ..\..\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;%(AdditionalIncludeDirectories) 178 | TARGET_IA32;HOST_IA32;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__i386__ 179 | false 180 | 181 | 182 | Default 183 | MultiThreadedDLL 184 | false 185 | true 186 | NotSet 187 | false 188 | 189 | 190 | Level3 191 | 192 | 193 | 4530;%(DisableSpecificWarnings) 194 | 195 | 196 | /export:main %(AdditionalOptions) 197 | pin.lib;xed.lib;pincrt.lib;kernel32.lib;crtbeginS.obj 198 | ..\..\..\ia32\lib;..\..\..\ia32\lib-ext;..\..\..\extras\xed-ia32\lib;..\..\..\ia32\runtime\pincrt;%(AdditionalLibraryDirectories) 199 | true 200 | %(IgnoreSpecificDefaultLibraries) 201 | true 202 | NotSet 203 | true 204 | 205 | 206 | 207 | 208 | Ptrace_DllMainCRTStartup%4012 209 | 0x55000000 210 | MachineX86 211 | false 212 | 213 | 214 | 215 | 216 | X64 217 | 218 | 219 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 220 | false 221 | false 222 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-intel64\include\xed;..\..\..\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) 223 | TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__LP64__ 224 | false 225 | 226 | 227 | Default 228 | MultiThreadedDLL 229 | false 230 | true 231 | false 232 | 233 | 234 | Level3 235 | 236 | 237 | 4530;%(DisableSpecificWarnings) 238 | 239 | 240 | /export:main %(AdditionalOptions) 241 | pin.lib;xed.lib;pincrt.lib;kernel32.lib;crtbeginS.obj 242 | ..\..\..\intel64\lib;..\..\..\intel64\lib-ext;..\..\..\extras\xed-intel64\lib;..\..\..\intel64\runtime\pincrt;%(AdditionalLibraryDirectories) 243 | true 244 | %(IgnoreSpecificDefaultLibraries) 245 | true 246 | NotSet 247 | true 248 | 249 | 250 | 251 | 252 | Ptrace_DllMainCRTStartup 253 | 0xC5000000 254 | MachineX64 255 | 256 | 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 | -------------------------------------------------------------------------------- /TinyTracer.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 | TinyTracer 24 | Win32Proj 25 | TinyTracer 26 | 27 | 28 | 29 | DynamicLibrary 30 | MultiByte 31 | true 32 | v110 33 | 34 | 35 | DynamicLibrary 36 | MultiByte 37 | v110 38 | 39 | 40 | DynamicLibrary 41 | MultiByte 42 | true 43 | v110 44 | 45 | 46 | DynamicLibrary 47 | MultiByte 48 | v110 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <_ProjectFileVersion>10.0.40219.1 68 | $(ProjectDir)$(Configuration)\ 69 | $(Configuration)\ 70 | false 71 | false 72 | $(ProjectDir)$(Platform)\$(Configuration)\ 73 | $(Platform)\$(Configuration)\ 74 | false 75 | false 76 | $(ProjectDir)$(Configuration)\ 77 | $(Configuration)\ 78 | false 79 | false 80 | $(ProjectDir)$(Platform)\$(Configuration)\ 81 | $(Platform)\$(Configuration)\ 82 | false 83 | false 84 | AllRules.ruleset 85 | 86 | 87 | AllRules.ruleset 88 | 89 | 90 | AllRules.ruleset 91 | 92 | 93 | AllRules.ruleset 94 | 95 | 96 | 97 | 98 | 99 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 100 | Disabled 101 | ..\..\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;%(AdditionalIncludeDirectories) 102 | TARGET_IA32;HOST_IA32;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__i386__ 103 | false 104 | 105 | 106 | Default 107 | MultiThreadedDLL 108 | false 109 | true 110 | NotSet 111 | false 112 | 113 | 114 | Level3 115 | ProgramDatabase 116 | 4530;%(DisableSpecificWarnings) 117 | 118 | 119 | /export:main %(AdditionalOptions) 120 | pin.lib;xed.lib;pincrt.lib;pinipc.lib;kernel32.lib;crtbeginS.obj 121 | ..\..\..\ia32\lib;..\..\..\ia32\lib-ext;..\..\..\extras\xed-ia32\lib;..\..\..\ia32\runtime\pincrt;%(AdditionalLibraryDirectories) 122 | true 123 | %(IgnoreSpecificDefaultLibraries) 124 | true 125 | NotSet 126 | false 127 | Ptrace_DllMainCRTStartup%4012 128 | 0x55000000 129 | MachineX86 130 | true 131 | false 132 | 133 | 134 | 135 | 136 | X64 137 | 138 | 139 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 140 | Disabled 141 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-intel64\include\xed;..\..\..\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) 142 | TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__LP64__ 143 | false 144 | 145 | 146 | Default 147 | MultiThreadedDLL 148 | false 149 | true 150 | false 151 | 152 | 153 | Level3 154 | ProgramDatabase 155 | 4530;%(DisableSpecificWarnings) 156 | 157 | 158 | /export:main %(AdditionalOptions) 159 | pin.lib;xed.lib;pincrt.lib;pinipc.lib;kernel32.lib;crtbeginS.obj 160 | ..\..\..\intel64\lib;..\..\..\intel64\lib-ext;..\..\..\extras\xed-intel64\lib;..\..\..\intel64\runtime\pincrt;%(AdditionalLibraryDirectories) 161 | true 162 | %(IgnoreSpecificDefaultLibraries) 163 | true 164 | NotSet 165 | false 166 | Ptrace_DllMainCRTStartup 167 | 0xC5000000 168 | MachineX64 169 | true 170 | 171 | 172 | 173 | 174 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 175 | false 176 | false 177 | ..\..\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;%(AdditionalIncludeDirectories) 178 | TARGET_IA32;HOST_IA32;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__i386__ 179 | false 180 | 181 | 182 | Default 183 | MultiThreadedDLL 184 | false 185 | true 186 | NotSet 187 | false 188 | 189 | 190 | Level3 191 | 192 | 193 | 4530;%(DisableSpecificWarnings) 194 | 195 | 196 | /export:main %(AdditionalOptions) 197 | pin.lib;xed.lib;pincrt.lib;pinipc.lib;kernel32.lib;crtbeginS.obj 198 | ..\..\..\ia32\lib;..\..\..\ia32\lib-ext;..\..\..\extras\xed-ia32\lib;..\..\..\ia32\runtime\pincrt;%(AdditionalLibraryDirectories) 199 | true 200 | %(IgnoreSpecificDefaultLibraries) 201 | true 202 | NotSet 203 | true 204 | 205 | 206 | 207 | 208 | Ptrace_DllMainCRTStartup%4012 209 | 0x55000000 210 | MachineX86 211 | false 212 | 213 | 214 | 215 | 216 | X64 217 | 218 | 219 | /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) 220 | false 221 | false 222 | ..\..\include\pin;..\..\include\pin\gen;..\InstLib;..\..\..\extras\xed-intel64\include\xed;..\..\..\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) 223 | TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__LP64__ 224 | false 225 | 226 | 227 | Default 228 | MultiThreadedDLL 229 | false 230 | true 231 | false 232 | 233 | 234 | Level3 235 | 236 | 237 | 4530;%(DisableSpecificWarnings) 238 | 239 | 240 | /export:main %(AdditionalOptions) 241 | pin.lib;xed.lib;pincrt.lib;pinipc.lib;kernel32.lib;crtbeginS.obj 242 | ..\..\..\intel64\lib;..\..\..\intel64\lib-ext;..\..\..\extras\xed-intel64\lib;..\..\..\intel64\runtime\pincrt;%(AdditionalLibraryDirectories) 243 | true 244 | %(IgnoreSpecificDefaultLibraries) 245 | true 246 | NotSet 247 | true 248 | 249 | 250 | 251 | 252 | Ptrace_DllMainCRTStartup 253 | 0xC5000000 254 | MachineX64 255 | 256 | 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 | --------------------------------------------------------------------------------