IDA动态调试Android App以及手动脱壳

0x00 背景

最近在做一个函数的app的脱壳,记录一下遇到的坑。

0x01 步骤

  1. 将IDA的android_server push 到手机上,启动android_server。
  2. 转发端口
    adb forward tcp:23946 tcp:23946
    

    如果是用gdbserver调试,则转发gdbserver设置的端口,比如

    adb forward tcp:9090 tcp:9090
    
  3. 启动app:
    adb shell am start -D -n com.aaaa.bbbb/com.seworks.medusah.MainActivity
    

    如果你想用gdbserver进行调试,则在进行这个步骤之后用gdbserver attach上进程:

    gdbserver64 tcp:9090 --attach [pid]
    
  4. 打开android studio,打开ddms。或者用这个命令转发jdwp的端口(mac用):
    for pid in `adb shell "ps | grep your.package.name" | awk '{print $2}'`; do adb forward tcp:8700 jdwp:$pid; done
    
  5. 打开IDA->Debugger->Attach->Remote ArmLinux/Android debugger,点击OK。
    如果你是使用gdb,则使用ndk的gdb输入以下命令连接gdbserver:

    gdb
    (gdb)set architecture arm
    (gdb)target remote :9090
    (gdb)set arm force-mode thumb // or arm if the instructions look weird
    
  6. 打开IDA->windows->modules,搜索libdvm.so,双击libdvm.so,在新开的tab中搜索dexFileParse,双击该函数,在函数开头按F2设置断点。
  7. 连接jdb
    jdb -connect "com.sun.jdi.SocketAttach:hostname=localhost,port=8700"
    
  8. 回到IDA中执行F9直到执行到断点。
  9. 打开File->Script command,输入:
    static main(void)
    {
      auto fp, begin, end, dexbyte;
      fp = fopen("E:\\dump.odex", "wb");
      begin = r0;
      end = r0 + r1;
      for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
          fputc(Byte(dexbyte), fp);
    }
    

    然后执行

  10. 取出手机里的所有framework文件:

    adb pull /system/framework/ ./framework/
    
  11. 根据framework将odex文件转换为smali文件:
    java -jar .\baksmali-2.1.2.jar -x .\dump.odex -d .\framework
    

    ,此时会生成out文件夹,里面都是smali文件。

  12. 将smali文件打包为dex文件:

    java -jar .\smali-2.1.2.jar out -o classes.dex
    
  13. 将dex文件反编译为jar文件:
    .\dex2jar-2.0\d2j-dex2jar.bat .\classes.dex
    
  14. 使用jd-gui打开classes-dex2jar.jar文件即可查看。

0x02 坑

  1. 必须把app设置为debuggable,否则即使打开ddms也无法使用jdb -connect。为了使所有app变为debuggable,可以使用这个substrate的hook: https://github.com/iSECPartners/Android-OpenDebug

  2. dump时C盘有可能没有写入权限,所以我们写入E盘。

  3. dvmDexFileOpenPartial并没有被执行到,无法在这个函数中设置断点进行dump,据网上的说法是有的壳判断系统版本,OS >= 4.0则使用dvmRawDexFileOpenArray函数,OS <= 4.0则使用dvmDexFileOpenPartial函数。(http://bbs.pediy.com/showthread.php?p=1396042