如何获取其PEB的内容

如何获取其PEB的内容,第1张

楼主可以去微软的官网下载一个巨强的进程 *** 纵/信息查看工具--ProcessExplorer。

网址:

查看句柄的码亏时候需要在工具栏中点击逗Show lower pane地或快捷键:Ctrl+L

在View菜单中选择逗select columns...地可以选择具体要查看进程的信息,如进程的用户名,句柄的具体值是多少等。

查看PEB的工具我一般是使用WinDbg调试工具,该工具也可以在微软的官网中下载,WinDbg是作为Windows SDK工具包的一部分提供的,且不同的 *** 作系统有不同的SDK,因此楼主需要根据自己的 *** 作系统选择合适的SDK。

微软的官方下载中心网址:

然后输入查询关键字逗SDK地,进行合适的SDK下载。

关于使用WinDbg查看PEB的一些入门说明:

WinDbg一般是以命令行的方式来 *** 纵进程调试信息的,类似于CMD。它的命令是以术语逗symbol(符号)地来表示的,刚开始使用WinDbg时可能无法正确识别symbol,因此需要进行一些设置,使WinDbg能够识别命令(symbol)。然后启动WinDbg需要调试的进程,最后输入各种调试命令。初次使用WinDbg及查看PEB的步骤为:

1)启动WinDbg;

2)菜单项--FILE/SYMBOL FILE PATH,d出逗SYMBOL SEARCH PATH地对话框;

3)在文本框中直接输入内容:SRV*C:\\我的符号文件夹*

在逗*地号包围的是需要存储符号表的文件夹路径,可以随意指定一个,无此文件夹会自动新建。

4)菜单项--FILE/OPEN EXECUTABLE...,d出浏览框,选择需要调试的应用程序文件;

5)在d出的COMMAND对话框的底部可以输入命令,提示符为0:000>

查看PEB的命令为:dt nt!_PEB,按回车键历模世,就可以看到_PEB了。

注意:命令可能会因WinDbg不同而不同,要想知道逗dt地命令的语法格式可以在命令输入框中输入:(提示符0:000>).hh dt 按回车键。会d出帮助对话框,里面会有详细的命令语法解释及SAMPLE。

6)菜单项--DEBUG/STOP DEBUGGING,停止进程调试,使WinDbg恢复到初次打开时的状态,因此可以再次选择其他调试进程。

7)对以后进一步使用WinDbg作一些调整,依旧打开SYMBOL SEARCH PATH对话框,将原有的URL等删除,只留下文件夹路径c:\\我的符号文件夹

8)要想对进程做更多的控制,需要保证应用程序文件一定有对应的*.PDB文件,然后将PDB文件所在的文件夹路径通过逗SYMBOL SEARCH PATH地对话框包含进来,因此一般的SYMBOL SEARCH PATH中的内容为:我的符号文件夹c:\\肢肢myAppDir以分号隔开的符号搜索路径。

9)与应用程序对应的PDB文件是由编译器生成的,C++编译器 CL.EXE可以指定开关/Fd[pdbFile]进行指定。当然使用VS,一般都会自动生成,文件名为应用程序名加PDB扩展名。

为了避免自己的某个dll模块被别人检测出来,有时候希望在自己加载一个dll之后,或者将dll注入到他人进程之后避免被检查出来。这就需要想办法抹掉这个dll的模辩脊块信息,使得Toolhelp、psapi等枚举模含余块谈灶滚的API无法枚举它。

我们可以先简单看看Windows枚举进程内模块的办法吧:

首先是BOOL EnumProcessModules( HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded)

EnumProcessModules实际调用EnumProcessModulesInternal进行枚举。下面是vista下psapi的代码片断:

.text:514024B8 push ebx

.text:514024B9 push 18h

.text:514024BB lea eax, [ebp+stProcessBasicInfo]

.text:514024BE push eax

.text:514024BF push ebx ebx=0

.text:514024C0 push [ebp+hProcess]

.text:514024C3 call ds:__imp__NtQueryInformationProcess@20 NtQueryInformationProcess(x,x,x,x,x)

