SEED实验——return-to-libc实验

摘要:
实验概述本实验的学习目标是让学生亲身体验返回libc攻击实验,这是缓冲区溢出攻击的一个有趣变体。因此,跳转到shell代码将导致程序失败。缓冲区溢出攻击有一种变种,它变成了返回libc攻击。它不需要可执行堆栈,甚至不需要外壳代码。在本实验中,我们根据以下命令编译包含缓冲区溢出漏洞的代码段:surootgcc fno stack protector zno execstack oretlibretlib。chmod4755retlib/chmodu+sretlibexit2.获取/bin/sh地址为了获取/bin/s的内存地址,我们需要编写一个程序。

实验概述

本实验的学习目标是让学生获得缓冲区溢出攻击的一种有趣变体——return-to-libc攻击实验的亲身体验。这种攻击可以绕过目前在主要linux操作系统中实现的现有保护方案。利用缓冲区溢出漏洞通常的方法是使缓冲区溢出,然后在溢出部分的返回地址指向一段恶意的shellcode,使程序跳转到存储在堆栈中的shellcode。为了防止这些类型的攻击,一些操作系统允许管理员关闭堆栈的可执行功能。因此跳转到shellcode将导致程序失败。不幸的是,上述保护机制不是足够安全的。存在一种成为return-to-libc攻击的缓冲区溢出攻击的变体,其不需要可执行堆栈,甚至不需要shellcode。相反,它会导致受到攻击的程序跳转到一些现有的代码。例如已经加载到内存中的libc库中的system()函数。在这个实验中,学生被给予一个包含缓冲区溢出漏洞的程序,他们的任务是利用该漏洞,开发一个返回到libc库函数的攻击,最终获得root权限。除了这些攻击之外,学生们还将参与学习在ubuntu中实施的防止缓冲区溢出攻击的几项保护措施。学生需要评估方案是否有效,并解释评估过程。


第二部分:实验任务

该实验共有三个任务:

  • 漏洞利用
  • 地址随机化
  • StackGuard保护机制

任务一:漏洞利用

1.编译代码是关闭地址随机化机制和非执行栈机制

sudo sysctl -w kernel.randomize_va_space=0 //注意:这里等号和0之间不能有空格

在进行代码编译时,加上-fno-stack-protector,即可关闭ubuntu上StackGuard保护机制,加上-z -execstack/noexecstack即可打开或关闭可执行栈的机制。

在本实验中,我们按照如下命令编译含有缓冲区溢出漏洞的代码段:

su root

gcc -fno-stack-protector -z noexecstack -o retlib retlib.c

chmod 4755 retlib / chmod u+s retlib

exit

2.获取/bin/sh地址

为了获取/bin/sh的内存地址,需要编写一个程序。

