-
-
[原创][看雪.众安 2021 KCTF 秋季赛]第二题 迷失丛林 WP
-
发表于: 2021-11-16 23:36 17648
-
题目是一个32位的窗体程序,通过GetDlgItemTextA
函数定位到消息处理函数sub_401270。主要部分伪代码如下:
取得输入后,检查输入长度为32,然后进行unhex操作得到16字节的数据,进入验证。
验证阶段,把处理得到的16字节数据分成前后两个8字节数据,进行两步验证,第一步验证验证前8字节数据(过程只涉及前8字节),后面验证后8字节(过程涉及前8字节参与变换的表)。
仔细研究了下,前后两部分均用到的0x404000处的表大小为256,其前8字节由输入数据处理后的前8字节初始化,且第二步的验证中还有表元素的交换操作,再加上其248个原始值都是唯一的,所以比较确定整个表的256个值原本都是唯一的,也就是说输入变换的前8字节必定表中未出现的8个值,只是需要确定顺序。所以第一部分的输入可以用穷举的方式通过第一步的验证条件来确定。
至于第二部分算法,没看懂。但是明显其算法是单字节进行的,也可以通过单字节爆破的方式来得到结果。
两部分的爆破脚本如下(unhex操作中,高低4bit顺序需要注意):
最后结果为:B4D682C8BF2DE13AD9B6AEF24A80CB22
GetDlgItemTextA(this[
1
],
1000
, String,
40
);
if
( strlen(String)
=
=
32
&& unhex_4014A0((
int
)unhex_input_part1_4041F0, (
int
)String,
32
)
=
=
16
&& (
*
(_DWORD
*
)&table_404000[
4
]
=
unhex_input_part1_4041F0[
1
],
*
(_DWORD
*
)table_404000
=
unhex_input_part1_4041F0[
0
],
check_401580(this, &unhex_input_part2_4041F8) >
0
) )
{
DestroyWindow(this[
1
]);
}
else
{
MessageBoxA(this[
1
], Text, Caption,
0x40u
);
DestroyWindow(this[
1
]);
}
PostQuitMessage(
1
);
GetDlgItemTextA(this[
1
],
1000
, String,
40
);
if
( strlen(String)
=
=
32
&& unhex_4014A0((
int
)unhex_input_part1_4041F0, (
int
)String,
32
)
=
=
16
&& (
*
(_DWORD
*
)&table_404000[
4
]
=
unhex_input_part1_4041F0[
1
],
*
(_DWORD
*
)table_404000
=
unhex_input_part1_4041F0[
0
],
check_401580(this, &unhex_input_part2_4041F8) >
0
) )
{
DestroyWindow(this[
1
]);
}
else
{
MessageBoxA(this[
1
], Text, Caption,
0x40u
);
DestroyWindow(this[
1
]);
}
PostQuitMessage(
1
);
# -*- coding:utf-8 -*-
import
itertools
def
test():
table
=
map
(
ord
,
file
(
'table.bin'
,
'rb'
).read())
dst
=
[
0
]
*
8
a
=
0x21
i
=
0
dst[i]
=
table[i]
for
j
in
range
(
8
):
if
a &
1
:
dst[i]
+
=
1
else
:
dst[i]
=
table[dst[i]]
a >>
=
1
if
i
in
[
0
,
7
]:
dst[i]
-
=
1
print
dst[i]
def
crack_part2():
table
=
map
(
ord
,
file
(
'table.bin'
,
'rb'
).read())
dst
=
[
0
]
*
8
flag
=
'B4D682C8BF2DE13A'
check
=
[
0x47
,
0x6F
,
0x6F
,
0x64
,
0x4A
,
0x6F
,
0x62
,
0x7E
]
for
i
in
range
(
8
):
for
k
in
range
(
256
):
a
=
k
dst[i]
=
table[i]
for
j
in
range
(
8
):
if
a &
1
:
dst[i]
+
=
1
else
:
dst[i]
=
table[dst[i]]
a >>
=
1
if
i
in
[
0
,
7
]:
dst[i]
-
=
1
if
dst[i]
=
=
check[i]:
flag
+
=
'{:02X}'
.
format
(k)[::
-
1
]
break
print
'flag:'
+
flag
print
'flag:'
+
flag
def
crack_table(a1,a2,a3,a4,a5,a6,a7,a8):
byte_40400
=
table
=
map
(
ord
,
file
(
'table_ori.bin'
,
'rb'
).read())
byte_40400[
0
]
=
a1
byte_40400[
1
]
=
a2
byte_40400[
2
]
=
a3
byte_40400[
3
]
=
a4
byte_40400[
4
]
=
a5
byte_40400[
5
]
=
a6
byte_40400[
6
]
=
a7
byte_40400[
7
]
=
a8
i
=
0
dword_404100
=
[
0x00000002
,
0x00000004
,
0x00000008
,
0x00000010
,
0x00000020
,
0x00000040
,
0x00000080
,
0
]
v21
=
0
v22
=
0
v23
=
0
v24
=
0
byte_404220
=
[
0
]
*
512
byte_v25
=
[]
while
i<
256
:
byte_v25.append([
0
]
*
256
)
j
=
0
byte_404220[
0
]
=
byte_40400[i]
byte_404220[
1
]
=
(i
+
1
)
%
256
tt
=
2
v3
=
0
while
j<
7
:
tmp
=
dword_404100[j]
double
=
0
while
tmp:
byte_404220[tt]
=
byte_40400[byte_404220[v3]]
byte_404220[tt
+
1
]
=
(byte_404220[v3]
+
1
)
%
256
tt
+
=
2
v3
+
=
1
tmp
-
=
1
j
+
=
1
for
k
in
range
(
256
):
byte_v25[i][byte_404220[v3]]
+
=
1
v3
+
=
1
i
+
=
1
for
i
in
range
(
256
):
first
=
40
if
byte_v25[i][first
-
40
]:
v21
+
=
1
if
byte_v25[i][first
-
26
]:
v22
+
=
1
if
byte_v25[i][first]:
v23
+
=
1
if
byte_v25[i][first
+
0x27
]:
v24
+
=
1
if
v21
=
=
0xa9
and
v22
=
=
0xac
and
v23
=
=
0xa7
and
v24>
0xc8
:
print
(
"Got"
)
return
True
return
False
def
crack_part1():
t
=
[
0x1e
,
0x28
,
0x4b
,
0x6d
,
0x8c
,
0xa3
,
0xd2
,
0xfb
]
it
=
itertools.permutations(t)
for
i
in
it:
if
crack_table(
*
i):
print
'
'.join(map(lambda x:'
{:
02X
}'.
format
(x)[::
-
1
],i))
break
def
main():
# crack_part1()
crack_part2()
if
__name__
=
=
'__main__'
:
main()
# -*- coding:utf-8 -*-
import
itertools
def
test():
table
=
map
(
ord
,
file
(
'table.bin'
,
'rb'
).read())
dst
=
[
0
]
*
8
a
=
0x21
i
=
0
dst[i]
=
table[i]
for
j
in
range
(
8
):
if
a &
1
:
dst[i]
+
=
1
else
:
dst[i]
=
table[dst[i]]
a >>
=
1
if
i
in
[
0
,
7
]:
dst[i]
-
=
1
print
dst[i]
def
crack_part2():
table
=
map
(
ord
,
file
(
'table.bin'
,
'rb'
).read())
dst
=
[
0
]
*
8
flag
=
'B4D682C8BF2DE13A'
check
=
[
0x47
,
0x6F
,
0x6F
,
0x64
,
0x4A
,
0x6F
,
0x62
,
0x7E
]
for
i
in
range
(
8
):
for
k
in
range
(
256
):
a
=
k
dst[i]
=
table[i]
for
j
in
range
(
8
):
if
a &
1
:
dst[i]
+
=
1
else
:
dst[i]
=
table[dst[i]]
a >>
=
1
if
i
in
[
0
,
7
]:
dst[i]
-
=
1
if
dst[i]
=
=
check[i]:
flag
+
=
'{:02X}'
.
format
(k)[::
-
1
]
break
print
'flag:'
+
flag
print
'flag:'
+
flag
def
crack_table(a1,a2,a3,a4,a5,a6,a7,a8):
byte_40400
=
table
=
map
(
ord
,
file
(
'table_ori.bin'
,
'rb'
).read())
byte_40400[
0
]
=
a1
byte_40400[
1
]
=
a2
byte_40400[
2
]
=
a3
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
看原图
赞赏
雪币:
留言: