第二届海啸杯部分题目Writeup
Misc
签到题
题目提供的1.zip
解压出flag.txt
,txt文件里面有大量意义不明的字符,尝试性使用base64
解密,得到结果如下图:
首行有PNG
、Adobe
等字样,推测是解密后的明文是PNG文件十六进制文件。用python解密后写入到后缀名为png
的文件中,查看图片内容,脚本如下:
1 | #./flag.txt |
flag
老烟枪
用binwalk分析图片,结果显示图片中有一个压缩包。使用命令binwalk -e cxk.png
分离出压缩包,得到flag.png,用ps的水平翻转功能,得到正常flag
flag
表白
这题就是可以百度到的png隐写操作—-修改图片宽高。用winhex打开png文件,对应修改头文件中的高数值,得到flag。
flag
小明的求助
题目给出压缩包里面有一个需要密码才能解压的flag.txt
文件,且题目提示密码他只知道”hlqiou”加上4位数字。尝试进行爆破。
生成密码字典:
1 | file = open("p.txt","w") |
爆破密码脚本(python2):
1 | #coding: utf-8 |
password found : hlqiou6974
flag
flag{5oiR54ix6buE6I6J6I2D}
密码学
恺撒将军
这题就是恺撒密码加密,特殊点就是有存在]
、<
等标点字符,一般在线解密会略过,干脆就自己写脚本,反正就是基于ASCII码做偏移:
1 | strings = "f_tnluz_aghggeao{t_oy_ldoia}" |
解密之后得到的是一个base64加密的密文:ZmxhZ3tjcnlwdG9faXNfaHhiX3NvX2VBc3kwfQ==
,在解密一次得到flag。
flag
flag{crypto_is_hxb_so_eAsy0}
小明家的小菜园
这题是栅栏密码,使用CTFcrack提供的栅栏密码工具解密:
flag
第2栏:flag{yo_uget_itzha_lan_good}
战报
这题提供较长的明文&密文,尝试分析字频,得到单表替换中的对应表。
得到对应表之后,还原得到明文,获得flag
flag
flag{eantosi}
reverse
baby reverse
这道题就是考察IDA的使用,IDA打开后,搜索(atl+t&ctrl+t)flag即可。
flag
flag{reverse_is_easy}
easy reverse
IDA打开,main()
里面存在一个条件函数,如果v1=v0
则输出you are right!!
,否则输出you are wrong!!
,推测出需要满足条件才能获得flag,即使v1=v0
。v0
被赋值为字符串kanlxvdzTljyTfyTeuor
;v1
是以参数为v3
的sub_401005
函数的返回值,v3
为我们输入值。
sub_401005
函数内部运算公式:
操作就是将每一位输入字符都与0xC
异或后加1。那么写个脚本将v0
每一位都减1后与0xC
异或得到我们应该输入的值。
1 | strings = "kanlxvdzTljyTfyTeuor" |
flag
flag{crypto_is_hxb_so_eAsy0}
霸王别姬
这题从描述到运行程序是的提示都是很明显地要脱壳。
通用脱壳软件脱壳一下,IDA打开main
函数中直接就能找到flag
这个加的是压缩壳UPX
,与pwnable.kr
中的flag
那题有些类似,可以在linux下用命令脱壳。
flag
flag{upx_so_easy_!}
电竞选手
IDA打开可以看见最后一个if条件,满足则输出Correct!\nFlag is your input
,提示我们输入的让条件符合的值就是flag。条件成立的前提是sub_401350(v4) && sub_40145A()
两个函数的返回值相同。sub_401350
的参数v4
就是输入值。
sub_401350
函数如下:
选择case 后数值按r
转换为字符
首先判断输入长度是否为32字节,然后取5~30位进入到循环结构,根据输入值的不同向dword_405060
数组中写入不同的值,若无匹配则返回0。程序正常循环结束后会返回1
sub_40145A
函数如下:
主体是一个循环体:每次v3
加上数组dword_402068
的第dword_405060[i]
位数;v4
加上数组dword_402078
的第dword_405060[i]
位数。然后3个if条件,如果v2\v3
大于9或者小于0;byte_402000[10 * v3 + v2] == 3
则返回0
。只有byte_402000[10 * v3 + v2] == 43
才返回1
。
dword_402068
、dword_402078
两个数组值:
byte_402000
数值值
根据sub_40145A()
内部结构,一开始推测是用wasd
控制每次循环读取byte_402000
的位置,也就是避开#
、控制最后读取是+
,但是发现长度不对。在师兄提点下发现是用一维数组代表二维数组,从这里看出来的:
10*v3
代表的是行号,还有给出提示一行有10个元素(v3+1就读取跳了10位,相当于读取下一行同一列的元素)。v2
代表列号。以此将byte_402000
数值的值转换为二维数组,如图所示:
出发点就是v2\v3
的初始值,用wasd
控制移动,最后移动到+
。
flag
flag{wwwwaaasssaassssdddssddddw}
Pwn
shellcode
32位只开PIE保护
直接运行:
IDA打开发现直接程序将输入的,当成命令执行了。那么直接输入shellcode就行了。
脚本
1 | from pwn import * |
simple_stackoverflow
32位保护全关
直接运行:
IDA分析,在main()
里面的overflow()
里面,变量buf
距离栈底为0x20
,而read
可以从终端输入取最多0x3FF
字节写入到buf
中,这里就存在栈溢出。
这里利用栈溢出控制指针,再次调用read函数向某地址写入shellcode之后,然后控制指针运行到shellcode。写入地址选择固定地址如bss段、data段(地址在IDA ctrl+s 查找),我就选择写入
然后问题就是怎么给溢出后调用的read传参。read函数有三个参数,32位传参看图:
脚本
1 | from pwn import * |
覆写eip的read函数地址应该是plt表中read地址,而不是read函数地址。即填入IDA中_read
地址,而不是read
地址