通过PEB遍历当前进程中的模块(C语言实现)

摘要:
0x00相关描述:如果Windows应用程序层希望遍历当前进程加载的模块,则可以使用WIN32API通过进程快照通过PEB遍历进程模块。没有使用WIN32API的痕迹。在某些情况下,最好使用32位应用程序的PEB地址。可以通过fs:[0x30]获得,fs:[0]是TEB结构的地址0x01。相关数据结构:可以使用命令在windg中查看以下数据结构(使用dt<数据结构名称>)类型定义
0x00 相关说明:

Windows应用层如果要遍历当前进程所加载的模块可以使用WIN32API通过进程快照来实现

通过PEB来遍历进程模块没有WIN32API的使用痕迹,在某些场合更加好用

其中32位应用程序的PEB 的地址可以通过 fs:[0x30]获取,fs:[0]为TEB结构的地址

0x01 相关数据结构:

下面的数据结构可以在windbg中使用命令查看(使用 dt <数据结构名称>)

typedef  struct  _TEB {  //fs:[0]
     NT_TIB                  Tib;
     PVOID                   EnvironmentPointer;
     CLIENT_ID               Cid;
     PVOID                   ActiveRpcInfo;
     PVOID                   ThreadLocalStoragePointer;
     PPEB                    Peb;
     //......
} TEB, * PTEB;

typedef  struct  _PEB {  //fs:[0x30]
     BYTE InheritedAddressSpace;
     BYTE ReadImageFileExecOptions;
     BYTE BeingDebugged;
     BYTE BitField;
     PVOID Mutant;
     PVOID ImageBaseAddress;
     PPEB_LDR_DATA Ldr;
     //......
} PEB, * PPEB;

typedef  struct  _PEB_LDR_DATA {
     UINT Length;
     BYTE Initialized;
     PVOID SsHandle;
     LIST_ENTRY InLoadOrderModuleList;
     LIST_ENTRY InMemoryOrderModuleList;
     LIST_ENTRY InInitializationOrderModuleList;
     //......
} PEB_LDR_DATA, * PPEB_LDR_DATA;

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;
     //......
} _LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

typedef  struct  _UNICODE_STRING {
     USHORT  Length;
     USHORT  MaximumLength;
     PWSTR  Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

typedef  struct  _CLIENT_ID {
     PVOID UniqueProcess;
     PVOID UniqueThread;
} CLIENT_ID, * PCLIENT_ID;

0x02 实现原理:

结构索引流程如下:

1

其中各个_LDR_DATA_TABLE_ENTRY结构的关系如下:(以3个模块为例)

2

其中 InLoadOrderLinks、InMemoryOrderLinks、InInitializationOrderLinks 均为:LIST_ENTRY

0x03 代码实现:

代码实现如下:(记得自行添加前面介绍的相关结构定义):

int main(int argc, char* argv[])
{
     PPEB pPEB = (PPEB)__readfsdword(0x30);
     PPEB_LDR_DATA pLdr = pPEB->Ldr;

    DWORD dwFixOffset=0;
     PLDR_DATA_TABLE_ENTRY pBase, pNext;

    printf("Enum InLoadOrderModuleList: ");
     dwFixOffset = 0;
     pBase = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pLdr->InLoadOrderModuleList.Flink) - dwFixOffset);
     pNext = pBase;
     do {
         wprintf_s(L"%s ", pNext->FullDllName.Buffer);
         pNext = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pNext->InLoadOrderLinks.Flink) - dwFixOffset);
     } while (pBase != pNext);
     printf("Enum InLoadOrderModuleList End! ");

    printf("Enum InMemoryOrderModuleList: ");
     dwFixOffset = (DWORD) & (pBase->InMemoryOrderLinks) - (DWORD)pBase;
     pBase = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pLdr->InMemoryOrderModuleList.Flink) - dwFixOffset);
     pNext = pBase;
     do {
         wprintf_s(L"%s ", pNext->FullDllName.Buffer);
         pNext = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pNext->InMemoryOrderLinks.Flink) - dwFixOffset);
     } while (pBase != pNext);
     printf("Enum InMemoryOrderModuleList End! ");

    printf("Enum InInitializationOrderModuleList: ");
     dwFixOffset = (DWORD) & (pBase->InInitializationOrderLinks) - (DWORD)pBase;
     pBase = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pLdr->InInitializationOrderModuleList.Flink) - dwFixOffset);
     pNext = pBase;
     do {
         wprintf_s(L"%s ", pNext->FullDllName.Buffer);
         pNext = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pNext->InInitializationOrderLinks.Flink) - dwFixOffset);
     } while (pBase != pNext);
     printf("Enum InInitializationOrderModuleList End! ");


     system("pause");
     return 0;
}

代码执行结果:

3

免责声明:文章转载自《通过PEB遍历当前进程中的模块(C语言实现)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇将某个div内容保存成图片,使用html2canvas截图方法(高清图并解决图片跨域问题)用jsmooth + inno生成exe并制作简单安装包下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python遍历文件夹下的文件

python遍历文件夹下的文件 在读文件的时候往往需要遍历文件夹,python的os.path包含了很多文件、文件夹操作的方法。下面列出: os.path.abspath(path) #返回绝对路径 os.path.basename(path) #返回文件名 os.path.commonprefix(list) #返回多个路径中,所有path共有的最长的路...

对数组名取地址 a[ ],&amp;amp;a

C语言规定,数组名代表数组的首地址,也就是第0号元素的地址。所以a==&a[0] 但对数组名取地址时却要注意了,在理解“对数组名取地址”这一表达式的含义时一定要记住:数组名是“数组”这种变量的变量名 这样,&a就好理解了,它取的是“数组”这种变量的地址 &a+1自然也就要跨过整个数组,所有元素长度总和,这么长的一个长度。例如:int...

数据结构C语言实现----销毁链表

1.首先,将*list(头指针)赋值给p,这样p也指向链表的第一个结点,成为链表的表头 2.然后判断只要p不为空,就将p指向下一个的指针赋值给q,再释放掉p 3.之后再将q赋值给p,用来找到下一轮释放掉的结点的下一个结点 代码如下: #include<stdio.h> #include<stdlib.h> typedef stru...

C++之匿名对象解析

我们知道在C++的创建对象是一个费时,费空间的一个操作。有些固然是必不可少,但还有一些对象却在我们不知道的情况下被创建了。通常以下三种情况会产生临时对象: 1,以值的方式给函数传参; 2,类型转换; 3,函数需要返回一个对象时; 现在我们依次看这三种情况: 一,以值的方式给函数传参。 我们知道给函数传参有两种方式。1,按值传递;2,按引用传递。按值传递时,...

MYSQL常用命令集合(转载)

文章出处:http://www.cnblogs.com/q1ng/p/4474501.html 1.导出整个数据库mysqldump -u 用户名 -p --default-character-set=latin1 数据库名 > 导出的文件名(数据库默认编码是latin1)mysqldump -u wcnc -p smgp_apps_wcnc >...

grep 命令 --在文件中搜索文本工具

grep命令      文件过滤分割与合并 grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。 Linux grep 命令用于查找文件里符合条件的字符串 语法...