A puzzle about hook arm function, by modify ELF file

我是研究僧i 提交于 2019-12-20 04:23:22

问题


I want to hook a function by modify elf file's .text binary, my mean is replace an instruction like 'bl xxxx' with 'bl yyyy', the 'yyyy' is point to an padding area in elf file. After jump, I save the registers and call dlopen&dlsym to get new function's addr of another lib, call it, then restore the registers and jump back to 'xxxx'.

It is not very hard, and I have almost successful except for a problem: I cannot use 64-bits var in my hook function. The int type is no problem, but when I printf int64_t var, it's always shows a wrong number.

1 This is the src code:
test_ori

// test_ori.c
#include <stdio.h>
#include <dlfcn.h>

// I will hook sub and jump to myfn
void sub() {
  printf("sub called...\n");
}

// The purpose of sub2 is just for let me know the addr of dlopen&dlsym
void (*func)();
void sub2() {
  void *p = dlopen("/system/lib/libyyy.so", RTLD_NOW);
  func = (void (*)())dlsym(p,"myfn2");
  func();
}

int main(){
  sub();
  sub2();
  return 0;
}

libyyy.so

// yyy.c
#include <stdio.h>

void myfn() {
  int x = 1;
  uint32_t y = 2;
  uint64_t z = 3;
  printf("x=%d, y=%u, z=%llu\n", x, y, z);
}

void myfn2() {}


2 Use objump to found the addrs of dlopen&dlsym

// dlopen is 0x8440, dlsym is 0x844c
84a8:       f7ff efca       blx     8440 <dlopen@plt>
...
84b2:       f7ff efcc       blx     844c <dlsym@plt>

// sub is 0x84d4
84e0:       003c            movs    r4, r7
84e2:       0000            movs    r0, r0
84e4:       b510            push    {r4, lr}
84e6:       f7ff fff5       bl      84d4 <puts@plt+0x7c>
84ea:       f7ff ffd9       bl      84a0 <puts@plt+0x48>


3 Find padding area and modify elf file

// I use the offset 0x550(it's padding area) as my jump destination, the addr is 0x8550
// by the way, I also modify the segment's size field(0x580->0x600) so my new code can be loaded
ori  ->  84e6:       f7ff fff5       bl      84d4
new  ->  84e6:       f000 f833       bl      8550


4 The hook process from 0x8550, by asm:

1.  push {r0-r7}        //  save registers
2.  push {lr}           //  save lr
3.  mov  r1, #0         //  param2 of dlopen(RTLD_NOW)
4.  mov  r0, pc
5.  add  r0, #xx        //  param1 of dlopen(addr of "libyyy.so")
6.  blx  xxxx           //  call dlopen
7.  mov  r1, pc         
8.  add  r1, #xx        //  param2 of dlsym(addr of "myfn")
9.  blx  xxxx           //  call dlsym
10. blx  r0             //  call myfn
11. pop  {r3}           //  
12. mov  lr, r3         //  restore lr
13. pop  {r0-r7}        //  restore registers
14. b    xxxx           //  jump back


5 Modify elf file: write code to the padding area

// I convert the asm above to machine code and write it(and strings "libyyy.so" & "myfn") to file  
// then I check it in gdb:  
(gdb) x/20i 0x8550
   0x8550:      push    {r0, r1, r2, r3, r4, r5, r6, r7}
   0x8552:      push    {lr}
   0x8554:      movs    r1, #0
   0x8556:      mov     r0, pc
   0x8558:      adds    r0, #24
   0x855a:      blx     0x8440
   0x855e:      mov     r1, pc
   0x8560:      adds    r1, #26
   0x8562:      blx     0x844c
   0x8566:      blx     r0
   0x8568:      pop     {r3}
   0x856a:      mov     lr, r3
   0x856c:      pop     {r0, r1, r2, r3, r4, r5, r6, r7}
   0x856e:      b.w     0x84d4

6 The result

# ./test_new
x=1, y=2, z=12884901888
sub called...


As you see, the x and y is normal, but z(uint64_t) is wrong. It shoule be 3, but I get 12884901888(0x300000000) here. It seems the high/low register for z is incorrect, but can you tell me why and how to fix it? Thanks for your attention!


回答1:


The answer to this question is in the ARM Procedure call standard.

 printf("x=%d, y=%u, z=%llu\n", x, y, z);

This has four arguments. The format string, the 32bit x and y and the 3rdz value. As the first three arguments land z at an odd address, the compiler pads a space so that ldrd and strd instruction can work; these 64-bit loads do not work if the stack is not aligned.

It is not clear whether you are showing assembler for the C code you compiled or if you are trying to modify the generated code. Most likely you do not ensure that the stack is eight byte aligned as var args must be put on the stack.

Ps: There is a good stack-overflow question about ARM 8-byte alignment, but I can not find it now. Feel free to edit my question or leave a comment.



来源:https://stackoverflow.com/questions/18000149/a-puzzle-about-hook-arm-function-by-modify-elf-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!