Table of Contents

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

Resurse

Exerciții

Arhiva de suport pentru exerciții se găsește 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-<numar>):

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 <TODO_payload>' | ./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 '<TODO_shellcode>') - | ./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