Skip to content

Latest commit

 

History

History
99 lines (81 loc) · 4.53 KB

ch03-ChunkSpy使用说明.md

File metadata and controls

99 lines (81 loc) · 4.53 KB

ChunkSpy使用说明

ChunkSpy是一个可以对Lua二进制文件进行反编译拿到对应Opcode的工具,其作者也是文档<<A No-Frills Introduction to Lua 5.1 VM Instructions>>的作者,这篇文档是我阅读Lua代码中参考最多的文档,结合着ChunkSpy工具,可以很好的分析Lua代码对应的Opcode指令,它的下载地址在这里.

简单介绍一下ChunkSpy工具的使用,主要有两种方式,一种是交互式的使用,这种方式下可以进入一个类似shell的命令行中,只要在其中输入正确的Lua代码,马上就能得到相应的Opcode,比如:

>local a=1
; source chunk: (interactive mode)
; x86 standard (32-bit, little endian, doubles)

; function [0] definition (level 1)
; 0 upvalues, 0 params, 2 stacks
.function  0 0 2 2
.local  "a"  ; 0
.const  1  ; 0
[1] loadk      0   0        ; 1
[2] return     0   1      
; end of function

简单介绍一下它的输出格式:

  • 以";"开头的,可以认为是介绍性的信息,或者说是注释.
  • 以"."开头的,比如上面的".function",".local",".const"是不同类型数据的定义,但是这里并不是真正的opcode,它只是写出来让读者明白这里有哪些类型的数据定义.
  • 以"[数字]"开头的,就是真正的opcode,对应FuncState中code中的一条指令,其中的数字是code数组中的索引,具体的格式与每个opcode相关,在每条指令后面可能会带一些以";"开头的注释.

另一种方式是对已经通过luac编译生成的Lua二进制文件进行反编译,同样是可以得到对应的opcode,比如最简单的Lua代码:

local i =1

通过luac编译之后生成luac.out文件,再通过ChunkSpy进行反编译:

lua ChunkSpy.lua  luac.out  my.lua -o test

它将luac.out的十六进制代码进行了反编译,结果如下:

Pos   Hex Data           Description or Code
------------------------------------------------------------------------
0000                     ** source chunk: luac.out
                         ** global header start **
0000  1B4C7561           header signature: "\27Lua"
0004  51                 version (major:minor hex digits)
0005  00                 format (0=official)
0006  01                 endianness (1=little endian)
0007  04                 size of int (bytes)
0008  08                 size of size_t (bytes)
0009  04                 size of Instruction (bytes)
000A  08                 size of number (bytes)
000B  00                 integral (1=integral)
                         * number type: double
                         * x86 standard (32-bit, little endian, doubles)
                         ** global header end **
                         
000C                     ** function [0] definition (level 1)
                         ** start of function **
000C  0800000000000000   string size (8)
0014  406D792E6C756100   "@my.lua\0"
                         source name: @my.lua
001C  00000000           line defined (0)
0020  00000000           last line defined (0)
0024  00                 nups (0)
0025  00                 numparams (0)
0026  02                 is_vararg (2)
0027  02                 maxstacksize (2)
                         * code:
0028  02000000           sizecode (2)
; (1)  local i =1
002C  01000000           [1] loadk      0   0        ; 1
0030  1E008000           [2] return     0   1      
                         * constants:
0034  01000000           sizek (1)
0038  03                 const type 3
0039  000000000000F03F   const [0]: (1)
                         * functions:
0041  00000000           sizep (0)
                         * lines:
0045  02000000           sizelineinfo (2)
                         [pc] (line)
0049  01000000           [1] (1)
004D  01000000           [2] (1)
                         * locals:
0051  01000000           sizelocvars (1)
0055  0200000000000000   string size (2)
005D  6900               "i\0"
                         local [0]: i
005F  01000000             startpc (1)
0063  01000000             endpc   (1)
                         * upvalues:
0067  00000000           sizeupvalues (0)
                         ** end of function **

006B                     ** end of chunk **

如果需要更简洁的输出结果,可以加入--brief参数.

需要说明的是,ChunkSpy在2006年之后就不怎么更新,对现在的64位系统支持可能不够好,如果在执行的时候发现提示如下的报错:

ChunkSpy.lua:1120: mismatch in size_t size (needs 4 but read 8)

那么可以尝试着把代码中两个定义size_size_t的地方由4改为8.