BROP - Blind Return Oriented Programming

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Celem tego ataku jest wykorzystanie ROP poprzez przepełnienie bufora bez żadnych informacji o podatnym binarnym pliku. Ten atak opiera się na następującym scenariuszu:

  • Podatność stosu i znajomość sposobu jej wywołania.

  • Aplikacja serwerowa, która restartuje się po awarii.

Atak

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

2. Bruteforce canary aby wyciekło go

3. Bruteforce przechowywane adresy RBP i RIP na stosie, aby je wyciec

Więcej informacji na temat tych procesów można znaleźć tutaj (BF Forked & Threaded Stack Canaries) oraz tutaj (BF Addresses in the Stack).

4. Znajdź gadżet stop

Ten gadżet pozwala potwierdzić, że coś interesującego zostało wykonane przez gadżet ROP, ponieważ wykonanie nie spowodowało awarii. Zazwyczaj będzie to coś, co zatrzymuje wykonanie i znajduje się na końcu łańcucha ROP podczas poszukiwania gadżetów ROP do potwierdzenia, że określony gadżet ROP został wykonany.

5. Znajdź gadżet BROP

Ta technika wykorzystuje gadżet ret2csu. Jest to dlatego, że jeśli uzyskasz dostęp do tego gadżetu w środku niektórych instrukcji, otrzymasz gadżety do kontrolowania rsi i rdi:

Są to gadżety:

  • pop rsi; pop r15; ret

  • pop rdi; ret

Zauważ, że dzięki tym gadżetom możliwe jest kontrolowanie 2 argumentów funkcji do wywołania.

Zauważ również, że gadżet ret2csu ma bardzo unikalny podpis, ponieważ będzie zdejmował 6 rejestrów ze stosu. Wysyłając łańcuch tak jak:

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

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

Aby usunąć tę ostatnią opcję, wykonuje się nowy łańcuch jak poniżej i nie powinien on wykonać gadżetu STOP, aby potwierdzić, że poprzedni zdejmował 6 rejestrów:

'A' * offset + canary + rbp + ADDR

Znając adres gadżetu ret2csu, możliwe jest wywnioskowanie adresów gadżetów do kontrolowania rsi i rdi.

6. Znajdź PLT

Tabelę PLT można przeszukiwać od 0x400000 lub od wyciekanego adresu RIP ze stosu (jeśli jest używany PIE). Wpisy w tabeli są oddzielone o 16B (0x10B), i gdy wywoływana jest jedna funkcja, serwer nie ulega awarii nawet jeśli argumenty nie są poprawne. Sprawdzenie adresu wpisu w PLT + 6B również nie powoduje awarii, ponieważ jest to pierwszy kod wykonany.

Dlatego możliwe jest znalezienie tabeli 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. Znajdź strcmp

Funkcja strcmp ustawia rejestr rdx na długość porównywanego łańcucha. Zauważ, że rdx jest trzecim argumentem i musi być większy niż 0, aby później można było użyć write do wycieku programu.

Możliwe jest znalezienie lokalizacji strcmp w PLT na podstawie jego zachowania, wykorzystując fakt, że teraz możemy kontrolować 2 pierwsze argumenty funkcji:

  • strcmp(<nieodczytywalny adres>, <nieodczytywalny adres>) -> awaria

  • strcmp(<nieodczytywalny adres>, <odczytywalny adres>) -> awaria

  • strcmp(<odczytywalny adres>, <nieodczytywalny adres>) -> awaria

  • strcmp(<odczytywalny adres>, <odczytywalny adres>) -> brak awarii

Można to sprawdzić, wywołując każdy wpis w tabeli PLT lub korzystając z wolnej ścieżki PLT, która polega w zasadzie na wywołaniu wpisu w tabeli PLT + 0xb (które wywołuje dlresolve) a następnie na stosie numeru wpisu, który chcemy sprawdzić (zaczynając od zera), aby przeskanować wszystkie wpisy PLT od pierwszego:

  • strcmp(<nieodczytywalny adres>, <odczytywalny adres>) -> awaria

  • b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP -> Spowoduje awarię

  • strcmp(<odczytywalny adres>, <nieodczytywalny adres>) -> awaria

  • b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP

  • strcmp(<odczytywalny adres>, <odczytywalny adres>) -> 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.

Znalezienie strcmp umożliwia ustawienie rdx na wartość większą niż 0.

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

### 8. Znajdowanie funkcji Write lub jej odpowiednika

W końcu potrzebny jest gadżet, który eksfiltruje dane w celu wyeksportowania binarnego. W tym momencie możliwe jest kontrolowanie 2 argumentów i ustawienie rdx większego niż 0.

Istnieją 3 wspólne funkcje, które mogą być wykorzystane do tego celu:

  • puts(data)

  • dprintf(fd, data)

  • write(fd, data, len(data)

Jednakże, oryginalny dokument wspomina tylko o funkcji write, więc porozmawiajmy o niej:

Aktualny problem polega na tym, że nie znamy gdzie znajduje się funkcja write w PLT i nie znamy numeru fd, aby wysłać dane do naszego gniazda.

Jednakże, znamy gdzie znajduje się tabela PLT i możliwe jest znalezienie write na podstawie jego zachowania. Możemy utworzyć kilka połączeń z serwerem i użyć wysokiego FD, mając nadzieję, że pasuje do niektórych naszych połączeń.

Sygnatury zachowania 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 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 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 znaleziono write

Automatyzacja Eksploatacji

Referencje

Last updated