pyc加花指令

VNCTF2022-BabyMaze

pyc相关知识-https://zhuanlan.zhihu.com/p/145811103

pyc混淆-https://blog.csdn.net/weixin_44222568/article/details/111672799

使用uncompyle6发现无法反编译,应该是添加了花指令

先查看字节码

脚本

1
2
3
4
import marshal, dis
f = open("D:\\new\\AD\\game\\vnctf2022\\re\\BabyMaze.pyc", "rb").read()
code = marshal.loads(f[16:]) #这边从16位开始取因为是python3 python2从8位开始取
dis.dis(code)

发现这一段就是花指令

去python的包里面搜索opcode.h,找到对应的字节码

转为十六进制后去010editor修改,去掉即可

但是发现还是不行,这是因为

pyc文件有co_code,所以修改长度之后要修改它

先打印出来长度,然后计算后修改

2030-6=7E8

重新uncompyle6

反编译成功,接下来就是maze图,打印出来之后手打

Pyc字节码阅读-unctf2021-pytrade

得到两个txt文件,一个是py的字节码,一个是输出

对字节码进行分析

https://www.jianshu.com/p/557cfe36f0f0

https://bbs.pediy.com/thread-246683.htm

https://docs.python.org/zh-cn/3/library/dis.html 这是python3的

1
2
0 LOAD_CONST               1 ('XXXXXX')       //This is flag,try to figure it out ! Don't forget to fill it in flag{} !
2 STORE_FAST 0 (flag)

LOAD_CONST加载const变量,比如数值、字符串等,一般用于传给函数参数

STORE_FAST 一般用于保存值到局部变量

这句话意思是

1
flag='XXXXXXXX'

第二段

1
2
3
4
5
4 LOAD_CONST               2 (0) const变量,一般用于传给函数的参数
6 BUILD_LIST 1 创建列表
8 LOAD_CONST 3 (18) const变量 num=[0]*18
10 BINARY_MULTIPLY
12 STORE_FAST 1 (num) 保存值到局部变量中

BINARY_MULTIPLY 是二元运算,即将栈顶的前两个元素取出进行计算,结果压回栈中

BUILD_LIST 创建列表

1
num=[0]*18

第三段

1
2
14 LOAD_CONST               2 (0)
16 STORE_FAST 2 (k)
1
k=0

第四段

1
2
3
4
5
6
7
8
18 LOAD_GLOBAL              0 (range) 加载全局变量
20 LOAD_GLOBAL 1 (len)
22 LOAD_FAST 0 (flag)
24 CALL_FUNCTION 1 调用一个函数,在此之前要先赋值 len(flag)
26 CALL_FUNCTION 1 range(len(flag))
28 GET_ITER 取迭代器
>> 30 FOR_ITER 112 (to 144) 一直到144都是for循环
32 STORE_FAST 3 (i)

LOAD_GLOBAL 用来加载全局变量,包括指定函数名,类名,模块名等全局符号。当和函数搭配时,要注意有CALL_FUNCTION

LOAD_FAST一般加载局部变量的值,也就是读取值,用于计算或者函数调用传参等。这里调用完len之后,要使用其传值,这里传入flag

前半段意思是

1
range(len(flag))

GET_ITER创建迭代器,一般是for循环

FOR_ITER(to 144)表示迭代器一直到144

STORE_FAST 创建局部变量,这里作为for循环的索引

1
for i in range(len(flag)):

第五段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
7          34 LOAD_GLOBAL              2 (ord) 			
36 LOAD_FAST 0 (flag)
38 LOAD_FAST 3 (i)
40 BINARY_SUBSCR 索引运算
42 CALL_FUNCTION 1 ord(flag[i])
44 LOAD_FAST 3 (i)
46 BINARY_ADD +i
48 LOAD_FAST 2 (k)
50 LOAD_CONST 4 (3)
52 BINARY_MODULO //取模运算 k%3
54 LOAD_CONST 5 (1)
56 BINARY_ADD (k%3)+1
58 BINARY_XOR (ord(flag[i])+i)^(k%3+1)
60 LOAD_FAST 1 (num)
62 LOAD_FAST 3 (i)
64 STORE_SUBSCR num[i]

