lua 怎么反编译

lua 怎么反编译,第1张

1.Lua的虚拟机指令,5.2 的有40条

Lua的指令使用一个32bit的unsigned integer表示。所有指令的定义都在lopcodes.h文件中(可以从Lua 官方网站下

载),使用一个enum OpCode代表指令类型。在lua5.2中,总共有40种指令(id从0到39)。根据指令参数的不同,可以将所有指令分为4

类:

typedef enum {

/*----------------------------------------------------------------------

nameargs description

------------------------------------------------------------------------*/

OP_MOVE,/* A B R(A) := R(B) */

OP_LOADK,/* A Bx R(A) := Kst(Bx) */

OP_LOADKX,/* A R(A) := Kst(extra arg)*/

OP_LOADBOOL,/* A B C R(A) := (Bool)Bif (C) pc++ */

OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil*/

OP_GETUPVAL,/* A B R(A) := UpValue[B]*/

OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */

OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)]*/

OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */

OP_SETUPVAL,/* A B UpValue[B] := R(A)*/

OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C)*/

OP_NEWTABLE,/* A B C R(A) := {} (size = B,C)*/

OP_SELF,/* A B C R(A+1) := R(B)R(A) := R(B)[RK(C)]*/

OP_ADD,/* A B C R(A) := RK(B) + RK(C)*/

OP_SUB,/* A B C R(A) := RK(B) - RK(C)*/

OP_MUL,/* A B C R(A) := RK(B) * RK(C)*/

OP_DIV,/* A B C R(A) := RK(B) / RK(C)*/

OP_MOD,/* A B C R(A) := RK(B) % RK(C)*/

OP_POW,/* A B C R(A) := RK(B) ^ RK(C)*/

OP_UNM,/* A B R(A) := -R(B) */

OP_NOT,/* A B R(A) := not R(B)*/

OP_LEN,/* A B R(A) := length of R(B)*/

OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */

OP_JMP,/* A sBx pc+=sBxif (A) close all upvalues >= R(A) + 1 */

OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++*/

OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++*/

OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++*/

OP_TEST,/* A C if not (R(A) <=>C) then pc++ */

OP_TESTSET,/* A B C if (R(B) <=>C) then R(A) := R(B) else pc++ */

OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */

OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1))*/

OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */

OP_FORLOOP,/* A sBx R(A)+=R(A+2)

if R(A) <?= R(A+1) then { pc+=sBxR(A+3)=R(A) }*/

OP_FORPREP,/* A sBx R(A)-=R(A+2)pc+=sBx*/

OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)) */

OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1)pc += sBx }*/

OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */

OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */

OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg*/

OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */

} OpCode

**********************************************************

虚拟机指令(2) MOVE &LOAD

OP_MOVE A B

OP_MOVE用来将寄存器B中的值拷贝到寄存器A中,由于Lua是基于寄存器虚拟机,大部分的指令都是直接对寄存器进行 *** 作,而不需要对数据进行压栈和d栈。OP_MOVE 指令的作用 是将一个Local变量复制给另一个local变量.

例子:

local a = 10

local b = a

编译出来的结果

1 [1] LOAD0 11代表的是常量表的项,这里代表的是10

2 [2] MOVE1 0

所代表的二进制为

B AOP_Code

Load0 1 = 100000000 000000000 00000000 000001 = 0x80000001 ,

也就是说, 0x80000001 的二进制所代表的指令为 Load 0 1,这里B中的最高位为1,表示的B为常量表的序号,而不是寄存器

MOVE 1 0 = 000000000 000000000 00000001 000000 = 0x40

*****************华丽分割线***********************************************

1.lua 的二进制格式,官方的luac.exe 编译出来的格式

原始的lua 脚本为

local a = 10

local b = a

print(b)

下面介绍格式文件,介绍每个字段的意思.当然啦,这种格式是官方的,各个游戏公司可能会做一些改动,但是万变不离其宗。个个字段已经用颜色标明了

在lua 的源文件中,前面四个字节 1b 4c 75 61 也就是 \033Lua , 标识的是lua文件的特有的标示符数据格式,代表是lua

#define LUA_SIGNATURE "\033Lua" 033时八进制 = 0x1b ,很多那些反编译工具判断这四个字节的值,来判断是否能反编译,很多公司都会偷偷的去掉或者用其他的值来替换,以迷惑菜鸟。呵呵

52 第五个字节,表示的是,当前lua 的目标版本,这里指的是5.2 版本。

感觉编辑的好痛苦,我还是直接贴我的比较图算了,看起来比较舒服

函数的头描述

linedefined =00 00 00 00 ;函数定义开始处的行号

linedefined =00 00 00 00 函数定义结束处的行号 顶级函数开始和结束行号都是为00

numparams =00 固定参数的数目 number of fixed parameters

is_vararg =01;可变参数标识符

• 1=VARARG_HASARG

• 2=VARARG_ISVARARG

• 4=VARARG_NEEDSARG

maxstacksize = 03 ;调用函数所需要的堆栈空间指令段

sizecode = 06 00 00 00 函数中 指令的数目,缓存区的大小 = sizecode * sizeof(Instruction),每四个字节为一条指令

code = 02 00 00 00 41 00 00 00 87 40 40 00 c1 00 80 00 a0 40 00 01 1e 00 80 00

常量列表 保存着函数中引用的常量的列表 (常量池)

Constant.sizek= 02 00 00 00;常量列表的大小 ,缓存区的大小 = Constant.sizek * sizeof(TValue) = 2 * 8 = 16,每项为8个字节,

TValue * = 03 00 00 .

00 00 00 00 24 40 04 06 00 00 00 70 72 69 6e 74 ....$@.....print

Constant list 数据结构 保存着函数中引用的常量的列表 (常量池)

Integer 常量列表的大小 (sizek)

[

1 byte 常量类型 (value in parentheses): • 0=LUA_TNIL, 1=LUA_TBOOLEAN,• 3=LUA_TNUMBER, 4=LUA_TSTRING

Const 常量本身: 如果常量类型是0这个域不存在;如果类型是1,这个是0或1;如果类型是3这个域是 Number;如果类型是4 这个域是String。

]

这里的String 是包含"0"为结束的字符串

为什么上传图片以后,图片都变小了,而且不清晰呢?

***********************给大家发一点福利,矫正虚拟机指令的函数**************************************

//矫正虚拟机指令

DWORD Rectify(DWORD Source)

{

DWORD Instruction = Source

BYTE Source_OpCode = Instruction &0x3F

switch(Source_OpCode)

{

case OP_MOVE:

Source_OpCode = Target_OpCode

break

...

}

Instruction = ((Instruction &0xFFFFFFC0) | Source_OpCode)

return Instruction

}

标准的lua4.01 有“CFLuaDC”工具可以反编译。

标准的lua5 有 “DisLua”、“luadec” 两个工具可供选用。

--------以上三个工具在网上可搜索下载。

luajit 编译的luac 文件 尚无反编译工具。

对于使用原版的lua 所生成的脚本,都有相应的反编译器,你花点功夫搜索,网上一定能找到的。

lua4----CFLuaDC

lua5----DisLua 、luadec


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/8050619.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-13
下一篇 2023-04-13

发表评论

登录后才能评论

评论列表(0条)

保存