.text:514024C9 cmp eax, ebx

.text:514024CB jge short loc_514024E0

调用NtQueryInformationProcess获得ProcessBasicInformation,在PROCESS_BASIC_INFORMATION结构中取得PEB地址。然后读取指定进程PEB中的数据

text:514024E0 loc_514024E0:CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+24 j

.text:514024E0 mov eax, [ebp+stProcessBasicInfo.PebBaseAddress]

.text:514024E3 cmp eax, ebx

.text:514024E5 jnz short loc_514024EE

.text:514024E7 push 8000000Dh

.text:514024EC jmp short loc_514024CE

.text:514024EE ---------------------------------------------------------------------------

.text:514024EE

.text:514024EE loc_514024EE:CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+3E j

.text:514024EE push ebx lpNumberOfBytesRead

.text:514024EF push 4nSize

.text:514024F1 lea ecx, [ebp+Ldr]

.text:514024F4 push ecx lpBuffer

.text:514024F5 add eax, 0Ch

.text:514024F8 push eax lpBaseAddress

.text:514024F9 push [ebp+hProcess] hProcess

.text:514024FC mov edi, ds:__imp__ReadProcessMemory@20 ReadProcessMemory(x,x,x,x,x)

.text:51402502 call edi ReadProcessMemory(x,x,x,x,x) ReadProcessMemory(x,x,x,x,x)

这里读取的是PEB地址+0C处的四个字节。

通过WinDbg我们可以看看nt!_PEB的结构

0: kd>dt nt!_PEB

+0x000 InheritedAddressSpace : UChar

+0x001 ReadImageFileExecOptions : UChar

+0x002 BeingDebugged : UChar

+0x003 SpareBool : UChar

+0x004 Mutant: Ptr32 Void

+0x008 ImageBaseAddress : Ptr32 Void

+0x00c Ldr : Ptr32 _PEB_LDR_DATA

+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS

……

+0C处是一个_PEB_LDR_DATA结构指针,里面包含了和LDR相关的一些数据,进程的模块链表就保存在Ldr中。下面是_PEB_LDR_DATA的结构:

0: kd>dt nt!_PEB_LDR_DATA

+0x000 Length: Uint4B

+0x004 Initialized : UChar

+0x008 SsHandle : Ptr32 Void

+0x00c InLoadOrderModuleList : _LIST_ENTRY

+0x014 InMemoryOrderModuleList : _LIST_ENTRY

+0x01c InInitializationOrderModuleList : _LIST_ENTRY

+0x024 EntryInProgress : Ptr32 Void

其中,InLoadOrderModuleList、InMemoryOrderModuleList、InInitializationOrderModuleList就是进程当前已加载模块的链表,只是按照不同的方式排序。EnumProcessModules是通过InMemoryOrderModuleList链表枚举的,而根据Win2k代码,ToolHelp32函数是通过InLoadOrderModuleList枚举。这三个_LIST_ENTRY都是在一个RTL_PROCESS_MODULE_INFORMATION结构中的成员。这个结构在2k代码中有引用,不过没有确切的定义,下面是ReactOS中的定义,不过看起来我的vista PSAPI中使用的结构已经有所变化了,这里只作参考。

//

// Loader Data Table Entry

//

typedef struct _LDR_DATA_TABLE_ENTRY

{

LIST_ENTRY InLoadOrderLinks

LIST_ENTRY InMemoryOrderModuleList

LIST_ENTRY InInitializationOrderModuleList

PVOID DllBase

PVOID EntryPoint

ULONG SizeOfImage

UNICODE_STRING FullDllName

UNICODE_STRING BaseDllName

ULONG Flags

USHORT LoadCount

USHORT TlsIndex

union

{

LIST_ENTRY HashLinks

PVOID SectionPointer

}

ULONG CheckSum

union

{

ULONG TimeDateStamp

PVOID LoadedImports

}

PVOID EntryPointActivationContext

PVOID PatchInformation

} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY

