一、目标
今天我们来给so文件打补丁,解决load失败的问题。在之前模拟执行的时候有一个报错 android/content/pm/ApplicationInfo→sourceDir:Ljava/lang/String; ,模拟执行的时候可以忽略这个错误,但是实际载入so的时候就不能忽略了。我们修改so来解决这个问题。
二、步骤
首先在IDA中定位
Shift+F12 打开ida的字符串窗口,然后搜索 sourceDir , 定位到了偏移 00002D72 ,我们要跳过执行 android/content/pm/ApplicationInfo→sourceDir:Ljava/lang/String; 的代码块,
所以把注意打在了
00002D08 40 F0 40 81 BNE.W loc_2F8C
BNE是数据跳转指令,只有当标志寄存器Z不等于0的时候才跳转, 这里我们把它改成
00002D08 40 E1 B loc_2F8C
B是强制跳转指令,这样就跳过了 sourceDir 所在的代码块。
00002F8C 6F F0 02 00 MOV R0, #0xFFFFFFFD
强制跳转到 00002F8C 之后我们发现这里把函数返回值 R0 的值置为了 -3。 说明函数返回可能是失败的,这样不行,得改成成功 1 。
00002F8C 4F F0 01 00 MOV.W R0, #1
好了,这个函数就处理ok了,我们可以F5看一眼,sourceDir 部分的代码已经不会执行了,在它之前函数直接就返回 1 了。
处理JNI_OnLoad
我们在 00002AF8 这个函数上按 X键,回到它在 JNI_OnLoad 函数中的位置
先观察一下JNI_OnLoad函数最后退出的代码块在 loc_382A, 这里把R5的值赋给了返回值R0。所以我们要在调用完00002AF8函数之后,把寄存器R5赋值为 #0x10004 (JNI_VERSION_1_4)
修改前的代码为
000037C8 FF F7 96 F9 BL check_status
000037CC 80 46 MOV R8, R0
000037CE 00 28 CMP R0, #0
000037D0 67 D1 BNE loc_38A2
修改之后的代码为
000037C8 FF F7 96 F9 BL check_status
000037CC 04 25 C0 F2 01 05 MOVS R5, #0x10004
000037D2 2A E0 B loc_382A;
这样处理之后,就跳过了 sourceDir 部分报错的代码。
最后保存我们修改的结果 Edit→Patch program → Apply patches to input file
三、总结
在模拟执行的帮助下,我们准确的找到了Patch的位置和方法,如果你看的一脸懵逼或者一看汇编代码就头痛,也不用着急。Arm汇编是必须要掌握的,不过掌握点基础也够用了,后面我们会出一系列Arm汇编的基础教程。
关注微信公众号,最新技术干货实时推送