静态反调试技术(1)
文章目錄
- 聲明
- 靜態反調試目的
- 注意
- PEB
- https://blog.csdn.net/CSNN2019/article/details/113113347
- BeingDebugged(+0x2)
- 破解之法:
- Ldr(0xc)
- 破解之法:
- ProcessHeap(+0x18)
- Flags(0xC)&Force Flags(+0x10)
- 破解之法:
- NtGlobalFlag(+0x68)
- 破解之法
- 調試程序代碼
- 反調試技術系列:
聲明
靜態反調試目的
被調試的進程用靜態反調試技術來偵測自身是否處于被調試狀態,若偵測到處于被調試的狀態,則執行非常規代碼(主要是終止代碼)來阻止。具體的實現方法包括調試器檢測方法,調試環境檢測方法,強制隔離調試器的方法等等。反調試破解方法主要用來從探測代碼獲取信息,然后修改信息本身使反調試技術失效。
注意
許多靜態反調試技術對OS具有很強的依懶性。這意味著靜態反調試技術在Windows XP 系統下可以正常使用,而在Windows Vista/7操作系統中可能失效
接下來的東西需要用到以下知識,請自行查看:
PEB
https://blog.csdn.net/CSNN2019/article/details/113113347
+0x002 BeingDebugged : UChar+0x00c Ldr : Ptr32 _PEB_LDR_DATA+0x018 ProcessHeap : Ptr32 Void+0x068 NtGlobalFlag : Uint4BBeingDebugged(+0x2)
kernel32.dll中有個名Kernel32!IsDebuggerPresent()的API,但普通的應用程序開發中并不常用:
BOOL WINAPI IsDebuggerPresent()該API就是用來判斷當前進程是否處于調試狀態,并返回判斷結果。而該API就是通過檢測PEB.BeingDebugged成員來確定是否正在調試程序(是,則返回1;否,則返回0)。
老辦法,查看一下OD:
代碼如下:
提示:
Windows 7中,IsDebuggerPresent()API是在Kernelbase.dll中實現的。而在Windows XP 及以前版本的操作系統中,它是在kernel32.dll中。
先獲取FS:[30]地址,即PEB地址,然后通過[PEB+2]訪問BeingDebugged
這里取出來的是0的原因呢,是因為吾愛破解OD太強悍了,加了很多插件。。。
慢慢關閉就行,用原版OD或者IDA就能返回1。
破解之法:
用吾愛破解的OD(滑稽。。哈哈),用OD 的編輯功能把BeingDebugged改為0即可。
Ldr(0xc)
調試進程時,其堆內存區域中就會出現一些特殊標識,表示它正處于被調試狀態。其中未使用的堆內存區域全部填充著0xEEFEEEFE,這證明正在調試進程。利用這點可判斷進程正在被調試。
PEB.Ldr成員是一個指向_ PEB_ LDR DATA結構體的指針,而 PEB_ LDR _DATA結構體恰好是在堆里面創建的,所以掃描該區域即了輕松查找是否存在0xEEFEEEFE區域
PEB起始地址為0x3D2000,然后指針指向的區域是0x7710DCA0
我看了一下,我的沒有。。。有的堆內存中,如果往下拖動滑動條,會看到填充著0xEEFEEEFE的區域。。
破解之法:
只要將填充著0xEEFEEEFE值的區域全部覆寫為NULL即可
提示:
該方法僅僅適用于Windows XP系統,而在Windows Vista 以后的系統中則無法使用。另外,利用附加功能的將運行中的進程附加調試器時,堆內存中并不出現上述標識
ProcessHeap(+0x18)
PEB.ProcessHeap(+0x18)成員是指向HEAP結構體的指針
+0x000 Entry :_HEAP_ENTRY +0x008 Signature :Unit4B +0x00c Flags :Unit4B +0x010 ForceFlags :Unit4B +0x014 VirtualMemoryThreshold :Unit4B +0x018 SegmentReserve :Unit4B +0x01c SegmentCommit :Unit4B +0x020 DeCommitFreeBlockThreshold :Unit4B ……………………………………………………………………以上列出了HEAP結構體的部分成員,進程處于調試狀態時,Flags(+0xC)與ForceFlags成員(+0x10)被設置為特定值
GetprocessHeap():
PEB.ProcessHeap成員(+0x18)既可以從PEB結構體直接獲取,也可以通過GetprocessHeap()API獲取。下面看看GetprocessHeap()API的代碼
直接PEB—>PEB.ProcessHeap順序訪問
PEB.ProcessHeap=0x6B0000
Flags(0xC)&Force Flags(+0x10)
進程正常運行(非調試運行)時,Heap.Flags成員(+0xC)的值02,Heap.ForceFlags成員(+0x10)值為0。進程處于被調試狀態時,這些值也會隨之改變。
注意:
1.這里我用的是吾愛破解版的OD,插件比較多,內存單元里的值不能作參考。。。
2.該方法僅在Windows XP系統中有效,Windows 7系統則保留ForceFlags屬性和Flags屬性。此外,將運行中的進程附加到調試器時,也不會出現上述特征。
所以,比較這些值,就可以判斷進程是否處于被調試狀態。
破解之法:
只要將Heap.Flags成員(+0xC)的值設置成02,Heap.ForceFlags成員(+0x10)值設置成0。
NtGlobalFlag(+0x68)
調試進程時,PEB.NtGlobalFlag成員(+0x68)的值會被設置0x70。所以,檢測該成員的值即可判斷進程是否處于被調試狀態。
NtGlobalFlag 0x70是下列Flags進行bit OR(位或)運算的結果
FLG_HEAP_ENABLE_TAIL_CHECK (0x10) FLG_HEAP_ENABLE_FREE_CHECK (0x20) FLG_HEAP_VALIDATE_PARAMETERS (0x40)
被調試進程的堆內存中存在(不同于非調試運行進程的)特別標識,因此在PEB.NtGlobalFlag成員中添加了上述標志。(注意:這個OD的插件太多了。。。)
注意:
將運行的進程附加到調試器時,PEB.NtGlobalFlag的值不變
破解之法
重設PEB.NtGlobalFlag值為0即可(PEB.NtGlobalFlag=0).
strongOD->Options中的HidePEB可以繞過。
調試程序代碼
#include "stdio.h" #include "windows.h" #include "tchar.h"void PEB() {HMODULE hMod = NULL;FARPROC pProc = NULL;LPBYTE pTEB = NULL;LPBYTE pPEB = NULL;BOOL bIsDebugging = FALSE;//<span style="color:#ff0000;">[pPEB+0x2]==0x1</span>// IsDebuggerPresent()bIsDebugging = IsDebuggerPresent();printf("IsDebuggerPresent() = %d\n", bIsDebugging);if( bIsDebugging ) printf(" => Debugging!!!\n\n");else printf(" => Not debugging...\n\n");// Ldr xp特有pProc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCurrentTeb");pTEB = (LPBYTE)(*pProc)(); // address of TEBpPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30); // address of PEBprintf("PEB.Ldr\n");DWORD pLdrSig[4] = { 0xEEFEEEFE, 0xEEFEEEFE, 0xEEFEEEFE, 0xEEFEEEFE };LPBYTE pLdr = (LPBYTE)*(LPDWORD)(<span style="color:#ff0000;">pPEB+0xC</span>);__try {while( TRUE ){if( !memcmp(pLdr, pLdrSig, sizeof(pLdrSig)) ){printf(" => Debugging!!!\n\n");break;}pLdr++;}}__except (EXCEPTION_EXECUTE_HANDLER){printf(" => Not debugging...\n\n");}// Process Heap - Flags xp特有bIsDebugging = FALSE;LPBYTE pHeap = (LPBYTE)*(LPDWORD)(<span style="color:#ff0000;">pPEB+0x18</span>);DWORD dwFlags = *(LPDWORD)(<span style="color:#ff0000;">pHeap+0xC</span>);printf("PEB.ProcessHeap.Flags = 0x%X\n", dwFlags);if( dwFlags != 0x2 ) printf(" => Debugging!!!\n\n");else printf(" => Not debugging...\n\n");// Process Heap - ForceFlags xp特有bIsDebugging = FALSE;DWORD dwForceFlags = *(LPDWORD)(<span style="color:#ff0000;">pHeap+0x10</span>);printf("PEB.ProcessHeap.ForceFlags = 0x%X\n", dwForceFlags);if( dwForceFlags != 0x0 ) printf(" => Debugging!!!\n\n");else printf(" => Not debugging...\n\n");// NtGlobalFlagbIsDebugging = FALSE;DWORD dwNtGlobalFlag = *(LPDWORD)(<span style="color:#ff0000;">pPEB+0x68</span>);printf("PEB.NtGlobalFlag = 0x%X\n", dwNtGlobalFlag);if( (dwNtGlobalFlag & 0x70) == 0x70 ) printf(" => Debugging!!!\n\n");else printf(" => Not debugging...\n\n"); }int _tmain(int argc, TCHAR* argv[]) {PEB();printf("\npress any key to quit...\n");_gettch();return 0; }反調試技術系列:
靜態反調試技術(1)https://blog.csdn.net/CSNN2019/article/details/113105292
靜態反調試技術(2)https://blog.csdn.net/CSNN2019/article/details/113147820
靜態反調試技術(3)https://blog.csdn.net/CSNN2019/article/details/113178232
動態反調試技術 https://blog.csdn.net/CSNN2019/article/details/113181558
高級反調試技術 https://blog.csdn.net/CSNN2019/article/details/113263215
總結
以上是生活随笔為你收集整理的静态反调试技术(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 详解虚函数的实现过程之菱形继承(5)
- 下一篇: 静态反调试技术(2)