├── docs ├── pin-debugger-port.png ├── stealth-patching.png └── ida-debugger-settings.png ├── pintool ├── src │ ├── libdft │ │ ├── bridge.h │ │ ├── libdft_config.h │ │ ├── branch_pred.h │ │ ├── libdft_core.h │ │ ├── tagmap_custom.h │ │ ├── tag_traits.h │ │ ├── tag_traits.cpp │ │ ├── tagmap.h │ │ ├── libdft_api.h │ │ ├── bridge.cpp │ │ └── array.hpp │ ├── wmi.h │ ├── fpu.h │ ├── context.h │ ├── process.h │ ├── logging.h │ ├── state.cpp │ ├── exceptionHandler.h │ ├── itree.h │ ├── logging.cpp │ ├── ins.h │ ├── helper.h │ ├── dbg.h │ ├── exceptionHandler.cpp │ ├── syshooking.h │ ├── context.cpp │ ├── helper.cpp │ ├── config.h │ ├── fpu.cpp │ ├── syshooks.h │ ├── memory.h │ ├── state.h │ ├── wmi.cpp │ ├── HiddenElements.h │ ├── functions.h │ ├── itree.cpp │ ├── process.cpp │ ├── main.cpp │ ├── ins.cpp │ ├── HiddenElements.cpp │ ├── syshooking.cpp │ └── winheaders.h ├── pintool.filters ├── pintool.sln └── pintool.vcxproj.filters ├── Locals.props ├── scripts └── AddSegments.py ├── solution.sln ├── .gitignore ├── LICENSE └── README.md /docs/pin-debugger-port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/season-lab/bluepill/HEAD/docs/pin-debugger-port.png -------------------------------------------------------------------------------- /docs/stealth-patching.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/season-lab/bluepill/HEAD/docs/stealth-patching.png -------------------------------------------------------------------------------- /docs/ida-debugger-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/season-lab/bluepill/HEAD/docs/ida-debugger-settings.png -------------------------------------------------------------------------------- /pintool/src/libdft/bridge.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | #include "libdft_api.h" 4 | 5 | extern REG thread_ctx_ptr; 6 | 7 | void instrumentForTaintCheck(INS ins, void*); 8 | void registerThreadTaintAnalysis(THREADID tid, thread_ctx_t* thread_ctx); -------------------------------------------------------------------------------- /pintool/src/wmi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | #include "helper.h" 5 | #include "logging.h" 6 | 7 | namespace W { 8 | #include 9 | #include 10 | } 11 | 12 | VOID WMI_Patch(W::LPCWSTR query, W::VARIANT *enumerator); -------------------------------------------------------------------------------- /pintool/src/fpu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | #include "logging.h" 5 | 6 | #define FPUIPOFFSET 0xc 7 | 8 | VOID FPU_Init(); 9 | VOID FPU_InstrumentINS(INS ins); 10 | VOID PIN_FAST_ANALYSIS_CALL FPU_UpdateFPUStatus(ADDRINT regValue, ADDRINT op); 11 | ADDRINT PIN_FAST_ANALYSIS_CALL FPU_UpdateLastFpuIns(ADDRINT addr); 12 | -------------------------------------------------------------------------------- /pintool/src/context.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | #include "logging.h" 4 | 5 | VOID CONTEXT_ChangeContext(THREADID threadIndex, CONTEXT_CHANGE_REASON reason, 6 | const CONTEXT *ctxtFrom, CONTEXT *ctxtTo, INT32 info, VOID* v); 7 | 8 | EXCEPT_HANDLING_RESULT CONTEXT_InternalExceptionHandler(THREADID tid, 9 | EXCEPTION_INFO *pExceptInfo, PHYSICAL_CONTEXT *pPhysCtxt, VOID *v); -------------------------------------------------------------------------------- /pintool/src/process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | namespace Process { 5 | extern BOOL isWow64; 6 | 7 | // patch PEB fields 8 | VOID patchPEB(); 9 | 10 | // for GDB remote debugging 11 | BOOL VMMap(std::string* result); 12 | 13 | // instrumentation 14 | void OnImageLoad(IMG img); 15 | void OnImageUnload(IMG img); 16 | 17 | // check on return address 18 | VOID CheckRetAddrLibcall(ADDRINT* ESP); 19 | 20 | }; -------------------------------------------------------------------------------- /pintool/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | #define LOGPATH "C:\\pin316\\" 5 | #define LOGNAME "evasions.log" 6 | #define LOG_BUILD 1 7 | 8 | #define LOG_AR(fmt, ...) \ 9 | do { \ 10 | if (!LOG_BUILD) break; \ 11 | Logging::logMain(fmt"\n", __VA_ARGS__); \ 12 | } while (0) 13 | 14 | 15 | class Logging { 16 | 17 | public: 18 | static FILE* mainLog; 19 | 20 | static VOID LOGGING_Init(); 21 | static VOID LOGGING_Shutdown(); 22 | static VOID logMain(const char * fmt, ...); 23 | 24 | }; -------------------------------------------------------------------------------- /pintool/src/libdft/libdft_config.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBDFT_CONFIG_H 2 | #define LIBDFT_CONFIG_H 3 | 4 | // Enable custom taint tags unless default tags are explicitly requested. 5 | #if defined(LIBDFT_DEFAULT_TAG_TYPE) 6 | #undef LIBDFT_TAG_TYPE 7 | #undef USE_CUSTOM_TAG 8 | #elif !defined(LIBDFT_TAG_TYPE) 9 | //#define LIBDFT_TAG_TYPE libdft_tag_set_uint32 10 | #define LIBDFT_TAG_TYPE libdft_tag_uint8 // DCD 11 | #endif 12 | 13 | #ifdef LIBDFT_TAG_TYPE 14 | #define USE_CUSTOM_TAG 15 | #include "tag_traits.h" 16 | 17 | // Currently available tag types: 18 | // libdft_tag_uint8 19 | // libdft_tag_set_uint32 20 | // libdft_tag_set_fdoff 21 | // libdft_tag_bitset 22 | typedef LIBDFT_TAG_TYPE tag_t; 23 | #endif 24 | 25 | #endif /* LIBDFT_CONFIG_H */ -------------------------------------------------------------------------------- /pintool/src/state.cpp: -------------------------------------------------------------------------------- 1 | #include "state.h" 2 | 3 | State::hookEntryArgsTLS _hookEntryTLSArgs; 4 | //State::timeInfo _timeInfo; 5 | State::globalState _globalState; 6 | 7 | namespace State { 8 | void init() { 9 | // TODO check memset :-) 10 | memset(&_hookEntryTLSArgs, 0, sizeof(hookEntryArgsTLS)); 11 | //memset(&_timeInfo, 0, sizeof(timeInfo)); 12 | memset(&_globalState, 0, sizeof(globalState)); 13 | 14 | // magic numbers 15 | _globalState._timeInfo.tick = 3478921; 16 | _globalState._timeInfo._edx_eax = 0x6000000002346573ULL; 17 | } 18 | 19 | globalState* getGlobalState() { 20 | return &_globalState; 21 | } 22 | 23 | hookEntryArgsTLS* getHookEntryTLSArgs() { 24 | return &_hookEntryTLSArgs; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /pintool/pintool.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /Locals.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | C:\Pin316 6 | C:/Program Files (x86)/Windows Kits/8.1/Include/um 7 | 8 | 9 | <_PropertySheetDisplayName>Locals 10 | 11 | 12 | 13 | 14 | $(PinFolder) 15 | 16 | 17 | $(WinHPath) 18 | 19 | 20 | -------------------------------------------------------------------------------- /pintool/src/exceptionHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | #include 4 | 5 | namespace W { 6 | #include 7 | } 8 | 9 | class ExceptionHandler { // TODO turn it into a namespace 10 | 11 | public: 12 | static ExceptionHandler* getInstance(); 13 | static void executeExceptionIns(CONTEXT *ctx, THREADID tid, ADDRINT accessAddr); 14 | void setExceptionToExecute(W::UINT32 exceptionCode); 15 | void raisePendingException(CONTEXT *ctx, THREADID tid, ADDRINT accessAddr); 16 | bool isPendingException(); 17 | void setCode(W::UINT32 exceptionCode); 18 | 19 | ADDRINT lastAddress; 20 | W::UINT32 code; 21 | bool pending; 22 | THREADID tid; 23 | CONTEXT *ctx; 24 | 25 | private: 26 | ExceptionHandler(); 27 | 28 | static ExceptionHandler* instance; 29 | }; 30 | -------------------------------------------------------------------------------- /pintool/src/itree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" 4 | 5 | typedef struct itreenode { 6 | ADDRINT start_addr, end_addr; // range [a, b] 7 | void *data; // user-supplied data 8 | struct itreenode *left, *right; // left and right children 9 | } itreenode_t; 10 | 11 | itreenode_t *itree_init(ADDRINT start_addr, ADDRINT end_addr, void* data); 12 | bool itree_insert(itreenode_t *tree, ADDRINT start_addr, ADDRINT end_addr, void* data); 13 | itreenode_t* itree_delete(itreenode_t* tree, ADDRINT start_addr, ADDRINT end_addr); 14 | itreenode_t *itree_search(itreenode_t *tree, ADDRINT val); 15 | BOOL itree_dealloc(itreenode_t* tree); 16 | bool itree_verify(itreenode_t *tree); 17 | 18 | 19 | void itree_print(itreenode_t *node, ADDRINT lvl); 20 | VOID itree_stats(itreenode_t *node); -------------------------------------------------------------------------------- /pintool/src/logging.cpp: -------------------------------------------------------------------------------- 1 | #include "logging.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | FILE* Logging::mainLog; 8 | 9 | std::string getCurDateAndTime() { 10 | time_t rawtime; 11 | struct tm * timeinfo; 12 | char buffer[80]; 13 | time(&rawtime); 14 | timeinfo = localtime(&rawtime); 15 | strftime(buffer, 80, "%Y_%m_%d_%I_%M_%S", timeinfo); 16 | return string(buffer); 17 | } 18 | 19 | VOID Logging::LOGGING_Init() { 20 | 21 | string path = string(LOGPATH); 22 | 23 | mainLog = fopen(path.append(LOGNAME).c_str(), "a"); 24 | 25 | LOG_AR("Starting analysis..."); 26 | 27 | } 28 | 29 | VOID Logging::LOGGING_Shutdown() { 30 | fclose(Logging::mainLog); 31 | } 32 | 33 | VOID Logging::logMain(const char* fmt, ...) { 34 | 35 | if (!Logging::mainLog) return; // TODO shall we quit Pin instead? 36 | va_list args; 37 | va_start(args, fmt); 38 | vfprintf(Logging::mainLog, fmt, args); 39 | va_end(args); 40 | 41 | fflush(Logging::mainLog); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /scripts/AddSegments.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idc 3 | 4 | cmd = 'vmmap' 5 | try: 6 | r = idc.SendDbgCommand(cmd)#Eval('SendDbgCommand("%s");' % cmd).split("\n") 7 | r = r.splitlines() 8 | for s in r: 9 | s = s.lstrip("[") 10 | s = s.rstrip("]") 11 | str = s.split(",") 12 | if str[3].strip("\"") != "": 13 | sn = str[3].split("\\") 14 | idaapi.add_segm(0, int(str[0]), int(str[1]), sn[len(sn)-1], "DATA") 15 | SetSegmentAttr(int(str[0]), SEGATTR_PERM, int(str[2])) 16 | SetSegmentAttr(int(str[0]), SEGATTR_ES, 0) 17 | SetSegmentAttr(int(str[0]), SEGATTR_CS, 0) 18 | SetSegmentAttr(int(str[0]), SEGATTR_SS, 0) 19 | SetSegmentAttr(int(str[0]), SEGATTR_DS, 0) 20 | SetSegmentAttr(int(str[0]), SEGATTR_FS, 0) 21 | SetSegmentAttr(int(str[0]), SEGATTR_GS, 0) 22 | 23 | except: 24 | #self.AddLine(idaapi.COLSTR("Debugger is not active or does not export SendDbgCommand()", idaapi.SCOLOR_ERROR)) 25 | print "Debugger is not active or does not export SendDbgCommand()" -------------------------------------------------------------------------------- /pintool/src/ins.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | #include "state.h" 5 | #include "HiddenElements.h" 6 | #include "helper.h" 7 | #include "exceptionHandler.h" 8 | #include "config.h" 9 | #include "memory.h" 10 | 11 | #include 12 | 13 | #define ADDR 0x40108F 14 | #define PAGESIZE 4096 15 | #define PATCH_SIZE 50 16 | #define JMP_OPC_SIZE 2 17 | #define ADDR_SIZE 4 18 | 19 | typedef struct { 20 | UINT32 start; 21 | UINT32 fin; 22 | UINT32 ret; 23 | unsigned char patch[PATCH_SIZE]; 24 | } patch_struct; 25 | 26 | VOID INS_InstrumentINS(INS ins); 27 | 28 | VOID INS_patchRtdsc_exit(ADDRINT ip, CONTEXT *ctxt, ADDRINT cur_eip); 29 | VOID INS_patchCpuid_entry(ADDRINT ip, CONTEXT *ctxt, ADDRINT cur_eip); 30 | VOID INS_patchCpuid_exit(ADDRINT ip, CONTEXT *ctxt, ADDRINT cur_eip); 31 | VOID INS_patchInt2d_entry(CONTEXT *ctx, THREADID tid, ADDRINT accessAddr); 32 | VOID INS_patchIn_exit(CONTEXT *ctx); 33 | VOID INS_AddInsStealth(INS ins); 34 | BOOL INS_EnableInsStealth(std::string input, std::string *result); 35 | BOOL INS_DisableInsStealth(std::string input, std::string *result); 36 | -------------------------------------------------------------------------------- /pintool/src/helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | #include "winheaders.h" 4 | 5 | // CHAR (char) 6 | #define GET_STR_TO_UPPER(c, buf, bufSize) do { \ 7 | size_t i; \ 8 | for (i = 0; i < bufSize; i++) { \ 9 | (buf)[i] = toupper((c)[i]); \ 10 | if ((c)[i] == '\0') break; \ 11 | } \ 12 | } while (0) 13 | 14 | #define GET_STR(c, buf, bufSize) do { \ 15 | size_t i; \ 16 | for (i = 0; i < bufSize; i++) { \ 17 | (buf)[i] = (c)[i]; \ 18 | if ((c)[i] == '\0') break; \ 19 | } \ 20 | } while (0) 21 | 22 | //T_CHAR (wchar_t) 23 | #define GET_WSTR_TO_UPPER(c, buf, bufSize) do { \ 24 | size_t i; \ 25 | for (i = 0; i < bufSize; i++) { \ 26 | (buf)[i] = toupper((c)[2*i]); \ 27 | if ((c)[2*i] == '\0') break; \ 28 | } \ 29 | } while (0) 30 | 31 | #define GET_WSTR(c, buf, bufSize) do { \ 32 | size_t i; \ 33 | for (i = 0; i < bufSize; i++) { \ 34 | (buf)[i] = (c)[2*i]; \ 35 | if ((c)[2*i] == '\0') break; \ 36 | } \ 37 | } while (0) 38 | 39 | namespace Helper { 40 | 41 | size_t _strlen_a(const char *s); 42 | W::DWORD GetProcessIdByName(char* procName); 43 | std::string GetNameFromPid(W::DWORD pid); 44 | 45 | }; -------------------------------------------------------------------------------- /pintool/src/dbg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Zed's Awesome Debug Macros 3 | * http://c.learncodethehardway.org/book/ex20.html 4 | */ 5 | #ifndef LIBDFT_DBG_H 6 | #define LIBDFT_DBG_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef NDEBUG 14 | #define debug(M, ...) 15 | #else 16 | #define debug(M, ...) std::fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 17 | #endif 18 | 19 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 20 | 21 | #define log_err(M, ...) std::fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 22 | 23 | #define log_warn(M, ...) std::fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 24 | 25 | #define log_info(M, ...) std::fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 26 | 27 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 28 | 29 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 30 | 31 | #define check_mem(A) check((A), "Out of memory.") 32 | 33 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /pintool/pintool.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pintool", "pintool.vcxproj", "{639EF517-FCFC-408E-9500-71F0DC0458DB}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Debug|x64 = Debug|x64 10 | Release|Win32 = Release|Win32 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|Win32.Build.0 = Debug|Win32 16 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.ActiveCfg = Debug|x64 17 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.Build.0 = Debug|x64 18 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|Win32.ActiveCfg = Release|Win32 19 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|Win32.Build.0 = Release|Win32 20 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.ActiveCfg = Release|x64 21 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.Build.0 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /pintool/src/exceptionHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "exceptionHandler.h" 2 | 3 | ExceptionHandler::ExceptionHandler() { 4 | this->pending = FALSE; 5 | } 6 | 7 | ExceptionHandler* ExceptionHandler::instance = nullptr; //singleton 8 | 9 | ExceptionHandler* ExceptionHandler::getInstance() { 10 | if (instance == nullptr) 11 | instance = new ExceptionHandler(); 12 | return instance; 13 | } 14 | 15 | void ExceptionHandler::setExceptionToExecute(W::UINT32 exceptionCode) { 16 | this->pending = TRUE; 17 | this->code = exceptionCode; 18 | } 19 | 20 | bool ExceptionHandler::isPendingException() { 21 | return this->pending; 22 | } 23 | 24 | void ExceptionHandler::raisePendingException(CONTEXT *ctx, THREADID tid, ADDRINT accessAddr) { 25 | EXCEPTION_INFO exc; 26 | // we are interested only in a Windows environment 27 | PIN_InitWindowsExceptionInfo(&exc, this->code, accessAddr); 28 | PIN_SetContextReg(ctx, REG_INST_PTR, PIN_GetContextReg(ctx, REG_INST_PTR) + 0x1); // add 0x1 to get the right address 29 | this->pending = FALSE; 30 | PIN_RaiseException(ctx, tid, &exc); 31 | } 32 | 33 | void ExceptionHandler::executeExceptionIns(CONTEXT *ctx, THREADID tid, ADDRINT accessAddr) { 34 | ExceptionHandler *eh = ExceptionHandler::getInstance(); 35 | eh->raisePendingException(ctx, tid, accessAddr); 36 | } 37 | 38 | void ExceptionHandler::setCode(W::UINT32 exceptionCode) { 39 | this->code = exceptionCode; 40 | } -------------------------------------------------------------------------------- /solution.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2050 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pintool", "pintool\pintool.vcxproj", "{639EF517-FCFC-408E-9500-71F0DC0458DB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|Win32.Build.0 = Debug|Win32 18 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.ActiveCfg = Debug|x64 19 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.Build.0 = Debug|x64 20 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|Win32.ActiveCfg = Release|Win32 21 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|Win32.Build.0 = Release|Win32 22 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.ActiveCfg = Debug|Win32 23 | {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.Build.0 = Debug|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E492018D-DFDB-4968-97A1-6BC02CEF7740} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /pintool/src/syshooking.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.h" 3 | #include "config.h" 4 | 5 | 6 | /** THESE NUMBERS ARE TAILORED TO WINDOWS 7 SP1 **/ 7 | // we saw ordinals as high as 0x1a3 in ntdll 8 | #define MAXSYSCALLS 0x200 9 | // 0x1338 seen as max on https://j00ru.vexillium.org/syscalls/win32k/32/ 10 | #define MAXWIN32KSYSCALLS 0x1400 11 | 12 | /* embedded ordinals for Win7 SP1 */ 13 | // we subtract 0x1000 for array indexing 14 | #define NTUSERENUMDISPLAYDEVICES (0x1185-0x1000) 15 | #define NTUSERFINDWINDOWSEX (0x118C-0x1000) 16 | // GDI from SoK 17 | #define NTGDIPOLYTEXTOUTW (0x10fa-0x1000) 18 | #define NTGDIDRAWSTREAM (0x12db-0x1000) 19 | 20 | // BluePill won't need more than that 21 | #define SYSCALL_NUM_ARG 11 22 | 23 | //syscall structure 24 | typedef struct _syscall_t { 25 | ADDRINT syscall_number; 26 | union { 27 | ADDRINT args[12]; 28 | struct { 29 | ADDRINT arg0, arg1, arg2, arg3; 30 | ADDRINT arg4, arg5, arg6, arg7; 31 | ADDRINT arg8, arg9, arg10, arg11; 32 | }; 33 | }; 34 | } syscall_t; 35 | 36 | // function signature of our hook functions 37 | typedef void(*syscall_hook)(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 38 | 39 | typedef struct { 40 | syscall_t sc; 41 | } pintool_tls; 42 | 43 | 44 | namespace SYSHOOKING { 45 | VOID Init(); 46 | VOID SetTLSKey(THREADID tid); 47 | VOID SyscallEntry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v); 48 | VOID SyscallExit(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v); 49 | BOOL ReturnsToUserCode(CONTEXT* ctx); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /pintool/src/context.cpp: -------------------------------------------------------------------------------- 1 | #include "context.h" 2 | #include "config.h" 3 | #include "exceptionHandler.h" 4 | #include "state.h" 5 | #include "winheaders.h" 6 | 7 | #include 8 | 9 | VOID CONTEXT_ChangeContext(THREADID threadIndex, CONTEXT_CHANGE_REASON reason, const CONTEXT * ctxtFrom, CONTEXT * ctxtTo, INT32 info, VOID* v) { 10 | if (reason == CONTEXT_CHANGE_REASON_EXCEPTION) { // ==4 11 | FetchGlobalState; 12 | if (_debugger && gs->waitForDebugger) { 13 | PIN_WaitForDebuggerToConnect(99000); 14 | gs->waitForDebugger = FALSE; 15 | gs->flagStep = 0; 16 | } 17 | 18 | #if 0 19 | ADDRINT _eip; 20 | PIN_GetContextRegval(ctxtFrom, REG_INST_PTR, reinterpret_cast(&_eip)); 21 | 22 | LOG_AR("CAPOZI %08x %08x", _eip, info); // debug messages we like :-) 23 | #endif 24 | } 25 | } 26 | 27 | 28 | EXCEPT_HANDLING_RESULT CONTEXT_InternalExceptionHandler(THREADID tid, EXCEPTION_INFO *pExceptInfo, PHYSICAL_CONTEXT *pPhysCtxt, VOID *v) { 29 | std::cout << PIN_ExceptionToString(pExceptInfo).c_str() << " Code: " << pExceptInfo->GetExceptCode() << std::endl; // TODO use macro to print 30 | // handles single-step exception 31 | if (pExceptInfo->GetExceptCode() == EXCEPTCODE_DBG_SINGLE_STEP_TRAP) { 32 | LOG_AR("[SINGLE_STEP] - *"); 33 | ExceptionHandler *eh = ExceptionHandler::getInstance(); 34 | eh->setExceptionToExecute(NTSTATUS_STATUS_BREAKPOINT); 35 | return EHR_HANDLED; 36 | } 37 | 38 | //LOG_INFO("******Caught Exception:******\n"); 39 | //LOG_INFO("%s", PIN_ExceptionToString(pExceptInfo).c_str()); 40 | //LOG_INFO("*****Continue to search a valid exception handler******\n"); 41 | return EHR_CONTINUE_SEARCH; 42 | } 43 | -------------------------------------------------------------------------------- /pintool/src/helper.cpp: -------------------------------------------------------------------------------- 1 | #include "helper.h" 2 | #include "winheaders.h" 3 | 4 | #define MD5LEN 16 5 | 6 | using namespace std; 7 | 8 | namespace Helper { 9 | size_t Helper::_strlen_a(const char *s) { 10 | const char *s0 = s; 11 | 12 | if (s == 0) return 0; 13 | 14 | while (*s != 0) s++; 15 | 16 | return s - s0; 17 | } 18 | 19 | W::DWORD GetProcessIdByName(char* procName) { 20 | W::PROCESSENTRY32 entry; 21 | entry.dwSize = sizeof(W::PROCESSENTRY32); 22 | W::DWORD pid = NULL; 23 | 24 | W::HANDLE snapshot = W::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 25 | 26 | if (Process32First(snapshot, &entry) == TRUE) { 27 | while (Process32Next(snapshot, &entry) == TRUE) { 28 | if (strcmp(entry.szExeFile, procName) == 0) { 29 | W::HANDLE hProcess = W::OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); 30 | 31 | pid = W::GetProcessId(hProcess); 32 | 33 | W::CloseHandle(hProcess); 34 | } 35 | } 36 | } 37 | W::CloseHandle(snapshot); 38 | 39 | return pid; 40 | } 41 | 42 | string GetNameFromPid(W::DWORD pid) { 43 | 44 | W::PROCESSENTRY32 processInfo; 45 | processInfo.dwSize = sizeof(processInfo); 46 | W::HANDLE processesSnapshot = W::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 47 | if (processesSnapshot == (W::HANDLE) - 1) { 48 | return 0; 49 | } 50 | 51 | for (W::BOOL bok = Process32First(processesSnapshot, &processInfo); bok; bok = Process32Next(processesSnapshot, &processInfo)) { 52 | if (pid == processInfo.th32ProcessID) { 53 | W::CloseHandle(processesSnapshot); 54 | return processInfo.szExeFile; 55 | } 56 | 57 | } 58 | W::CloseHandle(processesSnapshot); 59 | return 0; 60 | 61 | } 62 | 63 | } 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /pintool/src/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.h" 3 | 4 | using namespace std; // TODO get rid of this... 5 | 6 | // enable to avoid supplying command-line args to Pin (see below) 7 | #define FIXED_KNOBS 0 8 | 9 | // generic configuration parameters 10 | #define BP_NUMCORES 4 11 | #define BP_MAC_VENDOR "\x07\x01\x33" 12 | #define BP_NETVENDOR "Intel" 13 | #define BP_FAKEPROCESS "cmd.exe" 14 | #define BP_WFAKEPROCESS L"abc.exe" 15 | #define BP_TIMER 150 16 | #define BP_ICMP_CREATE 300 17 | #define BP_ICMP_ECHO 200 18 | #define BP_HKL_LAYOUT 0x040c040c /* France (we likely used it for Retefe) */ 19 | #define BP_MUTEX "suppli" /* used to create a valid handle */ 20 | 21 | // these are exposed for now through WMI queries only 22 | #define BP_DISKSIZE 1000LL /* HDD size in GB */ 23 | #define BP_ACPIDEV L"ACPI\\ACPI0003\\0" /* Name of false device */ 24 | #define BP_MACADDR L"06:02:27:9C:BB:27" /* consistency with BP_MAC_VENDOR? :) */ 25 | #define BP_MUI "it-IT" /* MUI language string */ 26 | 27 | // fake objects 28 | #define BP_FAKEFILE "C:\\a\\" 29 | #define BP_FAKEFILE_W L"C:\\a\\" 30 | #define BP_POPEN "cd" 31 | #define BP_FAKEDLL "sup.dll" 32 | #define BP_FAKEDLL_W L"sup.dll" 33 | #define BP_FAKEDRV "vga.sys" 34 | #define BP_FAKEDRV_W L"vga.sys" 35 | 36 | // misc parameters used in the implementation 37 | #define PATH_BUFSIZE 512 38 | 39 | #if !FIXED_KNOBS 40 | extern BOOL _nxKnob; 41 | extern BOOL _paranoidKnob; 42 | extern BOOL _rwKnob; 43 | extern BOOL _leakKnob; 44 | extern BOOL _libdftKnob; 45 | extern BOOL _evasions; 46 | extern BOOL _debugger; 47 | #else 48 | #define _paranoidKnob false 49 | #define _nxKnob false 50 | #define _rwKnob false 51 | #define _leakKnob true 52 | #define _libdftKnob false 53 | #define _evasions true 54 | #define _debugger false 55 | #endif 56 | -------------------------------------------------------------------------------- /pintool/src/fpu.cpp: -------------------------------------------------------------------------------- 1 | #include "fpu.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | REG spilledFpu; 8 | 9 | VOID FPU_Init() { 10 | 11 | spilledFpu = PIN_ClaimToolRegister(); 12 | 13 | } 14 | 15 | VOID PIN_FAST_ANALYSIS_CALL FPU_UpdateFPUStatus(ADDRINT regValue, ADDRINT op) { 16 | 17 | LOG_AR("Possible FPU Leak"); 18 | PIN_SafeCopy((VOID *)(op + FPUIPOFFSET), ®Value, sizeof(ADDRINT)); 19 | 20 | } 21 | 22 | ADDRINT PIN_FAST_ANALYSIS_CALL FPU_UpdateLastFpuIns(ADDRINT addr) { 23 | 24 | return addr; 25 | 26 | } 27 | 28 | VOID FPU_InstrumentINS(INS ins) { 29 | 30 | if (INS_Category(ins) == XED_CATEGORY_X87_ALU) { 31 | 32 | string code = INS_Disassemble(ins); 33 | 34 | if (code.find("fwait") != string::npos) return; 35 | 36 | if (code.find("fnstenv") != string::npos || code.find("fstenv") != string::npos || 37 | code.find("fsave") != string::npos || code.find("fnsave") != string::npos || 38 | code.find("fxsave") != string::npos) { 39 | 40 | INS_InsertCall(ins, IPOINT_AFTER, 41 | (AFUNPTR)FPU_UpdateFPUStatus, 42 | IARG_FAST_ANALYSIS_CALL, 43 | IARG_REG_VALUE, spilledFpu, 44 | IARG_MEMORYOP_EA, 0, 45 | IARG_END); 46 | 47 | } 48 | else { //TODO specify only ins that change FPU state 49 | 50 | INS_InsertCall(ins, IPOINT_AFTER, 51 | (AFUNPTR)FPU_UpdateLastFpuIns, 52 | IARG_FAST_ANALYSIS_CALL, 53 | IARG_INST_PTR, 54 | IARG_RETURN_REGS, spilledFpu, 55 | IARG_END); 56 | 57 | } 58 | 59 | /* 60 | UINT32 opc = 0; //need this 61 | ADDRINT addr = INS_Address(ins); 62 | USIZE size = INS_Size(ins); 63 | PIN_SafeCopy(&opc, (void*)addr, size); 64 | cout << INS_Disassemble(ins) << " 0x" << hex << opc << " " << size << endl; 65 | opc &= 0xFF; 66 | cout << INS_Disassemble(ins) << " N0x" << hex << opc << endl; 67 | if (opc == 0x9B) return; 68 | if (opc == 0xD9 || 0xDD) cout << INS_Disassemble(ins) << endl;; 69 | */ 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /pintool/src/syshooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "syshooking.h" 3 | 4 | namespace SYSHOOKS { 5 | // BluePill 6 | VOID NtDelayexecution_entry(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 7 | VOID NtQueryDirectoryObject_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 8 | VOID NtOpenKey_exit(syscall_t * sc, CONTEXT * ctx, SYSCALL_STANDARD std); 9 | VOID NtCreateFile_entry(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 10 | VOID NtEnumerateKey_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 11 | VOID NtQueryValueKey_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 12 | VOID NtQueryAttributesFile_entry(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 13 | VOID NtQueryObject_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 14 | VOID NtUserEnumDisplayDevices_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 15 | VOID NtUserFindWindowEx_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 16 | VOID NtQuerySystemInformation_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 17 | VOID NtQueryInformationProcess_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 18 | VOID NtQueryPerformanceCounter_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 19 | 20 | // SoK DBI Anti-evasion 21 | VOID GenericScan_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 22 | VOID GenericHookDereference_exit(syscall_t *sc, CONTEXT *ctx, UINT32 argNum); 23 | VOID NtUnmapViewOfSection_entry(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 24 | VOID NtProtectVirtualMemory_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 25 | VOID NtUnmapViewOfSection_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 26 | VOID NtFreeVirtualMemory_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 27 | VOID NtFreeUserPhysicalPages_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 28 | VOID NtQueryVirtualMemory_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 29 | VOID NtAllocateVirtualMemory_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 30 | VOID NtAllocateUserPhysicalPages_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 31 | VOID NtMapViewOfSection_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 32 | VOID NtGetMUIRegistryInfo_exit(syscall_t *sc, CONTEXT *ctx, SYSCALL_STANDARD std); 33 | } -------------------------------------------------------------------------------- /pintool/src/libdft/branch_pred.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2010, 2011, 2012, 2013, Columbia University 3 | * All rights reserved. 4 | * 5 | * This software was developed by Vasileios P. Kemerlis 6 | * at Columbia University, New York, NY, USA, in June 2010. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Columbia University nor the 17 | * names of its contributors may be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef LIBDFT_BRANCH_PRED_H 34 | #define LIBDFT_BRANCH_PRED_H 35 | 36 | /* compiler directives for branch prediction */ 37 | //#define likely(x) __builtin_expect((x), 1) 38 | //#define unlikely(x) __builtin_expect((x), 0) 39 | 40 | // DCD not really effective on MSVC - shall we use (x) and !(x) instead? 41 | #define likely(x) ((x) ? 1 : 0) 42 | #define unlikely(x) ((!(x)) ? 0 : 1) 43 | 44 | #endif /* LIBDFT_BRANCH_PRED_H */ 45 | -------------------------------------------------------------------------------- /pintool/src/memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pin.H" 3 | 4 | #include "logging.h" 5 | 6 | namespace W { 7 | #define WIN32_LEAN_AND_MEAN 8 | #include "windows.h" 9 | #include "Winternl.h" 10 | #include "Intsafe.h" 11 | } 12 | 13 | #include "winheaders.h" 14 | 15 | #define OS_PAGE_SIZE 4096 16 | #define OS_PAGE_OFFSET_BITS 12 17 | #define OS_NUM_PAGES (1 << (32 - OS_PAGE_OFFSET_BITS)) 18 | #define OS_CLEAR_MASK 0xFFFFF000 19 | 20 | #define OS_ALLOCATION_SIZE 65536 21 | 22 | #define OS_KUSER_SHARED_DATA_ADDRESS 0x7ffe0000 23 | #define OS_KUSER_SHARED_DATA_SIZE 0x3e0 24 | 25 | #define MEMORY_VERBOSE 0 26 | #define MEMORY_NX_PARANOID_OLD 0 27 | 28 | 29 | 30 | typedef struct _MEMORY_BASIC_INFORMATION { 31 | W::PVOID BaseAddress; 32 | W::PVOID AllocationBase; 33 | W::ULONG AllocationProtect; 34 | W::SIZE_T RegionSize; 35 | W::ULONG State; 36 | W::ULONG Protect; 37 | W::ULONG Type; 38 | } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 39 | 40 | typedef enum _MEMORY_INFORMATION_CLASS { 41 | MemoryBasicInformation 42 | } MEMORY_INFORMATION_CLASS; 43 | 44 | typedef unsigned char MEM_MASK; 45 | 46 | typedef struct sez{ 47 | ADDRINT start; 48 | ADDRINT end; 49 | } struct_section; 50 | 51 | // instrumentation initialization and callbacks 52 | void MEMORY_Init(); 53 | void MEMORY_InstrumentINS(INS ins); 54 | void MEMORY_LoadImage(IMG img); 55 | void MEMORY_UnloadImage(IMG img); 56 | void MEMORY_OnThreadStart(CONTEXT *ctxt); 57 | 58 | // helper methods used also in hooks.cpp 59 | void MEMORY_RegisterArea(ADDRINT start, ADDRINT size, MEM_MASK mask); 60 | void MEMORY_ChangePermissionsForArea(ADDRINT start, ADDRINT size, MEM_MASK mask); 61 | void MEMORY_UnregisterArea(ADDRINT start, size_t size); 62 | void MEMORY_QueryWindows(ADDRINT address, ADDRINT *base, ADDRINT *size, MEM_MASK *mask); 63 | MEM_MASK MEMORY_WinToPinCast(UINT32 permissions); 64 | bool MEMORY_AddMappedMemoryStar(ADDRINT start, ADDRINT end, bool print); 65 | 66 | // internal functions (TODO add prototypes for others? we will see...) 67 | VOID MEMORY_AddPebAddress(); 68 | VOID MEMORY_AddProcessHeaps(); 69 | VOID MEMORY_AddKUserShareData(); 70 | bool MEMORY_AddMappedMemory(ADDRINT start, ADDRINT end, bool print, ADDRINT eip); 71 | int MEMORY_AuxRegisterArea(ADDRINT start, ADDRINT size, MEM_MASK mask); 72 | bool MEMORY_ChangePermissionsForAreaStar(ADDRINT start, ADDRINT size, MEM_MASK mask); 73 | -------------------------------------------------------------------------------- /pintool/src/libdft/libdft_core.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2010, 2011, 2012, 2013, Columbia University 3 | * All rights reserved. 4 | * 5 | * This software was developed by Vasileios P. Kemerlis 6 | * at Columbia University, New York, NY, USA, in June 2010. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Columbia University nor the 17 | * names of its contributors may be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef LIBDFT_CORE_H 34 | #define LIBDFT_CORE_H 35 | 36 | #include "pin.H" // DCD 37 | 38 | #define VCPU_MASK32 0x0F /* 32-bit VCPU mask */ 39 | #define VCPU_MASK16 0x03 /* 16-bit VCPU mask */ 40 | #define VCPU_MASK8 0x01 /* 8-bit VCPU mask */ 41 | #define MEM_LONG_LEN 32 /* long size (32-bit) */ 42 | #define MEM_WORD_LEN 16 /* word size (16-bit) */ 43 | #define MEM_BYTE_LEN 8 /* byte size (8-bit) */ 44 | #define BIT2BYTE(len) ((len) >> 3) /* scale change; macro */ 45 | 46 | /* extract the EFLAGS.DF bit by applying the corresponding mask */ 47 | #define EFLAGS_DF(eflags) ((eflags & 0x0400)) 48 | 49 | enum { 50 | /* #define */ OP_0 = 0, /* 0th (1st) operand index */ 51 | /* #define */ OP_1 = 1, /* 1st (2nd) operand index */ 52 | /* #define */ OP_2 = 2, /* 2nd (3rd) operand index */ 53 | /* #define */ OP_3 = 3, /* 3rd (4th) operand index */ 54 | /* #define */ OP_4 = 4 /* 4rd (5th) operand index */ 55 | }; 56 | 57 | 58 | /* core API */ 59 | void ins_inspect(INS); 60 | 61 | #endif /* LIBDFT_CORE_H */ 62 | -------------------------------------------------------------------------------- /pintool/src/libdft/tagmap_custom.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBDFT_TAGMAP_CUSTOM_H 2 | #define LIBDFT_TAGMAP_CUSTOM_H 3 | #include "array.hpp" 4 | 5 | const unsigned long DIR_PAGE_BITS = 12; 6 | const unsigned long DIR_PAGE_SZ = 1 << DIR_PAGE_BITS; 7 | const unsigned long DIR_PAGE_MASK = DIR_PAGE_SZ - 1; 8 | const unsigned long DIR_TABLE_BITS = 10; 9 | const unsigned long DIR_TABLE_SZ = 1 << DIR_TABLE_BITS; 10 | const unsigned long DIR_TABLE_MASK = DIR_TABLE_SZ - 1; 11 | const unsigned long DIR_BITS = 10; 12 | const unsigned long DIR_SZ = 1 << DIR_BITS; 13 | const unsigned long DIR_MASK = DIR_SZ - 1; 14 | 15 | inline unsigned long virt2table(unsigned long addr) { 16 | return (addr >> (DIR_PAGE_BITS + DIR_TABLE_BITS)) & DIR_MASK; 17 | } 18 | 19 | inline unsigned long virt2page(unsigned long addr) { 20 | return (addr >> DIR_PAGE_BITS) & DIR_TABLE_MASK; 21 | } 22 | 23 | inline unsigned long virt2offset(unsigned long addr) { 24 | return addr & DIR_PAGE_MASK; 25 | } 26 | 27 | typedef cpp11::array tag_page_t; 28 | typedef cpp11::array tag_table_t; 29 | typedef cpp11::array tag_dir_t; 30 | 31 | extern int tagmap_all_tainted; 32 | extern void libdft_die(); 33 | 34 | inline tag_t const * tag_dir_getb_as_ptr(tag_dir_t const & dir, ADDRINT addr) { 35 | if(dir[virt2table(addr)]) { 36 | tag_table_t * table = dir[virt2table(addr)]; 37 | if ((*table)[virt2page(addr)]) { 38 | tag_page_t * page = (*table)[virt2page(addr)]; 39 | if (page != NULL) 40 | return &(*page)[virt2offset(addr)]; 41 | } 42 | } 43 | return &tag_traits::cleared_val; 44 | } 45 | 46 | inline tag_t tag_dir_getb(tag_dir_t const & dir, ADDRINT addr) { 47 | return *tag_dir_getb_as_ptr(dir, addr); 48 | } 49 | 50 | 51 | inline void tag_dir_setb(tag_dir_t & dir, ADDRINT addr, tag_t const & tag) 52 | { 53 | //LOG("Setting tag "+hexstr(addr)+"\n"); 54 | if(dir[virt2table(addr)] == NULL) 55 | { 56 | //LOG("No tag table for "+hexstr(addr)+" allocating new table\n"); 57 | tag_table_t * new_table = new tag_table_t(); // DCD (nothrow) 58 | if (new_table == NULL) 59 | { 60 | LOG("Failed to allocate tag table!\n"); 61 | libdft_die(); 62 | } 63 | dir[virt2table(addr)] = new_table; 64 | } 65 | 66 | tag_table_t * table = dir[virt2table(addr)]; 67 | if ((*table)[virt2page(addr)] == NULL) 68 | { 69 | //LOG("No tag page for "+hexstr(addr)+" allocating new page\n"); 70 | tag_page_t * new_page = new tag_page_t(); // DCD (nothrow) 71 | if (new_page == NULL) 72 | { 73 | LOG("Failed to allocate tag page!\n"); 74 | libdft_die(); 75 | } 76 | cpp::fill(new_page->begin(), new_page->end(), tag_traits::cleared_val); 77 | (*table)[virt2page(addr)] = new_page; 78 | } 79 | 80 | tag_page_t * page = (*table)[virt2page(addr)]; 81 | //LOG("Writing tag for "+hexstr(addr)+"\n"); 82 | (*page)[virt2offset(addr)] = tag; 83 | } 84 | #endif 85 | -------------------------------------------------------------------------------- /pintool/src/state.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pin.H" // has to go before winheaders.h or everything will break... meh! 4 | #include "winheaders.h" 5 | #include "itree.h" 6 | 7 | namespace State { 8 | 9 | void init(); 10 | 11 | 12 | struct timeInfo { 13 | W::DWORD sleepMs; // WaitForSingleObjectHook, SYSHOOKS::NtDelayexecution_entry, INS_patchRtdsc_exit 14 | W::DWORD sleepMsTick; // GetTickCount, WaitForSingleObjectHook, SYSHOOKS::NtDelayexecution_entry, SYSHOOKS::NtQueryPerformanceCounter_exit 15 | W::SHORT sleepTime; // NtDelayexecution, IcmpCreateFileEntryHook 16 | W::DWORD lastMs; // SYSHOOKS::NtDelayexecution_entry 17 | W::DWORD numLastMs; // SYSHOOKS::NtDelayexecution_entry 18 | W::DWORD lastMs2; // SYSHOOKS::NtQueryPerformanceCounter 19 | W::DWORD numLastMs2; // SYSHOOKS::NtQueryPerformanceCounter 20 | W::DWORD tick; // GetTickCountHook - REQUIRES INITIALIZATION 21 | UINT64 _edx_eax; // INS_patchRtdsc_exit - REQUIRES INITIALIZATION 22 | UINT32 _eax; // INS_patchRtdsc_exit 23 | UINT32 _edx; // INS_patchRtdsc_exit 24 | }; 25 | 26 | struct globalState { 27 | timeInfo _timeInfo; 28 | W::SHORT ntQueryCounter; 29 | W::SHORT flagStep; 30 | W::BOOL waitForDebugger; 31 | itreenode_t* dllRangeITree; 32 | }; 33 | 34 | // union would have been great, but how can we rule out nested hooks? 35 | struct hookEntryArgsTLS { 36 | ADDRINT cpuid_eax; // INS_patchCpuid_entry 37 | W::LPBYTE dataQuery; // RegQueryValueEx 38 | W::LPTSTR buf; // WNetGetProviderNameHookEntry 39 | W::LPPROCESSENTRY32 lp; // Process32NextEntry 40 | struct getDiskFreeSpace { // GetDiskFreeSpaceHookEntry 41 | W::PULARGE_INTEGER lpFreeBytesAvailable; 42 | W::PULARGE_INTEGER lpTotalNumberOfBytes; 43 | W::PULARGE_INTEGER lpTotalNumberOfFreeBytes; 44 | } _getDiskFreeSpace; 45 | W::LPTSTR driverBaseName; // GetDeviceDriverBaseNameHookEntry 46 | W::LPTSTR windowName; // GetWindowTextHookEntry 47 | W::LPTSTR modName; // GetModuleFileNameHookEntry 48 | struct getAdaptersInfo { // GetAdaptersInfoHookEntry 49 | PIP_ADAPTER_INFO macStruct; 50 | W::PULONG macSizeStruct; 51 | W::ULONG macSizeStructInitial; 52 | } _getAdaptersInfo; 53 | W::PBYTE devBuff; // SetupDiGetDeviceRegistryPropertyHookEntry 54 | W::INT NtCloseFlag; // CloseHandleHookEntry 55 | W::LPPOINT cursorPoint; // GetCursorPosHookEntry 56 | W::LPSYSTEM_INFO sysInfo; // GetSystemInfoHookEntry 57 | W::PSYSTEM_POWER_CAPABILITIES powerCap; // GetPwrCapabilitiesHookEntry 58 | struct wmiQuery { 59 | W::VARIANT *varpt; // WMIQueryHookEntry 60 | W::LPCWSTR queryWMI; // WMIQueryHookEntry 61 | } _wmiQuery; 62 | // misc stuff 63 | ADDRINT retAddr; 64 | bool retAddrInDLL; 65 | const char* retAddrInDll_data; 66 | ADDRINT getDiskFreeSpaceRetAddr; 67 | }; 68 | 69 | // timing info 70 | //W::DWORD tick; 71 | 72 | // access methods 73 | globalState* getGlobalState(); 74 | hookEntryArgsTLS* getHookEntryTLSArgs(); 75 | }; 76 | 77 | 78 | extern State::hookEntryArgsTLS _hookEntryTLSArgs; 79 | //extern State::timeInfo _timeInfo; 80 | extern State::globalState _globalState; 81 | 82 | #define FetchHookTLS State::hookEntryArgsTLS* in = &_hookEntryTLSArgs; 83 | #define FetchTimeState State::timeInfo* tinfo = &_globalState._timeInfo; 84 | #define FetchGlobalState State::globalState* gs = &_globalState; 85 | -------------------------------------------------------------------------------- /pintool/src/libdft/tag_traits.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBDFT_TAG_TRAITS_H 2 | #define LIBDFT_TAG_TRAITS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /******************************************************** 9 | templates for tag type and combine functions 10 | ********************************************************/ 11 | template struct tag_traits {}; 12 | 13 | /* combine tags */ 14 | template T tag_combine(T const & lhs, T const & rhs); 15 | 16 | /* combine tags in-place */ 17 | template void tag_combine_inplace(T & lhs, T const & rhs); 18 | 19 | /* print to string */ 20 | template std::string tag_sprint(T const & tag); 21 | 22 | 23 | /******************************************************** 24 | uint8_t tags 25 | ********************************************************/ 26 | typedef uint8_t libdft_tag_uint8; 27 | 28 | template<> 29 | struct tag_traits 30 | { 31 | typedef unsigned char type; 32 | static const bool is_container = false; 33 | static const uint8_t cleared_val = 0; 34 | static const uint8_t set_val = 1; 35 | }; 36 | 37 | template<> 38 | unsigned char tag_combine(unsigned char const & lhs, unsigned char const & rhs); 39 | 40 | template<> 41 | void tag_combine_inplace(unsigned char & lhs, unsigned char const & rhs); 42 | 43 | template<> 44 | std::string tag_sprint(unsigned char const & tag); 45 | 46 | /******************************************************** 47 | uint32_t set tags 48 | ********************************************************/ 49 | typedef std::set libdft_tag_set_uint32; // DCD typedef typename vs C++03 50 | 51 | template<> 52 | struct tag_traits > 53 | { 54 | typedef std::set type; // DCD typedef typename vs C++03 55 | typedef uint32_t inner_type; 56 | static const bool is_container = true; 57 | static const std::set cleared_val; 58 | static const std::set set_val; 59 | }; 60 | 61 | template<> 62 | std::set tag_combine(std::set const & lhs, std::set const & rhs); 63 | 64 | template<> 65 | void tag_combine_inplace(std::set & lhs, std::set const & rhs); 66 | 67 | template<> 68 | std::string tag_sprint(std::set const & tag); 69 | 70 | /******************************************************** 71 | fd-offset set tags 72 | ********************************************************/ 73 | typedef std::pair fdoff_t; // DCD typedef typename vs C++03 74 | typedef std::set libdft_tag_set_fdoff; // DCD typedef typename vs C++03 75 | 76 | template<> 77 | struct tag_traits > 78 | { 79 | typedef std::set type; // DCD typedef typename vs C++03 80 | typedef fdoff_t inner_type; 81 | static const bool is_container = true; 82 | static const std::set cleared_val; 83 | static const std::set set_val; 84 | }; 85 | 86 | template<> 87 | std::set > tag_combine(std::set > const & lhs, std::set > const & rhs); 88 | 89 | template<> 90 | void tag_combine_inplace(std::set > & lhs, std::set > const & rhs); 91 | 92 | template<> 93 | std::string tag_sprint(std::set > const & tag); 94 | 95 | /******************************************************** 96 | bitset tags 97 | ********************************************************/ 98 | #if TAG_BITSET_SIZE < 8 99 | #undef TAG_BITSET_SIZE 100 | #define TAG_BITSET_SIZE 8 101 | #endif 102 | typedef std::bitset libdft_tag_bitset; // DCD typedef typename vs C++03 103 | 104 | template<> 105 | struct tag_traits > 106 | { 107 | typedef std::bitset type; // DCD typedef typename vs C++03 108 | typedef uint8_t inner_type; // ??? 109 | static const bool is_container = false; 110 | static const std::bitset cleared_val; 111 | static const std::bitset set_val; 112 | }; 113 | 114 | template<> 115 | std::bitset tag_combine(std::bitset const & lhs, std::bitset const & rhs); 116 | 117 | template<> 118 | void tag_combine_inplace(std::bitset & lhs, std::bitset const & rhs); 119 | 120 | template<> 121 | std::string tag_sprint(std::bitset const & tag); 122 | 123 | #endif /* LIBDFT_TAG_TRAITS_H */ 124 | 125 | /* vim: set noet ts=4 sts=4 : */ 126 | -------------------------------------------------------------------------------- /pintool/src/libdft/tag_traits.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "tag_traits.h" 7 | 8 | /* *** Unsigned char based tags. ************************************/ 9 | //extern void* __dso_handle; // needed when compiling with PinCRT 10 | 11 | template<> 12 | unsigned char tag_combine(unsigned char const & lhs, unsigned char const & rhs) { 13 | return lhs | rhs; 14 | } 15 | 16 | template<> 17 | void tag_combine_inplace(unsigned char & lhs, unsigned char const & rhs) { 18 | lhs |= rhs; 19 | } 20 | 21 | template<> 22 | std::string tag_sprint(unsigned char const & tag) { 23 | std::stringstream ss; 24 | ss << std::bitset<(sizeof(tag) << 3)>(tag); 25 | return ss.str(); 26 | //return std::bitset<(sizeof(tag) << 3)>(tag).to_string(); 27 | } 28 | 29 | /* *** Workaround for initializer lists *****************************/ 30 | std::set setValWrapper() { 31 | std::set s; 32 | s.insert(1); 33 | return s; 34 | } 35 | 36 | std::set setFdoffWrapper() { 37 | std::set s; 38 | s.insert(fdoff_t(0,0)); 39 | return s; 40 | } 41 | 42 | 43 | /* *** set based tags. ************************************/ 44 | /* define the set/cleared values */ 45 | const std::set tag_traits >::cleared_val = std::set(); 46 | 47 | const std::set tag_traits >::set_val = setValWrapper(); //std::set{1}; 48 | 49 | template<> 50 | std::set tag_combine(std::set const & lhs, std::set const & rhs) { 51 | std::set res; 52 | 53 | std::set_union( 54 | lhs.begin(), lhs.end(), 55 | rhs.begin(), rhs.end(), 56 | std::inserter(res, res.begin()) 57 | ); 58 | 59 | return res; 60 | } 61 | 62 | template<> 63 | void tag_combine_inplace(std::set & lhs, std::set const & rhs) { 64 | lhs.insert(rhs.begin(), rhs.end()); 65 | } 66 | 67 | template<> 68 | std::string tag_sprint(std::set const & tag) { 69 | std::set::const_iterator t; 70 | std::stringstream ss; 71 | 72 | ss << "{"; 73 | if (!tag.empty()) { 74 | std::set::const_iterator last = --tag.end(); //std::prev(tag.end()); 75 | for (t = tag.begin(); t != last; t++) 76 | ss << *t << ", "; 77 | ss << *(t++); 78 | } 79 | ss << "}"; 80 | return ss.str(); 81 | } 82 | 83 | 84 | /* *** set based tags. ************************************/ 85 | /* 86 | define the set/cleared values 87 | the set_val is kind of arbitrary here - represents offset 0 of stdin 88 | */ 89 | const std::set tag_traits >::cleared_val = std::set(); 90 | const std::set tag_traits >::set_val = setFdoffWrapper(); //std::set{fdoff_t{0, 0}}; 91 | 92 | template<> 93 | std::set tag_combine(std::set const & lhs, std::set const & rhs) { 94 | std::set res; 95 | 96 | std::set_union( 97 | lhs.begin(), lhs.end(), 98 | rhs.begin(), rhs.end(), 99 | std::inserter(res, res.begin()) 100 | ); 101 | 102 | return res; 103 | } 104 | 105 | template<> 106 | void tag_combine_inplace(std::set & lhs, std::set const & rhs) { 107 | lhs.insert(rhs.begin(), rhs.end()); 108 | } 109 | 110 | template<> 111 | std::string tag_sprint(std::set const & tag) { 112 | std::set::const_iterator t; 113 | std::stringstream ss; 114 | 115 | ss << "{"; 116 | if (!tag.empty()) { 117 | std::set::const_iterator last = --tag.end(); //std::prev(tag.end()); 118 | for (t = tag.begin(); t != last; t++) 119 | ss << (*t).first << ":" << (*t).second << ", "; 120 | ss << (*t).first << ":" << (*t).second; 121 | t++; 122 | } 123 | ss << "}"; 124 | return ss.str(); 125 | } 126 | 127 | 128 | /* *** bitset<> based tags. ****************************************/ 129 | /* 130 | define the set/cleared values 131 | the set_val is kind of arbitrary - represents all bits set 132 | */ 133 | const std::bitset tag_traits >::cleared_val = std::bitset(); //std::bitset{}; 134 | const std::bitset tag_traits >::set_val = std::bitset().set(); //std::bitset{}.set(); 135 | 136 | template<> 137 | std::bitset tag_combine(std::bitset const & lhs, std::bitset const & rhs) { 138 | return lhs | rhs; 139 | } 140 | 141 | template<> 142 | void tag_combine_inplace(std::bitset & lhs, std::bitset const & rhs) { 143 | lhs |= rhs; 144 | } 145 | 146 | template<> 147 | std::string tag_sprint(std::bitset const & tag) { 148 | std::stringstream ss; 149 | ss << tag; 150 | return ss.str(); 151 | //return tag.to_string(); 152 | } 153 | 154 | /* vim: set noet ts=4 sts=4 : */ 155 | -------------------------------------------------------------------------------- /pintool/src/libdft/tagmap.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2010, 2011, 2012, 2013, Columbia University 3 | * All rights reserved. 4 | * 5 | * This software was developed by Vasileios P. Kemerlis 6 | * at Columbia University, New York, NY, USA, in June 2010. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Columbia University nor the 17 | * names of its contributors may be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | /* 34 | * 05/28/2011: 35 | * the size of the bitmap was reverted back to 512MB; 36 | * the vsyscall mechanism results into accessing 37 | * addresses above PAGE_OFFSET (i.e., 0xc0000000) 38 | */ 39 | 40 | #ifndef LIBDFT_TAGMAP_H 41 | #define LIBDFT_TAGMAP_H 42 | 43 | #include "pin.H" 44 | #include "libdft_config.h" 45 | 46 | 47 | #ifndef USE_CUSTOM_TAG 48 | /* 49 | * the bitmap size in bytes 50 | * 51 | * we assign one bit for every addressable 52 | * byte of the virtual memory; assuming a 53 | * 32-bit virtual address space, the bitmap 54 | * size should be 512 MB. However, in most 55 | * cases the upper 1G is mapped to the 56 | * kernel, so we only need 384 MB -- when 57 | * a 2G/2G, or 1G/3G split is used, we need 58 | * even less bytes for the bitmap (i.e., 59 | * 256 MB, or 128 MB respectively). 60 | */ 61 | /* #define BITMAP_SZ 384*1024*1024 */ 62 | #define BITMAP_SZ 512*1024*1024 63 | 64 | #define BYTE_MASK 0x01U /* byte mask; 1 bit */ 65 | #define WORD_MASK 0x0003U /* word mask; 2 sequential bits */ 66 | #define LONG_MASK 0x000FU /* long mask; 4 sequential bits */ 67 | #define QUAD_MASK 0x00FFU /* quad mask; 8 sequential bits */ 68 | #define _3BYTE_MASK 0x0007U /* 3 bytes mask; 3 sequential bits */ 69 | #define _5BYTE_MASK 0x001FU /* 5 bytes mask; 5 sequential bits */ 70 | #define _6BYTE_MASK 0x003FU /* 6 bytes mask; 6 sequential bits */ 71 | #define _7BYTE_MASK 0x007FU /* 7 bytes mask; 7 sequential bits */ 72 | 73 | /* given a virtual address estimate the byte offset on the bitmap */ 74 | #define VIRT2BYTE(addr) ((addr) >> 3) 75 | 76 | /* given a virtual address estimate the bit offset on the bitmap */ 77 | #define VIRT2BIT(addr) ((addr) & 0x00000007U) 78 | 79 | #define ALIGN_OFF_MAX 8 /* max alignment offset */ 80 | #define ASSERT_FAST 32 /* used in comparisons */ 81 | 82 | #else 83 | #include "tagmap_custom.h" 84 | #endif 85 | 86 | 87 | /* common tagmap API */ 88 | int tagmap_alloc(void); 89 | void tagmap_free(void); 90 | void PIN_FAST_ANALYSIS_CALL tagmap_setb(size_t); 91 | void PIN_FAST_ANALYSIS_CALL tagmap_setw(size_t); 92 | void PIN_FAST_ANALYSIS_CALL tagmap_setl(size_t); 93 | void PIN_FAST_ANALYSIS_CALL tagmap_clrb(size_t); 94 | void PIN_FAST_ANALYSIS_CALL tagmap_clrw(size_t); 95 | void PIN_FAST_ANALYSIS_CALL tagmap_clrl(size_t); 96 | void tagmap_clear_all(void); 97 | void tagmap_taint_all(void); 98 | void tagmap_setn(size_t, size_t); 99 | void tagmap_clrn(size_t, size_t); 100 | 101 | /* implementation-specific tagmap API */ 102 | #ifndef USE_CUSTOM_TAG 103 | size_t tagmap_getb(size_t); 104 | size_t PIN_FAST_ANALYSIS_CALL tagmap_getw(size_t); 105 | size_t PIN_FAST_ANALYSIS_CALL tagmap_getl(size_t); 106 | size_t tagmap_issetn(size_t, size_t); 107 | #else 108 | tag_t tagmap_getb(size_t); 109 | tag_t tagmap_getw(size_t); 110 | tag_t tagmap_getl(size_t); 111 | void PIN_FAST_ANALYSIS_CALL tagmap_setb_with_tag(size_t, tag_t const &); 112 | tag_t const * tagmap_getb_as_ptr(size_t); 113 | #endif 114 | 115 | #endif /* LIBDFT_TAGMAP_H */ 116 | 117 | /* vim: set noet ts=8 sts=8 : */ 118 | -------------------------------------------------------------------------------- /pintool/src/wmi.cpp: -------------------------------------------------------------------------------- 1 | #include "wmi.h" 2 | #include "config.h" 3 | 4 | #include 5 | using namespace std; 6 | 7 | #define SUCCEEDEDNEW(hr) (((W::HRESULT)(hr)) >= 0) 8 | 9 | // false string use to patch away VBOXVIDEO 10 | #define FALSESTR "win32k" 11 | 12 | // this may mean little to you, but means a lot to us developers (-: 13 | #define PANICCIA L"SASASASASASASASASA" /*Sattoh */ 14 | 15 | static W::HRESULT(WINAPI *pSafeArrayAccessData)(W::SAFEARRAY *psa, void HUGEP **ppvData); 16 | static W::HRESULT(WINAPI *pSafeArrayGetLBound)(W::SAFEARRAY *psa, UINT nDim, W::LONG *plLbound); 17 | static W::HRESULT(WINAPI *pSafeArrayGetUBound)(W::SAFEARRAY *psa, UINT nDim, W::LONG *plUbound); 18 | static W::HRESULT(WINAPI *pSafeArrayGetElement)(W::SAFEARRAY *psa, W::LONG *rgIndices, void *pv); 19 | 20 | VOID WMI_Patch(W::LPCWSTR query, W::VARIANT *var) { 21 | 22 | // Get the data from the query 23 | if (var == NULL) return; 24 | 25 | if ((var)->n1.n2.vt != W::VT_NULL) { 26 | 27 | char value[PATH_BUFSIZE]; 28 | GET_STR_TO_UPPER(query, value, PATH_BUFSIZE); 29 | 30 | LOG_AR("[WMI-Get]-%s", value); 31 | 32 | if (strstr(value, "NUMBEROFCORES") != NULL) { 33 | //set 8 cores in the machine 34 | var->n1.n2.n3.uintVal = BP_NUMCORES; 35 | } 36 | 37 | else if(strstr(value, "SIZE") != NULL) { 38 | //set new size of HDD 39 | var->n1.n2.n3.llVal = (BP_DISKSIZE * (1024LL * (1024LL * (1024LL)))); 40 | } 41 | 42 | else if (strstr(value, "DEVICEID") != NULL) { 43 | //set the new device ID 44 | memset(var->n1.n2.n3.bstrVal, 0, wcslen(var->n1.n2.n3.bstrVal)*2); 45 | wcscpy(var->n1.n2.n3.bstrVal, BP_ACPIDEV); 46 | } 47 | 48 | else if (strstr(value, "MACADDRESS") != NULL) { 49 | //set new MAC Address 50 | memset(var->n1.n2.n3.bstrVal, 0, wcslen(var->n1.n2.n3.bstrVal) * 2); 51 | wcscpy(var->n1.n2.n3.bstrVal, BP_MACADDR); 52 | } 53 | 54 | else if (strstr(value, "MUILANGUAGES") != NULL) { 55 | //set new MAC Address 56 | //clean NTLog file 57 | W::HMODULE hmod = W::LoadLibraryA("OleAut32.dll"); 58 | *(W::FARPROC *)&pSafeArrayAccessData = W::GetProcAddress(hmod, "SafeArrayAccessData"); 59 | *(W::FARPROC *)&pSafeArrayGetLBound = W::GetProcAddress(hmod, "SafeArrayGetLBound"); 60 | *(W::FARPROC *)&pSafeArrayGetUBound = W::GetProcAddress(hmod, "SafeArrayGetUBound"); 61 | *(W::FARPROC *)&pSafeArrayGetElement = W::GetProcAddress(hmod, "SafeArrayGetElement"); 62 | 63 | W::SAFEARRAY* saSources = var->n1.n2.n3.parray; 64 | W::LONG* pVals; 65 | W::HRESULT hr = pSafeArrayAccessData(saSources, (VOID**)&pVals); // direct access to SA memory 66 | 67 | if (SUCCEEDEDNEW(hr)) { 68 | W::LONG lowerBound, upperBound; 69 | pSafeArrayGetLBound(saSources, 1, &lowerBound); 70 | pSafeArrayGetUBound(saSources, 1, &upperBound); 71 | W::LONG iLength = upperBound - lowerBound + 1; 72 | 73 | // Iteare over our array of BTSR 74 | W::TCHAR* bstrItem; 75 | for (W::LONG ix = 0; ix < iLength; ix++) { 76 | pSafeArrayGetElement(saSources, &ix, (void *)&bstrItem); 77 | 78 | char value1[PATH_BUFSIZE]; 79 | GET_WSTR_TO_UPPER(bstrItem, value1, PATH_BUFSIZE); 80 | 81 | if (strcmp(value1, "EN-US") == 0) { 82 | long* pData = (long*)saSources->pvData + ix; 83 | 84 | memset((char*)*pData, 0, strlen((char*)*pData)); 85 | PIN_SafeCopy((char*)*pData, BP_MUI, strlen(BP_MUI)); 86 | } 87 | } 88 | } 89 | } 90 | 91 | else if (strstr(value, "SOURCES") != NULL) { 92 | //clean NTLog file 93 | W::HMODULE hmod = W::LoadLibraryA("OleAut32.dll"); 94 | *(W::FARPROC *)&pSafeArrayAccessData = W::GetProcAddress(hmod, "SafeArrayAccessData"); 95 | *(W::FARPROC *)&pSafeArrayGetLBound = W::GetProcAddress(hmod, "SafeArrayGetLBound"); 96 | *(W::FARPROC *)&pSafeArrayGetUBound = W::GetProcAddress(hmod, "SafeArrayGetUBound"); 97 | *(W::FARPROC *)&pSafeArrayGetElement = W::GetProcAddress(hmod, "SafeArrayGetElement"); 98 | 99 | W::SAFEARRAY* saSources = var->n1.n2.n3.parray; 100 | W::LONG* pVals; 101 | W::HRESULT hr = pSafeArrayAccessData(saSources, (VOID**)&pVals); // direct access to SA memory 102 | 103 | if (SUCCEEDEDNEW(hr)) { 104 | W::LONG lowerBound, upperBound; 105 | pSafeArrayGetLBound(saSources, 1, &lowerBound); 106 | pSafeArrayGetUBound(saSources, 1, &upperBound); 107 | W::LONG iLength = upperBound - lowerBound + 1; 108 | 109 | // iterate over our array of BTSR 110 | W::TCHAR* bstrItem; 111 | for (W::LONG ix = 0; ix < iLength; ix++) { 112 | pSafeArrayGetElement(saSources, &ix, (void *)&bstrItem); 113 | 114 | char value1[PATH_BUFSIZE]; 115 | GET_WSTR_TO_UPPER(bstrItem, value1, PATH_BUFSIZE); 116 | 117 | if (strcmp(value1, "VBOXVIDEO") == 0) { 118 | long* pData = (long*)saSources->pvData + ix; 119 | 120 | memset((char*)*pData, 0, strlen((char*)*pData)); 121 | PIN_SafeCopy((char*)*pData, FALSESTR, strlen(FALSESTR)); 122 | } 123 | } 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /pintool/src/HiddenElements.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /** 5 | Check HiddenElements.cpp for processes, files, registry 6 | key or values, and other artifacts you want to hide. 7 | **/ 8 | 9 | namespace HiddenElements { 10 | #define MAX_NUMHOOKS 100 11 | #define MAX_HOOKS_IN_GROUP 64 12 | extern bool KTM[MAX_NUMHOOKS]; 13 | 14 | void initializeHiddenStuff(); 15 | 16 | // check element against list of artifacts 17 | bool shouldHideProcessStr(const char* procNameUpper); 18 | bool shouldHideRegOpenKeyStr(const char* strUpper); 19 | bool shouldHideReqQueryValueStr(const char* strUpper); 20 | bool shouldHideGenericFileNameStr(const char* strUpper); 21 | bool shouldHideWindowStr(const char* strUpper); 22 | bool shouldWMIQueryFail(const char* strUpper); 23 | 24 | extern char* hiddenProcesses[MAX_HOOKS_IN_GROUP]; 25 | extern char* regOpenKeyStrings[MAX_HOOKS_IN_GROUP]; 26 | extern char* regQueryValueStrings[MAX_HOOKS_IN_GROUP]; 27 | extern char* genericFilenames[MAX_HOOKS_IN_GROUP]; 28 | extern char* windowNames[MAX_HOOKS_IN_GROUP]; 29 | extern char* WMIQueryFail[MAX_HOOKS_IN_GROUP]; 30 | 31 | /** 32 | We prototyped a GUI for internal use that can selectively 33 | disable hooks while the tool runs.For this reason several 34 | hooks come with a ACTIVE_HOOK() operation in the prologue. 35 | The GUI component would then alter the contents of the KTM 36 | array to turn off or reactivate hooks.For the initial 37 | public release of BluePill we have removed the GUI as its 38 | development didn't keep up the pace with the new additions 39 | to the tool, but we may add it at a later point.We thus 40 | we leave some code as it is, both to favor a reintegration 41 | and to let users manipulate KTM directly if they wish to. 42 | **/ 43 | 44 | // those were manipulated by the GUI 45 | void updateHiddenProcesses(char** procNames); 46 | void updateRegOpenKeyStrings(char** strings); 47 | void updateRegQueryValueStrings(char** strings); 48 | void updateGenericFileNames(char** fileNames); 49 | void updateWindowNames(char** windowsNames); 50 | void updateWMIQueryFail(char** strings); 51 | void setGroup(int groupID, bool value); 52 | 53 | #define ACTIVATE_ALL 0 // use 0 if you alter KTM 54 | #if ACTIVATE_ALL 55 | #define ACTIVE_HOOK(index) \ 56 | do { } while(0) 57 | #else 58 | #define ACTIVE_HOOK(index) \ 59 | do { if(!HiddenElements::KTM[index]) return; } while(0) 60 | #endif 61 | }; 62 | 63 | /** 64 | Those are out of sync with actual hooks available in BluePill. 65 | We should improve the design to have a single enum value to 66 | handle both the hook ID and the toggle for it defined here. 67 | **/ 68 | 69 | typedef enum _HOOK_LIST_ENABLE_DISABLE { 70 | /** syscall category **/ 71 | EN_NtQueryInformationProcess, 72 | EN_NtQuerySystemInformation, 73 | EN_NtQueryPerformanceCounter, 74 | EN_NtOpenProcess, 75 | EN_NtRequestWaitReplyPort, 76 | EN_NtAllocateVirtualMemory, 77 | EN_NtProtectVirtualMemory, 78 | EN_NtCreateFile, 79 | EN_NtWriteVirtualMemory, 80 | EN_NtMapViewOfSection, 81 | EN_NtCreateThreadEx, 82 | EN_NtQueueApcThread, 83 | EN_NtResumeThread, 84 | EN_NtDelayExecution, 85 | EN_NtQueryDirectoryObject, 86 | EN_NtOpenKey, 87 | EN_NtOpenKeyEx, 88 | EN_NtEnumerateKey, 89 | EN_NtQueryValueKey, 90 | EN_NtQueryAttributesFile, 91 | EN_NtOpenDirectoryObject, 92 | EN_NtQueryObject, 93 | EN_NtClose, 94 | /** function category **/ 95 | EN_PlaceholderForMem, // MEMORY group 96 | EN_GetFileAttributes, // FILE group 97 | EN_FindFirstFile, 98 | EN_FindNextFile, 99 | EN_CreateFile, 100 | EN_IsDebuggerPresent, // DEBUGGER group 101 | EN_GetCursorPos, // GUI group 102 | EN_FindWindow, 103 | EN_GetWindowText, 104 | EN_SysAllocString, // WMI group 105 | EN_GetDiskFreeSpaceEx, // HARDWARE group 106 | EN_GetPwrCapabilities, 107 | EN_SetupDiGetDeviceRegistryProperty, 108 | EN_EnumDisplaySettings, 109 | EN_K32GetDeviceDriverBaseName, 110 | EN_GetModuleFileName, // PROCESS group 111 | EN_GetModuleFileNameEx, 112 | EN_Process32Next, 113 | EN_CreateProcessInternal, 114 | EN__popen, // PIPE group 115 | EN__wpopen, 116 | EN__tpopen, 117 | EN_LoadLibrary, // DLL group 118 | EN_LoadLibraryEx, 119 | EN_LdrGetDllHandle, 120 | EN_LdrGetDllHandleEx, 121 | EN_GetTickCount, // TIME group 122 | EN_SetTimer, 123 | EN_GetSystemTimeAsFileTime, 124 | EN_WaitForSingleObject, // MUTEX group 125 | EN_IcmpCreateFile, // NETWORK group 126 | EN_IcmpSendEcho, 127 | EN_WNetGetProviderName, 128 | EN_GetAdaptersInfo, 129 | EN_RegOpenKeyEx, // REGISTRY group 130 | EN_RegOpenKey, 131 | EN_RegQueryValueEx, 132 | EN_RtlCompareUnicodeString, // STRING group 133 | EN_RtlEqualUnicodeString, 134 | EN_wcsstr, 135 | EN_wcscmp, 136 | EN_wcsncmp, 137 | EN__wcsnicmp, 138 | EN_strstr, 139 | EN_strcmp, 140 | EN__strcmpi, 141 | EN_CompareString, 142 | EN_CompareStringEx, 143 | EN_GetSystemInformation, 144 | EN_GetKeyboardLayout, 145 | /** instruction category **/ 146 | EN_rdtsc, 147 | EN_cpuid, 148 | EN_int0x2d, 149 | EN_in, 150 | /** log **/ 151 | EN_GetProcAddr, 152 | EN_GetModHand 153 | 154 | } HOOK_LIST; 155 | 156 | typedef enum { 157 | EN_GR_L_MEMORY, 158 | EN_GR_L_FILE, 159 | EN_GR_L_DEBUGGER, 160 | EN_GR_L_GUI, 161 | EN_GR_L_WMI, 162 | EN_GR_L_HARDWARE, 163 | EN_GR_L_PROCESS, 164 | EN_GR_L_PIPE, 165 | EN_GR_L_DLL, 166 | EN_GR_L_TIME, 167 | EN_GR_L_MUTEX, 168 | EN_GR_L_NETWORK, 169 | EN_GR_L_REGISTRY, 170 | EN_GR_L_STRING, 171 | EN_GR_S_ALL, 172 | EN_GR_I_ALL 173 | } HOOK_GROUPS; 174 | 175 | -------------------------------------------------------------------------------- /pintool/src/functions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "pin.H" 4 | #include "state.h" 5 | #include "config.h" 6 | #include "logging.h" 7 | #include "wmi.h" 8 | 9 | namespace W { 10 | #define WIN32_LEAN_AND_MEAN 11 | #include 12 | #include 13 | #include 14 | } 15 | 16 | namespace Functions { 17 | void Init(); 18 | void AddHooks(IMG img); 19 | }; 20 | 21 | //typedef W::WCHAR PIN_OLECHAR; // for SysAllocString (no longer used) 22 | 23 | /********************** 24 | HOOKS FOR API FUNCTIONS 25 | **********************/ 26 | 27 | // commented-out functions were replaced by lower-level hooks 28 | //VOID RegOpenKeyExHook(W::LPCTSTR * path); 29 | //VOID GetFileAttributesHook(W::LPCSTR * path); 30 | VOID GetAdaptersInfoHookEntry(PIP_ADAPTER_INFO *adapInfo, W::PULONG *size); 31 | VOID GetAdaptersInfoHookExit(ADDRINT ret); 32 | //VOID CreateFileHook(); 33 | VOID FindWindowHook(W::LPCTSTR* path1, W::LPCTSTR* path2); 34 | VOID WNetGetProviderNameHookEntry(W::LPTSTR* buffer); 35 | VOID WNetGetProviderNameHookExit(); 36 | VOID GetTickCountHook(W::DWORD* ret); 37 | VOID SetTimerHook(W::UINT *time); 38 | VOID WaitForSingleObjectHook(W::DWORD *time); 39 | VOID IcmpCreateFileEntryHook(); 40 | VOID IcmpCreateFileExitHook(); 41 | VOID IcmpSendEchoHook(W::DWORD *time); 42 | //VOID SysAllocStringHook(const PIN_OLECHAR **path, ADDRINT ip); 43 | VOID GetDiskFreeSpaceHookExit(); 44 | VOID FindFirstFileHook(W::LPCTSTR *path); 45 | //VOID GetSystemTimeAsFileTimeHook(W::LPFILETIME *lpSystemTimeAsFileTime); 46 | VOID _popenHook(const char **command); 47 | VOID LoadLibraryAHook(const char **lib); 48 | VOID LoadLibraryWHook(const wchar_t **lib); 49 | VOID GetDeviceDriverBaseNameHookEntry(W::LPTSTR *lpBaseName); 50 | VOID GetDeviceDriverBaseNameHookExit(); 51 | VOID GetWindowTextHookEntry(W::LPTSTR *lpString); 52 | VOID GetWindowTextHookExit(); 53 | VOID GetModuleFileNameHookEntry(W::LPTSTR *name); 54 | VOID GetModuleFileNameHookExit(); 55 | //VOID LdrGetDllHandleHook(W::PUNICODE_STRING *p); 56 | VOID SetupDiGetDeviceRegistryPropertyHookExit(ADDRINT ret); 57 | VOID SetupDiGetDeviceRegistryPropertyHookEntry(W::PBYTE *buffer); 58 | VOID CloseHandleHookEntry(W::HANDLE *handle); 59 | VOID CloseHandleHookExit(W::BOOL *ret); 60 | VOID GetCursorPosHookEntry(ADDRINT retAddr, W::LPPOINT *point); 61 | VOID GetCursorPosHookExit(); 62 | VOID GetKeyboardLayoutHookExit(W::HKL* ret); 63 | VOID GetSystemInfoHookEntry(W::LPSYSTEM_INFO *lpSystemInfo); 64 | VOID GetSystemInfoHookExit(); 65 | VOID GetPwrCapabilitiesHookEntry(W::PSYSTEM_POWER_CAPABILITIES *lpspc); 66 | VOID GetPwrCapabilitiesHookExit(); 67 | VOID WMIQueryHookEntry(W::LPCWSTR *query, W::VARIANT **var); 68 | VOID WMIQueryHookExit(); 69 | VOID WMIExecQueryHook(W::TCHAR **Query); 70 | VOID ChangeServiceConfigWHook(W::SC_HANDLE *hService); 71 | VOID GetEnvHookEntry(CHAR** var); 72 | BOOL InitiateSystemShutdownExWHook( 73 | W::LPSTR lpMachineName, 74 | W::LPSTR lpMessage, 75 | W::DWORD dwTimeout, 76 | W::BOOL bForceAppsClosed, 77 | W::BOOL bRebootAfterShutdown, 78 | W::DWORD dwReason); 79 | //VOID SCardDisconnectHookEntry(W::DWORD *par); // Ramillo out 80 | VOID GetDiskFreeSpaceHookEntry(ADDRINT retAddr, 81 | W::PULARGE_INTEGER *lpFreeBytesAvailable, 82 | W::PULARGE_INTEGER *lpTotalNumberOfBytes, 83 | W::PULARGE_INTEGER *lpTotalNumberOfFreeBytes); 84 | 85 | /*DEBUG HOOK*/ 86 | VOID CompareStringHook(W::LPCTSTR *s1, W::LPCTSTR *s2); 87 | VOID RtlCompareUnicodeStringHook(W::PCUNICODE_STRING *s1, W::PCUNICODE_STRING *s2); 88 | VOID wcsstrHook(wchar_t** wcs1, const wchar_t** wcs2); 89 | VOID wcscmpHook(wchar_t** wcs1, const wchar_t** wcs2); 90 | VOID strcmpHook(char** wcs1, const char** wcs2); 91 | VOID strstrHook(char** wcs1, const char** wcs2); 92 | 93 | /*Logging hooks*/ 94 | VOID timeLogHook(ADDRINT retAddr, const char* funName); 95 | VOID logGetSystemTimeAsFileTime(ADDRINT retAddr); 96 | 97 | 98 | // some of the following values might be unused as we 99 | // remove hooks that are no longer necessary 100 | enum { 101 | SLEEP_INDEX = 0, 102 | REGQUERYVALUE_INDEX, 103 | REGOPENKEY_INDEX, 104 | GETFILEATTRIBUTES_INDEX, 105 | GETADAPTER_INDEX, 106 | CREATEFILE_INDEX, 107 | FINDWINDOW_INDEX, 108 | WGETNET_INDEX, 109 | //NEXTPROC_INDEX, 110 | EXECQUERY_INDEX, 111 | GETTICKCOUNT_INDEX, 112 | SETTIMER_INDEX, 113 | WAITOBJ_INDEX, 114 | ICMPFILE_INDEX, 115 | ICMPECHO_INDEX, 116 | ZWQUERY_INDEX, 117 | SYSALLOC_INDEX, 118 | WMI_INDEX, 119 | GETDISKSPACE_INDEX, 120 | EXECQ_INDEX, 121 | GETFIRSTFILE_INDEX, 122 | TIMEASFILE_INDEX, 123 | POPEN_INDEX, 124 | LOADLIBA_INDEX, 125 | LOADLIBW_INDEX, 126 | VPROTECT_INDEX, 127 | DEVICEBASE_INDEX, 128 | WINNAME_INDEX, 129 | GETMODULE_INDEX, 130 | GETMODULEX_INDEX, 131 | LDRHND_INDEX, 132 | SETUPDEV_INDEX, 133 | CLOSEH_INDEX, 134 | GETCUR_INDEX, 135 | GETENV_INDEX, 136 | KEYB_INDEX, 137 | SYSINFO_INDEX, 138 | POWCAP_INDEX, 139 | CHANGSERV_INDEX, 140 | SHUTD_INDEX, 141 | //SANDBOX LOG 142 | GETPROC_INDEX, 143 | GETMODA_INDEX, 144 | GETMODW_INDEX, 145 | CONNECT_INDEX, 146 | //SCARD_INDEX, 147 | /********* index for registry report ***********/ 148 | REGOPEN_INDEX = 60, 149 | REGSET_INDEX, 150 | REGCLOSE_INDEX, 151 | REGCREATE_INDEX, 152 | /********* index for special logging hooks ***********/ 153 | NTDELAYEXEC_INDEX = 70, 154 | NTQUERYPERF_INDEX, 155 | /************* index for debug **************/ 156 | CMPSTR_INDEX = 100, 157 | RTLSTR_INDEX, 158 | WCSSTR_INDEX, 159 | WCSCMP_INDEX, 160 | STRSTR_INDEX, 161 | STRCMP_INDEX 162 | }; 163 | 164 | #define MAX_HOOK_FUNCTIONS_INDEX 128 // TODO handle the enum above more nicely -------------------------------------------------------------------------------- /pintool/src/itree.cpp: -------------------------------------------------------------------------------- 1 | #include "itree.h" 2 | #include 3 | 4 | // most of the following code is a reworked and extended 5 | // version of https://github.com/Frky/iCi (ACSAC'18) 6 | 7 | // Init interval tree 8 | itreenode_t *itree_init(ADDRINT start_addr, ADDRINT end_addr, void *data) { 9 | itreenode_t *tree = (itreenode_t *)malloc(sizeof(itreenode_t)); 10 | tree->start_addr = start_addr; 11 | tree->end_addr = end_addr; 12 | tree->data = data; 13 | tree->left = NULL; 14 | tree->right = NULL; 15 | return tree; 16 | } 17 | 18 | // Insert element in interval tree 19 | bool itree_insert(itreenode_t *tree, ADDRINT start_addr, ADDRINT end_addr, void* data) { 20 | 21 | itreenode_t *senti = tree; 22 | 23 | // Insert duplicate 24 | if (senti->start_addr == start_addr && senti->end_addr == end_addr) 25 | return false; 26 | // Insert in right subtree 27 | else if (senti->end_addr < start_addr) { 28 | // Right subtree present 29 | if (senti->right) { 30 | return itree_insert(senti->right, start_addr, end_addr, data); 31 | } 32 | // No right subtree 33 | else { 34 | senti->right = itree_init(start_addr, end_addr, data); 35 | return true; 36 | } 37 | } 38 | // Insert in left subtree 39 | else { 40 | // Left subtree present 41 | if (senti->left) { 42 | return itree_insert(senti->left, start_addr, end_addr, data); 43 | } 44 | // No left subtree 45 | else { 46 | senti->left = itree_init(start_addr, end_addr, data); 47 | return true; 48 | } 49 | } 50 | return false; 51 | } 52 | 53 | // DCD added node removal 54 | itreenode_t* itree_delete(itreenode_t* tree, ADDRINT start_addr, ADDRINT end_addr) { 55 | // base case 56 | if (tree == NULL) return NULL; 57 | 58 | // node found 59 | if (tree->start_addr == start_addr && tree->end_addr == end_addr) { 60 | itreenode_t* tmp; 61 | // node with only one child 62 | if (tree->left == NULL) { // or no child 63 | tmp = tree->right; 64 | free(tree); 65 | return tmp; 66 | } 67 | else if (tree->right == NULL) { 68 | tmp = tree->left; 69 | free(tree); 70 | return tmp; 71 | } 72 | else { 73 | // node with two children: find leftmost descendant in right 74 | // subtree and paste it into current node, then remove it 75 | tmp = tree->right; 76 | while (tmp && tmp->left) tmp = tmp->left; 77 | tree->start_addr = tmp->start_addr; 78 | tree->end_addr = tmp->end_addr; 79 | tree->data = tmp->data; // TODO memory leak here 80 | tree->right = itree_delete(tree->right, tmp->start_addr, tmp->end_addr); 81 | } 82 | } 83 | else if (tree->end_addr < start_addr) { // right subtree 84 | tree->right = itree_delete(tree->right, start_addr, end_addr); 85 | } 86 | else { // left subtree 87 | tree->left = itree_delete(tree->left, start_addr, end_addr); 88 | } 89 | return tree; 90 | } 91 | 92 | // Search inside interval tree 93 | itreenode_t *itree_search(itreenode_t *tree, ADDRINT val) { 94 | if (!tree) 95 | return NULL; 96 | itreenode_t *senti = tree; 97 | 98 | // Address found in interval 99 | if (val >= senti->start_addr && val <= senti->end_addr) { 100 | return senti; 101 | } 102 | // Search right subtree 103 | else if (senti->end_addr < val) 104 | if (senti->right) 105 | return itree_search(senti->right, val); 106 | else 107 | return NULL; 108 | // Search left subtree 109 | else 110 | if (senti->left) 111 | return itree_search(senti->left, val); 112 | else 113 | return NULL; 114 | return NULL; 115 | } 116 | 117 | // DCD added to perform sanity check 118 | bool itree_verify(itreenode_t *tree) { 119 | if (!tree) return true; 120 | 121 | // well-formed interval: redundant, unless Pin screws up (why so?) 122 | if (tree->end_addr <= tree->start_addr) return false; 123 | 124 | // left child contains interval ending beyond the parent interval's start 125 | if (tree->left && tree->left->end_addr >= tree->start_addr) return false; 126 | 127 | // right child contains interval starting before the parent interval's end 128 | if (tree->right && tree->right->start_addr <= tree->end_addr) return false; 129 | 130 | return (itree_verify(tree->left) && itree_verify(tree->right)); 131 | } 132 | 133 | 134 | void itree_print(itreenode_t *node, ADDRINT lvl) { 135 | if (!node) 136 | return; 137 | 138 | fprintf(stderr, "Level: %u , Range: [0x%0x, 0x%0x]\n", 139 | lvl, node->start_addr, node->end_addr); 140 | itree_print(node->left, lvl + 1); 141 | itree_print(node->right, lvl + 1); 142 | 143 | return; 144 | } 145 | 146 | UINT32 depth(itreenode_t *tree) { 147 | if (!tree) 148 | return 0; 149 | else 150 | return 1 + MAX(depth(tree->right), depth(tree->left)); 151 | } 152 | 153 | UINT32 nb_nodes(itreenode_t *tree) { 154 | if (!tree) 155 | return 0; 156 | else 157 | return 1 + nb_nodes(tree->right) + nb_nodes(tree->left); 158 | } 159 | 160 | // TODO compute balance factor 161 | VOID itree_stats(itreenode_t *node) { 162 | std::cerr << "NODES: " << nb_nodes(node) << std::endl; 163 | std::cerr << "DEPTH: " << depth(node) << std::endl; 164 | return; 165 | } 166 | 167 | // Deallocate interval tree 168 | BOOL itree_dealloc(itreenode_t* tree) { 169 | if (!tree) 170 | return true; 171 | 172 | itreenode_t *senti = tree; 173 | itreenode_t *right = tree->right; 174 | itreenode_t *left = tree->left; 175 | free(tree); // TODO memory leak on data 176 | 177 | if (right) { 178 | itree_dealloc(right); 179 | } 180 | if (left) { 181 | itree_dealloc(left); 182 | } 183 | 184 | return true; 185 | } -------------------------------------------------------------------------------- /pintool/pintool.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Source files 6 | 7 | 8 | Source files 9 | 10 | 11 | Source files 12 | 13 | 14 | Source files 15 | 16 | 17 | 18 | libdft 19 | 20 | 21 | libdft 22 | 23 | 24 | libdft 25 | 26 | 27 | libdft 28 | 29 | 30 | libdft 31 | 32 | 33 | Source files 34 | 35 | 36 | Source files 37 | 38 | 39 | Source files 40 | 41 | 42 | Source files 43 | 44 | 45 | Source files 46 | 47 | 48 | Source files 49 | 50 | 51 | Source files 52 | 53 | 54 | Source files 55 | 56 | 57 | Source files 58 | 59 | 60 | Source files 61 | 62 | 63 | Source files 64 | 65 | 66 | 67 | 68 | {e351ae10-7f4b-438c-b9dd-5ac8e4202289} 69 | 70 | 71 | {a5f1e442-61fc-4dcf-8628-560252b6df05} 72 | 73 | 74 | {25a80272-668f-4457-afcf-1f3963deb8dd} 75 | 76 | 77 | 78 | 79 | Header files 80 | 81 | 82 | Header files 83 | 84 | 85 | Header files 86 | 87 | 88 | Header files 89 | 90 | 91 | Header files 92 | 93 | 94 | Header files 95 | 96 | 97 | libdft 98 | 99 | 100 | libdft 101 | 102 | 103 | libdft 104 | 105 | 106 | libdft 107 | 108 | 109 | libdft 110 | 111 | 112 | libdft 113 | 114 | 115 | libdft 116 | 117 | 118 | libdft 119 | 120 | 121 | libdft 122 | 123 | 124 | Header files 125 | 126 | 127 | Header files 128 | 129 | 130 | Header files 131 | 132 | 133 | Header files 134 | 135 | 136 | Header files 137 | 138 | 139 | Header files 140 | 141 | 142 | Header files 143 | 144 | 145 | Header files 146 | 147 | 148 | Header files 149 | 150 | 151 | Header files 152 | 153 | 154 | Header files 155 | 156 | 157 | Header files 158 | 159 | 160 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /pintool/src/process.cpp: -------------------------------------------------------------------------------- 1 | #include "process.h" 2 | #include "memory.h" 3 | #include "state.h" 4 | #include "itree.h" 5 | #include "config.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define SEG_PROT_R 4 12 | #define SEG_PROT_W 2 13 | #define SEG_PROT_X 1 14 | 15 | using namespace std; 16 | 17 | namespace Process { 18 | BOOL isWow64; 19 | 20 | // helpers 21 | std::ostream& stringify(std::ostream& out, std::string const& s); 22 | 23 | VOID patchPEB() { 24 | PEB32* peb32 = NULL; 25 | PEB64* peb64 = NULL; 26 | if (isWow64) { 27 | W::BYTE* teb32; // = (W::BYTE*)W::NtCurrentTeb(); 28 | __asm { 29 | mov eax, fs:18h 30 | mov teb32, eax 31 | } 32 | W::BYTE* teb64 = teb32 - 0x2000; 33 | peb32 = (PEB32*)(*(W::DWORD*)(teb32 + 0x30)); 34 | peb64 = (PEB64*)(*(W::DWORD64*)(teb64 + 0x60)); 35 | } 36 | else { 37 | __asm { 38 | mov eax, fs:30h 39 | mov peb32, eax 40 | } 41 | } 42 | 43 | // patch PEB32 44 | W::DWORD zero = 0; 45 | W::ULONG numCores = BP_NUMCORES; 46 | W::HANDLE hProc = (W::HANDLE)(-1); 47 | 48 | W::WriteProcessMemory(hProc, (&peb32->NumberOfProcessors), &numCores, sizeof(W::DWORD), 0); 49 | W::WriteProcessMemory(hProc, (&peb32->BeingDebugged), &zero, sizeof(W::BYTE), 0); 50 | W::WriteProcessMemory(hProc, (&peb32->NtGlobalFlag), &zero, sizeof(W::DWORD), 0); 51 | 52 | if (isWow64) { 53 | W::WriteProcessMemory(hProc, (W::LPVOID)(&peb64->NumberOfProcessors), &numCores, sizeof(W::DWORD), 0); 54 | W::WriteProcessMemory(hProc, (&peb64->BeingDebugged), &zero, sizeof(W::BYTE), 0); 55 | W::WriteProcessMemory(hProc, (&peb64->NtGlobalFlag), &zero, sizeof(W::DWORD), 0); 56 | } 57 | } 58 | 59 | /* From IDAngr - Thanks to Andrea Fioraldi */ 60 | // TODO refine it when we have SoK info available? 61 | BOOL Process::VMMap(string* result) { 62 | W::LPBYTE base = NULL; 63 | W::MEMORY_BASIC_INFORMATION mbi; 64 | ostringstream ss; 65 | 66 | BOOL has_map = FALSE; 67 | 68 | while (W::VirtualQuery(base, &mbi, sizeof(W::MEMORY_BASIC_INFORMATION)) > 0) 69 | { 70 | has_map = TRUE; 71 | ss << "[" << (size_t)mbi.BaseAddress << "," << (size_t)mbi.BaseAddress + mbi.RegionSize << ","; 72 | 73 | int mapperm = 0; 74 | if (mbi.Protect & PAGE_EXECUTE) 75 | mapperm = SEG_PROT_X; 76 | else if (mbi.Protect & PAGE_EXECUTE_READ) 77 | mapperm = SEG_PROT_X | SEG_PROT_R; 78 | else if (mbi.Protect & PAGE_EXECUTE_READWRITE) 79 | mapperm = SEG_PROT_X | SEG_PROT_R | SEG_PROT_W; 80 | else if (mbi.Protect & PAGE_EXECUTE_WRITECOPY) 81 | mapperm = SEG_PROT_X | SEG_PROT_R; 82 | //else if (mbi.Protect & PAGE_NOACCESS) 83 | // mapperm = 0; 84 | else if (mbi.Protect & PAGE_READONLY) 85 | mapperm = SEG_PROT_R; 86 | else if (mbi.Protect & PAGE_READWRITE) 87 | mapperm = SEG_PROT_R | SEG_PROT_W; 88 | else if (mbi.Protect & PAGE_WRITECOPY) 89 | mapperm = SEG_PROT_R; 90 | 91 | ss << mapperm << ","; 92 | 93 | IMG img = IMG_FindByAddress((ADDRINT)mbi.BaseAddress); 94 | if (IMG_Valid(img)) 95 | { 96 | ss << "\""; 97 | if (IMG_IsMainExecutable(img)) { 98 | for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { 99 | if (SEC_Address(sec) == (UINT32)mbi.BaseAddress) { 100 | stringify(ss, SEC_Name(sec)); 101 | break; 102 | } 103 | } 104 | } 105 | else { 106 | stringify(ss, IMG_Name(img)); 107 | } 108 | ss << "\""; 109 | } 110 | else 111 | ss << "\"\""; 112 | ss << "]" << endl; 113 | 114 | base += mbi.RegionSize; 115 | } 116 | 117 | *result = ss.str(); 118 | result->pop_back(); 119 | 120 | return has_map; 121 | } 122 | 123 | // credits: https://stackoverflow.com/questions/42711201/ 124 | static std::ostream& stringify(std::ostream& out, std::string const& s) { 125 | for each (char ch in s) 126 | { 127 | switch (ch) 128 | { 129 | case '\'': 130 | out << "\\'"; 131 | break; 132 | case '\"': 133 | out << "\\\""; 134 | break; 135 | case '\?': 136 | out << "\\?"; 137 | break; 138 | case '\\': 139 | out << "\\\\"; 140 | break; 141 | case '\a': 142 | out << "\\a"; 143 | break; 144 | case '\b': 145 | out << "\\b"; 146 | break; 147 | case '\f': 148 | out << "\\f"; 149 | break; 150 | case '\n': 151 | out << "\\n"; 152 | break; 153 | case '\r': 154 | out << "\\r"; 155 | break; 156 | case '\t': 157 | out << "\\t"; 158 | break; 159 | case '\v': 160 | out << "\\v"; 161 | break; 162 | default: 163 | out << ch; 164 | } 165 | } 166 | return out; 167 | } 168 | 169 | void OnImageLoad(IMG img) { 170 | if (IMG_IsMainExecutable(img)) return; // we only want to track Windows DLLs 171 | 172 | const char* imgName = IMG_Name(img).c_str(); 173 | char* data = strdup(imgName); 174 | size_t len = strlen(data) + 1; 175 | while (len--) data[len] = tolower(data[len]); 176 | 177 | if (strstr(data, "windows\\system32\\") || strstr(data, "windows\\syswow64\\") || 178 | strstr(data, "windows\\winsxs\\")) { 179 | ADDRINT imgStart = IMG_LowAddress(img); 180 | ADDRINT imgEnd = IMG_HighAddress(img); 181 | 182 | PIN_LockClient(); // rendundant? check AOT hooks 183 | State::globalState* gs = State::getGlobalState(); 184 | if (gs->dllRangeITree == NULL) { 185 | gs->dllRangeITree = itree_init(imgStart, imgEnd, (void*)data); 186 | } else { 187 | bool success = itree_insert(gs->dllRangeITree, imgStart, imgEnd, (void*)data); 188 | if (!success) { 189 | LOG_AR("Duplicate range insertion for DLL %s", data); 190 | fprintf(stderr, "==> Duplicate range insertion for DLL %s\n", data); 191 | } 192 | } 193 | PIN_UnlockClient(); 194 | // debugging 195 | //fprintf(stderr, "==> Added DLL %s with range %0x->%0x\n", data, imgStart, imgEnd); 196 | bool validIntervalTree = itree_verify(gs->dllRangeITree); 197 | if (!validIntervalTree) { 198 | itree_print(gs->dllRangeITree, 0); 199 | ASSERT(false, "Broken DLL interval tree"); 200 | } 201 | 202 | } 203 | else { 204 | free(data); 205 | return; 206 | } 207 | 208 | 209 | } 210 | 211 | void OnImageUnload(IMG img) { 212 | if (IMG_IsMainExecutable(img)) return; // only for clarity 213 | 214 | ADDRINT imgStart = IMG_LowAddress(img); 215 | ADDRINT imgEnd = IMG_HighAddress(img); 216 | PIN_LockClient(); 217 | State::globalState* gs = State::getGlobalState(); 218 | if (gs->dllRangeITree) { 219 | // oblivious delete 220 | gs->dllRangeITree = itree_delete(gs->dllRangeITree, imgStart, imgEnd); 221 | // debugging 222 | //fprintf(stderr, "==> Deleted DLL %s with range %0x->%0x\n", IMG_Name(img).c_str(), imgStart, imgEnd); 223 | bool validIntervalTree = itree_verify(gs->dllRangeITree); 224 | if (!validIntervalTree) { 225 | itree_print(gs->dllRangeITree, 0); 226 | ASSERT(false, "Broken DLL interval tree"); 227 | } 228 | } 229 | PIN_UnlockClient(); 230 | } 231 | 232 | VOID CheckRetAddrLibcall(ADDRINT* ESP) { 233 | State::globalState* gs = State::getGlobalState(); 234 | State::hookEntryArgsTLS* hookTls = State::getHookEntryTLSArgs(); 235 | itreenode_t* node = itree_search(gs->dllRangeITree, *ESP); 236 | hookTls->retAddrInDLL = (node) ? true : false; 237 | hookTls->retAddrInDll_data = (node) ? (const char*)node->data : (const char*)NULL; 238 | hookTls->retAddr = *ESP; 239 | } 240 | 241 | } 242 | -------------------------------------------------------------------------------- /pintool/src/libdft/libdft_api.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2010, 2011, 2012, 2013, Columbia University 3 | * All rights reserved. 4 | * 5 | * This software was developed by Vasileios P. Kemerlis 6 | * at Columbia University, New York, NY, USA, in June 2010. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * * Neither the name of Columbia University nor the 17 | * names of its contributors may be used to endorse or promote products 18 | * derived from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef LIBDFT_API_H 34 | #define LIBDFT_API_H 35 | 36 | #include 37 | #include 38 | 39 | #include "pin.H" 40 | #include "libdft_config.h" 41 | 42 | /* [originally from BluePill] => host a bunch of useful fields */ 43 | typedef struct { 44 | THREADID tid; 45 | OS_THREAD_ID os_tid; 46 | uint8_t tainted; 47 | const char* logname; 48 | // TODO more stuff 49 | } taint_thread_info; 50 | 51 | 52 | 53 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) 54 | #error "Your kernel is tool old and this version of libdft does not support it" 55 | #elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,26) 56 | #define SYSCALL_MAX __NR_timerfd_gettime+1 /* max syscall number */ 57 | #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && \ 58 | LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) 59 | #define SYSCALL_MAX __NR_inotify_init1+1 /* max syscall number */ 60 | #elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,30) 61 | #define SYSCALL_MAX __NR_pwritev+1 /* max syscall number */ 62 | #elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,31) 63 | #define SYSCALL_MAX __NR_perf_counter_open+1/* max syscall number */ 64 | #elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,32) 65 | #define SYSCALL_MAX __NR_perf_event_open+1 /* max syscall number */ 66 | #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) && \ 67 | LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) 68 | #define SYSCALL_MAX __NR_recvmmsg+1 /* max syscall number */ 69 | #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) && \ 70 | LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) 71 | #define SYSCALL_MAX __NR_prlimit64+1 /* max syscall number */ 72 | #else 73 | #define SYSCALL_MAX __NR_syncfs+1 /* max syscall number */ 74 | #endif 75 | 76 | #define GPR_NUM 8 /* general purpose registers */ 77 | 78 | /* FIXME: turn off the EFLAGS.AC bit by applying the corresponding mask */ 79 | #define CLEAR_EFLAGS_AC(eflags) ((eflags & 0xfffbffff)) 80 | 81 | 82 | enum { 83 | /* #define */ SYSCALL_ARG0 = 0, /* 1st argument in syscall */ 84 | /* #define */ SYSCALL_ARG1 = 1, /* 2nd argument in syscall */ 85 | /* #define */ SYSCALL_ARG2 = 2, /* 3rd argument in syscall */ 86 | /* #define */ SYSCALL_ARG3 = 3, /* 4th argument in syscall */ 87 | /* #define */ SYSCALL_ARG4 = 4, /* 5th argument in syscall */ 88 | /* #define */ SYSCALL_ARG5 = 5, /* 6th argument in syscall */ 89 | /* #define */ SYSCALL_ARG_NUM = 6 /* syscall arguments */ 90 | }; 91 | 92 | enum { /* {en,dis}able (ins_desc_t) */ 93 | /* #define */ INSDFL_ENABLE = 0, 94 | /* #define */ INSDFL_DISABLE = 1 95 | }; 96 | 97 | // NOTE: This uses the same mapping as the vcpu_ctx_t struct defined below! 98 | enum gpr {GPR_EDI, GPR_ESI, GPR_EBP, GPR_ESP, GPR_EBX, GPR_EDX, GPR_ECX, GPR_EAX, GPR_SCRATCH}; 99 | 100 | #ifdef USE_CUSTOM_TAG 101 | #define TAGS_PER_GPR 4 102 | 103 | // The gpr_reg_idx struct specifies an individual byte of a gpr reg. 104 | struct gpr_idx 105 | { 106 | gpr reg; 107 | uint8_t idx; 108 | }; 109 | 110 | inline gpr_idx get_gpr_idx(gpr reg, uint8_t idx) { 111 | gpr_idx g; 112 | g.reg = reg; 113 | g.idx = idx; 114 | return g; 115 | } 116 | #endif 117 | 118 | /* 119 | * virtual CPU (VCPU) context definition; 120 | * x86/x86_32/i386 arch 121 | */ 122 | typedef struct { 123 | /* 124 | * general purpose registers (GPRs) 125 | * 126 | * we assign one bit of tag information for 127 | * for every byte of addressable memory; the 32-bit 128 | * GPRs of the x86 architecture will be represented 129 | * with 4 bits each (the lower 4 bits of a 32-bit 130 | * unsigned integer) 131 | * 132 | * NOTE the mapping: 133 | * 0: EDI 134 | * 1: ESI 135 | * 2: EBP 136 | * 3: ESP 137 | * 4: EBX 138 | * 5: EDX 139 | * 6: ECX 140 | * 7: EAX 141 | * 8: scratch (not a real register; helper) 142 | */ 143 | #ifdef USE_CUSTOM_TAG 144 | tag_t gpr[GPR_NUM + 1][TAGS_PER_GPR]; 145 | #else 146 | uint32_t gpr[GPR_NUM + 1]; 147 | #endif 148 | } vcpu_ctx_t; 149 | 150 | /* 151 | * system call context definition 152 | * 153 | * only up to SYSCALL_ARGS (i.e., 6) are saved 154 | */ 155 | typedef struct { 156 | int nr; /* syscall number */ 157 | ADDRINT arg[SYSCALL_ARG_NUM]; /* arguments */ 158 | ADDRINT ret; /* return value */ 159 | void *aux; /* auxiliary data (processor state) */ 160 | /* ADDRINT errno; */ /* error code */ 161 | } syscall_ctx_t; 162 | 163 | /* thread context definition */ 164 | typedef struct { 165 | vcpu_ctx_t vcpu; /* VCPU context */ 166 | syscall_ctx_t syscall_ctx; /* syscall context */ 167 | void *uval; /* local storage */ 168 | taint_thread_info ttinfo; /* DCD */ 169 | } thread_ctx_t; 170 | 171 | /* instruction (ins) descriptor */ 172 | typedef struct { 173 | void (* pre)(INS ins); /* pre-ins instrumentation callback */ 174 | void (* post)(INS ins); /* post-ins instrumentation callback */ 175 | size_t dflact; /* default instrumentation predicate */ 176 | } ins_desc_t; 177 | 178 | 179 | /* libdft API */ 180 | int libdft_init(ADDRINT version_mask = 0); 181 | void libdft_die(void); 182 | 183 | /* integration with DBI Blue Pill */ 184 | int libdft_init_data_only(); 185 | thread_ctx_t* libdft_thread_start(CONTEXT *ctx); 186 | void libdft_thread_fini(const CONTEXT *ctx); 187 | void libdft_trace_inspect(TRACE trace, VOID *v); 188 | EXCEPT_HANDLING_RESULT libdft_fix_eflags(THREADID tid, EXCEPTION_INFO *pExceptInfo, PHYSICAL_CONTEXT *pPhysCtxt, VOID *v); 189 | 190 | /* ins API */ 191 | int ins_set_pre(ins_desc_t*, void (*)(INS)); // TODO not in original code - leftover? 192 | int ins_clr_pre(ins_desc_t*); 193 | int ins_set_post(ins_desc_t*, void (*)(INS)); // TODO not in original code - leftover? 194 | int ins_clr_post(ins_desc_t*); 195 | int ins_set_dflact(ins_desc_t *desc, size_t action); 196 | 197 | /* REG API */ 198 | size_t REG32_INDX(REG); 199 | size_t REG16_INDX(REG); 200 | size_t REG8_INDX(REG); 201 | 202 | #endif /* LIBDFT_API_H */ 203 | -------------------------------------------------------------------------------- /pintool/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "pin.H" 2 | #include 3 | 4 | #include "config.h" 5 | #include "memory.h" 6 | #include "syshooking.h" 7 | #include "fpu.h" 8 | #include "context.h" 9 | #include "logging.h" 10 | #include "ins.h" 11 | #include "exceptionHandler.h" 12 | #include "functions.h" 13 | #include "state.h" 14 | #include "process.h" 15 | #include "wmi.h" 16 | 17 | // libdft 18 | #include "libdft/libdft_config.h" 19 | #include "libdft/bridge.h" 20 | #include "libdft/libdft_api.h" 21 | #include "libdft/tagmap.h" 22 | 23 | using namespace std; 24 | 25 | 26 | TLS_KEY tls_key = INVALID_TLS_KEY; 27 | 28 | #if !FIXED_KNOBS 29 | BOOL _nxKnob; 30 | BOOL _paranoidKnob; 31 | BOOL _rwKnob; 32 | BOOL _leakKnob; 33 | BOOL _libdftKnob; 34 | BOOL _evasions; 35 | BOOL _debugger; 36 | #endif 37 | 38 | // knobs for BluePill 39 | KNOB KnobEvasions(KNOB_MODE_WRITEONCE, "pintool", 40 | "evasions", "false", "enable observe-check-replace hooks"); 41 | KNOB KnobDebugger(KNOB_MODE_WRITEONCE, "pintool", 42 | "debugger", "false", "enable debugging"); 43 | 44 | // knobs from SoK DBI anti-evasion 45 | KNOB KnobNX(KNOB_MODE_WRITEONCE, "pintool", 46 | "nx", "false", "enable nx protection"); 47 | KNOB KnobParanoid(KNOB_MODE_WRITEONCE, "pintool", 48 | "paranoid", "false", "enable nx full protection"); 49 | KNOB KnobRW(KNOB_MODE_WRITEONCE, "pintool", 50 | "read_write", "false", "enable read/write protection"); 51 | KNOB KnobLeak(KNOB_MODE_WRITEONCE, "pintool", 52 | "leak", "false", "enable fpu context protection"); 53 | 54 | // knobs for libdft 55 | KNOB KnobLibdft(KNOB_MODE_WRITEONCE, "pintool", 56 | "libdft", "false", "setup libdft"); 57 | 58 | // very useful help message 59 | INT32 Usage() { 60 | cout << "Hi there :-) Have fun with BluePill!\n" << endl; 61 | 62 | cout << KNOB_BASE::StringKnobSummary() << endl; 63 | 64 | return -1; 65 | } 66 | 67 | // custom commands that we define over GDB remote server protocol 68 | // -> attach-detach feature to get around problems in exception handling 69 | // -> transfer memory map information missing in GDB 70 | // -> add/remove (stealth) code patches 71 | static BOOL DebugInterpreter(THREADID tid, CONTEXT *ctxt, const string &cmd, string *result, VOID *) { 72 | std::cout << "GDB Command: " << cmd << std::endl; 73 | 74 | if (cmd.compare("wait") == 0) { 75 | //ProcInfo* gs = ProcInfo::getInstance(); 76 | FetchGlobalState; 77 | gs->waitForDebugger = TRUE; 78 | *result = "Pin will wait debugger after exception..."; 79 | return TRUE; 80 | } 81 | else if (cmd.compare("vmmap") == 0) { 82 | return Process::VMMap(result); 83 | } 84 | else if (cmd.find("set") != string::npos) { 85 | return INS_EnableInsStealth(cmd, result); 86 | } 87 | else if (cmd.find("rm") != string::npos) { 88 | return INS_DisableInsStealth(cmd, result); 89 | } 90 | // [...] 91 | *result = "Command not found!"; 92 | return TRUE; // Unknown command 93 | 94 | } 95 | 96 | VOID PINTOOL_Config() { 97 | 98 | Logging::LOGGING_Init(); 99 | 100 | // obtain a TLS key 101 | tls_key = PIN_CreateThreadDataKey(NULL); 102 | if (tls_key == INVALID_TLS_KEY) { 103 | LOG_AR("Cannot initialize TLS"); 104 | PIN_ExitProcess(1); 105 | } 106 | 107 | #if !FIXED_KNOBS 108 | _leakKnob = KnobLeak.Value(); 109 | _rwKnob = KnobRW.Value(); 110 | _nxKnob = KnobNX.Value(); 111 | _paranoidKnob = KnobParanoid.Value(); 112 | _libdftKnob = KnobLibdft.Value(); 113 | _evasions = KnobEvasions.Value(); 114 | _debugger = KnobDebugger.Value(); 115 | #endif 116 | 117 | } 118 | 119 | VOID FiniCallback(INT32 code, VOID *v) { 120 | //Logging::LOGGING_Shutdown(); 121 | } 122 | 123 | VOID OnThreadStart(THREADID tid, CONTEXT *ctxt, INT32, VOID *) { 124 | // TLS handling 125 | SYSHOOKING::SetTLSKey(tid); 126 | 127 | // [SoK DBI evasions] Map memory associated with new thread 128 | MEMORY_OnThreadStart(ctxt); 129 | 130 | //libdft 131 | if (_libdftKnob) { 132 | thread_ctx_t *thread_ctx = libdft_thread_start(ctxt); 133 | #define TTINFO(field) thread_ctx->ttinfo.field 134 | TTINFO(tid) = tid; 135 | TTINFO(os_tid) = PIN_GetTid(); 136 | char tmp[32]; 137 | sprintf(tmp, "tainted-%u.log", TTINFO(os_tid)); 138 | TTINFO(logname) = strdup(tmp); 139 | #undef TTINFO 140 | } 141 | } 142 | 143 | VOID OnThreadFini(THREADID tid, const CONTEXT *ctxt, INT32, VOID *) { 144 | if (_libdftKnob) 145 | libdft_thread_fini(ctxt); 146 | } 147 | 148 | // Instruction instrumentation 149 | VOID Instruction(INS ins, VOID *v) { 150 | if (_debugger) // stealth code patching 151 | INS_AddInsStealth(ins); 152 | 153 | if (_rwKnob || _nxKnob) // [SoK DBI evasions] 154 | MEMORY_InstrumentINS(ins); 155 | if (_leakKnob) // [SoK DBI evasions] 156 | FPU_InstrumentINS(ins); 157 | 158 | if (_evasions) // BluePill low-level hooks 159 | INS_InstrumentINS(ins); 160 | 161 | //if (_libdftKnob) instrumentForTaintCheck(ins, NULL); 162 | } 163 | 164 | // AOT instrumentation 165 | VOID Image(IMG img, VOID* v) { 166 | if (_rwKnob || _nxKnob) { // [SoK DBI evasions] 167 | MEMORY_LoadImage(img); 168 | } 169 | Process::OnImageLoad(img); 170 | Functions::AddHooks(img); // BluePill API hooks 171 | } 172 | 173 | VOID ImageUnload(IMG img, VOID* v) { 174 | if (_rwKnob || _nxKnob) { // [SoK DBI evasions] 175 | MEMORY_UnloadImage(img); 176 | } 177 | Process::OnImageUnload(img); 178 | } 179 | 180 | 181 | /******************** 182 | STUFF FOR DEBUGGING 183 | ********************/ 184 | VOID KKTM2() { // debug specific function 185 | cout << "[CIAO]" << endl; 186 | } 187 | 188 | VOID KKTM(const char* str) { // trivial logger for API calls 189 | cout << str << endl; 190 | } 191 | 192 | // for debugging purposes (default: unregistered) 193 | static VOID InstrumentRoutine(RTN rtn, VOID *) { 194 | #if 1 195 | const char* rtnName = RTN_Name(rtn).c_str(); 196 | 197 | RTN_Open(rtn); 198 | RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)KKTM, IARG_ADDRINT, rtnName, IARG_END); 199 | RTN_Close(rtn); 200 | 201 | #endif 202 | #if 0 203 | if (RTN_Name(rtn).find("ExecQuery") != string::npos) { 204 | RTN_Open(rtn); 205 | RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)KKTM2, IARG_END); 206 | RTN_Close(rtn); 207 | } 208 | #endif 209 | } 210 | /**** END OF STUFF FOR DEBUGGING ***/ 211 | 212 | int main(int argc, char *argv[]) { 213 | 214 | PIN_InitSymbols(); 215 | if (PIN_Init(argc, argv)) { 216 | return Usage(); 217 | } 218 | 219 | // check Wow64 information 220 | W::BOOL bWow64; 221 | W::IsWow64Process((W::HANDLE)(-1), &bWow64); 222 | Process::isWow64 = (bWow64 != 0); 223 | 224 | // initialize some stuff 225 | PINTOOL_Config(); 226 | Functions::Init(); 227 | 228 | // set up elements to be hidden 229 | HiddenElements::initializeHiddenStuff(); 230 | 231 | if (_rwKnob || _nxKnob) { 232 | MEMORY_Init(); 233 | } 234 | 235 | if (_leakKnob) { 236 | FPU_Init(); 237 | } 238 | 239 | // syscall instrumentation: PIN_AddSyscallEntryFunction, PIN_AddSyscallExitFunction 240 | SYSHOOKING::Init(); 241 | 242 | // INS instrumentation 243 | INS_AddInstrumentFunction(Instruction, NULL); 244 | 245 | // AOT instrumentation (IMG) 246 | IMG_AddInstrumentFunction(Image, NULL); 247 | IMG_AddUnloadFunction(ImageUnload, NULL); 248 | 249 | // process PEB 250 | Process::patchPEB(); 251 | 252 | // exceptional control flow (see context.cpp) 253 | PIN_AddContextChangeFunction(CONTEXT_ChangeContext, NULL); 254 | PIN_AddInternalExceptionHandler(CONTEXT_InternalExceptionHandler, NULL); 255 | 256 | // events 257 | PIN_AddThreadStartFunction(OnThreadStart, NULL); 258 | PIN_AddThreadFiniFunction(OnThreadFini, NULL); 259 | 260 | // libdft initialization 261 | if (_libdftKnob) { 262 | if (libdft_init_data_only()) { 263 | LOG_AR("Error initializing libdft"); 264 | exit(1); 265 | } 266 | TRACE_AddInstrumentFunction(libdft_trace_inspect, NULL); 267 | //INS_AddInstrumentFunction(instrumentForTaintCheck, NULL); 268 | } 269 | 270 | // debugger 271 | if (_debugger) { 272 | PIN_AddDebugInterpreter(DebugInterpreter, nullptr); 273 | // TODO merge GUI thread here when we release that component 274 | } 275 | 276 | // routine instrumentation (for debugging only) 277 | //RTN_AddInstrumentFunction(InstrumentRoutine, NULL); 278 | 279 | // process exit callback 280 | PIN_AddFiniFunction(FiniCallback, NULL); 281 | 282 | PIN_StartProgram(); 283 | return 0; 284 | } 285 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /pintool/src/libdft/bridge.cpp: -------------------------------------------------------------------------------- 1 | #include "pin.H" 2 | 3 | #include 4 | 5 | #include "libdft_api.h" 6 | #include "tagmap.h" 7 | #include "bridge.h" // also for thread_ctx_ptr 8 | 9 | // DCD: assert_* methods have been borrowed from libdft-dta.c 10 | 11 | #define TTINFO(field) thread_ctx->ttinfo.field 12 | 13 | // borrowed from libdft_core.cpp 14 | #define RTAG thread_ctx->vcpu.gpr 15 | #define R32TAG(RIDX) \ 16 | {RTAG[(RIDX)][0], RTAG[(RIDX)][1], RTAG[(RIDX)][2], RTAG[(RIDX)][3]} 17 | 18 | //thread_ctx_t *thread_ctx = (thread_ctx_t *) PIN_GetContextReg(ctx, thread_ctx_ptr); 19 | void addTaintRegister(thread_ctx_t *thread_ctx, int gpr, tag_t tags[], bool reset) { 20 | tag_t src_tag[] = R32TAG(gpr); 21 | for (UINT32 i = 0; i < 4; ++i) { 22 | tag_t t = tags[i]; 23 | if (!reset) t |= src_tag[i]; 24 | RTAG[gpr][i] = t; 25 | } 26 | } 27 | 28 | void clearTaintRegister(thread_ctx_t *thread_ctx, int gpr) { 29 | memset(RTAG[gpr], 0, sizeof(RTAG[gpr])); 30 | } 31 | 32 | void getRegisterTaints(thread_ctx_t *thread_ctx, int gpr, tag_t *tags) { 33 | memcpy(tags, RTAG[gpr], sizeof(RTAG[gpr])); 34 | } 35 | 36 | void getMemoryTaints(ADDRINT addr, tag_t* tags, UINT32 size) { 37 | for (UINT32 i = 0; i < size; ++i) { 38 | tags[i] = tagmap_getb(addr + i); 39 | } 40 | } 41 | 42 | void addTaintMemory(ADDRINT addr, UINT32 size, tag_t tag, bool reset) { 43 | ASSERT(sizeof(ADDRINT) == sizeof(UINT32), "64-bit mode not supported yet"); 44 | std::cerr << "Tainting addresses " << addr << " to " << addr + size << std::endl; 45 | for (UINT32 i = 0; i < size; ++i) { 46 | tag_t t = tag; 47 | if (!reset) t |= tagmap_getb(addr + i); 48 | tagmap_setb_with_tag(addr + i, t); 49 | } 50 | 51 | //tag_t x = tagmap_getl(addr); // TODO check why we have this leftover 52 | } 53 | 54 | void clearTaintMemory(ADDRINT addr, UINT32 size) { 55 | ASSERT(sizeof(ADDRINT) == sizeof(UINT32), "64-bit mode not supported yet"); 56 | for (UINT32 i = 0; i < size; ++i) { 57 | tag_t t = 0; 58 | tagmap_setb_with_tag(addr + i, t); 59 | } 60 | } 61 | 62 | /* 63 | * DTA/DFT alert 64 | * 65 | * @ins: address of the offending instruction 66 | * @bt: address of the branch target 67 | */ 68 | static void PIN_FAST_ANALYSIS_CALL alert(thread_ctx_t *thread_ctx, ADDRINT addr, INS i) { 69 | /* log file */ 70 | if (TTINFO(tainted)) { 71 | #if 0 72 | if (Process::getInstance()->isInsideMainIMG(addr)) goto END; 73 | char buf[512]; 74 | sprintf(buf, "Tainted instruction: 0x%08x [%d] %s\n", 75 | addr, (int)TTINFO(tainted), INS_Disassemble(i).c_str()); 76 | //fprintf(stderr, "%s", buf); 77 | FILE *logFile = fopen(TTINFO(logname), "a"); 78 | if (logFile) { 79 | fprintf(logFile, "%s", buf); 80 | fclose(logFile); 81 | } 82 | } 83 | END: 84 | #else 85 | } 86 | #endif 87 | TTINFO(tainted) = 0; 88 | } 89 | 90 | static void PIN_FAST_ANALYSIS_CALL 91 | assert_reg32(thread_ctx_t *thread_ctx, UINT32 reg) { 92 | // DCD we use uint8_t as LIBDFT_TAG_TYPE 93 | TTINFO(tainted) |= thread_ctx->vcpu.gpr[reg][0] | 94 | thread_ctx->vcpu.gpr[reg][1] | 95 | thread_ctx->vcpu.gpr[reg][2] | 96 | thread_ctx->vcpu.gpr[reg][3]; 97 | //std::cerr << "REG32" << std::endl; 98 | } 99 | 100 | static void PIN_FAST_ANALYSIS_CALL 101 | assert_reg16(thread_ctx_t *thread_ctx, UINT32 reg) { 102 | // DCD we use uint8_t as LIBDFT_TAG_TYPE 103 | TTINFO(tainted) |= thread_ctx->vcpu.gpr[reg][0] | 104 | thread_ctx->vcpu.gpr[reg][1]; 105 | //std::cerr << "REG16" << std::endl; 106 | } 107 | 108 | static void PIN_FAST_ANALYSIS_CALL 109 | assert_reg8(thread_ctx_t *thread_ctx, UINT32 reg) { // DCD TODO 110 | // DCD we use uint8_t as LIBDFT_TAG_TYPE 111 | TTINFO(tainted) |= thread_ctx->vcpu.gpr[reg][0]; 112 | //std::cerr << "REG8" << std::endl; 113 | } 114 | 115 | static void PIN_FAST_ANALYSIS_CALL 116 | assert_mem256(thread_ctx_t *thread_ctx, UINT32 addr) { 117 | TTINFO(tainted) |= tagmap_getl(addr) | tagmap_getl(addr + 4) | 118 | tagmap_getl(addr + 8) | tagmap_getl(addr + 12) | 119 | tagmap_getl(addr + 16) | tagmap_getl(addr + 20) | 120 | tagmap_getl(addr + 24) | tagmap_getl(addr + 28); 121 | //std::cerr << "MEM256" << std::endl; 122 | } 123 | 124 | static void PIN_FAST_ANALYSIS_CALL 125 | assert_mem128(thread_ctx_t *thread_ctx, UINT32 addr) { 126 | TTINFO(tainted) |= tagmap_getl(addr) | tagmap_getl(addr + 4) | 127 | tagmap_getl(addr + 8) | tagmap_getl(addr + 12); 128 | //std::cerr << "MEM128" << std::endl; 129 | } 130 | 131 | static void PIN_FAST_ANALYSIS_CALL 132 | assert_mem64(thread_ctx_t *thread_ctx, UINT32 addr) { 133 | TTINFO(tainted) |= tagmap_getl(addr) | tagmap_getl(addr + 4); 134 | //std::cerr << "MEM64" << std::endl; 135 | } 136 | 137 | static void PIN_FAST_ANALYSIS_CALL 138 | assert_mem32(thread_ctx_t *thread_ctx, UINT32 addr) { 139 | TTINFO(tainted) |= tagmap_getl(addr); 140 | //std::cerr << "MEM32" << std::endl; 141 | } 142 | 143 | static void PIN_FAST_ANALYSIS_CALL 144 | assert_mem16(thread_ctx_t *thread_ctx, UINT32 addr) { 145 | TTINFO(tainted) |= tagmap_getw(addr); 146 | //std::cerr << "MEM16" << std::endl; 147 | } 148 | 149 | static void PIN_FAST_ANALYSIS_CALL 150 | assert_mem8(thread_ctx_t *thread_ctx, UINT32 addr) { 151 | TTINFO(tainted) |= tagmap_getb(addr); 152 | //std::cerr << "MEM8" << std::endl; 153 | } 154 | 155 | static void PIN_FAST_ANALYSIS_CALL 156 | assert_mem_generic(thread_ctx_t *thread_ctx, UINT32 addr, UINT32 size) { 157 | ASSERT(size % 4 == 0, "Unaligned memory access?"); 158 | for (UINT32 i = 0; i < size / 4; i++) 159 | TTINFO(tainted) |= tagmap_getl(addr + 4 * i); 160 | //std::cerr << "MEM" << size*8 << std::endl; 161 | } 162 | 163 | void instrumentForTaintCheck(INS ins, void*) { 164 | if (INS_MaxNumRRegs(ins) == 0) return; // the instruction does not have read operands 165 | 166 | UINT32 operands = INS_OperandCount(ins); 167 | 168 | // iterate over registers 169 | for (UINT32 opIdx = 0; opIdx < operands; ++opIdx) { 170 | if (INS_OperandIsReg(ins, opIdx) && INS_OperandRead(ins, opIdx)) { 171 | REG reg = INS_OperandReg(ins, opIdx); 172 | if (REG_is_gr32(reg)) { 173 | INS_InsertCall(ins, 174 | IPOINT_BEFORE, 175 | (AFUNPTR)assert_reg32, 176 | IARG_FAST_ANALYSIS_CALL, 177 | IARG_REG_VALUE, 178 | thread_ctx_ptr, 179 | IARG_UINT32, 180 | REG32_INDX(reg), 181 | IARG_END); 182 | } 183 | else if (REG_is_gr16(reg)) { 184 | INS_InsertCall(ins, 185 | IPOINT_BEFORE, 186 | (AFUNPTR)assert_reg16, 187 | IARG_FAST_ANALYSIS_CALL, 188 | IARG_REG_VALUE, 189 | thread_ctx_ptr, 190 | IARG_UINT32, 191 | REG16_INDX(reg), 192 | IARG_END); 193 | } 194 | else if (REG_is_gr8(reg)) { 195 | // DCD what about this? no sign of it in libdft-dta 196 | INS_InsertCall(ins, 197 | IPOINT_BEFORE, 198 | (AFUNPTR)assert_reg8, 199 | IARG_FAST_ANALYSIS_CALL, 200 | IARG_REG_VALUE, 201 | thread_ctx_ptr, 202 | IARG_UINT32, 203 | REG8_INDX(reg), 204 | IARG_END); 205 | } 206 | } 207 | } 208 | 209 | if (!INS_IsMemoryRead(ins)) goto end; 210 | 211 | UINT32 memOperands = INS_MemoryOperandCount(ins); 212 | for (UINT32 memOpIdx = 0; memOpIdx < memOperands; memOpIdx++) { 213 | if (INS_MemoryOperandIsRead(ins, memOpIdx)) { 214 | USIZE opSize = INS_MemoryOperandSize(ins, memOpIdx); 215 | AFUNPTR assert_mem = NULL; 216 | switch (opSize) { 217 | case 32: 218 | assert_mem = (AFUNPTR)assert_mem256; 219 | break; 220 | case 16: 221 | assert_mem = (AFUNPTR)assert_mem128; 222 | break; 223 | case 8: 224 | assert_mem = (AFUNPTR)assert_mem64; 225 | break; 226 | case 4: 227 | assert_mem = (AFUNPTR)assert_mem32; 228 | break; 229 | case 2: 230 | assert_mem = (AFUNPTR)assert_mem16; 231 | break; 232 | case 1: 233 | assert_mem = (AFUNPTR)assert_mem8; 234 | break; 235 | default: 236 | std::cerr << "Unknown memory read size: " << opSize << std::endl; 237 | } 238 | if (assert_mem != NULL) { 239 | INS_InsertCall(ins, 240 | IPOINT_BEFORE, 241 | (AFUNPTR)assert_mem, 242 | IARG_FAST_ANALYSIS_CALL, 243 | IARG_REG_VALUE, 244 | thread_ctx_ptr, 245 | IARG_MEMORYOP_EA, 246 | memOpIdx, 247 | IARG_END); 248 | } 249 | else { 250 | INS_InsertCall(ins, 251 | IPOINT_BEFORE, 252 | (AFUNPTR)assert_mem_generic, 253 | IARG_FAST_ANALYSIS_CALL, 254 | IARG_REG_VALUE, 255 | thread_ctx_ptr, 256 | IARG_MEMORYOP_EA, 257 | memOpIdx, 258 | IARG_UINT32, 259 | opSize, 260 | IARG_END); 261 | } 262 | } 263 | } 264 | 265 | end: 266 | // check taint before the instruction is executed 267 | // TODO: it would be cool to have just one InsertIfCall and use an InsertThenCall here 268 | INS_InsertCall(ins, 269 | IPOINT_BEFORE, 270 | (AFUNPTR)alert, 271 | IARG_FAST_ANALYSIS_CALL, 272 | IARG_REG_VALUE, 273 | thread_ctx_ptr, 274 | IARG_INST_PTR, 275 | IARG_PTR, 276 | ins, 277 | IARG_END); 278 | return; 279 | } 280 | -------------------------------------------------------------------------------- /pintool/src/ins.cpp: -------------------------------------------------------------------------------- 1 | #include "ins.h" 2 | #include "winheaders.h" 3 | #include "process.h" 4 | 5 | using namespace std; 6 | 7 | static map patch_map; 8 | 9 | // helpers 10 | VOID regInit(REGSET* regsIn, REGSET* regsOut); 11 | 12 | VOID INS_InstrumentINS(INS ins) { 13 | static int insCount = 0; // NOTE was in a global state, but we only use it here 14 | 15 | /* raise exception at second istruction after real trap */ 16 | ExceptionHandler *eh = ExceptionHandler::getInstance(); 17 | if (eh->isPendingException()) { 18 | //ProcInfo *pc = ProcInfo::getInstance(); 19 | if (insCount == 0) 20 | insCount++; 21 | else { 22 | insCount = 0; 23 | INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ExceptionHandler::executeExceptionIns, IARG_CONTEXT, 24 | IARG_THREAD_ID, IARG_ADDRINT, INS_Address(ins), IARG_END); 25 | return; 26 | } 27 | } 28 | 29 | // TODO register some callback for when the debugger reattaches 30 | if (_debugger && (PIN_GetDebugStatus() != DEBUG_STATUS_UNCONNECTABLE)) { 31 | //ProcInfo *gs = ProcInfo::getInstance(); 32 | FetchGlobalState; 33 | if (gs->flagStep < 2) {//TODO && pc->isInsideMainIMG(INS_Address(ins))) 34 | gs->flagStep = gs->flagStep + 1; 35 | if (gs->flagStep == 1) {} 36 | else { 37 | // FIX PEB for debugging flags 38 | Process::patchPEB(); 39 | } 40 | } 41 | } 42 | 43 | string cat = INS_Disassemble(ins); 44 | 45 | REGSET regsIn; 46 | REGSET regsOut; 47 | 48 | if (cat.find("cpuid") != string::npos) { 49 | 50 | regInit(®sIn, ®sOut); 51 | ADDRINT curEip = INS_Address(ins); 52 | 53 | INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)INS_patchCpuid_entry, 54 | IARG_INST_PTR, 55 | IARG_PARTIAL_CONTEXT, ®sIn, ®sOut, 56 | IARG_ADDRINT, curEip, 57 | IARG_END); 58 | INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)INS_patchCpuid_exit, 59 | IARG_INST_PTR, 60 | IARG_PARTIAL_CONTEXT, ®sIn, ®sOut, 61 | IARG_ADDRINT, curEip, 62 | IARG_END); 63 | 64 | } 65 | else if (cat.find("rdtsc") != string::npos) { 66 | 67 | regInit(®sIn, ®sOut); 68 | ADDRINT curEip = INS_Address(ins); 69 | 70 | INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)INS_patchRtdsc_exit, 71 | IARG_INST_PTR, 72 | IARG_PARTIAL_CONTEXT, ®sIn, ®sOut, 73 | IARG_ADDRINT, curEip, 74 | IARG_END); 75 | 76 | } 77 | else if (cat.find("int 0x2d") != string::npos) { 78 | 79 | ADDRINT curEip = INS_Address(ins); 80 | 81 | INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)INS_patchInt2d_entry, 82 | IARG_END); 83 | 84 | } 85 | else if (cat.find("in eax, dx") != string::npos) { 86 | 87 | regInit(®sIn, ®sOut); 88 | ADDRINT curEip = INS_Address(ins); 89 | 90 | INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)INS_patchIn_exit, 91 | IARG_PARTIAL_CONTEXT, ®sIn, ®sOut, 92 | IARG_END); 93 | 94 | } 95 | else if (cat.find("sti") != string::npos) { 96 | if (_debugger) { 97 | INS_Delete(ins); 98 | } 99 | } 100 | 101 | } 102 | 103 | VOID INS_patchRtdsc_exit(ADDRINT ip, CONTEXT * ctxt, ADDRINT cur_eip) { 104 | 105 | ACTIVE_HOOK(EN_rdtsc); 106 | 107 | // TODO add check on memory range for instruction? 108 | 109 | FetchTimeState; 110 | 111 | tinfo->_edx = (tinfo->_edx_eax & 0xffffffff00000000ULL) >> 32; // most significant 32 112 | tinfo->_edx_eax += tinfo->sleepMs; //add to result ms of previous sleep call 113 | tinfo->_eax = tinfo->_edx_eax & 0x00000000ffffffffULL; // less significant 32 114 | tinfo->_edx_eax += 30; 115 | tinfo->sleepMs = 0; 116 | 117 | PIN_SetContextReg(ctxt, REG_GAX, tinfo->_eax); 118 | PIN_SetContextReg(ctxt, REG_GDX, tinfo->_edx); 119 | 120 | } 121 | 122 | VOID INS_patchCpuid_entry(ADDRINT ip, CONTEXT * ctxt, ADDRINT cur_eip) { 123 | 124 | ACTIVE_HOOK(EN_cpuid); 125 | 126 | FetchHookTLS; 127 | 128 | ADDRINT _eax; 129 | PIN_GetContextRegval(ctxt, REG_GAX, reinterpret_cast(&_eax)); 130 | in->cpuid_eax = _eax; 131 | 132 | } 133 | 134 | VOID INS_patchCpuid_exit(ADDRINT ip, CONTEXT * ctxt, ADDRINT cur_eip) { 135 | 136 | ACTIVE_HOOK(EN_cpuid); 137 | 138 | FetchHookTLS; 139 | 140 | ADDRINT _ebx, _ecx, _edx; 141 | PIN_GetContextRegval(ctxt, REG_GDX, reinterpret_cast(&_edx)); 142 | PIN_GetContextRegval(ctxt, REG_GBX, reinterpret_cast(&_ebx)); 143 | PIN_GetContextRegval(ctxt, REG_GCX, reinterpret_cast(&_ecx)); 144 | 145 | if (in->cpuid_eax == 1) { 146 | // TODO add check on memory range for instruction? 147 | UINT32 mask = 0xFFFFFFFFULL; 148 | _ecx &= (mask >> 1); 149 | } 150 | else if (in->cpuid_eax >= 0x40000000 && in->cpuid_eax <= 0x400000FF) { 151 | LOG_AR("[CPUID] - 0x4"); 152 | _ecx = 0x0ULL; 153 | _ebx = 0x0ULL; 154 | _edx = 0x0ULL; 155 | } 156 | 157 | PIN_SetContextReg(ctxt, REG_GCX, _ecx); 158 | PIN_SetContextReg(ctxt, REG_GBX, _ebx); 159 | PIN_SetContextReg(ctxt, REG_GDX, _edx); 160 | 161 | } 162 | 163 | VOID INS_patchInt2d_entry(CONTEXT * ctx, THREADID tid, ADDRINT accessAddr) { 164 | 165 | ACTIVE_HOOK(EN_int0x2d); 166 | 167 | LOG_AR("[INT 2D] - int 2d"); 168 | 169 | // insert exception on int 2d 170 | ExceptionHandler *eh = ExceptionHandler::getInstance(); 171 | eh->setExceptionToExecute(NTSTATUS_STATUS_BREAKPOINT); 172 | 173 | } 174 | 175 | VOID INS_patchIn_exit(CONTEXT * ctx) { 176 | 177 | ACTIVE_HOOK(EN_in); 178 | 179 | LOG_AR("[IN eax, dx] - vmware magic number"); 180 | 181 | ADDRINT _ebx = 0; 182 | PIN_SetContextReg(ctx, REG_GBX, _ebx); 183 | 184 | } 185 | 186 | static VOID regInit(REGSET* regsIn, REGSET* regsOut) { 187 | REGSET_AddAll(*regsIn); 188 | REGSET_Clear(*regsOut); 189 | REGSET_Insert(*regsOut, REG_GAX); 190 | REGSET_Insert(*regsOut, REG_GBX); 191 | REGSET_Insert(*regsOut, REG_GDX); 192 | REGSET_Insert(*regsOut, REG_GCX); 193 | } 194 | 195 | /*** STEALTH CODE PATCHING ***/ 196 | 197 | BOOL INS_DisableInsStealth(string input, string *result) { 198 | 199 | string delimiter_addr = "_"; 200 | string token; 201 | size_t pos = 0; 202 | size_t count_addr = 0; 203 | 204 | ADDRINT start_addr, end_addr; 205 | 206 | while ((pos = input.find(delimiter_addr)) != string::npos) { 207 | token = input.substr(0, pos); 208 | if (count_addr == 1) { 209 | UINT32 tmp = strtol(token.c_str(), NULL, 16); 210 | start_addr = tmp; 211 | } 212 | count_addr++; 213 | input.erase(0, pos + delimiter_addr.length()); 214 | } 215 | UINT32 tmp = strtol(input.c_str(), NULL, 16); 216 | end_addr = tmp; 217 | 218 | for (UINT32 i = start_addr; i < end_addr; i++) { 219 | patch_map.erase(i); 220 | } 221 | 222 | PIN_RemoveInstrumentationInRange(start_addr, end_addr); 223 | 224 | *result = "OK"; 225 | return TRUE; 226 | 227 | } 228 | 229 | BOOL INS_EnableInsStealth(string input, string *result) { 230 | 231 | patch_struct *ps = (patch_struct*)malloc(sizeof(patch_struct)); 232 | 233 | string delimiter_addr = "_"; 234 | string delimiter_patch = ","; 235 | size_t pos = 0; 236 | string token; 237 | size_t count_addr = 0; 238 | size_t count_patch = 0; 239 | 240 | /* STRING HELPER: INIT_ADDR:END_ADDR:RET_ADDR:PATCH_CODE */ 241 | /* STRING EXAMPLE: set_40108F_401095_401098_83,e9,01 */ 242 | 243 | /* ADDRESSES LOOP */ 244 | while ((pos = input.find(delimiter_addr)) != string::npos) { 245 | token = input.substr(0, pos); 246 | if (count_addr == 1) { 247 | UINT32 tmp = strtol(token.c_str(), NULL, 16); 248 | ps->start = tmp; 249 | } 250 | else if (count_addr == 2) { 251 | UINT32 tmp = strtol(token.c_str(), NULL, 16); 252 | ps->fin = tmp; 253 | } 254 | else if (count_addr == 3) { 255 | UINT32 tmp = strtol(token.c_str(), NULL, 16); 256 | ps->ret = tmp; 257 | } 258 | count_addr++; 259 | input.erase(0, pos + delimiter_addr.length()); 260 | } 261 | 262 | /* PATCH LOOP */ 263 | while ((pos = input.find(delimiter_patch)) != string::npos) { 264 | token = input.substr(0, pos); 265 | 266 | UINT32 tmp = strtol(token.c_str(), NULL, 16); 267 | ps->patch[count_patch] = (unsigned char)tmp; 268 | 269 | count_patch++; 270 | input.erase(0, pos + delimiter_patch.length()); 271 | } 272 | /* last byte */ 273 | UINT32 tmp = strtol(input.c_str(), NULL, 16); 274 | ps->patch[count_patch++] = (unsigned char)tmp; 275 | 276 | ps->patch[count_patch] = '\0'; 277 | 278 | patch_map.insert(pair(ps->start, ps)); 279 | 280 | 281 | for (UINT32 j = ps->start + 1; j <= ps->fin; j++) { 282 | patch_map.insert(pair(j, (patch_struct*)-1)); 283 | } 284 | 285 | PIN_RemoveInstrumentationInRange(ps->start, ps->fin); 286 | 287 | *result = "OK"; 288 | return TRUE; 289 | 290 | } 291 | 292 | 293 | VOID INS_HandlerInsStealth(CONTEXT *ctxt, ADDRINT addr) { 294 | 295 | patch_struct *ps = patch_map.find(addr)->second; 296 | size_t patch_len = strlen((char*)ps->patch); 297 | UINT32 addr_of_jmp = (UINT32)&ps->ret; 298 | UINT32 start = ps->start; 299 | 300 | unsigned char jmp_opc[] = { 0xff, 0x25 }; 301 | 302 | VOID *mem = W::VirtualAlloc(NULL, PATCH_SIZE + JMP_OPC_SIZE + ADDR_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 303 | 304 | // push patch code 305 | memcpy((VOID*)((UINT32)mem), ps->patch, patch_len); 306 | 307 | // push jmp opc 308 | memcpy((VOID*)((UINT32)mem + patch_len), (void*)jmp_opc, JMP_OPC_SIZE); 309 | 310 | // push jmp addr 311 | memcpy((VOID*)((UINT32)mem + patch_len + JMP_OPC_SIZE), (void*)&addr_of_jmp, ADDR_SIZE); 312 | 313 | PIN_SetContextReg(ctxt, REG_EIP, (ADDRINT)mem); 314 | PIN_ExecuteAt(ctxt); 315 | 316 | } 317 | 318 | VOID INS_AddInsStealth(INS ins) { 319 | 320 | map::iterator ip = patch_map.find(INS_Address(ins)); 321 | if (ip != patch_map.end()) { 322 | if (ip->second != (VOID*)-1) { 323 | INS_InsertCall( 324 | ins, 325 | IPOINT_BEFORE, 326 | (AFUNPTR)INS_HandlerInsStealth, 327 | IARG_CONTEXT, IARG_ADDRINT, 328 | INS_Address(ins), 329 | IARG_END 330 | ); 331 | } 332 | INS_Delete(ins); 333 | } 334 | 335 | } -------------------------------------------------------------------------------- /pintool/src/libdft/array.hpp: -------------------------------------------------------------------------------- 1 | // DCD Stripped down and adapted to Pin's CRT 2 | 3 | /* Copyright (c) 2016, Pollard Banknote Limited 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation and/or 14 | other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its contributors 17 | may be used to endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | #ifndef PBL_CPP_ARRAY_H 32 | #define PBL_CPP_ARRAY_H 33 | 34 | #include "pin.H" // ASSERT() 35 | 36 | //#include "version.hpp" 37 | //#ifdef CPP11 38 | //#include 39 | //#else 40 | #include 41 | //#include 42 | #include 43 | #include 44 | //#include "algorithm.h" 45 | //#include "iterator.h" 46 | 47 | /*namespace cpp11 48 | { 49 | class nullptr_t 50 | { 51 | public: 52 | template< class T > 53 | operator T*() const 54 | { 55 | return 0; 56 | } 57 | 58 | template< class C, class T > 59 | operator T C::*() const 60 | { 61 | return 0; 62 | } 63 | private: 64 | void operator&() const; 65 | }; 66 | 67 | } 68 | 69 | const cpp11::nullptr_t nullptr = {}; 70 | */ // I think we can rely on std::nullptr_t from Pin 71 | 72 | namespace cpp11 73 | { 74 | template< class T, std::size_t N > 75 | struct array 76 | { 77 | typedef T& reference; 78 | typedef const T& const_reference; 79 | typedef T* iterator; 80 | typedef const T* const_iterator; 81 | typedef std::size_t size_type; 82 | typedef std::ptrdiff_t difference_type; 83 | typedef T value_type; 84 | typedef T* pointer; 85 | typedef const T* const_pointer; 86 | typedef std::reverse_iterator< iterator > reverse_iterator; 87 | typedef std::reverse_iterator< const_iterator > const_reverse_iterator; 88 | 89 | reference at(size_type n) 90 | { 91 | ASSERT(n < N, "Out of range"); 92 | return elems[n]; 93 | } 94 | 95 | const_reference at(size_type n) const 96 | { 97 | ASSERT(n < N, "Out of range"); 98 | return elems[n]; 99 | } 100 | 101 | reference operator[](size_type n) 102 | { 103 | return elems[n]; 104 | } 105 | 106 | const_reference operator[](size_type n) const 107 | { 108 | return elems[n]; 109 | } 110 | 111 | reference front() 112 | { 113 | return elems[0]; 114 | } 115 | 116 | const_reference front() const 117 | { 118 | return elems[0]; 119 | } 120 | 121 | reference back() 122 | { 123 | return elems[N - 1]; 124 | } 125 | 126 | const_reference back() const 127 | { 128 | return elems[N - 1]; 129 | } 130 | 131 | T* data() 132 | { 133 | return elems; 134 | } 135 | 136 | const T* data() const 137 | { 138 | return elems; 139 | } 140 | 141 | iterator begin() 142 | { 143 | return elems; 144 | } 145 | 146 | const_iterator begin() const 147 | { 148 | return elems; 149 | } 150 | 151 | const_iterator cbegin() const 152 | { 153 | return elems; 154 | } 155 | 156 | iterator end() 157 | { 158 | return elems + N; 159 | } 160 | 161 | const_iterator end() const 162 | { 163 | return elems + N; 164 | } 165 | 166 | const_iterator cend() const 167 | { 168 | return elems + N; 169 | } 170 | 171 | reverse_iterator rbegin() 172 | { 173 | return reverse_iterator( elems + ( N - 1 ) ); 174 | } 175 | 176 | const_reverse_iterator rbegin() const 177 | { 178 | return reverse_iterator( elems + ( N - 1 ) ); 179 | } 180 | 181 | const_reverse_iterator crbegin() const 182 | { 183 | return reverse_iterator( elems + ( N - 1 ) ); 184 | } 185 | 186 | reverse_iterator rend() 187 | { 188 | return reverse_iterator(elems - 1); 189 | } 190 | 191 | const_reverse_iterator rend() const 192 | { 193 | return reverse_iterator(elems - 1); 194 | } 195 | 196 | const_reverse_iterator crend() const 197 | { 198 | return reverse_iterator(elems - 1); 199 | } 200 | 201 | bool empty() const 202 | { 203 | return false; // DCD would be true only if array size is 0 204 | } 205 | 206 | size_type size() const 207 | { 208 | return N; 209 | } 210 | 211 | size_type max_size() const 212 | { 213 | return N; 214 | } 215 | 216 | void fill(const T& t) 217 | { 218 | std::fill_n(elems, N, t); 219 | } 220 | 221 | void swap(array< T, N >& a) 222 | { 223 | std::swap_ranges(elems, elems + N, a.elems); 224 | } 225 | 226 | T elems[N]; 227 | }; 228 | 229 | 230 | template< class T > 231 | struct array< T, 0 > 232 | { 233 | typedef T& reference; 234 | typedef const T& const_reference; 235 | typedef T* iterator; 236 | typedef const T* const_iterator; 237 | typedef std::size_t size_type; 238 | typedef std::ptrdiff_t difference_type; 239 | typedef T value_type; 240 | typedef T* pointer; 241 | typedef const T* const_pointer; 242 | typedef std::reverse_iterator< iterator > reverse_iterator; 243 | typedef std::reverse_iterator< const_iterator > const_reverse_iterator; 244 | 245 | T elems[1]; 246 | 247 | void fill(const T& t) 248 | { 249 | } 250 | 251 | void swap(array< T, 0 >&) 252 | { 253 | } 254 | 255 | iterator begin() 256 | { 257 | return elems; 258 | } 259 | 260 | const_iterator begin() const 261 | { 262 | return elems; 263 | } 264 | 265 | const_iterator cbegin() const 266 | { 267 | return elems; 268 | } 269 | 270 | iterator end() 271 | { 272 | return elems; 273 | } 274 | 275 | const_iterator end() const 276 | { 277 | return elems; 278 | } 279 | 280 | const_iterator cend() const 281 | { 282 | return elems; 283 | } 284 | 285 | reverse_iterator rbegin() 286 | { 287 | return reverse_iterator(); 288 | } 289 | 290 | const_reverse_iterator rbegin() const 291 | { 292 | return reverse_iterator(); 293 | } 294 | 295 | const_reverse_iterator crbegin() const 296 | { 297 | return reverse_iterator(); 298 | } 299 | 300 | reverse_iterator rend() 301 | { 302 | return reverse_iterator(); 303 | } 304 | 305 | const_reverse_iterator rend() const 306 | { 307 | return reverse_iterator(); 308 | } 309 | 310 | const_reverse_iterator crend() const 311 | { 312 | return reverse_iterator(); 313 | } 314 | 315 | size_type size() const 316 | { 317 | return 0; 318 | } 319 | 320 | size_type max_size() const 321 | { 322 | return 0; 323 | } 324 | 325 | bool empty() const 326 | { 327 | return true; 328 | } 329 | 330 | reference operator[](size_type n) 331 | { 332 | return elems[n]; 333 | } 334 | 335 | const_reference operator[](size_type n) const 336 | { 337 | return elems[n]; 338 | } 339 | 340 | reference at(size_type n) 341 | { 342 | ASSERT(false, "Empty array is always out of range") 343 | return elems[n]; 344 | } 345 | 346 | const_reference at(size_type n) const 347 | { 348 | ASSERT(false, "Empty array is always out of range") 349 | return elems[n]; 350 | } 351 | 352 | reference front() 353 | { 354 | return elems[0]; 355 | } 356 | 357 | const_reference front() const 358 | { 359 | return elems[0]; 360 | } 361 | 362 | reference back() 363 | { 364 | return elems[0]; 365 | } 366 | 367 | const_reference back() const 368 | { 369 | return elems[0]; 370 | } 371 | 372 | T* data() 373 | { 374 | return elems; 375 | } 376 | 377 | const T* data() const 378 | { 379 | return elems; 380 | } 381 | 382 | }; 383 | 384 | template< class T, std::size_t N > 385 | void swap( 386 | array< T, N >& a, 387 | array< T, N >& b 388 | ) 389 | { 390 | a.swap(b); 391 | } 392 | 393 | template< class T, std::size_t N > 394 | bool operator==( 395 | const array< T, N >& a, 396 | const array< T, N >& b 397 | ) 398 | { 399 | return std::equal( a.begin(), a.end(), b.begin() ); 400 | } 401 | 402 | template< class T, std::size_t N > 403 | bool operator!=( 404 | const array< T, N >& a, 405 | const array< T, N >& b 406 | ) 407 | { 408 | return !std::equal( a.begin(), a.end(), b.begin() ); 409 | } 410 | 411 | template< class T, std::size_t N > 412 | bool operator<( 413 | const array< T, N >& a, 414 | const array< T, N >& b 415 | ) 416 | { 417 | return std::lexicographical_compare( a.begin(), a.end(), b.begin(), b.end() ); 418 | } 419 | 420 | template< class T, std::size_t N > 421 | bool operator<=( 422 | const array< T, N >& a, 423 | const array< T, N >& b 424 | ) 425 | { 426 | return !std::lexicographical_compare( b.begin(), b.end(), a.begin(), a.end() ); 427 | } 428 | 429 | template< class T, std::size_t N > 430 | bool operator>( 431 | const array< T, N >& a, 432 | const array< T, N >& b 433 | ) 434 | { 435 | return std::lexicographical_compare( b.begin(), b.end(), a.begin(), a.end() ); 436 | } 437 | 438 | template< class T, std::size_t N > 439 | bool operator>=( 440 | const array< T, N >& a, 441 | const array< T, N >& b 442 | ) 443 | { 444 | return !std::lexicographical_compare( a.begin(), a.end(), b.begin(), b.end() ); 445 | } 446 | 447 | } 448 | 449 | namespace cpp 450 | { 451 | using namespace ::std; 452 | using namespace ::cpp11; 453 | } 454 | 455 | //#endif // ifdef CPP11 456 | #endif // PBL_CPP_ARRAY_H 457 | -------------------------------------------------------------------------------- /pintool/src/HiddenElements.cpp: -------------------------------------------------------------------------------- 1 | #include "HiddenElements.h" 2 | #include "pin.H" 3 | #include 4 | 5 | namespace HiddenElements { 6 | 7 | bool KTM[MAX_NUMHOOKS]; 8 | 9 | char* hiddenProcesses[MAX_HOOKS_IN_GROUP]; 10 | char* regOpenKeyStrings[MAX_HOOKS_IN_GROUP]; 11 | char* regQueryValueStrings[MAX_HOOKS_IN_GROUP]; 12 | char* genericFilenames[MAX_HOOKS_IN_GROUP]; 13 | char* windowNames[MAX_HOOKS_IN_GROUP]; 14 | char* WMIQueryFail[MAX_HOOKS_IN_GROUP]; 15 | 16 | char* defaultHiddenProcesses[] = { 17 | "VBOX", "ORACLE", "OLLYDBG", "PROCESSHACKER", 18 | "AUTORUNS", "PYTHON", "REGSHOT", "TCPVIEW", 19 | "FILEMON", "PROCMON", "REGMON", "PROCEXP", 20 | "IDAQ", "IMMUNITY", "WIRESHARK", "DUMPCAP", 21 | "HOOKEXPLORER", "IMPORTREC", "PETOOLS", "LORDPE", 22 | "SYSINSPECTOR", "ANALYZER", "SNIFF", "WINDBG", 23 | "JOEBOX", "VMWARE", "VMUSRVC", "VMTOOLSD", "DF5SERV", 24 | "PIN", "CMD", 25 | NULL 26 | }; 27 | 28 | char* defaultRegOpenKeyStrings[] = { 29 | "VIRTUALBOX", "VBOX", "GUEST ADDITION", "ORACLE", 30 | "PCI", "VIRTUAL", "DEVICE", "DRIVER", "CYGWIN", // "FLAG", 31 | "ENUM\\IDE", "VMWARE", "DESCRIPTION\\SYSTEM", 32 | "CONTROL\\VIDEO", 33 | NULL 34 | }; 35 | 36 | char* defaultRegQueryValueStrings[] = { 37 | "VIRTUALBOX", "VBOX", "IDA", "ORACLE", "06/23/99", 38 | "VMWARE", "BIOS", "VIRTUAL_DISK", 39 | NULL 40 | }; 41 | 42 | char* defaultGenericFilenames[] = { 43 | "VIRTUALBOX", "VBOX", "ORACLE", "GUEST", "PHYSICALDRIVE", 44 | "VMMOUSE", "HGFS", "VMHGFS", "VMCI", "VMWARE", 45 | NULL 46 | }; 47 | 48 | char* defaultWindowNames[] = { 49 | "VIRTUALBOX", "VBOX", "ORACLE", 50 | "QWINDOWICON", "OLLY", "ID", "GUEST", 51 | NULL 52 | }; 53 | 54 | char* defaultWMIQueryFail[] = { 55 | "PNPENTITY", "NTEVENTLOGFILE", "LOGICALDISK", 56 | "BIOS", "NETWORKADAPTER", "PROCESSOR", 57 | "OPERATINGSYSTEM", "COMPUTERSYSTEM", 58 | NULL 59 | }; 60 | 61 | static inline int copyArrayOfStringRefs(char** src, char** dest) { 62 | char** tmp = dest; 63 | while (*src) { 64 | *tmp = *src; 65 | tmp++, src++; 66 | } 67 | *tmp = NULL; 68 | return tmp - dest; // number of copied elements 69 | } 70 | 71 | void initializeHiddenStuff() { 72 | updateHiddenProcesses(NULL); 73 | updateRegOpenKeyStrings(NULL); 74 | updateRegQueryValueStrings(NULL); 75 | updateGenericFileNames(NULL); 76 | updateWindowNames(NULL); 77 | updateWMIQueryFail(NULL); 78 | int i; 79 | for (i = 0; i < MAX_NUMHOOKS; i++) { 80 | KTM[i] = TRUE; 81 | } 82 | } 83 | 84 | static inline void setGroupAux(const int* IDs, int numIDs, bool value) { 85 | for (int i = 0; i < numIDs; i++) 86 | KTM[IDs[i]] = value; 87 | } 88 | 89 | void setGroup(int groupID, bool value) { 90 | 91 | static const int libMemory[] = { 92 | EN_PlaceholderForMem // MEMORY group 93 | }; 94 | 95 | static const int libFile[] = { 96 | EN_GetFileAttributes, // FILE group 97 | EN_FindFirstFile, 98 | EN_FindNextFile, 99 | EN_CreateFile 100 | }; 101 | 102 | static const int libDebugger[] = { 103 | EN_IsDebuggerPresent // DEBUGGER lonely group 104 | }; 105 | 106 | static const int libGUI[] = { 107 | EN_GetCursorPos, // GUI group 108 | EN_FindWindow, 109 | EN_GetWindowText, 110 | EN_SysAllocString 111 | }; 112 | 113 | static const int libWMI[] = { 114 | EN_SysAllocString // WMI lonely group 115 | }; 116 | 117 | static const int libHardware[] = { 118 | EN_GetDiskFreeSpaceEx, // HARDWARE group 119 | EN_SetupDiGetDeviceRegistryProperty, 120 | EN_EnumDisplaySettings, 121 | EN_K32GetDeviceDriverBaseName 122 | }; 123 | 124 | static const int libProcess[] = { 125 | EN_GetModuleFileName, // PROCESS group 126 | EN_GetModuleFileNameEx, 127 | EN_Process32Next, 128 | EN_CreateProcessInternal 129 | }; 130 | 131 | static const int libPipe[] = { 132 | EN__popen, // PIPE group 133 | EN__wpopen, 134 | EN__tpopen 135 | }; 136 | 137 | static const int libDLL[] = { 138 | EN_LoadLibrary, // DLL group 139 | EN_LoadLibraryEx, 140 | EN_LdrGetDllHandle, 141 | EN_LdrGetDllHandleEx 142 | }; 143 | 144 | static const int libTime[] = { 145 | EN_GetTickCount, // TIME group 146 | EN_SetTimer, 147 | EN_GetSystemTimeAsFileTime 148 | }; 149 | 150 | static const int libMutex[] = { 151 | EN_WaitForSingleObject // MUTEX lonely group 152 | }; 153 | 154 | static const int libNetwork[] = { 155 | EN_IcmpCreateFile, // NETWORK group 156 | EN_IcmpSendEcho, 157 | EN_WNetGetProviderName, 158 | EN_GetAdaptersInfo 159 | }; 160 | 161 | static const int libRegistry[] = { 162 | EN_RegOpenKeyEx, // REGISTRY group 163 | EN_RegOpenKey, 164 | EN_RegQueryValueEx, 165 | EN_RtlCompareUnicodeString 166 | }; 167 | 168 | static const int libString[] = { 169 | EN_RtlCompareUnicodeString, // STRING group 170 | EN_RtlEqualUnicodeString, 171 | EN_wcsstr, 172 | EN_wcscmp, 173 | EN_wcsncmp, 174 | EN__wcsnicmp, 175 | EN_strstr, 176 | EN_strcmp, 177 | EN__strcmpi, 178 | EN_CompareString, 179 | EN_CompareStringEx 180 | }; 181 | 182 | static const int syscallsAll[] = { 183 | EN_NtQueryInformationProcess, 184 | EN_NtQuerySystemInformation, 185 | EN_NtQueryPerformanceCounter, 186 | EN_NtOpenProcess, 187 | EN_NtRequestWaitReplyPort, 188 | EN_NtAllocateVirtualMemory, 189 | EN_NtProtectVirtualMemory, 190 | EN_NtCreateFile, 191 | EN_NtWriteVirtualMemory, 192 | EN_NtMapViewOfSection, 193 | EN_NtCreateThreadEx, 194 | EN_NtQueueApcThread, 195 | EN_NtResumeThread, 196 | EN_NtDelayExecution, 197 | EN_NtQueryDirectoryObject, 198 | EN_NtOpenKey, 199 | EN_NtOpenKeyEx, 200 | EN_NtEnumerateKey, 201 | EN_NtQueryValueKey, 202 | EN_NtQueryAttributesFile, 203 | EN_NtOpenDirectoryObject, 204 | EN_NtQueryObject, 205 | EN_NtClose 206 | }; 207 | 208 | static const int instructionsAll[] = { 209 | EN_rdtsc, 210 | EN_cpuid, 211 | EN_int0x2d 212 | }; 213 | 214 | switch (groupID) { 215 | case EN_GR_L_MEMORY: 216 | setGroupAux(libMemory, sizeof(libMemory) / sizeof(libMemory[0]), value); 217 | break; 218 | case EN_GR_L_FILE: 219 | setGroupAux(libFile, sizeof(libFile) / sizeof(libFile[0]), value); 220 | break; 221 | case EN_GR_L_DEBUGGER: 222 | setGroupAux(libDebugger, sizeof(libDebugger) / sizeof(libDebugger[0]), value); 223 | break; 224 | case EN_GR_L_GUI: 225 | setGroupAux(libGUI, sizeof(libGUI) / sizeof(libGUI[0]), value); 226 | break; 227 | case EN_GR_L_WMI: 228 | setGroupAux(libWMI, sizeof(libWMI) / sizeof(libWMI[0]), value); 229 | break; 230 | case EN_GR_L_HARDWARE: 231 | setGroupAux(libHardware, sizeof(libHardware) / sizeof(libHardware[0]), value); 232 | break; 233 | case EN_GR_L_PROCESS: 234 | setGroupAux(libProcess, sizeof(libProcess) / sizeof(libProcess[0]), value); 235 | break; 236 | case EN_GR_L_PIPE: 237 | setGroupAux(libPipe, sizeof(libPipe) / sizeof(libPipe[0]), value); 238 | break; 239 | case EN_GR_L_DLL: 240 | setGroupAux(libDLL, sizeof(libDLL) / sizeof(libDLL[0]), value); 241 | break; 242 | case EN_GR_L_TIME: 243 | setGroupAux(libTime, sizeof(libTime) / sizeof(libTime[0]), value); 244 | break; 245 | case EN_GR_L_MUTEX: 246 | setGroupAux(libMutex, sizeof(libMutex) / sizeof(libMutex[0]), value); 247 | break; 248 | case EN_GR_L_NETWORK: 249 | setGroupAux(libNetwork, sizeof(libNetwork) / sizeof(libNetwork[0]), value); 250 | break; 251 | case EN_GR_L_REGISTRY: 252 | setGroupAux(libRegistry, sizeof(libRegistry) / sizeof(libRegistry[0]), value); 253 | break; 254 | case EN_GR_L_STRING: 255 | setGroupAux(libString, sizeof(libString) / sizeof(libString[0]), value); 256 | break; 257 | case EN_GR_S_ALL: 258 | setGroupAux(syscallsAll, sizeof(syscallsAll) / sizeof(syscallsAll[0]), value); 259 | break; 260 | case EN_GR_I_ALL: 261 | setGroupAux(instructionsAll, sizeof(instructionsAll) / sizeof(instructionsAll[0]), value); 262 | break; 263 | default: 264 | std::cerr << "UNKNOWN GROUP ID! TRY AND CHECK KTM INSTEAD" << std::endl; 265 | } 266 | } 267 | 268 | 269 | void updateHiddenProcesses(char** procNames) { 270 | if (!procNames) 271 | copyArrayOfStringRefs(defaultHiddenProcesses, hiddenProcesses); 272 | else 273 | copyArrayOfStringRefs(procNames, hiddenProcesses); 274 | } 275 | 276 | void updateRegOpenKeyStrings(char** strings) { 277 | if (!strings) 278 | copyArrayOfStringRefs(defaultRegOpenKeyStrings, regOpenKeyStrings); 279 | else 280 | copyArrayOfStringRefs(strings, regOpenKeyStrings); 281 | } 282 | 283 | void updateRegQueryValueStrings(char** strings) { 284 | if (!strings) 285 | copyArrayOfStringRefs(defaultRegQueryValueStrings, regQueryValueStrings); 286 | else 287 | copyArrayOfStringRefs(strings, regQueryValueStrings); 288 | } 289 | 290 | void updateGenericFileNames(char** fileNames) { 291 | if (!fileNames) 292 | copyArrayOfStringRefs(defaultGenericFilenames, genericFilenames); 293 | else 294 | copyArrayOfStringRefs(fileNames, genericFilenames); 295 | } 296 | 297 | void updateWindowNames(char** windowsNames) { 298 | if (!windowsNames) 299 | copyArrayOfStringRefs(defaultWindowNames, windowNames); 300 | else 301 | copyArrayOfStringRefs(windowsNames, windowNames); 302 | } 303 | 304 | void updateWMIQueryFail(char** strings) { 305 | if (!strings) 306 | copyArrayOfStringRefs(defaultWMIQueryFail, WMIQueryFail); 307 | else 308 | copyArrayOfStringRefs(strings, WMIQueryFail); 309 | } 310 | 311 | static inline bool lookupSubstring(const char* str, char** strings) { 312 | while (*strings) { 313 | if (strstr(str, *strings)) return true; 314 | strings++; 315 | } 316 | return false; 317 | } 318 | 319 | bool shouldHideProcessStr(const char* procNameUpper) { 320 | return lookupSubstring(procNameUpper, hiddenProcesses); 321 | } 322 | 323 | bool shouldHideRegOpenKeyStr(const char* strUpper) { 324 | return lookupSubstring(strUpper, regOpenKeyStrings); 325 | } 326 | 327 | bool shouldHideReqQueryValueStr(const char* strUpper) { 328 | return lookupSubstring(strUpper, regQueryValueStrings); 329 | } 330 | 331 | bool shouldHideGenericFileNameStr(const char * strUpper) { 332 | return lookupSubstring(strUpper, genericFilenames); 333 | } 334 | 335 | bool shouldHideWindowStr(const char* strUpper) { 336 | return lookupSubstring(strUpper, windowNames); 337 | } 338 | 339 | bool shouldWMIQueryFail(const char * strUpper) { 340 | return lookupSubstring(strUpper, WMIQueryFail); 341 | } 342 | 343 | } /* END OF NAMESPACE*/ 344 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BluePill 2 | 3 | **BluePill** is an open-source dynamic analysis framework for handling evasive malware. Its goal is to reconcile the transparency properties needed for automatic analyses with the fine-grained execution inspection and patching capabilities required for manual analysis. 4 | 5 | BluePill is an academic prototype that we maintain in our spare time: your feedback is precious! 6 | 7 | BluePill can counter many red pills targeting hypervisors, debuggers, third-party tools, and timing artifacts. It builds on dynamic binary instrumentation (DBI) to monitor queries that malware can make on the environment looking for artifacts, altering their results when they may reveal the presence of an automated analysis system or a human agent. BluePill offers a GDB remote interface to debug a sample while taking care of evasions of behalf of the analysts, along with a new stealth patching mechanisms to hide code changes made in the debugger from self-checksumming schemes. 8 | 9 | We tested BluePill on heterogeneous PE32 Windows malware running on 32-bit Windows 7 SP1: as an example, we can run executables protected with recent versions of VMProtect and Themida and highly evasive samples like Furtim. 10 | 11 | BluePill has been presented in: 12 | * ***Black Hat Europe 2019***. *BluePill: Neutralizing Anti-Analysis Behavior in Malware Dissection*. [[link]](https://www.blackhat.com/eu-19/briefings/schedule/index.html#bluepill-neutralizing-anti-analysis-behavior-in-malware-dissection-17685) [[slides]](https://i.blackhat.com/eu-19/Wednesday/eu-19-Delia-BluePill-Neutralizing-Anti-Analysis-Behavior-In-Malware-Dissection.pdf) [[video]](https://www.youtube.com/watch?v=F_AK5eDGeak) 13 | * ***IEEE Transactions on Information Forensics and Security 2020***. *On the Dissection of Evasive Malware*. [[link]](https://ieeexplore.ieee.org/document/9018111) [[preprint]](https://www.diag.uniroma1.it/~delia/papers/tifs20.pdf) 14 | 15 | To counter DBI evasions, BluePill uses a [library of mitigations](https://github.com/season-lab/sok-dbi-security/) that we wrote for Intel Pin as part of our paper *SoK: Using Dynamic Binary Instrumentation for Security (And How You May Get Caught Red-Handed)* from ASIACCS 2019. In BluePill, we extended the library with further mitigations for time overheads and red pills targeting the GDB remote debugging interface and exception handling. You can read more about DBI evasions in the paper *Evaluating Dynamic Binary Instrumentation Systems for Conspicuous Features and Artifacts* recently appeared in ACM DTRAP ([preprint](http://www.diag.uniroma1.it//~delia/papers/dtrap21.pdf)). 16 | 17 | ### Supported Evasions 18 | 19 | Below a partial list of the evasions BluePill countered in our tests on a Windows 7 SP1 32-bit VirtualBox 5.2 machine for a large deal of executable protectors and armored samples: 20 | 21 | Category | Instances 22 | --- | --- 23 | Hypervisor | Guest additions, files, registry entries, libraries, and drivers from VirtualBox 24 | Hardware | BIOS and firmware strings, MAC address, `cpuid`, disk size, power/thermal capabilities 25 | Time | Slowdown detection using `rtdsc` and Windows time-related APIs 26 | Software | Artifacts of common monitoring tools (running processes, GUI windows), parent process, HKL keyboard layout, frozen mouse cursor 27 | Debugging | Single-step exceptions, `int 2d`, OS queries for active/installed debuggers (e.g. `NtQueryInformationProcess`), Process Entry Block fields 28 | WMI queries | CPU, disk size, MAC address, ACPI, MUI languages, VirtualBox `VBOXVIDEO` 29 | DBI | Pointer leaks with FPU instructions, memory contents and permissions (e.g. guard pages, NX enforcing) 30 | 31 | *NOTE: Before going public for BH Europe 2019, we made radical changes that broke the handling of 64-bit code and (to a small extent) of the WoW64 subsystem: please consider these scenarios experimental as we complete the regression testing, and feel free to report issues.* 32 | 33 | ### Compilation 34 | 35 | BluePill builds on [Intel Pin](https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool) (v3.16 recommended) and requires Visual Studio 2015 or higher for its compilation. 36 | 37 | Pin has some dependencies that require manual inclusion in the project. We created a `Locals.props` file that simplifies the project configuration. Its defaults are Pin being installed in `C:\Pin316` and the SDK 8.1 headers being in use: 38 | 39 | ``` 40 | 41 | C:\Pin316 42 | C:/Program Files (x86)/Windows Kits/8.1/Include/um 43 | 44 | ``` 45 | 46 | For instance, if you wish to use the SDK 10.0.17763.0 headers, after modifying the Project settings in Visual Studio 47 | you should also change the value of the `WinHPath` property to `C:/Program Files/Windows Kits/10/Include/10.0.17763.0/um`. Similary, modify the property value if your SDK 8.1 headers are installed in `C:/Program Files/` instead of `C:/Program Files (x86)/`. The purpose of this field is to assist Pin when it includes the absolute path of `Windows.h` from its CRT headers. 48 | 49 | You should now be able to compile BluePill. Once compilation ends, you will find a `bluepill32.dll` library in the Pin directory. If you encounter a missing `msvc_compat.h` error, make sure that `$(PinFolder)\extras\crt\include` is a valid path. 50 | 51 | 52 | ### Quick start 53 | 54 | To run an executable under BluePill use: 55 | 56 | ``` 57 | C:\Pin316\pin.exe -t bluepill32.dll [options] -- 58 | ``` 59 | 60 | BluePill supports the following command-line options: 61 | 62 | Option | Meaning 63 | --- | --- 64 | `-evasions` | Detect and handle the majority of evasions supported (see below for DBI) 65 | `-debugger` | Enable debugger mode via GDB remote interface 66 | `-leak` | DBI evasions: fix leaks of real EIP (e.g. FPU instructions) 67 | `-nx` | DBI evasions: check that code pages are executable 68 | `-rw` | DBI evasions: hide pages that belong to the DBI engine 69 | 70 | For instance, to run an evasive program named `sample.exe` in a sandbox-like automatic mode try: 71 | 72 | ``` 73 | C:\Pin316\pin.exe -t bluepill32.dll -evasions -leak -- sample.exe 74 | ``` 75 | 76 | Enabling the `-leak` mitigation has minimal performance impact, while `-nx` and ultimately `-rw` can help with complex packers that attempt conformance checking on the address space of the program. 77 | 78 | BluePill will create a file named `evasions.log` under Pin's folder `C:\Pin316` (modify the `LOGPATH` variable inside `pintool\src\logging.h` to change it) that logs possible evasion attempts intercepted during the execution. 79 | 80 | ### Debugging via GDB remote interface 81 | 82 | BluePill supports the use of a debugger to control the execution and carry out malware dissection. We rely on the GDB remote interface of Pin: BluePill can thus be used as a remote backend from your debugger tool if it supports the GDB protocol. In the following we provide instructions to set up a debugging session with IDA Pro. 83 | 84 | To enable the debugger interface, you need to provide additional command-line options to both Pin (`-appdebug -appdebug_server_port `) and BluePill (`-debugger`) as follows: 85 | 86 | ``` 87 | C:\Pin316\pin.exe -appdebug —appdebug_server_port 10000 -t bluepill32.dll -debugger [other options] -- 88 | ``` 89 | 90 | We will use `10000` as port number in this guide. The application will stay paused until you connect a debugger to the socket: however, if you try *attaching* a local debugger to the process, you will end up debugging the whole Pin engine instead of just the application. The expected output on screen will be something like: 91 | 92 | ![Pin waiting for a debugger to connect](docs/pin-debugger-port.png) 93 | 94 | #### Setting up IDA Pro 95 | You can now open the executable in IDA and select the *Remote GDB debugger* backend from `Debugger->Switch debugger`. Check that the options (e.g. port number) are correct using `Debugger->Process options` like in the screenshot below: 96 | 97 | ![IDA debugger settings](docs/ida-debugger-settings.png) 98 | 99 | At this point it helps to insert a breakpoint on some address in the main executable section, for instance on the entrypoint. Then you can start your debugging session with `Debugger->Start process`. IDA will notify you that *"There is already a process being debugged by remote. Do you want to attach to it?"*. Just click *Yes* and the debugging session will start, with EIP being somewhere inside in ntdll.dll. 100 | 101 | Since memory mapping information is not available by default over the GDB remote protocol, we added a custom debugger command `vmmap` that instructs BluePill to build such a map. We automated this process with a script `addSegments.py` available in the `scripts/` folder: just load it in IDA with `File->Script file`. The script will populate the *Segments* subview of IDA with the memory layout information (i.e. sections and their permissions) for each code module. *Note: we will soon add code to update the Module subview, which currently stays stale.* 102 | 103 | You can now debug your sample as BluePill shields you from a whole lot of evasions :-) 104 | 105 | Please note that exception handling requires a workaround for the current GDB server support in Pin. When an exception should not be passed to the application (e.g., `0xc0000008` for an invalid handle passed to CloseHandle), send a `wait` command in the GDB console right after you receive the exception message, then disconnect and reconnect IDA to BluePill. In the meantime, the debugger helper will keep the executable on hold in response to the command. 106 | 107 | *NOTE: we originally relied on the disconnection trick also for other exception kinds. For them, newly introduced changes in some Pin release after the 3.5 one lead to an internal assertion failure when reattaching the debugger (*`A: source\pinvm\debugger-connection\debugger-connection.cpp: PINVM::DEBUGGER_CONNECTION::NotifyThreadsStopped: 1004: assertion failed: focus != PIN::INVALID_THREADID`*). Therefore, when you face e.g. a *`0xc0000005`* exception from an *`int 3`* opcode or an *`int 2d`* evasion, you shoud pass the exception to the application. The debugger interface of Pin will not be detected directly, but the adversary may still do that by using a write watch. We are currently thinking of a workaround to shield such artifacts too.* 108 | 109 | #### Making stealth code edits 110 | BluePill implements a unique functionality to patch a code portion when debugging while hiding it from the executing code. An applied patch remains invisible to anti-tampering schemes (e.g. self-checksumming sequences) as it is tighly coupled with the JIT mechanism of Pin. In a nutshell, we redo the JIT compilation to add trampolines that override the compiled (original) instructions and go unnoticed by code protection mechanisms, as memory reads keep being redirected to the original program instructions. 111 | 112 | The creation of a patch is divded into three steps: 113 | 1. identifying the code portion you want to overwrite (start and end addresses); 114 | 2. assembling a piece of code to execute instead of the one identified at the previous step; 115 | 3. selecting the continuation address where to transfer execution once the patch has executed. 116 | 117 | Consider the code block in the image below, and suppose we want to overwrite the `mov ebp, esp` instruction at address `0x771X37A5` with a `mov eax, esp` instruction (`89 e0` in binary), and then make execution resume at address `0x771X37A8`. 118 | 119 | ![stealth patching](docs/stealth-patching.png) 120 | 121 | When BluePill is operating in debugger mode, we can instruct Pin for patches through a custom GDB command: `set____`, with addresses expressed as hex numbers and code patch bytes separated by a comma. For the example above we can use: `set_771c37a6_771c37a6_771c37a8_89,e0`. 122 | 123 | Patches can then simply be removed using another custom GDB command: `rm__`. 124 | 125 | ### Citation 126 | 127 | If you are using BluePill in an academic project or you believe it would fit some discussion section in your paper, we would be grateful if you could reference our work using the following BibTeX entry: 128 | 129 | ``` 130 | @ARTICLE{BluePill, 131 | author={D'Elia, Daniele Cono and Coppa, Emilio and Palmaro, Federico and Cavallaro, Lorenzo}, 132 | journal={IEEE Transactions on Information Forensics and Security}, 133 | title={On the Dissection of Evasive Malware}, 134 | year={2020}, 135 | volume={15}, 136 | number={}, 137 | pages={2750-2765}, 138 | doi={10.1109/TIFS.2020.2976559}} 139 | ``` 140 | 141 | ### Authors 142 | * Daniele Cono D'Elia ([@dcdelia](https://github.com/dcdelia)) - design & enhancements 143 | * Federico Palmaro ([@nik94](https://github.com/nik94)) - core development 144 | -------------------------------------------------------------------------------- /pintool/src/syshooking.cpp: -------------------------------------------------------------------------------- 1 | #include "pin.H" 2 | 3 | #include "syshooking.h" 4 | #include "memory.h" 5 | #include "syshooks.h" 6 | 7 | #include 8 | 9 | #include "process.h" 10 | #include "state.h" 11 | #include "HiddenElements.h" 12 | #include "helper.h" 13 | #include "itree.h" 14 | 15 | 16 | namespace W { 17 | #include "windows.h" 18 | } 19 | 20 | extern TLS_KEY tls_key; 21 | 22 | namespace SYSHOOKING { 23 | CHAR* syscallIDs[MAXSYSCALLS]; 24 | ADDRINT ntdllImgStart, ntdllImgEnd; 25 | 26 | typedef bool(*t_checkCS)(itreenode_t* node, itreenode_t* root, ADDRINT* ESP); 27 | t_checkCS checkCS_callback; 28 | 29 | // entries NULL by default (POD) 30 | syscall_hook sysEntryHooks[MAXSYSCALLS]; 31 | syscall_hook sysExitHooks[MAXSYSCALLS]; 32 | syscall_hook win32sysEntryHooks[MAXWIN32KSYSCALLS-0x1000]; 33 | syscall_hook win32sysExitHooks[MAXWIN32KSYSCALLS-0x1000]; 34 | 35 | // helpers 36 | VOID getNtdllRangesAndWow64Info(); 37 | VOID enumSyscalls(); 38 | VOID registerHooks(); 39 | VOID getArgumentsOnEntry(CONTEXT *ctx, SYSCALL_STANDARD std, int count, ...); 40 | int lookupIndex(const char* syscallName); 41 | bool checkCallSiteNTDLLWin32(itreenode_t* node, itreenode_t* root, ADDRINT* ESP); 42 | bool checkCallSiteNTDLLWow64(itreenode_t* node, itreenode_t* root, ADDRINT* ESP); 43 | 44 | VOID Init() { 45 | getNtdllRangesAndWow64Info(); 46 | enumSyscalls(); 47 | registerHooks(); 48 | } 49 | 50 | // for now this TLS is used for syscall info only 51 | // TODO merge it with stuff from state.h etc? 52 | VOID SetTLSKey(THREADID tid) { 53 | pintool_tls* tdata = new pintool_tls; // POD is zero-initialized 54 | 55 | if (PIN_SetThreadData(tls_key, tdata, tid) == FALSE) { 56 | LOG_AR("PIN_SetThreadData failed"); 57 | PIN_ExitProcess(1); 58 | } 59 | } 60 | 61 | // analysis callback for Pin 62 | VOID SyscallEntry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) { 63 | ADDRINT syscall_number = PIN_GetSyscallNumber(ctx, std); 64 | 65 | if (syscall_number == 0) { 66 | LOG_AR("==> WARNING: 0 system call number, possible int 2e case?"); 67 | return; 68 | } 69 | 70 | pintool_tls *tdata = static_cast(PIN_GetThreadData(tls_key, thread_id)); 71 | syscall_t *sc = &tdata->sc; 72 | 73 | sc->syscall_number = syscall_number; 74 | 75 | // TODO for testing purposes 76 | //if (ReturnsToUserCode(ctx)) { 77 | // fprintf(stderr, "Syscall %d returns to user code!\n", syscall_number); 78 | //} 79 | 80 | //if (!(_rwKnob || _nxKnob)) return; // TODO 81 | 82 | if (syscall_number < MAXSYSCALLS) { 83 | syscall_hook hookEntry = sysEntryHooks[syscall_number]; 84 | syscall_hook hookExit = sysExitHooks[syscall_number]; 85 | 86 | if (hookEntry || hookExit) { // fill sc (we may have a hook on exit only) 87 | // TODO selective filling :-/ we need to add prototypes 88 | getArgumentsOnEntry(ctx, std, SYSCALL_NUM_ARG, 89 | 0, &sc->arg0, 1, &sc->arg1, 2, &sc->arg2, 3, &sc->arg3, 90 | 4, &sc->arg4, 5, &sc->arg5, 6, &sc->arg6, 7, &sc->arg7, 91 | 8, &sc->arg8, 9, &sc->arg9, 10, &sc->arg10, 11, &sc->arg11); 92 | 93 | // call onEntry hook 94 | if (hookEntry) hookEntry(sc, ctx, std); 95 | } 96 | } else if (sc->syscall_number >= 0x1000 && sc->syscall_number < MAXWIN32KSYSCALLS) { 97 | ADDRINT num = sc->syscall_number - 0x1000; 98 | syscall_hook hookEntry = win32sysEntryHooks[num]; 99 | syscall_hook hookExit = win32sysExitHooks[num]; 100 | 101 | if (hookEntry || hookExit) { // fill sc (we may have a hook on exit only) 102 | // TODO selective filling :-/ we need to add prototypes 103 | getArgumentsOnEntry(ctx, std, SYSCALL_NUM_ARG, 104 | 0, &sc->arg0, 1, &sc->arg1, 2, &sc->arg2, 3, &sc->arg3, 105 | 4, &sc->arg4, 5, &sc->arg5, 6, &sc->arg6, 7, &sc->arg7, 106 | 8, &sc->arg8, 9, &sc->arg9, 10, &sc->arg10, 11, &sc->arg11); 107 | 108 | // call onEntry hook 109 | if (hookEntry) hookEntry(sc, ctx, std); 110 | } 111 | } 112 | } 113 | 114 | // analysis callback for Pin 115 | VOID SyscallExit(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) { 116 | pintool_tls *tdata = static_cast(PIN_GetThreadData(tls_key, thread_id)); 117 | syscall_t *sc = &tdata->sc; 118 | 119 | //if (!(_rwKnob || _nxKnob)) return; // TODO 120 | 121 | // TODO at some point we will build an array for win32k syscalls 122 | // where we subtract 0x1000 from the ordinal. For now we leave 123 | // this garbage with multiple if statements :-) 124 | if (sc->syscall_number < MAXSYSCALLS) { 125 | syscall_hook hook = sysExitHooks[sc->syscall_number]; 126 | if (hook) hook(sc, ctx, std); 127 | } else if (sc->syscall_number >= 0x1000 && sc->syscall_number < MAXWIN32KSYSCALLS) { 128 | ADDRINT num = sc->syscall_number - 0x1000; 129 | syscall_hook hook = win32sysExitHooks[num]; 130 | if (hook) hook(sc, ctx, std); 131 | } 132 | } 133 | 134 | BOOL ReturnsToUserCode(CONTEXT* ctx) { 135 | ADDRINT *ESP = (ADDRINT*)PIN_GetContextReg(ctx, REG_STACK_PTR); 136 | State::globalState* gs = State::getGlobalState(); 137 | itreenode_t* node = itree_search(gs->dllRangeITree, *ESP); 138 | if (node) { // we might be inside ntdll though 139 | return checkCS_callback(node, gs->dllRangeITree, ESP); 140 | } 141 | return TRUE; 142 | } 143 | 144 | /** HELPER METHODS BEGIN HERE **/ 145 | 146 | // used in getNtdllRangesAndWow64Info() 147 | typedef NTSYSAPI W::PIMAGE_NT_HEADERS NTAPI _RtlImageNtHeader( 148 | W::PVOID ModuleAddress 149 | ); 150 | 151 | static VOID getNtdllRangesAndWow64Info() { 152 | checkCS_callback = (Process::isWow64) ? checkCallSiteNTDLLWow64 : checkCallSiteNTDLLWin32; 153 | 154 | // credits https://www.oipapio.com/question-547093 as 155 | // I couldn't use GetModuleInformation from psapi.dll 156 | // (unless I wanted to load the library dynamically) 157 | W::HMODULE image = W::GetModuleHandle("ntdll"); 158 | 159 | _RtlImageNtHeader* fun = (_RtlImageNtHeader*)W::GetProcAddress(image, "RtlImageNtHeader"); 160 | W::PIMAGE_NT_HEADERS headers = fun(image); 161 | 162 | ntdllImgStart = (ADDRINT)headers->OptionalHeader.ImageBase; // == (ADDRINT)image 163 | ntdllImgEnd = ntdllImgStart + headers->OptionalHeader.SizeOfImage; 164 | } 165 | 166 | // ntdll parsing for syscall ordinal extraction 167 | // Win10 support by borrowing from SNIPER https://github.com/dcdelia/sniper 168 | static VOID enumSyscalls() { 169 | unsigned char *image = (unsigned char *)W::GetModuleHandle("ntdll"); 170 | W::IMAGE_DOS_HEADER *dos_header = (W::IMAGE_DOS_HEADER *) image; 171 | W::IMAGE_NT_HEADERS *nt_headers = (W::IMAGE_NT_HEADERS *)(image + dos_header->e_lfanew); 172 | W::IMAGE_DATA_DIRECTORY *data_directory = &nt_headers-> 173 | OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 174 | W::IMAGE_EXPORT_DIRECTORY *export_directory = (W::IMAGE_EXPORT_DIRECTORY *)(image + data_directory->VirtualAddress); 175 | W::DWORD *address_of_names = (W::DWORD*)(image + export_directory->AddressOfNames); 176 | W::DWORD *address_of_functions = (W::DWORD*)(image + export_directory->AddressOfFunctions); 177 | UINT16 *address_of_name_ordinals = (W::UINT16*)(image + export_directory->AddressOfNameOrdinals); 178 | W::DWORD number_of_names = MIN(export_directory->NumberOfFunctions, export_directory->NumberOfNames); 179 | 180 | for (W::DWORD i = 0; i < number_of_names; i++) { 181 | const char *name = (const char *)(image + address_of_names[i]); 182 | unsigned char *addr = image + address_of_functions[address_of_name_ordinals[i]]; 183 | if (!memcmp(name, "Zw", 2) || !memcmp(name, "Nt", 2)) { 184 | #ifdef __LP64__ 185 | // 64-bit Windows is standard among releases 186 | // mov r10, rcx ; mov eax, sycall_number ; syscall; ret 187 | // 4C 8B D1 ; B8 ?? ?? ?? ?? ; 0F 05 ; C3 188 | if (addr[0] == 0x4C && addr[3] == 0xB8) { 189 | UINT16 syscall_number = *(UINT16*)(addr + 4); // could read UINT32 as well 190 | if (!syscallIDs[syscall_number] || (!memcmp(name, "Nt", 2) && !memcmp(name, "Zw", 2))) { 191 | syscallIDs[syscall_number] = strdup(name); 192 | } 193 | } 194 | #else 195 | // does the signature match one of these cases? https://gist.github.com/wbenny/b08ef73b35782a1f57069dff2327ee4d 196 | // 1: > WoW64 on Windows XP and Windows 7 197 | // mov eax, syscall_number ; mov ecx, imm32 ; lea edx, [esp+04h] ; call fs:[C0h] 198 | // mov eax, syscall_number ; xor ecx, ecx ; lea edx, [esp+04h] ; call fs:[C0h] 199 | // B8 ?? ?? ?? ?? ; [33 C9 | B9 ?? ?? ?? ??] ; 8D 54 24 04 ; 64 FF 15 C0 00 00 00 200 | // epilogue is add esp, 4 ; retn [??] on Windows 7 while XP has no add 201 | // 83 C4 04 ; [C2 ?? ?? | C3] 202 | // 2: > WoW64 on Windows 8 and 8.1 - TODO untested, need a 64-bit Win8 VM :-) 203 | // mov eax, syscall_number; call large dword ptr fs:0C0h ; retn [??] 204 | // B8 ?? ?? ?? ?? ; 64 FF 15 C0 00 00 00 ; [C2 ?? ?? | C3] 205 | // 3: > WoW64 on Windows 10 206 | // mov eax, syscall_number; mov edx, imm32; call edx ; retn [??] 207 | // B8 ?? ?? ?? ?? ; B9 ?? ?? ?? ??] ; FF D2 ; [C2 ?? ?? | C3] 208 | // 4: > x86 - Windows XP and Windows 7 209 | // mov eax, syscall_number ; mov edx, 0x7ffe0300 ; call dword near [edx] ; retn [??] for XP SP3 or 7 210 | // mov eax, syscall_number ; mov edx, 0x7ffe0300 ; call edx ; retn [??] for XP before SP3 211 | // B8 ?? ?? ?? ?? ; BA 00 03 FE 7F; [FF D2 | FF 12] ; [C2 ?? ?? | C3] 212 | // 5: > x86 - Windows 8, 8.1, 10 - TODO untested, need a 32-bit Win8/Win10 VM :) 213 | // mov eax, syscall_number ; call $+?? ; retn [??] ; mov edx, esp ; sysenter ; ret 214 | // B8 ?? ?? ?? ?? ; E8 ?? 00 00 00 ; [C2 ?? ?? | C3] ; 8B D4 ; 0F 34 ; C3 215 | if (addr[0] == 0xb8 && (addr[5] == 0xB9 // case 1 and 3 216 | || addr[5] == 0x33 // case 1 217 | //|| addr[5] == 0x64 // case 2 - untested! 218 | || addr[5] == 0xBA // case 4 219 | //|| addr[5] == 0xE8 // case 5 - untested! 220 | )) { 221 | // on Windows 10 the syscall ordinal will be in the two least significant bytes 222 | // while the remaining two may be non-zero; we ignore them by reading an UINT16 223 | UINT16 syscall_number = *(UINT16*)(addr + 1); 224 | if (!syscallIDs[syscall_number] || (!memcmp(name, "Nt", 2) && !memcmp(name, "Zw", 2))) { 225 | syscallIDs[syscall_number] = strdup(name); 226 | } 227 | } 228 | #endif 229 | } 230 | } 231 | } 232 | 233 | static int lookupIndex(const char* syscallName) { 234 | for (int i = 0; i < MAXSYSCALLS; ++i) { 235 | if (!strcmp(syscallIDs[i], syscallName)) return i; 236 | } 237 | 238 | ASSERT(false, "Unknown system call number"); 239 | return 0; 240 | } 241 | 242 | static VOID getArgumentsOnEntry(CONTEXT *ctx, SYSCALL_STANDARD std, int count, ...) { 243 | va_list args; 244 | va_start(args, count); 245 | for (int i = 0; i < count; i++) { 246 | int index = va_arg(args, int); 247 | ADDRINT *ptr = va_arg(args, ADDRINT *); 248 | *ptr = PIN_GetSyscallArgument(ctx, std, index); 249 | } 250 | va_end(args); 251 | } 252 | 253 | static bool checkCallSiteNTDLLWin32(itreenode_t* node, itreenode_t* root, ADDRINT* ESP) { 254 | ADDRINT addr = *ESP; 255 | if (addr < ntdllImgStart || addr > ntdllImgEnd) return false; 256 | 257 | // not much black magic: retn [say 10h] or ret 258 | // C2 10 00 259 | uint8_t bytes[3] = { 0xFF, 0xFF, 0xFF }; // TODO 0 might be fine as well 260 | PIN_SafeCopy(bytes, (void*)addr, 6); 261 | 262 | if (!((bytes[0] == 0xC2 && bytes[2] == 0x00) || bytes[0] == 0xC3)) { 263 | ASSERT(false, "Check implementation for NTDLL call sites"); 264 | return false; 265 | } 266 | 267 | // the RA for the caller will be at ESP+4 268 | ADDRINT ra = *((ADDRINT*)ESP + 1); 269 | 270 | node = itree_search(root, ra); 271 | if (node) { 272 | //mycerr << "Syscall originated in " << node->dll_name 273 | // << " and would resume at " << ra << std::endl; 274 | return false; 275 | } 276 | 277 | return true; 278 | } 279 | 280 | static bool checkCallSiteNTDLLWow64(itreenode_t* node, itreenode_t* root, ADDRINT* ESP) { 281 | ADDRINT addr = *ESP; 282 | if (addr < ntdllImgStart || addr > ntdllImgEnd) return false; 283 | 284 | // black magic: add esp, 4 followed by retn [say 10h] or ret 285 | // 83 C4 04 286 | // C2 10 00 287 | uint8_t bytes[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // TODO 0 might be fine as well 288 | PIN_SafeCopy(bytes, (void*)addr, 6); 289 | if (!(bytes[0] == 0x83 && bytes[1] == 0xC4 && bytes[2] == 0x04)) { 290 | ASSERT(false, "Check implementation for NTDLL call sites"); 291 | return false; 292 | } 293 | 294 | if (!((bytes[3] == 0xC2 && bytes[5] == 0x00) || bytes[3] == 0xC3)) { 295 | ASSERT(false, "Check implementation for NTDLL call sites"); 296 | return false; 297 | } 298 | 299 | // the RA for the caller will be at ESP+4 300 | ADDRINT ra = *((ADDRINT*)ESP + 1); 301 | 302 | node = itree_search(root, ra); 303 | if (node) { 304 | //mycerr << "Syscall originated in " << node->dll_name 305 | // << " and would resume at " << ra << std::endl; 306 | return false; 307 | } 308 | 309 | return true; 310 | } 311 | 312 | 313 | static VOID registerHooks() { 314 | if (_rwKnob || _nxKnob) { // SoK DBI anti-evasion 315 | sysExitHooks[lookupIndex("NtProtectVirtualMemory")] = &SYSHOOKS::NtProtectVirtualMemory_exit; //&SYSHOOKS::GenericScan_exit; 316 | sysExitHooks[lookupIndex("NtUnmapViewOfSection")] = &SYSHOOKS::GenericScan_exit; // &SYSHOOKS::NtUnmapViewOfSection_exit; 317 | sysExitHooks[lookupIndex("NtFreeVirtualMemory")] = &SYSHOOKS::NtFreeVirtualMemory_exit; 318 | sysExitHooks[lookupIndex("NtFreeUserPhysicalPages")] = &SYSHOOKS::NtFreeUserPhysicalPages_exit; 319 | sysExitHooks[lookupIndex("NtQueryVirtualMemory")] = &SYSHOOKS::NtQueryVirtualMemory_exit; 320 | sysExitHooks[lookupIndex("NtAllocateVirtualMemory")] = &SYSHOOKS::NtAllocateVirtualMemory_exit; 321 | sysExitHooks[lookupIndex("NtAllocateUserPhysicalPages")] = &SYSHOOKS::GenericScan_exit; // &SYSHOOKS::NtAllocateUserPhysicalPages_exit; 322 | sysExitHooks[lookupIndex("NtMapViewOfSection")] = &SYSHOOKS::NtMapViewOfSection_exit; 323 | sysExitHooks[lookupIndex("NtGetMUIRegistryInfo")] = &SYSHOOKS::GenericScan_exit; //&SYSHOOKS::NtGetMUIRegistryInfo_exit; 324 | sysExitHooks[lookupIndex("NtQueryValueKey")] = &SYSHOOKS::GenericScan_exit; 325 | sysExitHooks[lookupIndex("NtRequestWaitReplyPort")] = &SYSHOOKS::GenericScan_exit; 326 | sysExitHooks[lookupIndex("NtClose")] = &SYSHOOKS::GenericScan_exit; 327 | sysExitHooks[lookupIndex("NtCreateSection")] = &SYSHOOKS::GenericScan_exit; 328 | sysExitHooks[lookupIndex("NtMapCMFModule")] = &SYSHOOKS::GenericScan_exit; 329 | sysExitHooks[lookupIndex("NtOpenFile")] = &SYSHOOKS::GenericScan_exit; 330 | sysExitHooks[lookupIndex("NtOpenKey")] = &SYSHOOKS::GenericScan_exit; 331 | sysExitHooks[lookupIndex("NtOpenProcessToken")] = &SYSHOOKS::GenericScan_exit; 332 | sysExitHooks[lookupIndex("NtOpenProcessTokenEx")] = &SYSHOOKS::GenericScan_exit; 333 | sysExitHooks[lookupIndex("NtOpenSection")] = &SYSHOOKS::GenericScan_exit; 334 | sysExitHooks[lookupIndex("NtQueryAttributesFile")] = &SYSHOOKS::GenericScan_exit; 335 | sysExitHooks[lookupIndex("NtQueryInformationProcess")] = &SYSHOOKS::GenericScan_exit; 336 | sysExitHooks[lookupIndex("NtQueryInformationToken")] = &SYSHOOKS::GenericScan_exit; 337 | sysExitHooks[lookupIndex("NtQuerySection")] = &SYSHOOKS::GenericScan_exit; 338 | //sysExitHooks[lookupIndex("")] = &SYSHOOKS::GenericScan_exit; 339 | 340 | // Win32k stuff (embedded ordinal) 341 | win32sysExitHooks[NTGDIPOLYTEXTOUTW] = &SYSHOOKS::GenericScan_exit; 342 | win32sysExitHooks[NTGDIDRAWSTREAM] = &SYSHOOKS::GenericScan_exit; 343 | } 344 | 345 | // BluePill 346 | sysEntryHooks[lookupIndex("NtDelayExecution")] = &SYSHOOKS::NtDelayexecution_entry; 347 | sysExitHooks[lookupIndex("NtQueryInformationProcess")] = &SYSHOOKS::NtQueryInformationProcess_exit; 348 | sysExitHooks[lookupIndex("NtQuerySystemInformation")] = &SYSHOOKS::NtQuerySystemInformation_exit; 349 | sysExitHooks[lookupIndex("NtQueryPerformanceCounter")] = &SYSHOOKS::NtQueryPerformanceCounter_exit; 350 | sysEntryHooks[lookupIndex("NtCreateFile")] = &SYSHOOKS::NtCreateFile_entry; 351 | //sysEntryHooks[lookupIndex("NtResumeThread")] = &SYSHOOKS::NtResumeThread_entry; 352 | sysExitHooks[lookupIndex("NtQueryDirectoryObject")] = &SYSHOOKS::NtQueryDirectoryObject_exit; 353 | sysExitHooks[lookupIndex("NtOpenKey")] = &SYSHOOKS::NtOpenKey_exit; 354 | sysExitHooks[lookupIndex("NtOpenKeyEx")] = &SYSHOOKS::NtOpenKey_exit; 355 | sysExitHooks[lookupIndex("NtEnumerateKey")] = &SYSHOOKS::NtEnumerateKey_exit; 356 | sysExitHooks[lookupIndex("NtQueryValueKey")] = &SYSHOOKS::NtQueryValueKey_exit; 357 | sysEntryHooks[lookupIndex("NtQueryAttributesFile")] = &SYSHOOKS::NtQueryAttributesFile_entry; 358 | //sysEntryHooks[lookupIndex("NtOpenDirectoryObject")] = &SYSHOOKS::NtOpenDirectoryObject_entry; 359 | sysExitHooks[lookupIndex("NtQueryObject")] = &SYSHOOKS::NtQueryObject_exit; 360 | //sysExitHooks[lookupIndex("NtGetContextThread")] = &SYSHOOKS::NtGetContextThreadHook; 361 | 362 | // Win32k stuff (embedded ordinal) 363 | win32sysExitHooks[NTUSERENUMDISPLAYDEVICES] = &SYSHOOKS::NtUserEnumDisplayDevices_exit; 364 | win32sysExitHooks[NTUSERFINDWINDOWSEX] = &SYSHOOKS::NtUserFindWindowEx_exit; 365 | 366 | // register analysis callbacks for Pin 367 | PIN_AddSyscallEntryFunction(&SyscallEntry, NULL); 368 | PIN_AddSyscallExitFunction(&SyscallExit, NULL); 369 | } 370 | 371 | } -------------------------------------------------------------------------------- /pintool/src/winheaders.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace W { 4 | #include "windows.h" 5 | #include 6 | #include "Winternl.h" 7 | #include "winnt.h" 8 | #include "Intsafe.h" 9 | #include "OAIdl.h" // MEH for W::VARIANT 10 | } 11 | 12 | // constants that depend on Windows version 13 | #define WMIOFFSETEXEC 0x1EBE0 14 | 15 | // constants not immediately found in headers 16 | #define CODEFORINVALIDHANDLE 0xC0000008 17 | #define CODEFORSTATUSPORTNOTSET 0xC0000353 18 | #define NTSTATUS_STATUS_BREAKPOINT 0x80000003L 19 | 20 | // some constants 21 | #define PROCESS_DEBUG_INHERIT 0x00000001 // default for a non-debugged process, used inside HOOKS_NtQueryInformationProcess_exit 22 | #define MAX_ADAPTER_NAME_LENGTH 256 // IP_ADAPTER_INFO 23 | #define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // IP_ADAPTER_INFO 24 | #define MAX_ADAPTER_ADDRESS_LENGTH 8 // IP_ADAPTER_INFO 25 | 26 | // credits https://www.aldeid.com/wiki/PEB-Process-Environment-Block 27 | // and https://www.geoffchappell.com/studies/windows/win32/ntdll/structs/peb/index.htm 28 | typedef struct _PEB32 { 29 | W::BYTE InheritedAddressSpace; 30 | W::BYTE ReadImageFileExecOptions; 31 | W::BYTE BeingDebugged; 32 | W::BYTE padding2[53]; 33 | W::PVOID ApiSetMap; // 0x38 34 | W::BYTE padding3[16]; 35 | W::PVOID ReadOnlySharedMemoryBase; // 0x4c 36 | W::BYTE padding4[8]; 37 | W::PVOID AnsiCodePageData; // 0x58 38 | W::PVOID OemCodePageData; 39 | W::PVOID UnicodeCaseTableData; 40 | W::ULONG NumberOfProcessors; 41 | W::ULONG NtGlobalFlag; // 0x68 42 | W::BYTE padding5[36]; 43 | W::PVOID ProcessHeaps; // 0x90 44 | W::PVOID GdiSharedHandleTable; // 0x94 45 | W::BYTE padding6[336]; 46 | W::PVOID pShimData; 47 | W::BYTE padding7[12]; 48 | W::PVOID ActivationContextData; 49 | W::BYTE padding8[4]; 50 | W::PVOID SystemDefaultActivationContextData; 51 | W::BYTE padding9[52]; 52 | W::PVOID pContextData; 53 | W::BYTE padding10[4]; 54 | W::BYTE padding11[4]; // DCD added to account for TracingFlags on Win7 55 | } PEB32, *PPEB32; 56 | 57 | // credits: Rolf Rolles http://terminus.rewolf.pl/terminus/structures/ntdll/_PEB_x64.html 58 | typedef struct _PEB64 { 59 | W::BYTE padding1[2]; // pad 0x1 60 | W::BYTE BeingDebugged; // @0x02 byte 61 | W::BYTE padding2[0x68 - 3]; // pad 0x65 62 | W::BYTE ptr_ApiSetMap[8]; // @0x68 63 | W::BYTE padding3[0x88 - 0x70]; // pad 0x18 64 | W::BYTE ptr_ReadOnlySharedMemoryBase[8]; // @0x88 65 | W::BYTE padding4[0xA0 - 0x90]; // pad 0x10 66 | W::BYTE ptr_AnsiCodePageData[8]; // @0xA0 67 | W::BYTE padding5a[0xB8 - 0xA8]; // pad 0x10 68 | W::BYTE NumberOfProcessors[4]; // @OxB8 dword 69 | W::BYTE NtGlobalFlag[4]; // @OxBC dword 70 | W::BYTE padding5[0x2D8 - 0xC0]; // pad 0x218 71 | // DCD: ProcessHeaps and GdiSharedHandleTable are unused 72 | W::BYTE ptr_pShimData[8]; // @0x2D8 73 | W::BYTE padding7[0x2F8 - 0x2E0]; // pad 0x18 74 | W::BYTE ptr_ActivationContextData[8]; // @0x2F8 75 | W::BYTE padding8[0x308 - 0x300]; // pad 0x8 76 | W::BYTE ptr_SystemDefaultActivationContextData[8]; // @0x308 77 | W::BYTE padding9[0x368 - 0x310]; // pad 0x58 78 | W::BYTE ptr_pContextData[8]; // @0x368 79 | W::BYTE padding10[4 + 0x37C - 0x370]; // pImageHeaderHash + TracingFlags + 4-byte padding for alignment 80 | } PEB64, *PPEB64; 81 | 82 | 83 | typedef struct _PROCESS_BASIC_INFORMATION { 84 | W::NTSTATUS ExitStatus; 85 | W::PPEB PebBaseAddress; 86 | W::ULONG_PTR AffinityMask; 87 | W::LONG BasePriority; 88 | W::HANDLE UniqueProcessId; 89 | W::HANDLE InheritedFromUniqueProcessId; 90 | } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; 91 | 92 | typedef struct { 93 | char String[4 * 4]; 94 | } IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING; 95 | 96 | typedef struct _IP_ADDR_STRING { 97 | struct _IP_ADDR_STRING *Next; 98 | IP_ADDRESS_STRING IpAddress; 99 | IP_MASK_STRING IpMask; 100 | W::DWORD Context; 101 | } IP_ADDR_STRING, *PIP_ADDR_STRING; 102 | 103 | typedef struct _IP_ADAPTER_INFO { 104 | struct _IP_ADAPTER_INFO *Next; 105 | W::DWORD ComboIndex; 106 | char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; 107 | char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; 108 | W::UINT AddressLength; 109 | W::BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; 110 | W::DWORD Index; 111 | W::UINT Type; 112 | W::UINT DhcpEnabled; 113 | PIP_ADDR_STRING CurrentIpAddress; 114 | IP_ADDR_STRING IpAddressList; 115 | IP_ADDR_STRING GatewayList; 116 | IP_ADDR_STRING DhcpServer; 117 | W::BOOL HaveWins; 118 | IP_ADDR_STRING PrimaryWinsServer; 119 | IP_ADDR_STRING SecondaryWinsServer; 120 | time_t LeaseObtained; 121 | time_t LeaseExpires; 122 | } IP_ADAPTER_INFO, *PIP_ADAPTER_INFO; 123 | 124 | // More data structures that we found here and there 125 | // TODO look up sources again and give proper credit 126 | 127 | typedef struct _OBJECT_HANDLE_FLAG_INFORMATION { 128 | W::BOOLEAN Inherit; 129 | W::BOOLEAN ProtectFromClose; 130 | } OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION; 131 | 132 | typedef struct _SYSTEM_PROCESS_INFO { 133 | W::ULONG NextEntryOffset; 134 | W::ULONG NumberOfThreads; 135 | W::LARGE_INTEGER Reserved[3]; 136 | W::LARGE_INTEGER CreateTime; 137 | W::LARGE_INTEGER UserTime; 138 | W::LARGE_INTEGER KernelTime; 139 | W::UNICODE_STRING ImageName; 140 | W::ULONG BasePriority; 141 | W::HANDLE ProcessId; 142 | W::HANDLE InheritedFromProcessId; 143 | } SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO; 144 | 145 | typedef struct _KEY_BASIC_INFORMATION { 146 | W::LARGE_INTEGER LastWriteTime; 147 | W::ULONG TitleIndex; 148 | W::ULONG NameLength; 149 | W::WCHAR Name[1]; 150 | } KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; 151 | 152 | typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION { 153 | SystemFirmwareTable_Enumerate, 154 | SystemFirmwareTable_Get 155 | } SYSTEM_FIRMWARE_TABLE_ACTION, *PSYSTEM_FIRMWARE_TABLE_ACTION; 156 | 157 | typedef struct _OBJECT_DIRECTORY_INFORMATION { 158 | W::UNICODE_STRING Name; 159 | W::UNICODE_STRING TypeName; 160 | } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; 161 | 162 | typedef enum _KEY_INFORMATION_CLASS { 163 | KeyBasicInformation = 0, 164 | KeyNodeInformation = 1, 165 | KeyFullInformation = 2, 166 | KeyNameInformation = 3, 167 | KeyCachedInformation = 4, 168 | KeyFlagsInformation = 5, 169 | KeyVirtualizationInformation = 6, 170 | KeyHandleTagsInformation = 7, 171 | MaxKeyInfoClass = 8 172 | } KEY_INFORMATION_CLASS; 173 | 174 | typedef struct _OBJECT_TYPE_INFORMATION { 175 | W::UNICODE_STRING TypeName; 176 | W::ULONG TotalNumberOfHandles; 177 | W::ULONG TotalNumberOfObjects; 178 | }OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; 179 | 180 | typedef struct _OBJECT_ALL_INFORMATION { 181 | W::ULONG NumberOfObjects; 182 | OBJECT_TYPE_INFORMATION ObjectTypeInformation[1]; 183 | }OBJECT_ALL_INFORMATION, *POBJECT_ALL_INFORMATION; 184 | 185 | typedef enum _KEY_VALUE_INFORMATION_CLASS { 186 | KeyValueBasicInformation = 0, 187 | KeyValueFullInformation, 188 | KeyValuePartialInformation, 189 | KeyValueFullInformationAlign64, 190 | KeyValuePartialInformationAlign64, 191 | MaxKeyValueInfoClass 192 | } KEY_VALUE_INFORMATION_CLASS; 193 | 194 | typedef struct _OBJECT_ATTRIBUTES { 195 | W::ULONG Length; 196 | W::HANDLE RootDirectory; 197 | W::PUNICODE_STRING ObjectName; 198 | W::ULONG Attributes; 199 | W::PVOID SecurityDescriptor; 200 | W::PVOID SecurityQualityOfService; 201 | } OBJECT_ATTRIBUTES; 202 | typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; 203 | 204 | typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION { 205 | W::ULONG ProviderSignature; 206 | SYSTEM_FIRMWARE_TABLE_ACTION Action; 207 | W::ULONG TableID; 208 | W::ULONG TableBufferLength; 209 | W::UCHAR TableBuffer[ANYSIZE_ARRAY]; 210 | } SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; 211 | 212 | typedef struct _RTL_PROCESS_MODULE_INFORMATION { 213 | W::HANDLE Section; // DCD was: HANDLE 214 | W::PVOID MappedBase; 215 | W::PVOID ImageBase; 216 | W::ULONG ImageSize; 217 | W::ULONG Flags; 218 | W::USHORT LoadOrderIndex; 219 | W::USHORT InitOrderIndex; 220 | W::USHORT LoadCount; 221 | W::USHORT OffsetToFileName; 222 | W::UCHAR FullPathName[256]; 223 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 224 | 225 | typedef struct _RTL_PROCESS_MODULES { 226 | W::ULONG NumberOfModules; 227 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 228 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 229 | 230 | typedef enum _PROCESSINFOCLASS { 231 | ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION 232 | ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX 233 | ProcessIoCounters, // q: IO_COUNTERS 234 | ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 235 | ProcessTimes, // q: KERNEL_USER_TIMES 236 | ProcessBasePriority, // s: KPRIORITY 237 | ProcessRaisePriority, // s: ULONG 238 | ProcessDebugPort, // q: HANDLE 239 | ProcessExceptionPort, // s: HANDLE 240 | ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN 241 | ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 242 | ProcessLdtSize, // s: PROCESS_LDT_SIZE 243 | ProcessDefaultHardErrorMode, // qs: ULONG 244 | ProcessIoPortHandlers, // (kernel-mode only) 245 | ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS 246 | ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void 247 | ProcessUserModeIOPL, 248 | ProcessEnableAlignmentFaultFixup, // s: BOOLEAN 249 | ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS 250 | ProcessWx86Information, 251 | ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 252 | ProcessAffinityMask, // s: KAFFINITY 253 | ProcessPriorityBoost, // qs: ULONG 254 | ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX 255 | ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION 256 | ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND 257 | ProcessWow64Information, // q: ULONG_PTR 258 | ProcessImageFileName, // q: UNICODE_STRING 259 | ProcessLUIDDeviceMapsEnabled, // q: ULONG 260 | ProcessBreakOnTermination, // qs: ULONG 261 | ProcessDebugObjectHandle, // q: HANDLE // 30 262 | ProcessDebugFlags, // qs: ULONG 263 | ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables 264 | ProcessIoPriority, // qs: IO_PRIORITY_HINT 265 | ProcessExecuteFlags, // qs: ULONG 266 | ProcessResourceManagement, 267 | ProcessCookie, // q: ULONG 268 | ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION 269 | ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA 270 | ProcessPagePriority, // q: ULONG 271 | ProcessInstrumentationCallback, // 40 272 | ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX 273 | ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] 274 | ProcessImageFileNameWin32, // q: UNICODE_STRING 275 | ProcessImageFileMapping, // q: HANDLE (input) 276 | ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE 277 | ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE 278 | ProcessGroupInformation, // q: USHORT[] 279 | ProcessTokenVirtualizationEnabled, // s: ULONG 280 | ProcessConsoleHostProcess, // q: ULONG_PTR 281 | ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 282 | ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 283 | ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION 284 | ProcessDynamicFunctionTableInformation, 285 | ProcessHandleCheckingMode, 286 | ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION 287 | ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION 288 | ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL 289 | ProcessHandleTable, // since WINBLUE 290 | ProcessCheckStackExtentsMode, 291 | ProcessCommandLineInformation, // q: UNICODE_STRING // 60 292 | ProcessProtectionInformation, // q: PS_PROTECTION 293 | ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD 294 | ProcessFaultInformation, // PROCESS_FAULT_INFORMATION 295 | ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION 296 | ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION 297 | ProcessDefaultCpuSetsInformation, 298 | ProcessAllowedCpuSetsInformation, 299 | ProcessSubsystemProcess, 300 | ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO 301 | ProcessInPrivate, // since THRESHOLD2 // 70 302 | ProcessRaiseUMExceptionOnInvalidHandleClose, 303 | ProcessIumChallengeResponse, 304 | ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION 305 | ProcessHighGraphicsPriorityInformation, 306 | ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 307 | ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES 308 | ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE 309 | ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY 310 | ProcessWin32kSyscallFilterInformation, 311 | ProcessDisableSystemAllowedCpuSets, 312 | ProcessWakeInformation, // PROCESS_WAKE_INFORMATION 313 | ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE 314 | ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 315 | ProcessCaptureTrustletLiveDump, 316 | ProcessTelemetryCoverage, 317 | ProcessEnclaveInformation, 318 | ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION 319 | ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION 320 | ProcessImageSection, 321 | MaxProcessInfoClass 322 | } PROCESSINFOCLASS; 323 | 324 | enum _SYSTEM_INFORMATION_CLASS { 325 | SystemBasicInformation = 0x0000, 326 | SystemProcessorInformation = 0x0001, 327 | SystemPerformanceInformation = 0x0002, 328 | SystemTimeOfDayInformation = 0x0003, 329 | SystemPathInformation = 0x0004, 330 | SystemProcessInformation = 0x0005, 331 | SystemCallCountInformation = 0x0006, 332 | SystemDeviceInformation = 0x0007, 333 | SystemProcessorPerformanceInformation = 0x0008, 334 | SystemFlagsInformation = 0x0009, 335 | SystemCallTimeInformation = 0x000A, 336 | SystemModuleInformation = 0x000B, 337 | SystemLocksInformation = 0x000C, 338 | SystemStackTraceInformation = 0x000D, 339 | SystemPagedPoolInformation = 0x000E, 340 | SystemNonPagedPoolInformation = 0x000F, 341 | SystemHandleInformation = 0x0010, 342 | SystemObjectInformation = 0x0011, 343 | SystemPageFileInformation = 0x0012, 344 | SystemVdmInstemulInformation = 0x0013, 345 | SystemVdmBopInformation = 0x0014, 346 | SystemFileCacheInformation = 0x0015, 347 | SystemPoolTagInformation = 0x0016, 348 | SystemInterruptInformation = 0x0017, 349 | SystemDpcBehaviorInformation = 0x0018, 350 | SystemFullMemoryInformation = 0x0019, 351 | SystemLoadGdiDriverInformation = 0x001A, 352 | SystemUnloadGdiDriverInformation = 0x001B, 353 | SystemTimeAdjustmentInformation = 0x001C, 354 | SystemSummaryMemoryInformation = 0x001D, 355 | SystemMirrorMemoryInformation = 0x001E, 356 | SystemPerformanceTraceInformation = 0x001F, 357 | SystemCrashDumpInformation = 0x0020, 358 | SystemExceptionInformation = 0x0021, 359 | SystemCrashDumpStateInformation = 0x0022, 360 | SystemKernelDebuggerInformation = 0x0023, 361 | SystemContextSwitchInformation = 0x0024, 362 | SystemRegistryQuotaInformation = 0x0025, 363 | SystemExtendServiceTableInformation = 0x0026, 364 | SystemPrioritySeperation = 0x0027, 365 | SystemVerifierAddDriverInformation = 0x0028, 366 | SystemVerifierRemoveDriverInformation = 0x0029, 367 | SystemProcessorIdleInformation = 0x002A, 368 | SystemLegacyDriverInformation = 0x002B, 369 | SystemCurrentTimeZoneInformation = 0x002C, 370 | SystemLookasideInformation = 0x002D, 371 | SystemTimeSlipNotification = 0x002E, 372 | SystemSessionCreate = 0x002F, 373 | SystemSessionDetach = 0x0030, 374 | SystemSessionInformation = 0x0031, 375 | SystemRangeStartInformation = 0x0032, 376 | SystemVerifierInformation = 0x0033, 377 | SystemVerifierThunkExtend = 0x0034, 378 | SystemSessionProcessInformation = 0x0035, 379 | SystemLoadGdiDriverInSystemSpace = 0x0036, 380 | SystemNumaProcessorMap = 0x0037, 381 | SystemPrefetcherInformation = 0x0038, 382 | SystemExtendedProcessInformation = 0x0039, 383 | SystemRecommendedSharedDataAlignment = 0x003A, 384 | SystemComPlusPackage = 0x003B, 385 | SystemNumaAvailableMemory = 0x003C, 386 | SystemProcessorPowerInformation = 0x003D, 387 | SystemEmulationBasicInformation = 0x003E, 388 | SystemEmulationProcessorInformation = 0x003F, 389 | SystemExtendedHandleInformation = 0x0040, 390 | SystemLostDelayedWriteInformation = 0x0041, 391 | SystemBigPoolInformation = 0x0042, 392 | SystemSessionPoolTagInformation = 0x0043, 393 | SystemSessionMappedViewInformation = 0x0044, 394 | SystemHotpatchInformation = 0x0045, 395 | SystemObjectSecurityMode = 0x0046, 396 | SystemWatchdogTimerHandler = 0x0047, 397 | SystemWatchdogTimerInformation = 0x0048, 398 | SystemLogicalProcessorInformation = 0x0049, 399 | SystemWow64SharedInformationObsolete = 0x004A, 400 | SystemRegisterFirmwareTableInformationHandler = 0x004B, 401 | SystemFirmwareTableInformation = 0x004C, 402 | SystemModuleInformationEx = 0x004D, 403 | SystemVerifierTriageInformation = 0x004E, 404 | SystemSuperfetchInformation = 0x004F, 405 | SystemMemoryListInformation = 0x0050, 406 | SystemFileCacheInformationEx = 0x0051, 407 | SystemThreadPriorityClientIdInformation = 0x0052, 408 | SystemProcessorIdleCycleTimeInformation = 0x0053, 409 | SystemVerifierCancellationInformation = 0x0054, 410 | SystemProcessorPowerInformationEx = 0x0055, 411 | SystemRefTraceInformation = 0x0056, 412 | SystemSpecialPoolInformation = 0x0057, 413 | SystemProcessIdInformation = 0x0058, 414 | SystemErrorPortInformation = 0x0059, 415 | SystemBootEnvironmentInformation = 0x005A, 416 | SystemHypervisorInformation = 0x005B, 417 | SystemVerifierInformationEx = 0x005C, 418 | SystemTimeZoneInformation = 0x005D, 419 | SystemImageFileExecutionOptionsInformation = 0x005E, 420 | SystemCoverageInformation = 0x005F, 421 | SystemPrefetchPatchInformation = 0x0060, 422 | SystemVerifierFaultsInformation = 0x0061, 423 | SystemSystemPartitionInformation = 0x0062, 424 | SystemSystemDiskInformation = 0x0063, 425 | SystemProcessorPerformanceDistribution = 0x0064, 426 | SystemNumaProximityNodeInformation = 0x0065, 427 | SystemDynamicTimeZoneInformation = 0x0066, 428 | SystemCodeIntegrityInformation = 0x0067, 429 | SystemProcessorMicrocodeUpdateInformation = 0x0068, 430 | SystemProcessorBrandString = 0x0069, 431 | SystemVirtualAddressInformation = 0x006A, 432 | SystemLogicalProcessorAndGroupInformation = 0x006B, 433 | SystemProcessorCycleTimeInformation = 0x006C, 434 | SystemStoreInformation = 0x006D, 435 | SystemRegistryAppendString = 0x006E, 436 | SystemAitSamplingValue = 0x006F, 437 | SystemVhdBootInformation = 0x0070, 438 | SystemCpuQuotaInformation = 0x0071, 439 | SystemNativeBasicInformation = 0x0072, 440 | SystemErrorPortTimeouts = 0x0073, 441 | SystemLowPriorityIoInformation = 0x0074, 442 | SystemBootEntropyInformation = 0x0075, 443 | SystemVerifierCountersInformation = 0x0076, 444 | SystemPagedPoolInformationEx = 0x0077, 445 | SystemSystemPtesInformationEx = 0x0078, 446 | SystemNodeDistanceInformation = 0x0079, 447 | SystemAcpiAuditInformation = 0x007A, 448 | SystemBasicPerformanceInformation = 0x007B, 449 | SystemQueryPerformanceCounterInformation = 0x007C, 450 | SystemSessionBigPoolInformation = 0x007D, 451 | SystemBootGraphicsInformation = 0x007E, 452 | SystemScrubPhysicalMemoryInformation = 0x007F, 453 | SystemBadPageInformation = 0x0080, 454 | SystemProcessorProfileControlArea = 0x0081, 455 | SystemCombinePhysicalMemoryInformation = 0x0082, 456 | SystemEntropyInterruptTimingInformation = 0x0083, 457 | SystemConsoleInformation = 0x0084, 458 | SystemPlatformBinaryInformation = 0x0085, 459 | SystemThrottleNotificationInformation = 0x0086, 460 | SystemHypervisorProcessorCountInformation = 0x0087, 461 | SystemDeviceDataInformation = 0x0088, 462 | SystemDeviceDataEnumerationInformation = 0x0089, 463 | SystemMemoryTopologyInformation = 0x008A, 464 | SystemMemoryChannelInformation = 0x008B, 465 | SystemBootLogoInformation = 0x008C, 466 | SystemProcessorPerformanceInformationEx = 0x008D, 467 | SystemSpare0 = 0x008E, 468 | SystemSecureBootPolicyInformation = 0x008F, 469 | SystemPageFileInformationEx = 0x0090, 470 | SystemSecureBootInformation = 0x0091, 471 | SystemEntropyInterruptTimingRawInformation = 0x0092, 472 | SystemPortableWorkspaceEfiLauncherInformation = 0x0093, 473 | SystemFullProcessInformation = 0x0094, 474 | MaxSystemInfoClass = 0x0095 475 | }; --------------------------------------------------------------------------------