[CISCN 2023 初赛]moveAside
好题...
参考
+
mov混淆 demov首先环境比较难配 然后解混淆效果极差...
硬怼汇编
注意到这里:
这个unk_8057030
提取出来发现很符合flag的格式 xxxx-xxxx-xxxx 这种
所以可以猜测 '-' -> '\' 然后开头结尾的格式flag{}也能确定6个映射
接下来就是神奇的找规律环节
把这7组bin看一下:
0x5c: 0101 1100 0010 1101
0x60: 0110 0000 0110 0001
0x66: 0110 0110 0110 0111
0x67: 0110 0111 0110 0110
0x8a: 1000 1010 0111 1011
0x8c: 1000 1100 0111 1101
0x9d: 1001 1101 0110 1100
可以发现 低4bit是有规律的 bit0取反 bit1,2,3不变
而我们又知道flag字符在hex里取 所以可以枚举看下可能映射关系
for i in range(5,len(enc)-1):
print(f'{i} - {hex(enc[i])} : ',end='')
if(enc[i]==0x5c):
print(f" -")
continue
for c in pos:
x = ord(c)
if(x&0xe==enc[i]&0xe):
if((x&1)!=(enc[i]&1)):
print(f' {c}',end=' ')
print()
再根据已知f,a的映射 化简后得到:
5 - 0x56 : 7
6 - 0x49 : 8
7 - 0x50 : 1
8 - 0x65 : 4 d
9 - 0x65 : 4 d
10 - 0x60 : a
11 - 0x55 : 4 d
12 - 0x64 : 5 e
13 - 0x5c : -
14 - 0x65 : 4 d
15 - 0x48 : 9
16 - 0x50 : 1
17 - 0x51 : 0
18 - 0x5c : -
19 - 0x55 : 4 d
20 - 0x67 : f
21 - 0x51 : 0
22 - 0x57 : 6
23 - 0x5c : -
24 - 0x49 : 8
25 - 0x67 : f
26 - 0x54 : 5 e
27 - 0x63 : 2 b
28 - 0x5c : -
29 - 0x54 : 5 e
30 - 0x62 : 3 c
31 - 0x52 : 3 c
32 - 0x56 : 7
33 - 0x54 : 5 e
34 - 0x54 : 5 e
35 - 0x50 : 1
36 - 0x49 : 8
37 - 0x53 : 2 b
38 - 0x52 : 3 c
39 - 0x52 : 3 c
40 - 0x56 : 7
剩余可能:
4,d
5,e
2,b
3,c
共16种
那么我们写一个爆破程序 利用flag正确会输出yes 否则就没回显这一性质
(或者直接16个可能flag挨个submit 也行)
from pwn import *
enc = [0x67, 0x9D, 0x60, 0x66, 0x8A, 0x56, 0x49, 0x50, 0x65, 0x65, 0x60, 0x55, 0x64, 0x5C, 0x65, 0x48,
0x50, 0x51, 0x5C, 0x55, 0x67, 0x51, 0x57, 0x5C, 0x49, 0x67, 0x54, 0x63, 0x5C, 0x54, 0x62, 0x52,
0x56, 0x54, 0x54, 0x50, 0x49, 0x53, 0x52, 0x52, 0x56, 0x8C]
pos = "0123456789abcdef"
table = [0]*257
table[0x5c] = ord('-') # '\' -> '-'
table[0x67] = ord('f')
table[0x9d] = ord('l')
table[0x60] = ord('a')
table[0x66] = ord('g')
table[0x8a] = ord('{')
table[0x8c] = ord('}')
"""
bit0取反 bit1,2,3不变 高4bit要么全部取反 要么不变
0x5c: 0101 1100 0010 1101
0x60: 0110 0000 0110 0001
0x66: 0110 0110 0110 0111
0x67: 0110 0111 0110 0110
0x8a: 1000 1010 0111 1011
0x8c: 1000 1100 0111 1101
0x9d: 1001 1101 0110 1100
"""
# for i in range(5,len(enc)-1):
# print(f'{i} - {hex(enc[i])} : ',end='')
# if(enc[i]==0x5c):
# print(f" -")
# continue
# for c in pos:
# x = ord(c)
# if(x&0xe==enc[i]&0xe):
# if((x&1)!=(enc[i]&1)):
# print(f' {c}',end=' ')
# print()
table[0x56] = ord('7')
table[0x57] = ord('6')
table[0x49] = ord('8')
table[0x50] = ord('1')
table[0x48] = ord('9')
table[0x51] = ord('0')
for i1 in "4d":
tmp = table
tmp[0x55] = ord(i1)
tmp[0x65] = ord('4')+ord('d')-ord(i1)
for i2 in "5e":
tmp[0x54] = ord(i2)
tmp[0x64] = ord('5')+ord('e')-ord(i2)
for i3 in "2b":
tmp[0x53] = ord(i3)
tmp[0x63] = ord('2')+ord('b')-ord(i3)
for i4 in "3c":
tmp[0x52] = ord(i4)
tmp[0x62] = ord('3')+ord('c')-ord(i4)
flag = ""
for c in enc:
flag += chr(tmp[c])
print(flag)
# exit(0)
proc=process('./moveAside')
proc.sendlineafter(b'flag:\n', flag)
proc.recvline()
res = proc.recv(timeout=0.02)
if b'yes!' in res:
success('\n')
success(flag)
success('\n')
exit(0)
proc.kill()
""" 可能的映射表 结合a,f已知对应 可能情况数是在可爆破范围内的
剩余可能:
4,d
5,e
2,b
3,c
共16种
5 - 0x56 : 7
6 - 0x49 : 8
7 - 0x50 : 1
8 - 0x65 : 4 d
9 - 0x65 : 4 d
10 - 0x60 : a
11 - 0x55 : 4 d
12 - 0x64 : 5 e
13 - 0x5c : -
14 - 0x65 : 4 d
15 - 0x48 : 9
16 - 0x50 : 1
17 - 0x51 : 0
18 - 0x5c : -
19 - 0x55 : 4 d
20 - 0x67 : f
21 - 0x51 : 0
22 - 0x57 : 6
23 - 0x5c : -
24 - 0x49 : 8
25 - 0x67 : f
26 - 0x54 : 5 e
27 - 0x63 : 2 b
28 - 0x5c : -
29 - 0x54 : 5 e
30 - 0x62 : 3 c
31 - 0x52 : 3 c
32 - 0x56 : 7
33 - 0x54 : 5 e
34 - 0x54 : 5 e
35 - 0x50 : 1
36 - 0x49 : 8
37 - 0x53 : 2 b
38 - 0x52 : 3 c
39 - 0x52 : 3 c
40 - 0x56 : 7
"""
flag{781dda4e-d910-4f06-8f5b-5c3755182337}