-
-
[原创]看雪.TSRC 2017CTF秋季赛第三题 crackMe
-
2017-10-29 20:28 2859
-
对于这道题,服气。做的时候遇到思维定势,想着输入要符合base64解码和莫尔斯解码的规则,然而这题的关键就在与在解码时遇到不符合规则的情况就退出了,只解码符合规则的部分。
结果
这题很精彩,但是出现了多解。先上代码
#!/usr/bin/env python # -*- coding: utf8 -*- import subprocess import base64 import random import string # 需要安装https://github.com/guanzhi/GmSSL # 计算 SM3 哈希 def get_sm3(data): cmd = 'echo -n "{}" | gmssl sm3'.format(data) r = subprocess.check_output(cmd, shell=True) sm3 = r[-65:-1] return sm3 # 生成指定长度的随机字符串 def get_rand_str(length): r = '' candidate = string.ascii_letters + string.digits for i in range(length): r += random.choice(candidate) return r if __name__ == '__main__': for i in range(32): # data长度为9的倍数,保证两次base64编码后没有 '=' # 开头的 '/' 用于莫尔斯解码时产生一个空格 data = '/' + get_rand_str(8) b64b64 = base64.b64encode(base64.b64encode(data)) # 判断base64中是否包含 '/' 或 '+' if '/' in b64b64 or '+' in b64b64: continue sm3 = get_sm3(data[:3]) print(b64b64+sm3)
然后再给一组flag。
THpKWlkyeEtNRTA16818125a17a0a98a3c0a014bc0e978c3acdf71432e1e597afd6c487c4d182221 TDB4SVoweExjbXB59cd2d73624a93aababf3404b290ba7fcd8d8c4ecc8a15b8f1cd11de29b33b755 TDNoU2FIVlpiSGcyfda40f2c80d024eaab84558a237aa9200a3b3ae9f921cbeeaf598d249f79a6a7 TDNaaVNFZ3lkMDlR734eb4d95b85812c9bd401558e426d0d9fe93275f304df3dc42149bd85b764a9 TDJ0UVJVUkJUbkYye224b0ddc81dcaf802c9d31222cf84f4225d77e90ed652f53308f1f8489e36ab TDA1WVMxbzVjemhX87f0e5fa985af4492f4be21f12012129d1b3521ae44521c1d96822c724adee41 TDJSRWVtRlFhMFZ2174cd39924afa2fc8969c32be32aa4ea3ff170c3c633e897e3d8288282e7e95b TDNCT2IxbEdTSE5U151f04656fff01be882fd049d5ed9395c095d67c0237c03fff438ed8a8c763fe TDFkeVFUVjFZMjky44a0b5a26336988f7fbed52d8ffda04084446114ab6676892d27e7e939d9d33b TDJGeFVISnpPRWhJ5015ef13da10b5b2826719280e32b87e0732ffd367944ff1d5a31c754215f449 THpKVmVGUlJlWFZNe805f6d6360a74e82bd021470437770764c08bc4668eaf57ec6010e730bb805a TDJsUVpubE9aMHhQ3b5274917f8cdbb8c689d260271cbd8fb3137c4a68e3cb3b2fa8fd0db30ad3dd TDBZd2NYVTJSRWRC13706034fdb5d5f405a04d1814940b15da438f1bb4038ad1d12a2a9277217749 TDFwdE9VVTBOR1owccff9ad893ef112f473bc2a38c90b0e9a16058ac0ebfe26169eb12a8c73c2fbb TDNGT1IwZHlTSFJX0237b8a434f9f32c9dbc27d9e63e20d9977501de09d2c22cb18ce1ea988092c2 TDNveFpsZzNjRkpMdebd2e8137274def64b61d058f254074c04680d5ec9b3d4d030789ba4a8c344b
分析
首先,整个校验的总流程如下
首先对输入进行两次base64
解码,然后再进行一次莫尔斯解码,对第二次base64
解码的结果的前3个字节计算SM3
哈希。哈希结果和输入的最后64个字节进行比较,比较通过后,再调用check
函数对莫尔斯解码的结果进行检查。这个检查很迷,基本没用。
base64
如果逆向过base64
还是能意识到这是什么的。
morse code
这个函数比较长,只截取了关键的一段,其实这个解码没有多大用,只要知道/
是单词的间隔,也就是/
会被替换成空格
。
SM3 Hash
识别出这个主要是因为sm3_init
这个函数里面的初始值。
知道了算法之后就不用详细分析了。
关于反调试
这个题的一大亮点就是反调试,其实patch掉反调试之后,不用分析那么多也能搞出一个flag,就是三个0字节的SM3哈希183920f00e15a0433ee3a8fc90dd9ac164c4142ccf63ca189a8f645ec96ff8de
。原理就是这个哈希值进行两次base64
解码后为空字符串,缓冲里面全是0,取前三个字节也是0,正好符合。可能这才是作者的意图?
下面来看一下这个程序是怎么反调试的。
isDebuggerPresent
首先加载模块,然后得到函数地址,判断一下函数地址处是否有软中断,最后调用isDebuggerPresent
。
BeingDebugged
这里涉及到PEB
结构和TEB
结构,详情请参考《加密与解密》第三版401页15.1.1 BeingDebugged。(请把广告费打到我账户上)。
checkHeap
不详述了,参考《加密与解密》第三版407页15.1.3 Heap Magic。
FindWindow
调试器的主窗口,也有标题和类名。使用这个API可以判断各种调试器的窗口是否打开。参考《加密与解密》第三版435页15.3.2 OllyDbg检测方法。
Process32Next
与查找窗口类似,查找进程。
NTICE FILEM
通过句柄检测SoftICE和Filemon,参考《加密与解密》第三版433页15.3.1。
checkRemoteDebuggerPresent
这里的反汇编出来的伪代码不太对,参考《加密与解密》第三版413页15.2.1。
ZwQueryInformationProcess
参考《加密与解密》第三版415页。
ZwQuerySystemInformation
参考《加密与解密》第三版423页。
SeDebugPrivilege
参考《加密与解密》第三版436页。
检查父进程
参考《加密与解密》第三版440页15.3.5。
int3
原理就是如果没有调试器,就利用int 3
设置四个硬件断点,这四个硬件断点都会inc eax
,最后eax的值就是4。如果调试器处理的int 3
,那么最后eax就是0。
太多了,还是把书看一遍
以前没怎么逆向过Windows,一下搞了这么多反调试,太凶残。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课