使用 c 的缓冲区溢出
Buffer Overflow using c
我正在尝试创建缓冲区溢出,它将用值“31337”覆盖变量 "b"。编译后的文件名为"bo",缓冲区大小为010,8字节,所以我用"AAAAAAAA"填充,31337十六进制为7A69。因此,Linux 中的以下命令在理论上应该有效但不成功:
printf 'AAAAAAAA\x69\x7A\x00\x00' | ./bo
上面的命令应该覆盖 "b" 变量。如果我将 b 变量更改为 1337 并将命令更改为以下内容,它就会起作用:
printf 'xxxxxxxx\x39\x05\x00\x00' | ./bo
1337 的十六进制为 539。
这是终端的命令结果
root@kali:~# printf 'AAAAAAAA\x69\x7A\x00\x00' | ./bo
1111638594
我预计 31337
root@kali:~# printf 'AAAAAAAA\x39\x05\x00\x00' | ./bo
1337
有人知道我做错了什么吗?对十六进制1337有效,对31337无效。以下是源码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int play()
{
int a;
int b;
char buffer[010];
a = 0x41414141;
b = 0x42424242;
if (read(STDIN_FILENO, &buffer, 0xC) < 0)
perror("read");
printf("%d\n", b);
}
int main(int argc, char *argv[]){
play();
exit(EXIT_SUCCESS);
}
您不能假设变量将在堆栈上有特定位置。但是,有一种方法可以强制执行它。你可以这样做:
int play()
{
struct {
int a;
char buffer[010];
int b;
} vars;
vars.a = 0x41414141;
vars.b = 0x42424242;
if (read(STDIN_FILENO, &vars.buffer, 0xC) < 0)
perror("read");
printf("%d\n", vars.b);
}
这将强制变量在内存中的顺序。当我尝试这样做时,它起作用了,但是当我切换顺序时
struct {
int a;
int b;
char buffer[010];
} vars;
它没有。
虽然我不确定您可以信任或使用它多少。这只能保证&a<&buffer<&b
。它不保证&(a+1)=&buffer
。事实上,如果a
是一个单字节类型的变量就不会这样了。
以下是订单重要性的示例:
int main()
{
struct {
char x;
int a;
char y;
} v;
struct {
char x;
char y;
int a;
} w;
printf("%d\n", sizeof(v));
printf("%d\n", sizeof(w));
}
输出:
$ ./a.out
12
8
如果您对变量重新排序,结构的大小可能会发生变化,这是不允许编译器对它们重新排序的原因。
我正在尝试创建缓冲区溢出,它将用值“31337”覆盖变量 "b"。编译后的文件名为"bo",缓冲区大小为010,8字节,所以我用"AAAAAAAA"填充,31337十六进制为7A69。因此,Linux 中的以下命令在理论上应该有效但不成功:
printf 'AAAAAAAA\x69\x7A\x00\x00' | ./bo
上面的命令应该覆盖 "b" 变量。如果我将 b 变量更改为 1337 并将命令更改为以下内容,它就会起作用:
printf 'xxxxxxxx\x39\x05\x00\x00' | ./bo
1337 的十六进制为 539。
这是终端的命令结果
root@kali:~# printf 'AAAAAAAA\x69\x7A\x00\x00' | ./bo
1111638594
我预计 31337
root@kali:~# printf 'AAAAAAAA\x39\x05\x00\x00' | ./bo
1337
有人知道我做错了什么吗?对十六进制1337有效,对31337无效。以下是源码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int play()
{
int a;
int b;
char buffer[010];
a = 0x41414141;
b = 0x42424242;
if (read(STDIN_FILENO, &buffer, 0xC) < 0)
perror("read");
printf("%d\n", b);
}
int main(int argc, char *argv[]){
play();
exit(EXIT_SUCCESS);
}
您不能假设变量将在堆栈上有特定位置。但是,有一种方法可以强制执行它。你可以这样做:
int play()
{
struct {
int a;
char buffer[010];
int b;
} vars;
vars.a = 0x41414141;
vars.b = 0x42424242;
if (read(STDIN_FILENO, &vars.buffer, 0xC) < 0)
perror("read");
printf("%d\n", vars.b);
}
这将强制变量在内存中的顺序。当我尝试这样做时,它起作用了,但是当我切换顺序时
struct {
int a;
int b;
char buffer[010];
} vars;
它没有。
虽然我不确定您可以信任或使用它多少。这只能保证&a<&buffer<&b
。它不保证&(a+1)=&buffer
。事实上,如果a
是一个单字节类型的变量就不会这样了。
以下是订单重要性的示例:
int main()
{
struct {
char x;
int a;
char y;
} v;
struct {
char x;
char y;
int a;
} w;
printf("%d\n", sizeof(v));
printf("%d\n", sizeof(w));
}
输出:
$ ./a.out
12
8
如果您对变量重新排序,结构的大小可能会发生变化,这是不允许编译器对它们重新排序的原因。