刷了下手机看已经有人一血了。立马打开电脑开撸。
先看到题目里有sn.txt
,先看了下:原来是新规则,提供了一组用户名及对应序列号,试运行下,是个控制台程序:
Enter your name: B1AC71D22D82EBB1
Enter your sn: 1788bdf0f45ff24515cfb9313f6519039c24c635ee518afc320b915ecdbf1613
Congratulations! You did it!
先静态分析下,主程序代码比较明了:
name = 0; sn = 0; memset(&v7, 0, 0x60u); v8 = 0; v9 = 0; memset(&v11, 0, 0xC4u); v12 = 0; v13 = 0; v3 = time(0); sub_411AD8(v3); print_411A90((int)aEnterYourName); scanf(aS, &name); v4 = strlen(&name) + 1; if ( v4 - 1 < 3 || v4 - 1 > 20 ) { print_411A90((int)aBadName); result = -1; } else { print_411A90((int)aEnterYourSn); scanf(aS, &sn); if ( strlen(&sn) == 64 ) { check_401380((int)&name, v4 - 1, (int)&sn, 64); result = 0; } else { print_411A90((int)aBadSn); result = -1; } } return result;
输入长度限制跳过,直接看check_401380
函数。其伪代码如下,:
if ( name_length >= 3 && name_length <= 20 && sn_length == 64 ) { if ( unhex_401000((_WORD *)sn, 64, (int)&sn_unhex) != 32 || (aes_4010F0((int)&sn_unhex, 32, (int)&sn_de, (int)key_4190D0, 128, 0), rsa_401210((int)&sn_de, 32, (int)m),m[0]) || m[1] != 2 || m[15] ) { print_411A90((int)aBadSn); } else { hash_401190((const void *)name, name_length, (int)&hash); if ( !memcmp(&hash, &m[16], 0x10u) ) print_411A90((int)aCongratulation); } } }
校验的主要流程如下:
AES密钥是常量,RSA的N为256bits,可分解,用户名hash可以直接得到,似乎条件全了,可以由任意用户名求对应的序列号了。
在最后的求解过程中还遇到了点问题,因为rsa计算结果前16字节只校验了三个字节,那不是多解了,而且预设的序列号怎么求呢。想到题目提供的序列号是能过前面的check的,所以直接把它的rsa计算结果的前16字节直接拿来用试试,提交了下还对了。
晚上回来又把hash部分看了下:
signed int __cdecl hash_401190(const void *a1, unsigned int a2, int a3) { char v4; // [esp+8h] [ebp-DCh] int v5; // [esp+18h] [ebp-CCh] char v6; // [esp+1Ch] [ebp-C8h] qmemcpy(&v6, a1, a2); *(int *)((char *)&v5 + a2 + 4) = g_suffix1_41D038; sha256_md5_4010B0((int)&v6, a2 + 4, (int)&v4); v5 = g_suffix2_41D030; sha256_md5_4010B0((int)&v4, 20, a3); return 16; }
解题脚本为:
key = [0x48, 0x0B, 0x62, 0xC3, 0xAC, 0xD6, 0xC8, 0xA3, 0x6B, 0x18, 0xD9, 0xE9, 0x06, 0xCD, 0x90, 0xD2] key = ''.join(map(chr,key)) name = 'KCTF' c = md5(sha512(md5(sha512(name+'DEEDBEEF'.decode('hex')).digest()).digest()+'B979379E'.decode('hex')).digest()).hexdigest() c = (0x00025D343CED2E5A3CD5FE94CEA15700<<128)+int(c,16) n = 0x69823028577465ab3991df045146f91d556dee8870845d8ee1cd3cf77e4a0c39 p = 201522792635114097998567775554303915819 q = 236811285547763449711675622888914229291 e = 65537 d = invert(e,(p-1)*(q-1)) m = powmod(c,d,n) m = hex(m)[2:].rjust(64,'0').decode('hex') ci = AES.new(key,AES.MODE_ECB) flag = ci.encrypt(m).encode('hex').upper() print flag
结果为:6ED8BC1F04D0C360567FB579398265FEEC8B48DC4B804904FEB1AB538C823270
。