同济@复旦第一届网络安全竞赛WP
同济@复旦第一届网络安全竞赛 Write up
-
选手
1
用户名:isseymour
-
目录
[TOC]
一、WEB
题目:游戏
-
打开调试,查看源代码
-
读懂代码逻辑,一般来说,游戏都是最后会有个
GameOver
或者success
之类的。 -
本题发现是在
g._f_()
里面会输出胜利的结果。 -
我直接把在
g.state_GAMEOVER
里加入这个函数执行,使得最后结束一定会输出成功的逻辑。 -
至此,只需要直接进入一局游戏,直接死掉即可。
-
得到 flag (见下图)
1
flag{java3cr1qtG3}
题目:laohuji
-
一看是个老虎机游戏,那就是猜数字了。
-
查看源代码,发现在下面的代码是核心:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<script>
function numRand() {
var x = 9999; //上限
var y = 1111; //下限
var rand = parseInt(Math.random() * (x - y + 1) + y);
return rand;
}
function login1(result){
$.ajax({
url: "result.php",
data: {number: result,sign:md5(result)},
type: "POST",
//dataType: "json",
success: function(data) {
data = jQuery.parseJSON(data);
$('#res').text(data.flag);
}
});
} -
也就是实际上,每次通过
login1()
向服务器发请求,收到回复来确认是否正确。 -
而且数字只可能是四位数,所以那就直接爆就行。
(注:不能爆太快,服务器会不响应,间隔10ms)
-
JS方式爆:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18function loginAll(){
for (let i=0;i<=9999;i++)
{
setTimeout(() => {
$.ajax({
url: "result.php",
data: {number: i,sign:md5(i)},
type: "POST",
//dataType: "json",
success: function(data) {
data = jQuery.parseJSON(data);
$('#res').text(data.flag);
console.log(data.flag);
}
});
}, i*10)
}
}
-
看到flag
1
flag{rIhhOr}
二、REVERSE
题目:Just met
- 打开IDA 64位反汇编看一下
- 找到main函数处,查看到如下代码:
-
分析发现,虽然是两个
strcmp
,但是dest
的值是固定的,那么实际上输入的密码必须就是dest
的值 -
dest
的值是由src
复制而来,因此值就是src
的值。 -
然而,我交上去,答案错误。。。。
1
flag{sedecrem}
-
分析了好久,后面是看到有说大小端存储的问题,那么字符应该全部反过来读取。
-
重新提交,正确了。
1
flag{mercedes}
题目:jeb
- 题目就是 jeb,下载是个安卓软件。
- 用 JEB 打开,找到主要的逻辑判断的地方(看注释,有 ”错误“”恭喜你“之类的词)
- 发现是 和
edit_userName
进行比较,那就找到edit_userName
是Tenshine
- 后续代码逻辑在
checkSN
函数里
-
checkSN逻辑:
计算userName的md5 值,然后只取下标偶数的字符,包上
flag{}
就是答案1
2
3
4字符:Tenshine
md5: b9c77224ff234f27ac6badf83b855c76
取偶数下标:
flag{bc72f242a6af3857} -
测试一下,正确。
三、PWN
题目:cat2
-
nc 连接上
-
测试了一下
1
`ls`
发现有输出
-
那就直接获取了
1
`cat flag`
成功获取
1
flag{d1ec102aa389e7c7aa5796af5fe6039a}
四、CRYPTO
题目:enemy_command
-
打开发现 似乎只有三种可能:
45/46/32
-
猜测应该是 摩斯电码
1
45 45 45 45 45 32 45 46 46 45 32 45 45 46 46 46 32 46 46 46 45 45 32 45 45 46 46 46 32 45 45 45 45 46 32 45 46 46 46 46 32 46 32 45 45 46 46 46 32 46 46 46 46 45 32 45 45 46 46 46 32 45 46 46 46 32 45 46 46 46 46 32 46 45 32 46 46 46 46 45 32 45 45 45 46 46 32 46 46 46 46 45 32 45 45 45 46 46 32 46 46 46 45 45 32 46 46 46 45 45 32 45 46 46 46 46 32 45 46 46 46 32 46 46 46 46 45 32 46 32 46 46 46 46 46 32 45 46 46 46 46 32 46 46 46 46 45 32 45 46 46 32 46 46 46 46 45 32 45 46 46 32 46 46 46 46 46 32 45 45 46 46 46 32 46 46 46 45 45 32 46 46 46 45 45 32 45 46 46 46 46 32 45 46 46 46 46 32 46 46 46 45 45 32 45 45 45 45 45 32 46 46 46 46 45 32 46 46 45 45 45 32 45 46 46 46 46 32 46 46 46 45 45 32 45 46 46 46 46 32 46 45 45 45 45 32 45 45 46 46 46 32 45 46 46
-
同时,查了一下 ASCII 码,也证实了这一点:
-
写python脚本获取转换为摩斯电码的形式
1
2
3
4
5
6
7
8
9
10
11allnum = '45 45 45 45 45 32 45 46 46 45 32 45 45 46 46 46 32 46 46 46 45 45 32 45 45 46 46 46 32 45 45 45 45 46 32 45 46 46 46 46 32 46 32 45 45 46 46 46 32 46 46 46 46 45 32 45 45 46 46 46 32 45 46 46 46 32 45 46 46 46 46 32 46 45 32 46 46 46 46 45 32 45 45 45 46 46 32 46 46 46 46 45 32 45 45 45 46 46 32 46 46 46 45 45 32 46 46 46 45 45 32 45 46 46 46 46 32 45 46 46 46 32 46 46 46 46 45 32 46 32 46 46 46 46 46 32 45 46 46 46 46 32 46 46 46 46 45 32 45 46 46 32 46 46 46 46 45 32 45 46 46 32 46 46 46 46 46 32 45 45 46 46 46 32 46 46 46 45 45 32 46 46 46 45 45 32 45 46 46 46 46 32 45 46 46 46 46 32 46 46 46 45 45 32 45 45 45 45 45 32 46 46 46 46 45 32 46 46 45 45 45 32 45 46 46 46 46 32 46 46 46 45 45 32 45 46 46 46 46 32 46 45 45 45 45 32 45 45 46 46 46 32 45 46 46'
allnums = allnum.split()
str = ''
for c in allnums:
if c == '45':
str += '-'
elif c == '46':
str += '.'
elif c == '32':
str += '/'
print(str) -
摩斯电码解码,仍然继续使用十六进制解码 ,得到如下:
1
synt{jHH3kNVMMW3f0Bca}
-
这还不是答案,因为不是
flag{}
形式,猜测可能是移位密码(凯撒密码) -
写个脚本看一下。
1 | cf = 'synt{jHH3kNVMMW3f0Bca}' |
-
如下图,看到有一个是
flag{}
1
flag{wUU3xAIZZJ3s0Opn}
题目:rwx
- Hash是 分段hash的
- 因此可以分段爆破,最终复原明文。
- python脚本如下:
1 | f=open("output","rb").readlines() |
- 运行得到:
1 | flag{8uuuuu_dd_3yyyui_like_the_internet_g0} |
题目:easy_code
-
打开看到是 三层加密,
-
很简单,反过来三层解密即可。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29import base64
def decode1(code):
res = b''
for i in code:
x = i - 24
x = x ^ 31
res += bytes([x])
return res
def decode2(code):
res = b''
for i in code:
x = i ^ 31
x = x - 31
res += bytes([x])
return res
def decode3(code):
return base64.b32decode(code)
encoded_flag = 'V622VMEEVWVEC7FMPV7265VLPN7X25T5V2XKW5VLVZBKY5TZPN4UA7CBIKX2U6NKVODA===='
decoded_flag = decode1(decode2(decode3(encoded_flag)))
print(decoded_flag.decode('utf-8')) -
运行得到 flag
1
flag{da83c46f-b264-4eeb-be9c-0207389fa0ab}
题目:HASH
-
缺失部分值而已,爆破即可,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import hashlib
import itertools
# 字符集
dic = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-/"
passwd_template = "*ha*i*_go*d"
sha_template = "2aa90dc*46aa5d0*baedc4a*13e4c0a6*91bf6*2"
placeholders = [i for i, c in enumerate(passwd_template) if c == '*']
# 尝试所有可能
for combo in itertools.product(dic, repeat=len(placeholders)):
# 构造候选
candidate_passwd = list(passwd_template)
for char, pos in zip(combo, placeholders):
candidate_passwd[pos] = char
candidate_passwd = ''.join(candidate_passwd)
# 计算 SHA-1
sha_candidate = hashlib.sha1(candidate_passwd.encode('ascii')).hexdigest()
# 检查匹配
if sha_template[:7].replace('*', '') == sha_candidate[:7]:
print(f"SHA-1 = {sha_candidate}")
print(f"Password = {candidate_passwd}") -
运行拿到值后,包上flag
1
flag{sha1is_good}
五、MISC
题目:seeyouagain
-
这题,我真的是想破脑袋了!!!!
还好做出来了,要不然我要气死了。
-
前面的流程很正常,一路顺风
用 foremost 把 zip 压缩包分离出来;
压缩包密码在图片中,修改图片高度 为 FF 就能看到密码是
flag@abc
-
好,这里开始,开始我的痛苦了
我一看
flag.txt
这不显然是 Base64 编码吗!(因为末尾有=
故猜测)又是一通 Base 解码。
结果是 《See You Again》的歌词。
我就不懂了???题目就是答案???
我试了很多遍,各种姿势,就是不对。。。。
-
后面查询 Base64 编码原理,看到有个人提及“Base64隐写”
Base64 不是编码原理吗?还能隐写?
了解原理会发现, Base64 末尾为了能够使得位数为 6 的倍数,
当不是 6 的倍数时,会自动填充0 进来。
-
但是!!!这表明这里填充的内容是不会影响解码和编码的,
它就是填充作用,仅此而已。
也就是说,不论填0填1都可以!
-
好的,至此,隐写原理也就浮出水面了,就是利用这个填充位置来存储真实信息。
-
不得不说,确实挺好的一题。的的确确达到隐写效果了。
无论我是怎么编码解码,看到的都不会是隐写的内容!!!
-
下面的python脚本获取隐写内容:
1 | with open("flag.txt") as f: |
-
运行得到flag
1
flag{da6ac101b05b6974}
题目:Pirate king steganography
-
解压得到很多图片,只有一个是无法显示的,很简单,就是压缩包(也可以二进制打开查看文件头就知道是什么了)
-
修改后缀名,解压打开即可里面有一个flag.txt 就是答案
1
flag{7e8eee62-508e-4421-a28b-baa12d0b6aa9}
题目:password
- 题目提示可以通过现有信息获取到什么?
-
- CRC值
- 字节长度
- 可以看到里面的三个 password.txt文件很短,只有 4 大小。
- 直接 CRC 碰撞即可。
1 | import zipfile |
-
运行得到字符串,连起来,就是压缩包密码。
-
输入密码打开压缩包,得到
1
flag{fb39358b-6c2e-ddb4-56e0-0f026663058d}
题目:中国菜刀
-
打开流量分析
-
过滤只看 HTTP/TCP
-
所有数据都看了下,最后是这个 209 bytes 的包比较可能。
下载下来。
-
打开看到有
X@Y
,把头尾的这个数据去掉使用压缩包方式打开,得到flag
1
key{8769fe393f2b998fa6a11afe2bfcd65e}
题目:Basic type
- 打开,一眼就是像素点
- 写个 python 脚本恢复为文件。
- 但是图片长宽不知道,长 * 宽 = 像素点个数(135000)
- 挨个猜,试一下即可。
- 发现在 900 * 150 是对的。
1 | from PIL import Image |
-
运行打开图片如下,得到flag
1
flag{RGB_1s_e4sY}
题目:Only one picture
- 常规操作
- 放入 notepad++ 发现有 flag.txt ,说明肯定有藏文本或者压缩包
- 使用 foremost 分离出来,有一个压缩包
- 解压密码在 图片属性的作者 有写
4UEXBD0Q
-
解压得到flag
1
flag{d349bd48-5e00-4159-8b4a-008bb48502c5}