Flare-On 2018 writeup(下)

阅读量    27913 |

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

malware skillz

全能型后门,从LaunchAccelerator.exe开始分析

程序先修改注册表,复制自身自运行

然后释放下载后门的代码,载入内存运行

后门下载器加载库函数从ldr链表中遍历模块和模块函数,使用Hash来获取API定位,此后的API都用这种方法遍历,由于是病毒经典使用方法,可以搜到hash表,没有搜索到的可以动态修改hash参数来取结果

https://www.scriptjunkie.us/files/kernel32.dll.txt

后门下载器搜索了必要的库函数,通过DNSQuery_A中查询到的DNS附加数据,夹带了加密的PE文件

然后解密,并运行到指定的函数

直接运行起来,可以发现通过DNS查询到的数据解密后会有弹窗

并在桌面上放了一个crackme.exe

从pcap.pcap中dump出网包中的DNS数据,将DNS查询数据用网包数据覆盖得到真正的后门文件,后门下载器会运行到他的导出函数Shiny

该函数查询当前eip的位置,搜索到自身的PE头,获取所有Sector相关的信息,重新加载到申请的内存页中,并从Dll入口点开始运行

对必要资源初始化和库函数定位后,后门开始连接主控机,并等待交互

后门主要的流程从ShakeAndInitAes开始,连接主控机后,主控机和肉鸡各生成一个随机数以商定之后的AES通讯密码

此后由主控机发出请求,肉鸡执行对应命令,如果检测到数据异常则断开socket重新握手商定

所有收发包都由统一规则进行封装,封装大致格式

对原始数据进行了AES加密和Zlib压缩操作,并加入一些信息以及校验头,标明了长度、包类型、当前包AES_IV、hash等其他校验冗余信息

通过对网包的复原和回放、解码可以发现,肉鸡A被感染后通过TCP 9443与主控机通信,主要经历了握手、上报了Malware各类版本、获取计算机名、磁盘、列目录、文件信息、ping主机、http请求、SMB广播控制

肉鸡A在感染受控过程中通过SMB2协议对病毒文件进行广播,感染肉鸡B,并通过肉鸡A接管肉鸡B,通过SMB2协议建立命名管道进行交互,交互数据的打包解包方式和TCP方式一致

肉鸡B受控经历了一些磁盘、文件信息上报,并通过肉鸡A写入了Cryptor.exe,并执行Cryptor.exe level9.crypt level9.zip,然后执行删除相关文件,最后通过FTP上传level9.crypt

将level9.crypt从网包中dump,可以看出已经被Cryptor.exe加密了,取得Cryptor.exe,为.Net编写的文件加密程序,de4dot反混淆后整理

程序对原始文件进行Hash计算、将文件名长度、文件名、文件Hash作为文件头进行AES加密,最后在加密数据头部加上cryptar及github版本

AES加密会从github一项目获取信息作为文件加密AES的Key和IV,可以发现github项目最新版本已经不是level9.crypt的版本从网吧或者git中拿当时版本的信息

获取20180810的信息对level9.crypt进行AES解密,得到level9.zip文件

该zip包被加密了,密码需要在肉鸡A和主控机的通信中寻找

搜索zip敏感字,找到密码really_long_password_to_prevent_cracking

解压zip包,取得一张空白图片和一个并没有任何作用的exe

上色,取得flag

recover_these_messages_lost_in_the_colorful_bits@flare-on.com

 

Suspicious Floppy Disk

拿到floppy.img,得到一系列文件

可以发现大概为dos系统盘,和原版img进行比较,多了infohelp.exe、key.dat等文件

使用dosbox+ida5.5对infohelp.exe进行调试,由于是16位程序,无法使用F5插件,掏出王爽老师的汇编书籍温习一下16位x86汇编,然后在调试时,地址前加上对应的段名。

可以发现大致行为是输入password,将输入的password写入password.dat然后打开message.dat显示失败信息

ida对该文件进行逆向,可以发现

程序由16位Watcoom编译,使用对应的watcom编译带调试符号的库,并制作FLIRT signature的签名文件,ida识别出大部分函数

程序由sub_10000作为入口主要流程如下

printf("input pw")
scanf("%s", &pw)
fopen("key.dat")
fwrite(pw)
fclose()
fopen("message.dat")
fread()
fclose()
printf(msg)

所以这个程序并没有直接藏有密码信息

使用WinHex发现了镜像中还有一些碎片文件可以通过特征恢复,但并没有什么发现,进一步观察发现镜像的mbr和原版dos相比被篡改了其中一段

使用vm+ida对更改的mbr进行调试,起始流程如下

0:0x7c00:

memcpy &mbr_cpy_600h, &mbr_7c00h, 0x200

-> 0x662

 

0:0x662h

memcpy 0:0x800, &tmp.dat, 0x6000

call tmp.dat sub_0

-> 0:0x800

 

0:0x800 (tmp.dat sub_0:)

0:0x413 -= 0x0020 (0:0x413 = 0x025d)

0:0x6ff3 = 0x9740

memcpy 9740:0, 0:0x843(&tmp.dat+0x43, NICK RULES ~ NICK RULES), 0x5eb0

0x9740:0x5e5a = dw 0xca000117 (real int 13h)

0x9740:0x5e6f = db 0

0:0x200 = dw 0xca000117 (real int 13h)

0:0x4c = dw 0x97400012 (int 13h hook to 0x9740: 0x12)

-> ret 0:0x671

