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.
我希望这可以帮助。