-
-
[原创]看雪.京东 2018CTF-第七题分析
-
发表于: 2018-6-29 18:25 2702
-
int check() { signed int v0; // ebx signed int index; // esi signed int i; // eax int v3; // eax char *v4; // ecx signed int v5; // edi char *pkey3CharBuf; // eax int v7; // esi int v8; // ecx int v9; // ecx int v10; // ecx signed int v11; // eax char *v13; // [esp+Ch] [ebp-258h] int cnt; // [esp+10h] [ebp-254h] int v15; // [esp+14h] [ebp-250h] char key3CharBuf[3]; // [esp+18h] [ebp-24Ch] int v17; // [esp+1Ch] [ebp-248h] char inputIndexKey[20][16]; // [esp+20h] [ebp-244h] char table[256]; // [esp+160h] [ebp-104h] v0 = 0; *(_DWORD *)table = 65793; *(_DWORD *)&table[4] = 0; *(_DWORD *)&table[8] = 0; *(_DWORD *)&table[12] = 0; *(_DWORD *)&table[16] = 16777217; *(_DWORD *)&table[20] = 1; *(_DWORD *)&table[24] = 0; *(_DWORD *)&table[28] = 0; *(_DWORD *)&table[32] = 1; *(_DWORD *)&table[36] = 65792; *(_DWORD *)&table[40] = 0; *(_DWORD *)&table[44] = 0; *(_DWORD *)&table[48] = 256; *(_DWORD *)&table[52] = 16777472; *(_DWORD *)&table[56] = 0; *(_DWORD *)&table[60] = 0; *(_DWORD *)&table[64] = 256; *(_DWORD *)&table[68] = 65537; *(_DWORD *)&table[72] = 0; *(_DWORD *)&table[76] = 0; *(_DWORD *)&table[80] = 16842752; *(_DWORD *)&table[84] = 0; *(_DWORD *)&table[88] = 1; *(_DWORD *)&table[92] = 0; *(_DWORD *)&table[96] = 0x10000; *(_DWORD *)&table[100] = 1; *(_DWORD *)&table[104] = 256; *(_DWORD *)&table[108] = 0; *(_DWORD *)&table[112] = 0x1000000; *(_DWORD *)&table[116] = 0x1000000; *(_DWORD *)&table[120] = 0x10000; *(_DWORD *)&table[124] = 0; *(_DWORD *)&table[128] = 0; *(_DWORD *)&table[132] = 256; *(_DWORD *)&table[136] = 1; *(_DWORD *)&table[140] = 1; *(_DWORD *)&table[144] = 0; *(_DWORD *)&table[148] = 0x10000; *(_DWORD *)&table[152] = 0x1000000; *(_DWORD *)&table[156] = 256; *(_DWORD *)&table[160] = 0; *(_DWORD *)&table[164] = 0x1000000; *(_DWORD *)&table[168] = 0; *(_DWORD *)&table[172] = 257; *(_DWORD *)&table[176] = 0; *(_DWORD *)&table[180] = 0; *(_DWORD *)&table[184] = 16777472; *(_DWORD *)&table[188] = 0x10000; *(_DWORD *)&table[192] = 0; *(_DWORD *)&table[196] = 0; *(_DWORD *)&table[200] = 65537; *(_DWORD *)&table[204] = 0x10000; *(_DWORD *)&table[208] = 0; *(_DWORD *)&table[212] = 0; *(_DWORD *)&table[216] = 65792; *(_DWORD *)&table[220] = 0x1000000; *(_DWORD *)&table[224] = 0; *(_DWORD *)&table[228] = 0; *(_DWORD *)&table[232] = 0x1000000; *(_DWORD *)&table[236] = 16777217; *(_DWORD *)&table[240] = 0; *(_DWORD *)&table[244] = 0; *(_DWORD *)&table[248] = 0; *(_DWORD *)&table[252] = 16843008; index = 0; do { for ( i = 0; ; ++i ) { if ( i >= 64 ) { printf("input error\n"); system("PAUSE"); exit(-1); } if ( byte_40DA68[i] == (unsigned __int8)g_inputKey[index] ) break; } inputIndexKey[0][index++] = i; } while ( index < 16 ); printf("\n"); v3 = 0x10; v17 = 0x10; v15 = 2 - (_DWORD)inputIndexKey[1]; do { v4 = (char *)inputIndexKey + v3; v13 = (char *)inputIndexKey + v3; v5 = 0; do { pkey3CharBuf = key3CharBuf; v7 = (int)&v4[v15]; cnt = 4; do { v8 = (v7 - 2) % 16; if ( table[v5 + v8] ) *pkey3CharBuf++ = *((_BYTE *)&cnt + v8 + v17); v9 = (v7 - 1) % 16; if ( table[v5 + v9] ) *pkey3CharBuf++ = *((_BYTE *)&cnt + v9 + v17); if ( table[v5 + v7 % 16] ) *pkey3CharBuf++ = *((_BYTE *)&cnt + v7 % 16 + v17); v10 = (v7 + 1) % 16; if ( table[v5 + v10] ) *pkey3CharBuf++ = *((_BYTE *)&cnt + v10 + v17); v7 += 4; --cnt; } while ( cnt ); *v13 = byte_40FEF0[64 * ((unsigned __int8)key3CharBuf[1] + ((unsigned __int8)key3CharBuf[0] << 6)) + (unsigned __int8)key3CharBuf[2]]; v5 += 16; v4 = v13++ + 1; } while ( v5 < 0x100 ); v15 -= 16; v3 = v17 + 16; v17 = v3; } while ( v3 < 320 ); v11 = 0; do { if ( (unsigned __int8)inputIndexKey[0x13][v11] != byte_40FEE0[v11] ) return printf("serial error\n"); ++v11; } while ( v11 < 16 ); do printf("%c", (unsigned __int8)byte_40DA68[(unsigned int)(unsigned __int8)inputIndexKey[9][v0++] >> 1]); while ( v0 < 16 ); return printf("\n"); }
1、初始化了一个16*16的数组 table:
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
2、从"abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"查找输入kjey,并替换成对应字符所在的位置索引。
2、从"abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"查找输入kjey,并替换成对应字符所在的位置索引。
可以把输入16个字符变换后的数据比作16把钥匙,并将其存储在第0层房间inputIndexKey[0]中。而最内层循环的作用是根据变量索引index,获取与下层index相关的本层的三把钥匙,而本层具体三把钥匙与下层相关是由前面定义的talbe(16*16)来决定的。观察talbe,可以看到当前层的16把钥匙中的有且仅有3把钥匙与下层的某个钥匙相关。通过最内层循环索引
talbe后得到3把钥匙,放到key3CharBuf[中],而下层的钥匙数值value为:
value = key3CharBuf[0]*64*64 + key3CharBuf [1]*64 + key3CharBuf[0]。然后索引g_constKey[64][64][64]常量表, 因此取索引对应的数值作为下层相应的钥匙。 g_constKey存储的数据范围为:(0~63)。6、中间层循环使index数值从0 开始依次循环16次,从而获得下层的所有16把钥匙,才可以到最外层循环,进入到下一层。需要注意的是:当进行索引第i把钥匙,首先要确定索引 table的位置,即为table[i][i]开始,比如:
value = key3CharBuf[0]*64*64 +
key3CharBuf [1]*64 +
key3CharBuf[0]。然后索引g_constKey[64][64][64]常量表, 因此取索引对应的数值作为下层相应的钥匙。 g_constKey存储的数据范围为:(0~63)。
value = key3CharBuf[0]*64*64 +
key3CharBuf [1]*64 +
key3CharBuf[0]。然后索引g_constKey[64][64][64]常量表, 因此取索引对应的数值作为下层相应的钥匙。 g_constKey存储的数据范围为:(0~63)。
6、中间层循环
使index数值从0 开始依次循环16次,从而获得下层的所有16把钥匙,才可以到最外层循环,进入到下一层。需要注意的是:
当进行索引第i把钥匙,首先要确定索引
table的位置,即为table[i][i]开始,比如:
索引第0把钥匙,则取 table[0][0] ~ table[0][15]索引第1把钥匙,则取 table[1][1] ~table[1][15]、 table[1][0]
索引第0把钥匙,则取
table[0][0] ~
table[0][15]
索引第1把钥匙,则取 table[1][1] ~table[1][15]、
table[1][0]
通过分析中间层循环不难得出下一层钥匙与本次钥匙的关系,假如当前层是a,其16把钥匙为 a0-a15, 下一层为b,其16把钥匙为b0-b15:
b0 = g_constKey[ a0*64*64 + a1*64 + a2] b1 = g_constKey[ a3*64*64 + a4*64 + a0] b2 = g_constKey[ a5*64*64 + a6*64 + a0] b3 = g_constKey[ a5*64*64 + a7*64 + a1] b4 = g_constKey[ a4*64*64 + a6*64 + a1] b5 = g_constKey[ a8*64*64 + a2*64 + a3] b6 = g_constKey[ a9*64*64 + a8*64 + a4] b7 = g_constKey[ a7*64*64 + a10*64 + a3] b8 = g_constKey[ a8*64*64 + a12*64 + a5] b9 = g_constKey[ a11*64*64 + a13*64 + a6] b10 = g_constKey[ a12*64*64 + a13*64 + a7] b11 = g_constKey[ a11*64*64 + a14*64 + a9] b12 = g_constKey[ a14*64*64 + a8*64 + a10] b13 = g_constKey[ a15*64*64 + a9*64 + a10] b14 = g_constKey[ a15*64*64 + a11*64 + a12] b15 = g_constKey[ a15*64*64 + a13*64 + a14]
7、最外层循环获得下层所有钥匙后,就可以开启下层的门锁,从而进入下一层,依次循环一共循环20次。8、第20次循环的钥匙即: inputIndexKey [19]与全局变量byte_40DA68[16]必须相等,如果不同则返回失败,如果相同,则输入第9层相关信息,成功。二、算法分析现在我们需要做的是,根据最后一层的钥匙,来逆推前一层的钥匙,一直到第0层,从而拿到key。可以利用本层与下层的钥匙关系,进行暴力穷举,是可以获得最原始的初始钥匙,获得key大概需要4个小时。下面是个优化的算法,大概需要3-5分钟获得原始钥匙。已知本层所有钥匙,来获得上一层的所有钥匙:存在16把钥匙,就是存在16个方程,通过遍历 g_constKey 表,可知每个方程共有4096个解。假定本层第0把钥匙对应的上层3把钥匙a0, a1,a2确定,则可知本层第1、2、3、4、5、6把钥匙都分别有64个解。然后再以第1把钥匙为基础,遍历其64中可能,通过各钥匙之间的关系,可知其中每一种可能都可以锁定剩余11把钥匙的可能性。以次为基础,开始依次遍历校验,先获取16把钥匙每把的可能4096个解,然后循环4096*64次即可碰撞出上一层所有钥匙。#include "stdafx.h" #include <windows.h> extern char g_constKey[0x40000]; extern unsigned char g_indexKey[0x100]; typedef struct { unsigned char x; unsigned char y; unsigned char z; }result; typedef struct nextRest{ unsigned char m; unsigned char n; }nextRest; typedef struct nextRestInfo{ int count; nextRest result[640]; }nextRestInfo; typedef struct { //0--a0,a1,a2 //1--a3,a4,a0 result r[16][40960]; }allResult; unsigned char arm[16] = { 0x14, 0x22, 0x1E, 0x10, 0x38, 0x30, 0x18, 0x10, 0x04, 0x1A, 0x24, 0x08, 0x02, 0x26, 0x38, 0x2A }; char srt[] = "abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; unsigned char newArm[16]; nextRestInfo nr56; nextRestInfo nr34; nextRestInfo nr57; nextRestInfo nr46; nextRestInfo nr83; nextRestInfo nr94; allResult allr; bool getmnResult(nextRestInfo* nr, unsigned char a, int index, int xyz) { int count = 0; for (int i = 0; i < 4096; i++) { if (1 == xyz) { if (allr.r[index][i].x == a) { nr->result[count].m = allr.r[index][i].y; nr->result[count].n = allr.r[index][i].z; if (count < 64) count++; else { printf("ERROR: count > 64"); return false; } } } if (2 == xyz) { if (allr.r[index][i].y == a) { nr->result[count].m = allr.r[index][i].x; nr->result[count].n = allr.r[index][i].z; if (count < 64) count++; else { printf("ERROR: count > 64"); return false; } } } if (3 == xyz) { if (allr.r[index][i].z == a) { nr->result[count].m = allr.r[index][i].x; nr->result[count].n = allr.r[index][i].y; if (count < 64) { count++; } else { printf("ERROR: count > 64"); return false; } } } } return true; } unsigned char geta7Bya5(unsigned char a5) { for (int i = 0; i < 64; i++) { if (nr57.result[i].m == a5) return nr57.result[i].n; } return 0xff; } unsigned char geta4Bya6(unsigned char a6) { for (int i = 0; i < 64; i++) { if (nr46.result[i].n == a6) return nr46.result[i].m; } return 0xff; } unsigned char geta3Bya4(unsigned char a4) { for (int i = 0; i < 64; i++) { if (nr34.result[i].n== a4) return nr34.result[i].m; } return 0xff; } unsigned char geta8Bya3(unsigned char a3) { for (int i = 0; i < 64; i++) { if (nr83.result[i].n == a3) return nr34.result[i].m; } return 0xff; } unsigned char geta9Bya4(unsigned char a4) { for (int i = 0; i < 64; i++) { if (nr94.result[i].n == a4) return nr94.result[i].m; } return 0xff; } unsigned char geta10Bya7a3() { for (int i = 0; i < 4096; i++) { if (allr.r[7][i].x == newArm[7] && allr.r[7][i].z == newArm[3]) return allr.r[7][i].y; } return 0xff; } unsigned char geta12Bya8a5() { for (int i = 0; i < 4096; i++) { if (allr.r[8][i].x == newArm[8] && allr.r[8][i].z == newArm[5]) return allr.r[8][i].y; } return 0xff; } unsigned char geta13Bya11a6() { for (int i = 0; i < 4096; i++) { if (allr.r[9][i].x == newArm[11] && allr.r[9][i].z == newArm[6]) return allr.r[9][i].y; } return 0xff; } unsigned char geta14Bya8a10() { for (int i = 0; i < 4096; i++) { if (allr.r[12][i].y == newArm[8] && allr.r[12][i].z == newArm[10]) return allr.r[12][i].x; } return 0xff; } unsigned char geta11Bya14a9() { for (int i = 0; i < 4096; i++) { if (allr.r[11][i].y == newArm[14] && allr.r[11][i].z == newArm[9]) return allr.r[11][i].x; } return 0xff; } unsigned char geta15Bya9a10() { for (int i = 0; i < 4096; i++) { if (allr.r[13][i].y == newArm[9] && allr.r[13][i].z == newArm[10]) return allr.r[13][i].x; } return 0xff; } int _tmain(int argc, _TCHAR* argv[]) { int count = 0; unsigned char block = 0; unsigned char hh = 0; unsigned char ll = 0; int binggo = 0; printf("开始遍历: \r\n"); for (int loop = 0; loop < 19; loop++) { //获取16组解 for (int k = 0; k <16 ; k++) { int count = 0; for (int i = 0; i < 0x40000; i++) { if (g_constKey[i] == arm[k]) { block = i / (64 * 64); hh = (i % (64 * 64)) / 64; ll = i - block*(4 * 16 * 64) - 64 * hh; allr.r[k][count].x = block; allr.r[k][count].y = hh; allr.r[k][count].z = ll; count++; } } } for (int indexa1a2a3 = 0; indexa1a2a3 < 4096; indexa1a2a3++) { newArm[0] = allr.r[0][indexa1a2a3].x; newArm[1] = allr.r[0][indexa1a2a3].y; newArm[2] = allr.r[0][indexa1a2a3].z; //根据a0获得a3,a4可能解集合 //m=x,n=y getmnResult(&nr34, newArm[0],1,3); getmnResult(&nr56, newArm[0],2,3); getmnResult(&nr57, newArm[1],3,3); getmnResult(&nr46, newArm[1],4,3); getmnResult(&nr83, newArm[2],5,2); getmnResult(&nr94, newArm[2],6,2); for (int mnIndex = 0; mnIndex < 64; mnIndex++) { newArm[5] = nr56.result[mnIndex].m; newArm[6] = nr56.result[mnIndex].n; newArm[7] = geta7Bya5(newArm[5]); newArm[4] = geta4Bya6(newArm[6]); newArm[3] = geta3Bya4(newArm[4]); newArm[8] = geta8Bya3(newArm[3]); newArm[9] = geta9Bya4(newArm[4]); newArm[10] = geta10Bya7a3(); newArm[12] = geta12Bya8a5(); newArm[14] = geta14Bya8a10(); newArm[11] = geta11Bya14a9(); newArm[13] = geta13Bya11a6(); newArm[15] = geta15Bya9a10(); if (g_constKey[64 * 64 * newArm[0] + 64 * newArm[1] + newArm[2]] != arm[0])continue; if (g_constKey[64 * 64 * newArm[3] + 64 * newArm[4] + newArm[0]] != arm[1])continue; if (g_constKey[64 * 64 * newArm[5] + 64 * newArm[6] + newArm[0]] != arm[2])continue; if (g_constKey[64 * 64 * newArm[5] + 64 * newArm[7] + newArm[1]] != arm[3])continue; if (g_constKey[64 * 64 * newArm[4] + 64 * newArm[6] + newArm[1]] != arm[4])continue; if (g_constKey[64 * 64 * newArm[8] + 64 * newArm[2] + newArm[3]] != arm[5])continue; if (g_constKey[64 * 64 * newArm[9] + 64 * newArm[2] + newArm[4]] != arm[6])continue; if (g_constKey[64 * 64 * newArm[7] + 64 * newArm[10] + newArm[3]] != arm[7])continue; if (g_constKey[64 * 64 * newArm[8] + 64 * newArm[12] + newArm[5]] != arm[8])continue; if (g_constKey[64 * 64 * newArm[11] + 64 * newArm[13] + newArm[6]] != arm[9])continue; if (g_constKey[64 * 64 * newArm[12] + 64 * newArm[13] + newArm[7]] != arm[10])continue; if (g_constKey[64 * 64 * newArm[11] + 64 * newArm[14] + newArm[9]] != arm[11])continue; if (g_constKey[64 * 64 * newArm[14] + 64 * newArm[8] + newArm[10]] != arm[12])continue; if (g_constKey[64 * 64 * newArm[15] + 64 * newArm[9] + newArm[10]] != arm[13]) continue; if (g_constKey[64 * 64 * newArm[15] + 64 * newArm[11] + newArm[12]] != arm[14]) continue; if (g_constKey[64 * 64 * newArm[15] + 64 * newArm[13] + newArm[14]] != arm[15]) continue; //获得结果 binggo++; printf("倒数第%2d轮: ", 19-loop); for (int c = 0; c < 16; c++) printf("0x%02x ", newArm[c]); printf("\r\n"); memcpy(arm, newArm, 16); break; } } } printf("\n遍历完成:sn = "); for (int i = 0; i < 16; i++) { arm[i] = srt[arm[i]]; printf("%c", arm[i]); } return 0; }运行结果如下:开始遍历: 倒数第19轮: 0x0f 0x0b 0x07 0x0b 0x35 0x03 0x19 0x1f 0x0b 0x31 0x3b 0x33 0x03 0x07 0x15 0x37 倒数第18轮: 0x3a 0x26 0x00 0x3a 0x34 0x06 0x2c 0x3c 0x0e 0x1e 0x0a 0x26 0x24 0x18 0x3c 0x18 倒数第17轮: 0x0f 0x07 0x0d 0x15 0x23 0x3f 0x3f 0x19 0x11 0x0d 0x03 0x25 0x37 0x3b 0x19 0x31 倒数第16轮: 0x0c 0x36 0x16 0x06 0x06 0x26 0x04 0x2e 0x0c 0x0c 0x3a 0x10 0x10 0x16 0x36 0x22 倒数第15轮: 0x0f 0x1f 0x33 0x0d 0x2b 0x2b 0x19 0x19 0x3f 0x33 0x35 0x2d 0x27 0x1b 0x11 0x07 倒数第14轮: 0x3a 0x12 0x3c 0x0e 0x2c 0x3c 0x2e 0x08 0x1e 0x22 0x3c 0x12 0x26 0x18 0x0e 0x0e 倒数第13轮: 0x19 0x2f 0x03 0x29 0x15 0x03 0x11 0x29 0x15 0x3f 0x33 0x09 0x1f 0x1d 0x23 0x33 倒数第12轮: 0x38 0x1e 0x38 0x2a 0x0e 0x16 0x1e 0x2a 0x16 0x2c 0x1a 0x1e 0x3e 0x10 0x08 0x28 倒数第11轮: 0x27 0x3d 0x25 0x3f 0x2d 0x29 0x19 0x21 0x27 0x39 0x33 0x05 0x17 0x13 0x0d 0x15 倒数第10轮: 0x30 0x1c 0x28 0x22 0x24 0x08 0x22 0x10 0x00 0x16 0x10 0x24 0x0c 0x1c 0x1c 0x06 倒数第 9轮: 0x25 0x05 0x1f 0x2d 0x27 0x33 0x19 0x0b 0x01 0x0d 0x21 0x31 0x15 0x31 0x3b 0x17 倒数第 8轮: 0x16 0x2e 0x36 0x10 0x08 0x28 0x02 0x20 0x06 0x00 0x28 0x0e 0x14 0x0a 0x04 0x22 倒数第 7轮: 0x35 0x2d 0x31 0x17 0x3b 0x1d 0x29 0x03 0x21 0x0b 0x0b 0x3f 0x05 0x31 0x11 0x1d 倒数第 6轮: 0x3e 0x0a 0x2a 0x02 0x2a 0x08 0x24 0x1e 0x1e 0x3a 0x38 0x1e 0x2c 0x2a 0x1c 0x3c 倒数第 5轮: 0x13 0x01 0x27 0x39 0x2f 0x25 0x1b 0x09 0x2d 0x13 0x11 0x1d 0x31 0x0b 0x37 0x17 倒数第 4轮: 0x2e 0x22 0x24 0x0e 0x2a 0x36 0x00 0x0e 0x34 0x2a 0x32 0x00 0x14 0x20 0x14 0x08 倒数第 3轮: 0x21 0x1f 0x17 0x03 0x27 0x2b 0x29 0x01 0x15 0x1f 0x1b 0x05 0x25 0x39 0x35 0x23 倒数第 2轮: 0x20 0x30 0x32 0x16 0x32 0x12 0x06 0x32 0x3c 0x1a 0x16 0x18 0x30 0x22 0x24 0x1e 倒数第 1轮: 0x11 0x2b 0x21 0x05 0x3f 0x01 0x25 0x0b 0x39 0x13 0x33 0x09 0x3f 0x39 0x35 0x25 遍历完成:sn = rPFf9bJl3tXj93ZJsn 为 “rPFf9bJl3tXj93ZJ”
通过分析中间层循环不难得出下一层钥匙与本次钥匙的关系,假如当前层是a,其16把钥匙为 a0-a15, 下一层为b,其16把钥匙为b0-b15:
b0 = g_constKey[ a0*64*64 + a1*64 + a2] b1 = g_constKey[ a3*64*64 + a4*64 + a0] b2 = g_constKey[ a5*64*64 + a6*64 + a0] b3 = g_constKey[ a5*64*64 + a7*64 + a1] b4 = g_constKey[ a4*64*64 + a6*64 + a1] b5 = g_constKey[ a8*64*64 + a2*64 + a3] b6 = g_constKey[ a9*64*64 + a8*64 + a4] b7 = g_constKey[ a7*64*64 + a10*64 + a3] b8 = g_constKey[ a8*64*64 + a12*64 + a5] b9 = g_constKey[ a11*64*64 + a13*64 + a6] b10 = g_constKey[ a12*64*64 + a13*64 + a7] b11 = g_constKey[ a11*64*64 + a14*64 + a9] b12 = g_constKey[ a14*64*64 + a8*64 + a10] b13 = g_constKey[ a15*64*64 + a9*64 + a10] b14 = g_constKey[ a15*64*64 + a11*64 + a12] b15 = g_constKey[ a15*64*64 + a13*64 + a14]
7、最外层循环
获得下层所有钥匙后,就可以开启下层的门锁,从而进入下一层,依次循环一共循环20次。
8、第20次循环的钥匙即:
inputIndexKey
[19]与全局变量byte_40DA68[16]必须相等,如果不同则返回失败,如果相同,则输入第9层相关信息,成功。
二、算法分析
现在我们需要做的是,根据最后一层的钥匙,来逆推前一层的钥匙,一直到第0层,从而拿到key。可以利用本层与下层的钥匙关系,进行暴力穷举,是可以获得最原始的初始钥匙,获得key大概需要4个小时。下面是个优化的算法,大概需要3-5分钟获得原始钥匙。
已知本层所有钥匙,来获得上一层的所有钥匙:
存在16把钥匙,就是存在16个方程,通过遍历
g_constKey 表,可知每个方程共有4096个解。假定本层第0把钥匙对应的上层3把钥匙a0, a1,a2确定,则可知本层第1、2、3、4、5、6把钥匙都分别有64个解。然后再以第1把钥匙为基础,遍历其64中可能,通过各钥匙之间的关系,可知其中每一种可能都可以锁定剩余11把钥匙的可能性。以次为基础,开始依次遍历校验,先获取16把钥匙每把的可能4096个解,然后循环4096*64次即可碰撞出上一层所有钥匙。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2018-6-30 14:04
被oooAooo编辑
,原因:
赞赏
他的文章
- 看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本 5669
- [原创]看雪CTF2019Q3第四题WP 5934
- [原创]看雪CTF2019Q3 第二题WP 6760
- [2019看雪CTF晋级赛Q3第九题WP 12491
- [原创]看雪CTF2019晋级赛Q2第三题 5022
看原图
赞赏
雪币:
留言: