Git Product home page Git Product logo

luadec's Introduction

Overview

LuaDec is a Lua decompiler for lua 5.1 , and experimental for lua 5.2 and 5.3.

It is based on Hisham Muhammad's luadec which targeted lua 5.0.x and LuaDec51 by Zsolt Sz. Sztupak.

LuaDec is free software and uses the same license as the original LuaDec.

Compiling

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

If you want to build it for lua 5.2 or 5.3 , just replace 5.1 above to 5.2 or 5.3.

There are also project files for vc2008, tested for vc2008 and vc2013.
Before compiling, make sure there are correct sources in lua-5.1 , lua-5.2 or lua-5.3.

Usage

  • decompile lua binary file:
    luadec abc.luac
  • decompile lua source file for testing and comparing:
    luadec abc.lua
  • disassemble lua source or binary
    luadec -dis abc.lua
  • -pn print nested functions structure, could be used by -fn
luadec -pn test.lua
0
  0_0
    0_0_0
  0_1
  • -f decompile only specific nested function
    luadec -f 0_1 test.lua
  • -ns donot process sub functions
    luadec -ns -f 0_1 test.lua
  • -fc perform a instruction-by-instruction compare for each function
    luadec -fc test.lua
    outputs:
    -- function check pass 0
    -- function check fail 0_0 : cannot compile
    -- function check fail 0_1 : different code size; sizecode org: 66, decompiled: 67, same: 47;

There are some more options, usually for debug purposes, or for cases where the built in local guesser guesses wrong. Use -h to get a complete list of usable parameters

Credits

