这是c中的一个例子:
#include <stdio.h>
#include <string.h>
void bad() {
printf("Oh shit really bad~!\r\n");
}
void foo() {
char overme[4] = "WOW";
*(int*)(overme+8) = (int)bad;
}
int main() {
foo();
}
Run Code Online (Sandbox Code Playgroud) 我知道一个典型的基于堆栈的缓冲区溢出攻击有效负载看起来像这样:
(返回地址)(返回地址)...(返回地址)(返回地址)(返回地址)(返回地址)(NOP)(NOP)(NOP)(NOP)...(NOP)(NOP)(NOP) )(NOP)(SHELLCODE)
我也明白shellcode的成功执行取决于以下几点:
我没有得到的是使用这种技术的恶意软件如何能够始终正确地完成这两件事.在我看来,为了制作有效载荷,攻击者必须知道目标缓冲区的大致地址及其与返回地址的近似距离.
这两个通常是非常确定的吗?例如,如果攻击者在他的机器上执行了几次试验和错误会话,那么相同的有效负载是否会在具有完全相同二进制文件的所有其他计算机上运行?
我正在玩一个堆栈溢出示例.此示例如下所示:
void return_input (void){
char array[30];
gets (array);
printf("%s\n", array);
}
main() {
return_input();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所有这些代码都在名为overflow.c的文件中.我们有一个名为return_input的易受攻击的函数,特别是它的30字节char数组.我编译它并在gdb中打开易受攻击的函数并得到以下输出:
(gdb) disas return_input
0x08048464 <+0>: push %ebp
0x08048465 <+1>: mov %esp,%ebp
0x08048467 <+3>: sub $0x48,%esp
0x0804846a <+6>: mov %gs:0x14,%eax
0x08048470 <+12>: mov %eax,-0xc(%ebp)
0x08048473 <+15>: xor %eax,%eax
0x08048475 <+17>: lea -0x2a(%ebp),%eax
0x08048478 <+20>: mov %eax,(%esp)
0x0804847b <+23>: call 0x8048360 <gets@plt>
0x08048480 <+28>: lea -0x2a(%ebp),%eax
0x08048483 <+31>: mov %eax,(%esp)
0x08048486 <+34>: call 0x8048380 <puts@plt>
0x0804848b <+39>: mov -0xc(%ebp),%eax
0x0804848e …Run Code Online (Sandbox Code Playgroud) 可能重复:
如何在PHP/Python中进行缓冲区溢出?
当我进入这个时,我正在阅读本教程:
缓冲区溢出攻击试图溢出PHP应用程序内部的内存分配缓冲区,或者更严重的是,在Apache或底层操作系统中.请记住,您可能正在使用PHP等高级语言来编写Web应用程序,但最终,您将调用C(在Apache的情况下)来执行工作.与大多数低级语言一样,C对内存分配有严格的规定.
什么?我知道PHP已经过错误检查,因此无法进行缓冲区溢出.我应该检查用户输入长度以避免太大的数据流量吗?非常感谢你
我有很多函数需要一个字符串作为参数,我使用它char*,但我所有期望字节数组的函数也使用char*.
问题是我很容易犯错误,在字符串函数中传递一个字节数组,导致各种溢出,因为无法找到空终止符.
这通常如何解决?我可以想象改变我的所有字节数组函数uint8_t,然后编译器会在传递字符串时发出有关signed-ness的警告.或者这里的正确方法是什么?
有没有办法可以向使用的scanf发出非ascii十六进制字符%s?我正在尝试插入十六进制字符\x08\xDE\xAD等等(以演示缓冲区溢出).
输入不是命令行参数,而是程序内的scanf.
考虑以下易受攻击的代码/程序:
#include <string.h>
int main(int argc, char *argv[]) {
char buf[16];
strcpy(buf, argv[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在启用了NX和ASLR的运行Linux的IA-32(x86,32位)上,我将使用GOT覆盖技术来利用它,它基本上包括以下步骤:
strcpy@plt.text,例如pop edi ; pop ebp ; ret,作为返回地址strcpystrcpy:&bss-address as destination和one byte of /bin/shusing.text/bin/sh完全写入&bssstrcpywith system(使用偏移量,需要了解Libc的使用版本 - 让我们在这里忽略它)strcpy@plt堆栈,然后写入一些4字节的块,最后&bss指向的地址/bin/sh我想在x86-64上利用这一点,同时启用相同的缓解措施.但这更像想象的那样困难.基本上由于以下原因:
64位返回地址:x86-64中的RIP指向.text甚至不是32位长的RIP .因此,必须在堆栈上写入NULL字节以进行链函数调用.基本上,可以使用链式调用写入尽可能多的NULL字节,strcpy并利用NULL终止字符strcpy 始终写入.但是,只能strcpy通过覆盖RIP的最低有效字节来调用一次.
|0x00000000| (most significant …Run Code Online (Sandbox Code Playgroud)我正在学习堆溢出攻击,我的教科书提供了以下易受攻击的C代码:
/* record type to allocate on heap */
typedef struct chunk {
char inp[64]; /* vulnerable input buffer */
void (*process)(char *); /* pointer to function to process inp */
} chunk_t;
void showlen(char *buf)
{
int len;
len = strlen(buf);
printf("buffer5 read %d chars\n", len);
}
int main(int argc, char *argv[])
{
chunk_t *next;
setbuf(stdin, NULL);
next = malloc(sizeof(chunk_t));
next->process = showlen;
printf("Enter value: ");
gets(next->inp);
next->process(next->inp);
printf("buffer5 done\n");
}
Run Code Online (Sandbox Code Playgroud)
但是,教科书没有解释如何修复此漏洞.如果有人能够解释漏洞以及修复它的方法那将是很好的.(部分问题是我来自Java,而不是C)
我试图实现缓冲区溢出攻击,我需要知道我试图溢出的缓冲区的地址.
使用GDB显示的地址与我在代码中执行此操作时的地址不同:
确切的代码:
#include<stdio.h>
int main() {
char buffer[20];
printf("%p\n", buffer); // 0xbffff320
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我这样做在gdb中:
p &buffer
Run Code Online (Sandbox Code Playgroud)
我明白了: 0xbffff330
为什么会有差异,它会搞砸我的缓冲区溢出攻击?
我禁用了ALSR和堆栈防护.
谢谢.
编辑1:即使我单步执行gdb并遇到打印行,我也会得到0xbffff320作为地址
编辑2:
环境:在Windows 7上的虚拟框中运行Ubuntu Linux 9映像.
gdb版本:6.8-debian
使用GCC编译,例如:gcc -g -fno-stack-protector filename.c
立即执行:./a.out
地址打印:0xbffff320
然后,在这样的调试器打开:gdb ./a.out
然后输入b main
然后run
再p &buffer
然后地址是0xbffff330
编辑3:
这是重现行为的gdb日志:
$ gdb ./a.out
b主要
跑
这里的p&buffer/*地址与运行可执行文件时显示的不同*/
步骤通过程序到printf语句/*地址这里和p和缓冲区相同但不同于程序运行时打印的内容*/
我正在为学生开发缓冲区溢出练习。在这种情况下,您通常必须提供任意字节作为程序的输入(返回地址)。
假设这个例子:
#import <stdio.h>
#import <string.h>
void func() {
char buf[4];
gets(buf);
}
int main (int argc, char** argv) {
func();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
通常我会用 gdb 进行试验,直到找到一个解决方案,然后可以将其公式化为
python -c 'print "A"*8+"\x08\x04\88\72"' | ./program
Run Code Online (Sandbox Code Playgroud)
在开发越来越复杂的练习的同时,找到解决方案的难度也在增加。有时通过覆盖gdb中的返回地址
set {int}address_of_address = new_address
Run Code Online (Sandbox Code Playgroud)
有效,但 python 方法无效。调试它并能够在程序运行时在 gdb 中输入像“\x04”这样的字节会很好,分析效果。
有没有办法做到这一点?
这个问题似乎相关,但用 python 方法回答:从标准输入发送任意字节到 fgets
我的不止于此:-/