1.5 编写自定位ShellCode弹窗( 二 )


最后我们通过输入!peb命令,输出当前所有载入模块并验证一下:
既然有了如上所述的方法,那么读者可以很容易的实现这段功能,为了便于读者理解,笔者先提供一段使用C语言书写的实现方式,如下代码所示;
#include #include int main(int argc, char * argv[]){DWORD *PEB = NULL;DWORD *Ldr = NULL;DWORD *Init = NULL;DWORD *Kernel32 = NULL;__asm{mov eax, fs:[0x30]mov PEB,eax}printf("得到PEB指针 = %x \n", PEB);Ldr = *(DWORD **)((unsigned char *)PEB + 0x0c);printf("得到LDR结构指针 = %x \n", Ldr);Init = *(DWORD **)((unsigned char *)Ldr + 0x1c);printf("得到InInitializationOrderModuleList结构指针 = %x \n", Init);Kernel32 = *(DWORD **)((unsigned char *)Init + 0x08);printf("得到Kernel32的基地址 = %x \n", Kernel32);system("pause");return 0;}
【1.5 编写自定位ShellCode弹窗】运行输出效果如下图所示,读者可自行检查读取结果的准确性;
将此段代码翻译为汇编模式也很容易,如下是通过汇编实现的流程;

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;