前言
算了一下好长时间没打过CTF了,前两天看到ACTF逆向有道flutter逆向题就过来玩玩啦,花了一个下午做完了.说来也巧,我给DASCTF十月赛出的逆向题其中一道也是flutter,不过那题我难度降的相当之低啦,不知道有多少人做出来了呢~
还原函数名
flutter逆向的一大难点就是不知道libapp.so
的函数名,虽然有工具reflutter
可以帮助我们得到其中的符号,但是我个人认为基于对libflutter.so
源码插桩后重编译再重打包apk的方式具有极大的不可预料性,极有可能导致apk闪退,这一题便出现了这种情况,所以接下来我将介绍的工具blutter
是纯静态分析来还原函数名,更令人惊喜的是它提供了IDApython
脚本来让我们可以在IDA中对函数进行重命名,而这个项目中提供的其他文件也相当好用
blutter的编译及使用
blutter项目地址
在各个平台如何编译在这个项目的README.md中写的已经相当详细了,这里我就简单介绍一下Windows上的编译过程吧,注意一下这些命令需要全程运行在代理环境否则会导致无法下载
首先clone项目
1 | git clone https: //github .com /worawit/blutter --depth=1
|
随后运行初始化脚本
1 2 | cd .\blutter\
python .\scripts\init_env_win.py
|
请注意,接下来我们需要打开x64 Native Tools Command Prompt
,它可以在Visual Studio
文件夹中找到

然后运行blutter.py
并提供libapp.so
和libflutter.so
的文件夹路径以及输出文件夹路径
1 | python .\blutter.py ..\chall\lib\arm64-v8a\ .\output
|

输出文件夹目录如下

随后我们用ida反编译libapp.so
,并运行输出文件夹中的IDApython脚本ida_script/addNames.py
,符号就被全部恢复出来啦

hook关键函数 获取函数参数
这里我们需要关注的函数是flutter_application_1_main__LongPressDemoState::_onTap
,因为在flutter的开发中,onTap函数是按钮点击之后的响应函数

随后我们进入sub_1DE500
,在该函数中双击sub_1DE59C
进入

在这个函数中我们发现了256
,%
,^
这些特征,合理猜测一下算法可能是RC4


接下来我们使用输出文件夹中的blutter_frida.js
hook一下sub_1DE59C
看看情况

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 | PS D:\hgame\ACTF\native app\work\blutter> frida -U -f "com.example.flutter_application_1" -l .\output\blutter_frida.js
[Pixel 3::com.example.flutter_application_1 ]->
Unhandle class id : 46, TypeArguments
GrowableList@6d00488c29 = [
188676,
0,
{
"key" : "Unhandle class id: 46, TypeArguments"
},
34,
{
"key" : [
184,
132,
137,
215,
146,
65,
86,
157,
123,
100,
179,
131,
112,
170,
97,
210,
163,
179,
17,
171,
245,
30,
194,
144,
37,
41,
235,
121,
146,
210,
174,
92,
204,
22
]
},
0,
0,
0
]
|
这里我们只hook到一个数组的值,另一个数组的类型是TypeArguments
,研究了一下blutter_frida.js
后发现作者还没有对这种数据类型格式提供hook支持

IDA动态调试libapp.so
现在我们得到了一个数组,我们就暂时认为它就是flag经过加密之后得到的结果,接下来我们在IDA中对sub_1DE59C
下断点动态调试来更加深入的研究一下
首先我们需要将IDA文件夹中的dbgsrv/android_server64
push到手机上面,然后运行一下并且指定端口
1 2 3 | blueline: /data/local/tmp
IDA Android 64-bit remote debug server(ST) v7.7.27. Hex-Rays (c) 2004-2022
Listening on 0.0.0.0:11112...
|
随后端口转发一下
1 2 | PS C:\Users\oacia> adb forward tcp:11112 tcp:11112
11112
|
在IDA中选择调试器为Android debugger

随后点击Debugger->Debugger options...
选择如下配置

点击Debugger->Process options...
,Hostname
修改为127.0.0.1
,Port
修改为11112

然后点击Debugger->Attach to process...
,附加到我们目标包名的进程上面

弹出该弹窗选择Same即可

在手机上点击按钮,然后在IDA中点击这个绿色的剪头,就可以动态调试啦


在动态调试之后,未知的变量也逐渐浮现了出来,这里我们发现了v28>=256
,那么很有可能就是RC4了哦

既然这样,那么直接在这里唯一的异或的地方用IDA去trace一下,把异或的数组dump下来不就行了:)

于是我们得到了被异或的数组了

但是在异或运算的地方下断点之后,我输入的数全都是1
,这里被异或的数也全是0xce

所以莫非不是RC4?让0xce和0x31
异或一下看看,竟然是0xff
这么有意义的数字

所以exp也就能写出来啦~
1 2 3 4 5 6 7 8 | final = [ 184 , 132 , 137 , 215 , 146 , 65 , 86 , 157 , 123 , 100 , 179 , 131 , 112 , 170 , 97 , 210 , 163 , 179 , 17 , 171 , 245 , 30 , 194 ,
144 , 37 , 41 , 235 , 121 , 146 , 210 , 174 , 92 , 204 , 22 ]
xor = [ 14 , 14 , 68 , 80 , 29 , 201 , 241 , 46 , 197 , 208 , 123 , 79 , 187 , 55 , 234 , 104 , 40 , 117 , 133 , 12 , 67 , 137 , 91 , 31 , 136 ,
177 , 64 , 234 , 24 , 27 , 26 , 214 , 122 , 217 ]
flag = [ chr (xor[i]^final[i]^ 0xff ) for i in range ( len (final))]
print (''.join(flag))
|
[培训]《安卓高级研修班(网课)》月薪三万计划