mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-16 22:18:27 +00:00
Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc
This commit is contained in:
parent
7c883ca7ce
commit
dcf5bf8839
4 changed files with 326 additions and 293 deletions
|
@ -2,23 +2,23 @@
|
|||
|
||||
<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>
|
||||
<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ą na HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](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) albo **ś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>
|
||||
|
||||
## **Hook Malloc**
|
||||
## **Malloc Hook**
|
||||
|
||||
Jak można przeczytać na [Oficjalnej stronie 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**.
|
||||
Jak można przeczytać na [Oficjalnej stronie 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()` **zapisane 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 powoduje, że `libc` wywołuje malloc, aby je zaalokować na stercie.
|
||||
Aby wywołać malloc, można poczekać, aż program go wywoła, lub **wywołać `printf("%10000$c")`**, co alokuje zbyt wiele bajtów, co powoduje, że `libc` wywołuje malloc, aby je zaalokować na stercie.
|
||||
|
||||
Więcej informacji na temat One Gadget znajdziesz w:
|
||||
|
||||
|
@ -30,55 +30,66 @@ Więcej informacji na temat One Gadget znajdziesz w:
|
|||
Zauważ, że haki są **wyłączone dla GLIBC >= 2.34**. Istnieją inne techniki, które można stosować w nowszych wersjach GLIBC. Zobacz: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
{% endhint %}
|
||||
|
||||
## Hook Free
|
||||
## Free Hook
|
||||
|
||||
To zostało wykorzystane w jednym z przykładów na stronie, nadużywając ataku na szybki blok po wcześniejszym nadużyciu ataku na nieuporządkowany blok:
|
||||
To zostało wykorzystane w jednym z przykładów na stronie, wykorzystując atak na szybki blok po wcześniejszym wykorzystaniu ataku na nieuporządkowany blok:
|
||||
|
||||
{% content-ref url="../libc-heap/unsorted-bin-attack.md" %}
|
||||
[unsorted-bin-attack.md](../libc-heap/unsorted-bin-attack.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
Fajny trik (z [**tutaj**](https://guyinatuxedo.github.io/41-house\_of\_force/bkp16\_cookbook/index.html)), aby znaleźć lokalizację hooka free, jeśli binarny plik ma symbole, to **zrób coś w stylu**:
|
||||
```
|
||||
gef➤ set __free_hook = 0xfacade
|
||||
gef➤ search-pattern 0xfacade
|
||||
```
|
||||
W tym samym poście znajdziesz przewodnik krok po kroku dotyczący lokalizacji adresu haka free bez symboli. Podsumowując, w funkcji free:
|
||||
|
||||
```armasm
|
||||
gef➤ x/20i free
|
||||
0xf75dedc0 <free>: push ebx
|
||||
0xf75dedc1 <free+1>: call 0xf768f625
|
||||
0xf75dedc6 <free+6>: add ebx,0x14323a
|
||||
0xf75dedcc <free+12>: sub esp,0x8
|
||||
0xf75dedcf <free+15>: mov eax,DWORD PTR [ebx-0x98]
|
||||
0xf75dedd5 <free+21>: mov ecx,DWORD PTR [esp+0x10]
|
||||
0xf75dedd9 <free+25>: mov eax,DWORD PTR [eax]
|
||||
0xf75deddb <free+27>: test eax,eax ;<--- PRZERWIJ TUTAJ
|
||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||
```
|
||||
|
||||
W wspomnianym miejscu przerwania w poprzednim kodzie w `$eax` będzie znajdować się adres haka free.
|
||||
|
||||
Teraz wykonywany jest **szybki atak na bin**:
|
||||
|
||||
- Po pierwsze odkryto, że możliwe jest pracowanie z szybkimi **kawałkami o rozmiarze 200** w lokalizacji **`__free_hook`**:
|
||||
- ```c
|
||||
Możliwe jest znalezienie adresu `__free_hook`, jeśli binarny plik ma symbole za pomocą następującej komendy:
|
||||
```bash
|
||||
gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
- Jeśli uda nam się uzyskać szybki kawałek o rozmiarze 0x200 w tej lokalizacji, będzie możliwe nadpisanie wskaźnika funkcji, która zostanie wykonana.
|
||||
- W tym celu tworzony jest nowy kawałek o rozmiarze `0xfc` i dwukrotnie wywoływana jest funkcja scalająca z tym wskaźnikiem, w ten sposób uzyskujemy wskaźnik do zwolnionego kawałka o rozmiarze `0xfc*2 = 0x1f8` w szybkim binie.
|
||||
- Następnie wywoływana jest funkcja edycji w tym kawałku, aby zmodyfikować adres **`fd`** tego szybkiego binu wskazujący na poprzednią funkcję **`__free_hook`**.
|
||||
- Następnie tworzony jest kawałek o rozmiarze `0x1f8`, aby pobrać z szybkiego binu poprzedni nieużyteczny kawałek, więc tworzony jest kolejny kawałek o rozmiarze `0x1f8`, aby uzyskać kawałek szybkiego binu w **`__free_hook`**, który zostaje nadpisany adresem funkcji **`system`**.
|
||||
- Na koniec zwalniany jest kawałek zawierający ciąg znaków `/bin/sh\x00`, wywołując funkcję usuwania, co powoduje wywołanie funkcji **`__free_hook`**, która wskazuje na system z parametrem `/bin/sh\x00`.
|
||||
[W poście](https://guyinatuxedo.github.io/41-house\_of\_force/bkp16\_cookbook/index.html) znajdziesz przewodnik krok po kroku dotyczący lokalizacji adresu haka free bez symboli. Podsumowując, w funkcji free:
|
||||
|
||||
## Referencje
|
||||
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
|
||||
0xf75dedc0 <free>: push ebx
|
||||
0xf75dedc1 <free+1>: call 0xf768f625
|
||||
0xf75dedc6 <free+6>: add ebx,0x14323a
|
||||
0xf75dedcc <free+12>: sub esp,0x8
|
||||
0xf75dedcf <free+15>: mov eax,DWORD PTR [ebx-0x98]
|
||||
0xf75dedd5 <free+21>: mov ecx,DWORD PTR [esp+0x10]
|
||||
<strong>0xf75dedd9 <free+25>: mov eax,DWORD PTR [eax]--- PRZERWIJ TUTAJ
|
||||
</strong>0xf75deddb <free+27>: test eax,eax ;<
|
||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||
</code></pre>
|
||||
|
||||
W wspomnianym miejscu przerwania w powyższym kodzie w `$eax` będzie znajdować się adres haka free.
|
||||
|
||||
Następnie wykonywany jest **szybki atak na bin**:
|
||||
|
||||
* Po pierwsze odkryto, że możliwe jest pracowanie z szybkimi **kawałkami o rozmiarze 200** w lokalizacji **`__free_hook`**:
|
||||
* <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
* Jeśli uda nam się uzyskać szybki kawałek o rozmiarze 0x200 w tej lokalizacji, będzie możliwe nadpisanie wskaźnika funkcji, która zostanie wykonana
|
||||
* W tym celu tworzony jest nowy kawałek o rozmiarze `0xfc` i dwukrotnie wywoływana jest funkcja scalająca z tym wskaźnikiem, w ten sposób uzyskujemy wskaźnik do zwolnionego kawałka o rozmiarze `0xfc*2 = 0x1f8` w szybkim binie.
|
||||
* Następnie wywoływana jest funkcja edycji w tym kawałku, aby zmodyfikować adres **`fd`** tego szybkiego binu wskazujący na poprzednią funkcję **`__free_hook`**.
|
||||
* Następnie tworzony jest kawałek o rozmiarze `0x1f8` w celu odzyskania z szybkiego binu poprzedniego nieużytecznego kawałka, więc tworzony jest kolejny kawałek o rozmiarze `0x1f8`, aby uzyskać kawałek szybkiego binu w **`__free_hook`**, który zostaje nadpisany adresem funkcji **`system`**.
|
||||
* Na koniec zwalniany jest kawałek zawierający ciąg znaków `/bin/sh\x00`, wywołując funkcję usuwania, co powoduje wywołanie funkcji **`__free_hook`**, która wskazuje na system z parametrem `/bin/sh\x00`.
|
||||
|
||||
## Odnośniki
|
||||
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
* [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
|
||||
<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)!
|
||||
* 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>
|
||||
|
|
|
@ -9,24 +9,24 @@ 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) albo **ś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**
|
||||
|
||||
### **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 zewnętrznych symboli** 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 używają 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 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 adresu jest on 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 jest przekazywana 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 zewnętrznej lub zmiennej jest rozwiązany. **Wpisy PLT są używane do ułatwienia początkowego rozwiązania** tych adresów za pomocą dynamicznego łącznika.
|
||||
**Dlatego** wpisy GOT są używane bezpośrednio, gdy adres funkcji zewnętrznej lub zmiennej jest rozwiązany. **Wpisy PLT są używane do ułatwienia początkowego rozwiązania** tych adresów za pomocą łącznika dynamicznego.
|
||||
|
||||
## Uzyskanie wykonania
|
||||
|
||||
|
@ -36,11 +36,11 @@ Uzyskaj adres tabeli GOT za pomocą: **`objdump -s -j .got ./exec`**
|
|||
|
||||
![](<../../.gitbook/assets/image (121).png>)
|
||||
|
||||
Zauważ, jak po **załadowaniu** **wykonywalnego** pliku w GEF możesz **zobaczyć** **funkcje**, które znajdują się w **GOT**: `gef➤ x/20x 0xDIR_GOT`
|
||||
Zauważ, jak po **załadowaniu** **wykonywalnego** pliku w GEF możesz **zobaczyć** **funkcje**, które znajdują się w **GOT**: `gef➤ x/20x 0xADDR_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) (2) (2) (2).png>)
|
||||
|
||||
Korzystając z GEF, możesz **rozpocząć** sesję **debugowania** i wykonać **`got`** aby zobaczyć tabelę got:
|
||||
Za pomocą GEF możesz **rozpocząć** sesję **debugowania** i wykonać **`got`** aby zobaczyć tabelę got:
|
||||
|
||||
![](<../../.gitbook/assets/image (496).png>)
|
||||
|
||||
|
@ -48,9 +48,9 @@ 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 dowolnego 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 przekazywane do funkcji system).
|
||||
|
||||
Jeśli **`system`** **nie jest używany** przez skrypt, funkcja systemowa **nie** będzie miała wpisu w PLT. W tym 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 binarny, 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`**
|
||||
|
||||
|
@ -64,7 +64,13 @@ Znajdź [**więcej informacji na temat tej techniki tutaj**](https://github.com/
|
|||
|
||||
## **Free2system**
|
||||
|
||||
W wyzwalaczach eksploatacji sterty często można kontrolować zawartość fragmentów i w pewnym momencie nawet nadpisać tabelę GOT. Prostym trikiem, aby uzyskać RCE, jeśli nie są dostępne żadne gadżety, jest nadpisanie adresu `free` w GOT, aby wskazywał na `system` i zapisanie w fragmencie `"/bin/sh"`. W ten sposób, gdy ten fragment zostanie zwolniony, zostanie wykonane `system("/bin/sh")`.
|
||||
W wyzwaleniach eksploatacji sterty jest często możliwe kontrolowanie zawartości fragmentów i w pewnym momencie nawet nadpisanie tabeli GOT. Prostym trikiem, aby uzyskać RCE, jeśli nie są dostępne żadne gadżety, jest nadpisanie adresu GOT `free`, aby wskazywał na `system` i zapisanie w fragmencie `"/bin/sh"`. W ten sposób, gdy ten fragment zostanie zwolniony, zostanie wykonane `system("/bin/sh")`.
|
||||
|
||||
## **Strlen2system**
|
||||
|
||||
Inną powszechną techniką jest nadpisanie adresu **`strlen`** GOT, aby wskazywał na **`system`**, więc jeśli ta funkcja jest wywoływana z wejściem użytkownika, można przekazać ciąg `"/bin/sh"` i uzyskać powłokę.
|
||||
|
||||
Co więcej, jeśli `puts` jest używane z wejściem użytkownika, można nadpisać adres GOT `puts`, aby wskazywał na `system` i przekazać ciąg `"/bin/sh"` w celu uzyskania powłoki, ponieważ **`puts` wywoła `strlen` z wejściem użytkownika**.
|
||||
|
||||
## **One Gadget**
|
||||
|
||||
|
@ -74,18 +80,18 @@ W wyzwalaczach eksploatacji sterty często można kontrolować zawartość fragm
|
|||
|
||||
## **Wykorzystywanie GOT z Heap**
|
||||
|
||||
Powszechnym sposobem uzyskania RCE z podatności na stercie jest nadużycie fastbin, aby można było dodać część tabeli GOT do fast bin, dzięki czemu przy każdym przydzieleniu tego fragmentu będzie możliwe **nadpisanie wskaźnika funkcji, zwykle `free`**.\
|
||||
Następnie, wskazując `free` na `system` i zwalniając fragment, w którym został zapisany `/bin/sh\x00`, zostanie wykonany shell.
|
||||
Powszechnym sposobem uzyskania RCE z podatności sterty jest nadużycie fastbin, aby można było dodać część tabeli GOT do fast bin, dzięki czemu za każdym razem, gdy ten fragment jest alokowany, będzie możliwe **nadpisanie wskaźnika funkcji, zwykle `free`**.\
|
||||
Następnie wskazując `free` na `system` i zwalniając fragment, w którym został zapisany `/bin/sh\x00`, zostanie wykonana powłoka.
|
||||
|
||||
Można znaleźć [**przykład tutaj**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk\_extend\_overlapping/#hitcon-trainging-lab13)**.**
|
||||
Możliwe jest znalezienie [**przykładu tutaj**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk\_extend\_overlapping/#hitcon-trainging-lab13)**.**
|
||||
## **Ochrona**
|
||||
|
||||
## **Zabezpieczenia**
|
||||
|
||||
Ochrona **Full RELRO** 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:
|
||||
Ochrona **Full RELRO** 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:
|
||||
|
||||
{% content-ref url="../common-binary-protections-and-bypasses/relro.md" %}
|
||||
[relro.md](../common-binary-protections-and-bypasses/relro.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Odnośniki
|
||||
|
||||
* [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)
|
||||
|
@ -93,14 +99,14 @@ Ochrona **Full RELRO** ma na celu ochronę przed tego rodzaju techniką, rozwią
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>Zacznij od zera i zostań mistrzem 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>
|
||||
<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)!
|
||||
* Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* 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.
|
||||
* **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>
|
||||
|
|
|
@ -7,7 +7,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)!
|
||||
* Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* 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.
|
||||
|
@ -20,15 +20,15 @@ Inne sposoby wsparcia HackTricks:
|
|||
Obecnie jest bardzo **dziwne znalezienie binarnego pliku z sekcją .dtors!**
|
||||
{% endhint %}
|
||||
|
||||
Destruktory to funkcje, które są **wykonywane przed zakończeniem programu** (po zakończeniu działania funkcji `main`).\
|
||||
Adresy tych funkcji są przechowywane wewnątrz sekcji **`.dtors`** binarnego pliku, dlatego jeśli uda ci się **zapisać** **adres** do **shellcode** w **`__DTOR_END__`**, to zostanie **wykonany** przed zakończeniem programu.
|
||||
Destruktory to funkcje, które są **wykonywane przed zakończeniem programu** (po zwróceniu funkcji `main`).\
|
||||
Adresy tych funkcji są przechowywane w sekcji **`.dtors`** binarnego pliku, dlatego jeśli uda ci się **zapisać** **adres** do **shellcode** w **`__DTOR_END__`**, to zostanie **wykonany** przed zakończeniem programu.
|
||||
|
||||
Pobierz adres tej sekcji za pomocą:
|
||||
```bash
|
||||
objdump -s -j .dtors /exec
|
||||
rabin -s /exec | grep “__DTOR”
|
||||
```
|
||||
Zazwyczaj znajdziesz znaczniki **DTOR** **pomiędzy** wartościami `ffffffff` i `00000000`. Jeśli widzisz tylko te wartości, oznacza to, że **nie ma zarejestrowanej żadnej funkcji**. Nadpisz **`00000000`** adresem **shellcode**, aby go uruchomić.
|
||||
Zazwyczaj znajdziesz znaczniki **DTOR** **pomiędzy** wartościami `ffffffff` i `00000000`. Jeśli zobaczysz tylko te wartości, oznacza to, że **nie ma zarejestrowanej żadnej funkcji**. Następnie **nadpisz** **`00000000`** adresem **shellcode**, aby go uruchomić.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Oczywiście najpierw musisz znaleźć **miejsce do przechowywania shellcode**, aby później móc go wywołać.
|
||||
|
@ -36,7 +36,7 @@ Oczywiście najpierw musisz znaleźć **miejsce do przechowywania shellcode**, a
|
|||
|
||||
## **.fini\_array**
|
||||
|
||||
W zasadzie jest to struktura zawierająca **funkcje, które zostaną wywołane** przed zakończeniem programu, podobnie jak **`.dtors`**. Jest to interesujące, jeśli możesz wywołać swój **shellcode, skacząc do adresu**, lub w przypadkach, gdy musisz wrócić do `main` ponownie, aby **wykorzystać podatność po raz drugi**.
|
||||
W zasadzie jest to struktura zawierająca **funkcje, które zostaną wywołane** przed zakończeniem programu, podobnie jak **`.dtors`**. Jest to interesujące, jeśli możesz wywołać swoją **shellcode, skacząc do adresu**, lub w przypadkach, gdy musisz wrócić **do `main`**, aby **wykorzystać podatność po raz drugi**.
|
||||
```bash
|
||||
objdump -s -j .fini_array ./greeting
|
||||
|
||||
|
@ -49,226 +49,32 @@ Contents of section .fini_array:
|
|||
```
|
||||
Zauważ, że gdy funkcja z **`.fini_array`** jest wywoływana, przechodzi do następnej, więc nie będzie wykonywana wielokrotnie (zapobiegając wiecznym pętlom), ale również dostaniesz tylko 1 **wywołanie funkcji** umieszczonej tutaj.
|
||||
|
||||
Zauważ, że wpisy w `.fini_array` są wywoływane w **odwrotnej** kolejności, więc prawdopodobnie chcesz zacząć pisanie od ostatniego.
|
||||
Zauważ, że wpisy w `.fini_array` są wywoływane w **odwrotnej** kolejności, dlatego prawdopodobnie chcesz zacząć pisać od ostatniego.
|
||||
|
||||
#### Wieczna pętla
|
||||
|
||||
Aby nadużyć **`.fini_array`** i uzyskać wieczną pętlę, możesz [**sprawdzić, co zostało tutaj zrobione**](https://guyinatuxedo.github.io/17-stack\_pivot/insomnihack18\_onewrite/index.html)**:** Jeśli masz co najmniej 2 wpisy w **`.fini_array`**, możesz:
|
||||
|
||||
* Użyj swojego pierwszego zapisu, aby **ponownie wywołać podatną funkcję do dowolnego zapisu**
|
||||
* Użyj swojego pierwszego zapisu, aby **ponownie wywołać podatną funkcję do arbitralnego zapisu**
|
||||
* Następnie oblicz adres powrotu na stosie przechowywany przez **`__libc_csu_fini`** (funkcja wywołująca wszystkie funkcje `.fini_array`) i umieść tam **adres `__libc_csu_fini`**
|
||||
* Spowoduje to, że **`__libc_csu_fini`** ponownie wywoła siebie, wykonując ponownie funkcje **`.fini_array`**, które ponownie wywołają podatną funkcję WWW 2 razy: raz dla **dowolnego zapisu** i jeszcze raz, aby ponownie nadpisać **adres powrotu `__libc_csu_fini`** na stosie, aby ponownie wywołać siebie.
|
||||
* Spowoduje to, że **`__libc_csu_fini`** ponownie wywoła sam siebie, wykonując ponownie funkcje **`.fini_array`**, które ponownie wywołają podatną funkcję WWW 2 razy: raz dla **arbitralnego zapisu** i jeszcze raz, aby ponownie nadpisać **adres powrotu `__libc_csu_fini`** na stosie, aby ponownie się wywołać.
|
||||
|
||||
{% hint style="danger" %}
|
||||
Zauważ, że przy [**pełnym RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** sekcja **`.fini_array`** jest ustawiona jako **tylko do odczytu**.
|
||||
Zauważ, że z [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** sekcja **`.fini_array`** jest ustawiona jako **tylko do odczytu**.
|
||||
W nowszych wersjach, nawet z [**Partial RELRO**], sekcja **`.fini_array`** jest również ustawiona jako **tylko do odczytu**.
|
||||
{% endhint %}
|
||||
|
||||
## link\_map
|
||||
|
||||
Jak wyjaśniono [**w tym poście**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure), jeśli program zakończy działanie za pomocą `return` lub `exit()`, zostanie uruchomiona funkcja `__run_exit_handlers()`, która wywoła zarejestrowane destruktory.
|
||||
<details>
|
||||
|
||||
{% hint style="danger" %}
|
||||
Jeśli program zakończy działanie za pomocą funkcji **`_exit()`**, zostanie wywołane wywołanie systemowe **`exit`** i obsługiwane nie będą wykonywane. Aby potwierdzić wykonanie `__run_exit_handlers()`, można ustawić punkt przerwania na to.
|
||||
{% endhint %}
|
||||
<summary><strong>Dowiedz się, jak 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>
|
||||
|
||||
Ważny kod to ([źródło](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
|
||||
```c
|
||||
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
|
||||
if (fini_array != NULL)
|
||||
{
|
||||
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
|
||||
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
|
||||
Inne sposoby wsparcia HackTricks:
|
||||
|
||||
while (sz-- > 0)
|
||||
((fini_t) array[sz]) ();
|
||||
}
|
||||
[...]
|
||||
* 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.
|
||||
|
||||
|
||||
|
||||
|
||||
// This is the d_un structure
|
||||
ptype l->l_info[DT_FINI_ARRAY]->d_un
|
||||
type = union {
|
||||
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
|
||||
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
|
||||
}
|
||||
```
|
||||
Zauważ, jak `map -> l_addr + fini_array -> d_un.d_ptr` jest używane do **obliczenia** pozycji **tablicy funkcji do wywołania**.
|
||||
|
||||
Istnieje **kilka opcji**:
|
||||
|
||||
* Nadpisz wartość `map->l_addr`, aby wskazywała na **fałszywy `fini_array`** z instrukcjami do wykonania arbitralnego kodu
|
||||
* Nadpisz wpisy `l_info[DT_FINI_ARRAY]` i `l_info[DT_FINI_ARRAYSZ]` (które są mniej więcej kolejne w pamięci), aby wskazywały na sfałszowaną strukturę `Elf64_Dyn`, która ponownie spowoduje, że **`array` wskazuje na obszar pamięci kontrolowany przez atakującego**.
|
||||
* [**Ten opis**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) nadpisuje `l_info[DT_FINI_ARRAY]` adresem kontrolowanej pamięci w `.bss`, zawierającą fałszywy `fini_array`. Ten fałszywy array zawiera **najpierw** [**adres one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md), który zostanie wykonany, a następnie **różnicę** między adresem tego **fałszywego arraya** a **wartością `map->l_addr`**, aby `*array` wskazywał na fałszywy array.
|
||||
* Zgodnie z głównym postem na temat tej techniki i [**tym opisem**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so pozostawia wskaźnik na stosie, który wskazuje na binarny `link_map` w ld.so. Dzięki arbitralnemu zapisowi możliwe jest nadpisanie go i spowodowanie, że wskazuje na fałszywy `fini_array` kontrolowany przez atakującego z adresem [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) na przykład.
|
||||
|
||||
Po poprzednim kodzie znajdziesz kolejny interesujący fragment kodu:
|
||||
```c
|
||||
/* Next try the old-style destructor. */
|
||||
ElfW(Dyn) *fini = map->l_info[DT_FINI];
|
||||
if (fini != NULL)
|
||||
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
|
||||
}
|
||||
```
|
||||
W tym przypadku możliwe byłoby nadpisanie wartości `map->l_info[DT_FINI]`, wskazującej na sfałszowaną strukturę `ElfW(Dyn)`. Znajdź [**więcej informacji tutaj**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure).
|
||||
|
||||
## Nadpisanie listy dtor\_list w pamięci TLS w **`__run_exit_handlers`**
|
||||
|
||||
Jak [**wyjaśniono tutaj**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite), jeśli program kończy działanie za pomocą `return` lub `exit()`, zostanie wykonana funkcja **`__run_exit_handlers()`**, która wywoła zarejestrowane funkcje destrukcyjne.
|
||||
|
||||
Kod z `_run_exit_handlers()`:
|
||||
```c
|
||||
/* Call all functions registered with `atexit' and `on_exit',
|
||||
in the reverse of the order in which they were registered
|
||||
perform stdio cleanup, and terminate program execution with STATUS. */
|
||||
void
|
||||
attribute_hidden
|
||||
__run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
bool run_list_atexit, bool run_dtors)
|
||||
{
|
||||
/* First, call the TLS destructors. */
|
||||
#ifndef SHARED
|
||||
if (&__call_tls_dtors != NULL)
|
||||
#endif
|
||||
if (run_dtors)
|
||||
__call_tls_dtors ();
|
||||
```
|
||||
Kod z **`__call_tls_dtors()`**:
|
||||
```c
|
||||
typedef void (*dtor_func) (void *);
|
||||
struct dtor_list //struct added
|
||||
{
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
};
|
||||
|
||||
[...]
|
||||
/* Call the destructors. This is called either when a thread returns from the
|
||||
initial function or when the process exits via the exit function. */
|
||||
void
|
||||
__call_tls_dtors (void)
|
||||
{
|
||||
while (tls_dtor_list) // parse the dtor_list chained structures
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
|
||||
dtor_func func = cur->func;
|
||||
PTR_DEMANGLE (func); // demangle the function ptr
|
||||
|
||||
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
|
||||
func (cur->obj);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
Dla każdej zarejestrowanej funkcji w **`tls_dtor_list`**, zostanie odszyfrowany wskaźnik z **`cur->func`** i zostanie ona wywołana z argumentem **`cur->obj`**.
|
||||
|
||||
Korzystając z funkcji **`tls`** z tego [**forka GEF**](https://github.com/bata24/gef), można zobaczyć, że **`dtor_list`** jest bardzo **blisko** **stack canary** i **cookie PTR\_MANGLE**. Dlatego, przy przepełnieniu go, możliwe byłoby **nadpisanie** **cookie** i **stack canary**.\
|
||||
Przy nadpisaniu cookie PTR\_MANGLE, możliwe byłoby **obejście funkcji `PTR_DEMANLE`**, ustawiając ją na 0x00, co oznacza, że **`xor`** użyty do uzyskania rzeczywistego adresu to po prostu skonfigurowany adres. Następnie, pisząc na **`dtor_list`**, możliwe jest **łańcuchowe wywoływanie kilku funkcji** z adresem funkcji i jej **argumentem.**
|
||||
|
||||
Na koniec zauważ, że przechowywany wskaźnik nie tylko będzie xorowany z cookie, ale także obracany o 17 bitów:
|
||||
```armasm
|
||||
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
|
||||
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
|
||||
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
|
||||
```
|
||||
Należy wziąć to pod uwagę przed dodaniem nowego adresu.
|
||||
|
||||
Znajdź przykład w [**oryginalnym poście**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite).
|
||||
|
||||
## Inne zmodyfikowane wskaźniki w **`__run_exit_handlers`**
|
||||
|
||||
Ta technika jest [**wyjaśniona tutaj**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite) i ponownie zależy od programu **zakończającego działanie za pomocą `return` lub `exit()`**, aby zostało wywołane **`__run_exit_handlers()`**.
|
||||
|
||||
Sprawdźmy więcej kodu tej funkcji:
|
||||
```c
|
||||
while (true)
|
||||
{
|
||||
struct exit_function_list *cur;
|
||||
|
||||
restart:
|
||||
cur = *listp;
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
/* Exit processing complete. We will not allow any more
|
||||
atexit/on_exit registrations. */
|
||||
__exit_funcs_done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (cur->idx > 0)
|
||||
{
|
||||
struct exit_function *const f = &cur->fns[--cur->idx];
|
||||
const uint64_t new_exitfn_called = __new_exitfn_called;
|
||||
|
||||
switch (f->flavor)
|
||||
{
|
||||
void (*atfct) (void);
|
||||
void (*onfct) (int status, void *arg);
|
||||
void (*cxafct) (void *arg, int status);
|
||||
void *arg;
|
||||
|
||||
case ef_free:
|
||||
case ef_us:
|
||||
break;
|
||||
case ef_on:
|
||||
onfct = f->func.on.fn;
|
||||
arg = f->func.on.arg;
|
||||
PTR_DEMANGLE (onfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
onfct (status, arg);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_at:
|
||||
atfct = f->func.at;
|
||||
PTR_DEMANGLE (atfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
atfct ();
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_cxa:
|
||||
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
|
||||
we must mark this function as ef_free. */
|
||||
f->flavor = ef_free;
|
||||
cxafct = f->func.cxa.fn;
|
||||
arg = f->func.cxa.arg;
|
||||
PTR_DEMANGLE (cxafct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
cxafct (arg, status);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
goto restart;
|
||||
}
|
||||
|
||||
*listp = cur->next;
|
||||
if (*listp != NULL)
|
||||
/* Don't free the last element in the chain, this is the statically
|
||||
allocate element. */
|
||||
free (cur);
|
||||
}
|
||||
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
```
|
||||
Zmienna `f` wskazuje na strukturę **`initial`** i w zależności od wartości `f->flavor` zostaną wywołane różne funkcje.\
|
||||
W zależności od wartości, adres funkcji do wywołania będzie w innym miejscu, ale zawsze będzie **rozwiązany**.
|
||||
|
||||
Co więcej, w opcjach **`ef_on`** i **`ef_cxa`** można również kontrolować **argument**.
|
||||
|
||||
Możliwe jest sprawdzenie struktury **`initial`** w sesji debugowania z uruchomionym GEF za pomocą **`gef> p initial`**.
|
||||
|
||||
Aby to wykorzystać, należy albo **ujawnić lub usunąć ciasteczko `PTR_MANGLE`** a następnie nadpisać wpis `cxa` w initial wartością `system('/bin/sh')`.\
|
||||
Przykład tego można znaleźć w [**oryginalnym wpisie na blogu dotyczącym tej techniki**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
|
||||
</details>
|
||||
|
|
|
@ -1,31 +1,241 @@
|
|||
# WWW2Exec - atexit()
|
||||
# WWW2Exec - atexit(), Przechowywanie TLS i inne zniekształcone wskaźniki
|
||||
|
||||
<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>
|
||||
<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)!
|
||||
* 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ów**](https://opensea.io/collection/the-peass-family)
|
||||
* 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.
|
||||
* **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>
|
||||
|
||||
## **\_\_Struktury atexit()**
|
||||
## **Struktury \_\_atexit**
|
||||
|
||||
{% hint style="danger" %}
|
||||
Obecnie jest bardzo **dziwne, aby to wykorzystać!**
|
||||
{% endhint %}
|
||||
|
||||
**`atexit()`** to funkcja, do której **inne funkcje są przekazywane jako parametry.** Te **funkcje** zostaną **wykonane** podczas wykonywania **`exit()`** lub **powrotu** z **main**.\
|
||||
**`atexit()`** to funkcja, do której **przekazywane są inne funkcje jako parametry.** Te **funkcje** zostaną **wykonane** podczas wykonywania **`exit()`** lub **powrotu** z **main**.\
|
||||
Jeśli możesz **zmodyfikować** **adres** którejkolwiek z tych **funkcji**, aby wskazywał na shellcode na przykład, zdobędziesz 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 są adresami funkcji, ale są **zaszyfrowane za pomocą 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 wejście. Dlatego te architektury mogą być podatne na ten wektor ataku.
|
||||
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**. Obecnie ten wektor ataku **nie jest zbyt 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 na wejściu. Dlatego te architektury mogą być podatne na ten wektor ataku.
|
||||
|
||||
Możesz znaleźć dogłębne wyjaśnienie, jak to działa na [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
|
||||
Możesz znaleźć dogłębne wyjaśnienie, jak to działa pod adresem [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
|
||||
|
||||
## link\_map
|
||||
|
||||
Jak wyjaśniono [**w tym poście**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure), jeśli program kończy działanie za pomocą `return` lub `exit()`, zostanie uruchomiona funkcja `__run_exit_handlers()`, która wywoła zarejestrowane destruktory.
|
||||
|
||||
{% hint style="danger" %}
|
||||
Jeśli program kończy działanie za pomocą funkcji **`_exit()`**, zostanie wywołane wywołanie systemowe **`exit`** i obsługiwane nie będą wykonywane. Aby potwierdzić, że `__run_exit_handlers()` jest wywoływane, można ustawić punkt przerwania na to.
|
||||
{% endhint %}
|
||||
|
||||
Ważny kod to ([źródło](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
|
||||
```c
|
||||
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
|
||||
if (fini_array != NULL)
|
||||
{
|
||||
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
|
||||
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
|
||||
|
||||
while (sz-- > 0)
|
||||
((fini_t) array[sz]) ();
|
||||
}
|
||||
[...]
|
||||
|
||||
|
||||
|
||||
|
||||
// This is the d_un structure
|
||||
ptype l->l_info[DT_FINI_ARRAY]->d_un
|
||||
type = union {
|
||||
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
|
||||
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
|
||||
}
|
||||
```
|
||||
Zauważ, jak `map -> l_addr + fini_array -> d_un.d_ptr` jest używane do **obliczenia** pozycji **tablicy funkcji do wywołania**.
|
||||
|
||||
Istnieje **kilka opcji**:
|
||||
|
||||
* Nadpisz wartość `map->l_addr`, aby wskazywała na **fałszywy `fini_array`** z instrukcjami do wykonania arbitralnego kodu
|
||||
* Nadpisz wpisy `l_info[DT_FINI_ARRAY]` i `l_info[DT_FINI_ARRAYSZ]` (które są mniej więcej kolejne w pamięci), aby wskazywały na sfałszowaną strukturę `Elf64_Dyn`, która ponownie sprawi, że **`array` wskazuje na obszar pamięci kontrolowany przez atakującego**.
|
||||
* [**Ten opis**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) nadpisuje `l_info[DT_FINI_ARRAY]` adresem kontrolowanej pamięci w `.bss`, zawierającym fałszywy `fini_array`. Ten fałszywy array zawiera **najpierw** [**adres jednego gadżetu**](../rop-return-oriented-programing/ret2lib/one-gadget.md), który zostanie wykonany, a następnie **różnicę** między adresem tego **fałszywego arraya** a wartością `map->l_addr`, aby `*array` wskazywał na fałszywy array.
|
||||
* Zgodnie z głównym postem tej techniki i [**tym opisem**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so pozostawia wskaźnik na stosie, który wskazuje na `link_map` binarnego pliku w ld.so. Dzięki arbitralnemu zapisowi możliwe jest nadpisanie go i spowodowanie, że wskazuje na fałszywy `fini_array` kontrolowany przez atakującego z adresem [**jednego gadżetu**](../rop-return-oriented-programing/ret2lib/one-gadget.md) na przykład.
|
||||
|
||||
Po poprzednim kodzie znajdziesz kolejny interesujący fragment kodu:
|
||||
```c
|
||||
/* Next try the old-style destructor. */
|
||||
ElfW(Dyn) *fini = map->l_info[DT_FINI];
|
||||
if (fini != NULL)
|
||||
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
|
||||
}
|
||||
```
|
||||
W tym przypadku możliwe byłoby nadpisanie wartości `map->l_info[DT_FINI]`, wskazującej na sfałszowaną strukturę `ElfW(Dyn)`. Znajdź [**więcej informacji tutaj**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure).
|
||||
|
||||
## Nadpisanie listy dtor\_list w pamięci TLS w **`__run_exit_handlers`**
|
||||
|
||||
Jak [**wyjaśniono tutaj**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite), jeśli program kończy działanie za pomocą `return` lub `exit()`, zostanie wykonane **`__run_exit_handlers()`**, które wywoła zarejestrowane funkcje destruktorów.
|
||||
|
||||
Kod z `_run_exit_handlers()`:
|
||||
```c
|
||||
/* Call all functions registered with `atexit' and `on_exit',
|
||||
in the reverse of the order in which they were registered
|
||||
perform stdio cleanup, and terminate program execution with STATUS. */
|
||||
void
|
||||
attribute_hidden
|
||||
__run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
bool run_list_atexit, bool run_dtors)
|
||||
{
|
||||
/* First, call the TLS destructors. */
|
||||
#ifndef SHARED
|
||||
if (&__call_tls_dtors != NULL)
|
||||
#endif
|
||||
if (run_dtors)
|
||||
__call_tls_dtors ();
|
||||
```
|
||||
Kod z **`__call_tls_dtors()`**:
|
||||
```c
|
||||
typedef void (*dtor_func) (void *);
|
||||
struct dtor_list //struct added
|
||||
{
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
};
|
||||
|
||||
[...]
|
||||
/* Call the destructors. This is called either when a thread returns from the
|
||||
initial function or when the process exits via the exit function. */
|
||||
void
|
||||
__call_tls_dtors (void)
|
||||
{
|
||||
while (tls_dtor_list) // parse the dtor_list chained structures
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
|
||||
dtor_func func = cur->func;
|
||||
PTR_DEMANGLE (func); // demangle the function ptr
|
||||
|
||||
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
|
||||
func (cur->obj);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
Dla każdej zarejestrowanej funkcji w **`tls_dtor_list`**, zostanie odszyfrowany wskaźnik z **`cur->func`** i zostanie ona wywołana z argumentem **`cur->obj`**.
|
||||
|
||||
Korzystając z funkcji **`tls`** z tego [**forka GEF**](https://github.com/bata24/gef), można zobaczyć, że **`dtor_list`** jest bardzo **blisko** **stack canary** i **PTR\_MANGLE cookie**. Dlatego, przy przepełnieniu go, możliwe byłoby **nadpisanie** **cookie** i **stack canary**.\
|
||||
Poprzez nadpisanie PTR\_MANGLE cookie, możliwe byłoby **obejście funkcji `PTR_DEMANLE`** poprzez ustawienie go na 0x00, co oznaczałoby, że operacja **`xor`** użyta do uzyskania rzeczywistego adresu to po prostu skonfigurowany adres. Następnie, poprzez zapisanie w **`dtor_list`** jest możliwe **połączenie kilku funkcji** z adresem funkcji i jej **argumentem**.
|
||||
|
||||
Na koniec zauważ, że przechowywany wskaźnik nie tylko zostanie zaszyfrowany z użyciem cookie, ale także obrócony o 17 bitów:
|
||||
```armasm
|
||||
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
|
||||
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
|
||||
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
|
||||
```
|
||||
Więc musisz to wziąć pod uwagę przed dodaniem nowego adresu.
|
||||
|
||||
Znajdź przykład w [**oryginalnym poście**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
|
||||
|
||||
## Inne zmodyfikowane wskaźniki w **`__run_exit_handlers`**
|
||||
|
||||
Ta technika jest [**wyjaśniona tutaj**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) i zależy ponownie od programu **zakończającego działanie za pomocą `return` lub `exit()`**, więc zostaje wywołane **`__run_exit_handlers()`**.
|
||||
|
||||
Sprawdźmy więcej kodu tej funkcji:
|
||||
```c
|
||||
while (true)
|
||||
{
|
||||
struct exit_function_list *cur;
|
||||
|
||||
restart:
|
||||
cur = *listp;
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
/* Exit processing complete. We will not allow any more
|
||||
atexit/on_exit registrations. */
|
||||
__exit_funcs_done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (cur->idx > 0)
|
||||
{
|
||||
struct exit_function *const f = &cur->fns[--cur->idx];
|
||||
const uint64_t new_exitfn_called = __new_exitfn_called;
|
||||
|
||||
switch (f->flavor)
|
||||
{
|
||||
void (*atfct) (void);
|
||||
void (*onfct) (int status, void *arg);
|
||||
void (*cxafct) (void *arg, int status);
|
||||
void *arg;
|
||||
|
||||
case ef_free:
|
||||
case ef_us:
|
||||
break;
|
||||
case ef_on:
|
||||
onfct = f->func.on.fn;
|
||||
arg = f->func.on.arg;
|
||||
PTR_DEMANGLE (onfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
onfct (status, arg);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_at:
|
||||
atfct = f->func.at;
|
||||
PTR_DEMANGLE (atfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
atfct ();
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_cxa:
|
||||
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
|
||||
we must mark this function as ef_free. */
|
||||
f->flavor = ef_free;
|
||||
cxafct = f->func.cxa.fn;
|
||||
arg = f->func.cxa.arg;
|
||||
PTR_DEMANGLE (cxafct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
cxafct (arg, status);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
goto restart;
|
||||
}
|
||||
|
||||
*listp = cur->next;
|
||||
if (*listp != NULL)
|
||||
/* Don't free the last element in the chain, this is the statically
|
||||
allocate element. */
|
||||
free (cur);
|
||||
}
|
||||
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
```
|
||||
Zmienna `f` wskazuje na strukturę **`initial`** i w zależności od wartości `f->flavor` zostaną wywołane różne funkcje.\
|
||||
W zależności od wartości, adres funkcji do wywołania będzie w innym miejscu, ale zawsze będzie **rozwiązany**.
|
||||
|
||||
Ponadto, w opcjach **`ef_on`** i **`ef_cxa`** można również kontrolować **argument**.
|
||||
|
||||
Możliwe jest sprawdzenie struktury **`initial`** w sesji debugowania z uruchomionym GEF za pomocą **`gef> p initial`**.
|
||||
|
||||
Aby to wykorzystać, musisz albo **ujawnić lub usunąć ciasteczko `PTR_MANGLE`** a następnie nadpisać wpis `cxa` w initial na `system('/bin/sh')`.\
|
||||
Przykład tego znajdziesz w [**oryginalnym wpisie na blogu dotyczącym tej techniki**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -35,8 +245,8 @@ 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ów**](https://opensea.io/collection/the-peass-family)
|
||||
* 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.
|
||||
* **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…
Add table
Reference in a new issue