前言

和老手聊起PEB在反调试中常用的几个点, 做个试验.
前段时间玩cm, 打掉反调试还是挺费时间的. 熟练之后就好了:)
反调试手段挺多的, 应该有几百种吧, 如果没见过, 看行为选择是否NOP掉.
遇到反调试时,调试器的使用状态或cm运行结果应该会有不同的.
调试器有反应好弄, 总能找到让调试器失灵的点.
要是让运行结果不对, 那应该不太好找.

记录

查看PEB

双机调试看到的TEB不对, 可能附加有问题吧.
直接在WinXp虚拟机中装了x86版的windbg, 在菜单上附加正在运行的notepad.exe

0:001> dg @fs
                                  P Si Gr Pr Lo
Sel    Base     Limit     Type    l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0038 7ffde000 00000fff Data RW Ac 3 Bg By P  Nl 000004f3

fs:[0]是_NT_TIB地址, 地址是7ffde000

0:001> dd fs:[0]
0038:00000000  00acffe4 00ad0000 00acf000 00000000
0038:00000010  00001e00 00000000 7ffde000 00000000
0038:00000020  000007cc 000001b8 00000000 00000000
0038:00000030  7ffd3000 00000000 00000000 00000000
0038:00000040  00000000 00000000 00000000 00000000
0038:00000050  00000000 00000000 00000000 00000000
0038:00000060  00000000 00000000 00000000 00000000
0038:00000070  00000000 00000000 00000000 00000000
0:001> dd 7ffde000
7ffde000  00acffe4 00ad0000 00acf000 00000000
7ffde010  00001e00 00000000 7ffde000 00000000
7ffde020  000007cc 000001b8 00000000 00000000
7ffde030  7ffd3000 00000000 00000000 00000000
7ffde040  00000000 00000000 00000000 00000000
7ffde050  00000000 00000000 00000000 00000000
7ffde060  00000000 00000000 00000000 00000000
7ffde070  00000000 00000000 00000000 00000000

0:001> dt _NT_TIB 7ffde000
ntdll!_NT_TIB
   +0x000 ExceptionList    : 0x00acffe4 _EXCEPTION_REGISTRATION_RECORD
   +0x004 StackBase        : 0x00ad0000 Void
   +0x008 StackLimit       : 0x00acf000 Void
   +0x00c SubSystemTib     : (null) 
   +0x010 FiberData        : 0x00001e00 Void
   +0x010 Version          : 0x1e00
   +0x014 ArbitraryUserPointer : (null) 
   +0x018 Self             : 0x7ffde000 _NT_TIB

[TIB + 0x18]中是 _TEB的地址
0:001> dt _TEB 7ffde000
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : (null) 
   +0x030 ProcessEnvironmentBlock : 0x7ffd3000 _PEB
   +0x034 LastErrorValue   : 0
   +0x038 CountOfOwnedCriticalSections : 0
   +0x03c CsrClientThread  : (null) 
   +0x040 Win32ThreadInfo  : (null) 
   +0x044 User32Reserved   : [26] 0
   +0x0ac UserReserved     : [5] 0
   +0x0c0 WOW32Reserved    : (null) 
   +0x0c4 CurrentLocale    : 0x804
   +0x0c8 FpSoftwareStatusRegister : 0
   +0x0cc SystemReserved1  : [54] (null) 
   +0x1a4 ExceptionCode    : 0n0
   +0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
   +0x1bc SpareBytes1      : [24]  ""
   +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
   +0x6b4 RealClientId     : _CLIENT_ID
   +0x6bc GdiCachedProcessHandle : (null) 
   +0x6c0 GdiClientPID     : 0
   +0x6c4 GdiClientTID     : 0
   +0x6c8 GdiThreadLocalInfo : (null) 
   +0x6cc Win32ClientInfo  : [62] 0
   +0x7c4 glDispatchTable  : [233] (null) 
   +0xb68 glReserved1      : [29] 0
   +0xbdc glReserved2      : (null) 
   +0xbe0 glSectionInfo    : (null) 
   +0xbe4 glSection        : (null) 
   +0xbe8 glTable          : (null) 
   +0xbec glCurrentRC      : (null) 
   +0xbf0 glContext        : (null) 
   +0xbf4 LastStatusValue  : 0
   +0xbf8 StaticUnicodeString : _UNICODE_STRING ""
   +0xc00 StaticUnicodeBuffer : [261] 0
   +0xe0c DeallocationStack : 0x00ac0000 Void
   +0xe10 TlsSlots         : [64] (null) 
   +0xf10 TlsLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0xf18 Vdm              : (null) 
   +0xf1c ReservedForNtRpc : (null) 
   +0xf20 DbgSsReserved    : [2] (null) 
   +0xf28 HardErrorsAreDisabled : 0
   +0xf2c Instrumentation  : [16] (null) 
   +0xf6c WinSockData      : (null) 
   +0xf70 GdiBatchCount    : 0
   +0xf74 InDbgPrint       : 0 ''
   +0xf75 FreeStackOnTermination : 0 ''
   +0xf76 HasFiberData     : 0 ''
   +0xf77 IdealProcessor   : 0 ''
   +0xf78 Spare3           : 0
   +0xf7c ReservedForPerf  : (null) 
   +0xf80 ReservedForOle   : (null) 
   +0xf84 WaitingOnLoaderLock : 0
   +0xf88 Wx86Thread       : _Wx86ThreadState
   +0xf94 TlsExpansionSlots : (null) 
   +0xf98 ImpersonationLocale : 0
   +0xf9c IsImpersonating  : 0
   +0xfa0 NlsCache         : (null) 
   +0xfa4 pShimData        : (null) 
   +0xfa8 HeapVirtualAffinity : 0
   +0xfac CurrentTransactionHandle : (null) 
   +0xfb0 ActiveFrame      : (null) 
   +0xfb4 SafeThunkCall    : 0 ''
   +0xfb5 BooleanSpare     : [3]  ""


