2012-11-16 17 views
5

Mam mały program C do wykorzystania. Rozumiałem również logikę, jaka towarzyszyła atakowi. Jednak tak bardzo jak próbuję, to po prostu nie działa dla mnie.Format String Attack

#include <stdio.h> 
#include <stdlib.h> 

#define SECRET1 0x44 
#define SECRET2 0x55 

int main(int argc, char *argv[]) { 
    char user_input[100]; 
    int *secret; 
    int int_input; 
    int a, b, c, d; /* other variables, not used here.*/ 

    /* The secret value is stored on the heap */ 
    secret = (int *) malloc(2*sizeof(int)); 

    /* getting the secret */ 
    secret[0] = SECRET1; secret[1] = SECRET2; 

    printf("Please enter a decimal integer\n"); 
    scanf("%d", &int_input); /* getting an input from user */ 
    printf("Please enter a string\n"); 
    scanf("%s", user_input); /* getting a string from user */ 

    printf(user_input); 
    printf("\n"); 

    /* Verify whether your attack is successful */ 
    printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2); 
    printf("The new secrets:  0x%x -- 0x%x\n", secret[0], secret[1]); 
    return 0; 
} 

Po prostu muszę wydrukować adres i wartość sekretu [0], używając ciągu formatującego "printf (user_input);"

Próbowałem podając coś takiego "\ x6e \ xaf \ xff \ xff% x% x% x% x% s". ale to nie działa. Wszelkie sugestie zostaną docenione. Wielkie dzięki.

+1

Jeśli chcesz wydrukować adres czegoś, powinieneś prawdopodobnie użyć operatora addressof, '&'. –

+0

+1 dla dobrze sformatowanego kodu. –

Odpowiedz

8

To wygląda jak ćwiczenie dla klasy, więc podam kilka wskazówek, ale nie ma właściwego rozwiązania.

Próbujesz wykorzystać ten program, dostarczając niezaufane dane wejściowe. Są tu dwa dość oczywiste błędy; Jednym z nich jest scanf() przy użyciu %s, ponieważ można przepełnić bufor i nadpisać stos. Drugą jest luka typu string. Zastąpienie stosu prawdopodobnie nie pozwoliłoby ci na nic ciekawego, dopóki funkcja nie zostanie zwrócona. Na podstawie "sprawdź, czy Twój atak się powiódł", prawdopodobnie będziesz chciał wykorzystać lukę w zabezpieczeniach przed tym, więc przypuszczam, że ma to być luka w formacie.

W oparciu o sekcję weryfikacji oczekuje się, że nadpiszesz pamięć wskazaną przez secret. Jedynym sposobem wywołania przez printf zapisu w kontrolowanej lokalizacji w pamięci jest użycie specyfikatora formatu %n, który zapisuje dany wskaźnik.

Teraz chodzi o to, jak dojść do stosu, dopóki nie znajdziemy odpowiedniego wskaźnika. Wygodnie jest liczba całkowita kontrolowana przez użytkownika tuż przed wskaźnikiem na stosie. Wprowadzamy więc liczbę z łatwym do zauważenia wzorem (może 65535, który jest ffff w hex) i używamy ciąg formatu z wieloma %x s, aby zobaczyć, co jest na stosie. Gdy to stwierdzimy, następną rzeczą na stosie powinna być wskazówka.

Hmm. Po prostu próbowałem tego i okazuje się, że to nie jest takie proste. Dokładny układ ramki stosu nie jest faktycznie związany z kolejnością deklaracji; i różni się dla mnie różnymi systemami. Zamiast tego musiałem użyć wielu %lx s, wraz z dobrze znanym ciągiem na początku, i dodać linię, aby wydrukować rzeczywisty wskaźnik, więc wiedziałbym, kiedy ją znalazłem. Następnie zmień odpowiedni %lx na %n, aby pisać przez ten wskaźnik. Najłatwiej jest po prostu sprobować 20 lub tak %lx s i podstawiać je po kolei przez %n, dopóki nie uda ci się nadpisać tego wskaźnika.

W każdym razie, mam nadzieję, że wystarczy, aby zacząć. Daj mi znać, jeśli masz jakieś pytania.

+2

W rzeczywistości, na x86_64 jest wystarczająco dużo rejestrów, że jeśli skompilujesz z O2 lub O3, nic nie będzie na stosie poza buforem. –

+0

Ponadto niewykorzystane zmienne mogą zostać zoptymalizowane przez kompilator, więc rzeczywista konfiguracja stosu może nie być zgodna z oczekiwaniami. –

+0

Wielkie dzięki za twoje dane wejściowe. Dostaję powtarzające się adresy, kiedy daję% 1x wiele razy, co mnie myli. Rozumiem, że na stosie (od wysokiego do niskiego) zmienne są przechowywane w kolejności, user_input, secret, int_input. Więc jeśli podam% 1x 8 razy, powinienem móc wskazać na & int_input.Sekret = 0xbffffa5c, user_input = bffffa60, int_input = bffffa58 Proszę podać całkowitą dziesiętną Wpisz ciąg % 1x% 1x% 1x% 1x% 1x% 1x% 1x% 1x bffffa60bffffa60bffffa584002c8a440021000400212d810 Oryginalne Sekrety: 0x44 - - 0x55 Nowe sekrety: 0x44 - 0x55 – shambolic