有源码(又是Flask)
# !/usr/bin/env python
# -*-coding:utf-8 -*-
"""
# File : app.py
# Time :2022/10/20 15:16
# Author :g4_simon
# version :python 3.9.7
# Description:DragonBall Radar (BlockChain)
"""
import hashlib
from flask import *
import os
import json
import hashlib
from Crypto.Cipher import AES
import random
import time
import base64
#网上找的AES加密代码,加密我又不懂,加就完事儿了
class AESCipher():
def __init__(self,key):
self.key = self.add_16(hashlib.md5(key.encode()).hexdigest()[:16])
self.model = AES.MODE_ECB
self.aes = AES.new(self.key,self.model)
def add_16(self,par):
if type(par) == str:
par = par.encode()
while len(par) % 16 != 0:
par += b'\x00'
return par
def aesencrypt(self,text):
text = self.add_16(text)
self.encrypt_text = self.aes.encrypt(text)
return self.encrypt_text
def aesdecrypt(self,text):
self.decrypt_text = self.aes.decrypt(text)
self.decrypt_text = self.decrypt_text.strip(b"\x00")
return self.decrypt_text
#初始化全局变量
app = Flask(__name__)
flag=os.getenv('FLAG')
AES_ECB=AESCipher(flag)
app.config['JSON_AS_ASCII'] = False
#懒得弄数据库或者类,直接弄字典就完事儿了
players={}
@app.route('/', methods=['GET'])
def index():
"""
提供登录功能
"""
@app.route('/radar',methods=['GET','POST'])
def radar():
"""
提供雷达界面
"""
@app.route('/find_dragonball',methods=['GET','POST'])
def find_dragonball():
"""
找龙珠,返回龙珠地址
"""
xxxxxxxxxxx#无用代码可以忽略
if search_count==10:#第一次搜寻,给一个一星龙珠
dragonball="1"
elif search_count<=0:
data={"code":1,"msg":"搜寻次数已用完"}
return jsonify(data)
else:
random_num=random.randint(1,1000)
if random_num<=6:
dragonball=一个没拿过的球,比如'6'
else:
dragonball='0'#0就代表没有发现龙珠
players[player_id]['search_count']=search_count-1
data={'player_id':player_id,'dragonball':dragonball,'round_no':str(11-search_count),'time':time.strftime('%Y-%m-%d %H:%M:%S')}
#json.dumps(data)='{"player_id": "572d4e421e5e6b9bc11d815e8a027112", "dragonball": "1", "round_no": "9", "time":"2022-10-19 15:06:45"}'
data['address']= base64.b64encode(AES_ECB.aesencrypt(json.dumps(data))).decode()
return jsonify(data)
@app.route('/get_dragonball',methods=['GET','POST'])
def get_dragonball():
"""
根据龙珠地址解密后添加到用户信息
"""
xxxxxxxxx#无用代码可以忽略
try:
player_id=request.cookies.get("player_id")
address=request.args.get('address')
data=AES_ECB.aesdecrypt(base64.b64decode(address))
data=json.loads(data.decode())
if data['dragonball'] !="0":
players[data['player_id']]['dragonballs'].append(data['dragonball'])
return jsonify({'get_ball':data['dragonball']})
else:
return jsonify({'code':1,'msg':"这个地址没有发现龙珠"})
except:
return jsonify({'code':1,'msg':"你干啥???????"})
@app.route('/flag',methods=['GET','POST'])
def get_flag():
"""
查看龙珠库存
"""
#如果有7颗龙珠就拿到flag~
@app.route('/source',methods=['GET','POST'])
def get_source():
"""
查看源代码
"""
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=False)
没发现有什么可以利用的点
反正我是没有什么思路,看了wp之后才略有所悟
首先这题利用点在 address
我们应该要先了解aes.ecb加密
AES(Advanced Encryption Standard)是一种对称加密算法,用于在网络上安全传输数据。AES的加密过程包括以下几个步骤:
密钥扩展:将密钥转换为多个子密钥,以便在后续的轮次中使用。
初始轮:将明文按块进行分组,并与第一个子密钥进行XOR运算。
轮函数:将分组进行一系列的变换操作,包括替换、置换和线性变换等,以增强加密强度。
轮密钥加:将轮函数的输出结果与下一个子密钥进行XOR运算,以进一步混淆数据。
重复执行轮函数和轮密钥加操作,直至达到设定的轮数。
最终轮:在最后一轮中,不执行轮函数操作,只进行轮密钥加和末尾的置换操作。
加密完成后,将加密后的密文发送给接收方,在接收方使用相同密钥进行解密操作。
总体而言,AES算法采用了一系列复杂的技术手段来保证加密数据的安全性,因此在现代计算机上被广泛应用于各种场景下的加密需求,如网络通信、文件存储等。
ECB(Electronic Codebook)模式是一种对称加密算法中的分组密码模式,它将明文分成固定长度的块,然后每个块单独进行加密处理,最终得到密文。具体过程如下:
将明文划分为n个等长的块,每个块的长度与密钥长度相同。
对每个块执行相同的加密算法操作,使用相同的密钥。
最终得到的n个密文块拼接在一起,构成完整的密文。
ECB模式的特点是简单、快速,并且可以并行加解密。但由于相同的明文块会被加密成相同的密文块,因此ECB模式容易受到攻击。例如,如果攻击者知道某个数据块的明文内容,那么他只需要在密文中找到相应的块,就可以轻松地识别出原始明文。
因此,虽然ECB模式在一些特定场景下依然具有一定的应用价值,但在大多数情况下,建议使用更加安全的分组密码模式,如CBC、CFB和OFB等。
而在这道题中,ecb分段中每段大小为16字节,即将
{"player_id": "572d4e421e5e6b9bc11d815e8a027112", "dragonball": "1", "round_no": "9", "time":"2022-10-19 15:06:45"}
分段成
1 | {"player_id": "5
2 | 72d4e421e5e6b9bc
3 | 11d815e8a027112"
4 | , "dragonball":
5 | "1", "round_no":
6 | "9", "time":"20
7 | 22-10-19 15:06:
8 | 45"}
然后我们理一理题目的思路
题目会先获取一个随机值,当随机值在random_num<=6
范围时就会让dragonball等于这个值,超过这个范围就让其等于0,接着会将类似于这样的json对象{"player_id": "572d4e421e5e6b9bc11d815e8a027112", "dragonball": "1", "round_no": "9", "time":"2022-10-19 15:06:45"}
通过分段,然后进行aes加密成address,也就是说address中包含了这个json对象中的所有数据,而dragonball就是拿到龙珠的关键,所以也就是说我们可以通过改变address来获取龙珠,但是因为我们不知道密钥是多少,所以我们不能直接去解密修改加密,但因为这是分段加密的,所以我们可以去尝试删掉某一段,恰巧,当我们把第五段删掉后,dragonball就等于round_no,那很好,因为我们可以控制round_no(即轮数),那么我们就利用这个脚本去删掉第五段,让dragonball等于round_no
import base64
while True:
data=input('print input:')
data=base64.b64decode(data.encode()).hex()
data=data[:128]+data[160:]
print(base64.b64encode(bytes.fromhex(data)).decode())
经过七轮后,我们就成功拿到七颗龙珠了,我们也就可以拿到flag了