FCTF2020 WP of RE

RE4-JEB

附件是一个zip包,工具题目提示,是一道Android逆向,那么稍微看了下zip包内容,很明显这是是一个apk包而不是zip,后缀改为apk,进行反汇编。从程序入口开始寻找关键字符串,全局搜索FCTF,congratulation等关键字。在congratulation处定位到关键字。
在这里插入图片描述
那么查看此处Java源码,快速阅读,发现关键信息。
在这里插入图片描述
继续往下看。
在这里插入图片描述
将其中那串字符串,解密,得到如下字符串。

}321nimda{galflj

通常只要将字符串逆序一下,一般能发现什么,逆序如下。

jlflag{admin123}

那么很明显了。题目要求格式为flag{xxx},结果就是.

flag{admin123}

RE7-love

查看PE获得如下基本信息。
在这里插入图片描述
运行一下看看。
在这里插入图片描述

根据字符反馈,进入IDA定位关键函数,但在IDA进行字符串搜索的时候再次发现关键信息,题目提示为base64input,意思应该是对输入进行base64加密,那么这道题目应该是逆向base64算法。
在这里插入图片描述

进入程序后发现,查看主函数流程,十分明了。第一个红框获取输入后,将输入以及输入size传入一个函数,最后将函数返回的结果拷给Dest,并且此时大小大于输入长度,而且重新获取Dest长度,因此可以明显判断,函数为base64Encode函数。之后第二个红框再将结果加上了一段递增的偏移。
在这里插入图片描述
根据以上分析,破解脚本如下:

import base64
key = [0x65 ,0x33 ,0x6e ,0x69 ,0x66 ,0x49 ,0x48 ,0x39 ,0x62 ,0x5f ,0x43 ,0x40 ,0x6e ,0x40 ,0x64  ,0x48]
flag = ''

for i in range(len(key)):
    key[i] -= i
    flag += chr(key[i])
    i += 1

print(base64.b64decode(flag))

运行结果如下:
在这里插入图片描述

flag{i_l0ve_you}

RE8-maze

查看PE。
在这里插入图片描述
运行。
在这里插入图片描述
进入IDA查看,定位关键函数。发现第一个红框是一个函数退出点,应该是进行某种检测,进入后发现是反调试,禁用;第二个红框限定输入为24个字符,并且只能是0-9,a-f也就是16进制符号,后面紧跟着一个if,将输入传入函数,应该是进行校验,通过则get flag。那么我们进入该函数分析。
在这里插入图片描述
在这里插入图片描述
既然是迷宫问题,那么关键是获得迷宫地图。同时我们需要该函数返回true那么,我们就需要从最上面的第一个return语句返回,也就是res = 311。我们先看下byte_54…这个数组,为“delru0123456789”,这个数组应该是再跟进第三个switch语句调用的函数,此处应该有迷宫地图相关的信息。
在这里插入图片描述
该函数,进行了12轮循环,每次i += 26,那么猜测迷宫的size应该是1226。而res的值需要等于311也就是12 26 - 1,那么显然就是地图右下角,res起始值为0,也就是初始点是左上角。那2个数组的异或操作应该就是迷宫地图了,我们可以将数据dump下来,异或一下,这里我用IDA内置的IDC对数据进行异或一下,查看结果。
在这里插入图片描述
返回switch语句研究下迷宫移动是什么规则。第一个switch语句也就是获取第一个字符,进行4个分支判断,根据第三switch语句这是决定了走迷宫的方向;第二个switch语句获取了下一个字符,根据第三switch语句这是获取在该方向上要走多少步。那么用户输入的规则就是需要12组,每组第一个为1,2,3,4,5,分别是对应4个方向已经不走;第二个字符为该方向上的步数。选择就是确定dlru的方向了,我们分别查看第三switch语句的分支调用的函数,查看循环计数是怎么变换的,以此来确定走向,最终得到结果,观察下迷宫,上面是每个格子有4个字符,有几个字母表示这个格子上那个进行那几张操作。
在这里插入图片描述

眼睛看花后,终于得到了这组输入!

06360836063b0839073e0639

还是err,我们目前都只是分析主函数中一个调用的子函数,那么返回主函数看看有什么发现,发现输入还传入给了一个函数,以及进行一次异或。
在这里插入图片描述
在这里插入图片描述
又将输入传入了一个函数,再次跟进查看,结果这函数伪代码500行逻辑十分复杂,各种条件判断交叉,根本看不出什么,只好从汇编看看能不能发现什么。然而汇编仍然十分复杂,放弃了看汇编,联想到开始有反调试机制,也许可以从调试中看到什么。调试跟进查看。
在这里插入图片描述
我们输入24个1,进行调试。发现那个异或操作是对输入的第17个字符与1异或,接着往下看,我们终于发现那个对输入进行再处理的函数了,如下:
在这里插入图片描述
跟进,发现里面又将输入传个另一个函数,继续跟进并时刻注意栈上的输入何时变化,怎么变化,发现没有变化跳出了函数,那么继续往下观察。
在这里插入图片描述
发现经过下面这个函数时候,数据变了。
在这里插入图片描述
这里有跑大概近10次才对输入字符运算一个,不知道为什么。总之根据每一个变化情况,最后猜测是异或。首先,相同的输入,每个字符变化都不同,跨度极大,极有可能是异或,并且绝对不是异或一个固定的数字,否则结果一样。
在这里插入图片描述
根据猜测,最后发现结果是与下标异或。

arr = [0x30 ,0x36 ,0x33, 0x36, 0x30, 0x38 ,0x33 ,0x36 ,0x30 ,0x36 ,0x33 ,0x62 ,0x30 ,0x38, 0x33 ,0x39 ,0x30 ,0x37 ,0x33 ,0x65 ,0x30 ,0x36 ,0x33 ,0x39  ]

arr[16] ^= 1
flag = ''
for i in range(len(arr)):
    flag += chr(arr[i] ^ i)
print(flag)


结果如下:
在这里插入图片描述
验证成功,并给了张二维码。
在这里插入图片描述
在这里插入图片描述
查看,里面是一句话。
Congratulations! The flag is your input + “Docupa”

那么flag就是.

zsctf{07154=518?9i<5=6!&!v$#%.Docupa}

发布了19 篇原创文章 · 获赞 2 · 访问量 2525

猜你喜欢

转载自blog.csdn.net/SC_king/article/details/105338545