Android 逆向工程 —— Android 原生程序逆向 2

APK 下载
可调试的 APK
可动态调试的 APK

这次的 APP 是 2015 年移动安全挑战赛(看雪&阿里主办)中的第二题,网上已经有很多关于这个 APP 的破解方法,但是我跟着这些教程里的步骤来做,有些步骤总是不能成功,有些步骤也是半知半解,所以想把这个过程详细地记录下来

1. 逆向 APK####

首先用 jadx 大致看看程序的结构和流程

程序由 4 个类组成,大致浏览之后将注意力集中在 MainActivity 上,这个 Activity 有一个 native 方法,securityCheck,并且通过该方法来判断输入是否正确,我们要做的就是逆向这个方法来找到正确的输入

2. 静态分析####

打开 IDA,载入对应的 so 文件,找到 Java_com_yaotong_crackme_MainActivity_securityCheck 函数

导入 JNINativeMethod 和 JNINativeInterface 结构,进行简单处理后按下 F5

留意到影响函数返回值的实际上在最后的 while(1) 循环中,在该循环中将 v5 和 v7 的值进行比较,如果不相等就跳出循环返回 0 (即 false),而 v7 的值是 v6 存放的地址中的值,查看 v6 存放的地址处的值

看到一个很像答案的字符串 “Wojiushidanan”,然而试过之后发现并不是。这就说明前面乱七八糟的代码对这个字符串做了一定的处理,而具体是怎么处理的看起来太复杂了,于是来试试动态分析

3. 动态分析####

要用 IDA 对某个 APP 进行动态分析的前提是要有一台 root 过的手机,我之前用的华为 Mate 7 是 Android 6.0 的系统,root 起来特别麻烦,root 之后调试 APP 的效果也不太好,推荐使用低版本的 Android。模拟器好像也是不行的,我试了好几个,一运行就闪退,可能是程序对运行的环境也有检测,也可能是架构问题。反正最好是用一部装有低版本 Android 系统而且已 root 的真机

在有了满足条件的手机以后,将 IDA 安装目录下的 dbgsrv 目录下的 android_server 拷贝到手机上,拷贝的方法有很多,用 QQ 直接传也可以,用 adb push 也可以,只要能找到存储路径就行。接着用 adb shell 进入系统的 shell,然后在 root 权限下用 chmod 755 命令将 android_server 修改为可运行,修改好后运行 android_server,如果运行成功会显示:

说明现在 android_server 在手机的 23946 端口监听

现在要做的是把手机的 23946 端口映射到电脑上,用 adb forward tcp:23946 tcp:23946 就可以把手机的 23946 端口映射到电脑的 23946 端口

接下来在手机上运行该 APP,然后尝试用 IDA 进行连接,在 Debugger 选项卡中选择 Attach to,找到这个 APP,点击 OK 后发现程序闪退了,那就说明在程序中进行了判断,不允许动态调试

一般的反调试原理是这样的:IDA 使用 android_server 在 root 环境下注入到被调试的进程中,其用的技术是 Linux 中的 ptrace。在 Android 中如果一个进程被另一个进程 ptrace 之后,在它的 status 文件中的一个字段 TracePid 就标识了是那个进程 trace 了它自己。因此,只要在程序运行的过程中循环检测进程中的 TracePid 标识就可以知道程序是否被调试。需要注意的是,这种方法不仅可以用在程序启动的时候,在程序正常流程中间随机插入这样的检测代码(暗桩),往往可以给调试带来更大的难度。

再回过来看这个程序,这个程序是一开始运行就退出了调试界面,说明这个检测的执行时机比较早,已知的比较早运行的两个函数是 .init_array 和 JNI_onload,.init_array 是一个 so 最先加载的段信息,时机最早,一般的 so 解密操作都是在这里做的;而 JNI_onload 是在 so 被 System.loadLibrary 加载后紧接着调用的,时机早于 native 方法,但是在 .init_array 方法之后

先试试是不是在 JNI_onload 中进行的反调试检测

  1. 首先看看 AndroidManifest.xml 里面有没有添加 android:debuggable="true",发现没有,把它加到 application 标签下,最后重新打包签名成 APK 再安装到手机上
  2. 用 am 以调试的方式启动 MainActivity,命令如下:
    am start -D -n com.yaotong.crackme/.MainActivity-D 的意思是以调试的方式启动,具体用法可参见 Android AM 命令及使用
    使用 adb jdwp 命令可以看到当前可被调试的程序的 pid,如果该命令没有输出说明第一步出错了
  3. 用 IDA Attach 上调试方式启动的程序,在此之前要修改 Debug Options 修改为:



    不在 library 加载之前挂起那 library 执行后程序就退出啦

  4. 按 F9 让程序跑起来,然后用 jdb 连接,具体命令为:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
    这里的 port=8700 是在 DDMS 中看到的(好像要打开 DDMS 才能让 jdb 命令生效)
  5. 在静态分析 so 文件中查看 libcrack.so 中 JNI_onload 函数的偏移



    偏移是 1B9C

  6. 在动态调试中按下 Ctrl + S 查看段信息



    看到带有 X 属性的 libcrackme.so (至于为什么要找带有 X 属性的 so,我个人理解是只有这个 so 才是会执行的)的起始地址是 7651D000,加上 1B9C 就是 7651EB9C

  7. 按下 G 跳转到 7651EB9C,然后按下 F2 下个断点


  8. 按下 F9,让程序跑起来,程序没有闪退,说明没有在 .init_array 做反调试检测
  9. 接下来单步一步步往下走,看看是哪里让程序退出的。在单步往下走的过程中,最好在每个跳转指令的地方下个断点,防止程序退出以后又要重新定位退出点
  10. 试了几次之后,发现跑到 BLX R7 的时候,R7 存放是地址是 pthread_create 的地址,进一步分析发现,这里新建线程的目的就是循环检测程序是否在被调试

  11. 记下这行指令的地址,再减去 libcrackme.so 的起始地址,在 WinHex 中定位到该语句,将这部分十六进制的字节码修改为 NOP,即 00 F0 20 E3,然后保存修改、重新打包 APK 并签名,再安装到手机上运行
  12. APP 成功运行后,用 IDA 附加到该进程上
  13. 在静态的 libcrackme.so 中定位到 Java_com_yaotong_crackme_MainActivity_securityCheck 的地址,加上 libcrackme.so 的起始地址就得到了该函数在进程中的地址


  14. 随便输入一个注册码,然后运行程序,在 IDA 中跳转到
    Java_com_yaotong_crackme_MainActivity_securityCheck,进行单步步过


  15. 运行到下图时

    发现,程序出现了分支,在 R1 和 R3 不相等的时候,执行 MOV R1, #0,然后接着执行 MOV R0, R1,这就说明把返回值(R0)置成了 false。此时 R1 和 R3 一个存放的是我们的输入的第一个字符的 ASCII 码,另一个存放的就是正确的注册码的字符的 ASCII 码。而 R1 和 R3 是通过 LDRB R3, [R2]LDRB R1, [R0] 赋值的,查看 R0 和 R2,刚好一个是输入,一个是正确的注册码,如下:

最后推荐一个ARM 转机器码的网站

参考文档:
深入理解 JNI
IDA 调试 Android native(Crackme)
Android 逆向之动态调试总结
Android AM 命令及使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容