首页
论坛
课程
招聘
[原创] 看雪 2022 KCTF 秋季赛 第三题 水患猖獗
2022-11-21 01:51 3486

[原创] 看雪 2022 KCTF 秋季赛 第三题 水患猖獗

2022-11-21 01:51
3486

VMP是当下最强的代码混淆,它的强度已无需再验证,而且目前并不存在成熟开源自动化的脱壳工具。

 

然而,很多恶意软件也采用了类似的代码混淆,这为安全研究人员分析恶意软件带来了巨大的困难,因此一个通用自动化去混淆工具意义非凡。有一些探索性的研究项目,例如 VMProtect DevirtualizationSATURN - Software Deobfuscation Framework Based On LLVM 等,但是距离成熟的工具还有很大的距离。

 

如果不考虑副作用,那么代码逻辑本质是接受输入,对输入做计算和变换,最后输出结果,与数学上的函数并无二致。VMP保护虽然把控制流变得面目全非,但数据流作为运算逻辑的本质仍然是贯穿于程序中的(当然也有很多针对数据流的混淆(如不透明谓词、MBA等),但与控制流还是相对独立的),因为无论代码如何混淆,原始程序的逻辑是不能被改变的。

 

最擅长数据流分析的工具是编译器。目前很多去混淆通用工具的研究项目,核心思想还是设法把被混淆的程序提升为 LLVM IR,然后利用编译器强大的数据流优化能力(主要是常量传播、活跃分析、死代码消除等)剥离大部分与核心逻辑无关的垃圾指令,同时引入SMT求解器处理某些数据流混淆。

 

不久前才刚知道SATURN这篇论文,感觉可行性是最高的,文章对设计思路的描述也相当详细,只可惜作者没有开源。
(计算机行业的技术整体上还是开放共享的,SATURN论文虽然没有开源,但是可以相信一定有人会按照论文的思路实现这个项目(例如当年Google提出了MapReduce但没有开源,于是有了后来的Hadoop)。另外如果某个技术成熟了,尽管会有一些人做闭源商业化创收,但一定也会有另一些人做开源共享(例如IDA是最强的反编译器,它是商业化的,而开源界也有Ghidra,虽然效果差了一些,但总是有的)(这是计算机行业的整体技术氛围,应该说目前互联网的很多基础设施都依赖于一些基础的开源项目,所以真正投入开源的人是最值得尊重的(开源困境:Log4j2 维护者发声:没有工资,还要挨骂!!))


 

但是把代码混淆作为CTF题目考点来出的话,如果没有较为成熟的开源项目可以利用,个人感觉对攻击方是有些为难的。因为CTF的初衷是Hack for FUN,其次是技术交流。硬刚VMP的过程往往不太FUN,而从技术分享的角度看,此题的混淆强度4天时间如果从零开始写自动化工具基本也不大可能。
当然,防守方也许会考虑到攻击方有自己的私藏武器。但是如果思考一下这个问题可以发现,如果以SATURN论文的工作量作为参考,可以想象实现这样一个去混淆框架至少要全力投入数(甚至考虑前期对VMProtect的逆向分析,时间周期会更长),经过不断的迭代才能有一些初步的效果,可能只有本职工作在此的人才能有足够的精力投入其中;而且,即使有了这样的工具,用来解题肯定也要做针对性适配,而这又是一个深坑:单凭一道题目搞清楚代码混淆方式就要花费大量时间,何况还要修改原有的工具,再重新测试,4天时间恐怕也不太现实。另外,考虑到计算机行业的技术开放程度,虽然业界最强的工具不一定开源,但基本上开源界总会有相同功能的工具,而且至少可以做到能用的程度(可以对比IDA和Ghidra)。但是现在似乎还没有发现高调售卖的商业化VMP去混淆工具,而且现有的几个开源的VMP去混淆工具效果还不是非常好。不过,随着时间发展,还有能够相信未来会出现成熟的工具的。
(其他CTF比赛也出现过以代码混淆作为考点的题目,不过题目为了考虑时限内的可解性(而不是为了单纯测试混淆的强度是否足够高到无人能解;如果真是这样的目的就应该搞付费悬赏,和SRC平台一样),强度往往被有意降低,重点在于展示思路,于是很好的兼顾了难度和技术交流)

 

不妨回顾下近几届KCTF所有以代码混淆为主要考点的题目,似乎没有一个人是真的靠自己写的自动化去混淆工具还原出原始逻辑进而解出题目的,基本上都是靠动态调试、trace跟踪、人为观察等方式,靠堆体力找出逻辑,而且,也没有任意一个出题人公开自己写的自动化去混淆工具,这样无论攻击方还是防守方,从技术交流的角度总感觉缺少了一点灵魂(p.s. 不过很多基于动态调试的解题方法也非常硬核而且能学到很多知识)。而且这种工具对安全行业具有颠覆性的意义,即使闭源高价售卖也是有巨大市场的)(此外,回想自己作为某比赛出题人时,负责人给的硬性要求就是必须自己以做题人的视角解一遍确保可解性和做题体验,而且对于代码混淆的使用有严格的限制,必须保证自己有合理的解法(比如,有成熟工具可利用,或者从零开始能在赛期内写出工具,或者有足够的线索提示能够完全绕开混淆);而且到最后往往会发现,某些题目即使开源给做题者都不会降低难度)


 

