naby

导航

ISCC2024-练武

不亏是国赛,人人都是全栈爷啊

web

还没想好名字的塔防游戏

傻逼题目

点进网页大标题的大写字母和提示的大写字母组合成18位

代码审计

from flask import Flask
from flask import request
import hashlib
import urllib.parse
import os
import json


app = Flask(__name__)
secret_key = os.urandom(16)


class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if not os.path.exists(self.sandbox):
            os.mkdir(self.sandbox)
    def Exec(self):
        result = {}
        result['code'] = 500
        if self.checkSign():
            if "scan" in self.action:
                resp = scan(self.param)
                if resp == "Connection Timeout":
                    result['data'] = resp
                else:
                    print(resp)
                    self.append_to_file(resp)
                    result['code'] = 200
            if "read" in self.action:
                result['code'] = 200
                result['data'] = self.read_from_file()
        if result['code'] == 500:
            result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
            return result
    def checkSign(self):
        if get_sign(self.action, self.param) == self.sign:
            return True
        else:
            return False


@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.parse.unquote(request.args.get("param", ""))
    action = "scan"
    return get_sign(action, param)



@app.route('/De1ta', methods=['GET', 'POST'])
def challenge():
    action = urllib.parse.unquote(request.cookies.get("action"))
    param = urllib.parse.unquote(request.args.get("param", ""))
    sign = urllib.parse.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if waf(param):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return (json.dumps(task.Exec())

@app.route('/'))
def index():
    return open("code.txt", "r").read()
def scan(param):
    try:
        with open(param, 'r') as file:
            content = file.read()
            return content
    except FileNotFoundError:
        return "The file does not exist"
def md5(content):
    return hashlib.md5(content.encode()).hexdigest()


def get_sign(action, param):
    return hashlib.md5(secret_key + param.encode('latin1') + action.encode('latin1')).hexdigest()


def waf(param):
    check = param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else: return False


if __name__ == '__main__':
    app.debug = False
    app.run()

分析:

/geneSign:网页获取登录所需cookie

/De1tal:根据cookie中action的值决定模式,为read时可以获取flag文件

解题:

由于/geneSign中固定了md5计算的后缀scan,不是read

而/De1tal中判断模式只是看‘str' in action,单纯action中是否有对应模式的子字符串,所以不用在乎read和scan的位置

所以/geneSign中param=flag.txtread,这样就可以构成flag.txtreadscan

/De1tal中param=flag.txt,cookie: action=readscan;sign=[md5]

第一步,生成md5

第二步:登录获取flag

原神启动

查看源码访问success.html,得到提示flag在flag.txt

目录扫描,flag.txt中为fakeflag

访问docs文件,发现tomcat版本8.5.32

百度搜索到有CVE-2020-1938,获取脚本:

https://github.com/sv3nbeast/CVE-2020-1938-Tomact-file_include-file_read/

根据之前提示flag在flag.txt中,使用脚本,获取flag

misc

FunZip

一把梭

时间刺客

提取usb数据部分

#提取usb数据部分
fi=open('usbdata.txt','w')
with open('usb.pcap', 'rb') as f:
    k=1
    while 1:
        f.seek(24 + 16 * k + 35 * (k - 1))
        data = f.read(35)  # 读取数据包内容
        if not data:
            break
        for i in range(27,len(data)):
            fi.write("{:02X}".format(data[i]))
        fi.write('\n')
        k=k+1


#预处理
f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
    a=f.readline().strip()
    if a:
        if len(a)==16: # 鼠标流量的话len改为8
            out=''
            for i in range(0,len(a),2):
                if i+2 != len(a):
                    out+=a[i]+a[i+1]+":"
                else:
                    out+=a[i]+a[i+1]
            fi.write(out)
            fi.write('\n')
    else:
        break

fi.close()

