91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++的反調試技術與繞過方法

發布時間:2021-06-24 09:00:58 來源:億速云 閱讀:143 作者:chen 欄目:開發技術

這篇文章主要介紹“C++的反調試技術與繞過方法”,在日常操作中,相信很多人在C++的反調試技術與繞過方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C++的反調試技術與繞過方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

反調試技術的實現方式有很多,最簡單的一種實現方式莫過于直接調用Windows系統提供給我們的API函數,這些API函數中有些專門用來檢測調試器的,有些則是可被改造為用于探測調試器是否存在的工具,多數情況下,調用系統API函數實現反調試是不明智的,原因很簡單,目標主機通常會安裝主動防御系統,而作為主動防御產品默認會加載RootKit驅動掛鉤這些敏感函數的使用,如果被非法調用則會提示錯誤信息,病毒作者通常會使用匯編自行實現這些類似于系統提供給我們的反調試函數,并不會使用系統的API,這樣依附于API的主動防御的系統將會失效。

1.加載調試符號鏈接文件并放入d:/symbols目錄下.

0:000> .sympath srv*d:\symbols*http://msdl.microsoft.com/download/symbols
0:000> .reload
Reloading current modules

2.位于fs:[0x30]的位置就是PEB結構的指針,接著我們分析如何得到的該指針,并通過通配符找到TEB結構的名稱.

0:000> dt ntdll!*teb*
          ntdll!_TEB
          ntdll!_GDI_TEB_BATCH
          ntdll!_TEB_ACTIVE_FRAME
          ntdll!_TEB_ACTIVE_FRAME_CONTEXT
          ntdll!_TEB_ACTIVE_FRAME_CONTEXT

3.接著可通過dt命令,查詢下ntdll!_TEB結構,如下可看到0x30處ProcessEnvironmentBlock存放的正是PEB結構.

0:000> dt -rv ntdll!_TEB
struct _TEB, 66 elements, 0xfb8 bytes
   +0x000 NtTib            : struct _NT_TIB, 8 elements, 0x1c bytes                  # NT_TIB結構
   +0x018 Self             : Ptr32 to struct _NT_TIB, 8 elements, 0x1c bytes         # NT_TIB結構
   +0x020 ClientId         : struct _CLIENT_ID, 2 elements, 0x8 bytes                # 保存進程與線程ID
   +0x02c ThreadLocalStoragePointer : Ptr32 to Void
   +0x030 ProcessEnvironmentBlock : Ptr32 to struct _PEB, 65 elements, 0x210 bytes   # PEB結構

偏移地址0x18是_NT_TIB結構,也就是指向自身偏移0x0的位置.

0:000> r $teb
$teb=7ffdf000

0:000> dd $teb+0x18
7ffdf018  7ffdf000 00000000 00001320 00000c10
7ffdf028  00000000 00000000 7ffd9000 00000000

而!teb地址加0x30正是PEB的位置,可以使用如下命令驗證.

0:000> dd $teb+0x30
7ffdf030  7ffd9000 00000000 00000000 00000000
7ffdf040  00000000 00000000 00000000 00000000

0:000> !teb
TEB at 7ffdf000
    ExceptionList:        0012fd0c
    StackBase:            00130000
    StackLimit:           0012e000
    SubSystemTib:         00000000
    FiberData:            00001e00
    ArbitraryUserPointer: 00000000
    Self:                 7ffdf000
    EnvironmentPointer:   00000000
    ClientId:             00001320 . 00000c10
    RpcHandle:            00000000
    Tls Storage:          00000000
    PEB Address:          7ffd9000               # 此處teb地址

上方的查詢結果可得知偏移位置fs:[0x18]正是TEB的基址TEB:7ffdf000

0:000> dd fs:[0x18]
003b:00000018  7ffdf000 00000000 000010f4 00000f6c
003b:00000028  00000000 00000000 7ffda000 00000000

0:000> dt _teb 0x7ffdf000
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID         # 這里保存進程與線程信息

0:000> dt _CLIENT_ID 0x7ffdf000                 # 查看進程詳細結構
ntdll!_CLIENT_ID
   +0x000 UniqueProcess    : 0x0012fd0c Void    # 獲取進程PID
   +0x004 UniqueThread     : 0x00130000 Void    # 獲取線程PID

上方TEB首地址我們知道是fs:[0x18],接著我們通過以下公式計算得出本進程的進程ID.

在Windows系統中如果想要獲取到PID進程號,可以使用NtCurrentTeb()這個系統API來實現,但這里我們手動實現該API的獲取過程.

獲取進程PID:

#include "stdafx.h"
#include <Windows.h>

DWORD GetPid(){
	DWORD dwPid=0;
	__asm
	{
		mov eax,fs:[0x18]    // 獲取PEB地址
		add eax,0x20         // 加0x20得到進程PID
		mov eax,[eax]
		mov dwPid,eax
	}
	return dwPid;
}

int main()
{
	printf("%d\n",GetPid());
    return 0;
}

獲取線程PID:

#include "stdafx.h"
#include <Windows.h>

DWORD GetPid(){
	DWORD dwPid=0;
	__asm
	{
		mov eax,fs:[0x18]    // 獲取PEB地址
		add eax,0x20         // 加0x20得到進程PID
		add eax,0x04         // 加0x04得到線程PID
		mov eax,[eax]
		mov dwPid,eax
	}
	return dwPid;
}

int main()
{
    printf("%d\n",GetPid());
    return 0;
}

通過標志反調試:

下方的調試標志BeingDebugged是Char類型,為1表示調試狀態.為0表示沒有調試.可以用于反調試.

0:000> dt _peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 SpareBool        : UChar
   +0x004 Mutant           : Ptr32 Void
