本文所指luajit,皆指luajit2.1.0-beta2版本。

一、背景

逆向apk时,得到luajit字节码文件,将反编译luajit的过程记录如下。

本文主要分析ljd反编译工具源码(https://github.com/NightNord/ljd),并参照feicong的luajit字节码分析一文(https://github.com/feicong/lua_re/blob/master/lua/lua_re3.md),制作Luajit字节码文件格式结构图以直观反映luajit字节码文件格式,并对ljd中存在的bug进行修正,说明使用过程中遇到的问题。

二、反编译luajit字节码前期准备

搜集资料,找到两种解决方案。

方案一

将luajit字节码文件用luajit.exe(luajit -bl luajit-byte-path)反编成操作码文件,然后再将操作码文件解析成可读文件。

用autoit编写,下载下来的有打包好的exe文件,简单测试的话可以按如下操作:

1.下载编译字节码文件对应版本的luajit,可以自己编译,编译好后,将luajit.exe及对应的dll、lib等文件及源码目录下的jit文件夹一同拷贝进luajit-decomp目录。

2.将需要测试的luajit字节码文件拷贝至luajit-decomp目录,并重命名为test.lua

3.双击运行,会生成out.lua文件。

反编译效果如下图:

效果不如人意,对此不做具体分析。

方案二

分析luajit字节码文件,及对应版本的luajit源码,写反编译工具将字节码直接反编译成luajit源码。我们主要分析这种。

过程中主要参照这三篇文章:

三、Ljd源码分析

(1)ljd目录结构说明

(2)ljd函数调用流程分析

画了一张解析时调用流程图:

详细分析如下:

Main函数调用ljd.rawdump.parser.parse函数,如下:

parse会生成state对象实例parser和header对象实例header,然后调用_reader_header方法,并将parser和header传进去,如下图:

_reader_header调用read函数,如下图:

进入_check_magic、_read_vesion、_read_flags、_read_name函数查看的话,能得到magic为3个字节,version为1个字节,flags大小为1个uleb128,而接下来的源码文件名取决于flags里的is_stripped标志位,如果这个标志位是0,代表有字节码包含调试信息,文件中接下来的字节存放的是源码名称,否则不包含调试信息,接下来的字节内容就是prototypes。

_reader_header方法调用完成之后,会调用_read_prototypes函数,如下图:

这个函数会循环读取文件字节到prototype对象,我们来看prototype结构:

可以看到里面包含标志、参数数量及操作指令及大小数量、常量、调试信息,但是没看到整个prototype的大小信息及各个字段的字节大小信息。我们接着往下看ljd.rawdump.prototype.read函数:

这里我们可以看到在解析prototype之前会先读取size,大小为1uleb128,接着会解析prototype内容,同样进入_read_flags、_read_counts_and_sizes、_read_instructions、_read_constants、_read_debuginfo函数内,可以看到,flag为1字节,arguments_count为1字节,Framesize为1字节,upvalues_counts为1字节,complex_constants_count大小为1uleb128,numeric_constants_count大小为1uleb128,instructions_count大小为1uleb128,接下来的字节还是取决于文件头header的flag中的is_stripped标志位,如果is_stripped标志位是0,则接下来的字节存储的是debuginfo_size大小1uleb128,first_line_numb大小1uleb128,lines_count大小1uleb128,如果是1,则没有debuginfo信息。再然后存储的是操作指令instructions,大小取决于解析出来的instructions_count,然后是常量信息constants,大小取决于解析出来的upvalues_count、complex_constants_count、numeric_constants_count,最后,如果解析出来的debuginfo_size大小不为0,则接下来的字节存储的的debuginfo信息,如果debuginfo_size是0,则此prototype结束,然后循环读取下一个prototype。

根据上面的分析,制作下图,以直观反映luajit字节码文件结构:

(3)ljd的bug所在

还是需要看一下解析时的调用流程:

从图中可以很明显的看到,在ljd.rawdump.parser.py中的parser函数中,构造了parser和header对象,然后调用_read_header函数,读取luajit字节码文件的文件头到header对象,接下来调用_read_protoypes函数,并传递parser对象,由ljd.rawdump.prototype中的read负责解析。这是解析luajit字节码的一个宏观过程,我贴一张调试过程中的图,就能明显看到问题所在了,调试1:

调试二:

可以明显看出来_read_header函数解析过的header中的flag值没有被带进_read_protoypes函数,而后面读取debuginfo信息时,是需要根据header中的flag值去判断,这里就出现了bug。因为程序默认是读取的带有调试信息的luajit字节码文件,所以当读取带有调试信息的luajit字节码文件,bug不显,但是当读取不带调试信息的luajit字节码文件时,程序就会解析错误。如下:

错误一:

如果此时认为是编码问题的话,你可能会将编码都调成”Unicode-escape”,但是依然会出错。错误二:

(4)修正ljd的bug

知道bug原因了,就可以直接动手改了。如图:

四、结果

(1)当用LuaJit编译Lua源码时,编译字节码时如果加-g选项,即字节码包含调试信息,反编译时几乎可以完全还原的,还原效果如下图:

(2)编译时不加-g选项,即不带调试信息,反编译时,是解析不出函数体内的本地变量名称的,因为字节码文件中就没有变量名称信息,只知道有变量占位符,所以在反编译解析时,只能按照规则重命名命名本地变量,还原效果如下图:

(3)修正后源码

注意事项:工具使用环境python3+,用法:pythonmani.py “path”

Luajit 源码下载地址:http://luajit.org/download.html  windows下需要用vs控制台编译。

python反编译luac_LuaJIT反编译总结相关推荐

  1. python源代码的后缀名是_Python代码编译与反编译

    众所周知,Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议.那么很自然会有人有这样的疑问:难道Python程序只能以 ...

  2. Python程序编译与反编译

    众所周知,Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议.那么很自然会有人有这样的疑问:难道Python程序只能以 ...

  3. 谈谈Python的编译和反编译

    用Python写脚本,小程序可谓非常方便,但它需要有特定的python环境才能运行,因此如果你想在别的电脑上运行时就会出现许多问题,就算已经安装了Python,但版本可能相差较大,且相关的依赖库没有安 ...

  4. 总结python源文件编译、反编译、加密混淆

    本文更新地址 一.编译 1. 编译为 pyc 2. 编译为 pyo 或者 opt-n.pyc 文件 3. 编译成 pyd 或 so 链接库 编译方法一 编译方法二 编译方法三 使用建议 二.打包 1. ...

  5. python编译和反编译

    结论:从反编译的角度来看,想通过把.py 明文文件编译为.pyc二进制文件的方式,达到对python源码保密的目的是不可行的. 文章目录 1. 文件结构 2. 编译 3. 反编译 4. 总结 1. 文 ...

  6. Java——编译与反编译

    ** 一.基础知识 ** 1.1 编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language)分为低级 ...

  7. Java代码的编译与反编译那些事儿

    GitHub 2.5k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 2.5k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 2.5k Star 的 ...

  8. Java基础04 编译与反编译

    1. 编译 编译: 把所写的高级语言所写作的源代码程序,转换成计算机能直接识别.执行的低级语言的程序,也就是可执行文件. Java语言的编译: Java语言作为一种高级语言,想要被执行就要通过编译将其 ...

  9. vs可以编译python_Python如何进行编译和反编译

    用Python写脚本,小程序可谓非常方便,但它需要有特定的python环境才能运行,因此如果你想在别的电脑上运行时就会出现许多问题,就算已经安装了Python,但版本可能相差较大,且相关的依赖库没有安 ...

