前言

做DASCTF X GFCTF2022十月挑战赛逆向的时候第一次遇到反编译py字节码

趁热打铁学习一下

Py字节码

Python 的字节码是一种类似汇编指令的中间语言,一个 Python 语句会对应若干字节码指令,虚拟机一条一条执行字节码指令,从而完成程序执行。

Python 的 dis 模块支持对 Python 代码进行反汇编, 生成字节码指令。

如何查看python的字节码

方法一:

1
2
3
4
5
6
7
import dis

def main():
hello();
print("Hello, World!")

dis.dis(main)

方法二:

1
2
3
4
5
import dis

s=open('hello.py').read()
co=compile(s,'hello.py','exec')
dis.dis(co)

py字节码的结构

1
源码行号 | 指令在函数中的偏移 | 指令符号 | 指令参数 | 实际参数值

详解

变量

1.CONST

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

示例:

1
2
3
4
5
6
7
 11          52 LOAD_NAME                2 (test)
54 LOAD_CONST 16 ('nice')
56 CALL_FUNCTION 1
58 POP_TOP

-------------------------------------------------------------------
test('nice')

2.局部变量

LOAD_FAST 一般加载局部变量的值,也就是读值,用于计算或者函数调用传参等;

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

示例:

1
2
3
4
5
6
7
61          77 LOAD_FAST                0 (n)
80 LOAD_FAST 3 (p)
83 INPLACE_DIVIDE
84 STORE_FAST 0 (n)

--------------------------------------------------------------------
n = n / p

3.全局变量

LOAD_GLOBAL 用来加载全局变量,包括指定函数名、类名、模块名等全局符号;

STORE_GLOBAL 用来给全局变量赋值;

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import dis

def test():
global str
str = 'idi10t'
print(str)

dis.dis(test)

--------------------------------------------------------------------

5 0 LOAD_CONST 1 ('idi10t')
2 STORE_GLOBAL 0 (str)

6 4 LOAD_GLOBAL 1 (print)
6 LOAD_GLOBAL 0 (str)
8 CALL_FUNCTION 1
10 POP_TOP
12 LOAD_CONST 0 (None)
14 RETURN_VALUE

常用数据类型

list

BUILD_LIST 用于创建一个list结构:

示例:

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

str = [88, 117, 124, 124, 127, 48, 71, 127, 98, 124, 116, 48, 61, 61, 121, 116, 33, 32, 100, 62]

----------------------------------------------------------------------------

3 8 LOAD_CONST 2 (88)
10 LOAD_CONST 3 (117)
12 LOAD_CONST 4 (124)
14 LOAD_CONST 4 (124)
16 LOAD_CONST 5 (127)
18 LOAD_CONST 6 (48)
20 LOAD_CONST 7 (71)
22 LOAD_CONST 5 (127)
24 LOAD_CONST 8 (98)
26 LOAD_CONST 4 (124)
28 LOAD_CONST 9 (116)
30 LOAD_CONST 6 (48)
32 LOAD_CONST 10 (61)
34 LOAD_CONST 10 (61)
36 LOAD_CONST 11 (121)
38 LOAD_CONST 9 (116)
40 LOAD_CONST 12 (33)
42 LOAD_CONST 13 (32)
44 LOAD_CONST 14 (100)
46 LOAD_CONST 15 (62)
48 BUILD_LIST 20
50 STORE_NAME 1 (str)



dict

BUILD_MAP 用于创建一个空的dict;

STORE_NAME 用于初始化dict的内容;

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

str = {'name' : 'id10t'}
str['age'] = 3

---------------------------------------------------------------

1 0 LOAD_CONST 0 ('name')
2 LOAD_CONST 1 ('id10t')
4 BUILD_MAP 1
6 STORE_NAME 0 (str)

2 8 LOAD_CONST 2 (3)
10 LOAD_NAME 0 (str)
12 LOAD_CONST 3 ('age')
14 STORE_SUBSCR
16 LOAD_CONST 4 (None)
18 RETURN_VALUE

循环

while

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

i = 0
while i < 10:
i += 1

---------------------------------------------------

1 0 LOAD_CONST 0 (0)
2 STORE_NAME 0 (i)

2 >> 4 LOAD_NAME 0 (i)
6 LOAD_CONST 1 (10)
8 COMPARE_OP 0 (<)
10 POP_JUMP_IF_FALSE 22

3 12 LOAD_NAME 0 (i)
14 LOAD_CONST 2 (1)
16 INPLACE_ADD
18 STORE_NAME 0 (i)
20 JUMP_ABSOLUTE 4
>> 22 LOAD_CONST 3 (None)
24 RETURN_VALUE

for

示例:

1
2
3
4
5
6
7
8
9
10
11
12
for i in range(8):
-------------------------------------------------------
2 4 LOAD_NAME 1 (range)
6 LOAD_CONST 1 (8)
8 CALL_FUNCTION 1
10 GET_ITER
>> 12 FOR_ITER 38 (to 52)
14 STORE_NAME 2 (i)
...
50 JUMP_ABSOLUTE 12
>> 52 LOAD_CONST 6 (None)

判断

if

POP_JUMP_IF_FALSEJUMP_FORWARD 一般用于分支判断跳转:

· POP_JUMP_IF_FALSE 表示条件结果为 FALSE 就跳转到目标偏移指令

· JUMP_FORWARD 直接跳转到目标偏移指令

示例:

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

i = 0
if i < 5:
print('i < 5')
elif i > 5:
print('i > 5')
else:
print('i = 5')
----------------------------------------------------------

1 0 LOAD_CONST 0 (0)
2 STORE_NAME 0 (i)

2 4 LOAD_NAME 0 (i)
6 LOAD_CONST 1 (5)
8 COMPARE_OP 0 (<)
10 POP_JUMP_IF_FALSE 22

3 12 LOAD_NAME 1 (print)
14 LOAD_CONST 2 ('i < 5')
16 CALL_FUNCTION 1
18 POP_TOP
20 JUMP_FORWARD 26 (to 48)

4 >> 22 LOAD_NAME 0 (i)
24 LOAD_CONST 1 (5)
26 COMPARE_OP 4 (>)
28 POP_JUMP_IF_FALSE 40

5 30 LOAD_NAME 1 (print)
32 LOAD_CONST 3 ('i > 5')
34 CALL_FUNCTION 1
36 POP_TOP
38 JUMP_FORWARD 8 (to 48)

7 >> 40 LOAD_NAME 1 (print)
42 LOAD_CONST 4 ('i = 5')
44 CALL_FUNCTION 1
46 POP_TOP
>> 48 LOAD_CONST 5 (None)
50 RETURN_VALUE