0x00 题目分析

根据官方WP复现

关于NepCTF我好像只保存了这一道(

藏密钥的方式确实独特,下次遇到可能就做不出来的那种(

0x01 解

查壳略(Not packed)

直接上IDA

查字符串一眼base64

出去发现在这里被调用

这个函数再出去看到这个

我函数呢?

向上走

看来是没有识别出来

手动设一下函数

这下能识别了

F5粗略看下

这里有个626很可疑

记下位置

动调看看

在这个位置下断,然后点一下就断下了

看来这个值会和点击次数有关

看看57C620这个位置

确实是点一次加一

往下走走到判断(0x272=626)

在jne处改ZF标志位为1

直接跑

随便输点东西

然后会在这一步发现有个fake flag

继续执行会发现输入(输了123)被加密

根据加密结果或者图片或者堆栈信息可以找到一个叫skipjack的加密算法

回到IDA

发现在626判断的下面有一个626626626的判断

继续往下,还能看到一个662266的判断

这个判断之后就很抽象了

找一下这两个判断,然后都输出看看

第一个(0x25599042=626626626)

出真加密flag了

xmxO93Sn8YjfoWqaFS6poLf6n1q7bWrIyXbLAdcSjygWfs/jAVc4leFrTDZYdFoL

第二个(0x0A1AFA=662266)

第二个看不太懂

在一堆sub_405CE5后面夹了一段sub_405A07和一个sub_405CEB

进去看了一下sub_405CEB

有个hWndNewParent

对窗口进行操作的

那估计这么多东西是绘图了(

重新运行程序,在CreateWindowEXA处下断

运行至堆栈窗口出现960和640(初始化窗口位置)

然后都设置为0

然后运行,会发现左上角缺了一块

然后直接跳到上面所述的第二个判断那

运行此段

可以的,很抽象的藏密钥方式

key

NITORI2413

解密一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import base64

FTABLE = (0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,
0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,
0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,
0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,
0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,
0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,
0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,
0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,
0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,
0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,
0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,
0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,
0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,
0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,
0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,
0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,
0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46)


# G işlemi
def g(key, k, w):
g1 = 0xFF & (w >> 8)
g2 = 0xFF & w

g3 = FTABLE[g2 ^ key[(4 * k + 0) % 10]] ^ g1
g4 = FTABLE[g3 ^ key[(4 * k + 1) % 10]] ^ g2
g5 = FTABLE[g4 ^ key[(4 * k + 2) % 10]] ^ g3
g6 = FTABLE[g5 ^ key[(4 * k + 3) % 10]] ^ g4

return ((g5 << 8) + g6)


# G işleminin tersi
def ginv(key, k, w):
g5 = 0xFF & (w >> 8)
g6 = 0xFF & w

g4 = FTABLE[g5 ^ key[(4 * k + 3) % 10]] ^ g6
g3 = FTABLE[g4 ^ key[(4 * k + 2) % 10]] ^ g5
g2 = FTABLE[g3 ^ key[(4 * k + 1) % 10]] ^ g4
g1 = FTABLE[g2 ^ key[(4 * k + 0) % 10]] ^ g3

return ((g1 << 8) + g2)


def skip(key, buf, encrypt):
# Gruplara ayırma
w1 = (buf[0] << 8) + buf[1]
w2 = (buf[2] << 8) + buf[3]
w3 = (buf[4] << 8) + buf[5]
w4 = (buf[6] << 8) + buf[7]

if encrypt:
k, step = 0, 1

for t in range(2):
# A işlemi
for i in range(8):
gw1 = g(key, k, w1)
w1, w2, w3, w4 = gw1 ^ w4 ^ (k + step), gw1, w2, w3
k += step
# B işlemi
for i in range(8):
gw1 = g(key, k, w1)
w1, w2, w3, w4 = w4, gw1, w1 ^ w2 ^ (k + step), w3
k += step

else:
k, step = 32, -1

for t in range(2):
# B^-1
for i in range(8):
gw2 = ginv(key, k + step, w2)
w1, w2, w3, w4 = gw2, gw2 ^ w3 ^ k, w4, w1
k += step
# B
for i in range(8):
w1, w2, w3, w4 = ginv(key, k + step, w2), w3, w4, w1 ^ w2 ^ k
k += step

return bytes((w1 >> 8, w1 & 0xFF, w2 >> 8, w2 & 0xFF,
w3 >> 8, w3 & 0xFF, w4 >> 8, w4 & 0xFF))


class Skipjack:
# Class bir anahtar ile oluşturulur
def __init__(self, key):
if len(key) != 10:
raise ValueError("key must be 10 bytes in length")
else:
self._key = bytearray(key, 'utf-8')

# Şifreleme Fonksiyonu
def encrypt(self, value):
pad = bytearray(8 - len(value)) # 8 karakterden az şifreleme için padding
buf = bytearray(value, 'utf-8') + pad
enc = skip(self._key, buf, True)
print(enc)
return enc

def decrypt(self, value):
pad = bytearray(8 - len(value))
buf = value + pad
dec = skip(self._key, buf, False)
# print(dec)
return dec

# 抄的解密()
enc = 'xmxO93Sn8YjfoWqaFS6poLf6n1q7bWrIyXbLAdcSjygWfs/jAVc4leFrTDZYdFoL'
enc = base64.b64decode(enc)
enc1 = [int.from_bytes(enc[i*8:i*8+8], 'little') for i in range(len(enc)//8)]
enc1 = [bytes(enc[i*8:i*8+8]) for i in range(len(enc)//8)]
# example
CT = 0x33221100ddccbbaa
KEY = [ord(i) for i in "NITORI2413"]
sj = Skipjack("NITORI2413")
for i in enc1:
m = sj.decrypt(i)
print(m.decode(), end='')

# NepCTF{3456789TQKA2,Jack_was_skipped_by_EPL}