在共享库上设置断点

逆向工程 艾达 数据库 安卓 手臂
2021-06-18 22:23:50

我是倒车世界的菜鸟。我有一个通过 JNI 使用共享库的 Android Java 应用程序,我想在共享库中设置一个断点。共享库被剥离,据我所知,我只能按地址设置断点。我已经通过 IDA 放置了共享对象,并且有几个我想设置断点的位置,但我不确定如何计算这个或者即使这是可能的。我在 Android 上使用 gdbserver 连接到进程并使用 NDK 中的 gdb 从 Mac OSX 连接。我一直试图通过获取 /proc/'pid'/smap 给我的内容并计算我拥有的 IDA 程序集的偏移量来计算内存地址。这是正确的方向吗?这甚至可能吗?

1个回答

我最近一直在做同样/类似的事情,虽然你可以让它工作,但并不是那么容易。

如果你有一个有 root 权限的 android 设备,一个运行 gdbserver 的终端模拟器,并且如果可能的话,一个可以打开多个窗口的终端模拟器,它会有所帮助,所以如果 gdbserver 挂了,你可以从第二个窗口杀死 gdbserver。此外,Android 设备上的真正键盘会有所帮助,因为当您拥有真正的光标键时,重复命令会容易得多。

您无需使用 USB 数据线将 Droid 连接到 Mac。我像这样启动了 gdbserver:

gdbserver --attach 0.0.0.0:8765 2338

(其中 2338 是我的目标应用程序的 pid),然后使用

$ arm-none-eabi-gdb
target remote 192.168.178.103:8765

连接。192.168.178.103 是我的安卓设备的 IP 地址。

我不想在我的机器上安装完整的 NDK,所以我从https://launchpad.net/gcc-arm-embedded/+download下载了 ARM GDB ,它们有 windows、linux 和 mac 版本。当然,NDK GDB 也应该可以正常工作。

您可以将函数的“IDA 地址”添加到 Map 地址中。例如,在我的图书馆中:

  • 我感兴趣的两个函数具有“IDA 地址”BA584 和 BA99C。
  • /proc/maps 中的地址表示 688D0000 作为可执行段的基地址。
  • 真正的函数地址是6898A584/6898A99C,两种情况下都是基地址+“IDA地址”。

当您检查是否确实找到了正确的地址时,需要考虑两件事:

  • 您不能使用 gdb disassemble 命令,因为它依赖于函数和符号。使用 x/i 命令进行反汇编。例如,在我的例子中,x/20i 0x6898A584 来查看这个地址的 20 条指令。

  • 手臂有两种不同的模式,拇指模式和手臂模式。如果 gdb 没有符号,反汇编时可能会选择错误的符号,使您的 GDB 反汇编与 IDA 反汇编完全不同。

使用set arm force-mode armset arm force-mode thumb尝试两者。例如,这是 IDA 告诉我的有关我的 BA584 函数的内容:

.text:000BA584
.text:000BA584 sub_BA584                               ; CODE XREF: sub_BF1C4+3Ap
...
.text:000BA584                 PUSH.W          {R4-R11,LR}
.text:000BA588                 MOV             R6, R0
.text:000BA58A                 SUB             SP, SP, #0x1C
.text:000BA58C                 LDR             R0, [R0,#0x18]
.text:000BA58E                 MOV             R4, R1
.text:000BA590                 STR             R2, [SP,#0x40+var_34]

这是 gdb 首先制作的:

(gdb) x/20i 0x6890F584
 0x6890f584:  svcmi   0x00f0e92d
 0x6890f588:  addlt   r4, r7, r6, lsl #12
 0x6890f58c:  strmi   r6, [r12], -r0, lsl #19
 0x6890f590:  stmdacs r0, {r0, r1, r9, r12, pc}
 0x6890f594:  bichi   pc, r10, r0
 0x6890f598:  mlapl   r12, r6, r8, pc ; <UNPREDICTABLE>
 0x6890f59c:                  ; <UNDEFINED> instruction: 0xf0402d00

然后

(gdb) set arm force-mode thumb
(gdb) x/20i 0x6890F584
 0x6890f584:  stmdb   sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
 0x6890f588:  mov     r6, r0
 0x6890f58a:  sub     sp, #28
 0x6890f58c:  ldr     r0, [r0, #24]
 0x6890f58e:  mov     r4, r1
 0x6890f590:  str     r2, [sp, #12]

因此,如果反汇编看起来很奇怪,请不要放弃,尝试强制拇指/手臂模式。

我的应用程序在调试时多次崩溃,这使得 gdbserver 与 gdb 失去同步,导致来自 gdb 的大量“忽略数据包错误”消息。在这些情况下,杀死 gdbserver(因此是第二个窗口)、重新启动应用程序并重新连接 gdb 似乎是唯一的补救措施。当您重新启动应用程序时,请确保您重新检查 /proc/..../maps 以获取 .so 基地址,它大部分时间保持不变,但有时会发生变化,尤其是在调用之间有一段时间时。你会注意到我在上面的例子中的地址(0x6890F584)与我之前告诉你的地址不匹配,这是因为在这个例子中,地图基地址已更改为 68855000。