一、目标

一、目标

今天我们来给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; 的代码块,

jmp1
1:jmp1

所以把注意打在了

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 函数中的位置

rc
1:rc

先观察一下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汇编的基础教程。

100

关注微信公众号,最新技术干货实时推送

100