PEB(Process Environment Block,
进程环境块)
是存放进程信息的结构体,尺寸非常大,我们首先看看PEB
结构体:
typedef struct _PEB { // Size: 0x1D8
000h UCHAR InheritedAddressSpace;
001h UCHAR ReadImageFileExecOptions;
002h UCHAR BeingDebugged; //Debug
运行标志
003h UCHAR SpareBool;
004h HANDLE Mutant;
008h HINSTANCE ImageBaseAddress; //
程序加载的基地址
00Ch struct _PEB_LDR_DATA *Ldr //Ptr32 _PEB_LDR_DATA
010h struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters;
014h ULONG SubSystemData;
018h HANDLE ProcessHeap;
01Ch KSPIN_LOCK FastPebLock;
020h ULONG FastPebLockRoutine;
024h ULONG FastPebUnlockRoutine;
028h ULONG EnvironmentUpdateCount;
02Ch ULONG KernelCallbackTable;
030h LARGE_INTEGER SystemReserved;
038h struct _PEB_FREE_BLOCK *FreeList
03Ch ULONG TlsExpansionCounter;
040h ULONG TlsBitmap;
044h LARGE_INTEGER TlsBitmapBits;
04Ch ULONG ReadOnlySharedMemoryBase;
050h ULONG ReadOnlySharedMemoryHeap;
054h ULONG ReadOnlyStaticServerData;
058h ULONG AnsiCodePageData;
05Ch ULONG OemCodePageData;
060h ULONG UnicodeCaseTableData;
064h ULONG NumberOfProcessors;
068h LARGE_INTEGER NtGlobalFlag; // Address of a local copy
070h LARGE_INTEGER CriticalSectionTimeout;
078h ULONG HeapSegmentReserve;
07Ch ULONG HeapSegmentCommit;
080h ULONG HeapDeCommitTotalFreeThreshold;
084h ULONG HeapDeCommitFreeBlockThreshold;
088h ULONG NumberOfHeaps;
08Ch ULONG MaximumNumberOfHeaps;
090h ULONG ProcessHeaps;
094h ULONG GdiSharedHandleTable;
098h ULONG ProcessStarterHelper;
09Ch ULONG GdiDCAttributeList;
0A0h KSPIN_LOCK LoaderLock;
0A4h ULONG OSMajorVersion;
0A8h ULONG OSMinorVersion;
0ACh USHORT OSBuildNumber;
0AEh USHORT OSCSDVersion;
0B0h ULONG OSPlatformId;
0B4h ULONG ImageSubsystem;
0B8h ULONG ImageSubsystemMajorVersion;
0BCh ULONG ImageSubsystemMinorVersion;
0C0h ULONG ImageProcessAffinityMask;
0C4h ULONG GdiHandleBuffer[0x22];
14Ch ULONG PostProcessInitRoutine;
150h ULONG TlsExpansionBitmap;
154h UCHAR TlsExpansionBitmapBits[0x80];
1D4h ULONG SessionId;
} PEB, *PPEB;
其中与反调试技术密切相关的成员如下所示:
002h UCHAR BeingDebugged;
00Ch struct _PEB_LDR_DATA *Ldr;
018h HANDLE ProcessHeap;
068h LARGE_INTEGER NtGlobalFlag;
接下来分别讲解以上4
个PEB
成员。
1
:BeingDebugged
。
当进程处于调试状态时,BeingDebugged
的值会被设置为1
,进程在非调试状态下运行时,其值被设置为0
。所以我们可以通过判断这个成员的值来决定我们程序的运行流程。测试代码如下:
int main()
{
charresult=0;
__asm
{
moveax,fs:[0x30];//
获取PEB
的地址。
moval,BYTE PTR [eax+2];
movresult,al;//
得到BeingDebugged
成员的值。
}
if(result==1)
printf("isdebugging\n");
else
printf("notdebugging\n");
system("pause");//
为了观察方便,添加的。
return0;
}
2
:Ldr
。
调试进程时,其堆内存就会出现一些特殊的标识,表示它正处于被调试状态。这些标识中最醒目的是在未使用的堆内存区域中填充着OxFEEEFEEE
。我们利用这一特征即可判断进程是否处于被调试状态。PEB.Ldr
成员指向一个_PEB_LDR_DATA
结构体,而这个结构体就是在堆内存区域中创建的,所以我们可以扫描该区域来判断进程是否处于调试状态下。测试代码如下:
int main()
{
LPBYTEpLdr;
DWORDpLdrSig[4]={0xEEFEEEFE,0xEEFEEEFE,0xEEFEEEFE,0xEEFEEEFE};
__asm
{
moveax,fs:[0x30]; //PEB
地址
moveax,[eax+0xC];//Ldr
movpLdr,eax;
}
__try
{
while(1)
{
if(!memcmp(pLdr,pLdrSig,sizeof(pLdrSig)))
{
printf("is debuggig\n");
break;
}
else
{
pLdr++;
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("notdebugging\n");
}
system("pause");
return0;
}
3
:ProcessHeap
ProcessHeap
是指向
HEAP
结构体的指针,在
HEAP
结构体中的两个成员
Flags
和
Force Flags
,它们的偏移分别为
0xC
和
0x10
,进程运行正常时,
Heap.Flags
的成员值为
0x2,HEAP.ForceFlags
成员的值为
0x0
。进程处于调试状态时,这些值会发生变化。测试代码如下:(只测试了
ForceFlags
成员的值,测试
Flags
成员的值的方法是一样的)。整理发布 香樟
int main()
{
intresult=0;
__asm
{
moveax,fs:[0x30]; //PEB
地址
moveax,[eax+0x18];//ProcessHeap
成员
moveax,[eax+0x10];//ForceFlags
成员
movresult,eax;
}
if(result!=0)
printf("isdebugging\n");
else
printf("notdebugging\n");
system("pause");
return0;
}
4
:NtGlobalFlag
。
调试进程时,PEB.NtGlobalFlag
成员的值为被设置成0x70
。所以,检测该成员的值即可判断进程是否处于被调试状态。测试代码如下:
int main()
{
intresult=0;
__asm
{
moveax,fs:[0x30]; //PEB
地址
moveax,[eax+0x68];//NtGlobalFlag
成员
movresult,eax;
}
if(result==0x70)
printf("isdebugging\n");
else
printf("notdebugging\n");
system("pause");
return0;
}