反调试总结
目錄
PEB:
函數(shù)檢測(cè):
數(shù)據(jù)檢測(cè):
PEB:
?利用PEB結(jié)構(gòu)體信息可以判斷當(dāng)前進(jìn)程是否處于被調(diào)試狀態(tài)。其中與反調(diào)試密切相關(guān)的成員。
+0x002 BeingDebugged : UChar 調(diào)試標(biāo)志
+0x00c Ldr : Ptr32 _PEB_LDR_DATA 進(jìn)程加載模塊鏈表
+0x018 ProcessHeap : Ptr32 Void
+0x068 NtGlobalFlag : Uint4B
函數(shù)檢測(cè):
sDebuggerPresent():?
函數(shù)檢測(cè)就是通過 Windows 自帶的公開或未公開的函數(shù)直接檢測(cè)程序是否處于調(diào)試狀態(tài)。最簡(jiǎn)單的調(diào)試器檢測(cè)函數(shù)是 I
IsDebuggerPresent():API獲取PEB.BeingDebugged的值來判斷是否處于被調(diào)試狀態(tài)。進(jìn)程處于被調(diào)試狀態(tài)時(shí),PEB.BeingDebugged的值被設(shè)置為1,反之為0.
方法一:
我們?nèi)绾瓮ㄟ^此類反調(diào)試:首先查看其匯編形式
?將這里的jnz改為jz,我們就可以順利通過,再次反編譯結(jié)果如下 。
方法二:用OD將PEB.BeingDebugged 改為0.
PEB的結(jié)構(gòu)指針存儲(chǔ)在TEB中,fs:[0x18]存儲(chǔ)著TEB結(jié)構(gòu)指針,fs:[0x30]存儲(chǔ)著PEB結(jié)構(gòu)指針。
Ctrl+G跳轉(zhuǎn)到fs:[0x30]處。PEB的首地址為0x314000,跳轉(zhuǎn)到fs:[0x30]+2處,也就是BeingDebugged,ctrl+E組合鍵修改為“00”.
?原理定位peb
pbDebuggerPresent
BOOL WINAPI CheckRemoteDebuggerPresent(_In_ HANDLE hProcess,_Inout_ PBOOL pbDebuggerPresent );如果?hProcess?句柄表示的進(jìn)程處于調(diào)試上下文,則設(shè)置?pbDebuggerPresent?變量被設(shè)置為?TRUE,否則被設(shè)置為?FALSE。
方法:直接修改isDebuggerPresent的值或修改跳轉(zhuǎn)條件來繞過。?
NtQueryInformationProcess:
NTSTATUS WINAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle,_In_ PROCESSINFOCLASS ProcessInformationClass,_Out_ PVOID ProcessInformation,_In_ ULONG ProcessInformationLength,_Out_opt_ PULONG ReturnLength );第二個(gè)參數(shù)?ProcessInformationClass?給定了需要查詢的進(jìn)程信息類型。當(dāng)給定值為?0(ProcessBasicInformation)或?7(ProcessDebugPort)時(shí),就能得到相關(guān)調(diào)試信息,返回信息會(huì)寫到第三個(gè)參數(shù)?ProcessInformation?指向的緩沖區(qū)中。
?ProcessDebugPor:
未公開的ntdll的NtQueryInformationProcess()函數(shù)接受一個(gè)信息類的參數(shù)用于查詢.?ProcessDebugPort(7)是其中的一個(gè)信息類.進(jìn)程處于調(diào)試狀態(tài)時(shí),系統(tǒng)就會(huì)為他分配一個(gè)調(diào)試端口。ProcessInformationClass參數(shù)設(shè)置為?ProcessDebugPor(0x7)時(shí),調(diào)用NtQueryInformationProcess()函數(shù)就能獲取調(diào)試端口。若進(jìn)程處于非調(diào)試狀態(tài),則變量dwDebugPort的值設(shè)置為0,反之為1。
ProcessDebugObjectHandle:
Windows XP 引入了debug對(duì)象, 當(dāng)一個(gè)調(diào)試會(huì)話啟動(dòng), 會(huì)同時(shí)創(chuàng)建一個(gè)debug對(duì)象以及與之關(guān)聯(lián)的句柄. 我們可以使用ProcessDebugObjectHandle (0x1e)類來查詢這個(gè)句柄的值
ProcessDebugFlags:
檢測(cè)Debug Flags(調(diào)試標(biāo)志)的值也可以判斷進(jìn)程是否處于被調(diào)試狀態(tài)。函數(shù)的第二個(gè)參數(shù)設(shè)置為ProcessDebugFlags(Ox1F)時(shí),調(diào)用函數(shù)后通過第三個(gè)參數(shù)即可獲取調(diào)試標(biāo)志的值:若為0,則進(jìn)程處于被調(diào)試狀態(tài);若為1,則進(jìn)程處于非調(diào)試狀態(tài)。
ZwSetInformationThread:
利用ZwSetInformationThread()API,被調(diào)試者可將自身從調(diào)試器中分離出來。ZwSetInformationThread()函數(shù)是一個(gè)系統(tǒng)原生APl ( System Native API),顧名思義,它是用來為線程設(shè)置信息的。該函數(shù)擁有2個(gè)參數(shù),第一個(gè)參數(shù)ThreadHandle用來接收當(dāng)前線程的句柄,第二個(gè)參數(shù)ThreadInformationClass表示線程信息類型,若其值設(shè)置為ThreadHideFrom-Debugger(Ox11),調(diào)用該函數(shù)后,調(diào)試進(jìn)程就會(huì)被分離出來。ZwSetInformationThread()API不會(huì)對(duì)正常運(yùn)行的程序
數(shù)據(jù)檢測(cè):
調(diào)試進(jìn)程時(shí),PEB.NtGlobalFlagd的值會(huì)被設(shè)置為0x70.
?我的方法是attach匯編
?方法二:用OD的CommandLine插件
在判斷前下斷點(diǎn),打開CommandLine插件用dump fs:[30]+0x68dump 出NtGlobalFlag的內(nèi)容
右鍵選擇Binary->Fill with 00's將值0x70替換為0x00即可.、
時(shí)間差檢測(cè):
GetTickCount會(huì)返回啟動(dòng)到現(xiàn)在的毫秒數(shù), 循環(huán)里光是sleep(1)就進(jìn)行了 100 次, 也就是 100 毫秒. 兩次得到的時(shí)間作差如果大于 1000 毫秒, 時(shí)差明顯大于所耗的時(shí)間, 也就間接檢測(cè)到了調(diào)試.
我們可以通過修改判斷的時(shí)間來跳過這個(gè)反調(diào)試。?
ETC:
我們應(yīng)用反調(diào)試技術(shù)的目的在于防止程序遭受逆向分析。不必非得為此費(fèi)力判斷自身進(jìn)程是否處于被調(diào)試狀態(tài)。一個(gè)更簡(jiǎn)單、更好的方法是,判斷當(dāng)前系統(tǒng)是否為逆向分析專用系統(tǒng)(非常規(guī)系統(tǒng)),若是,則直接停止程序。這樣就出現(xiàn)了各種各樣的反調(diào)試技術(shù),這些技術(shù)都能從系統(tǒng)中輕松獲取各種信息(進(jìn)程、文件、窗口、注冊(cè)表、主機(jī)名、計(jì)算機(jī)名、用戶名、環(huán)境變量等)。這些反調(diào)試技術(shù)通常借助Win32API獲取系統(tǒng)信息來具體實(shí)現(xiàn)。
例如:
BOOL CheckDebug() {if (FindWindowA("OllyDbg", 0)){return 0;}return 1; } 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
- 上一篇: 花指令记录
- 下一篇: D3ctf-D3MUG(u3d