[TEB+0x30]中是PEB地址7ffd3000
0:001> dt 0x7ffd3000 _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0x1 ''
   +0x003 SpareBool        : 0 ''
   +0x004 Mutant           : 0xffffffff Void
   +0x008 ImageBaseAddress : 0x01000000 Void
   +0x00c Ldr              : 0x001a1e90 _PEB_LDR_DATA
   +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : (null) 
   +0x018 ProcessHeap      : 0x000a0000 Void
   +0x01c FastPebLock      : 0x7c99d600 _RTL_CRITICAL_SECTION
   +0x020 FastPebLockRoutine : 0x7c921000 Void
   +0x024 FastPebUnlockRoutine : 0x7c9210e0 Void
   +0x028 EnvironmentUpdateCount : 1
   +0x02c KernelCallbackTable : 0x77d12970 Void
   +0x030 SystemReserved   : [1] 0
   +0x034 AtlThunkSListPtr32 : 0
   +0x038 FreeList         : (null) 
   +0x03c TlsExpansionCounter : 0
   +0x040 TlsBitmap        : 0x7c99d5c0 Void
   +0x044 TlsBitmapBits    : [2] 0xfffff
   +0x04c ReadOnlySharedMemoryBase : 0x7f6f0000 Void
   +0x050 ReadOnlySharedMemoryHeap : 0x7f6f0000 Void
   +0x054 ReadOnlyStaticServerData : 0x7f6f0688  -> (null) 
   +0x058 AnsiCodePageData : 0x7ffa0000 Void
   +0x05c OemCodePageData  : 0x7ffa0000 Void
   +0x060 UnicodeCaseTableData : 0x7ffd1000 Void
   +0x064 NumberOfProcessors : 1
   +0x068 NtGlobalFlag     : 0
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER 0xffffe86d`079b8000
   +0x078 HeapSegmentReserve : 0x100000
   +0x07c HeapSegmentCommit : 0x2000
   +0x080 HeapDeCommitTotalFreeThreshold : 0x10000
   +0x084 HeapDeCommitFreeBlockThreshold : 0x1000
   +0x088 NumberOfHeaps    : 9
   +0x08c MaximumNumberOfHeaps : 0x10
   +0x090 ProcessHeaps     : 0x7c99cfc0  -> 0x000a0000 Void
   +0x094 GdiSharedHandleTable : 0x00480000 Void
   +0x098 ProcessStarterHelper : (null) 
   +0x09c GdiDCAttributeList : 0x14
   +0x0a0 LoaderLock       : 0x7c99b178 Void
   +0x0a4 OSMajorVersion   : 5
   +0x0a8 OSMinorVersion   : 1
   +0x0ac OSBuildNumber    : 0xa28
   +0x0ae OSCSDVersion     : 0x300
   +0x0b0 OSPlatformId     : 2
   +0x0b4 ImageSubsystem   : 2
   +0x0b8 ImageSubsystemMajorVersion : 4
   +0x0bc ImageSubsystemMinorVersion : 0
   +0x0c0 ImageProcessAffinityMask : 0
   +0x0c4 GdiHandleBuffer  : [34] 0
   +0x14c PostProcessInitRoutine : (null) 
   +0x150 TlsExpansionBitmap : 0x7c99d5b8 Void
   +0x154 TlsExpansionBitmapBits : [32] 0
   +0x1d4 SessionId        : 0
   +0x1d8 AppCompatFlags   : _ULARGE_INTEGER 0x0
   +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER 0x0
   +0x1e8 pShimData        : (null) 
   +0x1ec AppCompatInfo    : (null) 
   +0x1f0 CSDVersion       : _UNICODE_STRING "Service Pack 3"
   +0x1f8 ActivationContextData : 0x00090000 Void
   +0x1fc ProcessAssemblyStorageMap : 0x000a2f50 Void
   +0x200 SystemDefaultActivationContextData : 0x00080000 Void
   +0x204 SystemAssemblyStorageMap : (null) 
   +0x208 MinimumStackCommit : 0

PEB反调试的点

PEB.BeingDebugged

BOOL fnAntiDebug_PebBeingDebugged()
{
    int iPebBeingDebugged = 0;

    _asm {
        pushfd
        pushad

        // fs:[0x0] is _NT_TIB
        // fs:[0x18] is _NT_TEB
        /**
        0:001> dt 7ffde000 _NT_TIB
        ntdll!_NT_TIB
        +0x000 ExceptionList    : 0x00acffe4 _EXCEPTION_REGISTRATION_RECORD
        +0x004 StackBase        : 0x00ad0000 Void
        +0x008 StackLimit       : 0x00acf000 Void
        +0x00c SubSystemTib     : (null) 
        +0x010 FiberData        : 0x00001e00 Void
        +0x010 Version          : 0x1e00
        +0x014 ArbitraryUserPointer : (null) 
        +0x018 Self             : 0x7ffde000 _NT_TIB
        */
        // fs:x 已经是取内容
        mov eax, fs:0x18 ; addr => _NT_TEB

        /**
        0:001> dt 0x7ffde000 _TEB
        ntdll!_TEB
        +0x000 NtTib            : _NT_TIB
        +0x01c EnvironmentPointer : (null) 
        +0x020 ClientId         : _CLIENT_ID
        +0x028 ActiveRpcHandle  : (null) 
        +0x02c ThreadLocalStoragePointer : (null) 
        +0x030 ProcessEnvironmentBlock : 0x7ffd3000 _PEB
        */
        mov eax, [eax + 0x30] ; _PEB

        /**
        0:001> dt 0x7ffd3000 _PEB
        ntdll!_PEB
        +0x000 InheritedAddressSpace : 0 ''
        +0x001 ReadImageFileExecOptions : 0 ''
        +0x002 BeingDebugged    : 0x1 ''
        */
        movzx eax, BYTE PTR [eax + 0x2] ; _PEB.BeingDebugged
        mov iPebBeingDebugged, eax        

        popad
        popfd
    }

    return (iPebBeingDebugged != 0);
}

Peb.NtGlobalFlag

BOOL fnAntiDebug_PebNtGlobalFlag()
{
    int iPebNtGlobalFlag = 0;

    _asm {
        pushfd
        pushad

        mov eax, fs:0x18 ; addr => _NT_TEB
        mov eax, [eax + 0x30] ; _PEB

        /**
        0:001> dt 0x7ffd3000 _PEB
        ntdll!_PEB
        +0x000 InheritedAddressSpace : 0 ''
        +0x001 ReadImageFileExecOptions : 0 ''
        +0x002 BeingDebugged    : 0x1 ''
        +0x003 SpareBool        : 0 ''
        +0x004 Mutant           : 0xffffffff Void
        +0x008 ImageBaseAddress : 0x01000000 Void
        +0x00c Ldr              : 0x001a1e90 _PEB_LDR_DATA
        +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS
        +0x014 SubSystemData    : (null) 
        +0x018 ProcessHeap      : 0x000a0000 Void
        +0x01c FastPebLock      : 0x7c99d600 _RTL_CRITICAL_SECTION
        +0x020 FastPebLockRoutine : 0x7c921000 Void
        +0x024 FastPebUnlockRoutine : 0x7c9210e0 Void
        +0x028 EnvironmentUpdateCount : 1
        +0x02c KernelCallbackTable : 0x77d12970 Void
        +0x030 SystemReserved   : [1] 0
        +0x034 AtlThunkSListPtr32 : 0
        +0x038 FreeList         : (null) 
        +0x03c TlsExpansionCounter : 0
        +0x040 TlsBitmap        : 0x7c99d5c0 Void
        +0x044 TlsBitmapBits    : [2] 0xfffff
        +0x04c ReadOnlySharedMemoryBase : 0x7f6f0000 Void
        +0x050 ReadOnlySharedMemoryHeap : 0x7f6f0000 Void
        +0x054 ReadOnlyStaticServerData : 0x7f6f0688  -> (null) 
        +0x058 AnsiCodePageData : 0x7ffa0000 Void
        +0x05c OemCodePageData  : 0x7ffa0000 Void
        +0x060 UnicodeCaseTableData : 0x7ffd1000 Void
        +0x064 NumberOfProcessors : 1
        +0x068 NtGlobalFlag     : 0
        +0x070 CriticalSectionTimeout : _LARGE_INTEGER 0xffffe86d`079b8000
        */
        mov al, [eax+68h] ; _PEB.NtGlobalFlag
        and al, 70h
        cmp al, 70h
        jne NOT_ON_DEBUG_ENV

        mov eax, 1
        mov iPebNtGlobalFlag, eax

