Python逆向(五)—— Python字节码解读
一、前言
前些章节我们对python编译、反汇编的原理及相关模块已经做了解读。读者应该初步掌握了通过反汇编获取python程序可读字节码的能力。python逆向或者反汇编的目的就是在没有源码的基础上,通过字节码来理解源代码的运行内容,并且进一步对源码的远行进行调试。因此本次我们尝试对python字节码进行解读。
二、字节码结构
字节码结构如下:
源码行号 | 跳转注释符 | 指令在函数中的偏移 | 指令符号(助记符) | 指令参数 | 实际参数值

上图表示:
- 该字节码指令在源码中对应59行
- 此处是跳转的目的地址
- 82该字节指令的字节码偏移
- 操作指令对应的助记符为LOAD_GLOBAL
- 操作参数为6
- 操作参数对应的实际值为disassemble
三、字节码实战
3.1常量

加载常量只有一行LOAD_CONST,对应源码第1行,字节码偏移地址0字节,常量数组中索引0,实际常量值‘123’
3.2局部变量

加载局部变量a:LOAD_CONST加载常量1,调用STORE_NAME(参数a),并将变量a存储为1
同理加载局部变量b
3.3全局变量

加载全局变量a,与加载局部变量不同的是通过STORE_GLOBAL在存储变量。
3.4数据类型list

先将所有的list元素加载,调用BUILD_LIST方法生成list于内存中,通过STORE_NAME将堆栈中的list存储于局部变量a中
3.5数据类型dict

BUILD_MAP声明字典元素数量,通过两次LOAD_CONST后,调用STORE_MAP生成键值对存于堆栈,最终通过STORE_NAME将堆栈中长度为2的两个键值对最为字典数据类型存储在a中
3.6数学运算

字节码中显示先对局部变量a、b赋值,通过LOAD_NAME加载局部变量,调用加法BINARY_ADD,生成结果存储与堆栈中,使用STORE_NAME将堆栈中的计算结果存储与局部变量c
加减乘除的运算字节码相似,不不再赘述,读者可以自行分析,如下图:

上图中为对a、b做加减乘除的字节码,因为没有存储计算结果,所以每次运算完没有使用STORE_NAME方法存储,解释器默认调用POP_TOP方法将计算结果从堆栈顶部弹出,以保证堆栈平衡。
3.7循环FOR

上图显示一个FOR循环的过程。SETUP_LOOP表明循环开始,参数说明此循环知道字节码偏移28字节的指令结束(也就是28字节开始不是循环)。调用range方法生成generator存于堆栈。FOR_ITER调用堆栈,声明generator作用到字节码偏移位置27字节。从第16字节起到27为generator迭代作用域。其中为一个print函数。
3.8判断IF

以一个简单的IF判断为例,先加载需要比较的常量,调用COMPARE_OP指令对堆栈中两个常量进行比较,将结果存入堆栈。调用POP_JUMP_IF_FALSE指令,判断栈顶值来决定程序运行顺序实现判断功能。
四、参考
本文试图让读者能够通过简单的例子具备阅读字节码的能力,上文只是对字节码的阅读做了简单的讲解,文章难免有疏漏敬请包涵。如果读者对字节码的阅读有更多的解读需求可以前往这里:https://bbs.pediy.com/thread-246683.htm。通过官方文档https://docs.python.org/2/library/dis.html可以对更多的字节码指令了解。
Python逆向(五)—— Python字节码解读的更多相关文章
- python反编译之字节码
如果你曾经写过或者用过 Python,你可能已经习惯了看到 Python 源代码文件:它们的名称以.Py 结尾.你可能还见过另一种类型的文件是 .pyc 结尾的,它们就是 Python "字 ...
- Python的字符串与字节码转换
一张图弄懂python的字符串与字节码转换
- Python 文件编译为字节码的方法
一般情况下 python 不需要手动编译字节码.但是如果不想直接 release 源代码给其他人,将文件编译成字节码,可以实现一定程度的信息隐藏. 1) 使用模块 py_compile 编译一个单文件 ...
- ubuntu下把python脚本转为二进制字节码文件
ubuntu下把python脚本转为二进制字节码文件 听语音 原创 | 浏览:354 | 更新:2017-12-22 14:48 1 2 3 4 5 6 7 分步阅读 自己拥有个几个python脚本文 ...
- python 微信跳一跳和源码解读
刚好周末,想研究一下前阵子很火的微信跳一跳 下面进入正文. 本文适用对象为WIN10系统,安卓用户.目的在于让丝毫没有接触过Python的小伙伴都能成功运行,如果你恰好是这样的对象,那么跟着我开始操作 ...
- Android逆向基础----Dalvik字节码
参考此微博,更多详细内容可以到这里查看 http://blog.csdn.net/dd864140130/article/details/52076515 Dalvik字节码 1.寄存器位32位,64 ...
- python线程threading.Timer源码解读
threading.Timer的作用 官方给的定义是: """Call a function after a specified number of seconds: t ...
- Python基础(五) python装饰器使用
这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 # -*- coding:gbk -*- '''示例1: 最简单的函数,表示调用了两次 ...
- Python学习(五) Python数据类型:列表(重要)
列表: list是一组有序项目的数据结构. 列表是可变类型的数据,列表用[]进行表示,包含了多个以","分隔的项目. list=[] type(list) //<type ' ...
随机推荐
- YII 的SPA 写法
'use strict'; var findToolbar = function () { return document.querySelector('#yii-debug-toolbar'); } ...
- 6.transform?animation?区别?animation-duration【CSS】
1.Transform:它和width.left一样,定义了元素很多静态样式实现变形.旋转.缩放.移位及透视等功能,通过一系列功能的组合我们可以实现很炫酷的静态效果(非动画). 2.Animatio ...
- 微信web开发问题记录
问题一.微信浏览器中无法使用reload重载文档[VUE框架] 问题分析: 微信不支持location.reload()方法,在微信浏览器中会失效 Vue中的路由跳转是类似于ajax局部刷新,因此使用 ...
- JavaScript之循环语句
(1)while语句 while(条件){ 条件为真,进入循环体.出现0 null undefined false其中任意一种情况,条件即为假 循环体 } 案例: var n=0; var count ...
- sqlite移植
编译 # tar xvf sqlite-3.6.16.tar.gz # cd sqlite-3.6.16 # ./configure # ./configure --host=arm-linux -- ...
- instanceof 和isInstance
Java中的instanceof关键字 instanceof是Java的一个二元操作符,和==,>,<是同一类东东.由于它是由字母组成的,所以也是Java的保留关键字.它的作用是测试它左边 ...
- Java中数组的定义,初始化和使用
定义:数组是数据类型相同的,用一个标志符名称封装在一起的一个对象序列或基本类型数据序列(一组相同数据类型元素的集合,并且分配一块连续的内存来存储). 格式:int[] a1(常用) 或者 int a ...
- Replica set 的选举策略之一 (转)
首先介绍一下在replica set里分为三种节点类型: 1 primary 负责client的读写. 2 secondary 作为热备节点,应用Primary的oplog读取的操作日志,和pri ...
- ET·ci — 全自动软件测试调度(持续集成)平台
ET·ci 提供了编译-测试-发布解决方案,包括:自动提取配置库代码进行自动构建, 自动调度静态测试工具(如QAC)进行静态测试,自动调度单元测试工具(如Tessy)开展动态测试,自动 ...
- maven报错找不到依赖
遇到一个巨坑 跑公司的一个项目,拉下来代码,跑不起来.发现maven一直报这个错 was cached in the local repository,resolution will not be r ...