WriteUp:QCTF keyword&picture
前言
QCTF 的 keyword 和 picture。
之所以放到一起,因为两道题是一个解法。
另外 Noise 那个题是真的无聊,不管了。
本体分别如下
LSB + AES
之所以说两道题都是一个解法,是因为它们都用了这个脚本。
就是在 LSB 前先把要加密的文本 AES 加密了一遍。
keyword
这道题解密的密码通过图片内容很容易猜测到是 lovekfc,但是解密出来后是一个形似 flag 的字符串。
1 | PVSF{vVckHejqBOVX9C1c13GFfkHJrjIQeMwf} |
通过 hint 知道是 keyword 字符替换法,也就是说如果 keyword 是 lovekfc
那么字符对应关系就变成了
1 | A B C D E F G H I J K L M N ... |
这里有个细节是大写和小写都要进行相应的替换,其他字符不参与,所以可以构造脚本如下
1 | enc = r"PVSF{vVckHejqBOVX9C1c13GFfkHJrjIQeMwf}" |
picture
这道题的密码隐藏在文件名中,就是表情包文字的拼音缩写 wwjkwywq
,解出来后是一个 python 脚本,看起来是做 DES 的。
不过停一下,这个 __all__
是什么鬼,太出戏了吧。
The only solution is for the package author to provide an explicit index of the package. The import statement uses the following convention: if a package’s init.py code defines a list named all, it is taken to be the list of module names that should be imported when from package import * is encountered. It is up to the package author to keep this list up-to-date when a new version of the package is released. Package authors may also decide not to support it, if they don’t see a use for importing * from their package.
也就是说 __all__
正常来说只有模块或者 __init__.py
中才会出现,但是往下翻可以看到
显然从这个脚本后面的结构上来看并不是一个模块,但是它又有 __all__
,大胆猜测这是出题人不知道从哪扒来的代码,直接搜一下。
bingo,第一个结果正是这个脚本的出处。
可以看到出题人煞费苦心,删掉了注释删掉了正常的测试逻辑,结果百密一疏忘了 __all__
,这里我们直接用这个 repo 提供的解密模块就可以了。
后记
吃一堑长一智,反正下次就知道这个工具咯。
参考资料
这里引一篇 hackfun 的文章,总结的很到位。