1.5 编写自定位ShellCode弹窗

在笔者上一篇文章中简单的介绍了如何运用汇编语言编写一段弹窗代码,虽然简易可以被正常执行,但却存在很多问题,由于采用了硬编址的方式来调用相应API函数的,那么就会存在一个很大的缺陷,如果操作系统的版本不统或系统重启过,那么基址将会发生变化,此时如果再次调用基址参数则会调用失败,本章将解决这个棘手的问题,通过动态定位的方式解决这个缺陷,并以此设计出真正符合规范的代码片段 。
自定位代码是一种常见的技术,它使能够在任何系统上运行,而无需考虑系统内存布局和代码地址等问题 。以下是自定位代码的流程:
1.5.1 动态查找基址
首先我们需要通过汇编的方式来实现动态定位.dll中的基址,你或许会有个疑问? 为什么要查找.dll的地址而不是.dll,这是因为我们最终的目的是调用这个函数,而该函数位于 .dll这个动态链接库里,在某些程序中模块并不一定会被加载,而则必然会被加载,为了能够调用函数,我们就需要调用函数来加载.dll这个模块,而恰巧又位于.dll中,因此我们只需要找到函数,即可实现加载任意的动态链接库,并调用任意的函数的目的 。
由于我们需要动态获取()以及()这两个函数的地址,而这两个函数又是存在于.dll中的,因此这里需要先找到.dll的基址,然后通过对其进行解析,从而查找两个函数的动态地址 。动态的查找.dll的地址可总结为如下:
既然有了固定的查询定位公式,接下我们就使用调试器来手工完成对.dll地址的定位:
小提示:是 的缩写,是一种微软提供的免费调试器工具,用于分析和调试操作系统和应用程序 。可以在不重启系统的情况下,通过连接到正在运行的进程或者操作系统内核,获取并分析程序的运行信息、内存状态、寄存器状态、线程状态、调用堆栈等数据,并可以使用符号文件来解析程序中的符号名,从而帮助开发者定位问题和进行深入调试 。
读者可通过附件获取到程序,当用户打开时读者可通过Ctrl+E快捷键任意打开一个可执行程序,接着我们开始寻找吧;
1.通过段选择子FS在内存中找到当前的线程环境块TEB 。这里可以利用本地调试,并输入!teb指令,读者可看到如下输出:
小提示:TEB(Block)是操作系统中的一个重要数据结构,每个进程都有一个对应的TEB 。它主要用于存储线程的环境信息和状态,包括线程局部存储(TLS)指针、异常处理链、堆栈信息、Fiber信息等 。TEB由内核自动创建和管理,可以通过系统调用和调试器工具来访问和修改其内容 。
如上线程环境块偏移位置为0x30的地方存放着指向进程环境块PEB的指针 。结合上图可见,当前PEB的地址为
小提示:PEB是操作系统的进程环境块(Block)的缩写 。PEB是一个数据结构,其中包含了关于进程的许多信息,例如进程的模块、堆、线程等等 。PEB由操作系统内核在创建进程时分配和初始化,并且只有在进程运行期间才可用 。
2.在进程环境块中偏移位置为0x0c的地方存放着指向结构体的指针,其中存放着已经被进程装载的动态链接库的信息,如下图所示;
3.接着结构体偏移位置为0x1c的地方存放着指向模块初始化链表的头指针,如下图所示;
4.模块初始化链表中按顺序存放着PE装入运行时初始化模块的信息,第一个链表节点是ntdll.dll,第二个链表结点就是.dll 。我们可以先看看
中的内容:
上图中的保存的是第一个链节点的指针,解析一下这个结点,可发现如下地址:
上图中的为ntdll.dll的模块基地址,而则是指向下一个模块的指针,我们继续跟随地址,则此处看到的标黄处是下一个模块.dll的基地址 。