//getenvaddr.c
#include <stdio.h>#include <stdlib.h>#include <string.h>
int main(int argc,char const *argv[])
{
    char *ptr;
    if(argc<3)
    {
        printf("Usage: %s <environment var> <target program name>
", argv[10]);
        exit(0);
     }
    ptr = getenv(argv[1]);
    ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
    printf("%s will be at %p 
", argv[1], ptr ) ;
    return 0;
}

其中,getenv的参数为一个环境变量,因此我们需要创建一个环境变量来记录路径export BIN_SH="/bin/sh"。调用程序./getenvaddr BIN_SH ./retlib得到/bin/sh的地址。

SEED实验——return-to-libc实验第1张

如上面截图所示,/bin/sh的地址为:0xbffffe39。

3. 获取system()和exit()地址

这两个程序是驻留在内核态的,所有程序共享内核态的函数,因此我们可以用gdb来获取这两个程序的地址。

SEED实验——return-to-libc实验第2张

如上图所示,在main函数设置断点,然后运行,运用gdb调试命令,我们可以得到system()函数的地址是0xb7e5f430,exit()函数的地址是0xb7e52fb0。

将上述获得的三个地址写到代码中,


第三部分:

实验指导:了解函数调用机制

3.1 获取libc库函数的地址

用gdb命令进行获取。

3.2 将shell字符串放在内存中

本实验的一个挑战是将字符串“/bin/sh”放入内存中,并获取其地址。这可以使用环境变量来实现。执行C程序时,它会继承执行它的shell的所有环境变量。环境变量SHELL直接指向/bin/bash并且环境变量同时也被其他程序需要。所以我们引入一个新的shell变量MYSHELL,并指向zsh。

$ export MYSHELL = /bin/sh

我们将使用该变量的地址作为system()函数调用的参数。这个变量的位置在内存中使用以下代码就可以发现:

voidmain()
{
    char 8shell = getenv("MYSHELL");
    if(shell)
    prinf("%x
",(unsigned int)shell);
}

如果地址随机化被关闭,将会发现打印出的地址是相同的。然而,当您运行漏洞程序retlib时,环境变量的地址可能与通过运行上述程序获得的地址完全相同。当您更改程序名称时,这样的地址甚至会更改(文件名中的字符数不一样)。好消息是,shell的地址将与上述程序打印出来的地址相当接近。因此,您可能哟啊尝试几次才能成功。

3.3 理解栈

要知道如何进行return-to-libc攻击,必须了解堆栈的工作原理。我们使用一个小程序来了解函数调用对堆栈的影响。

/*foobar.c */
#include <stdio.h>
void foo(int x)
{
printf("Hello world: %d ", x);
}
int main()
{
foo(1);
return(0);
}

我们可以用“gcc -S foobar.c”来将程序编译成汇编代码。

免责声明:文章转载自《SEED实验——return-to-libc实验》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SQLSERVER 效能 建议加索引 EXEC sp_updatestats;对B+树,B树,红黑树的理解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Nginx基础06:location语法

location语法:表示uri方式定位 基础语法有三种: location = pattern{}  精准匹配 location pattern{}  一般匹配 location ~ pattern{} 正则匹配 location正则表达式: "~ xxx":匹配访问的请求的URL中必须包含"xxx" "~* xXx":匹配忽略后面"xXx"是否大...

usdt钱包如何跟交易所对接?

步入庚子鼠年,加密数字货币交易所之间的竞争从未停歇。头部交易所在思考创新模式、创新玩法争夺资本和用户,中小型交易所日夜探索如何在赛道中坚持下来。加密数字经济作为一种新兴行业,也是一场全天候、不停歇的全球比赛,时时刻刻都会带来意想不到的挑战,但往往与机遇、收获并存。   对于一些中小型加密货币交易所来说,要想真正吸引并且留住更多的用户,核心是了解并满足用户需...

linux socket编程client获取使用的ip和port

今天为了测试机器绑定多ip时socket client使用的ip和port, 因此查询资料看了下如何获取client的ip和port(系统自选而不是bind绑定) 主要是对连接的描述符通过getsockname 函数获取client的地址信息,函数说明如下 #include <sys/socket.h> int getsockname(int...

库、教程、论文实现,这是一份超全的PyTorch资源列表(Github 2.2K星)

项目地址:https://github.com/bharathgs/Awesome-pytorch-list 列表结构: NLP 与语音处理 计算机视觉 概率/生成库 其他库 教程与示例 论文实现 PyTorch 其他项目 自然语言处理和语音处理 该部分项目涉及语音识别、多说话人语音处理、机器翻译、共指消解、情感分类、词嵌入/表征、语音生成、文本语音转...

matlab环境配置

一.环境变量设置 AMD处理器:右键单击我的电脑 属性 — >高级 —> 环境变量 —> 系统变量 —> 新建 变量名:BLAS_VERSION,值为安装目录atlas_Athlon.dll.路径是相对的,根据的安装的路径来设置变量的值,如默认安装于C盘则设为C:MATLAB7inwin32atlas_Athlon.dll. atl...

memset函数及注意事项

  memset函数的原型为:void * memset(void *ptr,int value,size_t num);用于为地址ptr开始的num个字节赋值value。   memset函数的头文件为:C:<memory.h>或<string.h>    C++:<cstring>。   在用memset为申请的数组...