到这里,隐藏模块的方法就已经明了了:通过PEB取得Ldr数据,拿到三个模块链表,并将要隐藏的模块断链即可。下面是主要代码实现:

BOOL HideMyself()

{

HMODULE hMod = GetModuleHandle( _T( "ntdll.dll"))

HMODULE hModMyself = GetModuleHandle( _T("dll.dll"))

pfnNtQueryInformationProcess p = (pfnNtQueryInformationProcess)::GetProcAddress( hMod, "NtQueryInformationProcess")

PROCESS_BASIC_INFORMATION stInfo = {0}

DWORD dwRetnLen = 0

DWORD dw = p( GetCurrentProcess(), 0, &stInfo, sizeof(stInfo), &dwRetnLen)

PPEB pPeb = stInfo.PebBaseAddress

PLIST_ENTRY ListHead, Current

PLDR_DATA_TABLE_ENTRY pstEntry = NULL

ListHead = &( stInfo.PebBaseAddress->Ldr->InLoadOrderModuleList)

Current = ListHead->Flink

while ( Current != ListHead)

{

pstEntry = CONTAINING_RECORD( Current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks)

//DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint)

if ( pstEntry->DllBase == hModMyself)

{

pstEntry->InLoadOrderLinks.Flink->Blink = pstEntry->InLoadOrderLinks.Blink

pstEntry->InLoadOrderLinks.Blink->Flink = pstEntry->InLoadOrderLinks.Flink

DebugOut( _T( "Hide injected dll."))

break

}

Current = pstEntry->InLoadOrderLinks.Flink

}

ListHead = &( stInfo.PebBaseAddress->Ldr->InMemoryOrderModuleList)

Current = ListHead->Flink

while ( Current != ListHead)

{

pstEntry = CONTAINING_RECORD( Current, LDR_DATA_TABLE_ENTRY, InMemoryOrderModuleList)

DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint)

if ( pstEntry->DllBase == hModMyself)

{

pstEntry->InMemoryOrderModuleList.Flink->Blink = pstEntry->InMemoryOrderModuleList.Blink

pstEntry->InMemoryOrderModuleList.Blink->Flink = pstEntry->InMemoryOrderModuleList.Flink

DebugOut( _T( "Hide injected dll."))

break

}

Current = pstEntry->InMemoryOrderModuleList.Flink

}

DebugOutW( L"\r\n")

ListHead = &( stInfo.PebBaseAddress->Ldr->InInitializationOrderModuleList)

Current = ListHead->Flink

while ( Current != ListHead)

{

pstEntry = CONTAINING_RECORD( Current, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList)

DebugOutW( L"Module:%s, base:0x%X\r\n", pstEntry->FullDllName.Buffer, pstEntry->EntryPoint)

if ( pstEntry->DllBase == hModMyself)

{

pstEntry->InInitializationOrderModuleList.Flink->Blink = pstEntry->InInitializationOrderModuleList.Blink

pstEntry->InInitializationOrderModuleList.Blink->Flink = pstEntry->InInitializationOrderModuleList.Flink

DebugOut( _T( "Hide injected dll."))

break

}

Current = pstEntry->InInitializationOrderModuleList.Flink

}

//DebugOut( _T("Out HideMyself\r\n"))

return TRUE

}

这样处理之后,通过常规的枚举进程方式已经枚举不到隐藏模块,ProcessExplorer也无法枚举。但是,通过枚举进程内存空间等非常规方法,仍然是可以找到的。关于PSAPI和Toolhelp函数枚举模块的原理,可以逆向Windows代码,或者查找网上的代码看看就明白了。

author:forget

HideModuleFromPEB proc hInstDLL:DWORD

assume fs:nothing

mov esi,hInstDLL

xor eax,eax

mov eax,fs:[eax].TEB.Peb

mov eax,[eax].PEB.Ldr

lea eax,[eax].PEB_LDR_DATA.InLoadOrderModuleList

@@:

mov eax,[eax].LDR_MODULE.InLoadOrderModuleList.Flink

cmp esi,[eax].LDR_MODULE.BaseAddress

jnz @B

