首页
社区
课程
招聘
[原创]看雪CTF.TSRC 2018 团队赛 第十一题 伊甸园
2018-12-22 16:35 4555

[原创]看雪CTF.TSRC 2018 团队赛 第十一题 伊甸园

ccfer 活跃值
16
2018-12-22 16:35
4555
看雪CTF.TSRC 2018 团队赛 第十一题 伊甸园

题目做完,感觉靠的是幸运,像是在玩找茬游戏或者连连看,逆向写算法什么的都是不存在的。

从这里开始:
.text:0040342F                 mov     [ebp+var_94], offset ??_7Base62@@6B@ ; const Base62::`vftable'
.text:00403439                 mov     [ebp+var_7C], 0Fh
.text:00403440                 mov     [ebp+var_80], 0
.text:00403447                 mov     [ebp+var_90], 0
.text:0040344E                 push    3Dh             ; size_t
.text:00403450                 push    offset aAbcdefghijklmn ; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"...
.text:00403455                 lea     ecx, [ebp+var_90]
.text:0040345B                 mov     byte ptr [ebp+var_4], 2
.text:0040345F                 call    sub_401DD0
.text:00403464                 mov     [ebp+var_78], 39h
.text:00403468                 lea     ecx, [ebp+var_10D0]
.text:0040346E                 call    sub_408CF0
.text:00403473                 mov     edx, offset aPleaseInputThe ; "please input the key"
.text:00403478                 mov     byte ptr [ebp+var_4], 4
.text:0040347C                 mov     ecx, offset unk_4570F8
.text:00403481                 call    sub_4040C0
.text:00403486                 push    eax
.text:00403487                 call    sub_404370
.text:0040348C                 add     esp, 4
...
读取输入,然后在输入前面拼接了0x3E8长度的固定内容,输入后面拼接了0x1F40和0x208F长度的固定内容
判断总长度需要是0x4407
所以自己输入的长度是0x4407-0x3E8-0x1F40-0x208F=0x50
.text:00403623                 cmp     [ebp+var_4C], 4407h
.text:0040362A                 jnz     loc_40392D
...
.text:0040365F                 lea     eax, [ebp+var_2C]
.text:00403662                 push    eax             ; int
.text:00403663                 lea     ecx, [ebp+var_94]
.text:00403669                 call    sub_4017C0						//这里面输入的解码,表面看是base62,其实算上9开头的转义,实际相当于base64:9A对应9,9B对应+,9C对应/,9D对应=
.text:0040366E                 push    eax             ; void *
.text:0040366F                 lea     ecx, [ebp+var_5C] ; void *
.text:00403672                 call    sub_403B40
.text:00403677                 lea     ecx, [ebp+var_2C]
.text:0040367A                 call    sub_401C40
.text:0040367F                 mov     edx, offset aCheckingTheRes ; "checking the result ..."
.text:00403684                 mov     ecx, offset unk_4570F8
.text:00403689                 call    sub_4040C0
.text:0040368E                 push    eax
.text:0040368F                 call    sub_404370
.text:00403694                 add     esp, 4
.text:00403697                 cmp     [ebp+var_4C], 31ABh	//判断base64解码后的长度
.text:0040369E                 jnz     loc_40392D
.text:004036A4                 cmp     [ebp+var_48], 10h
.text:004036A8                 lea     edx, [ebp+var_5C]
.text:004036AB                 mov     [ebp+var_A0], 0
.text:004036B5                 cmovnb  edx, [ebp+var_5C]
.text:004036B9                 mov     [ebp+var_9C], 0
.text:004036C3                 sub     esp, 8
.text:004036C6                 mov     byte ptr [ebp+var_4], 8
.text:004036CA                 mov     ecx, esp
.text:004036CC                 sub     esp, 8
.text:004036CF                 mov     eax, esp
.text:004036D1                 mov     dword ptr [eax], 0
.text:004036D7                 mov     dword ptr [eax+4], 0
.text:004036DE                 call    sub_40C720						//处理解码后的逆波兰表达式,按树结构存储
.text:004036E3                 add     esp, 8
.text:004036E6                 lea     ecx, [ebp+var_A8]
.text:004036EC                 call    sub_405160
.text:004036F1                 lea     ecx, [ebp+var_A8]
.text:004036F7                 mov     byte ptr [ebp+var_4], 9
.text:004036FB                 call    sub_40B580						//对表达式进行自定义的运算处理
...
.text:004037D9                 cmp     dword_457FAC, 10h
.text:004037E0                 lea     ecx, [ebp+var_5C]
.text:004037E3                 push    dword_457FA8
.text:004037E9                 mov     edx, [ebp+var_4C]
.text:004037EC                 mov     eax, offset zz_exp_all
.text:004037F1                 cmovnb  eax, zz_exp_all
.text:004037F8                 cmp     [ebp+var_48], 10h
.text:004037FC                 push    eax
.text:004037FD                 cmovnb  ecx, [ebp+var_5C]
.text:00403801                 call    sub_403BF0						//处理结果和固定字符串比较,如果相同基本就算过关,后面的其它判断估计是防止多解的
.text:00403806                 add     esp, 8
.text:00403809                 test    eax, eax
.text:0040380B                 jnz     loc_40392D

题目中定义了3个常数:
.rdata:004525AC off_4525AC      dd offset asc_452500    ; "x"
.rdata:004525B0                 dd offset aE_1          ; "e"
.rdata:004525B4                 dd offset aPi           ; "pi"
和9种运算操作:
.rdata:004525B8 off_4525B8      dd offset asc_45250C    ; "+"
.rdata:004525BC                 dd offset asc_452510    ; "-"
.rdata:004525C0                 dd offset asc_452514    ; "*"
.rdata:004525C4                 dd offset asc_452518    ; "/"
.rdata:004525C8                 dd offset aPowerXa_3    ; "Power_xa"
.rdata:004525CC                 dd offset aPowerAx_0    ; "Power_ax"
.rdata:004525D0                 dd offset aLog_1        ; "Log"
.rdata:004525D4                 dd offset aSin_1        ; "Sin"
.rdata:004525D8                 dd offset aCos_1        ; "Cos"

这些运算操作不要用字面含义去理解,只是个符号而已,实际运算关系是在sub_40B580里面自定义的
我并没有详细分析每种操作具体如何定义
由于输入的表达式和目标结果的表达式第一个操作都是 / ,所以我只是跟了一下 / 的操作过程,大概类似这样:
a/b	相当于 (?*b-a)/b*b
这里面我写个?,是因为那些还要递归继续处理的,我只跟踪了最表面的一层关系
正规解法应该是把所有这些操作逆出来,对表达式做一次逆操作?感觉工作量有点大,还未必能成功,先尝试能不能投机取巧吧。

观察输入和目标输出发现,输入的片段都能在输出中找到相似的片段,那我们要求解的这部分也应该在面有相似的片段,
首先发现输入中的*,Log,x,x在输出中完全不存在,这应该是按*1处理直接优化掉了,所以先把输入中的*,Log,x,x组合全剔除

现在的问题就是整个表达式中间残缺的一段59个字节怎么补充,式子太长,我只截取前后一小段范围的数据,其中59个#就是要解决的:
Power_ax,68,x,x,*,pi,75,38,x,88,/,+,/,Power_ax,44,-,+,*,pi,75,x,x,*,pi,75,+,*,Power_ax,68,x,x,x,x,Log,Power_xa,*,pi,75,37,Log,Power_ax,90,Log,/,Power_ax,36,x,x,*,Power_ax,68,x,x,*,
###########################################################
pi,75,Log,*,-,Power_ax,23,-,Power_xa,*,Log,Power_ax,90,Log,/,Power_ax,36,x,x,*,Power_ax,68,x,x,*,pi,75

经过多次尝试,最后我盯上了38,x,88这一个小片段,按个小片段做个行对齐:

图中可以看出我标记的那几行(我当时并没有把输入后面部分放进去对比,现在在写WP时才全合到一起对比),输出中有多处对应最后一个#的位置是逗号,接下来是个/操作,说明下面结构合理:
pi,75,Log,*,-,Power_ax,23,-,Power_xa,*,Log,Power_ax,90,Log,
把这个替换到输入处验证,发现失败
然后才想到把输入中也全放进去对比,结果看到输入中那行和输出差了一个符号,*变成了+:
pi,75,Log,*,-,Power_ax,23,-,Power_xa,+,Log,Power_ax,90,Log,
把这个替换到输入处验证,OK了

最后把这部分base64编码回去,要注意base64的字节对齐位置,我开始也是失误了几次没做对
因为前面0x3E8长度中有30处9A转义,导致不是4的倍数,所以要把前面一个逗号借过来用
base64(",pi,75,Log,*,-,Power_ax,23,-,Power_xa,+,Log,Power_ax,90,Log,")
=LHBpLDc1LExvZywqLC0sUG93ZXJfYXgsMjMsLSxQb3dlcl94YSwrLExvZyxQb3dlcl9heCw5MCxMb2cs
把前两个字符LH还给借用方,最后一个字符s送给后面了,然后把其中的9换成9A得到最后结果:
BpLDc1LExvZywqLC0sUG9A3ZXJfYXgsMjMsLSxQb3dlcl9A4YSwrLExvZyxQb3dlcl9AheCw5MCxMb2c
本以为她在山的那边,却没想到她已在这边等候。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2018-12-22 21:25 被ccfer编辑 ,原因:
收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回