案例文件
文件放到了 github.com/aprz512/And… 下,可以自行下载。
案例分析
我们可以使用 file 命令看一下这个文件,或者直接拖到 vscode 里面:
发现这是 android 的一个 backup 文件,我们可以将其解压,在 github 里面搜索 Android backup :
下载其 release 文件,将该文件解压一下:
java -jar abe.jar unpack 1.ab 1.tar
得到一个 1.tar 文件,解压出来,使用 tree 命令看一下目录:
└── com.example.yaphetshan.tencentwelcome
├── a
│ ├── base.apk
├── db
│ └── Demo.db
├── Encryto.db
└── _manifest
里面有一个 base.apk,这个 apk 很老了,只能运行在低版本下,否则会报 so 链接错误。
我们使用 genymotion 开一个 android 5 的模拟器,安装运行界面如下d
点击登录可以进入下一个界面,但是提示明显不对:
反编译看下逻辑:
发现这个界面没有做什么判断,就直接给了一个提示,说明我们想要crack的逻辑不在这里,看下上一个界面的逻辑:
一进来就往数据库里面写了些数据,点击事件并没有使用这些数据。
但是看到 a 方法里面是有一些字符串处理逻辑的,而且这里的 SQLiteDataBase 有一个 loadLibs 方法,正常是没有的,搜索一下:
回想一下,我们解压出来的目录里面有一个 Encrypt.db,所以很明显,这里是要我们拿到这个加密数据库的密钥。看一下这个 sqlcipher 的用法,发现是在 getWritableDatabase 方法的时候传进去就行,那么就思路很简单了。
我们使用 frida hook 这个方法就行。
经过尝试,发现高版本 frida 在使用过程中会闪退,所以又装了一个 12.8.0 版本的环境。
首先,尝试一下 hook com.example.yaphetshan.tencentwelcome.a 类,发现它虽然继承了 net.sqlcipher.database.SQLiteOpenHelper 但是无法 hook 到 getWritableDatabase 方法。
所以,最后是直接 hook 了 net.sqlcipher.database.SQLiteOpenHelper 的 getWritableDatabase 方法:
android hooking watch class_method net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase --dump-args --dump-backtrace --dump-return
然后,手动调用 MainActivity 的 a 方法来触发逻辑执行:
...mple.yaphetshan.tencentwelcome on (Google: 5.1) [usb] # android heap search instances com.example.yaphetshan.tencentwelcome.MainActivity
Using exsiting matches for com.example.yaphetshan.tencentwelcome.MainActivity. Use --fresh flag for new instances.
Handle Class toString()
-------- -------------------------------------------------- -----------------------------------------------------------
0x100462 com.example.yaphetshan.tencentwelcome.MainActivity com.example.yaphetshan.tencentwelcome.MainActivity@15a1e11e
...mple.yaphetshan.tencentwelcome on (Google: 5.1) [usb] # android heap execute 0x100462 a
得到调用堆栈以及参数如下:
- [./incoming message] ----------------
(agent) [uwhcy5xnh7] Backtrace:
net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(Native Method)
com.example.yaphetshan.tencentwelcome.MainActivity.a(MainActivity.java:55)
com.example.yaphetshan.tencentwelcome.MainActivity.onCreate(MainActivity.java:42)
android.app.Activity.performCreate(Activity.java:5990)
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
android.app.ActivityThread.access$800(ActivityThread.java:151)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:135)
android.app.ActivityThread.main(ActivityThread.java:5254)
java.lang.reflect.Method.invoke(Native Method)
java.lang.reflect.Method.invoke(Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
- [incoming message] ------------------
{
"payload": "\u001b[90m[uwhcy5xnh7] \u001b[39mArguments \u001b[32mnet.sqlcipher.database.SQLiteOpenHelper\u001b[39m.\u001b[92mgetWritableDatabase\u001b[39m(\u001b[31mae56f99\u001b[39m)",
"type": "send"
}
- [./incoming message] ----------------
(agent) [uwhcy5xnh7] Arguments net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(ae56f99)
这里获取到的密钥为 :ae56f99。
使用 sqlitebrowser 打开:
拿到FLAG:
使用 base64 解码得到最终结果:
Tctf{H3ll0_Do_Y0u_Lov3_Tenc3nt!}