特殊条件数据传输

Beta-TNT 2016-04-07 15:16:00

0x00 借问酒家


有什么东西想拿却拿不出来?不妨开开脑洞。

缘起是2014年底的时候看到金山做的在线恶意代码分析系统“Fire eye”(https://fireeye.ijinshan.com/)。感觉很新鲜,丢了自己攒的几个样本丢了上去,分析的结果还算可以。从分析报告来看,它也是一类沙箱检测工具,把样本丢到虚拟机里跑,再在虚拟机内外布控,监测样本的各种行为,最后生成分析报告并给出判断是否恶意样本,分析报告里还包含样本运行时的截图。

0x01 柳暗


于是我开始有点好奇,这个沙箱大概是个什么样的,于是自己写了一些小的检测程序丢进去,把环境变量、系统信息、网络配置、进程列表、服务和驱动什么的读出来显示在窗体上,这样从分析报告里的样本截图就能读到这些信息了。

嘛,这里先说一下,本人并不会挖漏洞和逆向,说来惭愧,大学时候的汇编都是补考才过的。就是个小小的.net码农而已。

然后我在系统环境变量里发现一个别的地方没有的玩意:%FEKERNEL%,指向c:\mon\文件夹,想来应该是“FIRE EYE KERNEL”,即包含沙箱内部监控程序的核心文件夹。

有了这个发现自然不会放过,另外专门编写了程序去枚举和读取FEKERNEL里的东西,然而发现只要碰了那个文件夹,样本分析报告就会被隐去大部分内容,和FEKERNEL文件夹直接和间接(比如复制出来之后再读取复制的文件)相关的内容都被删掉了,想来应该是做了某种自我保护。只有读取文件夹大小的操作没被拦截。

0x02 花明


不过既然有了目标,路就好找了。试了几次找到了绕过保护的办法,成功读取到了FEKERNEL里的文件并把详细信息。下一步当然就是如何拿到里面的东西咯。

里面是大概几十MB的二进制文件,有EXE有DLL有SYS甚至还有PDB,估计是开发人员方便调试直接把符号文件也一起扔里面了。这么多东西怎么拿出来呢?最初的想法是通过网络传出来,然而沙箱的网络和互联网是不通的,对用户的唯一输出仅限样本分析报告。

然后我发现早几年前有人通过编写样本在注册表里写入HTML代码内容的键值在分析报告页面成功实施了XSS,觉得这个思路是可行的。然而几十MB的东西即便压缩成十几MB再按BASE64编码,写到一个监控程序会监控的地方,仍然没法全部拿出来,因为太多了。就算画在窗体上也…………

……慢着,画在窗体上?

脑袋灵光一闪,这办法可以啊!我先想到的是把BASE64串按能分辨的最小字号写在窗体上,然后进一步想到干脆利用窗体上的像素,一个像素表示一个字节,然后直接想到干脆一个像素用RGB分量存储三个字节,这样可输出的数据量就成几何级数上升。稍微计算了一下,按最高密度的数据传输方案,一个窗体能被截图下来的最大面积足够“画下”压缩过的完整目标数据。

思路有了,东西直接就搞出来了。由于FE只能上传单个可执行文件样本,于是把所有用到的东西打包成一个自解压RAR,并附带解压后执行脚本,先绕过保护读取到FEKERNEL里的所有内容并复制到另外的位置,然后用自带的WINRAR.EXE通过命令行将其压缩,最后把压缩包以二进制打开,把内容“画”在自己窗体上。

这样我就顺利拿到了FEKERNEL里的所有东西。当然这还得感谢FE在处理样本截图的时候没有做任何有损压缩,虽然是JPEG格式。

这个漏洞我已在去年提交给乌云:火眼恶意代码分析系统自保机制绕过导致二进制泄露

0x03 又一村


总结:如果有什么东西你知道在哪,但没法直接拿到,不妨冷静分析一下:

  1. 你能控制的输入因素有哪些;
  2. 阻拦你拿到数据的限制因素有什么,有没有绕过的办法;
  3. 你能拿到的输出数据有哪些,其中哪些可以通过输入数据直接或间接控制,哪些输出数据包含的信息量最大。

综合考虑这三方面因素,并仔细分析,就不难达成目标了。

评论

Knight 2016-04-07 15:53:21

最后的思路好赞。

E

Evi1cg 2016-04-07 16:06:36

666 之前有朋友跟我讲过类似的思路

W

winterFire 2016-04-07 17:06:09

卧槽。。。

B

Beta-TNT 2016-04-07 18:42:48

忘了说如何绕过保护了,方法很多。如果直接读不行,试试其他不常用的方式:创建符号连接,NTFS流文件,创建网络共享,借道第三方等。这次用的就是其中一种。以前用过一个文件保护工具,可以在资源管理器和控制台隐藏目标文件夹的内容,绕过方式也很有趣:用winrar压缩目标文件夹,压缩包里就是被隐藏的内容了

B

Beta-TNT 2016-04-07 18:45:38

这种数据传递方式的优势在于可以绕开目前绝大多数检测手段,将数据转为图片、视频和音频之后还可以再用这些媒体数据特有的处理方式进行再加工(图像处理、音频调制等),使其更难以发现和追踪。而且也不局限于传递数据,传点儿别的呢?

小葵 2016-04-08 07:18:42

当年脱裤的时候,遇到过流控。也用的类似的方法。

路人甲 2016-04-08 09:23:49

楼主为什么不用copy /b呢

路人甲 2016-04-08 09:37:18

思路牛逼!学习了!

Mark 2016-04-08 10:52:15

思路可以啊

B

Beta-TNT 2016-04-08 11:41:21

@今天早上起床 当时把各种拷贝复制的方式都试过了,直接读取都会被BLOCK,最后是通过设置共享文件夹的方式绕过保护的。嘛,绕过保护的方法并不是本文重点,把东西拿出来才是。我估计开发人员也只是考虑到即便绕过保护也不容易把数据带出来才没做太完善的防护

小秦 2016-04-08 13:59:14

我的问题是既然已经用RAR压缩成一个文件了, 为什么还要在头上写文件大小呢?
另外,你那个里面描述用前三个颜色值(RGBRGBRGB)来表示文件大小, 以你文章中的那个图片为例, 前三个像素的颜色值(RGB)分别为:
226 229 29
0 0 0
0 0 0
那么它的大小是 226+229+29 ? 还是 0xE2E51D000000000000 ?
很明显后面这个不太可能是文件大小.
在排除这三个像素的数据之后, 后面的内容转换之后,保存为rar文件,在解压的时候会报 `文件末端错误` 以及 `数据错误: xtools.sys`
其他的文件倒是正确的解出来了.

B

Beta-TNT 2016-04-08 14:08:45

@小秦 按字节序,高位在先,按这个例子应该是0x0000000000E2E51D,而不是相加,也不是低位在先。这个长度其实主要就是标定最后一行像素应该读多少个,重新按正确的长度截取长度你应该就能把最后一个文件正确读取出来了

小秦 2016-04-08 15:29:25

@Beta-TNT 0xE2E51D === 14869789
那个图片里一行有 965 像素, 然后一个像素能表示三个字节,那么单行的容量为
965 * 3 === 2895 这个数字远小于之前的 14869789, 如果说是像素数, 感觉也不对呀,一行才 965 个像素数.
如果说 14869789 是整个压缩文件的大小, 感觉不对呀, 解出来的压缩包不到2M.

B

Beta-TNT 2016-04-08 19:45:57

@小秦 14869789是整个数据的字节数

小白 2016-04-09 09:20:01

求分享绕过保护读目录,而不被发现的思路啊

路人甲 2016-04-11 13:06:58

最后怎么从窗体里面读取数据呢

T

tenzy 2016-04-11 13:45:05

这个问题其实当时在华为面试时,有想过,当时面试官问题是:假如一个物理隔绝的环境,服务器上开了一个agent,客户端通过该agent查看远程桌面,如何把服务器上的数据偷取下来。正确的答案当然就是通过agent的端口直接开个远程服务下载下来就行了,但是当时脑抽,结合了自己公司的实际情况(服务器放在公司内机房,直接通过视频延长线把显示器拖出到桌面,没有开端口),没有想到,于是给出了一个类似的答案,通过屏幕的黑白闪动,使用摄像机把屏幕录下来然后转成二进制即可。。。实际上最简单的做法是把数据转二维码,再把二维码解析下来即可。楼主不要搞得太复杂了。

B

Beta-TNT 2016-04-11 17:47:46

@tenzy 二维码当时考虑过,数据密度不够,放弃了。即便一个像素存3个字节的方式,也只是勉强画下RAR压缩过的所有数据。当然这还是要感谢截图是没有经过有损压缩的,不然确实还要麻烦很多,数据传输密度也会下降很多。

B

Beta-TNT 2016-04-11 17:48:49

@馒头 漏洞报告里我有写

刘海哥 2016-04-12 16:13:13

怎么办还看得不明不白。

_

_Evil 2016-04-12 23:29:29

脑洞好深

B

Beta-TNT

孤独的装具收集者

twitter weibo github wechat

随机分类

硬件与物联网 文章:40 篇
逻辑漏洞 文章:15 篇
无线安全 文章:27 篇
后门 文章:39 篇
神器分享 文章:71 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

Yukong

🐮皮

H

HHHeey

好的,谢谢师傅的解答

Article_kelp

a类中的变量secret_class_var = "secret"是在merge

H

HHHeey

secret_var = 1 def test(): pass

目录