路飞 发表于 2012-6-3 15:35:55

暴力搜索内存枚举进程

这个网上资料很多,不过我找到的都没有考虑到PAE的因素,下面是一些PAE的资料
Physical Address Extension, in computing, a CPU capability for addressing more physical memory than its address space size

开启或者关闭PAE模式的话通过修改BOOT.ini进行,我虚拟机里面的XP系统默认在没有/PAE参数和/noexecute=optin的时候是开启PAE模式的,所以起初我搜索了很多网上的代码都枚举不出进程
关闭的话把/noexecute=optin改成/execute就可以
具体资料参考这里:PAE模式

由于我的测试环境是XPSP2,所以接下去没特殊说明都是指这个环境

现在来明确一下我们的方法,在指定的内存范围当中按照某些特征对有效的内存地址进行搜索枚举出EProcess
1.内存范围:
从MmSystemRangeStart(0x80000000)到System进程的EProcess地址+一定量偏移
加上一定偏移是为了保险起见 :D   如何验证?用!process 0 0
相关代码:
SysEProcess = (DWORD)PsGetCurrentProcess () ;   
dwStart = *(PDWORD)MmSystemRangeStart ;//0x80000000
dwEnd = 0x800000 + SysEProcess ;
for( i = dwStart; i < dwEnd; i += 4 )
{}
关于MmSystemRangeStart:
我起初用EasySYS生成VC2005版本的里面调用MmSystemRangeStart会蓝屏,捣鼓了很久以后发现生产VC6.0版本的话不会蓝屏...
生成的VC6.0换成VC2005跟直接生产VC2005版本的是不一样的,自己看看就知道了
2某些特征:
所有的PEB地址都符合0x7FFDXXXX的特征
PROCESS 81fb7830 SessionId: none Cid: 0004    Peb: 00000000 ParentCid: 0000
    DirBase: 027c0000 ObjectTable: e1002e40 HandleCount: 339.
    Image: System

PROCESS 81ef4b18 SessionId: none Cid: 022c    Peb: 7ffd8000 ParentCid: 0004
    DirBase: 07bcc000 ObjectTable: e12eff28 HandleCount: 21.
    Image: smss.exe

PROCESS 81a7e5a0 SessionId: 0 Cid: 025c    Peb: 7ffd8000 ParentCid: 022c
    DirBase: 085d8000 ObjectTable: e12ecc48 HandleCount: 374.
    Image: csrss.exe

PROCESS 81a4c480 SessionId: 0 Cid: 0274    Peb: 7ffd8000 ParentCid: 022c
    DirBase: 0899d000 ObjectTable: e1012120 HandleCount: 455.
这样子就看得出来了,不过为了科学验证于是我们去摸索WRK,下面是我抠出来的代码,拿去运行一次就知道了
#define MmHighestUserAddress 0x7FFEFFFF
#define MM_HIGHEST_USER_ADDRESS MmHighestUserAddress
#define MM_HIGHEST_VAD_ADDRESS ((PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (64 * 1024)))

#define PAGE_SHIFT 12L
#define X64K (ULONG)65536

int main()
{
    PVOID HighestVadAddress = (PVOID) ((PCHAR)MM_HIGHEST_VAD_ADDRESS + 1);
   LARGE_INTEGER CurrentTime;
   CurrentTime.LowPart &= ((X64K >> PAGE_SHIFT) - 1);
   HighestVadAddress = (PVOID) ((PCHAR)HighestVadAddress - (CurrentTime.LowPart << PAGE_SHIFT));
    return    0;
}
当然这个还是不推荐使用硬编码,你可以按照如下写法,获取0x7FFD0000
CurEProcess = (ULONG)((PLIST_ENTRY)((ULONG)SysEProcess + dwProcessLinkOffset))->Flink - dwProcessLinkOffset;
dwPebHigh = *(PULONG)(CurEProcess + dwPebOffset);
dwPebHigh = dwPebHigh & 0xFFFF0000;