BINARY_SUBSCR下标 访问操作

BINARY_ADD也是二元运算,相加

BINARY_MODULO,二元运算取模

BINARY_XOR二元运算异或

STORE_SUBSCR下标访问操作

1
num[i]= (ord(flag[i]) + i) ^ (k % 3 + 1)

第六段

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
8          66 LOAD_GLOBAL              2 (ord)
68 LOAD_FAST 0 (flag)
70 LOAD_GLOBAL 1 (len)
72 LOAD_FAST 0 (flag)
74 CALL_FUNCTION 1 len(flag)
76 LOAD_FAST 3 (i) len(flag)-i
78 BINARY_SUBTRACT
80 LOAD_CONST 5 (1)
82 BINARY_SUBTRACT 减法 len(flag)-i-1
84 BINARY_SUBSCR 索引运算 flag[len(flag)-i-1]
86 CALL_FUNCTION 1 ord(flag[len(flag)-i-1])
88 LOAD_GLOBAL 1 (len)
90 LOAD_FAST 0 (flag)
92 CALL_FUNCTION 1 len(flag)
94 BINARY_ADD ord(flag[len(flag)-i-1])+len(flag)-i-1
96 LOAD_FAST 3 (i)
98 BINARY_SUBTRACT
100 LOAD_CONST 5 (1)
102 BINARY_SUBTRACT
104 LOAD_FAST 2 (k)
106 LOAD_CONST 4 (3)
108 BINARY_MODULO k%3
110 LOAD_CONST 5 (1)
112 BINARY_ADD k%3+1
114 BINARY_XOR ord(flag[len(flag)-i-1])+(len(flag)-i-1)^(k%3+1)
116 LOAD_FAST 1 (num)
118 LOAD_GLOBAL 1 (len)
120 LOAD_FAST 0 (flag) len(flag)
122 CALL_FUNCTION 1
124 LOAD_FAST 3 (i)
126 BINARY_SUBTRACT len(flag)-i
128 LOAD_CONST 5 (1)
130 BINARY_SUBTRACT len(flag)-i-1
132 STORE_SUBSCR num[len(flag)-i-1]=ord(flag[len(flag)-i-1])+(len(flag)-i-1)^(k%3+1)

BINARY_SUBTRACT二元运算减法

1
num[len(flag)-i-1]=ord(flag[len(flag)-i-1])+(len(flag)-i-1)^(k%3+1)

第七段

1
2
3
4
5
6
9         134 LOAD_FAST                2 (k)
136 LOAD_CONST 5 (1)
138 INPLACE_ADD k++
140 STORE_FAST 2 (k)
142 JUMP_ABSOLUTE 30//循环结束

JUMP_ABSOLUTE绝对跳转,结束循环

INPLACE_ADD 计算结果可以被操作数引用的到,每一个 二元运算,都对应一个inplace 运算

1
k+=1

第八段

1
2
3
4
5
6
10     >>  144 LOAD_GLOBAL              3 (print)
146 LOAD_FAST 1 (num)
148 CALL_FUNCTION 1 print(num)
150 POP_TOP
152 LOAD_CONST 0 (None)
154 RETURN_VALUE
1
print(num)

Easy_Re

