2016-08-18 24 views
4

我正在學習我的書「Hacking:Art of Exploitation」中的格式化字符串攻擊。 我有這個小程序,這是代碼:如何在c中輸入/ x00內存地址?

#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); 
} 

我想輸入地址,我的程序和打印。地址是0x00600b98因爲Little Endian字節序我輸入"\x98\x0b\x60\x00"

這是我的bash代碼: ./fmt_vuln $(python -c 'print "\x98\x0b\x60\x00"')%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.

但問題是,第一個地址(\ X00),其變爲零,而不是inputed到我的地址當內存被打印時,它變成25600b98。所以我的問題是,爲什麼會出現這個問題以及如何輸入00的地址?

這是輸出:

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 

回答

0

argv[1]指向內容爲"\x98\x0b\x60\x00"的字符數組。注意這是5個字節:4加上一個空字符。

以下代碼只複製到達空字符,導致只有4個字節被複制,因爲argv[1][3]是空字符。

strcpy(text, argv[1]); 

建議添加可選的第二個參數並使用指示長度的附加參數調用程序。

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); 

注意,下面的代碼將仍然只打印到前3個字符

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

BTW:建議做調試輸出printf(text);前,確定其不匹配的格式

// 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

這是因爲空字節(/ X00),至少在C,用來端接的字符串。所以,當你printf他們,他們被解釋爲字符串的結束。

對此的一個很好的解釋,加上關於如何正確地將空字節合併到代碼中的信息可以在here找到。

我希望這會有所幫助。