静态反调试技术
PEB (进程环境块)反调
PEB 的概念
PEB(Process Environment Block)是存放进程信息的结构体,与之概念类似的是 TEB(Thread Environment Block),即线程环境块,PEB 的指针 是 TEB 结构体的成员,因此想要访问 PEB ,就可以通过系统 API Ntdll.NtCurrentTeb()
访问 TEB 再加上 0x30 得到。而在汇编层面中,FS 段寄存器用来指示当前线程的 TEB ,FS:[0x30]
就是 PEB 的地址,FS:[0x18]
就是 TEB 的地址。
注意:PEB 在各个版本的系统中不太一样,因此使用库函数即可准确获取到自己想要的信息,是最稳妥的办法。win10 PEB 附在文后。
PEB 中比较重要的成员
+002 BeingDebugged(XP、win7、win10 都适用)
该成员用于判断当前进程是否处于调试状态。
BeingDebugged
可由Kernelbase.dll
中的IsDebuggerPresent()
API 来得到,示例代码如下:
1 2 3 4
| if(IsDebuggerPresent()) { exit(0); }
|
注意:在使用调试器附加到进程时,该值也会生效。
+0xC Ldr
注意:Ldr 的反调试仅适用于 XP 系统。
在调试时,堆内存区域会出现一些特殊的标识,未使用的堆内存区域填充为0xEEFEEEFE
,而Ldr指向 _PEB_LDR_DATA 结构体,该结构体是在堆内存中创建的。
+0x18 ProcessHeap
注意:ProcessHeap 的反调试仅适用于 XP 系统。
该成员是指向 HEAP 结构体的指针,而 HEAP 结构体中的 Flags(+0xC)和 ForceFlags(+0x10)成员在正常运行时为 2和 0 。ProcessHeap 可由GetProcessHeap()
API 得到。
+0x68 NtGlobalFlag(XP、win7、win10都适用)
调试时,NtGlobalFlag 的值为 0x70 。
注意:使用调试器附加时,该值不变
函数定义如下:
1 2 3 4 5 6 7
| __kernel_entry NTSTATUS NtQueryInformationProcess( HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength );
|
其中ProcessHandle
为进程句柄,第3个参数根据第二个 enum 的值来传出不同值,第二个参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| typedef enum _PROCESSINFOCLASS{ ProcessBasicInformation = 1, ProcessQuotaLimits, ProcessIoCounters, ProcessVmCounters ProcessTimes, ProcessBasePriority, ProcessRaisePriority, ProcessDebugPort = 7, ProcessExceptionPort, ProcessAccessToken, ProcessLdtInformation, ProcessLdtSize, ProcessDefaultHardErrorMode, ProcessIoPortHandlers, ProcessPooledUsageAndLimits, ProcessWorkingSetWatch, ProcessUserModeIOPL, rocessEnableAlignmentFaultFixup, ProcessPriorityClass, ProcessWx86Information, ProcessHandleCount, ProcessAffinityMask, ProcessPriorityBoost, ProcessDeviceMap, ProcessSessionInformation, ProcessForegroundInformation, ProcessWow64Information = 26, ProcessImageFileName = 27, ProcessLUIDDeviceMapsEnabled, ProcessBreakOnTermination, ProcessDebugObjectHandle = 30, ProcessDebugFlags = 31, ProcessHandleTracing, ProcessUnknown33, ProcessUnknown34, ProcessUnknown35, ProcessCookie, MaxProcessInfoClass } PROCESSINFOCLASS;
|
该函数虽然存在于winternl.h
中,但直接从头文件引入却会有链接错误,需要加载ntdll.dll
来使用:
1 2 3 4 5 6 7 8 9 10 11 12 13
| typedef NTSTATUS(NTAPI* pfnNtQueryInformationProcess)( _In_ HANDLE ProcessHandle, _In_ UINT ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength ); HMODULE hNtDll = LoadLibraryA("ntdll.dll"); pfnNtQueryInformationProcess NtQueryInformationProcess=NULL; if (hNtDll) { NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformationProcess"); }
|
ProcessDebugPort (0x7)
使用原函数
进程处于调试状态时,系统会分配一个调试端口。当 enum 的值为 0x7 时,使用该函数就能在第三个参数处获取调试端口,若进程处于非调试状态,则传出的值为 0 ,处于调试状态则传出0xFFFFFFFF
。示例代码:
1 2 3 4
| int Port; NtQueryInformationProcess(GetCurrentProcess(),ProcessDebugPort,&Port,sizeof(Port),NULL); if(Port) exit(0);
|
使用 CheckRemoteDebuggerPresent()
该函数与IsDebuggerPresent()
类似,但其不仅可以检测当前进程,还可用于检测其他进程是否处于调试状态。
函数原型:
1 2 3 4
| BOOL CheckRemoteDebuggerPresent( HANDLE hProcess, PBOOL pbDebuggerPresent );
|
示例:
1 2 3 4
| int status; CheckRemoteDebuggerPresent(GetcurrentProcess(),&status); if(status) exit(0);
|
实际上在该函数内部仍然使用了NtQueryInformationProcess() 函数:
ProcessDebugObjectHandle(0x1E)
调试进程时会生成调试对象,函数的第二个参数值为 ProcessDebugObjectHandle(0x1E) 时,传出的第三个参数为调试对象句柄。非调试状态时传出NULL。
1 2 3 4
| int handle; NtQueryInformationProcess(GetCurrentProcess(),ProcessDebugObjectHandle,&handle,sizeof(handle),NULL); if(!handle) exit(0);
|
ProcessDebugFlags(0x1F)
第二个参数值为 ProcessDebugFlags(0x1F) 时,第三个参数传出调试标志的值。若为 0 则被调试,若为 1 则非调试。
1 2 3 4
| int flag; NtQueryInformationProcess(GetCurrentProcess(),ProcessDebugFlags,&flag,sizeof(flag),NULL); if(!flag) exit(0);
|
该函数用来获取当前运行的多种 OS 信息,以此来判断有无调试环境,间接判断程序是否为调试状态。
函数原型:
1 2 3 4 5 6 7
| __kernel_entry NTSTATUS NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength );
|
参数解释: SystemInformationClass 中指定需要的系统信息类型,将信息结构体的地址传递给 SystemInformation 参数。
SYSTEM_INFORMATION_CLASS 类型定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation = 0, SystemPerformanceInformation = 2, SystemTimeOfDayInformation = 3, SystemProcessInformation = 5, SystemProcessorPerformanceInformation = 8, SystemInterruptInformation = 23, SystemExceptionInformation = 33, SystemKernelDebuggerInformation = 35, SystemRegistryQuotaInformation = 37, SystemLookasideInformation = 45, SystemCodeIntegrityInformation = 103, SystemPolicyInformation = 134, } SYSTEM_INFORMATION_CLASS;
|
该函数定义存在于 winternl.h 但直接使用会出现链接错误,因此需加载 ntdll.dll 使用:
1 2 3 4 5 6 7 8 9 10 11 12
| typedef NTSTATUS (WINAPI* pfnNtQuerySystemInformation)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); HMODULE hNtDll = LoadLibraryA("ntdll.dll"); pfnNtQuerySystemInformation NtQuerySystemInformation=NULL; if (hNtDll) { NtQuerySystemInformation = (pfnNtQuerySystemInformation)GetProcAddress(hNtDll, "NtQuerySystemInformation"); }
|
使用以上方法引入 NtQuerySystemInformation 函数后,即可使用该函数完成功能。
1 2 3 4 5 6 7 8
| typedef struct DebuggerInformation { BOOLEAN DebuggerEnabled; BOOLEAN DebuggerNotPresent; }DebuggerInformation; DebuggerInformation info; NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x23,&info,sizeof(info),NULL); if(info.DebuggerEnabled) exit(0);
|
该函数可强制分离被调试者与调试器。
1 2 3 4
| typedef DWORD(WINAPI* ZW_SET_INFORMATION_THREAD) (HANDLE, DWORD, PVOID, ULONG); HMODULE hNtDll = LoadLibraryA("ntdll.dll"); ZW_SET_INFORMATION_THREAD ZSsetInformationThread = (ZW_SET_INFORMATION_THREAD)GetProcAddress(hNtDll, "ZwSetInformationThread"); ZwSetInformationThread(GetCurrentThread(),0x11,NULL,NULL);
|
进程检测,窗口检测等
检测窗口:FindWindow()
检测进程:CreateToolhelp32Snapshot()
获取计算机名称:GetComputerName()
检查程序运行路径:GetCommandLine()
检查是否有虚拟机运行:检查特定进程:VMWareService.exe
win10 PEB
32位:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 BitField : UChar +0x003 ImageUsesLargePages : Pos 0, 1 Bit +0x003 IsProtectedProcess : Pos 1, 1 Bit +0x003 IsImageDynamicallyRelocated : Pos 2, 1 Bit +0x003 SkipPatchingUser32Forwarders : Pos 3, 1 Bit +0x003 IsPackagedProcess : Pos 4, 1 Bit +0x003 IsAppContainer : Pos 5, 1 Bit +0x003 IsProtectedProcessLight : Pos 6, 1 Bit +0x003 IsLongPathAwareProcess : Pos 7, 1 Bit +0x004 Mutant : Ptr32 Void +0x008 ImageBaseAddress : Ptr32 Void +0x00c Ldr : Ptr32 _PEB_LDR_DATA +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +0x014 SubSystemData : Ptr32 Void +0x018 ProcessHeap : Ptr32 Void +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +0x020 AtlThunkSListPtr : Ptr32 _SLIST_HEADER +0x024 IFEOKey : Ptr32 Void +0x028 CrossProcessFlags : Uint4B +0x028 ProcessInJob : Pos 0, 1 Bit +0x028 ProcessInitializing : Pos 1, 1 Bit +0x028 ProcessUsingVEH : Pos 2, 1 Bit +0x028 ProcessUsingVCH : Pos 3, 1 Bit +0x028 ProcessUsingFTH : Pos 4, 1 Bit +0x028 ProcessPreviouslyThrottled : Pos 5, 1 Bit +0x028 ProcessCurrentlyThrottled : Pos 6, 1 Bit +0x028 ProcessImagesHotPatched : Pos 7, 1 Bit +0x028 ReservedBits0 : Pos 8, 24 Bits +0x02c KernelCallbackTable : Ptr32 Void +0x02c UserSharedInfoPtr : Ptr32 Void +0x030 SystemReserved : Uint4B +0x034 AtlThunkSListPtr32 : Ptr32 _SLIST_HEADER +0x038 ApiSetMap : Ptr32 Void +0x03c TlsExpansionCounter : Uint4B +0x040 TlsBitmap : Ptr32 Void +0x044 TlsBitmapBits : [2] Uint4B +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +0x050 SharedData : Ptr32 Void +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +0x058 AnsiCodePageData : Ptr32 Void +0x05c OemCodePageData : Ptr32 Void +0x060 UnicodeCaseTableData : Ptr32 Void +0x064 NumberOfProcessors : Uint4B +0x068 NtGlobalFlag : Uint4B +0x070 CriticalSectionTimeout : _LARGE_INTEGER +0x078 HeapSegmentReserve : Uint4B +0x07c HeapSegmentCommit : Uint4B +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +0x088 NumberOfHeaps : Uint4B +0x08c MaximumNumberOfHeaps : Uint4B +0x090 ProcessHeaps : Ptr32 Ptr32 Void +0x094 GdiSharedHandleTable : Ptr32 Void +0x098 ProcessStarterHelper : Ptr32 Void +0x09c GdiDCAttributeList : Uint4B +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +0x0a4 OSMajorVersion : Uint4B +0x0a8 OSMinorVersion : Uint4B +0x0ac OSBuildNumber : Uint2B +0x0ae OSCSDVersion : Uint2B +0x0b0 OSPlatformId : Uint4B +0x0b4 ImageSubsystem : Uint4B +0x0b8 ImageSubsystemMajorVersion : Uint4B +0x0bc ImageSubsystemMinorVersion : Uint4B +0x0c0 ActiveProcessAffinityMask : Uint4B +0x0c4 GdiHandleBuffer : [34] Uint4B +0x14c PostProcessInitRoutine : Ptr32 void +0x150 TlsExpansionBitmap : Ptr32 Void +0x154 TlsExpansionBitmapBits : [32] Uint4B +0x1d4 SessionId : Uint4B +0x1d8 AppCompatFlags : _ULARGE_INTEGER +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +0x1e8 pShimData : Ptr32 Void +0x1ec AppCompatInfo : Ptr32 Void +0x1f0 CSDVersion : _UNICODE_STRING +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +0x208 MinimumStackCommit : Uint4B +0x20c SparePointers : [4] Ptr32 Void +0x21c SpareUlongs : [5] Uint4B +0x230 WerRegistrationData : Ptr32 Void +0x234 WerShipAssertPtr : Ptr32 Void +0x238 pUnused : Ptr32 Void +0x23c pImageHeaderHash : Ptr32 Void +0x240 TracingFlags : Uint4B +0x240 HeapTracingEnabled : Pos 0, 1 Bit +0x240 CritSecTracingEnabled : Pos 1, 1 Bit +0x240 LibLoaderTracingEnabled : Pos 2, 1 Bit +0x240 SpareTracingBits : Pos 3, 29 Bits +0x248 CsrServerReadOnlySharedMemoryBase : Uint8B +0x250 TppWorkerpListLock : Uint4B +0x254 TppWorkerpList : _LIST_ENTRY +0x25c WaitOnAddressHashTable : [128] Ptr32 Void +0x45c TelemetryCoverageHeader : Ptr32 Void +0x460 CloudFileFlags : Uint4B +0x464 CloudFileDiagFlags : Uint4B +0x468 PlaceholderCompatibilityMode : Char +0x469 PlaceholderCompatibilityModeReserved : [7] Char +0x470 LeapSecondData : Ptr32 _LEAP_SECOND_DATA +0x474 LeapSecondFlags : Uint4B +0x474 SixtySecondEnabled : Pos 0, 1 Bit +0x474 Reserved : Pos 1, 31 Bits +0x478 NtGlobalFlag2 : Uint4B
|
64位:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 BitField : UChar +0x003 ImageUsesLargePages : Pos 0, 1 Bit +0x003 IsProtectedProcess : Pos 1, 1 Bit +0x003 IsImageDynamicallyRelocated : Pos 2, 1 Bit +0x003 SkipPatchingUser32Forwarders : Pos 3, 1 Bit +0x003 IsPackagedProcess : Pos 4, 1 Bit +0x003 IsAppContainer : Pos 5, 1 Bit +0x003 IsProtectedProcessLight : Pos 6, 1 Bit +0x003 IsLongPathAwareProcess : Pos 7, 1 Bit +0x004 Padding0 : [4] UChar +0x008 Mutant : Ptr64 Void +0x010 ImageBaseAddress : Ptr64 Void +0x018 Ldr : Ptr64 _PEB_LDR_DATA +0x020 ProcessParameters : Ptr64 _RTL_USER_PROCESS_PARAMETERS +0x028 SubSystemData : Ptr64 Void +0x030 ProcessHeap : Ptr64 Void +0x038 FastPebLock : Ptr64 _RTL_CRITICAL_SECTION +0x040 AtlThunkSListPtr : Ptr64 _SLIST_HEADER +0x048 IFEOKey : Ptr64 Void +0x050 CrossProcessFlags : Uint4B +0x050 ProcessInJob : Pos 0, 1 Bit +0x050 ProcessInitializing : Pos 1, 1 Bit +0x050 ProcessUsingVEH : Pos 2, 1 Bit +0x050 ProcessUsingVCH : Pos 3, 1 Bit +0x050 ProcessUsingFTH : Pos 4, 1 Bit +0x050 ProcessPreviouslyThrottled : Pos 5, 1 Bit +0x050 ProcessCurrentlyThrottled : Pos 6, 1 Bit +0x050 ProcessImagesHotPatched : Pos 7, 1 Bit +0x050 ReservedBits0 : Pos 8, 24 Bits +0x054 Padding1 : [4] UChar +0x058 KernelCallbackTable : Ptr64 Void +0x058 UserSharedInfoPtr : Ptr64 Void +0x060 SystemReserved : Uint4B +0x064 AtlThunkSListPtr32 : Uint4B +0x068 ApiSetMap : Ptr64 Void +0x070 TlsExpansionCounter : Uint4B +0x074 Padding2 : [4] UChar +0x078 TlsBitmap : Ptr64 Void +0x080 TlsBitmapBits : [2] Uint4B +0x088 ReadOnlySharedMemoryBase : Ptr64 Void +0x090 SharedData : Ptr64 Void +0x098 ReadOnlyStaticServerData : Ptr64 Ptr64 Void +0x0a0 AnsiCodePageData : Ptr64 Void +0x0a8 OemCodePageData : Ptr64 Void +0x0b0 UnicodeCaseTableData : Ptr64 Void +0x0b8 NumberOfProcessors : Uint4B +0x0bc NtGlobalFlag : Uint4B +0x0c0 CriticalSectionTimeout : _LARGE_INTEGER +0x0c8 HeapSegmentReserve : Uint8B +0x0d0 HeapSegmentCommit : Uint8B +0x0d8 HeapDeCommitTotalFreeThreshold : Uint8B +0x0e0 HeapDeCommitFreeBlockThreshold : Uint8B +0x0e8 NumberOfHeaps : Uint4B +0x0ec MaximumNumberOfHeaps : Uint4B +0x0f0 ProcessHeaps : Ptr64 Ptr64 Void +0x0f8 GdiSharedHandleTable : Ptr64 Void +0x100 ProcessStarterHelper : Ptr64 Void +0x108 GdiDCAttributeList : Uint4B +0x10c Padding3 : [4] UChar +0x110 LoaderLock : Ptr64 _RTL_CRITICAL_SECTION +0x118 OSMajorVersion : Uint4B +0x11c OSMinorVersion : Uint4B +0x120 OSBuildNumber : Uint2B +0x122 OSCSDVersion : Uint2B +0x124 OSPlatformId : Uint4B +0x128 ImageSubsystem : Uint4B +0x12c ImageSubsystemMajorVersion : Uint4B +0x130 ImageSubsystemMinorVersion : Uint4B +0x134 Padding4 : [4] UChar +0x138 ActiveProcessAffinityMask : Uint8B +0x140 GdiHandleBuffer : [60] Uint4B +0x230 PostProcessInitRoutine : Ptr64 void +0x238 TlsExpansionBitmap : Ptr64 Void +0x240 TlsExpansionBitmapBits : [32] Uint4B +0x2c0 SessionId : Uint4B +0x2c4 Padding5 : [4] UChar +0x2c8 AppCompatFlags : _ULARGE_INTEGER +0x2d0 AppCompatFlagsUser : _ULARGE_INTEGER +0x2d8 pShimData : Ptr64 Void +0x2e0 AppCompatInfo : Ptr64 Void +0x2e8 CSDVersion : _UNICODE_STRING +0x2f8 ActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +0x300 ProcessAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +0x308 SystemDefaultActivationContextData : Ptr64 _ACTIVATION_CONTEXT_DATA +0x310 SystemAssemblyStorageMap : Ptr64 _ASSEMBLY_STORAGE_MAP +0x318 MinimumStackCommit : Uint8B +0x320 SparePointers : [4] Ptr64 Void +0x340 SpareUlongs : [5] Uint4B +0x358 WerRegistrationData : Ptr64 Void +0x360 WerShipAssertPtr : Ptr64 Void +0x368 pUnused : Ptr64 Void +0x370 pImageHeaderHash : Ptr64 Void +0x378 TracingFlags : Uint4B +0x378 HeapTracingEnabled : Pos 0, 1 Bit +0x378 CritSecTracingEnabled : Pos 1, 1 Bit +0x378 LibLoaderTracingEnabled : Pos 2, 1 Bit +0x378 SpareTracingBits : Pos 3, 29 Bits +0x37c Padding6 : [4] UChar +0x380 CsrServerReadOnlySharedMemoryBase : Uint8B +0x388 TppWorkerpListLock : Uint8B +0x390 TppWorkerpList : _LIST_ENTRY +0x3a0 WaitOnAddressHashTable : [128] Ptr64 Void +0x7a0 TelemetryCoverageHeader : Ptr64 Void +0x7a8 CloudFileFlags : Uint4B +0x7ac CloudFileDiagFlags : Uint4B +0x7b0 PlaceholderCompatibilityMode : Char +0x7b1 PlaceholderCompatibilityModeReserved : [7] Char +0x7b8 LeapSecondData : Ptr64 _LEAP_SECOND_DATA +0x7c0 LeapSecondFlags : Uint4B +0x7c0 SixtySecondEnabled : Pos 0, 1 Bit +0x7c0 Reserved : Pos 1, 31 Bits +0x7c4 NtGlobalFlag2 : Uint4B
|