BROP - Blind Return Oriented Programming

Reading time: 6 minutes

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks

Podstawowe informacje

Celem tego ataku jest wykorzystanie ROP za pomocą przepełnienia bufora bez jakiejkolwiek informacji o podatnym binarnym.
Atak oparty jest na następującym scenariuszu:

  • Wrażliwość na stosie i wiedza, jak ją wywołać.
  • Aplikacja serwerowa, która restartuje się po awarii.

Atak

1. Znajdź wrażliwy offset wysyłając jeden dodatkowy znak, aż zostanie wykryta awaria serwera

2. Bruteforce canary aby go wyciekł

3. Bruteforce przechowywanych adresów RBP i RIP na stosie, aby je wyciekł

Możesz znaleźć więcej informacji na temat tych procesów tutaj (BF Forked & Threaded Stack Canaries) i tutaj (BF Addresses in the Stack).

4. Znajdź gadget stop

Ten gadget zasadniczo pozwala potwierdzić, że coś interesującego zostało wykonane przez gadget ROP, ponieważ wykonanie nie spowodowało awarii. Zwykle ten gadget będzie czymś, co zatrzymuje wykonanie i jest umieszczone na końcu łańcucha ROP, gdy szuka się gadgetów ROP, aby potwierdzić, że konkretny gadget ROP został wykonany.

5. Znajdź gadget BROP

Ta technika wykorzystuje gadget ret2csu. I to dlatego, że jeśli uzyskasz dostęp do tego gadgetu w trakcie niektórych instrukcji, otrzymasz gadgety do kontrolowania rsi i rdi:

https://www.scs.stanford.edu/brop/bittau-brop.pdf

To byłyby gadgety:

  • pop rsi; pop r15; ret
  • pop rdi; ret

Zauważ, jak z tymi gadgetami można kontrolować 2 argumenty funkcji do wywołania.

Zauważ również, że gadget ret2csu ma bardzo unikalny podpis, ponieważ będzie wyciągał 6 rejestrów ze stosu. Więc wysyłając łańcuch taki jak:

'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP

Jeśli STOP zostanie wykonany, oznacza to zasadniczo, że adres, który wyciąga 6 rejestrów ze stosu został użyty. Lub że użyty adres był również adresem STOP.

Aby usunąć tę ostatnią opcję, wykonuje się nowy łańcuch taki jak poniżej i nie może on wykonać gadgetu STOP, aby potwierdzić, że poprzedni rzeczywiście wyciągnął 6 rejestrów:

'A' * offset + canary + rbp + ADDR

Znając adres gadgetu ret2csu, można wnioskować adresy gadgetów do kontrolowania rsi i rdi.

6. Znajdź PLT

Tabela PLT może być przeszukiwana od 0x400000 lub z wyciekłego adresu RIP ze stosu (jeśli PIE jest używane). Wpisy tabeli są oddzielone o 16B (0x10B), a gdy jedna funkcja jest wywoływana, serwer nie zawiesza się, nawet jeśli argumenty nie są poprawne. Ponadto, sprawdzanie adresu wpisu w PLT + 6B również nie powoduje awarii, ponieważ jest to pierwszy kod wykonywany.

Dlatego można znaleźć tabelę PLT, sprawdzając następujące zachowania:

  • 'A' * offset + canary + rbp + ADDR + STOP -> brak awarii
  • 'A' * offset + canary + rbp + (ADDR + 0x6) + STOP -> brak awarii
  • 'A' * offset + canary + rbp + (ADDR + 0x10) + STOP -> brak awarii

7. Znajdowanie strcmp

Funkcja strcmp ustawia rejestr rdx na długość porównywanego ciągu. Zauważ, że rdx jest trzecim argumentem i musimy, aby był większy niż 0, aby później użyć write, aby wyciekł program.

Można znaleźć lokalizację strcmp w PLT na podstawie jej zachowania, wykorzystując fakt, że teraz możemy kontrolować 2 pierwsze argumenty funkcji:

  • strcmp(<non read addr>, <non read addr>) -> awaria
  • strcmp(<non read addr>, <read addr>) -> awaria
  • strcmp(<read addr>, <non read addr>) -> awaria
  • strcmp(<read addr>, <read addr>) -> brak awarii

Można to sprawdzić, wywołując każdy wpis w tabeli PLT lub używając wolnej ścieżki PLT, która zasadniczo polega na wywołaniu wpisu w tabeli PLT + 0xb (co wywołuje dlresolve) a następnie na stosie przez numer wpisu, który chce się zbadać (zaczynając od zera), aby przeskanować wszystkie wpisy PLT od pierwszego:

  • strcmp(<non read addr>, <read addr>) -> awaria
  • b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP -> Spowoduje awarię
  • strcmp(<read addr>, <non read addr>) -> awaria
  • b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
  • strcmp(<read addr>, <read addr>) -> brak awarii
  • b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP

Pamiętaj, że:

  • BROP + 0x7 wskazuje na pop RSI; pop R15; ret;
  • BROP + 0x9 wskazuje na pop RDI; ret;
  • PLT + 0xb wskazuje na wywołanie dl_resolve.

Po znalezieniu strcmp można ustawić rdx na wartość większą niż 0.

tip

Zauważ, że zazwyczaj rdx będzie już miało wartość większą niż 0, więc ten krok może nie być konieczny.

8. Znajdowanie Write lub ekwiwalentu

Na koniec potrzebny jest gadget, który eksfiltruje dane, aby wyeksportować binarny. A w tym momencie można kontrolować 2 argumenty i ustawić rdx większe niż 0.

Istnieją 3 powszechne funkcje, które można wykorzystać do tego:

  • puts(data)
  • dprintf(fd, data)
  • write(fd, data, len(data)

Jednak oryginalny artykuł wspomina tylko o funkcji write, więc porozmawiajmy o niej:

Obecnym problemem jest to, że nie wiemy gdzie funkcja write znajduje się w PLT i nie znamy numeru fd, aby wysłać dane do naszego gniazda.

Jednak wiemy gdzie znajduje się tabela PLT i można znaleźć write na podstawie jej zachowania. Możemy stworzyć wiele połączeń z serwerem i użyć wysokiego FD, mając nadzieję, że pasuje do niektórych naszych połączeń.

Podpisy zachowań do znalezienia tych funkcji:

  • 'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP -> Jeśli dane są drukowane, to znaczy, że znaleziono puts
  • 'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP -> Jeśli dane są drukowane, to znaczy, że znaleziono dprintf
  • '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 -> Jeśli dane są drukowane, to znaczy, że znaleziono write

Automatyczna eksploatacja

Odniesienia

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks