通过EPROCESS枚举进程

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()  就比较清楚


}
在xp sp2的虚拟机中成功的搜索出系统里的进程
可是在我的主机上却没有成功
从80000000到90000000全部显示pde_invalid
这是怎么回事?


你可能感兴趣的:(通过EPROCESS枚举进程)