
Un cercatore di ROP Gadget multithread fulmineamente veloce™. Alternativa a ropper / ropgadget (attualmente solo x86)
ropr è un cercatore di ROP Gadget multithread ultra veloce
I ROP Gadget (Return Oriented Programming) sono piccoli snippet di poche istruzioni assembly che tipicamente terminano con un'istruzione ret e che esistono già come codice eseguibile all'interno di ogni binario o libreria. Questi gadget possono essere utilizzati per lo sfruttamento di binari e per sovvertire eseguibili vulnerabili.
Quando gli indirizzi di molti ROP Gadget vengono scritti in un buffer, formiamo una ROP Chain. Se un attaccante può spostare il puntatore dello stack in questa ROP Chain, il controllo può essere completamente trasferito all'attaccante.
La maggior parte degli eseguibili contiene abbastanza gadget per scrivere una ROP Chain Turing-completa. Per quelli che non li hanno, si possono sempre utilizzare librerie dinamiche contenute nello stesso spazio di indirizzi, come libc, una volta noti i loro indirizzi.
La bellezza dell'uso dei ROP Gadget è che non è necessario scrivere nuovo codice eseguibile da nessuna parte: un attaccante può raggiungere il suo obiettivo utilizzando solo il codice già esistente nel programma.
Tipicamente il primo requisito per utilizzare i ROP Gadget è avere un posto dove scrivere la propria ROP Chain: questo può essere qualsiasi buffer leggibile. Basta scrivere gli indirizzi di ogni gadget che si desidera utilizzare in questo buffer. Se il buffer è troppo piccolo, potrebbe non esserci spazio sufficiente per scrivere una lunga ROP Chain, quindi un attaccante deve fare attenzione a costruire la propria ROP Chain in modo che sia abbastanza efficiente da entrare nello spazio disponibile.
Il requisito successivo è essere in grado di controllare lo stack. Questo può assumere la forma di un overflow dello stack, che consente di scrivere la ROP Chain direttamente sotto il puntatore dello stack, o di un "stack pivot", che di solito è un singolo gadget che sposta il puntatore dello stack al resto della ROP Chain.
Una volta che il puntatore dello stack è all'inizio della tua ROP Chain, la successiva istruzione ret attiverà l'esecuzione sequenziale dei gadget, ciascuno utilizzando il successivo come indirizzo di ritorno nel proprio stack frame.
È anche possibile aggiungere puntatori a funzione in una ROP Chain, avendo cura che gli argomenti della funzione vengano forniti dopo l'elemento successivo della ROP Chain. Questo viene tipicamente combinato con un "pop gadget", che estrae gli argomenti dallo stack per passare senza problemi al gadget successivo dopo gli argomenti della funzione.
Installazione semplice:
cargo install ropr
l'applicazione verrà installata in ~/.cargo/bin
Da sorgente:
git clone https://github.com/Ben-Lichtman/ropr
cd ropr
cargo build --release
il binario risultante sarà in target/release/ropr
In alternativa:
git clone https://github.com/Ben-Lichtman/ropr
cd ropr
cargo install --path .
l'applicazione verrà installata in ~/.cargo/bin
USAGE:
ropr [OPTIONS] <BINARY>
ARGS:
<BINARY> The path of the file to inspect
OPTIONS:
-b, --base-pivot Filters for gadgets which alter the base pointer
-c, --colour <COLOUR> Forces output to be in colour or plain text (`true` or `false`)
-h, --help Print help information
-j, --nojop Removes "JOP Gadgets" - these may have a controllable branch,
call, etc. instead of a simple `ret` at the end
-m, --max-instr <MAX_INSTR> Maximum number of instructions in a gadget [default: 6]
-n, --noisy Includes potentially low-quality gadgets such as prefixes,
conditional branches, and near branches (will find significantly
more gadgets)
-p, --stack-pivot Filters for gadgets which alter the stack pointer
-r, --norop Removes normal "ROP Gadgets"
-R, --regex <REGEX> Perform a regex search on the returned gadgets for easy filtering
--range <RANGE> Search between address ranges (in hexadecial) eg. `0x1234-0x4567`
--raw <RAW> Treats the input file as a blob of code (`true` or `false`)
-s, --nosys Removes syscalls and other interrupts
-V, --version Print version information
Per esempio, se stessi cercando un modo per riempire rax con un valore da un altro registro, potrei scegliere di filtrare con la regex ^mov eax, ...;:
❯ ropr /usr/lib/libc.so.6 -R "^mov eax, ...;" > /dev/null
==> Found 197 gadgets in 0.118 seconds
Ora posso aggiungere alcuni filtri alla riga di comando per ottenere i risultati di massima qualità:
❯ ropr /usr/lib/libc.so.6 -m 2 -j -s -R "^mov eax, ...;"
0x000353e7: mov eax, eax; ret;
0x000788c8: mov eax, ecx; ret;
0x00052252: mov eax, edi; ret;
0x0003ae43: mov eax, edx; ret;
0x000353e6: mov eax, r8d; ret;
0x000788c7: mov eax, r9d; ret;
==> Found 6 gadgets in 0.046 seconds
Ora ho un buon candidato per un gadget mov all'indirizzo 0x00052252