Przechwytywanie wpisów GOT

https://chacker.pl/

Obie omówione do tej pory techniki – modyfikacja punktu wejścia i przechwytywanie konstruktora/destruktora – pozwalają na jednorazowe uruchomienie wstrzykniętego kodu podczas uruchamiania lub zamykania pliku binarnego. Co zrobić, jeśli chcesz wielokrotnie wywoływać wstrzykniętą funkcję, na przykład w celu zastąpienia istniejącej funkcji bibliotecznej? Pokażę teraz, jak przechwycić wpis GOT, aby zastąpić wywołanie biblioteki wstrzykniętą funkcją. Przypomnijmy , że Global Offset Table (GOT) to tabela zawierająca wskaźniki do współdzielonych funkcji bibliotecznych, używanych do dynamicznego linkowania. Nadpisanie jednego lub więcej z tych wpisów daje zasadniczo taki sam poziom kontroli, jak technika LD_PRELOAD, ale bez potrzeby zewnętrznej biblioteki zawierającej nową funkcję, co pozwala zachować integralność pliku binarnego. Co więcej, przechwytywanie GOT to odpowiednia technika nie tylko do trwałej modyfikacji pliku binarnego, ale także do wykorzystywania pliku binarnego w czasie wykonywania. Technika przejęcia kontroli nad GOT wymaga niewielkiej modyfikacji wstrzykiwanego kodu, jak pokazano na Listingu

Listing : hello-got.s

BITS 64

SECTION .text

global main

main:

push rax ; save all clobbered registers

push rcx ; (rcx and r11 destroyed by kernel)

push rdx

push rsi

push rdi

push r11

mov rax,1 ; sys_write

mov rdi,1 ; stdout

lea rsi,[rel $+hello-$] ; hello

mov rdx,[rel $+len-$] ; len

syscall

pop r11

pop rdi

pop rsi

pop rdx

pop rcx

pop rax

(1) ret ; return

hello: db „hello world”,33,10

len : dd 13

W przypadku przejęcia GOT następuje całkowita zamiana funkcji bibliotecznej, więc nie ma potrzeby przekazywania kontroli z powrotem do oryginalnej implementacji po zakończeniu wstrzykiwanego kodu. Zatem Listing 7-17 nie zawiera żadnego zakodowanego na stałe adresu, na który przekazywane jest sterowanie na końcu. Zamiast tego kończy się po prostu normalnym zwrotem (1). Przyjrzyjmy się, jak zaimplementować technikę przejęcia GOT w praktyce. Listing 18 przedstawia przykład, w którym wpis GOT dla funkcji bibliotecznej fwrite_unlocked w pliku binarnym ls jest zastępowany wskaźnikiem do funkcji „hello world”, jak pokazano na Listingu wcześniejszym. Funkcja fwrite_unlocked to funkcja, której ls używa do wyświetlania wszystkich swoich komunikatów na ekranie.

Listing : Calling injected code by hijacking a GOT entry

(1) $ cp /bin/ls ls.got

(2)$ ./elfinject ls.got hello-got.bin „.injected” 0x800000 -1

$ objdump -M intel -d ls.got

(3) 0000000000402800 <fwrite_unlocked@plt>:

402800: ff 25 9a ba 21 00 jmp QWORD PTR [rip+0x21ba9a] # (4)61e2a0 <_fini@@Base+0x20a644>

402806: 68 51 00 00 00 push 0x51

40280b: e9 d0 fa ff ff jmp 4022e0 <_init@@Base+0x28>

$ objdump ls.got -s –section=.got.plt

ls.got: file format elf64-x86-64

Contents of section .got.plt:

61e290 e6274000 00000000 f6274000 00000000 .’@……’@…..

61e2a0 (5)06284000 00000000 16284000 00000000 .(@……(@…..

61e2b0 26284000 00000000 36284000 00000000 &(@…..6(@…..

(6) $ hexedit ls.got

$ objdump ls.got -s –section=.got.plt

ls.got: file format elf64-x86-64

Contents of section .got.plt:

61e290 e6274000 00000000 f6274000 00000000 .’@……’@…..

61e2a0 (7)780e8000 00000000 16284000 00000000 x……..(@…..

61e2b0 26284000 00000000 36284000 00000000 &(@…..6(@…..

(8) $ ./ls.got

hello world!

hello world!

hello world!

hello world!

hello world!

Po utworzeniu nowej kopii ls (1) i wstrzyknięciu do niej swojego kodu (2), możesz użyć objdump do wyświetlenia wpisów PLT pliku binarnego (gdzie używane są wpisy GOT) i znaleźć wpis dla fwrite_unlocked (3). Zaczyna się on pod adresem 0x402800, a używany przez niego wpis GOT znajduje się pod adresem 0x61e2a0 (4), czyli w sekcji .got.plt. Używając objdump do wyświetlenia sekcji .got.plt, możesz zobaczyć oryginalny adres zapisany we wpisie GOT (5): 402806 (zakodowany w formacie little-endian). Jak wyjaśniono w rozdziale 2, jest to adres następnej instrukcji we wpisie PLT fwrite_unlocked, którą chcesz nadpisać adresem wstrzykniętego kodu. Następnym krokiem jest uruchomienie hexeditu, wyszukanie ciągu 062840 i zastąpienie go adresem 0x800e78 wstrzykniętego kodu (6), jak zwykle. Zmiany potwierdza się, ponownie używając objdump, aby wyświetlić zmodyfikowany wpis GOT (7). Po zmianie wpisu GOT tak, aby wskazywał na funkcję „hello world”,

program ls wyświetla teraz „hello world” za każdym razem, gdy wywołuje fwrite_unlocked (8), zastępując wszystkie standardowe dane wyjściowe ls kopiami ciągu „hello world”. Oczywiście w rzeczywistości warto zastąpić fwrite_unlocked bardziej użyteczną funkcją. Zaletą przechwytywania GOT jest to, że jest ono nie tylko proste, ale można je również łatwo wykonać w czasie wykonywania. Dzieje się tak, ponieważ, w przeciwieństwie do sekcji kodu, plik .got.plt jest zapisywalny w czasie wykonywania. W rezultacie przejęcie kontroli nad GOT stało się popularną techniką nie tylko w przypadku statycznych modyfikacji plików binarnych, jak pokazałem tutaj, ale także w przypadku ataków mających na celu zmianę zachowania uruchomionego procesu.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *