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

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 实现原理:

结构索引流程如下:

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

其中 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:\r\n");
     dwFixOffset = 0;
     pBase = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pLdr->InLoadOrderModuleList.Flink) - dwFixOffset);
     pNext = pBase;
     do {
         wprintf_s(L"%s\r\n", pNext->FullDllName.Buffer);
         pNext = (PLDR_DATA_TABLE_ENTRY)((DWORD)(pNext->InLoadOrderLinks.Flink) - dwFixOffset);
     } while (pBase != pNext);
     printf("Enum InLoadOrderModuleList End!\r\n\r\n");

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

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

system("pause");
     return 0;
}

代码执行结果:

原文地址:https://www.cnblogs.com/DarkBright/p/10865193.html

时间: 2024-11-05 19:43:16

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

VC中遍历目标进程中的模块

VC中遍历目标进程中的模块 MFC代码win32 也可以用 在下面代码进行修改转换就可以了CString strModule; 可以换成 char* 但是MODULEENTRY32结构中的szModule是WCHAR 由于博主基础知识较差 所以使用的MFC里的Cstring函数 #include <Tlhelp32.h> /***************************************************/ /* 函数: 查找目标进程中是否有指定模块信息 /* 参数:DWO

学习笔记之卸载远程目标进程中的DLL模块(转)

学习笔记之卸载远程目标进程中的DLL模块 (2007-07-23 23:51:02) 转载▼ 学习笔记之卸载远程目标进程中的DLL模块2007/7/231.首先得把DLL模块中的线程结束使用CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);创建系统线程的快照然后用Thread32First()和Thread32Next()遍历系统中所有线程.将遍历到的线程保存到THREADENTRY32结构,然后判断结构中的th32OwnerProcessID成员是否与

使用ptrace向已运行进程中注入.so并执行相关函数(转)

1. 简介 使用ptrace向已运行进程中注入.so并执行相关函数,其中的“注入”二字的真正含义为:此.so被link到已运行进程(以下简称为:目标进程)空间中,从而.so中的函数在目标进程空间中有对应的地址,然后通过此地址便可在目标进程中进行调用. 到底是如何注入的呢? 本文实现方案为:在目标进程中,通过dlopen把需要注入的.so加载到目标进程的空间中. 2. 如何让目标进程执行dlopen加载.so? 显然,目标进程本来是没有实现通过dlopen来加载我们想注入的.so,为了实现此功能,

使用ptrace向已运行进程中注入.so并执行相关函数

这个总结的很好,从前一个项目也用到这中技术 转自:http://blog.csdn.net/myarrow/article/details/9630377 1. 简介 使用ptrace向已运行进程中注入.so并执行相关函数,其中的“注入”二字的真正含义为:此.so被link到已运行进程(以下简称为:目标进程)空间中,从而.so中的函数在目标进程空间中有对应的地址,然后通过此地址便可在目标进程中进行调用. 到底是如何注入的呢? 本文实现方案为:在目标进程中,通过dlopen把需要注入的.so加载到

手把手教你R0下通过EPROCESS获取进程加载模块

在R3下获取一个进程加载的相关模块儿还是比较简单的,直接通过ToolHelp32库API就能够获取到进程关联的模块儿了,但是既然已经在R0下混了再去使用R3层的东西就没什么意义了,所以这里小悠在这里将会一部一部的介绍如何在R0下通过EPROCESS结构获取到进程加载的模块. 首先这里我们先介绍一下我们通过EPROCESS查询的大概思路 ①  通过EPROCESS 获取到对应的PEB 结构 ②  通过PEB找到 _PEB_LDR_DATA这货 ③  在_PEB_LDR_DATA内部有3个LIST_

Node.js中的模块机制

本文为读书笔记. 一.CommonJS的模块规范 Node与浏览器以及 W3C组织.CommonJS组织.ECMAScript之间的关系 Node借鉴CommonJS的Modules规范实现了一套模块系统,所以先来看看CommonJS的模块规范. CommonJS对模块的定义十分简单,主要分为模块引用.模块定义和模块标识3个部分. 1. 模块引用 模块引用的示例代码如下: var math = require('math'); 在CommonJS规范中,存在require()方法,这个方法接受模

Python中time模块详解

在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. 在开始之前,首先要说明这几点: 在Python中,通常有这几种方式来表示时间:1)时间戳 2)格式化的时间字符串 3)元组(struct_time)共九个元素.由于Python的time模块实现主要调用C库,所以各个平台可能有所不同. UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间.在中国为UTC+8.DST

跟我一起学extjs5(13--执行菜单命令在tabPanel中显示模块)

跟我一起学extjs5(13--执行菜单命令在tabPanel中显示模块) 上面设计好了一个模块的主界面,下面通过菜单命令的执行来把这个模块加入到主界面当中.在MainModule.js中有一个函数,生成了当前的菜单数据: // 根据data.systemMenu生成菜单条和菜单按钮下面使用的菜单数据 getMenus : function() { var items = []; var menuData = this.get('systemMenu'); // 取得定义好的菜单数据 Ext.A

Windows编程 - 遍历所有进程(exe) 代码(C++)

遍历所有进程(exe) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/29381987 遍历所有进程, 即任务管理器中所有的进程目录, 包含名称和进程ID. 返回字典: Key: 进程名字, Value: 进程ID. 代码: /* * main.cpp * * Created on: 2014.06.08 * Author: Spike */ /*vs 2012*/ #include <iostream> #