mov esi,[eax].LIST_ENTRY.Flink

mov ebx,[eax].LIST_ENTRY.Blink

mov [ebx].LIST_ENTRY.Flink,esi

mov esi,[eax].LIST_ENTRY.Blink

mov ebx,[eax].LIST_ENTRY.Flink

mov [ebx].LIST_ENTRY.Blink,esi

lea eax,[eax].LDR_MODULE.InMemoryOrderModuleList

mov esi,[eax].LIST_ENTRY.Flink

mov ebx,[eax].LIST_ENTRY.Blink

mov [ebx].LIST_ENTRY.Flink,esi

mov esi,[eax].LIST_ENTRY.Blink

mov ebx,[eax].LIST_ENTRY.Flink

mov [ebx].LIST_ENTRY.Blink,esi

ret

HideModuleFromPEB endp

我也来段 占内存用的,其中testdll是隐式连接。

void *PEB = NULL

void *Ldr = NULL

_LIST_ENTRY *Flink = NULL

_LIST_ENTRY *p = NULL

BYTE *BaseAddress = NULL

BYTE *FullDllName = NULL

__asm

{

mov eax,fs:[0x30]

mov PEB,eax

}

Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) )

Flink = (_LIST_ENTRY*)*( ( void ** )( ( unsigned char * )Ldr+ 0x0c ) )

p = Flink

do

{

BaseAddress = *( ( BYTE ** )( ( unsigned char * )p+ 0x18 ) )

FullDllName = *( ( BYTE ** )( ( unsigned char * )p+ 0x28 ) )

LPSTR strFullDllName

UnicodeToAnsi((LPCOLESTR)FullDllName,&strFullDllName)

if( strFullDllName )

{

if( strstr(strFullDllName,"testdll") )

{

*(LPDWORD)((LPBYTE)p + 0x38) = 1

}

}

CO_SAFE_DELETE(strFullDllName)

p = p->Flink

}

while ( Flink != p )

FreeLibrary(GetModuleHandle("testdll.dll"))

LPVOID lpdata = VirtualAlloc((LPVOID)NULL,1024*1024*6,MEM_COMMIT,PAGE_EXECUTE_READWRITE)

if( lpdata != (LPVOID)0x400000 )

{

return FALSE

}

都发代码片段,我也来一个

while(modulo->BaseAddress != 0)

{

if( (ULONG_PTR)modulo->BaseAddress == DllHandle)

{

if(modulo->InInitializationOrderModuleList.Blink == NULL) return FALSE

prec = (LDR_MODULE*)(ULONG_PTR)((ULONG_PTR)modulo->InInitializationOrderModuleList.Blink - 16)

next = (LDR_MODULE*)(ULONG_PTR)((ULONG_PTR)modulo->InInitializationOrderModuleList.Flink - 16)

prec->InInitializationOrderModuleList.Flink = modulo->InInitializationOrderModuleList.Flink

next->InInitializationOrderModuleList.Blink = modulo->InInitializationOrderModuleList.Blink

prec = (LDR_MODULE*)modulo->InLoadOrderModuleList.Blink

next = (LDR_MODULE*)modulo->InLoadOrderModuleList.Flink

prec->InLoadOrderModuleList.Flink = modulo->InLoadOrderModuleList.Flink

prec->InMemoryOrderModuleList.Flink = modulo->InMemoryOrderModuleList.Flink

next->InLoadOrderModuleList.Blink = modulo->InLoadOrderModuleList.Blink

next->InMemoryOrderModuleList.Blink = modulo->InMemoryOrderModuleList.Blink

return TRUE

}

modulo = (LDR_MODULE*)modulo->InLoadOrderModuleList.Flink

}

通过VirtualQueryEx函数列举出进程内虚拟内存的段,然后根据PE结构和内存属性来定位Image文件的映像基地址,即可确认以下三项数据, 该数据是连续的,

PVOID DllBase

PVOID EntryPoint

ULONG SizeOfImage

在内存中搜索这个三个数据,即可定位LDR。

iceword 可能查出


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12298554.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存