如何将一些代码永久注入 ARM .so 文件?

逆向工程 手臂 注射
2021-07-03 15:13:25

我想弄清楚如何解决以下问题。我有两个具有相同功能的 ARM .SO 库(32 位和 64 位)。有一个返回 const char* 的方法,它在 ARM32 中看起来像这样:

.text:0006F264                 PUSH            {LR}
.text:0006F266                 SUB             SP, SP, #0xC
.text:0006F268                 STR             R0, [SP,#0x10+var_C]
.text:0006F26A                 LDR             R3, =(dword_9A030 - 0x6F270)
.text:0006F26C                 ADD             R3, PC  ; dword_9A030
.text:0006F26E                 LDR.W           R3, [R3,#(dword_9A250 - 0x9A030)]
.text:0006F272                 LDR             R0, [SP,#0x10+var_C]
.text:0006F274                 BLX             R3
.text:0006F276                 MOV             R3, R0
.text:0006F278                 NOP
.text:0006F27A                 MOV             R0, R3
.text:0006F27C                 ADD             SP, SP, #0xC
.text:0006F27E                 LDR.W           PC, [SP+4+var_4],#4

在 ARM64 中:

.text:0000000000079CAC                 SUB             SP, SP, #0x20
.text:0000000000079CB0                 STR             X30, [SP,#0x20+var_20]
.text:0000000000079CB4                 STR             X0, [SP,#0x20+var_8]
.text:0000000000079CB8                 ADRP            X0, #dword_DE080@PAGE
.text:0000000000079CBC                 ADD             X0, X0, #dword_DE080@PAGEOFF
.text:0000000000079CC0                 LDR             X1, [X0,#(qword_DE4C0 - 0xDE080)]
.text:0000000000079CC4                 LDR             X0, [SP,#0x20+var_8]
.text:0000000000079CC8                 BLR             X1
.text:0000000000079CCC                 NOP
.text:0000000000079CD0                 LDR             X30, [SP,#0x20+var_20]
.text:0000000000079CD4                 ADD             SP, SP, #0x20
.text:0000000000079CD8                 RET

这是一个函数的 ASM 代码

const char* GetStatus ( const DetailsHandle obj )

此函数可以返回 3 个字符串值之一“abcd”、“kowewqzb”或“jvbrnbfghert”(作为 char*)。我希望它始终返回“kowewqzb”,而不管此函数中发生的调用如何,这会导致一大堆动态加载的函数。那我怎么能:

1)编写代码使其始终返回“kowewqzb”的地址(需要先将其放入内存中的某个位置)并且不进行任何其他调用(因此基本上除了SP操作之外的整个指令集都可以替换为其他说明

2)如果没有足够的空间让它直接在那里工作,我怎么能在不破坏现有代码的情况下注入一些新代码,.SO库中有没有合适的地方呢?例如,将 BL 放在一些未使用的区域(如何获得它们?)并在那里放置更多的代码片段。

理想情况下,如果这可以针对 ARM32 和 ARM64 进行概述,我会非常高兴。提前致谢!!!

1个回答

据我了解,您想用代码替换该函数,以便它返回一个指向 ASCII 字符串“kowewqzb”的指针。

由于所讨论的函数很长,因此您有足够的空间为 ARM32 和 ARM64 编写内联补丁。

对于ARM32,您可以使用以下代码

.global main
.text
.thumb_func

main:
adr r0, str
bx lr

str:
.asciz "kowewqzb"

请注意,这是 16 位 Thumb 代码而不是 32 位 ARM,因为即使您发布的反汇编也使用 Thumb 指令。组装后,objdump这将产生

$ arm-linux-gnueabi-objdump -d arm32.o

arm32.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <main>:
   0:   a000        add r0, pc, #0  ; (adr r0, 4 <str>)
   2:   4770        bx  lr

00000004 <str>:
   4:   65776f6b    .word   0x65776f6b
   8:   627a7177    .word   0x627a7177

对于ARM64

.global main
.text    
main:
adr x0, str
ret

str:
.asciz "kowewqzb"

这产生

$ aarch64-linux-gnu-objdump -d aarch64.o

aarch64.o:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000000000 <main>:
   0:   10000040        adr     x0, 8 <str>
   4:   d65f03c0        ret

0000000000000008 <str>:
   8:   65776f6b        .word   0x65776f6b
   c:   627a7177        .word   0x627a7177

最后,一定要在末尾添加一个零字节,使其成为正确的以空字符结尾的 ASCII 字符串。


编辑:

正如下面评论中所说,您不需要编辑 .rodata或二进制文件中的任何其他部分。该字符串作为代码字节的一部分包含在您将要覆盖GetStatus函数的代码字节中

例如,对于 ARM 32,

main:
adr r0, str
bx lr

str:
.asciz "kowewqzb"

adr r0, str指令加载紧跟其后的字符串地址。adr指令实际上是一个伪指令并汇编为add r0, pc, #0. 它通过添加0到当前程序计数器 ( PC)计算字符串的地址在 ARM 中,thePC总是指向当前执行指令之前的两条指令。这就是我们添加的原因,0因为它str在执行adr r0, str指令已经指向

以这种方式获取字符串的地址称为PC相对寻址。这使得可以避免在修补代码中硬编码字符串的地址。

你可以使用这个在线arm汇编器来查看指令对应的字节。

在此处输入图片说明

您需要使用左侧面板上显示的字节覆盖该函数。无需其他修改。