
用IDA打开cefsimple.exe,然后按ctrl+s跳到.data段(一般来说密文和秘钥都在这附近)。
在.data段开头位置发现一串32字节的数据,疑似加密后的flag。
交叉引用到代码段验证。
修改跳转后弹出一个"correct"信息框,这说明之前的猜测是对的。
加密算法分析keybox生成算法:
输入32字节的flag后,生成key_box。
虽然看不懂这个key_box的生成算法,但由于其与输入的flag内容没有关联,下个断点等它生成完后,再从内存里复制出来就行了。
加密验证部分:
算法很短,能很快的用python复刻出相同的加密算法脚本。
但我算法太菜了看不出来这具体是啥算法,导致当时写不出来解密脚本。wtcl tcl tcl 看了四个小时都没写出来。
赛后问了一下群里的师傅,Lu1u师傅一眼就认出来这是魔改的sm4算法,师傅们太强了,磕头了。
get_flag对比网上的sm4算法后写出解密脚本:
import struct
enc_flag = bytes([
0x7D, 0x54, 0xCB, 0xC0, 0x74, 0xDB, 0xF5, 0xD7, 0x6F, 0xD9,
0x92, 0x1B, 0xEB, 0x28, 0x46, 0x20, 0xE5, 0xD5, 0xD3, 0x60,
0x80, 0x6D, 0x36, 0x2F, 0xB0, 0x63, 0x2F, 0x61, 0x20, 0x0F,
0xA9, 0x30])
# init key_r
key_r = [0xE8DB227C, 0x012451B9, 0xED08A9DB, 0xC91F65C3,
0xB3D1E981, 0x319B4734, 0xA4BA5551, 0xD0F2ED2D,
0x4A00D692, 0xE0AEFE30, 0x6BBCDB4A, 0xC315F6F1,
0xB4E1B030, 0x694C4ACE, 0x479208D3, 0x3F8C7B97,
0x747777A6, 0xEDEC9BBB, 0xC8E506C1, 0xB955A92A,
0xB388FDBB, 0x1A4697C3, 0xB10826AA, 0xBB1F2207,
0x291DCD60, 0x2BA3E3A7, 0x1B83DFDD, 0x014D4FD5,
0x80C659F3, 0x3EB45B23, 0x43E36266, 0xBD22532C]
def rol(val, shift):
return ((val << shift) | (val >> (32 - shift))) & 0xFFFFFFFF
def ror(val, shift):
return ((val >> (shift)) | (val << (32 - shift))) & 0xFFFFFFFF
def do_crypt(buf, key_r):
for i in range(32):
v3 = key_r[i] ^ buf[(i + 1) % 4] ^ buf[(i + 2) %
4] ^ buf[(i + 3) % 4]
buf[i % 4] ^= v3 ^ rol(v3, 2) ^ ror(v3, 8) ^ rol(v3, 10) ^ ror(v3, 14)
def encrypt(buf, key_r):
key_r = key_r[:]
tmp = unpack_buf(buf)
ct = []
for k in range(0, 8, 4):
buf = tmp[k:4+k]
do_crypt(buf, key_r)
ct.extend(buf[::-1])
for i in range(4):
key_r[5+i+k] = buf[3-i]
return pack_buf(ct)
def decrypt(buf, key_r):
key_r = key_r[:]
tmp = unpack_buf(buf)
pt = []
for k in range(0, 8, 4):
buf = tmp[k:4+k]
do_crypt(buf, key_r[::-1])
pt.extend(buf[::-1])
temp = tmp[k:4+k][::-1]
for i in range(4):
key_r[5+i+k] = temp[3-i]
return pack_buf(pt)
def unpack_buf(buf):
return list(struct.unpack('<8I', buf))
def pack_buf(buf):
return struct.pack('<8I', *buf)
def check_flag(flag):
return encrypt(flag.encode(), key_r) == enc_flag
# a = encrypt('12345678abcdefghABCDEFGH00000000'.encode(), key_r)
# b = decrypt(a, key_r)
# print(b)
flag = decrypt(enc_flag, key_r)
print('flag:', flag.decode())
# flag: 3b2365b04700b5eac3a5fd0ba21b687f
if check_flag('3b2365b04700b5eac3a5fd0ba21b687f'):
print('牛蛙牛蛙')