http://bbs.pediy.com/showthread.php?p=583402
网上的一段代码 通过内存搜索EPROCESS来枚举进程
在我的xp sp2系统上测试 只能枚举出三个进程 这是为什么?
关键代码如下:
代码:
VOID searchprocess(void)
{
ULONG i;
ULONG result;
for (i = 0x80000000 ;i<0x90000000;i+=4){
result = validpage(i);
if (result == VALID){
if (*(PULONG)i == 0x7ffdf000){
if(IsARealProcess(i)){
DbgPrint("EPROCESS: 0x%x ",i-PEB_OFFSET);
getname(i);
}
}
}
else if(result == PTE_INVALID){
i -=4;
i += 0x1000;//4k
}
else{
i-=4;
i+= 0x400000;//4mb
}
}
for (i = 0xf0000000 ;i<0xffbe0000;i+=4){
result = validpage(i);
if (result == VALID){
if (*(PULONG)i == 0x7ffdf000){
if(IsARealProcess(i)){
DbgPrint("EPROCESS: 0x%x ",i-PEB_OFFSET);
getname(i);
}
}
}
else if(result == PTE_INVALID){
i -=4;
i += 0x1000;//4k
}
else{
i-=4;
i+= 0x400000;//4mb
}
}
DbgPrint("searching finish /n");
}
//--------------------------------------------------------------------
VOID getname(ULONG Addr)
{
DbgPrint("process name: %s/n",(PCHAR)(Addr-PEB_OFFSET+EPROCESS_NAME_OFFSET));
}
//--------------------------------------------------------------------
ULONG validpage(ULONG Addr)
{
ULONG pte;
ULONG pde;
pde = 0xc0300000 + (Addr>>22)*4;
if((*(PULONG)pde & 0x1) != 0){
//lArge pAge
if((*(PULONG)pde & 0x80) != 0){
return VALID;
}
pte = 0xc0000000 + (Addr>>12)*4;
if((*(PULONG)pte & 0x1) != 0){
return VALID;
}
else{
return PTE_INVALID;
}
}
return PDE_INVALID;
}
//--------------------------------------------------------------------
BOOLEAN IsARealProcess(ULONG i)
{
NTSTATUS status;
PUNICODE_STRING pUnicode;
UNICODE_STRING Process;
ULONG pObjectType;
ULONG pObjectTypeProcess;
pObjectTypeProcess = *(PULONG)((ULONG)PsGetCurrentProcess() -OBJECT_HEADER_SIZE +OBJECT_TYPE_OFFSET);
if (validpage(i-PEB_OFFSET) != VALID){
return FALSE;
}
if (validpage(i-PEB_OFFSET - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET) == VALID){
pObjectType = *(PULONG)(i-PEB_OFFSET - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET);
}
else{
return FALSE;
}
if(pObjectTypeProcess == pObjectType){
return TRUE;
}
return FALSE;
}
*(PULONG)i == 0x7ffdf000
以上代码判断一个进程的关键是在这里,即只有当进程的PEB结构指针是0x7ffdf000你才能找到它。
但是在XP SP2系统下,进程PEB结构位置是不定的,并不固定为0x7ffdf000。
你可以自己在windbg里试一试看看系统当前所有进程的PEB就会发现这个问题了。
如在我的XP SP3下,我刚刚试了一下:
lkd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 855b6830 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 05990020 ObjectTable: e1003df8 HandleCount: 437.
Image: System
PROCESS 84c4d020 SessionId: none Cid: 046c Peb: 7ffde000 ParentCid: 0004
DirBase: 05990040 ObjectTable: e100dc10 HandleCount: 19.
Image: smss.exe
PROCESS 84bfb020 SessionId: 0 Cid: 04b0 Peb: 7ffd8000 ParentCid: 046c
DirBase: 05990060 ObjectTable: e188da08 HandleCount: 702.
Image: csrss.exe
PROCESS 84bf2a90 SessionId: 0 Cid: 04cc Peb: 7ffde000 ParentCid: 046c
DirBase: 05990080 ObjectTable: e188f170 HandleCount: 526.
Image: winlogon.exe
PROCESS 84b2bc10 SessionId: 0 Cid: 04f8 Peb: 7ffd4000 ParentCid: 04cc
DirBase: 059900a0 ObjectTable: e1d60518 HandleCount: 310.
Image: SERVICES.EXE
PROCESS 84b363c0 SessionId: 0 Cid: 0504 Peb: 7ffdd000 ParentCid: 04cc
DirBase: 059900c0 ObjectTable: e223c248 HandleCount: 477.
Image: LSASS.EXE
PROCESS 84b5eda0 SessionId: 0 Cid: 05c0 Peb: 7ffda000 ParentCid: 04f8
DirBase: 059900e0 ObjectTable: e236af00 HandleCount: 99.
Image: Ati2evxx.exe
PROCESS 84b59b28 SessionId: 0 Cid: 05e0 Peb: 7ffd7000 ParentCid: 04f8
DirBase: 05990100 ObjectTable: e23686c8 HandleCount: 196.
Image: SVCHOST.EXE
PROCESS 846313b0 SessionId: 0 Cid: 063c Peb: 7ffd5000 ParentCid: 04f8
DirBase: 05990140 ObjectTable: e19a3c08 HandleCount: 317.
Image: SVCHOST.EXE
(以下省略类似的条目)
你可以看到它们的PEB并不都是0x7ffdf000,这也就解释了你只能搜到一部分进程结构。
好像哪本书上说的XP SP2开始PEB结构位置才是不定的,在此之前好像就是固定为0x7ffdf000的,不知道我有没有记错。
xfocus的一篇文章《Windows XP Sp2溢出保护》中就提到了PEB的地址的随机,详见http://www.xfocus.net/articles/200412/762.html
这里还有一个问题
我把程序修改了一下 如下
代码:
VOID searchprocess(void)
{
ULONG i;
ULONG res;
for (i = 0x80000000; i < 0x90000000; i += 4)
{
res = validpage(i);
if (res == VALID)
{
DbgPrint("%x : %x/n", i, *(PULONG)i);
//if (*(PULONG)i == 0x7ffdf000)
if (*(PUCHAR)(i+0) == 0x00 &&
*(PUCHAR)(i+2) == 0xfd &&
*(PUCHAR)(i+3) == 0x7f &&
(*(PUCHAR)(i+1) & 0x0f) == 0)
{
if(IsARealProcess(i))
{
DbgPrint("EPROCESS: 0x%x ",i-PEB_OFFSET);
getname(i);
}
}
}
else if(res == PTE_INVALID)
{
DbgPrint("%x pte_invalid./n", i);
i -= 4;
i += 0x1000;//4k
}
else
{
DbgPrint("%x pde_invalid./n", i);
i -= 4;
i += 0x400000;//4mb
}
}
for (i = 0xf0000000; i < 0xffbe0000; i += 4)
{
res = validpage(i);
if (res == VALID)
{
//if (*(PULONG)i == 0x7ffdf000)
if (*(PUCHAR)(i+0) == 0x00 &&
*(PUCHAR)(i+2) == 0xfd &&
*(PUCHAR)(i+3) == 0x7f &&
(*(PUCHAR)(i+1) & 0x0f) == 0)
{
if(IsARealProcess(i))
{
DbgPrint("EPROCESS: 0x%x ",i-PEB_OFFSET);
getname(i);
}
}
}
else if(res == PTE_INVALID)
{
i -= 4;
i += 0x1000;//4k
}
else
{
i -= 4;
i += 0x400000;//4mb
}
}
DbgPrint("searching finish /n");
windows xp sp2 的页目录是0xc0600000 而且是PAE(物理地址扩展)模式 计算方法有些不同的 2000的 具体请反汇编xp sp2 的涵数MmIsAddressValid() 就比较清楚
}
可是在我的主机上却没有成功
从80000000到90000000全部显示pde_invalid
这是怎么回事?