日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows反调试技术全攻略

發(fā)布時(shí)間:2024/1/1 windows 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows反调试技术全攻略 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在調(diào)試一些病毒程序的時(shí)候,可能會(huì)碰到一些反調(diào)試技術(shù),也就是說,被調(diào)試的程序可以檢測到自己是否被調(diào)試器附加了,如果探知自己正在被調(diào)試,肯定是有人試圖反匯編啦之類的方法破解自己。為了了解如何破解反調(diào)試技術(shù),首先我們來看看反調(diào)試技術(shù)。一、Windows API方法Win32提供了兩個(gè)API, IsDebuggerPresent和CheckRemoteDebuggerPresent可以用來檢測當(dāng)前進(jìn)程是否正在被調(diào)試,以IsDebuggerPresent函數(shù)為例,例子如下:BOOL ret = IsDebuggerPresent(); printf("ret = %d\n", ret);破解方法很簡單,就是在系統(tǒng)里將這兩個(gè)函數(shù)hook掉,讓這兩個(gè)函數(shù)一直返回false就可以了,網(wǎng)上有很多做hook API工作的工具,也有很多工具源代碼是開放的,所以這里就不細(xì)談了。二、查詢進(jìn)程PEB的BeingDebugged標(biāo)志位當(dāng)進(jìn)程被調(diào)試器所附加的時(shí)候,操作系統(tǒng)會(huì)自動(dòng)設(shè)置這個(gè)標(biāo)志位,因此在程序里定期查詢這個(gè)標(biāo)志位就可以了,例子如下:bool PebIsDebuggedApproach() {char result = 0;__asm{// 進(jìn)程的PEB地址放在fs這個(gè)寄存器位置上mov eax, fs:[30h]// 查詢BeingDebugged標(biāo)志位mov al, BYTE PTR [eax + 2] mov result, al}return result != 0; }三、查詢進(jìn)程PEB的NtGlobal標(biāo)志位 跟第二個(gè)方法一樣,當(dāng)進(jìn)程被調(diào)試的時(shí)候,操作系統(tǒng)除了修改BeingDebugged這個(gè)標(biāo)志位以外,還會(huì)修改其他幾個(gè)地方,其中NtDll中一些控制堆(Heap)操作的函數(shù)的標(biāo)志位就會(huì)被修改,因此也可以查詢這個(gè)標(biāo)志位,例子如下:bool PebNtGlobalFlagsApproach() {int result = 0;__asm{// 進(jìn)程的PEBmov eax, fs:[30h]// 控制堆操作函數(shù)的工作方式的標(biāo)志位mov eax, [eax + 68h]// 操作系統(tǒng)會(huì)加上這些標(biāo)志位FLG_HEAP_ENABLE_TAIL_CHECK, // FLG_HEAP_ENABLE_FREE_CHECK and FLG_HEAP_VALIDATE_PARAMETERS,// 它們的并集就是x70//// 下面的代碼相當(dāng)于C/C++的// eax = eax & 0x70and eax, 0x70mov result, eax}return result != 0; }四、查詢進(jìn)程堆的一些標(biāo)志位這個(gè)方法是第三個(gè)方法的變種,只要進(jìn)程被調(diào)試,進(jìn)程在堆上分配的內(nèi)存,在分配的堆的頭信息里,ForceFlags這個(gè)標(biāo)志位會(huì)被修改,因此可以通過判斷這個(gè)標(biāo)志位的方式來反調(diào)試。因?yàn)檫M(jìn)程可以有很多的堆,因此只要檢查任意一個(gè)堆的頭信息就可以了,所以這個(gè)方法貌似很強(qiáng)大,例子如下:bool HeapFlagsApproach() {int result = 0;__asm{// 進(jìn)程的PEBmov eax, fs:[30h]// 進(jìn)程的堆,我們隨便訪問了一個(gè)堆,下面是默認(rèn)的堆mov eax, [eax + 18h]// 檢查ForceFlag標(biāo)志位,在沒有被調(diào)試的情況下應(yīng)該是mov eax, [eax + 10h]mov result, eax}return result != 0; }五、使用NtQueryInformationProcess函數(shù)NtQueryInformationProcess函數(shù)是一個(gè)未公開的API,它的第二個(gè)參數(shù)可以用來查詢進(jìn)程的調(diào)試端口。如果進(jìn)程被調(diào)試,那么返回的端口值會(huì)是-1,否則就是其他的值。由于這個(gè)函數(shù)是一個(gè)未公開的函數(shù),因此需要使用LoadLibrary和GetProceAddress的方法獲取調(diào)用地址,示例代碼如下:// 聲明一個(gè)函數(shù)指針。 typedef NTSTATUS (WINAPI *NtQueryInformationProcessPtr)(HANDLE processHandle,PROCESSINFOCLASS processInformationClass,PVOID processInformation,ULONG processInformationLength,PULONG returnLength);bool NtQueryInformationProcessApproach() {int debugPort = 0;HMODULE hModule = LoadLibrary(TEXT("Ntdll.dll "));NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hModule, "NtQueryInformationProcess");if ( NtQueryInformationProcess(GetCurrentProcess(), (PROCESSINFOCLASS)7, &debugPort, sizeof(debugPort), NULL) )printf("[ERROR NtQueryInformationProcessApproach] NtQueryInformationProcess failed\n");elsereturn debugPort == -1;return false; }六、NtSetInformationThread方法這個(gè)也是使用Windows的一個(gè)未公開函數(shù)的方法,你可以在當(dāng)前線程里調(diào)用NtSetInformationThread,調(diào)用這個(gè)函數(shù)時(shí),如果在第二個(gè)參數(shù)里指定0x11這個(gè)值(意思是ThreadHideFromDebugger),等于告訴操作系統(tǒng),將所有附加的調(diào)試器統(tǒng)統(tǒng)取消掉。示例代碼:// 聲明一個(gè)函數(shù)指針。 typedef NTSTATUS (*NtSetInformationThreadPtr)(HANDLE threadHandle,THREADINFOCLASS threadInformationClass,PVOID threadInformation,ULONG threadInformationLength);void NtSetInformationThreadApproach() {HMODULE hModule = LoadLibrary(TEXT("ntdll.dll"));NtSetInformationThreadPtr NtSetInformationThread = (NtSetInformationThreadPtr)GetProcAddress(hModule, "NtSetInformationThread");NtSetInformationThread(GetCurrentThread(), (THREADINFOCLASS)0x11, 0, 0); }七、觸發(fā)異常的方法這個(gè)技術(shù)的原理是,首先,進(jìn)程使用SetUnhandledExceptionFilter函數(shù)注冊一個(gè)未處理異常處理函數(shù)A,如果進(jìn)程沒有被調(diào)試的話,那么觸發(fā)一個(gè)未處理異常,會(huì)導(dǎo)致操作系統(tǒng)將控制權(quán)交給先前注冊的函數(shù)A;而如果進(jìn)程被調(diào)試的話,那么這個(gè)未處理異常會(huì)被調(diào)試器捕捉,這樣我們的函數(shù)A就沒有機(jī)會(huì)運(yùn)行了。這里有一個(gè)技巧,就是觸發(fā)未處理異常的時(shí)候,如果跳轉(zhuǎn)回原來代碼繼續(xù)執(zhí)行,而不是讓操作系統(tǒng)關(guān)閉進(jìn)程。方案是在函數(shù)A里修改eip的值,因?yàn)樵诤瘮?shù)A的參數(shù)_EXCEPTION_POINTERS里,會(huì)保存當(dāng)時(shí)觸發(fā)異常的指令地址,所以在函數(shù)A里根據(jù)這個(gè)指令地址修改寄存器eip的值就可以了,示例代碼如下:// 進(jìn)程要注冊的未處理異常處理程序A LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pei) {SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)pei->ContextRecord->Eax);// 修改寄存器eip的值pei->ContextRecord->Eip += 2;// 告訴操作系統(tǒng),繼續(xù)執(zhí)行進(jìn)程剩余的指令(指令保存在eip里),而不是關(guān)閉進(jìn)程return EXCEPTION_CONTINUE_EXECUTION; }bool UnhandledExceptionFilterApproach() {SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);__asm{// 將eax清零xor eax, eax// 觸發(fā)一個(gè)除零異常div eax}return false; }八、調(diào)用DeleteFiber函數(shù)如果給DeleteFiber函數(shù)傳遞一個(gè)無效的參數(shù)的話,DeleteFiber函數(shù)除了會(huì)拋出一個(gè)異常以外,還是將進(jìn)程的LastError值設(shè)置為具體出錯(cuò)原因的代號(hào)。然而,如果進(jìn)程正在被調(diào)試的話,這個(gè)LastError值會(huì)被修改,因此如果調(diào)試器繞過了第七步里講的反調(diào)試技術(shù)的話,我們還可以通過驗(yàn)證LastError值是不是被修改過來檢測調(diào)試器的存在,示例代碼:bool DeleteFiberApproach() {char fib[1024] = {0};// 會(huì)拋出一個(gè)異常并被調(diào)試器捕獲DeleteFiber(fib);// 0x57的意思是ERROR_INVALID_PARAMETERreturn (GetLastError() != 0x57); }

?

總結(jié)

以上是生活随笔為你收集整理的Windows反调试技术全攻略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。