最新文章

  1. 使用GDAL创建Erdas格式的金字塔
  2. 高职扩招有计算机专业吗,高职扩招计算机专业
  3. 少儿编程150讲轻松学Scratch(十一)-用Scratch算法给矩形工具填充颜色
  4. 2017.9.5 组合数学 思考记录
  5. thinkphp 相关
  6. vscode-tab按键失效变为切换功能的解决方法
  7. LINUX右键打开方式,如何同时存在多种应用?
  8. VSCode下载安装最新详细教程2022(win10)
  9. 缓解眼睛疲劳,护眼调节色温软件推荐
  10. 指纹识别传感器市场仍将持续上涨
  11. 【c项目】网吧管理系统的设计和实现
  12. 我的互联网创业公司的第一笔收入磨难记
  13. 【节能学院】消防应急疏散指示系统在淞沪路-三门路项目的应用
  14. 8*8点阵贪食蛇,全教程
  15. 火狐浏览器,错误代码:SEC_ERROR_REUSED_ISSUER_AND_SERIAL
  16. Linux - 新建用户教程(新增一个具有root权限的新用户)
  17. 第07篇 部署区块链浏览器(2)
  18. 洛谷P1244青蛙过河
  19. Windows 7 x64 SP1 安装 Windows Edge 浏览器
  20. 地理位置处理---Redis的GeoHash和MySQL的geography类型(之后有空再详细介绍)

热门文章

  1. 资源管理器有共享磁盘但CAD等软件无法访问共享磁盘
  2. 另类万圣节:十三种令程序员们夜不能寐的恐怖噩梦
  3. 使用大华设备开发行AI人流量统计出现时间不正确的原因分析
  4. 三菱FX3uPLC和安邦信变频器通讯程序
  5. 招标文件 服务器参数,深信服超融合平台招标参数.docx
  6. java运行平台的叙述,智慧职教: 以下关于Java运行平台的叙述错误的是( )。
  7. 星光嵌入式SIM800C GPRS GSM开发板发布
  8. asp核酸检测预登记系统源码
  9. 短视频美颜SDK里的祛痘功能是怎么实现的?
  10. 计算机考研专业难度排名,计算机考研难度排行榜!真真不容易