http://www.voidcn.com/article/p-mxtmqdwk-bcu.html
这两天研究x64内 枚举进程模块(目前以PEB来枚举,断链无法显示),枚举64位进程还比较容易,但枚举32位进程刚开始没想通(经验少,知识也少,奋斗努力学啊)。
后来才知道x64位系统有两个PEB结构,一个对应64位的 PEB64,一个对应32位的PEB32。这两个PEB对应两个内核API(原先不知道32位对应的API,搞了两天也不得知,后来开着词霸去国外论坛找,才找到,我滴个汗啊,外文不好累死人啊大哭,最终还是国内相关文章太匮乏了)
对应64位进程获取PEB64:
函数原型:PPEB PsGetProcessPeb(PEPROCESS Process);
对应32位进程获取PEB32:
 函数原型:PPEB PsGetProcessWow64Process(PEPROCESS Process);
对应PEB解析进程模块实际就是找对应模块链表
PEB结构:PEB->Ldr->InLoadOrderModuleList->Flink
结构类型:_PEB->_PEB_LDR_DATA->_LDR_DATA_TABLE_ENTRY
这里我们要注意下_LDR_DATA_TABLE_ENTRY,默认在x64系统中_LDR_DATA_TABLE_ENTRY结构中所有数据类型对应的全是x64,如果我们要用x64的结构来对应32位进程模块是万万不可的,因为地址长度不一样,会造成数据读取错误。
这里直接给出我修改过数据类型的_LDR_DATA_TABLE_ENTRY,后面的数字对应的不同位数的进程
typedef struct _LDR_DATA_TABLE_ENTRY64
 {
 LIST_ENTRY InLoadOrderLinks;
 LIST_ENTRY InMemoryOrderLinks;
 LIST_ENTRY InInitializationOrderLinks;
 PVOID DllBase;
 PVOID EntryPoint;
 ULONG SizeOfImage;
 UNICODE_STRING FullDllName;
 UNICODE_STRING BaseDllName;
 ULONG Flags;
 USHORT LoadCount;
 USHORT TlsIndex;
 PVOID SectionPointer;
 ULONG CheckSum;
 PVOID LoadedImports;
 PVOID EntryPointActivationContext;
 PVOID PatchInformation;
 LIST_ENTRY ForwarderLinks;
 LIST_ENTRY ServiceTagLinks;
 LIST_ENTRY StaticLinks;
 PVOID ContextInformation;
 ULONG OriginalBase;
 LARGE_INTEGER LoadTime;
 } LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
typedef struct _LDR_DATA_TABLE_ENTRY32
 {
 LIST_ENTRY32 InLoadOrderLinks;
 LIST_ENTRY32 InMemoryOrderLinks;
 LIST_ENTRY32 InInitializationOrderLinks;
 ULONG DllBase;
 ULONG EntryPoint;
 ULONG SizeOfImage;
 UNICODE_STRING32 FullDllName;
 UNICODE_STRING32 BaseDllName;
 ULONG Flags;
 USHORT LoadCount;
 USHORT TlsIndex;
 LIST_ENTRY32 HashLinks;
 ULONG SectionPointer;
 ULONG CheckSum;
 ULONG TimeDateStamp;
 ULONG LoadedImports;
 ULONG EntryPointActivationContext;
 ULONG PatchInformation;
 LIST_ENTRY32 ForwarderLinks;
 LIST_ENTRY32 ServiceTagLinks;
 LIST_ENTRY32 StaticLinks;
 ULONG ContextInformation;
 ULONG OriginalBase;
 LARGE_INTEGER LoadTime;
 } LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
我原来一直以为UNICODE_STRING 在内存中应该是一个变量地址,地址里面才是真正的数据,昨天仔细看了下内存才发现,这货直接把体内变量的数据直接就这么扔在外面了,三个红框分别是对应的Length,MaximumLength,Buffer
枚举模块具体怎么编码就是个人问题了,容易出错的地方注意些其他都是小意思了,不过这里还有个小问题,
就是我的32位模块有些枚举出来的是在system32目录下(不应该啊),但PCHunter显示的却是syswow64目录下,如果有朋友能帮我指出是哪里的问题,万分感激。
还有一些小情况,由于32位进程部分模块是在64位PEB里面存放着的,比如wow64.dll,枚举时需要同时使用PEB64和PEB32一起枚举(但会出现两条同样的数据—进程路径,忽略掉一条就行了)
59316022
