由于工作需求,要反编译一个luajit编译过的文件。百度反编译luajit,得到的信息是目前没有此类成熟的反编译器。所以,如果你用luajit编译了代码,基本上不用担心被别人破解(2015.12)。

虽然没有luaj反编译器,但是不代表反编译不可能。至少,人肉反编译是可以的,哈。因为我只需要反编译一个文件,所以采取人肉的方式,也许是可行的。

首先,在github上面找到了唯一的一个项目是关于反编译luaj的项目,这个作者写了个工具,可以把手头上的代码翻译成可以可以阅读的模式。(在win/linux下可以直接执行他的工具,他的工具用的是AutoIt脚本写的)

通过阅读他的源码,才知道这个工具首先是用luajit的命令行工具,把字节码转换成可读的模式:

luajit -bl test.lua test.txt

翻译的思路,就是根据luajit提供的指令表,把指令翻译成对应的lua源码,例如, 对这句指令 MOV dst var,翻译成 local dst = var

在对luajit指令的翻译过程,最麻烦的是,lua里的function被重新整理,原来是树状结构的(毕竟大家总是会在function里嵌套function),编译后变成线性的。

这个项目的作者没有解决这个问题,反编译出来的内容,是无数个function,而且没有排版,function里的指令也只是单纯的翻译。所以看着翻译后的代码(三千多行),也极是头疼。

但是这是唯一的线索,所以只能硬着头皮做了。在阅读和整理的过程中,我也懂得去luajit的wiki上查找指令的意思,发现这个作者写的工具bug不少,一些比较难理解的地方,一般都是翻译错了,所以还得再过一遍指令。

作者自己也说了,这个项目只是够用他自己的需求而已。

在经过整合代码后,终于人肉地把线性的function列表整理回树状的。事实上这块是有规则可循的,所以写一个工具来转换,肯定是可以的。

当整个结构和代码看似都整理好后,我面临着一个大问题。function里有些变量是上某层function的,怎么去定位这个变量呢,由于这样的变量不少,如果不能定位准确,那可能前功要尽弃。

luajit的命令行工具luajit -bl指令翻译出来的可读字节码并没有包含这层信息。但是文件要执行,必然需要这层信息,也就是说luajit -bl没有翻译完所有信息。

上面提到的那个反编译项目,作者在他的说明里提到了这点,说他也不知道有没有可能解决这个问题。

我在谷歌上,试着再去搜索luajit,翻遍了也没有找到相关的,但是找到了另一个luajit-language-toolkit,这个项目的存在也挺特别,只是单纯地把luajit的一些功能(编译功能)用lua源码重新实现一遍。(作者说,单纯是提供学习)

看着使用方法,感觉好像没有卵用,但是在说明的最后一部分,看到了希望,这个工具除了能像luajit -bl一样外,还可以进一步地,把函数内的全局变量表引用的信息也翻译出来了。

有了这件法宝,接下来我就顺利得反编译出这个源码了(1千多行的代码)

<div class="ds-thread" data-thread-key="Luajit反编译之探索记" data-title="Luajit反编译之探索记" data-url="/log/2016/05/17/the-journey-with-luajit.html"></div>