BROP - Blind Return Oriented Programming
Reading time: 7 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
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
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.
Aanval
1. Vind kwesbare offset deur een meer karakter te stuur totdat 'n wanfunksie van die bediener opgespoor word
2. Brute-force canary om dit te lek
3. Brute-force gestoor RBP en RIP adresse in die stapel om hulle te lek
Jy kan meer inligting oor hierdie prosesse hier (BF Forked & Threaded Stack Canaries) en hier (BF Addresses in the Stack) vind.
4. Vind die stop gadget
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.
5. Vind BROP gadget
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.
6. Vind PLT
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 dit 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
7. Vind strcmp
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 dit 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 jy wil toets (begin by nul) om al die 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 te stel.
tip
Let daarop dat gewoonlik rdx
reeds 'n waarde groter as 0 sal hê, so hierdie stap mag dalk nie nodig wees nie.
8. Vind Write of gelykwaardig
Laastens, is 'n gadget nodig wat data uit die program kan verwyder om die binêre te verwyder. En op hierdie oomblik is dit moontlik om 2 argumente te beheer en rdx
groter as 0 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 slegs 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
Outomatiese Exploitatie
Verwysings
- Oorspronklike artikel: https://www.scs.stanford.edu/brop/bittau-brop.pdf
- https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop
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
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.