-
-
[原创][看雪.众安 2021 KCTF 秋季赛]第二题 迷失丛林 WP
-
发表于: 2021-11-16 23:36 18009
-
题目是一个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
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏记录
参与人
雪币
留言
时间
一路南寻
为你点赞!
2025-4-19 01:51
飘零丶
为你点赞!
2025-4-3 05:55
東陽不列山
为你点赞!
2025-3-19 01:16
心游尘世外
为你点赞!
2025-3-13 01:35
伟叔叔
为你点赞~
2023-3-18 05:20
PLEBFE
为你点赞~
2022-7-28 00:03
赞赏
他的文章
赞赏
雪币:
留言: