如何在c中输入/x00内存地址?

时间:2021-08-09 22:47:55

I am learning format string attack from my book Hacking : Art of Exploitation. I have this small program and this is the code :

我从我的书《黑客:剥削艺术》中学习了格式字符串攻击。我有一个小程序,这是代码:

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

I want to input address to my program and print it. The address is 0x00600b98 because of little endian byte order I input "\x98\x0b\x60\x00"

我想把地址输入我的程序并打印出来。地址是0x00600b98,因为我输入的字节顺序是“\x98\x0b\x60\x00”

this is my bash code : ./fmt_vuln $(python -c 'print "\x98\x0b\x60\x00"')%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.

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

But the problem is, the first address (\x00) its become null and not inputed to my address and when the memory is printed it become 25600b98. So my question is, why this problem happen and how to input address of 00 ?

但是问题是,第一个地址(\x00)它会变成null而不会被输入到我的地址,当内存被打印出来时,它会变成25600b98。我的问题是,为什么会出现这个问题以及如何输入00的地址?

This is the output:

这是输出:

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

2 个解决方案

#1


0  

argv[1] points to a character array with the contents "\x98\x0b\x60\x00". Notice this is 5 bytes: 4 plus a null character.

argv[1]指向一个字符数组,内容为“\x98\x0b\x60\x00”。注意这是5个字节:4加上一个空字符。

The following code only copies until reaching a null character, which results in only 4 bytes being copied as argv[1][3] is a null character.

下面的代码只复制到一个空字符,这导致只有4个字节被复制为argv[1][3]是一个空字符。

strcpy(text, argv[1]);

Suggest adding optional 2nd parameter and calling the program with an additional parameter indicating the length.

建议添加可选的第二个参数,并使用一个表示长度的附加参数调用程序。

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

Note that the following code will still only print to first 3 characters

注意,下面的代码仍然只打印到前3个字符

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

BTW: Suggest doing debug output before printf(text); and fixing its mis-matched formats

建议在printf(文本)之前进行调试输出;修复不匹配的格式

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


0  

It's because null bytes (/x00), at least in C, are used to terminate a string. So, when you printf them, they are interpreted as the end of the string.

这是因为至少在C中,空字节(/x00)用于终止字符串。当你打印它们时,它们被解释为字符串的末尾。

A great explanation on this, coupled with information on how to properly incorporate null bytes into your code can be found here.

这里有一个很好的解释,以及如何正确地将空字节合并到代码中的信息。

I hope this helps.

我希望这可以帮助。

#1


0  

argv[1] points to a character array with the contents "\x98\x0b\x60\x00". Notice this is 5 bytes: 4 plus a null character.

argv[1]指向一个字符数组,内容为“\x98\x0b\x60\x00”。注意这是5个字节:4加上一个空字符。

The following code only copies until reaching a null character, which results in only 4 bytes being copied as argv[1][3] is a null character.

下面的代码只复制到一个空字符,这导致只有4个字节被复制为argv[1][3]是一个空字符。

strcpy(text, argv[1]);

Suggest adding optional 2nd parameter and calling the program with an additional parameter indicating the length.

建议添加可选的第二个参数,并使用一个表示长度的附加参数调用程序。

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

Note that the following code will still only print to first 3 characters

注意,下面的代码仍然只打印到前3个字符

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

BTW: Suggest doing debug output before printf(text); and fixing its mis-matched formats

建议在printf(文本)之前进行调试输出;修复不匹配的格式

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


0  

It's because null bytes (/x00), at least in C, are used to terminate a string. So, when you printf them, they are interpreted as the end of the string.

这是因为至少在C中,空字节(/x00)用于终止字符串。当你打印它们时,它们被解释为字符串的末尾。

A great explanation on this, coupled with information on how to properly incorporate null bytes into your code can be found here.

这里有一个很好的解释,以及如何正确地将空字节合并到代码中的信息。

I hope this helps.

我希望这可以帮助。