2016-08-18 11 views
4

Ich lerne format string attack aus meinem Buch Hacking: Art of Exploitation. Ich habe dieses kleine Programm, und dies ist der Code:wie man/x00 Speicheradresse in c eingibt?

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

int main(int argc, char *argv[]) { 
    char text[1024]; 
    static int test_val = -72; 

    if(argc < 2) { 
     printf("Usage: %s <text to print>\n", argv[0]); 
     exit(0); 
    } 
    strcpy(text, argv[1]); 

    printf("The right way to print user-controlled input:\n"); 
    printf("%s", text); 


    printf("\nThe wrong way to print user-controlled input:\n"); 
    printf(text); 

    printf("\n"); 

    // Debug output 
    printf("[*] test_val @ 0x%016x = %d 0x%08x\n", &test_val, test_val, test_val); 

    exit(0); 
} 

ich mein Programm Eingangsadresse wollen und ausdrucken. Die Adresse ist 0x00600b98 wegen Little-Endian-Byte-Reihenfolge I-Eingang "\x98\x0b\x60\x00"

dies ist mein bash Code: ./fmt_vuln $(python -c 'print "\x98\x0b\x60\x00"')%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.

Aber das Problem ist, die erste Adresse (\ x00) seine Null wird und nicht an meine Adresse inputed und wenn der Speicher gedruckt wird, wird es 25600b98. Also meine Frage ist, warum dieses Problem passiert und wie die Adresse von 00 eingeben?

Dies ist die Ausgabe:

The right way to print user-controlled input: 
� 
`%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x. 
The wrong way to print user-controlled input: 
� 
`f7ff5000.f7dd7970.f7b128c0.f7fd8700.0000002b.ffffe3b8.f7ddb72d.25600b98. 
[*] test_val @ 0x0000000000600b98 = -72 0xffffffb8 

Antwort

0

argv[1] verweist auf ein Zeichenarray mit dem Inhalt "\x98\x0b\x60\x00". Beachten Sie, dass dies 5 Byte ist: 4 plus ein Nullzeichen.

Der folgende Code wird nur kopiert, bis ein Nullzeichen erreicht wird. Dies führt dazu, dass nur 4 Byte kopiert werden, da argv[1][3] ein Nullzeichen ist.

Vorschlagen, optionalen zweiten Parameter hinzuzufügen und das Programm mit einem zusätzlichen Parameter aufzurufen, der die Länge angibt.

size_t size = 0; 
if (argc > 2) { 
    long i = atol(argv[2]); 
    if (i >= 0 && i < SIZE_MAX) { 
    size = (size_t) i; 
    } 
else { 
    size = strlen(argv[1]) + 1; 
} 
// strcpy(text, argv[1]); 
memcpy(text, argv[1], size); 

Beachten Sie, dass der folgende Code wird nach wie vor nur auf ersten 3 Zeichen drucken

printf("%s", text); 
printf(text); // UB if it contains '%' 

BTW: Vorschlagen Ausgang tun Debug vor printf(text); und Fixierung seiner nicht abgestimmten Formate

// printf("[*] test_val @ 0x%016x = %d 0x%08x\n", &test_val, test_val, test_val); 
printf("[*] test_val @ 0x%016x = %d 0x%08x\n", 
    (unsigned) &test_val, test_val, (unsigned) test_val); 
// or 
printf("[*] test_val @ %p = %d 0x%08x\n", 
    (void*) &test_val, test_val, (unsigned) test_val); 
0

Es ist, weil Null-Bytes (/ x00), wenigstens in C, verwendet werden, um eine Zeichenfolge zu beenden. Also, wenn Sie sie printf, werden sie als das Ende der Zeichenfolge interpretiert.

Eine großartige Erklärung dazu, zusammen mit Informationen darüber, wie man Null-Bytes in Ihren Code korrekt einbaut, finden Sie unter here.

Ich hoffe, das hilft.

Verwandte Themen