Układanka o funkcji ramienia haka, poprzez modyfikację pliku ELF

Chcę podłączyć funkcję przez modyfikację pliku binarnego pliku elfa, mój środek to zastąpienie instrukcji takiej jak „bl xxxx” przez „bl yyyy”, „yyyy” to wskazanie obszaru dopełnienia w pliku elf. Po przeskoczeniu zapisuję rejestry i wywołuję dlopen & dlsym, aby uzyskać addr nowej funkcji innego liba, wywołać go, a następnie przywrócić rejestry i wrócić do 'xxxx'.

Nie jest to bardzo trudne i prawie udało mi się, z wyjątkiem problemu: nie mogę użyć 64 bitów var w mojej funkcji haka. Typ int nie stanowi problemu, ale kiedy drukujęint64_t var, zawsze pokazuje zły numer.

1 To jest kod src:
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 Użyj objump, aby znaleźć dodatki dlopen i 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 Znajdź obszar wypełnienia i zmodyfikuj plik elfa

// 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 Proces przechwytywania od 0x8550, przez 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 Modyfikuj plik elfa: napisz kod do obszaru wypełnienia

// 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 Wynik

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


Jak widzisz, xiy są normalne, ale z (uint64_t) jest błędne. Musi być 3, ale dostaję12884901888 (0x300000000) tutaj. Wydaje się, że rejestr wysoki / niski dla z jest niepoprawny, ale czy możesz mi powiedzieć dlaczego i jak to naprawić? Dziękuję za uwagę!

questionAnswers(1)

yourAnswerToTheQuestion