【问题标题】:how to input /x00 memory address in c?如何在c中输入/ x00内存地址?
【发布时间】:2016-08-18 09:36:08
【问题描述】:

我正在从我的书 Hacking : Art of Exploitation 中学习格式字符串攻击。 我有这个小程序,这是代码:

#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 因为小端字节顺序我输入"\x98\x0b\x60\x00"

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

但问题是,第一个地址 (\x00) 变为 null 并且没有输入到我的地址,当打印内存时它变为 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

【问题讨论】:

    标签: c linux memory


    【解决方案1】:

    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 '%'
    

    顺便说一句:建议在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);
    

    【讨论】:

      【解决方案2】:

      这是因为空字节 (/x00),至少在 C 中,用于终止字符串。所以,当你printf他们时,他们被解释为字符串的结尾。

      可以在here 找到对此的很好解释,以及有关如何将空字节正确合并到代码中的信息。

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-01
        • 1970-01-01
        • 2021-03-09
        • 1970-01-01
        • 2020-07-30
        • 1970-01-01
        • 2018-10-22
        • 1970-01-01
        相关资源
        最近更新 更多