Debug Hook
- 命名
關(guān)于這個(gè)命名是我自己這樣說(shuō)的,至于這種HOOK技術(shù),先前在一個(gè)開源項(xiàng)目中叫做RemoteHook,我比較喜歡自己的這種命名,所以就叫Debug Hook。如果有錯(cuò)誤,請(qǐng)指出。
-
先來(lái)說(shuō)說(shuō)調(diào)試的原理
在Windows操作系統(tǒng),有兩種方法可以來(lái)調(diào)試一個(gè)進(jìn)程。
1: CreateProcess()
可以使用此函數(shù)來(lái)啟動(dòng)調(diào)試一個(gè)進(jìn)程。
CreateProcess(FileFullPath,NULL,NULL,NULL, false,DEBUG_PROCESS |DEBUG_ONLY_THIS_PROCESS| CREATE_NEW_CONSOLE, NULL,NULL,&StartupInfo,&ProcessInfo)2:DebugActiveProcess(ProcessID)
?可以使用此函數(shù)來(lái)附加到一個(gè)進(jìn)程來(lái)進(jìn)行調(diào)試。
我們使用以上兩種方法中的任何一種方法來(lái)調(diào)試一個(gè)進(jìn)程,每當(dāng)被調(diào)試進(jìn)程發(fā)生調(diào)試事件的時(shí)候,OS都會(huì)暫停其運(yùn)行。并向調(diào)試器報(bào)告相應(yīng)的事件,調(diào)試器處理之后就可以繼續(xù)運(yùn)行。
-
利用調(diào)試技術(shù)來(lái)HOOK API函數(shù)的相關(guān)步驟如下
?
利用調(diào)試技術(shù)來(lái)HOOK API函數(shù)的相關(guān)步驟如下
1對(duì)想要鉤取的進(jìn)程進(jìn)行附加操作,使之成為被調(diào)試者。
2將要鉤取的API的起始地址的第一個(gè)字節(jié)修改為0xcc(或者使用硬件斷點(diǎn))。
3當(dāng)調(diào)用目標(biāo)API的時(shí)候,控制權(quán)就轉(zhuǎn)移到調(diào)試器進(jìn)程。
4執(zhí)行需要的操作。
5脫鉤,將API 函數(shù)的第一個(gè)字節(jié)恢復(fù)。
6運(yùn)行相應(yīng)的API。
1 #include<Windows.h> 2 #include<iostream> 3 #include<stdio.h> 4 5 using namespace std; 6 7 LPVOID WriteFileAddress = NULL; 8 CREATE_PROCESS_DEBUG_INFO CreateProcessDebugInfomation; 9 BYTE INT3 = 0xCC, OldByte = 0; 10 11 BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde) 12 { 13 // WriteFile()函數(shù)地址 14 WriteFileAddress = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile"); 15 16 // API Hook - WriteFile() 17 //將WriteFile函數(shù)的首個(gè)字節(jié)改為0xcc 18 memcpy(&CreateProcessDebugInfomation, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO)); 19 ReadProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress, 20 &OldByte, sizeof(BYTE), NULL); 21 WriteProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress, 22 &INT3, sizeof(BYTE), NULL); 23 24 return TRUE; 25 } 26 27 BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pDebugEvent) 28 { 29 CONTEXT Context; 30 PBYTE lpBuffer = NULL; 31 DWORD dwNumOfBytesToWrite, dwAddrOfBuffer, i; 32 PEXCEPTION_RECORD pExceptionRecord = &pDebugEvent->u.Exception.ExceptionRecord; 33 34 // BreakPoint exception 35 if( EXCEPTION_BREAKPOINT == pExceptionRecord->ExceptionCode ) 36 { 37 // 發(fā)生異常的地方是否為我們要鉤取的函數(shù) 38 if( WriteFileAddress == pExceptionRecord->ExceptionAddress ) 39 { 40 // #1. Unhook 41 // 先恢復(fù),以免進(jìn)入死循環(huán) 42 WriteProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress, 43 &OldByte, sizeof(BYTE), NULL); 44 45 // #2. 獲得線程上下背景文 為了修改EIp的值,來(lái)使進(jìn)程恢復(fù)正常運(yùn)行 46 Context.ContextFlags = CONTEXT_CONTROL; 47 GetThreadContext(CreateProcessDebugInfomation.hThread, &Context); 48 49 // #3. WriteFile() 根據(jù)ESP來(lái)獲得WriteFile 函數(shù)的參數(shù),以達(dá)到修改數(shù)據(jù)的目的 50 51 ReadProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)(Context.Esp + 0x8), 52 &dwAddrOfBuffer, sizeof(DWORD), NULL); 53 54 ReadProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)(Context.Esp + 0xC), 55 &dwNumOfBytesToWrite, sizeof(DWORD), NULL); 56 57 // #4. 58 lpBuffer = (PBYTE)malloc(dwNumOfBytesToWrite+1); 59 memset(lpBuffer, 0, dwNumOfBytesToWrite+1); 60 61 // #5. WriteFile() 62 ReadProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)dwAddrOfBuffer, 63 lpBuffer, dwNumOfBytesToWrite, NULL); 64 printf("\n### original string ###\n%s\n", lpBuffer); 65 66 // #6. 修改數(shù)據(jù) 67 for( i = 0; i < dwNumOfBytesToWrite; i++ ) 68 { 69 if( 0x61 <= lpBuffer[i] && lpBuffer[i] <= 0x7A ) 70 lpBuffer[i] -= 0x20; 71 } 72 73 printf("\n### converted string ###\n%s\n", lpBuffer); 74 75 // #7. 調(diào)用原函數(shù) 76 WriteProcessMemory(CreateProcessDebugInfomation.hProcess, (LPVOID)dwAddrOfBuffer, 77 lpBuffer, dwNumOfBytesToWrite, NULL); 78 79 80 free(lpBuffer); 81 82 // 設(shè)置EIP的值來(lái)實(shí)現(xiàn)正常運(yùn)行,注意EIP的值為0xcc的下一條指令的地址。 83 Context.Eip = (DWORD)WriteFileAddress; 84 SetThreadContext(CreateProcessDebugInfomation.hThread, &Context); 85 86 // 運(yùn)行 87 ContinueDebugEvent(pDebugEvent->dwProcessId, pDebugEvent->dwThreadId, DBG_CONTINUE); 88 Sleep(0); 89 90 // 再次鉤取 91 WriteProcessMemory(CreateProcessDebugInfomation.hProcess, WriteFileAddress, 92 &INT3, sizeof(BYTE), NULL); 93 94 return TRUE; 95 } 96 } 97 98 return FALSE; 99 } 100 101 void DebugLoop() 102 { 103 DEBUG_EVENT DebugEvent; 104 DWORD dwContinueStatus; 105 106 // 等待調(diào)試事件 107 while( WaitForDebugEvent(&DebugEvent, INFINITE) ) 108 { 109 dwContinueStatus = DBG_CONTINUE; 110 111 // 調(diào)試事件為創(chuàng)建進(jìn)程 112 if( CREATE_PROCESS_DEBUG_EVENT == DebugEvent.dwDebugEventCode ) 113 { 114 OnCreateProcessDebugEvent(&DebugEvent); 115 } 116 // 調(diào)試事件 117 else if( EXCEPTION_DEBUG_EVENT == DebugEvent.dwDebugEventCode ) 118 { 119 if( OnExceptionDebugEvent(&DebugEvent) ) 120 continue; 121 } 122 // 調(diào)試進(jìn)程退出 123 else if( EXIT_PROCESS_DEBUG_EVENT == DebugEvent.dwDebugEventCode ) 124 { 125 126 break; 127 } 128 129 130 ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, dwContinueStatus); 131 } 132 } 133 134 int main(int argc, char* argv[]) 135 { 136 DWORD dwProcessID; 137 cout << "Input ProcessID" << endl; 138 cin >> dwProcessID; 139 140 // Attach Process 141 142 if( !DebugActiveProcess(dwProcessID) ) 143 { 144 printf("DebugActiveProcess(%d) failed!!!\n" 145 "Error Code = %d\n", dwProcessID, GetLastError()); 146 return 1; 147 } 148 149 // 調(diào)試事件循環(huán) 150 DebugLoop(); 151 152 return 0; 153 }參考《逆向工程核心原理》
轉(zhuǎn)載于:https://www.cnblogs.com/banchen/p/6696562.html
總結(jié)
以上是生活随笔為你收集整理的Debug Hook的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 程序猜价格c语言,C语言大作业:编写菜单
- 下一篇: jQuery之效果