2015 0CTF simple writeup

考察知识点

  • hook 系统函数
  • dump 内存搜索 flag

赛题链接

https://github.com/eternalsakura/ctf_pwn/blob/master/android逆向/EasyRe.apk

分析

java层


用jadx反编译apk,在java层的逻辑很简单。
读取flag.txt这个文件的内容,然后和我们的输入数据相对比,如果一致就提示“That’s the flag!”
找一下这个文件,


0ctf{Too_Simple_Sometimes_Naive!!!}
不出意外是个假flag。

提示一下,请不要用模拟器打开去输入flag,那你会输出That’s the flag!

究其原因是因为模拟器都是用的x86去模拟arm,而这里动的手脚是在so文件里,所以请用真机测试。

so层分析

我们推测应该是在apk运行前做了什么操作,找到so文件用IDA打开
so文件里没有JNI_Onload函数,找到.init_array段,调用了my_init函数

打开后F5反编译,发现CheckSig和j_hook函数,推测做了签名验证反调试和对系统函数进行hook。

并且根据传入的参数判断应该是hook的read函数。

解题

http://www.purpleroc.com/MD/2015-03-31@0CTF_WriteUp.html
http://ipushino.blogspot.de/2015/04/0ops-ctf-qualifiers-2015-simpleapk.html
github上面给出的两篇wp都没有分析代码,而是在内存中搜索字符串。
我翻了翻代码看不太懂,就先学习一下这种姿势。

dump 内存搜索 flag

利用 ddms 的 dump HPROF file 功能 (带箭头的油桶图标)

然后搜索字符串:
strings easyre.sjl.gossip.easyre.hprof | grep 0ctf

flag得到:0ctf{It’s_More_Than_Meets_The_Eye!}

利用 gore

gdb下载

Android NDK 在 r11 之后去掉了 toolchain 中的 gdb 工具,所以我下载了r10 的.(整包下载,只有gdbserver和gdb会报bug),就像下图这样。

将gdbserver放入手机并添加执行权限

adb push gdbserver /data/local/tmp

查找要dump的应用的pid


ps | grep 名字

启动gdbserver,指定监听端口

./gdbserver :1234 --attach pid
1234可随意指定

转发端口并调试

1
2
3
4
adb forward tcp:1234 tcp:1234
./arm-linux-androideabi-gdb
(gdb) target remote :1234
(gdb) gcore

gore dump 出内存后,搜索字符串

strings core.xxx | grep xxx

总结

dump出内存的第一种方法比第二种要快速高效一些。
另外,在我测试的时候,在不进行任何输入的时候,搜索字符串是搜索不到真正的flag的。
click前:

click后(随便输个123456):


这也验证了确实是hook了read函数,把从flag.txt读取的字符串进行了某种变换,得到0ctf{It’s_More_Than_Meets_The_Eye!}在内存中。