2016-08-18 93 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找到。

我希望这会有所帮助。