2020 网鼎杯(青龙组) jocker

拿到程序,拖入IDA进行反编译,我们可以获取到一些基本的信息

1.png

我们可以得到flag的长度为24,同时点击对应的encrypt可以发现跳到的是一个地址,我们可以断定是一个SMC程序,程序将我们的输入保存了两份,第一份用来判断是否是假的flag,第二部分用于真正的加密,同时判断是否与flag加密后相同

我们可以利用一个SMC解密脚本进行手动解密来进行静态分析,而不是动态调试来进行解密

1
2
3
4
5
6
7
8
9
10
11
12
13
import idc
def aPatch(start,end,key):
n=0
while(start+n!=end+1):
addr=start+n
idc.patch_byte(addr,idc.get_wide_byte(addr)^key)
n+=1
print("%d Byte has been changed"%n)

codeStart=0x401500
codeLen=187
xorData=0x41
aPatch(codeStart,codeStart+codeLen-1,xorData)

我们观察wrong函数,也就是一个简单的加密

2.png

十分简单的我们便可以写出逆过程

1
2
3
4
5
6
7
8
9
10
11
12
13
enc = [0x000066, 0x00006B, 0x000063, 0x000064, 0x00007F, 0x000061, 0x000067, 0x000064, 0x00003B, 0x000056, 0x00006B, 0x000061, 0x00007B, 0x000026, 0x00003B, 0x000050, 0x000063, 0x00005F, 0x00004D, 0x00005A, 0x000071, 0x00000C, 0x000037, 0x000066]
def de1(a):
for i in range(24):
if i&1 !=0 :
a[i] += i
else:
a[i]^=i

de1(enc)
for i in range(len(enc)):
print(chr(enc[i]),end='')

# flag{fak3_alw35_sp_me!!}

明显的看出来这个就是一个Fake Flag,我们观察下面的函数

3.png

同样的是一个异或,但是执行这个脚本我们会发现少了后面的5Flag,此时我们有下面的一个函数:

4.png

可以发现这个函数比较的难看,我们已知flag最后一位必定为},我们猜测最后一个加密与前面相同,同样是异或,经过简单的尝试后,发现没有问题…

于是我们便可以得到如下脚本对完整的flag进行解密

1
2
3
4
5
6
7
8
9
10
11
enc2 = [0x0000000E, 0x0000000D, 0x00000009, 0x00000006, 0x00000013, 0x00000005, 0x00000058, 0x00000056, 0x0000003E, 0x00000006, 0x0000000C, 0x0000003C, 0x0000001F, 0x00000057, 0x00000014, 0x0000006B, 0x00000057, 0x00000059, 0x0000000D]
xor_data ="hahahaha_do_you_find_me?"
for i in range(19):
print(chr(enc2[i]^ord(xor_data[i])),end='')

enc3 ="%tp&:"
xor_data2 = ord(enc3[-1])^ord('}')
for i in range(len(enc3)):
print(chr(ord(enc3[i])^xor_data2),end='')

# flag{d07abccf8a410cb37a}

2020 网鼎杯(青龙组) jocker
https://equinox-shame.github.io/2022/08/15/2020 网鼎杯(青龙组) jocker/
作者
梓曰
发布于
2022年8月15日
许可协议