2013-02-09 27 views
9

Poznaję przepełnienia bufora i próbuję je wykonać. Mam ten kod:Skompiluj C, aby umożliwić przepełnienie bufora

#include <stdio.h> 

char *secret = "password"; 

void go_shell() { 
    char *shell = "/bin/sh"; 
    char *cmd[] = { "/bin/sh", 0 }; 
    setreuid(0); 
    execve(shell,cmd,0); 
} 

int authorize() { 
    char password[64]; 
    printf("Enter Password: "); 
    gets(password); 
    if (!strcmp(password,secret)) { 
     return 1; 
    } 
    else { 
     return 0; 
    } 
} 

int main() { 
    if (authorize()) { 
     printf("login successful\n"); 
     go_shell(); 
    } else { 
     printf("Incorrect password\n"); 
    } 
    return 0; 
} 

skompilować to z gcc, a następnie uruchomić go w gdb

wchodzę około 100 "A" S jako hasło i wywala programowych.

Problem ma rejestr jest zastępowany do 0x4141414141414141

google to i dodaje flagę -fno-stack-protector do gcc, co pozwoliło RBP być nadpisane do 0x4141414141414141 ale nic więcej.

Zastanawiam się, czy istnieje sposób na skompilowanie kodu, aby można było zastąpić protokół RIP.

+0

Czy używasz systemu Linux? Musisz też ustawić tam pewną flagę. – nhahtdh

+0

Korzystanie z systemu Mac OSX. Masz pojęcie, co to jest flaga? – carloabelli

+0

Nie wiem o Mac OSX - prawdopodobnie będzie to znacznie różniło się od Ubuntu (przykro mi, faktycznie zrobiłem to na Ubuntu, a nie na Linuksie). – nhahtdh

Odpowiedz

3

Twój kod już robi to, co chcesz, jeśli skompilujesz z -fno-stack-protector. Powodem, dla którego nie widzisz wartości RIP o wartości 0x4141414141414141 w GDB, jest generowanie ogólnego błędu ochrony przed zaktualizowaniem RIP. (Jeśli wystąpi błąd strony, procedura obsługi GPF zwykle ładuje stronę z wymiany i wznawia wykonywanie, zaczynając od nieudanej instrukcji.)

+0

Dzięki za pomoc, ale zastanawiałem się, czy istnieje sposób na wyłączenie tego GPF, aby można było ustawić RIP na" 0x4141414141414141 ", ponieważ tak się dzieje w samouczku, którego używam. – carloabelli

+0

@ cabellicar123 Nie można uniknąć GPF, chyba że utworzysz plik wykonywalny pod tym adresem. Po prostu kontynuuj swój tutorial. Prawdopodobnie następnym krokiem będzie dostarczenie specjalnie spreparowanego hasła, które sprawi, że kod przeskoczy do poprawnego adresu. – nwellnhof

+0

Bardzo dziękuję za pomoc! – carloabelli

1

Powodem, dla którego masz awarię EIP 0 × 41414141 na x32, jest to, że kiedy program wyskoczy poprzednio zapisaną wartość EIP poza stosem iz powrotem do EIP, CPU następnie próbuje wykonać polecenie pod adresem pamięci 0 × 41414141, co powoduje błąd segfault. (musi pobrać stronę przed wykonaniem oczywiście)

Teraz, podczas wykonywania x64, gdy program wyskakuje wcześniej zapisana wartość RIP z powrotem do rejestru RIP, jądro następnie próbuje wykonać instrukcje pod adresem pamięci 0 × 4141414141414141. Po pierwsze, ze względu na kanoniczne adresowanie formularzy, bity od 48 do 63 dowolnego adresu wirtualnego muszą być kopiami bitu 47 (w sposób zbliżony do rozszerzenia znaku) lub procesor zgłasza wyjątek. Jeśli to nie było problemem - jądro wykonuje dodatkowe kontrole przed wywołaniem procedury obsługi błędów strony, ponieważ maksymalny adres przestrzeni użytkownika to 0x00007FFFFFFFFFF.

Podsumowując, w architekturze x32 adres jest przekazywany bez "sprawdzania poprawności" do procedury obsługi błędów strony, która próbuje załadować stronę, która wyzwala jądro, aby wysłać program segfault, ale x64 nie zajdzie tak daleko.

Przetestuj, nadpisaj RIP za pomocą 0 × 0000414141414141, a zobaczysz, że spodziewana wartość jest umieszczana w RIP, ponieważ pre-test przechodzi przez przepustkę jądra, a następnie procedura obsługi błędów strony jest wywoływana jak w przypadku x32 (co oczywiście, wtedy powoduje awarię programu).

Powiązane problemy