#include "stdafx.h"
#include <Windows.h>

int main()
{
    DWORD dwIsDebug = 0;
    __asm
    {
        mov eax, fs:[0x18];      // 獲取TEB  
        mov eax, [eax + 0x30];   // 獲取PEB
        movzx eax, [eax + 2];    // 獲取調試標志
        mov dwIsDebug,eax
    }

    if (1 == dwIsDebug)
    {
        printf("正在被調試");
    }
    else
    {
        printf("沒有被調試");
    }
    return 0;
}

通過API反調試:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int main()
{
    STARTUPINFO temp;
    temp.cb = sizeof(temp);
    GetStartupInfo(&temp);

    if (temp.dwFlags != 1)
    {
        ExitProcess(0);
    }
    printf("程序沒有被反調試");
    return 0;
}

反調試與繞過思路

BeingDebugged 屬性反調試:

進程運行時,位置FS:[30h]指向PEB的基地址,為了實現反調試技術,惡意代碼通過這個位置來檢查BeingDebugged標志位是否為1,如果為1則說明進程被調試。

1.首先我們可以使用 dt _teb 命令解析一下TEB的結構,如下TEB結構的起始偏移為0x0,而0x30的位置指向的是 ProcessEnvironmentBlock 也就是指向了進程環境塊。

0:000> dt _teb
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : Ptr32 Void
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : Ptr32 Void
   +0x02c ThreadLocalStoragePointer : Ptr32 Void
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB       // 此處是進程環境塊
   +0x034 LastErrorValue   : Uint4B
   +0x038 CountOfOwnedCriticalSections : Uint4B
   +0x03c CsrClientThread  : Ptr32 Void
   +0x040 Win32ThreadInfo  : Ptr32 Void
   +0x044 User32Reserved   : [26] Uint4B
   +0x0ac UserReserved     : [5] Uint4B
   +0x0c0 WOW32Reserved    : Ptr32 Void

只需要在進程環境塊的基礎上 +0x2 就能定位到線程環境塊TEB中 BeingDebugged 的標志,此處的標志位如果為1則說明程序正在被調試,為0則說明沒有被調試。

0:000> dt _peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 BitField         : UChar
   +0x003 ImageUsesLargePages : Pos 0, 1 Bit
   +0x003 IsProtectedProcess : Pos 1, 1 Bit

我們手動來驗證一下,首先線程環境塊地址是007f1000在此基礎上加0x30即可得到進程環境快的基地址007ee000繼續加0x2即可得到BeingDebugged的狀態 ffff0401 需要 byte=1

0:000> r $teb
$teb=007f1000

0:000> dd 007f1000 + 0x30
007f1030  007ee000 00000000 00000000 00000000
007f1040  00000000 00000000 00000000 00000000

0:000> r $peb
$peb=007ee000

0:000> dd 007ee000 + 0x2
007ee002  ffff0401 0000ffff 0c400112 19f0775f
007ee012  0000001b 00000000 09e0001b 0000775f

梳理一下知識點我們可以寫出一下反調試代碼,本代碼單獨運行程序不會出問題,一旦被調試器附加則會提示正在被調試。

#include <stdio.h>
#include <windows.h>

int main()
{
	BYTE IsDebug = 0;
	__asm{
		mov eax, dword ptr fs:[0x30]
		mov bl, byte ptr [eax+ 0x2]
		mov IsDebug, bl
	}
	/* 另一種反調試實現方式
	__asm{
		push dword ptr fs:[0x30]
		pop edx
		mov al, [edx + 2]
		mov IsDebug,al
	}
	*/

	if (IsDebug != 0)
		printf("本程序正在被調試. %d", IsDebug);
	else
		printf("程序沒有被調試.");
	getchar();
	return 0;
}

如果惡意代碼中使用該種技術阻礙我們正常調試,該如何繞過呢?如下我們只需要在命令行中執行dump fs:[30]+2來定位到BeingDebugged的位置,并將其數值改為0然后運行程序,會發現反調試已經被繞過了。

C++的反調試技術與繞過方法

ProcessHeap 屬性反調試:

該屬性是一個未公開的屬性,它被設置為加載器為進程分配的第一個堆的位置,ProcessHeap位于PEB結構的0x18處,第一個堆頭部有一個屬性字段,這個屬性叫做ForceFlags和Flags屬性偏移為10,該屬性為0說明程序沒有被調試,非0則說明被調試。

0:000> dt !_peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x018 ProcessHeap      : Ptr32 Void
   +0x01c FastPebLock      : Ptr32 _RTL_CRITICAL_SECTION

0:000> r $peb
$peb=006e1000

0:000> dd 006e1000+18
006e1018  00ca0000 775f09e0 00000000 00000000

0:000> dd 00ca0000 + 10
00ca0010  00ca00a4 00ca00a4 00ca0000 00ca0000

要實現反反調試,只需要將 00ca0000 + 10 位置的值修改為0即可,執行dump ds:[fs:[30] + 0x18] + 0x10 定位到修改即可。

到此,關于“C++的反調試技術與繞過方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

南岸区| 枝江市| 库伦旗| 临朐县| 忻州市| 香港| 会理县| 从化市| 灌云县| 伽师县| 京山县| 安泽县| 清新县| 华蓥市| 萝北县| 四川省| 德令哈市| 平定县| 彭泽县| 丰顺县| 望都县| 邳州市| 巴林左旗| 依安县| 高清| 芒康县| 田东县| 安远县| 台湾省| 威信县| 卢氏县| 安泽县| 乡城县| 洪泽县| 社会| 峡江县| 镇原县| 遂宁市| 延吉市| 深州市| 昌宁县|