此题防护与第三赛季的第10题差不多,加了修改。算法方面就更简单了。
我发现的主要修改在于(不全):一是代码迁移的跳转部分加了一种方法;二是数据地址也是动态计算,并不是以前的ebp寻址。代码解码直接用上次的脚本就能搞定,不过需要稍改下断点,范围。
代码解码后发现似乎前面大部分代码都没有涉及到有关输入的算法,只是在最后部分有计算代码。动态调试了下,果然算法只在最后一部分,上次的AES使用的表依然在,只是没用上。其伪代码如下:
v24 = a1; s13_14 = a2->state[13] + (a2->state[14] << 8); s9_10 = a2->state[9] + (a2->state[10] << 8); s11_12 = (a2->state[12] << 8); LOWORD(s11_12) = a2->state[11] + s11_12; v4 = s11_12; v5 = (s11_12 - s9_10); s15_0 = a2->state[15] + (a2->state[0] << 8); s5_6 = a2->state[6] << 8; LOWORD(s5_6) = a2->state[5] + s5_6; v7 = s5_6; s1_2 = (a2->state[2] << 8); LOWORD(s1_2) = a2->state[1] + s1_2; v26 = s1_2; s3_4 = a2->state[4] << 8; LOWORD(s3_4) = a2->state[3] + s3_4; v27 = s3_4; v10 = (s1_2 ^ s3_4) & 0xFFFF; s7_8 = (a2->state[8] << 8) + a2->state[7]; LOWORD(s3_4) = ((v7 ^ s7_8) & 0x5555) + (((v7 ^ s7_8) >> 1) & 0x5555); v12 = (((s3_4 & 0x3333) + ((s3_4 >> 2) & 0x3333)) & 0xF0F) + ((((s3_4 & 0x3333) + ((s3_4 >> 2) & 0x3333)) >> 4) & 0xF0F); v13 = (v5 & ~v10 | v10 & (s15_0 + s13_14)); v30 = v13 ^ v7; LOWORD(v30) = __ROL2__(v30, HIBYTE(v12) + v12); v14 = (v5 & ~v10 | v10 & (s15_0 + s13_14)); v15 = v14; v25 = __ROL2__(v13 ^ ((a2->state[8] << 8) + a2->state[7]), HIBYTE(v12) + v12); v16 = ((v10 * v13 >> (HIBYTE(v12) + v12)) + 24) + 0x42DA59; v17 = v16; v18 = v16 - 0x42DA59; v19 = v5 ^ (v17 - 0x42DA59); v20 = v14 | v18; v23 = v18 + v4; v22 = v15 & v18; v21 = v22 | (v19 & v20); *&a2->state[10] = v18 + a2->state[9] + (a2->state[10] << 8); *&a2->state[4] = v19 + s15_0; *&a2->state[2] = v26 ^ v21; *&a2->state[12] = v25; *&a2->state[6] = s13_14 - v19; *&a2->state[8] = v23; *a2->state = v27 ^ v21; *&a2->state[14] = v30; *&a2->xbox[220] = v27 ^ v21; *&a2->subkey[2][4] = v30; *&a2->xbox[176] = v22; *&a2->subkey[1][8] = v23; *&a2->subkey[5][12] = v24; check_4FF3DE();
算法用python模拟如下:
serial = '5E2BA658A0E9C5F1B52C4C3C4C5C161C'.decode('hex') #BE1C6CB1F1616083 name = 'BE1C6CB1F1616083' s = struct.unpack('H'*8,serial[1:]+serial[0]) v10 = s[0] ^ s[1] v5 = (s[5] - s[4])&0xffff v13 = (v5 & ~v10 | v10 & (s[7] + s[6])) tmp = ((s[2]^s[3]) & 0x5555) + (((s[2]^s[3]) >> 1) & 0x5555) v12 = ((((tmp & 0x3333) + ((tmp >> 2) & 0x3333)) & 0xF0F) + ((((tmp & 0x3333) + ((tmp >> 2) & 0x3333)) >> 4) & 0xF0F))&0xffff bits = ((v12&0xff) + (v12 >> 8))&0xff v16 = (((v10 * v13) >> bits) + 24) v19 = v5 ^ v16 v20 = v13 | v16 v23 = (v16 + s[5])&0xffff v22 = v13 & v16 v21 = (v22 | (v19 & v20))&0xffff n = [0]*8 n[0] = s[1] ^ v21 n[1] = s[0] ^ v21 n[2] = (v19 + s[7])&0xffff n[3] = (s[6] - v19)&0xffff n[4] = v23 n[5] = (v16 + s[4])&0xffff n[6] = rol(v13^s[3],bits,16) n[7] = rol(v13^s[2],bits,16) nn = struct.pack('H'*8,*n) assert(nn == name)
反算如下:
# -*- coding:utf-8 -*- import struct def rol(num,bit,n): return ((num << (bit%n)) | (num >> (n - bit%n)))&0xffff def crack(): s = [0]*8 name = 'KCTF'+'\x00\x1A\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10' #6CCDE9D2EC1D469DC67C647E66B4C565 n = struct.unpack('H'*8,name) v10 = n[0] ^ n[1] v5 = (n[4] - n[5])&0xffff v13 = (v5 & ~v10 | v10 & (n[2] + n[3])) x = n[6] ^ n[7] bits = 0 for i in range(0x10000): tmp = ((i) & 0x5555) + (((i) >> 1) & 0x5555) v12 = ((((tmp & 0x3333) + ((tmp >> 2) & 0x3333)) & 0xF0F) + ((((tmp & 0x3333) + ((tmp >> 2) & 0x3333)) >> 4) & 0xF0F))&0xffff bits = ((v12&0xff) + (v12 >> 8))&0xff if ((i >>(16- bits%16)) | (i << (bits%16))) & 0xffff == x: break v16 = (((v10 * v13) >> bits) + 24) v19 = v5 ^ v16 v20 = v13 | v16 v22 = v13 & v16 v21 = (v22 | (v19 & v20))&0xffff s[0] = n[1] ^ v21 s[1] = n[0] ^ v21 s[7] = (n[2]-v19)&0xffff s[6] = (v19 + n[3])&0xffff s[5] = (n[4] - v16)&0xffff s[4] = (n[5] - v16)&0xffff s[3] = (((n[6] >> (bits%16))|(n[6]<<(16-bits%16))) ^ v13)&0xffff s[2] = (((n[7] >> (bits%16))|(n[7]<<(16-bits%16))) ^ v13)&0xffff ss = struct.pack('H'*8,*s) ss = ss[15]+ss[:15] serial = ss.encode('hex').upper() test(name,ss) print serial def test(name,serial): # serial = '5E2BA658A0E9C5F1B52C4C3C4C5C161C'.decode('hex') #BE1C6CB1F1616083 # name = 'BE1C6CB1F1616083' s = struct.unpack('H'*8,serial[1:]+serial[0]) v10 = s[0] ^ s[1] v5 = (s[5] - s[4])&0xffff v13 = (v5 & ~v10 | v10 & (s[7] + s[6])) tmp = ((s[2]^s[3]) & 0x5555) + (((s[2]^s[3]) >> 1) & 0x5555) v12 = ((((tmp & 0x3333) + ((tmp >> 2) & 0x3333)) & 0xF0F) + ((((tmp & 0x3333) + ((tmp >> 2) & 0x3333)) >> 4) & 0xF0F))&0xffff bits = ((v12&0xff) + (v12 >> 8))&0xff v16 = (((v10 * v13) >> bits) + 24) v19 = v5 ^ v16 v20 = v13 | v16 v23 = (v16 + s[5])&0xffff v22 = v13 & v16 v21 = (v22 | (v19 & v20))&0xffff n = [0]*8 n[0] = s[1] ^ v21 n[1] = s[0] ^ v21 n[2] = (v19 + s[7])&0xffff n[3] = (s[6] - v19)&0xffff n[4] = v23 n[5] = (v16 + s[4])&0xffff n[6] = rol(v13^s[3],bits,16) n[7] = rol(v13^s[2],bits,16) nn = struct.pack('H'*8,*n) assert(nn == name) def main(): crack() print 'end.' if __name__ == '__main__': main()
[进行中] 看雪20周年庆典12月28日上海举办,LV四级(中级)以上会员免费参与!,同时在校学生免费参加:学生报名链接!