您的位置:首页 > 编程语言 > C语言/C++

PEB结构的获取

2014-08-15 10:44 411 查看
32位获取KERNEL32地址汇编代码PEB结构----枚举用户模块列表。

PEB地址的取得:

1:通过CreateProcess()创建新的被挂起的进程,此时其初始化线程上下文中,ebx 指向其PEB结构, EAX指向其EIP(代码执行地址)

demo:

CreateProcess(NULL, TARGETPROC,
NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, pi))
{
ctx->ContextFlags=CONTEXT_FULL;
GetThreadContext(pi->hThread, ctx); //获得线程的所有重要的寄存器CTX

DWORD *pebInfo = (DWORD *)ctx->Ebx; //ctx->Ebx = points to PEB

2:如果线程没被挂起, 通过FS寄存器指向当前TEB结构 , 再TEB偏移0x30处是PEB指针 ,通过这个指针可以取得PEB结构的地址

demo:

__asm
{
mov eax,fs:[0x30]
mov PEB,eax
}

3:X64程序下的FS寄存器角色已经换成了gs

暂时发现的一些东西:

gs:[0x30] TEB

gs:[0x40] Pid

gs:[0x48] Tid

gs:[0x60]  PEB

gs:[0x68]  LastError.

虽然gs:[0x60]直接存放的PEB,但是由于vista/7后的地址随机化机制,还是从TEB获取比较靠谱。

0:009> dt 000007fffff98000 _TEB

ntdll!_TEB

+0×000 NtTib            : _NT_TIB

+0×038 EnvironmentPointer : (null)

+0×040 ClientId         : _CLIENT_ID

+0×050 ActiveRpcHandle  : (null)

+0×058 ThreadLocalStoragePointer : (null)

+0×060 ProcessEnvironmentBlock : 0x000007ff`fffd5000 _PEB    //这里即是PEB

//用c语言描述就是

#define x64_GetPeb()                    ( (LONG64*)(*((LONG64*)((BYTE*)x64_GetTeb()+0×060))) )

得到了PEB,剩下的就和x86下一样了.只是偏移不一样了

0:009> dt 0x000007ff`fffd5000 _PEB

ntdll!_PEB

+0×000 InheritedAddressSpace : 0 ”

+0×001 ReadImageFileExecOptions : 0 ”

+0×002 BeingDebugged    : 0×1 ”

+0×003 BitField         : 0×8 ”

+0×003 ImageUsesLargePages : 0y0

+0×003 IsProtectedProcess : 0y0

+0×003 IsLegacyProcess  : 0y0

+0×003 IsImageDynamicallyRelocated : 0y1

+0×003 SkipPatchingUser32Forwarders : 0y0

+0×003 SpareBits        : 0y000

+0×008 Mutant           : 0xffffffff`ffffffff Void

+0×010 ImageBaseAddress : 0×00000000`ff310000 Void

+0×018 Ldr              : 0×00000000`77222640 _PEB_LDR_DATA

0:009> dt 0×00000000`77222640 _PEB_LDR_DATA

ntdll!_PEB_LDR_DATA

+0×000 Length           : 0×58

+0×004 Initialized      : 0×1 ”

+0×008 SsHandle         : (null) //length 8 ,32位系统length 4

+0×010 InLoadOrderModuleList : _LIST_ENTRY [ 0x00000000`00202780 - 0x2421b0 ]   //length 0x10h , x86 length 0x8h .结构多8字节

+0×020 InMemoryOrderModuleList : _LIST_ENTRY [ 0x00000000`00202790 - 0x2421c0 ]  //同上

+0×030 InInitializationOrderModuleList : _LIST_ENTRY [ 0x00000000`00202890 - 0x2421d0 ]  //同上

同样的,搜索InInitializationOrderModuleList 即可得到Kernel32的基址.

由于x64下vs2005没法直接使用内联汇编,所以只把必须使用汇编来做的事情写成单独的asm

x64下.指针的长度已经是8个字节,所以偏移不一样了.

0:009> dt _LDR_DATA_TABLE_ENTRY

ntdll!_LDR_DATA_TABLE_ENTRY

+0×000 InLoadOrderLinks : _LIST_ENTRY

+0×010 InMemoryOrderLinks : _LIST_ENTRY

+0×020 InInitializationOrderLinks : _LIST_ENTRY

+0×030 DllBase          : Ptr64 Void

+0×038 EntryPoint       : Ptr64 Void

+0×040 SizeOfImage      : Uint4B

+0×048 FullDllName      : _UNICODE_STRING

C语言表示x64搜索过程:

HMODULE x64_GetKernel32(void)
{
HMODULE	hKernel32 = NULL;
UNICODE_STRING * pBaseName = NULL;
LIST_ENTRY * pNode = NULL;
pNode = X64_GetPebInitOrderList();
while{1}
{
pBaseName = (UNICODE_STRING *)((BYTE *)pNode + 0x038);
if (*(pBaseName->Buffer)+12=='\0')
{
/* code */
hKernel32 = (HMODULE)(*((LONG64*)((BYTE*)pNode+0x010)));
break;
}
pNode = pNode->Flink;
}
return hKernel32;
}


win7 x64下测试通过win7 x64下测试通过

32位程序的通用Kernel32地址获取方法

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 结构