Rozważmy następujący podatny kodu/program:Wykorzystanie przepełnienie ciąg oparte na x86-64 z NX (DEP) oraz ASLR włączona
#include <string.h>
int main(int argc, char *argv[]) {
char buf[16];
strcpy(buf, argv[1]);
return 0;
}
Na IA-32 (x86, 32-bit) z systemem Linux NX ASLR przyczyniłoby się to, że za pomocą wykorzystania GOT nadpisywanie techniki, który zasadniczo obejmuje następujące etapy:
- przepełnienie bufora aż ODP
- nadpisywania rip adres
[email protected]
- Użyj czystego gadżetu z
.text
, np.pop edi ; pop ebp ; ret
, jako adres zwrotnystrcpy
- argumentów pisać dla
strcpy
:&bss
-address jako cel i jeden bajt/bin/sh
wykorzystaniem.text
- powtórz kroki 2-4 aż
/bin/sh
jest całkowicie zapisywane&bss
- nadpisywania GOT wjazdu od
strcpy
zsystem
(używając przesunięcia, wymaga wiedzy na temat używanej wersji Libc - zignorujmy to tutaj) - Napisz
[email protected]
na stosie, a następnie jakiś 4-bajtowy fragment i wreszcie adres&bss
whi ch wskazuje/bin/sh
- Profit
chcę wykorzystać to na x86-64 z tych samych środków łagodzących włączone. Ale jest to trudniejsze, niż to sobie wyobrażaliśmy. Zasadniczo z następujących powodów:
- x86-64 rejestru opartego na konwencji wywołania: Argumenty funkcji są przekazywane za pomocą rejestrów, nie stos. Dlatego niektóre dodatkowe gadżety ROP są wymagane do przeniesienia argumentów ze stosu do odpowiedniego rejestru. Jest to niewielki problem, ale ma również wpływ następujący problem:
64-bitowy adres zwrotny: RIP w x86-64 wskazuje na
.text
, który nie ma nawet długości 32-bitów. Dlatego też NULL-bajty muszą być zapisane na stosie w celu wywołania funkcji łańcuchowych. Zasadniczo można zapisać tyle bajtów NULL, ile pożądane, przy użyciu przykutych wywołań dostrcpy
i korzystając z kończącego znaków NULL,strcpy
zawsze zapisuje. Ale można tylko raz wywołaćstrcpy
, tylko nadpisując najmniej znaczące bajty RIP-a.|0x00000000| (most significant bytes) |0x00deadbe| <- RIP (least significant bytes) |0x41414141| |0x41414141| <- SFP | ... |
Są to główne problemy dostałem z wykorzystanie programu na x86-64 z NX i ASLR włączona. Czy są jakieś techniki, które rozwiązują te problemy? Czy naprawdę x86-64 naprawdę uniemożliwia działanie, exploit otwierający powłoki?
Jeśli RIP ma oznaczać adres zwrotny, potrzebujesz nowej terminologii dla x86-64. Tak jak EAX jest rozszerzony do RAX, EIP (aktualny Wskaźnik Instrukcji) jest rozszerzony do RIP. Tak więc w x86-64, RIP jest nazwą rejestru i sam nie tworzy dobrej nazwy dla adresu zwrotnego, który odczyta RET. –