前言
做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_FALSE 和 JUMP_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
|