python3.9,无法uncompyle6,使用pycdc翻译成字节码

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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
main.pyc (Python 3.9)
[Code]
File Name: main.py
Object Name: <module>
Arg Count: 0
Pos Only Arg Count: 0
KW Only Arg Count: 0
Locals: 0
Stack Size: 4
Flags: 0x00000040 (CO_NOFREE)
[Names]
'base64'
'encode'
'enCodeAgain'
'correct'
'flag'
'print'
'input'
[Var Names]
[Free Vars]
[Cell Vars]
[Constants]
0
None
[Code]
File Name: main.py
Object Name: encode
Arg Count: 1
Pos Only Arg Count: 0
KW Only Arg Count: 0
Locals: 4
Stack Size: 5
Flags: 0x00000043 (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)
[Names]
'chr'
'base64'
'b64encode'
'encode'
[Var Names]
'message'
's'
'i'
'x'
[Free Vars]
[Cell Vars]
[Constants]
None
''
32
16
'utf-8'
[Disassembly]
0 LOAD_CONST 1: ''
2 STORE_FAST 1: s s=''
4 LOAD_FAST 0: message
6 GET_ITER
8 FOR_ITER 32 (to 42) for i in message:
10 STORE_FAST 2: i
12 LOAD_FAST 2: i
14 LOAD_CONST 2: 32
16 BINARY_XOR i^32
18 STORE_FAST 3: x x=i^32
20 LOAD_FAST 3: x
22 LOAD_CONST 3: 16
24 BINARY_ADD x+16
26 STORE_FAST 3: x x=x+16
28 LOAD_FAST 1: s
30 LOAD_GLOBAL 0: chr
32 LOAD_FAST 3: x
34 CALL_FUNCTION 1 chr(x)
36 INPLACE_ADD s+chr(x)
38 STORE_FAST 1: s s=s+chr(x)
40 JUMP_ABSOLUTE 8 循环结束
42 LOAD_GLOBAL 1: base64
44 LOAD_METHOD 2: b64encode base64.b64
46 LOAD_FAST 1: s
48 LOAD_METHOD 3: encode LOAD_METHOD是加载类,CALL调用
50 LOAD_CONST 4: 'utf-8'
52 CALL_METHOD 1
54 CALL_METHOD 1 base64.b64(s.encode('utf-8'))
56 RETURN_VALUE return base64.b64(s.encode('utf-8'))
'encode'
[Code]
File Name: main.py
Object Name: enCodeAgain
Arg Count: 2
Pos Only Arg Count: 0
KW Only Arg Count: 0
Locals: 5
Stack Size: 5
Flags: 0x00000043 (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)
[Names]
'str'
'range'
'len'
[Var Names]
'string'
'space'
's'
'i'
'j'
[Free Vars]
[Cell Vars]
[Constants]
None
''
'utf-8'
0
[Disassembly]
0 LOAD_CONST 1: ''
2 STORE_FAST 2: s s=''
4 LOAD_GLOBAL 0: str
6 LOAD_FAST 0: string
8 LOAD_CONST 2: 'utf-8'
10 CALL_FUNCTION 2//参数个数 str(string,'utf-8')
12 STORE_FAST 0: string string=str(string,'utf-8')
14 LOAD_GLOBAL 1: range
16 LOAD_CONST 3: 0
18 LOAD_FAST 1: space
20 CALL_FUNCTION 2 range(0,space)
22 GET_ITER //创建迭代器
24 FOR_ITER 50 (to 76)
26 STORE_FAST 3: i for i range(0,space):
28 LOAD_GLOBAL 1: range
30 LOAD_FAST 3: i
32 LOAD_GLOBAL 2: len
34 LOAD_FAST 0: string
36 CALL_FUNCTION 1 len(string)
38 LOAD_FAST 1: space
40 CALL_FUNCTION 3
42 GET_ITER
44 FOR_ITER 28 (to 74)
46 STORE_FAST 4: j for j in range(i,len(string),space)
48 LOAD_FAST 4: j
50 LOAD_GLOBAL 2: len
52 LOAD_FAST 0: string
54 CALL_FUNCTION 1 len(string)
56 COMPARE_OP 0 (<) if(j<len(string))
58 POP_JUMP_IF_FALSE 44 跳转
60 LOAD_FAST 2: s
62 LOAD_FAST 0: string
64 LOAD_FAST 4: j
66 BINARY_SUBSCR string[j]
68 INPLACE_ADD
70 STORE_FAST 2: s s+=string[j]
72 JUMP_ABSOLUTE 44 第二个循环
74 JUMP_ABSOLUTE 24 第一个循环
76 LOAD_FAST 2: s
78 RETURN_VALUE return s
'enCodeAgain'
'VxVtd5dKIPjMw9wVb=lR2WVTcPWC2goWoeQ='
''
'Input flag:'
'utf-8'
2
'correct'
'wrong'
[Disassembly]
0 LOAD_CONST 0: 0
2 LOAD_CONST 1: None
4 IMPORT_NAME 0: base64
6 STORE_NAME 0: base64 import base64
8 LOAD_CONST 2: <CODE> encode
10 LOAD_CONST 3: 'encode' //函数
12 MAKE_FUNCTION 0
14 STORE_NAME 1: encode
16 LOAD_CONST 4: <CODE> enCodeAgain
18 LOAD_CONST 5: 'enCodeAgain'
20 MAKE_FUNCTION 0 //第二个函数
22 STORE_NAME 2: enCodeAgain
24 LOAD_CONST 6: 'VxVtd5dKIPjMw9wVb=lR2WVTcPWC2goWoeQ='
26 STORE_NAME 3: correct correct=VxVtd5dKIPjMw9wVb=lR2WVTcPWC2goWoeQ=
28 LOAD_CONST 7: ''
30 STORE_NAME 4: flag flag=''
32 LOAD_NAME 5: print
34 LOAD_CONST 8: 'Input flag:'
36 CALL_FUNCTION 1 print('Int flag:')
38 POP_TOP
40 LOAD_NAME 6: input
42 CALL_FUNCTION 0 input()
44 STORE_NAME 4: flag flag=input()
46 LOAD_NAME 4: flag
48 LOAD_METHOD 1: encode
50 LOAD_CONST 9: 'utf-8'
52 CALL_METHOD 1
54 STORE_NAME 4: flag flag=flag.encode('utf-8')
56 LOAD_NAME 5: print
58 LOAD_NAME 2: enCodeAgain
60 LOAD_NAME 1: encode
62 LOAD_NAME 4: flag
64 CALL_FUNCTION 1
66 LOAD_CONST 10: 2 其中一个参数
68 CALL_FUNCTION 2//两个参数
70 CALL_FUNCTION 1 print(enCodeAgain(encodee(flag),2))
72 POP_TOP 函数栈顶元素出栈
74 LOAD_NAME 2: enCodeAgain
76 LOAD_NAME 1: encode
78 LOAD_NAME 4: flag
80 CALL_FUNCTION 1
82 LOAD_CONST 10: 2
84 CALL_FUNCTION 2 (enCodeAgain(encodee(flag),2))
86 LOAD_NAME 3: correct
88 COMPARE_OP 2 (==) //比较
90 POP_JUMP_IF_FALSE 102 跳转
92 LOAD_NAME 5: print
94 LOAD_CONST 11: 'correct'
96 CALL_FUNCTION 1 print('correct')
98 POP_TOP
100 JUMP_FORWARD 8 (to 110) 结束
102 LOAD_NAME 5: print
104 LOAD_CONST 12: 'wrong'
106 CALL_FUNCTION 1 print('wrong)
108 POP_TOP
110 LOAD_CONST 1: None
112 RETURN_VALUE

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
import base64


def encode(message):
s = ''
for i in message:
x = i ^ 32
x += 16
s += chr(x)
return (base64.b64encode(s.encode('utf-8')))


def enCodeAgain(string, space):
s = ''
string = str(string, 'utf-8')
for i in range(0, space):
for j in range(i, len(string), space):
if j < len(string):
s += string[j]
return s


correct = 'VxVtd5dKIPjMw9wVb=lR2WVTcPWC2goWoeQ='
flag = ''
print('Input flag:')
flag = input()
flag = flag.encode('utf-8')
print(enCodeAgain(encode(flag), 2))
if enCodeAgain(encode(flag), 2) == correct:
print(correct)
else:
print('wrong')