前言
- 第十届极客大挑战结束了,感谢Syc的师傅们,赛题质量很高!学到了很多东西!
- 菜是原罪!
WEB
0x01 打比赛前先撸一只猫
- 不是web选手,但是基本的get传参之类的还是会的。
查看源码发现了这个假的flag。
直接get传参
?get=dog
构造成http://118.25.14.40:8110/?cat=dog
这种形式即可得到真正的flag。
MISC
0x01 签到
- 签到,关注公众号即可签到拿flag。
0x02 我好兴奋啊
- 十六进制打开,搜索
Syc{
就能找到flag。
0x03 翻过这座山
- 在所给链接的github里面,有一个教翻墙的详细教程。而且里面有个注意事项,但是里面是假的flag, 真正的flag通过找这个翻墙项目的回收站(大概可以这么叫吧),里面有个flag.md,真正的flag在里面。
0x04 散打黑客的压缩包
- 两次爆破压缩包即可得到flag。
0x05 是谁杀了谁
- 这道题目我直接dnSpy动态调试拿到flag。
- 或者解那个DES(我是没解出来..)
- 官方WP如下:
exe的逻辑如下 按钮点第一次 –> 生成一个HP的隐藏文件(注意要在“我的电脑”里面勾选隐藏文件选项)
按钮点第二次 –> 往HP文件里面写入flag
按钮点第三次 –> 删除HP文件里面的flag
按钮点第四次 –> 删除HP文件
原本出题的时候打算加壳,防止被逆向。后来想想可以多给一条路,于是没有加壳。所以逆 向选手也可以直接逆向分析。
0x06 嘿,你喜欢吃鲱鱼罐头么?
破伪加密拿到图片,详细信息里面给了提示
它看起来像死鱼一样
,图片末尾有一串oids串iisiiiisiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiioddddddddddddddddddddddddddddddddddddddddoiiodddoioioddoddddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiooddddoiiiiiodddddddoddddddddoiiiiiiiiiioiiiiiiiiiioddddddddddddddddddddoiiiiioiodddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddddddoiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddoiiiiiiiiiio
根据提示,这和鲱鱼有关系, 最后了解到有一种编码叫deadfish编码。
官方WP提供了解密网站:
- 自己写解密脚本也不难, O 表示输出(output), s表示平方(square),d表示减(dec),i表示(inc),解密脚本如下:
1 |
|
0x07 我也想成为r1ngs
- hex转ascii以后是flag的立体字。
- 真有新意。
0x08 早点睡
- 脑洞太大,官方WP如下:
这题出的太智障了,原本都不打算放的… 首先010查看发现这是个psd文件,先把文件后缀改为psd。 然后用ps或者其他类似软件打开,可以看到有一个隐藏图层。里面有个链接。 访问之后下载到第二部分,利用base64转图片可以得到第二个链接。 访问之后下载到第三部分,利用base64转图片可以得到第三个链接。 访问之后下载到第四部分,利用base64转图片发现转不出来了,观察下数据,发现是一段 base64很有规律的重复,将重复的base64提取出来然后解base64就得到了flag。
0x09 RPG真是太好玩了吧
- 我这边一直打不开,也就没法做了。
- 官方WP说题目没啥难度,打通关就能拿到flag。而且为了防止CE修改破坏游戏体验,设置了当 任意人物到达30级时会出线变态怪物的设定.但是忘记加异常状态抗性了,很轻松就被打死了, 这算一个非预期吧.。
0x10 I wanna be a geek
- 每次修改save文件即可跳关。 flag在背景图上。
0x11 游戏玩累了 不如来听听歌吧
- 做的时候忽略了题目的含义
吉良吉影发动了败者食尘!时间开始倒流了!
。看了WP知道需要倒放(从后往前分析)。 - 倒放后在开头有摩斯编码,解码得到flag。
0x12 马里奥真是太有趣了
- 参考官方WP:
下载下来是个nes后缀的文件,下载nes模拟器打开发现是初代SMB
游玩过了一世界库巴后会告诉你flag在8-4。直接金手指跳到8-4,从水关回来就是flag。
0x13 The final
- 师傅们tql! wp见师傅们给的wp:
PWN
0x01 Find tools
- pwntools远程拿到key,base64解码,然后send, 注意要interactive,不然拿不到flag。
0x02 BabyROP
- 简单ROP,但官方WP说有小坑???
1 | from pwn import * |
0x03 Babyshellcode
1 | Arch: amd64-64-little |
开了seccomp,通过seccomp-tools查看可知允许Open read write,所以采用ORW
1 | from pwn import * |
0x04 EasyCanary
- 泄露Canary。
1 | from pwn import * |
0x05 BabyCanary
- SSP Leak
1 | from pwn import * |
0x06 not bad
相比babyshellcode,多了栈迁移,依旧是ORW
1 | Arch: amd64-64-little |
1 | from pwn import * |
RE
0x01 Jiang’s fan
- 签到题目,IDA打开就能看到flag
0x02 secret
- 拖入IDA找到关键字符串
5379637B6E30775F794F755F6B6E6F775F6234736531367D
,直接base16解码或者直接hex转ascii得到flag。
0x03 Easy VB
- 用OD动态调试, 不能用IDA。
- 调试发现是将输入的flag与字符串
12345a789012345678g012345a789012
逐位异或,然后将结果与bKPObQ@goYBGRXjtVKVSn^@kFQh[V_]O
比较,如果相等则输入flag正确。所以直接上脚本就行。
1 | # -*- coding: UTF-8 -*- |
0x04 冰菓
- C#逆向,用dnSpy打开以后就能找到关键算法,直接逆算法就行。
- 脚本如下:
1 | # -*- coding: UTF-8 -*- |
0x05 PYC是啥子嘛
- 拿到PYC程序反编译以后, 可以看出来是个迷宫, 大小为10×10,稍微改改可以变成这种形式。
- 要从S(Start) 走到 E(End)且路径长度最短, &表示往上走, $表示往下走, 6表示往左走, 3表示往右走。
- flag为 Syc{Your Input}
0x06 Dll Reverse
- 题目加载
_setup0.dll
,调用里面的_TRocMxlr
函数, 如果_TRocMxlr
函数返回为true,则提示正确。 所以需要sub_10001028(Str) != 0
1 | char __usercall sub_10001028@<al>(const char *a1@<eax>) |
根据伪代码, 这个函数先把我们输入的flag进行base64加密,然后分情况进行异或运算,最后与s2进行比较,如果如果一致,则成功。
注意这里的base64进行了换表!!!! 这里的base64Table为
BCDEFGHIJKLMNOPQSVXZRWYTUeadbcfghijklmnopqrstuvwxyz0123456789+/
另外:
1 | v12 = 0; |
这一块不太容易搞清
v14 = s1[v13+v12]
到底是什么? 通过OD动态调试得知, v14每次都是依次取的flag经过base64加密以后的字符串的字符。所以解密脚本如下:
1 | # -*- coding: UTF-8 -*- |
0x07 Win32 Program
0x08 阅兵你认真看了么
- 官方WP如下:
可以直接爆破MD5,字典选用ABCD,就五位,直接正向爆破得到
ACBAD
。也可以在线解密MD5。
可以分析到unk_2020A0为数独第一行。unk_2020C4为数独的第二行到第九行。
由此可以得到数独:
1 | 1 2 0 5 4 3 0 0 0 |
- 在线数独求解可得
从而得到我们应该输入
679845716297812345981276642931281374512369848935677645
运行程序并输入两组答案
ACBAD
和679845716297812345981276642931281374512369848935677645
即可得到flag。
0x09 Python1
- 这道题挺顶的,反编译以后的代码如下:
1 | import struct, time |
重点在于b函数和d函数。如果a经过×2运算以后大于
0xffffffffffffffffL
(即溢出了),则先按位与0xffffffffffffffffL
,然后再与0xb0004b7679fa26b3L
异或,则得到的结果一定为奇数。如果a经过×2运算以后小于等于0xffffffffffffffffL
,则一定为偶数。另外一个关键点在于,如何还原溢出的数据?
对于这个程序,如果a×2(相当于左移1位)以后溢出了,那么损失的是最高位(转换成二进制来看),最低位会自动补为0。那么我们只需要补回来最高位(加上2的最高位次方,比如这次是加上2的64次方)然后再除以2就能得到原来的a了。
根据这些可以得出解密脚本。
鉴于C语言unsigned long long 最大有64位, 而我们的溢出位就是第64位,所以我们可以先除以2,然后再加上原本要补的值的一半,就相当于先加上要补的值然后再除以2。
1 | // C语言版解密脚本 |
- 此刻python的优势显出来了。
- Python解密脚本如下:
1 | # -*- coding:utf-8 -* |
0x10 Python2
- 反编译以后得到如下代码:
1 | import struct, time |
关键点1: 这个fun函数就是rand函数, 其参数s即为随机数种子。
关键点2: 如何确定这个随机数种子。
关键点3: 如何确定flag的长度。
首先: d的长度为72, b的长度为32 。
通过这一部分能知道, 我们最大能够访问到d[71], 而j最大取到31,所以length(flag的长度)最大取到40,所以flag的长度为41。
而且, d[0]只能由d[0+0]来访问,即i和j均为0。 d[71]只能由d[31+40]来访问到,所以需要d[0] = arr[0] = 77,d[71] = arr[71] = 184。
又因为flag的开头为
Syc{
, 开头第一个为S
,末尾为}
。所以b[0] = ord(‘S’)^d[0] = 30, b[31] = ord(‘}’) ^ d[71] = 194
又因为
a = struct.unpack('<I', flag[length - 4:].encode())[0] & 255
,所以随机数种子的取值为 0~255 。然后就可以爆破这个随机数种子了。
爆破脚本如下:
1 | # -*- coding: UTF-8 -*- |
得出来 seed 为 49 。b为
b = [30, 243, 208, 79, 68, 71, 24, 83, 90, 65, 118,219, 76, 115, 12, 17, 108, 37, 218, 7, 180, 179, 110,175, 88, 181, 248, 45, 8, 249, 114, 197]
然后利用z3约束求出flag。
Z3脚本如下:
1 | # -*- coding: UTF-8 -*- |
- 不一会就能得出flag,当然手动去逆也不是不可以。
0x11 Python3
Android
0x01 Sign_in
- 拖入JEB在主函数可以直接找到字符串
U3lje1NpOW5fMW5fSTNfRTRzeSF9
,base64解码即可得到flag。
0x02 蒋学姐的秘密
- 用户名可以在JEB里面找到,是
Syclover
, 密码是用户名的MD5, flag为Syc{密码}
。
0x03 正在尝试重新连接
- 程序通过访问
https://0xe4s0n.github.io/download/get_data.json
获得一个字符串和一个data,我们访问这个链接可以知道字符串为Syclover
,data是一个数组["33","28","21","20","93","13","13","96","0","11","66","27","51","42","10","12","1","85","41","38","34","23","60","33","23","86","2","94","2","90","4"]
- 程序有一个check方法,但是是在native层的, 所以我们分析
native-lib.so
。
- WP里面的F5解密是这样的…而我的F5界面是这样的…一些关键信息都没法正常显示。
- 向出题人请教了一下以后得知,需要对a1进行类型转换。
- 点一下a1 然后按Y,输出
JNIEnv *
,然后就very nice了。
- 稍作修改以后
逻辑挺简单, 将input与str[i%str__len]异或(其中str已经完成逆序,变成了
revolcyS
),如果结果与数组相同,则返回1,否则返回0。直接逆回去得到解密脚本:
1 | # -*- coding: UTF-8 -*- |
- 运行即可得到flag。