GKCTF2021 Crash
Golang 逆向,我用的是 IDA7.7, 已经可以直接恢复符号表
如果熟悉 Golang 逆向的话,应该知道 Golang 的 String 和 Slice 的内存排布,这里再给一下 String 的
struct goString {
BYTE* ptr;
goint len;
}
这里用的是 C 风格的声明,64 位下 go 的 int 默认就是 64 位的,也就是一个 goString 占 0x10 字节,正好是两个 __int64, 这个比较方便看就不单独给 IDA 声明结构体了
可以看到 main.main 里主要是对 flag 格式的检查,然后放在 main_check 中检验
分成三段校验,str[6:30] 放在 encrypto 中,最后要生成一段 base64 样字符串,str[30:34] 被 HashHex2,str[34:38] 被 HashHex5, 其中 30~34 要和已有的碰撞, 这之后直接 return 0 了,我们希望它返回的是 true,直接 return 0 显然不符合常理,我们回到汇编里看
可以看到,51483A 的 retn 是对应的最后一个 return0,而 51483F 处的字符串应该是第三个碰撞,何况后面还有 38:42, 猜测上面指向的 jz 是一个恒振条件,我们把后面的 nop 掉帮助 IDA 反汇编
后面的其实就可以猜到了,HashHex5 的碰撞也是明文,最后四位通过 main_hash 要再碰撞一次。现在这四部分有两部分是 GOAPI,两部分是自己写的,我们从第一个看过去
可以看得出来是从字符串解析一个 json,然后 DES 再 Base64. json 中给了 Key 和 IV 的明文
.noptrdata:0000000000608840 aKeyWelcometoth db '{',0Dh,0Ah ; DATA XREF: .data:off_61E540↓o
.noptrdata:0000000000608840 db ' "key": "WelcomeToTheGKCTF2021XXX",',0Dh,0Ah
.noptrdata:0000000000608840 db ' "iv": "1Ssecret"',0Dh,0Ah
.noptrdata:0000000000608840 db '}',0
直接去解
得到第一段 flag :87f645e9-b628-412f-9d7a-
后面三段其实可以通过长度猜测,这都明显是消息摘要的结果,长度分别是 64、128、32,对应比特要乘4,那很明显可以猜测为 SHA256、SHA512、md5,我们不妨爆破一下。这和题目名字也互相印证。
import hashlib
tar1 = "6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74"
tar2 = "6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9b757caae1ecce804582ae78f87fa3c9"
tar3 = "ff6e2fd78aca4736037258f0ede4ecf0"
alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
for i in alphabet :
for j in alphabet :
for k in alphabet :
for l in alphabet :
tmp = i + j + k + l
if hashlib.sha256(tmp.encode("utf-8")).hexdigest() == tar1 :
print(("ans1", tmp))
if hashlib.sha512(tmp.encode("utf-8")).hexdigest() == tar2 :
print(("ans2", tmp))
if hashlib.md5(tmp.encode("utf-8")).hexdigest() == tar3 :
print(("ans3", tmp))
('ans1', 'e402')
('ans2', 'f20a')
('ans3', 'f940')
GKCTF{87f645e9-b628-412f-9d7a-e402f20af940}