Android Native Library脱壳的一些Tips

这几天看了一下Android下so文件的壳与脱壳,目前这一块应该还算是比较新的市场。个人感觉,受到调试器和计算资源的影响,虽然已经有多家厂商在做,但目前的总体强度和花样,远没有x86下的五花八门。

对于我们这种每天都在被各种病毒的变形外壳虐待的人,掌握了技巧,一般的Android壳还是很好脱的。其实,到目前为止我也只看了一个。

福利

今天,鱼妹兔在看雪论坛上发表的《ApkProtect 分析》绝对是一个很好的研究资料。其中包括了完整逆向的壳代码,还有大量注释的idb,很好的呈现了Android壳的主要流程和必须的细节。掌握了其中的关键,别的壳也就是时间的问题。

工具

手头没空闲的真机调试,最近只能考虑虚拟机/模拟器了。尝试了BlueStacks,Root之后还是无法附加,遂放弃。最后还是使用了AVD。调试器方面,Windows下可用的,目前只知道IDA Pro 6.x。

调试步骤

为了调试Android上的Native程序,首先要在Android上运行IDA的android_server。
运行android_server:

.adb.exe push "D:ToolsDebuggersIDAIDA.Pro.v6.1android_server" /data/ida/android_server
.adb.exe shell chmod 755 /data/ida/android_server
.adb.exe shell /data/ida/android_server
IDA Android 32-bit remote debug server(ST) v1.14. Hex-Rays (c) 2004-2011
Listening on port #23946...

设置转发端口:

.adb.exe forward tcp:23946 tcp:23946

完成上述步骤,就可以使用IDA的Remote ARMLinux/Android Debugger附加到指定的进程上。

0xBE

尚不知道如何创建APK进行调试,所以只能采取迂回的方法实现。类似于Windows下修改入口的0xCC的做法,通过修改入口代码产生软件断点,然后调试器附加进程,修改回原始代码进行调试。Arm上就不是0xCC,而是0xBE。具体的步骤如下:

  1. 从压缩包中提取so。
  2. IDA加载so,找到JNI_OnLoad(或者其他函数),记录下Offset。
  3. Hex工具打开so,转到Offset+1,记下原始字节,然后修改为0xBE。
  4. 重新打包并签名。

上传并运行apk之后,如果程序加载了so,会断在入口。此时,附加并把0xBE修改回原始的代码就行了。

反调试

今天还真过了一个反调试,还没完全过掉,以后再写。

Original Entry Point

原始入口原型:

jint JNI_OnLoad(JavaVM* vm, void* reserved);

ARM下面的函数调用AAPCS,所以vm和reserved分别是r0和r1。所以,跟踪一下r0和r1的走向,r0和r1的值一开始都会被保存在某个地方,当这两个值恢复到r0和r1的时候,也就是调用OEP的地方。
暂时就这样。

Android Native Library脱壳的一些Tips》有4个想法

  1. NFE

    attach进程之后,直接去找so的开始地址,再加函数的offset设置断点岂不是方便些嘛?r0-r3一般用来传递参数,如果过多的参数就用堆栈方式

    回复
    1. TheCjw 文章作者

      这是主要是脱壳,改so是最方便的方法了。不知道你这样怎么让程序停在入口?
      当然重新打包会导致一些问题,直接修改安装好的so最实在。

      回复
  2. neve

    请问楼主,如果进程在启动的时候就加载so,我们没有attach的时间呢?进程会由于没有处理BE直接退出了~~~

    回复
    1. TheCjw 文章作者

      当时写这文章的时候考虑不周。
      首先,你需要确定一下,是Thumb Mode还是Arm Mode。Thumb的改BE BE没问题,Arm的话改成FE FF FF EA。
      第二,检查一下是否有.init_proc,有的话要处理这个。

      回复

NFE进行回复取消回复