Original by Hisham Muhammad (http://luadec.luaforge.net)

Ongoing port to Lua 5.1 by Zsolt Sz. Sztupak (https://github.com/sztupy/luadec51/)

The internals of Lua5.1 was learned from Kein-Hong Man's A No-Frills Introduction to Lua 5.1 VM Instructions

luadec's People

Contributors

viruscamp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luadec's Issues

local function of using the same local as upvalue

do
    local z=function() return 1 end
end

do
    local function z() return 1 end
end

do
    local z=function() return z end
end

do
    local function z() return z end
end

local z=function() return z end

>local z=function() return z end
; function [0] definition (level 1) 0
; 0 upvalues, 0 params, is_vararg = 2, 2 stacks
.function  0 0 2 2
.local  "z"  ; 0
[1] closure    0   0        ; R0 := closure(function[0]) 0 upvalues
[2] return     0   1        ; return

; function [0] definition (level 2) 0_0
; 0 upvalues, 0 params, is_vararg = 0, 2 stacks
.function  0 0 0 2
.const  "z"  ; 0
[1] getglobal  0   0        ; R0 := z
[2] return     0   2        ; return R0
[3] return     0   1        ; return

local function z() return z end

>local function z() return z end
; function [0] definition (level 1) 0
; 0 upvalues, 0 params, is_vararg = 2, 2 stacks
.function  0 0 2 2
.local  "z"  ; 0
[1] closure    0   0        ; R0 := closure(function[0]) 1 upvalues
[2] move       0   0        ; R0 := R0
[3] return     0   1        ; return

; function [0] definition (level 2) 0_0
; 1 upvalues, 0 params, is_vararg = 0, 2 stacks
.function  1 0 0 2
.upvalue  "z"  ; 0
[1] getupval   0   0        ; R0 := U0 , z
[2] return     0   2        ; return R0
[3] return     0   1        ; return

local z=function() return 1 end
local function z() return 1 end

>local function z() return 1 end
; function [0] definition (level 1) 0
; 0 upvalues, 0 params, is_vararg = 2, 2 stacks
.function  0 0 2 2
.local  "z"  ; 0
[1] closure    0   0        ; R0 := closure(function[0]) 0 upvalues
[2] return     0   1        ; return

; function [0] definition (level 2) 0_0
; 0 upvalues, 0 params, is_vararg = 0, 2 stacks
.function  0 0 0 2
.const  1  ; 0
[1] loadk      0   0        ; R0 := 1
[2] return     0   2        ; return R0
[3] return     0   1        ; return

膜拜大神

看到repo的wiki才发现你是国人,大神!前来膜拜~
能否mail一份联系方式。我们一起交流~

missing a upvalue set nil at start of sub function

local a, b
function f()
    a,b=nil
    return false
end

luadec issue15_fn_upvalue.lua

-- function num : 0
local a, b = nil, nil
f = function()
  -- function num : 0_0 , upvalues : a, b
  a = nil
  return false
end

if-if error

source:

local a,b,c,d,e
if a then
    b()
    if c then
        d()
    end
end
e()

decompiled:

local a, b, c, d, e = nil
if a then
  b()
end
if c then
  d()
end
e()

I get some waring by `make LUAVER=5.2`

I run make LUAVER=5.2, I get some waring, as shown below
I don't know if this will affect luadec normal work
My OS is macOS 10.12.3

╰─➤  make LUAVER=5.2
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o guess.o guess.c
guess.c:216:7: warning: unused variable 'bc' [-Wunused-variable]
                int bc = GETARG_Bx(instr);
                    ^
1 warning generated.
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o luadec.o luadec.c
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o decompile.o decompile.c
decompile.c:168:52: warning: comparison of constant -2147483648 with expression of type 'StatementType' (aka 'enum StatementType_') is always false
      [-Wtautological-constant-out-of-range-compare]
        return ((item->type == match->type)||(match->type == INT_MIN))
                                              ~~~~~~~~~~~ ^  ~~~~~~~
decompile.c:606:8: warning: unused variable 'blockSize' [-Wunused-variable]
                        int blockSize = block->sub->size;
                            ^
decompile.c:591:17: warning: unused variable 'tail' [-Wunused-variable]
                AstStatement* tail = cast(AstStatement*, block->sub->tail);
                              ^
decompile.c:666:8: warning: unused variable 'whileStart' [-Wunused-variable]
                        int whileStart = walk->start;
                            ^
decompile.c:1432:12: warning: enumeration value 'SQUARE_BRACKET' not handled in switch [-Wswitch]
                        switch (type) {
                                ^
decompile.c:1703:24: warning: format specifies type 'unsigned int' but the argument has type 'LoopItem *' (aka 'struct LoopItem_ *') [-Wformat]
                ,stmttype[li->type], li, li->prep, li->start, li->body, li->end, li->out, li->block);
                                     ^~
decompile.c:1703:77: warning: format specifies type 'unsigned int' but the argument has type 'AstStatement *' (aka 'struct AstStatement_ *') [-Wformat]
                ,stmttype[li->type], li, li->prep, li->start, li->body, li->end, li->out, li->block);
                                                                                          ^~~~~~~~~
decompile.c:1836:7: warning: unused variable 'func_check_result' [-Wunused-variable]
                int func_check_result = FunctionCheck(f, funcnumstr, str);
                    ^
decompile.c:2062:12: warning: enumeration value 'iAx' not handled in switch [-Wswitch]
                        switch (getOpMode(o)) {
                                ^
../lua-5.2/src/lopcodes.h:274:22: note: expanded from macro 'getOpMode'
#define getOpMode(m)    (cast(enum OpMode, luaP_opmodes[m] & 3))
                        ^
decompile.c:2211:23: warning: unused variable 'endif' [-Wunused-variable]
                                int thenaddr = 0, endif = 0;
                                                  ^
decompile.c:2614:23: warning: unused variable 'endif' [-Wunused-variable]
                                int thenaddr = 0, endif = 0;
                                                  ^
decompile.c:2755:19: warning: unused variable 'parentStmt' [-Wunused-variable]
                                AstStatement* parentStmt = NULL;
                                              ^
decompile.c:3049:8: warning: unused variable 'cfnum' [-Wunused-variable]
                        int cfnum = functionnum;
                            ^
decompile.c:1792:6: warning: unused variable 'baseIndent' [-Wunused-variable]
        int baseIndent = indent;
            ^
14 warnings generated.
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o disassemble.o disassemble.c
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o proto.o proto.c
proto.c:84:14: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        while (*p++ = toupper(*p));
               ~~~~~^~~~~~~~~~~~~
proto.c:84:14: note: place parentheses around the assignment to silence this warning
        while (*p++ = toupper(*p));
                    ^
               (                 )
proto.c:84:14: note: use '==' to turn this assignment into an equality comparison
        while (*p++ = toupper(*p));
                    ^
                    ==
proto.c:84:11: warning: unsequenced modification and access to 'p' [-Wunsequenced]
        while (*p++ = toupper(*p));
                 ^             ~
2 warnings generated.
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o StringBuffer.o StringBuffer.c
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o structs.o structs.c
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o statement.o statement.c
statement.c:118:50: warning: data argument not used by format string [-Wformat-extra-args]
                StringBuffer_addPrintf(buff, "do break end\n", stmt->code);
                                             ~~~~~~~~~~~~~~~~  ^
statement.c:121:43: warning: data argument not used by format string [-Wformat-extra-args]
                StringBuffer_addPrintf(buff, "break\n", stmt->code);
                                             ~~~~~~~~~  ^
2 warnings generated.
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o macro-array.o macro-array.c
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o expression.o expression.c
gcc -o luadec  guess.o luadec.o decompile.o disassemble.o proto.o StringBuffer.o structs.o statement.o macro-array.o expression.o ../lua-5.2/src/liblua.a -lm 
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o luareplace.o luareplace.c
gcc -o luareplace  luareplace.o ../lua-5.2/src/liblua.a -lm 
../lua-5.2/src/lua ../bin/bin2c.lua ../bin/allopcodes-5.2.lua allopcodes_lua > allopcodes_lua.h
../lua-5.2/src/luac -o allopcodes.luac ../bin/allopcodes-5.2.lua
../lua-5.2/src/lua ../bin/bin2c.lua allopcodes.luac allopcodes_luac > allopcodes_luac.h
gcc -O2 -Wall -DSRCVERSION=\"UNKNOWN\" -I../lua-5.2/src    -c -o luaopswap.o luaopswap.c
luaopswap.c:323:15: warning: initializing 'const char *' with an expression of type 'unsigned char *' converts between pointers to integer types with different sign
      [-Wpointer-sign]
                const char* buff = cmp_gen_lua ? allopcodes_lua : allopcodes_luac;
                            ^      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
gcc -o luaopswap  luaopswap.o ../lua-5.2/src/liblua.a -lm 

A standalone program for lua function replacing

A standalone program for lua function replacing.
创建一个独立程序,用于 lua 函数编译并替换。

Inspired by Co0kieMonster's LuaTool

luareplace dest.lua 0_0 src.lua 0_1 -o output.luac
luareplace -rs dest.lua 0 src.lua 0

direct call function output error

(
function()
    print("abc")
end
)()
;-- must output this
(
function(a)
    print(type(a))
end
)(function()
    print("abe")
end)
;
local a = (function() print(1) end)+1

((function() print(1) end)+(function() print(2) end))()
;
(1+(function() print(1) end)+2)()

Try to compile the decompiled code for each function for comparing

Try to compile the decompiled code for each function for comparing.
This issue is base of #10 , and must be fixed after #12 and #13 .
need to generate sub functions like this:

_fucntion_to_be_compare_ = function(arg0)
  local a = 3
  b = function()
    -- sub function stub
    a = nil -- upvalues
  end
  c = 4
end

编译反编译得到的子函数,用于验证正确性,并准备与原始数据对比。
#10 的前置条件, 此项前置条件包括 #12#13
需生成调用 upvalue 的最简子函数。同样可用于 -ns 选项。

char* ProcessCode(const Proto* f, int indent, int func_checking, char* funcnumstr)
现有 int func_checking 用于指示生成用于再次编译的函数

单独的 OP_JMP 跳到 OP_LOADBOOL 且 sbc=2 时,与 #1 相关

单独的 OP_JMP 跳到 OP_LOADBOOL 且 sbc=2 时,与 #1 相关
在 ProcessCode case:OP_JMP 到下列分支

} else if (sbc == 2 && GET_OPCODE(code[pc+2]) == OP_LOADBOOL) {

测试代码

-- or操作符, 不能用 if 表示, 需要中间变量
function debug_or()
  local f,a,b
  fg = ((not a) or b)
  -- if (a) then x = b else x = true end; fg = x
end

-- and操作符,不能用 if 表示, 需要中间变量
function debug_and_call()
  local f,a,b,c
  fg = ((a<b) and c)
  -- if (a<b) then x = c else x = false end; fg = x
end

-- and操作符,可以用 if 表示,已反编译成 if,正常无视了一条 LOADBOOL
function debug_and_set()
  local f,a,b,c
  f = ((a<b) and c)
  -- if (a<b) then f = c else f = false end;
end

The logic is confused when I compile and decompile this code with lua 5.1.5

The origin code

area = "native"
g = {}
local g = g
local a = function(text)
  textCache = textCache or {}
  local tc = textCache
  if area == "native" then
    if sdk_android and sdk_type == 100 then
      require("texttransform")
      local tt = g.texttransform.s[text]
      if tt then
        return tt
      end
    end
    text = string.gsub(text, "\\n", "\n")
    text = string.gsub(text, "<key:.*>", "")
    return text
  end
  if not g.checkChinese(text) then
    if config.chinese_character_forbid then
      string.gsub(text, "。", ".")
    end
    return text
  end
  local key = string.match(text, "<key:(.*)>") or "nil"
  text = string.gsub(text, "<key:.*>", "")
  if area ~= "native" then
    local tfix = string.gsub(text, " ", "")
    tc[tfix] = tc[tfix] or {}
    if tc[tfix][key] then
      return tc[tfix][key]
    else
      if g.textConfig then
        for i,v in ipairs(g.textConfig) do
          if v.text == tfix then
            local id = v.key or "nil"
            if id == key then
              id = v.id
              local tt = g.getDataTable("textconfig")
              local trans = tt[id] or {}
              trans = trans[config.textconfig_translation_key or "TRANSLATION"]
              trans = trans or text
              if trans == "<nil>" then
                trans = ""
              end
              trans = string.gsub(trans, "\\n", "\n")
              if string.match(trans, "^<注释>") then
                trans = ""
              end
              tc[tfix][key] = trans
              return trans
            end
          end
        end
      end
    end
  end
  return text
end

g.formatText = a

and the decompiled code

-- Decompiled using luadec 2.2 rev: 705713f for Lua 5.1 from https://github.com/viruscamp/luadec
-- Command line: test1.lua

-- params : ...
-- function num : 0
area = "native"
g = {}
local g = g
local a = function(text)
  -- function num : 0_0 , upvalues : g
  if not textCache then
    textCache = {}
  end
  local tc = textCache
  if area == "native" then
    if sdk_android and sdk_type == 100 then
      require("texttransform")
      local tt = ((g.texttransform).s)[text]
      if tt then
        return tt
      end
    end
    do
      text = (string.gsub)(text, "\\n", "\n")
      text = (string.gsub)(text, "<key:.*>", "")
      return text
      if not (g.checkChinese)(text) and config.chinese_character_forbid then
        (string.gsub)(text, "。", ".")
      end
      return text
      local key = (string.match)(text, "<key:(.*)>") or "nil"
      text = (string.gsub)(text, "<key:.*>", "")
      if area ~= "native" then
        local tfix = (string.gsub)(text, " ", "")
        if not tc[tfix] then
          tc[tfix] = {}
        end
        if (tc[tfix])[key] then
          return (tc[tfix])[key]
        else
          if g.textConfig then
            for i,v in ipairs(g.textConfig) do
              if not v.key then
                local id = v.text ~= tfix or "nil"
              end
              if id == key then
                id = v.id
                local tt = (g.getDataTable)("textconfig")
                if not tt[id] then
                  local trans = {}
                end
                trans = trans[config.textconfig_translation_key or "TRANSLATION"]
                if not trans then
                  trans = text
                end
                if trans == "<nil>" then
                  trans = ""
                end
                trans = (string.gsub)(trans, "\\n", "\n")
                if (string.match)(trans, "^<注释>") then
                  trans = ""
                end
                -- DECOMPILER ERROR at PC149: Confused about usage of register: R12 in 'UnsetPending'

                ;
                (tc[tfix])[key] = trans
                return trans
              end
            end
          end
          do
            return text
          end
        end
      end
    end
  end
end

g.formatText = a

remove operand swap when processing EQ LT LE

test case

function lt_const(a,b,c)
    b = a>3
    b = 3<a
    b = not (a<=3)
    b = not (3>=a)
end

function lt_if(a,b,c)
    if a>3 then
        b()
    end
    if not (a<=3) then
        c()
    end
end

function eq_const(a,b,c)
    b = a==3
    b = 3==a
end

bytecode generated by 'luac -s' can't be decompiled.

assume the lua file is testbyte.lua and the code is :

function add(x, y)
    return x + y
end
print (add(3, 4))

first i use luac -s -o testbyte.luac testbyte.lua
then i use luadec testbyte.luac it failed with error

cannot find blockend > 9 , pc = 8, f->sizecode = 9
cannot find blockend > 3 , pc = 2, f->sizecode = 3
-- Decompiled using luadec 2.2 rev: 033cc84 for Lua 5.2 from https://github.com/viruscamp/luadec\
[1]    2129 bus error  ./luadec 

so, am i did something wrong? or how to decompile the ' luac -s' file?
@jeffallen Thanks a lot!

luadec-5.1 fails to compile undefined luaS_new

followinfg the installation instructions for luadec 5.1 on a kali rolling box:

make LUAVER=5.1

gcc -o luadec guess.o luadec.o decompile.o disassemble.o proto.o StringBuffer.o structs.o statement.o macro-array.o expression.o ../lua-5.1/src/liblua.a -lm
guess.o: In function luaU_guess_locals': guess.c:(.text+0x8eb): undefined reference toluaS_new'
luadec.o: In function strip': luadec.c:(.text+0x87): undefined reference toluaS_new'
luadec.c:(.text+0x9c): undefined reference to luaS_new' luadec.o: In functionInject':
luadec.c:(.text+0x30c): undefined reference to luaS_new' luadec.o: In functionmain':
luadec.c:(.text.startup+0xe6): undefined reference to luaL_loadfilex' decompile.o: In functionFixLocalNames':
decompile.c:(.text+0x2637): undefined reference to luaS_new' decompile.c:(.text+0x26c9): undefined reference toluaS_new'
decompile.o: In function ProcessSubFunction': decompile.c:(.text+0x3f21): undefined reference toluaS_new'
decompile.c:(.text+0x4042): undefined reference to luaS_new' decompile.o: In functionProcessCode':
decompile.c:(.text+0x5e37): undefined reference to luaS_new' /usr/bin/ld: luadec: hidden symbolluaS_new' isn't defined
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
Makefile:52: recipe for target 'luadec' failed
make: *** [luadec] Error 1

how to compile for 32 bit cpu

This luadec is a greate library! It works fine.
But I have a question.
my mac is 64 bit, so the binary is x86_64.
i can compile lua for i386, but when set the "-arch i386" flag for luadec/Makefile, it still compile faied.
error: Undefined symbols for architecture x86_64:
could you tell me how to compile for 32 bit cpu? Thanks!

`allopcodes_lua_len` not found?

I cloned this repo on Linux and macOS but both are failed while looking for the symbol allopcodes_lua_len:

luaopswap.c:324:31: error: use of undeclared identifier 'allopcodes_lua_len'; did you mean 'allopcodes_luac_len'?
                int bufflen = cmp_gen_lua ? allopcodes_lua_len : allopcodes_luac_len;
                                            ^~~~~~~~~~~~~~~~~~
                                            allopcodes_luac_len

How could I fix this issue?

print 'function' error when processing multi files

luadec issue4_jmp_loadbool.lua main.lua
affects #7 #9

functionlocal a=nil
end
()

functionlocal b=nil
f(b)
end
()

目前错误 多文件 combine 下 function 后未正常断行
解决方法,函数头, 改成全部自己函数负责,自己函数的 function end 全部由自己输出
影响到 #7 #9

正确处理函数直接调用见 #13

setlist bug

3 [-]: NEWTABLE  R6 16 0      ; R6 := {}
4 [-]: LOADK     R7 K1        ; R7 := "a"
5 [-]: LOADK     R8 K2        ; R8 := "b"
6 [-]: LOADK     R9 K3        ; R9 := "c"
7 [-]: LOADK     R10 K4       ; R10 := "d"
8 [-]: LOADK     R11 K5       ; R11 := "l"
9 [-]: LOADK     R12 K6       ; R12 := "f"

10 [-]: LOADK R13 K7 ; R13 := "g"
11 [-]: LOADK R14 K8 ; R14 := "i"
12 [-]: LOADK R15 K9 ; R15 := "j"
13 [-]: LOADK R16 K10 ; R16 := "k"
14 [-]: LOADK R17 K4 ; R17 := "d"
15 [-]: LOADK R18 K11 ; R18 := "e"
16 [-]: LOADK R19 K12 ; R19 := "z"
17 [-]: LOADK R20 K13 ; R20 := "y"
18 [-]: LOADK R21 K14 ; R21 := "h"
19 [-]: LOADK R22 K15 ; R22 := "x"
20 [-]: SETLIST R6 16 1 ; R6[0] to R6[15] := R7 to R22 ; R(a)[(c-1)*FPF+i] := R(a+i), 1 <= i <= b, a=6, b=16, c=1, FPF=50 --NEWTABLE already close!

use ChunkSpy.lua accur error:ChunkSpy53.lua:1344: bad argument #3 to 'format' (number expected, got nil)

lua ChunkSpy.lua --source test.lua
It show that:

Pos   Hex Data           Description or Code
------------------------------------------------------------------------
0000                     ** source chunk: test1.lua
                         ** global header start **
0000  1B4C7561           header signature: "\27Lua"
0004  53                 version (major:minor hex digits)
0005  00                 format (0=official)
0006  19930D0A1A0A       LUAC_DATA: "\25\147\r\n\26\n"
ChunkSpy: A Lua 5.3 binary chunk disassembler
Version 0.9.9 (20150329)
Copyright (c) 2004-2006 Kein-Hong Man , 2014-2015 VirusCamp
The COPYRIGHT file describes the conditions under which this
software may be distributed (basically a Lua 5-style license.)

* Run with option -h or --help for usage information
ChunkSpy53.lua:1344: bad argument #3 to 'format' (number expected, got nil)

This is test.lua content:

local a
local b = 1
a = b

OS is mac,lua version is 5.3.3

((a and b) or c or d)

see 997e684 #1
line 464 currExp->parent = prevParent;
When I use this line, it outputs ok, but cause a memory leak.
Else, it outputs: if (a and b) or d then

-- Command line: -fc -fn 0_10 E:\cbprojects\luadec\angrybirds_lua\scripts\menus\level_end.lua 
Decompiled_0_10 = function (p)
    local a,b,c,d
    --if (a and b) or d then
    if ((a and b) or c or d) then
        p = 3
    end
end

SETLIST with c==0

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

If C is 0, the next instruction is cast as an integer, and used as the C value.This happens only when operand C is unable to encode the block number,i.e. when C > 511, equivalent to an array index greater than 25550.
如果 C 是 0,下一条指令被转换为整数并用作 C 的值。只有当操作数 C 不能编码块编号时出现该情况,例如当 C > 511 时,等同于数组索引大于25550。

        case OP_SETLIST:
        {
            if (c==0) {
                c = code[pc+1];
                pc++;
            }
            TRY(SetList(F, a, b, c));
            break;
        }

settable to a expression cause errors

--  OP_SETTABLE MakeIndex( DOT )
-- DECOMPILER ERROR: Confused about usage of registers!
;(1+a).f3 = x
-- DECOMPILER ERROR: Confused about usage of registers!
;({2,3,4}+5)[6] =x
-- DECOMPILER ERROR: Overwrote pending register.
;({0,1}).a = x
local y =4 -- need to output last statement with error
-- local y = {0, 1; a = x}

see #17

decompile sub function not output local defines of upvalues all the time

When decompile using -fn ,it is not output local defines of upvalues all the time.
用 -fn 时,函数前的 upvalue 定义不总是出现

not output local defines of upvalues before function define:
应该写的 upvalues 定义没写
luadec -ns -fn 0_0 fn_upvalue.lua

output local defines of upvalues
此处写了,这是 strip 过的函数,有一个猜测 upvalue name 的功能,此时输出到 stdout 了
luadec -ns -fn 0_0 ..\test\compiled\Main.luac

test case for LocVar startpc endpc

for i = 1, 10 do
    local a,b,c,d = i,i+1,i+2;
    print(a);
end
local c=...
local b,a=3,4;
print(a)

for i = 1, 10 do
    local x,y,z
    f[i] = function() x=x+1; print(y); z=i; end
end

do
    local a1 = 0
    print(a1)
end
local b1 = 1

local t = {a,b,c}

local var scope

test local var scope saved in locvars for 5.1 5.2 and 5.3

logic expression

处理逻辑表达式问题
..\test\error_nested_if\logic\logic.lua

Recompile compiled function and compare function proto one by one

Recompile compiled function and compare function proto one by one, must be after #9 .
逐个函数比较功能,应该在 #9 后完成。

目前有
-fc compile decompiled function and compare
int func_check=0; /* compile decompiled function and compare */

int FunctionCheck(const Proto* f, int indent, StringBuffer* str) // 未实现

is_vararg lua 5.1 and lua 5.2 test case, for add function param arg

-- 5.1 main always is_vararg=2
-- 5.2 main always is_vararg=1
local a;

(function()
-- 5.2 don't has arg
    for k,v in ipairs(_G.arg) do
        print(v)
    end
end)()

for k,v in ipairs({...}) do
    print(v)
end

-- 5.2 don't has arg
for k,v in ipairs(arg) do
    print(v)
end

-- is_vararg=0
function f0()
    local x=arg
end

-- 5.1 is_vararg=7
-- 5.2 is_vararg=1
function f1(...)
    local x=arg
end

-- 5.1 is_vararg=3, not use arg, but put arg as param
-- 5.2 is_vararg=1
function f2(...)
    local x=...
end

-- 5.1 is_vararg=3
-- 5.2 is_vararg=1
function f3(...)
    local x=arg
    local y=...
end

-- 5.1 is_vararg=3
-- 5.2 is_vararg=1
function f4(x, ...)
    local x=arg
    local y=...
end

单独的 OP_JMP 跳到 OP_LOADBOOL 时,与 #1 相关

单独的 OP_JMP 跳到 OP_LOADBOOL 时,与 #1 相关
在 ProcessCode case:OP_JMP 到下列分支

processing OP_JMP to } else if (GET_OPCODE(idest) == OP_LOADBOOL) {

基本确认这是错误的处理方法

测试代码

local upv0 = nil
local upv1 = nil
-- 程序反编译出的
DecompiledFunction = function(arg0)
    -- function num : 0_246_0 , upvalues : upv1 , upv2
    if upv0 and (not upv1 or ((upv1 and arg0.bFightState) or IsPlayerExist(arg0.dwID))) then
        return true
    end
    return false
    -- DECOMPILER ERROR: 2 unprocessed JMP targets
end

-- 人工反编译的,字节码相同,已验证
GuessedFunction = function(arg0)
    if upv0 then
        if (not upv1) or (upv1 and arg0.bFightState or IsPlayerExist(arg0.dwID)) then
            return true
        end
    else
        return true
    end
    return false
end

surround () before OP_SETTABLE OP_GETTABLE OP_CALL OP_SELF

-- OP_SETTABLE MakeIndex( DOT )
local x = (1+a).f4
x = ({0,1}).a
x = ({2,3,4}+5)[6]

--  OP_GETTABLE MakeIndex( DOT )
;(1+a).f3 = x
--;({0,1}).a = x
;({2,3,4}+5)[6] =x

-- OP_CALL
_a22_2_a()
a()
a.f3()
;(1+a)(s)
;(function(f) print(type(f)) end)(3)

--OP_SELF MakeIndex( SELF )
a:f() -- decompiled as (a:f)() imported in e4f956c
a:f3() -- decompied as (a:f3)() from long ago
;(2+a):f3()

#13

A standalone program for lua OpCode swap

A standalone program for lua OpCode swap.
创建一个独立程序,用于 lua 操作码替换。

A small lua script that use all OpCode.
一个尽量小的 lua 脚本,用了所有的操作码。

_ENV may not be the first upval

_ENV may not be the first upval in 5.2 and 5.3 , pay attention to it when processing stripped code

local a
local function c()
    a=a+1
    return math.abs(a)
end

upval list from chunkspy

                         * upvalue names:
00E2  02000000           size_upvalue_names (2)
                         upvalue [0]: a
00E6  02000000           string size (2)
00EA  6100               "a\0"
                         upvalue [1]: _ENV
00EC  05000000           string size (5)
00F0  5F454E5600         "_ENV\0"

decompiled:

local a = nil
local c = function()
  -- function num : 0_0 , upvalues : a, _ENV
  a = a + 1
  return (math.abs)(a)
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.