====== 6. Exploatarea memoriei ======
Folosirea necorespunzătoare a șirurilor, întregilor și a altor tipuri de date și funcționalități poate lăsa atacatorului posibilitatea de citire și suprascriere de informații critice din memorie. Exploatarea memoriei este unul dintre modurile în care un atacator urmărește accesul la sistem și controlul acestuia.
===== Subiecte abordate =====
* fluxul de control al programului
* pointeri de cod
* redirectarea execuției
* injecția de cod
===== Resurse =====
* [[http://koala.cs.pub.ro/training/res/secure-low-level-programming/slides/06-exploatarea-memoriei.pdf|Slide-uri]]
* [[http://koala.cs.pub.ro/training/res/secure-low-level-programming/arc/06-exploatarea-memoriei-skel.zip|Arhiva de suport]]
===== Exerciții =====
Arhiva de suport pentru exerciții se găsește [[http://koala.cs.pub.ro/training/res/secure-low-level-programming/arc/06-exploatarea-memoriei-skel.zip|aici]]. Descărcați arhiva și apoi decomprimați-o folosind comenzile:
wget http://koala.cs.pub.ro/training/res/secure-low-level-programming/arc/06-exploatarea-memoriei-skel.zip
unzip 06-exploatarea-memoriei-skel.zip
cd 06-exploatarea-memoriei-skel/
==== Buffer overflow pe variabilă locală ====
Accesăm directorul ''bo-local-variable/'' din arhiva de suport.
Urmăriți conținutul fișierului ''vuln.c'' și rulați executabilul ''vuln''. Folosiți-vă de buffer overflow-ul existent în program ca să afișați mesajul //You've got it. Congratulations!//.
Ca să afișați un șir mai complex folosiți Python ca mai jos:
student@pr706-pc:~$ python -c 'print "A"*16'
AAAAAAAAAAAAAAAA
student@pr706-pc:~$ python -c 'print "A"*16 + "B"*4'
AAAAAAAAAAAAAAAABBBB
student@pr706-pc:~$ python -c 'print "A"*16 + "B"*4 + "\xaa\xbb"'
AAAAAAAAAAAAAAAABBBB
student@pr706-pc:~$ python -c 'print "A"*16 + "B"*4 + "\xaa\xbb"' | xxd
00000000: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
00000010: 4242 4242 aabb 0a BBBB...
Ca să vedeți unde sunt plasate variabilele locale și bufferele și să aflați diferența între ele (//offset//-ul), dezasamblați executabilul și aflați adresa bufferului și a variabilei (sunt de forma ''rbp-''):
student@pr706-pc:~$ objdump -d -M intel vuln
Ca să transmiteți un payload unui program folosiți o linie de comandă de forma:
student@pr706-pc:~$ python -c 'print ' | ./vuln
==== Buffer overflow pe pointer de funcție ====
Accesăm directorul ''bo-function-pointer/'' din arhiva de suport.
Urmăriți conținutul fișierului ''vuln.c'' și rulați executabilul ''vuln''. Folosiți-vă de buffer overflow-ul existent în program ca să afișați mesajul //You've got it. Congratulations!//. Trebuie să suprascrieți variabila locală de tip pointer de funcție ''f'' cu adresa funcției ''hidden()'' în locul funcției ''public()''.
Ca să aflați adresa unei funcții a unui program executabil, rulați comanda ''nm'' pe acel executabil:
student@pr706-pc:~$ nm vuln
==== Buffer overflow pe adresă de retur ====
Accesăm directorul ''bo-return-address/'' din arhiva de suport.
Urmăriți conținutul fișierului ''vuln.c'' și rulați executabilul ''vuln''. Folosiți-vă de buffer overflow-ul existent în program ca să afișați mesajul //You've got it. Congratulations!// prin apelarea funcției ''hidden''. Va trebui să suprascrieți adresa de retur a funcției ''do_nasty()'' cu adresa funcției ''hidden()''.
Adresa de retur a unei funcții se găsește la adresa ''rbp+8''.
==== Rulare de shellcode ====
Accesăm directorul ''run-shellcode/'' din arhiva de suport.
Urmăriți conținutul fișierului ''prog.c'' și rulați executabilul ''prog''. Programul vă deschide un shell nou. Ca să ieșiți din acel shell folosiți comanda ''exit'' sau combinația de taste ''Ctrl+d''.
Programul folosește variabila ''shellcode'' pentru a reține un cod binar care generează un shell (realizează apelul de sistem ''execve'') atunci când este executat.
Pentru a investiga în detaliu shellcode-ul (codul binar) puteți folosi ''objdump'' ca mai jos:
student@pr706-pc:~$ echo -en '\x6a\x42\x58\xfe\xc4\x48\x99\x52\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5e\x49\x89\xd0\x49\x89\xd2\x0f\x05' > shellcode
student@pr706-pc:~$ objdump -D -M intel -b binary -m i386:x86-64 shellcode
shellcode: file format binary
Disassembly of section .data:
0000000000000000 <.data>:
0: 6a 42 push 0x42
2: 58 pop rax
3: fe c4 inc ah
5: 48 99 cqo
7: 52 push rdx
8: 48 bf 2f 62 69 6e 2f movabs rdi,0x68732f2f6e69622f
f: 2f 73 68
12: 57 push rdi
13: 54 push rsp
14: 5e pop rsi
15: 49 89 d0 mov r8,rdx
18: 49 89 d2 mov r10,rdx
1b: 0f 05 syscall
==== Injectare de shellcode ====
Accesăm directorul ''inject-shellcode/'' din arhiva de suport.
Urmăriți conținutul fișierului ''vuln.c'' și rulați executabilul ''vuln''. Furnizați-i la intrarea standard shellcode-ul pentru a genera un shell.
Va trebui să mențineți conexiunea activă la standard input pentru ''vuln''. Cel mai indicat este să folosiți comanda:
cat <(echo -e '') - | ./vuln
După ce obțineți un shell nu vă apare prompt, tastați comenzi precum ''ls'' sau ''ps''. Ca să închideți shell-ul generat folosiți comanda ''exit'' sau combinația de taste ''Ctrl+d''.
==== Buffer overflow și injectare de shellcode ====
Accesăm directorul ''bo-inject-shellcode/'' din arhiva de suport.
Urmăriți conținutul fișierului ''vuln.c'' și rulați executabilul ''vuln''. Va trebui să injectați un shellcode în variabila ''shellcode'' și să generați buffer overflow care să conducă la executarea shellcode-ului. Buffer overflow-ul va suprascrie adresa de retur a funcției ''do_nasty()'' cu adresa variabilei ''shellcode''.
Aflați adresa variabilei ''shellcode'' folosind comanda ''nm''.
Modificați template-ul din scriptul ''exploit'' pentru obținerea shell-ului și rulați scriptul folosind:
./exploit | ./vuln