最后我们通过输入!peb命令,输出当前所有载入模块并验证一下:
既然有了如上所述的方法,那么读者可以很容易的实现这段功能,为了便于读者理解,笔者先提供一段使用C语言书写的实现方式,如下代码所示;
#include
【1.5 编写自定位ShellCode弹窗】运行输出效果如下图所示,读者可自行检查读取结果的准确性;
将此段代码翻译为汇编模式也很容易,如下是通过汇编实现的流程;
文章插图
.386p.model flat,stdcalloption casemap:noneinclude windows.incinclude kernel32.incincludelib kerbcli.libassume fs:nothing.codemain PROCxor eax,eaxxor edx,edxmov eax,fs:[30h]; 得到PEB结构地址mov eax,[eax + 0ch]; 得到PEB_LDR_DATA结构地址mov esi,[eax + 1ch]; 得到 InInitializationOrderModuleListlodsd; 得到KERNEL32.DLL所在LDR_MODULE结构的mov eax,[eax]; Windows 7 以上要将这里打开mov edx,[eax + 8h]; 得到BaseAddress,既Kernel32.dll基址retmain ENDPEND main
1.5.2 动态查找并枚举进程模块
在读者阅读过第一节中的内容时,相信您已经可以熟练的掌握调试器的基本使用了,本节我们将扩展一个知识点,以让读者能更好的理解调试命令,本次我们实现枚举进程模块的功能,本案例将不在解释基本功能 。
通过PEB/TEB找到自身进程的所有载入模块数据,首先获取TEB线程环境块 。在编程的时候,TEB始终保存在寄存器FS中 。
得到LDR结构:Ldr = *( ( DWORD ** )( (char * )PEB + 0x0c ) );
然后再找到PEB结构偏移为0x30从该命令的输出可以看出,PEB结构体的地址位于TEB结构体偏移0x30的位置处 。
找到了PEB也就可以找到结构 其位于PEB偏移0c的位置上 。
Ldr = *( ( DWORD ** )( (char * )PEB + 0x0c ) );
从输出结果可以看出,LDR在PEB结构体偏移的0x0C处,该地址保存的地址是通过该地址来解析LDR结构体 。
Flink = *( ( DWORD ** )( (char * )Ldr + 0x14 ) );
位于LDR偏移14的位置就是t其所指向的就是模块名称表 。
现在来手动遍历[-]第一条链表,输入命令dd
链表偏移0x18的位置是模块的映射地址,链表偏移 0x28 的位置是模块的路径及名称的地址,链表偏移 0x30 的位置是模块名称的地址 。
如上图中的输出结果,地址保存有当前模块详细路径信息,而则保存有当前模块名,我们可以通过du命令来进行验证;
当读者需要读入下一个模块链表时,则需要访问这个内存地址,其中保存着下一个链表结构,依次遍历 。
当然这个链表结构其实访问ist同样可以得到,这两个都指向同一片区域 。
上方介绍的结构,是微软保留结构,只能从网上找到一个结构定义,根据该结构的定义做进一步解析即可 。
typedef struct _LDR_DATA_TABLE_ENTRY {PVOID Reserved1[2];LIST_ENTRY InMemoryOrderLinks;PVOID Reserved2[2];PVOID DllBase;PVOID EntryPoint;PVOID Reserved3;UNICODE_STRING FullDllName;BYTE Reserved4[8];PVOID Reserved5[3];union {ULONG CheckSum;PVOID Reserved6;};ULONG TimeDateStamp;} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
- 如果可以爱台湾版
- 卡度士自旋翼机
- 马肉刺身
- 全国自驾路线查询
- 不务正业?黑莓设立自动驾驶测试中心
- 关门山门票
- A股历史上十大牛股竟有6成都来自这个板块 中国股市历年十大牛股
- 莫干山自驾游
- android自动黏贴功能,未来Android拥有拖拽复制粘贴功能
- 口水鸡排