所以,基于以上推理,只能合理假设既然用了VMP来出题,那么就默认了出题人是希望攻击方寻找捷径,而不是硬刚代码混淆,因为对于本题的混淆强度从零开始的话4天的时间基本上不可能写出自动化的工具。


 

回到本题,对本人来说正常做是不可能做出来了,也只能想一想其他的路。

 

根据公开的serial可知合法的serial长64字节,每个字符取值[0-9A-F],实际上hexdecode后是32字节。
jadx逆向apk,发现java层什么都没有,只是把name和serial都传给so然后接受一个字符串并显示出来。

 

Android Studio 开一台 arm 架构的虚拟机,x64dbg 调试 qemu-system-armel.exe

 

输入正确的serial会提示"祝贺,闯关顺利",输入错误的serial会提示"不对!再探再报",而且从java层看到这两个字符串都是so返回的。

 

把这两个字符串utf8编码,在x64dbg里全内存搜索,只能找到一片内存。
保持name不变,改变输入的serial,观察附近内存的变换,发现以下区域:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
000002892A9CE570  00 00 00 00 00 00 00 00 13 00 00 00 AB 00 00 00  ............«... 
000002892A9CE580  02 EB FF FF A9 15 00 00 E7 97 8C 92 84 96 8C 92  .ëÿÿ©...ç....... 
000002892A9CE590  E8 96 8C 92 50 00 00 00 23 00 00 00 10 C1 7B A2  è...P...#....Á{¢ 
000002892A9CE5A0  EE DF DE 0E B8 CB 7B A2 00 00 00 00 1C 96 8C 92  îßÞ.¸Ë{¢........ 
000002892A9CE5B0  15 FC 7D A2 9D 60 7C A2 D4 FF 7D A2 00 00 00 00  .ü}¢.`|¢Ôÿ}¢.... 
000002892A9CE5C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................ 
000002892A9CE5D0  00 00 00 00 00 00 00 00 00 00 00 00 2C 3F 7C A2  ............,?|¢ 
000002892A9CE5E0  01 00 00 00 E8 96 8C 92 E7 97 8C 92 23 C1 7B A2  ....è...ç...#Á{¢ 
000002892A9CE5F0  E7 97 8C 92 00 00 00 00 E8 96 8C 92 50 00 00 00  ç.......è...P... 
000002892A9CE600  FC 56 00 00 00 30 7B A2 FC 86 7B A2 23 00 00 00  üV...0{¢ü.{¢#... 
000002892A9CE610  E8 96 8C 92 04 00 00 00 79 3F 7C A2 FC 86 7B A2  è.......y?|¢ü.{¢ 
000002892A9CE620  20 00 00 00 84 96 8C 92 5C 96 8C 92 49 49 7B A2   .......\...II{¢ 
000002892A9CE630  A9 15 00 00 00 00 00 00 00 00 00 00 20 0A 00 00  ©........... ... 
000002892A9CE640  22 00 00 00 30 00 00 00 EF FE DD 00 30 C1 7B A2  "...0...ïþÝ.0Á{¢

观察到 0x2892A9CE580 处的 02 EB 会随着 serial 的变化而变化,而且错误的 serial 在此处的值都小于 0xEB02。

 

固定 name 为 KCTF,逐字节改变输入。每个字节有 16 种取值,找出使得 0x2892A9CE580 处的值最大的那种即为正确的输入。

 

剩下的就是体力活了,下面是花几个小时手动搞出来的表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
(初始serial是640;行标头表示改变serial的第几位,列标头表示改变为哪个值)
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
 0  DB86 DB76 DB66 DB56  DBC6 DBB6 DBA6 DB96  DB06 DAF6 DAE6 DAD6  DB46 DB36 DB26 DB16
 1  DB86 DB85 DB88 DB87  DB82 DB81 DB84 DB83  DB7E DB7D DB80 DB7F  DB7A DB79 DB7C DB7B
 2  DB86 DB76 DBA6 DB96  DB46 DB36 DB66 DB56  DC06 DBF6 DC26 DC16  DBC6 DBB6 DBE6 DBD6
 3    86   85   84   83    8A   89   88   87    7E   7D   7C   7B    82   81   80   7F
 4   B8   B7   BA   B9    BC   BB   BE   BD    C0   BF   C2   C1    C4   C3   C6   C5
 5    86   85   84   83    8A   89   88   87    8E   8D   8C   8B    92   91   90   8F
 6   B8   B7   BA   B9    B4   B3   B6   B5    C0   BF   C2   C1    BC   BB   BE   BD
 7    86   85   84   83    82   81   80   7F    7E   7D   7C   7B    7A   79   78   77
42A4ECA0    // 这是使得 0x2892A9CE580 取值最大的输入
(BD5B135F)    // 这是使得 0x2892A9CE580 取值最小的输入
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
 8   B8   B7   BA   B9    BC   BB   BE   BD    B0   AF   B2   B1    B4   B3   B6   B5
 9    86   87   88   89    8A   8B   8C   8D    7E   7F   80   81    82   83   84   85
10   B8   B9              BC                   C0                   C4             C7
11    86                   8A   8B        89    7E        7C         82       
12   B8   B7   B6   B5    BC             B9    B0             AD    B4             B1
13    86                   82                   7E                   7A             77
14   B8                   BC              BF   B0             B3    B4          
15    86                   8A   89              7E   7D   7C   7B    82         
67F54074
(980ABF8B)
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
16   B8             B5    BC                   C0                   C4           
17    86             89    82                   7E             81    7A             7D
18   B8   B7        B9    BC                   C0                   C4   C3   C6   C5
19    86                   82   83   84         8E   8F        91    8A       
20   B8   B7   BA                        B5    B0                   AC   AB        AD
21    86             89    8A                   8E                   92             95
22   B8   B9        B7    B4                   B0   B1   AE         AC   AD   AA     
23    86                   8A             8D    7E                          
C3EB2F17
(3C14D0E8)
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
24   B8                   BC             BF    B0                   B4           
25    86                   82   81        83    8E        90         8A         
26   B8              B5                        C0                   C4              C1
27    86                   82   83              8E        90   91    8A           
28   B8                   B4                   B0                   AC              A9
29    86                   8A   89   8C   8B    7E   7D                       
30   B8              BB   BC                   C0                   C4    C5   C6   C7
31    86   85                   89                        90              91   94   93
7ACB06FE
(8534F901)
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
32   B8   B9                   B5   B2   B3              AE                   AA   AB
33    86   87        89         83                        80         7A        7C   7D
34   B8                        BD        BF    B0        B2                        B7
35    86                        83   80              8F   8C                        89
36   B8                        B3                        AE                        A9
37    86                        8B                        7C                   
38   B8                        BD                        AE                        B3
39    86        84   83         89                        8C         92             8F
1379055C
(EC86FAA3)
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
40   B8        B6              BD                        BE              C5        C3
41    86                   8A   89   88                   7C   7B                   7F
42   B8                        BD                        C2                        C7
43    86                   82   83        85              90   91                   8D
44   B8        BA              B3                        B2         AC   AB        AD
45    86        88              81                        80              79        7B
46   B8   B9                   B5                        AE                   AA   AB
47    86  87                    83                        7C                   78   79
D4FB2211
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
48   B8             B5         BB                        BE         C4        C2   C1
49    86             89         83                        80         7A             7D
50   B8                   B4   B5                        C2   C3                   BF
51    86        84              8B                        8C              93        91
52   B8                        B3        B1    C0        BE                        B9
53    86                        8B        8D    7E        80                        85
54   B8                   BC   BB              B0        AE   AD                   B1
55    86                        8B                        90         92             95
C3BD874F
 
       0    1    2    3     4    5    6    7     8    9    A    B     C    D    E    F
56   B8                        B3                        C2                  
57    86        84              8B                        8C              93        91
58   B8                   B4   B5   B2              C1   BE   BF                   BB
59    86   85   88              89                   8D   90                   94   93
60   B8   B9   B6              B5                        AE                   AA   AB
61    86                        81                        7C                        77
62   B8   B9                   B5                        AE                   AA   AB
63    86        84              8B                        8C              93        91
AD9E101D

(做完才发现,其实每个字节尝试 1、2、4、8 四种情况就够了。如果某种情况使得 0x2892A9CE580 的值比输入取 0 时大,就加上这个值,否则不加)

 

(另外自动化也是有可能的:通过 adb shell input 控制输入,ReadProcessMemory 读取内存;但是评估了下手动的工作量,感觉几个小时能搞完,所以还是手动搞的)

 

(以及,第一次动手发现 Windows 上通过 ReadProcessMemory 读其他进程的内存竟然不需要权限。细思恐极,Windows上的恶意软件是不是随便读其他进程内存获取密码等敏感数据?)

 

题目的最终答案:

1
2
name: KCTF
serial: 42A4ECA067F54074C3EB2F177ACB06FE1379055CD4FB2211C3BD874FAD9E101D

(p.s. 关于动态调试,这两天才知道内核的 eBPF uprobe 机制(从Linux 3.5就存在了)。通过这个机制可以跟踪用户态程序、在任意地址处停下、dump寄存器等(原理也是插入int 3指令,但不走ptrace(?),应对反调试估计很有效),值得发掘)


 

P.S. 发帖时竟然提示涉黄,要人工审核?好想知道是哪个词触发的问题,自己完全看不出来。


[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

最后于 2022-11-21 02:21 被mb_mgodlfyn编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回