NOT_ON_DEBUG_ENV:
        popad
        popfd
    }

    return (iPebNtGlobalFlag != 0);
}

Peb.ProcessHeap

BOOL fnAntiDebug_PebProcessHeap()
{
    int iOnDebugDev = 0;
    DWORD dwVer = GetVersion();

    _asm {
        pushfd
        pushad

        ; 确定 _PEB.ProcessHeap 后面多少偏移是调试标记
        mov eax, dwVer ; 0x1db10106
        cmp al, 6
        cmc ; Inverts Carry Flag
        sbb ebx, ebx
        and ebx, 34h

        mov eax, fs:0x18 ; addr => _NT_TEB
        mov eax, [eax + 0x30] ; _PEB

        /**
        0:001> dt 0x7ffd3000 _PEB
        ntdll!_PEB
        +0x000 InheritedAddressSpace : 0 ''
        +0x001 ReadImageFileExecOptions : 0 ''
        +0x002 BeingDebugged    : 0x1 ''
        +0x003 SpareBool        : 0 ''
        +0x004 Mutant           : 0xffffffff Void
        +0x008 ImageBaseAddress : 0x01000000 Void
        +0x00c Ldr              : 0x001a1e90 _PEB_LDR_DATA
        +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS
        +0x014 SubSystemData    : (null) 
        +0x018 ProcessHeap      : 0x000a0000 Void
        */
        mov eax, [eax+18h] ; _PEB.ProcessHeap

        ; ForceFlags
        ; HEAP_TAIL_CHECKING_ENABLED
        ; HEAP_FREE_CHECKING_ENABLED
        ; HEAP_VALIDATE_PARAMETERS_ENABLED
        cmp [eax+ebx+10h], 40000060h

        jne NOT_ON_DEBUG_ENV

        mov eax, 1
        mov iOnDebugDev, eax

NOT_ON_DEBUG_ENV:
        popad
        popfd
    }

    return (iOnDebugDev != 0);
}

