-
-
[原创]看雪.京东 2018CTF-第七题分析
-
发表于: 2018-6-29 18:25 2825
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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, |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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:
12345678910111213141516b0 = 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次即可碰撞出上一层所有钥匙。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280#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;
}
运行结果如下:
12345678910111213141516171819202122开始遍历:
倒数第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 = rPFf9bJl3tXj93ZJ
sn 为 “rPFf9bJl3tXj93ZJ”
通过分析中间层循环不难得出下一层钥匙与本次钥匙的关系,假如当前层是a,其16把钥匙为 a0-a15, 下一层为b,其16把钥匙为b0-b15:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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次即可碰撞出上一层所有钥匙。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2018-6-30 14:04
被oooAooo编辑
,原因:
赞赏
他的文章
- 看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本 5864
- [原创]看雪CTF2019Q3第四题WP 6132
- [原创]看雪CTF2019Q3 第二题WP 7037
- [2019看雪CTF晋级赛Q3第九题WP 12775
- [原创]看雪CTF2019晋级赛Q2第三题 5198
赞赏
雪币:
留言: