0x00 前言
- 菜是原罪。
- 目前还未更完,持续更新中…
0x01 MISC
0x001 签到题
- 拖入IDA查看字符串即可得到flag,或者不拖入IDA,直接记事本打开搜索flag也能找到。
0x002 上下左右
脑洞大开的题目,考察PIL库或者turtal库等的使用。
D代表Down(下),R代表Right(右),L代表Left(左),U代表UP(上)。
脚本如下。
1 | # -*- coding: UTF-8 -*- |
- 运行脚本就能画出来flag了。
0x003 压缩包的秘密
- 用16进制查看器查看文件发现压缩包flag.zip的每相邻两个字节互换了位置,写个脚本还原回去。脚本如下:
1 | # -*- coding: UTF-8 -*- |
- 还原以后发现压缩包有密码,用16进制查看器查看发现尾部有一段字符串
dGhlcmUtaXMtaGFsZi1wd2Qtc2hlbnNp
,是一段base64,解码以后是there-is-half-pwd-shensi
,也就是说shensi
是压缩包密码的一半。 - 那么掩码爆破另外6个字符即可,不到半分钟就能爆破出来,爆破得到最终密码为
sdniscshensi
,解压压缩包即可得到flag。
0x02 Stego
0x001 啾咪~
又一道想暴打出题人的题目,这道题竟然有一半左右的人做出来???
用Stegosolve打开,Analyse-Data Extract。
- 这么勾选(这道题是BGR)然后点Preview,能找到一串base64(出题人还不忘提醒这就是flag.txt),解码得到flag。
0x002 我和我的祖国
- 考察音频隐写。
- 将附件拖入Audacity,在末尾,有猫腻。
- 向上表示1,向下表示0得到
0110011001101100011000010110011101111011011001100110010100111000011001100110010000110100001101100011100000110010001100000011010100110001001100110110001000110101001101000110001101100100011001000011010100111001011000100011000000110100001110000011010100110111001100010011100101100110001110010011010001111101
- bin转ascii得到flag。
0x003 你真的很不错
根据题目提示要求用winrar,考虑到这道题目是NTFS流隐写。
打开工具NtfsStreamsEditor,用winrar将附件flag.rar里面的内容解压出来,然后在NtfsStreamsEditor搜索,找到flag.png。
- 导出flag.png,查看该图片即可得到flag。
0x03 Crypto
0x001 简单的密码学
- 考察培根密码,解密得到
BACONEASY
。
0x003 被加密的消息
考察RSA相关知识。
后续会写一篇关于RSA的博客, 解密脚本如下:
1 | import gmpy2 |
0x04 Forensic
0x001 日志分析
考察盲注日志分析以及写脚本(正则)的能力。
比赛的时候脚本写不出来,手撕的,费眼而且费了不少时间…
- 找规律可以得到如上图所示: 在每个
C1、C2、C3、C4...
区间中,从下往上找第一个状态码200右边的那个值为215的日志对应的%3E后面的那个数。。。那个数就是flag中某一位的ascii码, 而且从C1一直到C38~ 依次找到的是flag的第一位、第二位….第三十八位。
- 至于怎么找到的这个规律…WEB选手可能有别的办法,但卑微菜鸡是把
flag{
正向输出得到ascii码为102 108 97 103 123
,然后通过ascii码去找对应的215(Response包的长度)
,然后基本找到规律以后又去验证了一下第38位}
,根据规律果然能得到应有的结果125
。
这种找规律的方法带有猜的因素, 但是前面几道题目的flag大都是38位:
flag{
+ 32位的16进制(大概是md5), +}
, 能做出来这个也算是我走运吧~赛后写了个匹配脚本(re大法好):
1 | # -*- coding: UTF-8 -*- |
0x004 流量分析
考察USB流量分析。
用wireshark从附件hack.pcapng中可以提取出来一个zip文件,名字为flag.zip。
zip的密码可以通过分析USB流量获得。
USB协议的数据部分在Leftover Capture Data域之中,在Mac和Linux下可以用tshark命令可以将 leftover capture data单独提取出来。
Mac或者Linux下的命令为
tshark -r hack.pcapng -T fields -e usb.capdata
,如果想导入usbdata.txt文件中,后面加上参数:>usbdata.txt
。Windows下如果安装了wireshark,可以在wireshark的安装目录下找到tshark.exe,调用cmd定位到wireshark的安装目录下,并将hack.pcapng也放到安装目录下,用命令
tshark.exe -r hack.pcapng -T fields -e usb.capdata
,同样如果要导入到txt文件中,后面也要加上参数。
键盘数据包的数据长度为8个字节,击键信息集中在第3个字节,每次key stroke都会产生一个keyboard event usb packet。
鼠标数据包的数据长度为4个字节,第一个字节代表按键,当取0x00时,代表没有按键、为0x01时,代表按左键,为0x02时,代表当前按键为右键。第二个字节可以看成是一个signed byte类型,其最高位为符号位,当这个值为正时,代表鼠标水平右移多少像素,为负时,代表水平左移多少像素。第三个字节与第二字节类似,代表垂直上下移动的偏移。
- 下方通过python字典的形式列出了usb keyboard的映射关系。
1 | normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"} |
- 所以完整解密脚本如下(已经将Leftover Capture Data提取到usbdata.txt中):
1 | # -*- coding: UTF-8 -*- |
- 得到压缩包密码,解压即可得到flag.txt,里面就有flag。
0x05 Re
0x001Python是世界上最好的语言
- 比赛时这道题反编译总是不成功,还以为是工具出了问题…结果比完以后大佬告诉我pyc的文件头被改了…
- 正常的pyc的文件头应该是
03 F3 0D 0A
,而这道题被改成20 19 0D 0A
, 把文件头再改回来以后就可以正常反编译了。
这算法和素数有关,懒得逆回去了,直接正向爆破(因为知道了输出)。
根据其他题的flag, 这道题目的flag也会是由
0123456789abcdef
以及lg{}
(用来组成flag)组成,那么只需要解出来这些里的每个字符的输出, 然后去跟题目给的输出进行比对就能找出flag。(如果觉得flag还会由其他字符组成,可自行尝试,原理一样)所以Python脚本如下,写脚本的能力还是有待提高啊!
1 | # -*- coding: UTF-8 -*- |
0x06 Moble
0x001 简单的apk
- 根据关键算法
1 |
|
- 可以得到脚本如下:
1 | # -*- coding: UTF-8 -*- |
0x002 贪吃蛇
- 关键函数在这俩
根据代码可以得知,paramInt1应该为90, 然后由paramInt1、paramInt2、paramInt3组成的字符串总共8位。
没必要逆算法,直接正向爆破。
鉴于str的形式可能是
90XXXXXX(其中第一个X取值为1~9)
,也可能是900XXXXX
,所以采用如下方法进行爆破。(应该会有更优的方案。)把
encrypt(int paramInt1, int paramInt2, int paramInt3)
变成encrypt(int paramInt1)
,下面只保留((StringBuilder)localObject).append(String.valueOf(paramInt1));
,这样算是为了方便爆破吧…爆破脚本如下(Java):
1 | package test_for_ctf; |
- 运行得到flag。
0x07 Pwn
0x001 pwn_MinZhu
- 考察格式化字符串漏洞。
程序首先要求输入一段Key并进行验证。
这个Key手撕就能弄出来,解出来以后是
xNd9y6
也可以用angr(借鉴表哥思路)
1 | import angr |
- 通过验证后可以来到这个函数,并且发现这个函数存在明显的格式化字符串漏洞。
- 这里的
dword_804A064
为1, 也就意味着循环只能执行一次,似乎一次循环是不够的,所以可以先通过修改这个值来让循环执行更多次数从而多次利用格式化字符串漏洞。
发现了
cat flag
,但需要满足dword_804A060 == 0x2019
。所以基本思路确定了, 第一次循环先改掉
dword_804A064
的值,让这个值大于等于3, 第二次循环让dword_804A060 == 0x2019
, 第三次循环把puts
的got
换为cat flag
所在的地址,这里也可以更换putchar
的got
。exp如下:
1 | from pwn import * |