Heap’s Content On Peb.ProcessHeap

整理了2个版本, 检测原理 : 被调试时,堆后面有8个连续的0xab.

BOOL fnAntiDebug_PebHeapAlloc()
{
    BYTE* pHeap = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x10);
    int iOnDebugDev = 0;
    DWORD dwVer = GetVersion();

    if (pHeap) {
        __asm {
            pushfd
            pushad

            mov edx, pHeap // save the pHeap
            xor ebx, ebx
            mov eax, dwVer
            cmp al, 6

            push ebp
            sbb ebp, ebp
            jb L1 // Process Environment Block

            mov eax, fs:0x18
            mov eax, [eax + 0x30] // _PEB

            mov eax, [eax+18h] // get process heap base
            mov ecx, [eax+24h] // check for protected heap
            jecxz L1
            mov ecx, [ecx]
            test [eax+4ch], ecx
            cmovne ebx, [eax+50h] // conditionally get heap key
L1:
            mov eax, edx
            movzx edx, WORD PTR [eax-8] // size
            xor dx, bx
            movzx ecx, BYTE PTR [eax+ebp-1] // overhead
            pop ebp

            sub eax, ecx
            lea edi, [edx*8+eax]
            mov al, 0abh
            mov cl, 8
            repe scasb
            // 被调试的程序中, 在堆后面有8个连续的0xab

            jne NOT_ON_DEBUG_ENV
            mov eax, 1
            mov iOnDebugDev, eax
NOT_ON_DEBUG_ENV:
            popad
            popfd
        }
        HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pHeap);
        pHeap = NULL;
    }

    return (iOnDebugDev != 0);
}
BOOL fnAntiDebug_PebHeapAlloc_V1()
{
    BYTE* pHeap = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x10);
    int iOnDebugDev = 0;
    DWORD dwVer = GetVersion();

    if (pHeap) {
        __asm {
                pushfd
                pushad

                mov eax, pHeap
                movzx ecx, BYTE PTR [eax - 1] // get the heap alloc size (0x10 + 8)
                lea edi, [eax + ecx - 8]
                mov al, 0abh
                mov cl, 8
                repe scasb
                // 被调试的程序中, 在堆后面有8个连续的0xab

                jne NOT_ON_DEBUG_ENV
                mov eax, 1
                mov iOnDebugDev, eax
NOT_ON_DEBUG_ENV:
                popad
                popfd
        }
        HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pHeap);
        pHeap = NULL;
    }

    return (iOnDebugDev != 0);
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