-
-
[原创]2018看雪CTF第十五题WP
-
2018-7-15 13:23 3721
-
试运行程序
解压题目附件压缩包。内有4个文件:
1、zImage(arm的linux内核)
2、vexpress-v2p-ca9.dtb(设备树)
3、ReadMe.txt(题目说明)
4、a9rootfs(根文件系统)
(实际上前3个文件只是提供运行环境,需要逆向的是a9rootfs)
ReadMe.txt中的内容:
操作系统:ubuntu 16.04 32位; 软件:qemu-system-arm 2.5.0/2.10.0版本均测试过(sudo apt-get install qemu-system-arm安装即可),pediy_ctf_2018.tar.gz压缩包内的三个文件; Uboot的目标板:vexpress-a9; Uboot的内存:128M、256M、512M均可; 将压缩包pediy_ctf_2018.tar.gz解压到目录下,在解压后的目录中执行uboot引导命令(二选一即可) Qemu uboot引导命令1:qemu-system-arm -M vexpress-a9 -m 128M -dtb vexpress-v2p-ca9.dtb -kernel zImage -append "root=/dev/mmcblk0 rw" -sd a9rootfs (有图形化界面) Qemu uboot引导命令2:qemu-system-arm -M vexpress-a9 -m 128M -dtb vexpress-v2p-ca9.dtb -kernel zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd a9rootfs (无图形化界面)
为了便于用IDA调试,我没有选择说明文件中建议的Ubuntu而是Windows。
命令行输入:
λ qemu-system-arm -M vexpress-a9 -m 128M -dtb vexpress-v2p-ca9.dtb -kernel zImage -append "root=/dev/mmcblk0 rw" -sd a9rootfs
弹出qemu界面:
设备要求输入key,输入错误则在此处一直循环
提取ELF
1、根据提示信息,用010Editor在3个binary中搜索字符串'please input your key'。对应的文件是a9rootfs。
2、尝试用IDA打开a9rootfs,IDA只能识别为2进制文件。
3、file命令识别文件格式,为ext3格式
abc@ubuntu64:~/Desktop$ file a9rootfs a9rootfs: Linux rev 1.0 ext3 filesystem data, UUID=d8a4bf4a-95c3-4cba-9893-827cd9e120fd (needs journal recovery) (large files)
4、用Explore2fs提取文件系统中的文件
5、在sh文件中搜索到了目的字符串'please input...',且sh为ELF格式。
逆向分析
sh文件运行时,系统还没初始化完成,故所使用的库均为静态链接的。(可能说的不对),没有导入表,没有符号,也没有got和plt。静态分析只能靠经验去'猜'。
比如start中:
EXPORT start MOV R11, #0 MOV LR, #0 LDR R1, [SP+arg_0],#4 MOV R2, SP STR R2, [SP,#-4+arg_0]! STR R0, [SP,#var_4]! LDR R12, =sub_11F8C STR R12, [SP,#4+var_8]! LDR R0, =sub_11374 LDR R3, =sub_11EF0 BL sub_1179C start
根据对ELF的经验猜测,sub_1179c为libc_start_main,而传递给该函数的第一个参数(LDR R0,sub_11374),就是main函数。
main函数中可以看到对printf("please input your key")的循环调用:
loc_113B0 LDR R0, =aPleaseInputYou ; "please input your key:" BL printf
跳出循环的关键判断:
SUB R3, R11, #-input SUB R3, R3, #4 SUB R3, R3, #4 MOV R1, R3 LDR R0, =a100s ; "%100s" BL scanf SUB R3, R11, #-input SUB R3, R3, #4 SUB R3, R3, #4 MOV R0, R3 BL strlen__ MOV R3, R0 STR R3, [R11,#len] SUB R1, R11, #-out1 SUB R3, R11, #-input SUB R3, R3, #4 SUB R3, R3, #4 LDR R2, [R11,#len] MOV R0, R3 BL t1 SUB R1, R11, #-out2 SUB R1, R1, #4 SUB R1, R1, #4 SUB R3, R11, #-input SUB R3, R3, #4 SUB R3, R3, #4 LDR R2, [R11,#len] MOV R0, R3 BL t2 SUB R1, R11, #-out3 SUB R3, R11, #-out2 SUB R3, R3, #4 SUB R3, R3, #4 LDR R2, [R11,#len] MOV R0, R3 BL t3 SUB R3, R11, #-out3 LDR R1, =aC1371da51a9030 ; "C1371DA51A9030079E21DCDC5B78E3856387213"... MOV R0, R3 BL strcmp MOV R3, R0 CMP R3, #0 BNE loc_11648
输入的key经过t2和t3两次变换,和'C1371DA51A9030079E21DCDC5B78E38563872139C13F6F'比较,相等则成功。
t2变换中:
memcpy(out, (int)in, v4, v4); a1((int)out_1, (int)temp, v4); b1((int)out_1, (int)temp, v4); c((int)out_1, v4); a2((int)out_1, (int)temp, v4); b2((int)out_1, (int)temp, v4); c((int)out_1, v4); a1((int)out_1, (int)temp, v4); b2((int)out_1, (int)temp, v4); c((int)out_1, v4); a2((int)out_1, (int)temp, v4); b1((int)out_1, (int)temp, v4); c((int)out_1, v4);
a1和a2算法一致(函数内部的字符串常量不同),b1、b2算法一致,且a和b互为逆运算。(很简单的字符串变换)
c将输入每字节异或并首尾互换。
abc函数均可求逆。
t3其实也是a函数。
求key代码
def r1(input,s): r = '' for i in range(len(input)//2): a = s.find(input[2*i]) b = s.find(input[2*i+1]) r += chr(a*16+b) return r def r2(input,s): r = '' for i in range(len(input)): a = ord(input[i])//16 b = ord(input[i])%16 r += s[a] + s[b] return r def r3(input): l = [ord(input[0])]*len(input) for i in range(1,len(input)): a = ord(input[i]) for j in range(i): a = a^l[j] l[i] = a for i in range(len(input)//2): l[i], l[len(input)-i-1] = l[len(input)-i-1],l[i] r = '' for i in range(len(input)): r += chr(l[i]) return r s1 = 'FDB08642ECA97531' s2 = '13579BDF02468ACE' s3 = '0369CF258BE147AD' s4 = 'FA50B61C72D83E94' s5 = 'FDB08642ECA97531' s6 = 'FA50B61C72D83E94' s7 = '0369CF258BE147AD' s8 = '13579BDF02468ACE' expected = 'C1371DA51A9030079E21DCDC5B78E38563872139C13F6F' a = r1(expected,'0123456789ABCDEF') a = r3(a) a = r2(a,s8) a = r1(a,s7) a = r3(a) a = r2(a,s6) a = r1(a,s5) a = r3(a) a = r2(a,s4) a = r1(a,s3) a = r3(a) a = r2(a,s2) a = r1(a,s1) print(a)
得到Key是2018ctf0520pediy1314yyp
输进qemu,得到:
拿到flag之后还有一次exploit的机会?估计这题最初设计是个pwn吧。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法