Lua的编译和反编译

背景

无论是unity项目还是unreal的项目,我都使用了lua!!既然用了lua那么打包的时候肯定是离不开Lua的编译和反编译了!

Lua的编译

  • Luac
  • Luajit

以上两种应该是比较常用的了,当然,你可以自定义加密和解密的算法!

Luac

lua的安装在这里就不累述了!

测试使用的lua文件 TestLua.lua

local AAClass = {}
function AAClass:TestFunction(value1)
	print(value1)
end

function AAClass:TestAdd(a, b)
	return a+b
end

local str = "Test!!!"
local obj = AAClass
obj:TestFunction(str)

local numA=10
local numB=50
local res = obj:TestAdd(numA, numB)
print(res)
return

使用指令lua ./TestLua.lua测试一下代码是否正确!

PS Desktop\testLua> lua .\TestLua.lua
Test!!!
60

Luac是对lua进行编译为luac字节码!

luac -o TestLua.bytes .\TestLua.lua

png

编译成功!

使用编译后的字节运行看看!

PS Desktop\testLua> lua .\TestLua.bytes
Test!!!
60

完美!

Luajit

目前unity项目使用的是Luajit所以,这个方案也要看看!

Luajit的环境可以自己下载编译,自行安排,我比较懒,就直接冲unity里把luajit直接考来用就行了!

注意:

unknown luaJIT command or jit.* modules not installed

如果出现上文的报错,把 luajit\src\src\jit 文件放到 luajit.exe 同级目录的 lua 文件夹下。

.
├── lua
│   └── jit
│       ├── bc.lua
│       ├── bcsave.lua
│       ├── dis_arm.lua
│       ├── dis_mips.lua
│       ├── dis_mipsel.lua
│       ├── dis_ppc.lua
│       ├── dis_x64.lua
│       ├── dis_x86.lua
│       ├── dump.lua
│       ├── p.lua
│       ├── v.lua
│       ├── vmdef.lua
│       └── zone.lua
├── lua51.dll
├── lua51.exp
├── lua51.lib
└── luajit.exe

还是上文的TestLua.lua

直接luajit运行一下!

PS Desktop\testLua> .\luajit64\luajit64.exe .\TestLua.lua
Test!!!
60

妥了!开始编译一下

.\luajit64\luajit64.exe -b -g .\TestLua.lua TestLua.jitbytes

png

运行一下字节

PS Desktop\testLua> .\luajit64\luajit64.exe .\TestLua.jitbytes
Test!!!
60

简单比较一下两种编译的结果! png

其他更加详细的ua程序逆向之Luajit文件格式

Lua的反编译

Luac

目前对于luac的反编译普遍使用的是luadec这个工具:

https://github.com/viruscamp/luadec

git clone https://github.com/viruscamp/luadec
cd luadec
git submodule update --init lua-5.1

然后进入vcproj-5.1使用vs打开编译就可以了!

试一下反编译!

PS Desktop\testLua> G:\other_workspace\luadec\vcproj-5.1\Debug\bin\luadec.exe .\TestLua.bytes > .\TestLua_Decode.lua

得到以下的代码!

-- Decompiled using luadec 2.2 rev: 895d923 for Lua 5.1 from https://github.com/viruscamp/luadec
-- Command line: .\TestLua.bytes 

-- params : ...
-- function num : 0
local AAClass = {}
AAClass.TestFunction = function(self, value1)
  -- function num : 0_0
  print(value1)
end

AAClass.TestAdd = function(self, a, b)
  -- function num : 0_1
  return a + b
end

local str = "Test!!!"
local obj = AAClass
obj:TestFunction(str)
local numA = 10
local numB = 50
local res = obj:TestAdd(numA, numB)
print(res)
return 

Luajit

google一下,你会看到很多luajit decompile的内容,但是不少都需要复杂的操作,而已还不是那么直观 [luajit-decomp] (也有可能是我技术不到位,有知道的大佬可以link评论我学习一下)。

我借助了别人的一个工具:https://github.com/zzwlpx/ljd 项目中使用的luajit2.1.0-beta3,工具说明是luajit2.1.0-beta2,但是我对比一下luajit源码中的opcode,没有差异!

由于ljd源码目前仅支持32位的字节码反编译,如果要支持64位,需要改ljdpython代码,暂时我没有时间,写这个文章只是因为我想看看打包后lua文件有没有正确,工程里是有32位的字节文件的!

PS Desktop\testLua> .\luajit32\luajit32.exe -bg .\TestLua.lua TestLua.jitbytes

这里先保留debug信息吧!

将编译好的TestLua.jitbytes移动到ljd目录下执行指令py main.py .\TestLua.jitbytes >.\jitDecode.lua

local AAClass = {
	TestFunction = function (self, value1)
		print(value1)

		return 
	end,
	TestAdd = function (self, a, b)
		return a + b
	end
}
local str = "Test!!!"
local obj = AAClass

obj.TestFunction(obj, str)

local numA = 10
local numB = 50
local res = obj.TestAdd(obj, numA, numB)

print(res)

return 

上面的就是decompile出来的,可读性还是杠杠的! 如果是不带-g的呢?

({
	TestFunction = function (slot0, slot1)
		print(slot1)

		return 
	end,
	TestAdd = function (slot0, slot1, slot2)
		return slot1 + slot2
	end
})["TestFunction"](slot2, slot1)
print(({
	TestFunction = function (slot0, slot1)
		print(slot1)

		return 
	end,
	TestAdd = function (slot0, slot1, slot2)
		return slot1 + slot2
	end
})["TestAdd"](slot2, slot3, 50))

return 

也勉强能接受,毕竟信息少了很多!

最后再放一下我参考的文件!

LuaJIT反编译总结 Lua程序逆向之Luac文件格式分析