我是一枚从事网络安全行业十余年的小师哥🫡,做过红队技术支持,也做过技术开发leader,乐于分享技术,喜欢结交朋友。
- 这是我做的一个关于shellcode入门和开发的专题课👩🏻💻,主要面向对网络安全技术感兴趣的小伙伴,属于实战、经验性内容,里面的每一个操作我都亲测过。
- 本专栏内容也有对应的视频版课程▶️,需要看视频版的小伙伴可以私信我get折扣券(wx:imbyter)
一、shellcode概念
一般来说,shellcode就是系统可以直接识别并执行的二进制代码,通常以作为测试漏洞利用效果的功能“载荷”的形式来使用。
为什么叫shellcode?因为在最初的大多数场景下,攻击者是把获取对方系统的shell作为最终目标,所以实现这个功能的代码也因此被称作shellcode。
具体的说,shellcode在使用前,可以 以文件的形式存储在本地。比如我们通过一些工具,或者自己编写的代码,生成了一个shellcode文件,我们可以把它起名为file存在本地D盘中,比如:D\demo\file
,或者把它其名为1.bin
、2.sc
,甚至3.txt
,任何名字都可以。
shellcode本身不依赖它叫什么名字,也无关要紧存放在哪。操作系统本身没法直接运行它,我们只能通过自己编写代码,或者一些特殊的工具、手段,才能把它运行起来。
具体如何加载运行shellcode,我们在后文中会有详细介绍。
二、与其它文件的区别
shellcode文件与windows中的其它文件有着本质上的区别,我具体具体归了以下几点:
-
文件类型方面: 在windows系统中,文件的类型是以后缀名作区分的。比如图片文件以
jpg/png/bmp
等作为后缀,记事本文件以txt
作为后缀,而PE(可执行文件)文件一般是指以exe/dll/com
等为后缀的可执行文件,但shellcode并没有后缀,他是非标准文件,只能由指定的加载器来识别和运行,系统本身“不认识”shellcode。 -
文件格式方面: 几乎任何windows系统下的文件都有其自身的格式,比如JPG图片的头部有“
JFIF
”标志,ZIP压缩包文件头部有“PK
”标志,而PE可执行文件的头部是“MZ
”头,我们用二进制工具(比如 WinHex)打开这类文件时,在文件最开始的几个字节都能看到:对于shellcode文件来说,它可以没有任何标志。(或者说它的标志由编写它的人来设置的,理论上可以做到:你写的shellcode只有你才能认识)
-
加载运行方面: Windows中所有文件的执行,都有其相应的运行软件,或者叫加载器,比如zip可以由
7zip
软件或者WinRAR
加载打开,doc文件可以由WPS
或者Word
加载打开,PE文件是由系统加载器
来加载运行。而shellcode文件,我们可以把它放在系统的几乎任何进程中执行,比如放在画图的mspaint.exe
中,计算器calc.exe
中,或者word软件的进程、winrar软件的进程,甚至理论上可以放在杀毒软件的进程运行。
三、shellcode基本特点
总结一下,我觉得shellcode整体具备了以下几个特点:
- 独立存在,无需任何文件格式的包装;
- 内存执行,几乎能运行在任何进程中;
- 精简轻便,执行效率高,文件体积小;
- 灵活多变,易于加密变形,伪装性强;
1. 独立存在
通常情况下,我们编程实现某个程序或软件的功能,无非就三步:
编写代码 --> 生成exe文件 --> 执行exe文件
也就是说,我们编写的代码,最后是被包装在了exe文件中,从表面上,根本无法找到我们之前写的代码,只有运行这个exe文件,才能把我们编写的代码执行起来。比如下面这段C语言代码:
#include <stdio.h>
#include <windows.h>
int main()
{
MessageBox(NULL, L"Hello World", L"imbyter.com", MB_OK);
return 0;
}
真正的功能只是一句MessageBox
的弹框提示,但实际上生成的exe文件却有几十KB大小,这些而外的体积,都是作为一个标准exe要具备的格式。 而shellcode文件,不需要任何格式,整个文件都是以围绕着我们写的代码存在的。像上面MessageBox这个功能,用以我们后面讲的方式写成shellcode的话,只有816字节:
2. 内存运行
shellcode可以在任意进程的内存中直接运行,不需要固定的宿主进程。
拿上面的那个例子来解释,普通模式下,弹框功能的这个MessageBox,是包装在这个exe文件中的,也就是只有我们执行这个exe,才能得到弹框提示的功能。而我们上面所说的这个shellcode的bin文件,通过一定的方式,可以在任何exe中执行,我们后面会做详细讲解。
3. 精简轻便
由于shellcode文件没有PE结构的约束,因此也就不存在所谓的资源段、数据段、重定位表、以及导入导出表等等,它一开始就是冲着主功能的那几行代码去执行的,所以执行效率很高,而文件的体积又很小。
4. 灵活多变
它可以根据调用者的需要,任意的进行加密变形,在表面上看起来,他可以达到一堆“乱码”的效果,只受调用者的控制。
做过红队免杀对抗的同学应该比较清楚,基于shellcode的这种“七十二变”的特征,我们很少听到过说“我的shellcode文件被xx杀软干掉了”,因为杀软不可能看到一堆“乱码”就去杀,更多的时候红队说“我的shellcode被杀了”,是说shellcode在内存中被检测到,或者shellcode功能在执行的时候被查杀。
四、生成shellcode方法
现阶段,生成shellcode的方式主要有两种:
-
用编程语言自己编写
这种方式能够灵活的得到我们任意想使用的shellcode,内部处理受我们控制,易于变形。但前提是我们要懂编程,能自己去写。
-
shellcode生成器进行生成
这种方式是借助于网上已有或者开源的shellcode生成框架,这类框架使用时无须我们自己编写代码,用起来方便。但也有它存在的问题,比如既是开源,便已经被各类安防软件分析尽透,难在实际场景下发挥作者用。
两种方法各有优劣,我们可以都对其有所掌握,按场景需求,选择最合适的方式来使用。
在后面的内容中,我会着重针对如何用C/C++编程语言,来设计编写自己的shellcode生成框架。同时也会对现有的开源shellcode生成器做一些使用方面的介绍。我们的目标是,通过学习,既能自己编写shellcode功能模块,也能使用开源工具,快速的生成需要的shellcode模块。
如果有任何问题,欢迎在我们的知识社群『imbyter代码酷』中提问
个人主页:https://imbyter.com