这道题曾是阿里某次CTF比赛中的一道题,如图:

要求是:输入一个网页的URL,然后点击按钮跳转到另一个页面,但要弹出指定内容的 Toast提示,内容是 "祥龙!"
将apk拖到JEB中:

可以看到只有一个StubApplication,且 attachBaseContext 和 onCreate 是在 libmobisec.so 库中实现的,很明显该apk被加固了。
用apktool 对 apk 进行反编译,查看一下反编译后的目录结构:

看到有 assets目录,进入该目录:

发现这里有两个 jar文件,可以猜想这两个文件存放的是原始dex经过加密后的数据。
从上面的分析看,我们分析的切入点可以是 libmobisec.so 这个共享库,使用IDA pro 对它进行动态调试,在关键函数处下断,在内存中dump出解密后的 dex。但这次我打算用一个更加简单直接的方式,就是对 libdvm.so 进行动态调试,在 dvmDexFileOpenPartial 函数开始处下断,然后进行内存dump。
因为加固后的dex文件最终都是要加载到内存中运行的,而dvmDexFileOpenPartial 函数会将最终得到的dex文件加载到内存中。该函数的的实现在Android 系统源码的 dalvik/vm/DvmDex.cpp 文件中,其声明如下:
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);
其第一个参数是 dex 在内存中的起始地址,第二个参数是 dex 的大小。
下面就来对 libdvm.so 进行动态调试:
(1) libdvm.so 可从 Android 设备中 pull 出来,然后拖到IDA 中
adb pull /system/lib/libdvm.so .
(2) 启动IDA 的 android_server

(3) 设置本地端口转发

(4) 启动 ddms,然后用 am -D 的方式启动应用:

(5) 使用 IDA 进行 attach:

(6) 启动 jdb:

(6) 在 dvmDexFileOpenPartial 函数开始处下断点,点击IDA 运行按钮:

现在断下了,此时,R0 寄存器存放的是第一个参数,即dex在内存中的地址,而 R1 寄存器存放的是第二个参数,即dex 的大小,此时,用idc 脚本将其 dump 出来:

将 dump出来的 dex文件拖入 JEB 中,可以看到该 dex 是正常的,各个类都能解析出来了:

接着就可以使用 baksmali 将 dump.dex 反编译,然后将反编译后得到的 smali 文件 拷贝到上面反编译加固apk 得到的目录中,【同时记得修改清单文件的入口点】再利用 apktool 进行打包,最后签名,就可以得到脱壳后的 apk,这里将其命名为:CrackMe_unpack_sig.apk ,安装到 Android 设备上,确实可以正常运行。至此,脱壳这一步已完成。
接下来继续分析代码:
先来看 MainActivity:

逻辑很简单,就是接收EditText 中的输入内容,并将其作为数据传给要启动的 WebViewActivity 中。继续看 WebViewActivity 的代码:

这里关注两个方法调用:
- addJavascriptInterface 方法
- loadUrl 方法
addJavascriptInterface() 的一般用法如下:
mWebView.addJavascriptInterface(new JavaObject(this), "object_name");
第一个参数是本地的Java 对象,第二个参数是给 JavaScript 脚本使用的对象的名称。在 JavaScript 脚本中,可通过该对象名称来调用对应本地Java 对象的方法。
但是这里的对象名称已经被 ListViewAutoScrollHelpern.decrypt_native() 方法给加密了,加密后的字符串就是:"BQ1$*[w6G_" .
点击进入 ListViewAutoScrollHelpern 查看:

发现 decrypt_native 是一个 native 方法,实现在 libtranslate.so 共享库中。
分析到这,其实最简单的解密方法是,自己构造一个 ListViewAutoScrollHelpern 类,然后定义 native 方法decrypt_native(),然后调用 libtranslate.so 进行解密即可。
于是,新建一个 Android 工程,在上面反编译加固apk的目录下找到 libtranslate.so,添加到工程中;然后创建所需要的类,这里要注意,如果是仅仅创建 ListViewAutoScrollHelpern 类还是不够的,因为 libtranslate.so 中还注册了其他类的 native 函数,这个可以将 libtranslate.so 拖到 IDA 分析可知:


新建的 Android 工程的目录结构如下:

运行程序可解密获得对象名称为:SmokeyBear
于是创建一个 html 页面 crack.html,内容如下:

这里就没必要搭建服务器了,直接本地测试,将crack.html 给push 到CrackMe 应用的数据目录下:

运行CrackMe 程序,通过 adb shell input text 将内容输入到 EditText:

点击跳转,成功弹出了 Toast:

相关文件下载:
链接:https://pan.baidu.com/s/1CVAUeEK-JDXupQmqk6g6aA 密码:o3ok
网友评论