看雪2022 KCTF 秋季赛 | 第三题设计思路及解析
出题团队简介
赛题设计思路
本题算法延续了KCTF2022-春季赛-第八题迷雾散去的设计方法:
1、题目设计为双进程模式,算法的校验分别放在两个进程中,并通过管道通信且父子进程使用相互ptrace防调试处理;
2、管道通信读写及部分操作如: open/read/getpid等系统调用通过中断svc指令实现;
5、增加防frida检查;
题目考查点:
反汇编器 负责解析输入二进制文件,输出函数指令和数据流
解释器 负责对vm指令和数据流进行解释执行
链接器 负责将vmachine嵌入新二进制文件中,并对地址相关的指令做重定位
.text:000016C2 19 4C LDR R4, =(__stack_chk_guard_ptr - 0x16CC).text:000016C4 C3 B0 SUB SP, SP, #0x10C.text:000016C6 01 AE ADD R6, SP, #0x120+var_11C.text:000016C8 7C 44 ADD R4, PC.text:000016CA 24 68 LDR R4, [R4]….text:00001728 A0 38 00 00 off_1728 DCD __stack_chk_guard_ptr - 0x16CC
.text:00006000 19 4C LDR R4, =(__stack_chk_guard_ptr - 0x16CC).text:00006002 C3 B0 SUB SP, SP, #0x10C.text:00006004 01 AE ADD R6, SP, #0x120+var_11C.text:00006006 7C 44 ADD R4, PC.text:00006008 24 68 LDR R4, [R4]….text:0000606C A0 38 00 00 off_1728 DCD __stack_chk_guard_ptr - 0x16CC
LABEL_BASE:.word 0x62220000LABEL_DISP:.word 0x3280PUSH {R0-R15}LDR R0, LABEL_BASELDR R1, LABEL_DISPADD R0, R1STR R0, [SP, #0x3C]POP {R0-R12}ADD SP, #0xCLDR PC, [SP, #-4]
赛题解析
本赛题解析由看雪论坛会员 mb_mgodlfyn 给出:
但是把代码混淆作为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
保持name不变,改变输入的serial,观察附近内存的变换,发现以下区域:
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Á{¢
(初始serial是64个0;行标头表示改变serial的第几位,列标头表示改变为哪个值)0 1 2 3 4 5 6 7 8 9 A B C D E F0 DB86 DB76 DB66 DB56 DBC6 DBB6 DBA6 DB96 DB06 DAF6 DAE6 DAD6 DB46 DB36 DB26 DB161 DB86 DB85 DB88 DB87 DB82 DB81 DB84 DB83 DB7E DB7D DB80 DB7F DB7A DB79 DB7C DB7B2 DB86 DB76 DBA6 DB96 DB46 DB36 DB66 DB56 DC06 DBF6 DC26 DC16 DBC6 DBB6 DBE6 DBD63 86 85 84 83 8A 89 88 87 7E 7D 7C 7B 82 81 80 7F4 B8 B7 BA B9 BC BB BE BD C0 BF C2 C1 C4 C3 C6 C55 86 85 84 83 8A 89 88 87 8E 8D 8C 8B 92 91 90 8F6 B8 B7 BA B9 B4 B3 B6 B5 C0 BF C2 C1 BC BB BE BD7 86 85 84 83 82 81 80 7F 7E 7D 7C 7B 7A 79 78 7742A4ECA0 // 这是使得 0x2892A9CE580 取值最大的输入(BD5B135F) // 这是使得 0x2892A9CE580 取值最小的输入0 1 2 3 4 5 6 7 8 9 A B C D E F8 B8 B7 BA B9 BC BB BE BD B0 AF B2 B1 B4 B3 B6 B59 86 87 88 89 8A 8B 8C 8D 7E 7F 80 81 82 83 84 8510 B8 B9 BC C0 C4 C711 86 8A 8B 89 7E 7C 8212 B8 B7 B6 B5 BC B9 B0 AD B4 B113 86 82 7E 7A 7714 B8 BC BF B0 B3 B415 86 8A 89 7E 7D 7C 7B 8267F54074(980ABF8B)0 1 2 3 4 5 6 7 8 9 A B C D E F16 B8 B5 BC C0 C417 86 89 82 7E 81 7A 7D18 B8 B7 B9 BC C0 C4 C3 C6 C519 86 82 83 84 8E 8F 91 8A20 B8 B7 BA B5 B0 AC AB AD21 86 89 8A 8E 92 9522 B8 B9 B7 B4 B0 B1 AE AC AD AA23 86 8A 8D 7EC3EB2F17(3C14D0E8)0 1 2 3 4 5 6 7 8 9 A B C D E F24 B8 BC BF B0 B425 86 82 81 83 8E 90 8A26 B8 B5 C0 C4 C127 86 82 83 8E 90 91 8A28 B8 B4 B0 AC A929 86 8A 89 8C 8B 7E 7D30 B8 BB BC C0 C4 C5 C6 C731 86 85 89 90 91 94 937ACB06FE(8534F901)0 1 2 3 4 5 6 7 8 9 A B C D E F32 B8 B9 B5 B2 B3 AE AA AB33 86 87 89 83 80 7A 7C 7D34 B8 BD BF B0 B2 B735 86 83 80 8F 8C 8936 B8 B3 AE A937 86 8B 7C38 B8 BD AE B339 86 84 83 89 8C 92 8F1379055C(EC86FAA3)0 1 2 3 4 5 6 7 8 9 A B C D E F40 B8 B6 BD BE C5 C341 86 8A 89 88 7C 7B 7F42 B8 BD C2 C743 86 82 83 85 90 91 8D44 B8 BA B3 B2 AC AB AD45 86 88 81 80 79 7B46 B8 B9 B5 AE AA AB47 86 87 83 7C 78 79D4FB22110 1 2 3 4 5 6 7 8 9 A B C D E F48 B8 B5 BB BE C4 C2 C149 86 89 83 80 7A 7D50 B8 B4 B5 C2 C3 BF51 86 84 8B 8C 93 9152 B8 B3 B1 C0 BE B953 86 8B 8D 7E 80 8554 B8 BC BB B0 AE AD B155 86 8B 90 92 95C3BD874F0 1 2 3 4 5 6 7 8 9 A B C D E F56 B8 B3 C257 86 84 8B 8C 93 9158 B8 B4 B5 B2 C1 BE BF BB59 86 85 88 89 8D 90 94 9360 B8 B9 B6 B5 AE AA AB61 86 81 7C 7762 B8 B9 B5 AE AA AB63 86 84 8B 8C 93 91AD9E101D
name: KCTFserial: 42A4ECA067F54074C3EB2F177ACB06FE1379055CD4FB2211C3BD874FAD9E101D
球分享
球点赞
球在看