#处理
mappings = { 0x04:"A",  0x05:"B",  0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G",  0x0B:"H", 0x0C:"I",  0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O",  0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5",  0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"\n", 0x2a:"[DEL]",  0X2B:"    ", 0x2C:" ",  0x2D:"-", 0x2E:"=", 0x2F:"[",  0x30:"]",  0x31:"\\", 0x32:"~", 0x33:";",  0x34:"'", 0x36:",",  0x37:"." }

nums = []
keys = open('out.txt')
for line in keys:
    if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
         continue
    nums.append(int(line[6:8],16))

keys.close()

output = ""
for n in nums:
    if n == 0 :
        continue
    if n in mappings:
        output += mappings[n]
    else:
        output += '[unknown]'

print(output)


#FLAGPR3550NWARDSA2FEE6E0

压缩包密码就是PR3550NWARDSA2FEE6E0

压缩包内文件修改时间很有问题,查到一篇博客

【CTF-MISC出题思路分享】匿于时之下_ctf 0kb-CSDN博客

import os
for i in range(18):
    filename = ".\\46\\.{0}.txt".format(i)
    file_attr = os.stat(filename)
    create_time = str(file_attr.st_mtime)
    print(chr(int(create_time[7:10])),end='')
#keDH7HrPXf4hytq3Dc

提交ISCC{keDH7HrPXf4hytq3Dc}

reverse

迷失之门

关键:

exp: 直接跟它爆了

a=[70,83,66,66,104,75,88,84,112,67,116,77,85,103,107,77,109,74,75,110,116,88,118,107,75,68,54]
v3=b'DABBZXQESVFRWNGTHYJUMKIOLPC'
v4=b'0123456789+/-=!#&*()?;:*^%'
v10=b'abcdefghijklmnopqrstuvwxyz'

ans=[]
for i in range(27):
    for j in range(33,127):
        v22=j-v3[i]
        flag=0
        if v22>0:
            if v22>25:
                if v22>51 :
                    flag=v4[v22-52]
                else :
                    flag=v10[v22-26]
            else :
                flag=ord('A')+v22
            if flag==a[i]:
                ans.append(j)
for i in ans:
    print(chr(i),end="")
#ISCC{bhX|Xs^knk`nbT|zbxsVS}

CrypticConundrum

查壳脱壳

直接看重点,进行了两次加密函数。但经过分析,mix没用,因为mix函数中又将v5 strcpy成了原来的值,所以不用管mix

先看数据,直接看汇编代码,发现应该是小端序存储,而且如果直接看汇编代码,会有重复覆盖的数值,这点是必须注意的。

查看Encryption加密函数,经过分析,NewEncryption中和加密函数中都又进行位置的对调,所以抵消之后可以不用考虑,接下来就是简单的运算操作了

但是,如果直接编写完脚本输出后会有问题,会发现有的值大于256,不在正常ascii范围内,经过测试,对大于256的值 模上256即可得到flag

EXP

v5=[0x97,0x87,0xd0,0x44,0x13,0x39,0x6e,0x99,0x35,0xf9,0xc1,0x84,0xf4,0x37,0x94,0x78,0xe5,0x29,0x95,0xaa,0xe2,0x34,0x87,0x71,0xfa,0x34]
v7=[0x49,0x53,0x43,0x43]

Str = "So--this-is-the-right-flag"
v10 = len(Str)  # 26   

for i in range(v10):
    v5[i] = v5[i] - 10

for i in range(0,v10-1):
    v5[i] = v5[i] + v5[i + 1]

for i in range(v10 - 1):
    v5[i] = v5[i] ^ v7[2]

for i in range(0, v10, 2):
    v5[i] = v5[i] ^ v7[i % 4]

for i in range(v10):
    v5[i] = v5[i] + v7[i % 4]

print(v5)
"""try:
    for i in v5:
        print(chr(i), end="")
except:
    pass"""

for i in v5:
    if i>256:
        print(chr(i%256),end="")
    else:
        print(chr(i),end="")

crypto

rsa_ku

不亏是放在misc里的密码

非预期:

笑死了n可以直接分解

http://www.factordb.com/index.php

预期:

解方程

s1 = (p-2)*(q-1) = pq-p-2q+2
s2 = (p-1)*(q-2) = pq-2p-q+2
s3 = s1-s2 = p-q
q = p-s3
n = p*(p-s3)

from Crypto.Util.number import *
from gmpy2 import *
n = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977
e = 65537
c = 79671417622863203790134201771403727501040623919447341148857390413114945657547483683496084856711621909580402488534439384610699065630556412669884735847728302698585205335825700281740418633221444675077781978038803125127642719914573970412875738100167515619227904660058420447041619894572445078978800847546643214713
#(p-2)*(q-1) = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834
#(p-1)*(q-2) = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458

#非预期
p=11104861498641160020551133747582851050482827883841239117180799157472078278661946047575808556331157873693827396366774529894387508349540416345196575506278923
q=11679509046055093484387585536769973960915016129595089156764897709796981174994469835617477280580153684696296947700908005372625963068761884667061288424062299
print(long_to_bytes(pow(c,invert(e,(p-1)*(q-1)),n)))


#预期解
s1 = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834
s2 = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458
from z3 import *
x=Int('x')
p=Solver()
p.add(x*(x-(s1-s2))==n)
p.check()
p=p.model()
p=p[x].as_long()
q=n//p
print(long_to_bytes(pow(c,invert(e,(p-1)*(q-1)),n)))


#b'ISCC{3pfzTcYhOYAMRFQeVE--}'

posted on 2024-05-25 20:21  Naby  阅读(40)  评论(0编辑  收藏  举报