篡改的mbr加载了tmp.dat中的函数,对0:0x4c地址的数据进行改写了,然后解码恢复原版mbr继续运行

0:0x4c这个地址正是int 13h中断服务函数地址,篡改后的地址为0x97400012

查阅资料,这种在mbr将系统服务进行hook的技术在bootkit很常用,由于预先于操作系统、应用程序加载所以很难被查杀

继续跟进,可以发现进入伪造的int 13h函数会先记录int 13h所有的参数并执行真正的系统服务,然后对参数进行比对进入相应的handler,主要是读扇区时,hook解码原版mbr以及在打开message.dat文件时会call tmp.dat中的函数,写扇区时也会有对应的handler

由img中的参数得知LBA=0x200 *  【柱面 * 36    +   磁头*18   +   扇区  –  1 】,经过计算可以发现cx = 0x2111, dh = 1, al = 1时正好对应message.dat,读取该文件时执行事先加载tmp.dat中的函数

界面如下

也就是通过Infohelp.exe作为触发器,当输入密码打开message.dat显示不正确的信息时,实际被hook到另一个解密程序,通过跟踪恢复出这个handler

通过infohelp输入完密码后对key.dat写扇区的hook handler,先取得密码,然后在读取message.dat时执行真正的密码检查函数,并返回结果

由于这个bootkit对vm的bios兼容性不好,并不能进入dos系统执行infohelp(bochs据说可以正常运行和调试),我在int 13h进行其他服务时,修改了参数以触发解密程序

解密程序如下

查阅wiki资料,这是one-instruction set computer (oisc),subleq的软件仿真,本来旨在于只支持一种指令的低成本芯片,也同时给逆向带来麻烦

在python中重构subleq的仿真环境

参考网上关于Flare-on 2017,11题类似的subleq题解,进行侧信道攻击,通过不同密码输入的cpu titk、pc graph等手段,除了发现密码中输入了@会大大增加计算量以外并没有明显发现

然后进行数据流分析,追踪密码的流向,对读写密码的敏感位置进行标记,得到巨量的操作一时没有总结出规律

最后这段程序也是由出题者编写的编译器编译的,本着编译本身有一些规律,参考去年11题官解,对subleq进行命令组合

去年官解并没有把所有的指令定义列出,不断尝试和摸索中定义了以下指令

其中最难的是subleq通过指令修改了自身指令,这种情况通过指令操作的target address写入了已经识别为指令的地址区域列出,进一步可以发现这些自身修改的指令主要用于指针操作*(%a) = %b, %b = *(%a), jmp *(%a)等操作,可以理解通过修改自身指令替换简单mov中的操作地址,来实现指针访问

反编译器的设计思路是先区分指令区、数据区(通过运行的实际情况可以覆盖大多数),标记subleq基础指令(如 subleq s,d,t / subleq z,d / subleq z,z等),基础指令由3个操作数构成,通过区分源、目标、跳转地址是否为零是否相等区分出不同的基础指令,包括数据也认为是一种特殊指令,保存

然后将简单指令组合成复合指令,复合指令一般会以基础指令的固定组合重复多次,并且意义明显,如mov或者跳转操作

然后将指令解析成对应的LikeC,并分别生成具有完全标签和自动简化标签的两个文件

 

防止因为一些指针跳转,无法找到对应指令位置的情况,然后对LikeC进行静态分析

这段subleq程序大致如下

查阅资料,这又是一个vm,oisc的另一种rssb

同样的进行侧信道和数据流分析,一时没有掌握到规律,在编写一个反汇编器

rssb比subleq还要抽象,基础指令只有一条rssb x,但是x有几个特殊值

x为-2时代表返回,-1只填补位置,0为当前程序指针,1为rssb累加器,2为常0寄存器,6为输出寄存器

当然这个是由本题的编译器定义的,并不一定通用,类似subleq反汇编器一样,合并基础指令为复合指令如下

生成对应的rssb解析文件和LikeC(带完整标签/自动简化标签)

进行静态分析,还原,关键函数如下

可以发现@作为检查密码的结尾字符,而最后的密码校验方式是自定义hash算法与预定的hash表比对

hash计算公式如下

for i in range(15):
    hash[i] = (((key[i+1]-32) << 7 + (k[i]-32)) ^ (i * 33) + magicsum) & 0xffff

其中magicsum是所有密码的ascii和加3072乘密码长度

magicsum = 3072 * len(key) + sum(key)

由于magicsum不得知,key也不知到,只有期望的hash表,magicsum只能为0~0xffff

进行枚举倒推key[],然后检查magicsum是否符合约定并打印

找到明文数据Av0cad0_Love_2018@flare-on.com,至此Flare-on5完成

 

Easter Egg

彩蛋关,malware skillz关卡中通过DNS协议下载的crackme

程序带壳,上来pushad,esp定律,下esp写入断点F9

停在OEP 0x401000,dump源程序

拖入IDA

程序混淆了字符串和控制流结构

大致流程是分别putc:Password:

然后getc,一位一位校验

然后输出校验结果,一般password一位字符的校验程序如下,由于所有的字符处理都是线性处理,先设置输入password为’\x00’ * 40然后在关键的比较位置下bp取出jz的比较值

如比较值为0xc8,正确输入时应为0x00,则意味着该位password实际应该为(char) (0x00-0xc8),即’8’

解出所有的password位:83cbeb65375d4a1263c2e28bc9cf4f8a8c8f834e

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多