-
-
[原创]KCTF2021第2题通关分析(穷举)
-
发表于: 2021-11-17 14:03 11485
-
分析上述算法,密码为长度32字符串,且字符只能包含0123456789ABCDEF
如:0123456789ABCDEF0123456789ABCDEF
简化后为2个16byte的字节数组
算法1 长度为8字节的数组 byte key1[8] //0123456789ABCDEF 变为{0x10,0x32,0x54,0x76,0x98,0xBA,0xDC,0xFE}
算法2 长度为8字节的数组 byte key2[8] //7923456789ABCDEF 变为{0x97,0x32,0x54,0x76,0x98,0xBA,0xDC,0xFE}
分析后拆分为两个算法
算法1:
密码表为0x100字节,前8位为key1填入
一系列计算后生成一个数组:tmparr[0x100][0x100]
然后遍历0x100次,每次取4个固定索引的值,不为0则计次+1
v21、v22、v23、v23为计次
if (v21 == 0xA9 && v22 == 0xAC && v23 == 0xA7 && v24 > 0xC8u)
{
//成功
}
算法2:
将key2的8个字节,每个字节计算每一位为单数或双数,进而将key1的值++或改为从密码表取
计算后key1的值是字符串"GoodJob~" 则为成功
破解步骤
1、分析算法2逻辑,发现在循环遍历密码表和索引值打乱,拷贝出密码表发现缺少8个字节的密码,判断出密钥在其中且不能重复。
密钥1的8个字节为0x1E,0x28,0x4B,0x6D,0x8C,0xA3,0xD2,0xFB,遂穷举
穷举结果key1为0x4b,0x6d,0x28,0x8c,0xfb,0xd2,0x1e,0xa3
也就是32位序列号前16位为B4D682C8BF2DE13A
算法2分析
修改key2值并调试,发现单个索引只改变单个字节的值,遂穷举key[0]-key[7]
都穷举0-0xff,判断算法后的字符是否相等
穷举后得出结果密钥为0x9d,0x6b,0xea,0x2f,0xa4,0x08,0xbc,0x22
也就是32位序列号后16位为D9B6AEF24A80CB22
拼接key1和key2,得出完整结果B4D682C8BF2DE13AD9B6AEF24A80CB22
for
(size_t i0
=
0
; i0 <
8
; i0
+
+
)
{
g_404000[
0
]
=
key[i0];
for
(size_t i1
=
0
; i1 <
8
; i1
+
+
)
{
g_404000[
1
]
=
key[i1];
for
(size_t i2
=
0
; i2 <
8
; i2
+
+
)
{
g_404000[
2
]
=
key[i2];
for
(size_t i3
=
0
; i3 <
8
; i3
+
+
)
{
g_404000[
3
]
=
key[i3];
for
(size_t i4
=
0
; i4 <
8
; i4
+
+
)
{
g_404000[
4
]
=
key[i4];
for
(size_t i5
=
0
; i5 <
8
; i5
+
+
)
{
g_404000[
5
]
=
key[i5];
for
(size_t i6
=
0
; i6 <
8
; i6
+
+
)
{
g_404000[
6
]
=
key[i6];
for
(size_t i7
=
0
; i7 <
8
; i7
+
+
)
{
g_404000[
7
]
=
key[i7];
bool
isRepeat
=
false;
for
(size_t iii
=
0
; iii <
8
; iii
+
+
)
{
for
(size_t jjj
=
0
; jjj <
8
; jjj
+
+
)
{
if
(iii !
=
jjj && g_404000[iii]
=
=
g_404000[jjj])
{
isRepeat
=
true;
}
}
}
if
(isRepeat)
continue
;
int
nRet
=
sync_1();
/
/
printf(
"nRet[%d]\n"
, nRet);
static
int
aaa
=
0
;
if
(aaa
+
+
%
10000
=
=
0
)
{
printf(
"%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x find\n"
, i0, i1, i2, i3, i4, i5, i6, i7);
}
if
(nRet
=
=
1
)
{
static
int
oknum
=
0
;
/
/
printf(
"%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x ok\n"
, i0, i1, i2, i3, i4, i5, i6, i7);
printf(
"0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x oknum[%d]\n"
, key[i0], key[i1], key[i2], key[i3], key[i4], key[i5], key[i6], key[i7],
+
+
oknum);
}
}
}
}
}
}
}
}
}
for
(size_t i0
=
0
; i0 <
8
; i0
+
+
)
{
g_404000[
0
]
=
key[i0];
for
(size_t i1
=
0
; i1 <
8
; i1
+
+
)
{
g_404000[
1
]
=
key[i1];
for
(size_t i2
=
0
; i2 <
8
; i2
+
+
)
{
g_404000[
2
]
=
key[i2];
for
(size_t i3
=
0
; i3 <
8
; i3
+
+
)
{
g_404000[
3
]
=
key[i3];
for
(size_t i4
=
0
; i4 <
8
; i4
+
+
)
{
g_404000[
4
]
=
key[i4];
for
(size_t i5
=
0
; i5 <
8
; i5
+
+
)
{
g_404000[
5
]
=
key[i5];
for
(size_t i6
=
0
; i6 <
8
; i6
+
+
)
{
g_404000[
6
]
=
key[i6];
for
(size_t i7
=
0
; i7 <
8
; i7
+
+
)
{
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)