还有个特征就是对象类型要跟System的一样,System进程的EProcess可以用PsGetCurrentProcess获得(FS:)
3.判断内存是否有效.
具体可以参考MmIsAddressValid写一个,不过为了加快搜索,我们要做一些判断,于是下面是我参考了MmIsAddressValid写的一个函数
具体的也可以参考这篇,可以理解对于PAE模式相关判断透过MmIsAddressValid看Windows分页机制

PAGE_STATUS hypIsAddressValid ( ULONG VirtualAddress )   
{   
    typedef struct _MMPTE_HARDWARE {
      ULONG Valid : 1;
#if defined(NT_UP)
      ULONG Write : 1;       // UP version
#else
      ULONG Writable : 1;    // changed for MP version
#endif
      ULONG Owner : 1;
      ULONG WriteThrough : 1;
      ULONG CacheDisable : 1;
      ULONG Accessed : 1;
      ULONG Dirty : 1;
      ULONG LargePage : 1;
      ULONG Global : 1;
      ULONG CopyOnWrite : 1; // software field
      ULONG Prototype : 1;   // software field
#if defined(NT_UP)
      ULONG reserved : 1;    // software field
#else
      ULONG Write : 1;       // software field - MP change
#endif
      ULONG PageFrameNumber : 20;
   } MMPTE_HARDWARE, *PMMPTE_HARDWARE;

    typedef struct _MMPTE {
      union   {
            ULONG Long;
             MMPTE_HARDWARE Hard;
         } u;
   } MMPTE , *PMMPTE;

   PMMPTE PointerPde;
   PMMPTE PointerPte;

#define PTE_BASE       0xC0000000
#define PTE_BASE_PAE   0xC0000000
#define PDE_BASE       0xC0300000
#define PDE_BASE_PAE   0xC0600000
#define MiGetPdeAddress(va)   ((PMMPTE)(((((ULONG)(va)) >> 22) << 2) + PDE_BASE))
#define MiGetPdeAddressPAE(va) ((PMMPTE)(((((ULONG)(va)) >> 21) << 3) + PDE_BASE_PAE))
#define MiGetPteAddress(va)   ((PMMPTE)(((((ULONG)(va)) >> 12) << 2) + PTE_BASE))
#define MiGetPteAddressPAE(va) ((PMMPTE)(((((ULONG)(va)) >> 12) << 3) + PTE_BASE_PAE))

    DWORD cr4;
   __asm
   {
         _emit 0x0f
         _emit 0x20
         _emit 0xE0    //mov eax,cr4
         mov cr4,eax
   }
    /*
   ? If PAE (bit 5) is 0 in control register CR4, paging translates from 32-bit linear addresses
         to 32-bit physical addresses. (This mode can translate to 36-bit physical addresses, but
         only for large pages.) This mode is described in more detail in Section 8.2.
   ? If CR4.PAE = 1 and LMA (bit 10) is 0 in the IA32_EFER MSR, paging translates from
         32-bit linear addresses to 36-bit physical addresses. This mode is described in more
         detail in Section 8.1.
   */
    if ( cr4 & 0x20 )    //PAE bit
   {
         PointerPde = MiGetPdeAddressPAE (VirtualAddress);
         PointerPte = MiGetPteAddressPAE (VirtualAddress);
   }
   else
   {
         PointerPde = MiGetPdeAddress (VirtualAddress);
         PointerPte = MiGetPteAddress (VirtualAddress);
   }
   
    if (PointerPde->u.Hard.Valid == 0)
   {
      return INVALID_PDE;
   }

#define MI_PDE_MAPS_LARGE_PAGE(PDE) ((PDE)->u.Hard.LargePage == 1)

    if (MI_PDE_MAPS_LARGE_PAGE (PointerPde))
   {
      return VALID_PAGE;
   }

    if (PointerPte->u.Hard.Valid == 0)
   {
      return INVALID_PTE;
   }

    return VALID_PAGE ;   
}
大体就这样,完整代码就不发了,网上多得是拿来然后照着hypIsAddressValid的方法判断PAE就可以了,希望大家都能做出来
O(∩_∩)O~
页: [1]
查看完整版本: 暴力搜索内存枚举进程