
LuaJit分析系列
文章平均质量分 75
2019年研究luajit加固保护,记录下了研究过程中的一些分析。现在分享出来
CCTV果冻爽
这个作者很懒,什么都没留下…
展开
-
LuaJit分析(一)LuaJit交叉编译
使用ndk版本 r16bNDKP指定了ndk编译器的前缀NDKARCH指定了编译成armv7平台NDK_SYSROOT_BUILD指定了头文件目录NDK_SYSROOT_LINK=$NDK/platforms/android-$NDKABI/arch-arm指定了链接时的库文件目录1、Windows下编译:启动cygwin64,切换到luajit目录,sh运行脚本(需要安装make)2、Linux下编译:sh运行脚本,注意ndk路径。原创 2024-08-29 10:29:21 · 1159 阅读 · 0 评论 -
LuaJit分析(二)luajit反编译工具
总的来说,luajit-decomp比较稳定,但是反编译出来的代码可读性差,之所以稳定,是因为它先使用 luajit -bl 命令将字节码转换成汇编代码,再通过线性扫描汇编代码,转换成lua脚本代码。Ljd是使用Python写的反编译工具,定义了luajit2.0完整的指令信息,并实现了所有的luajit字节码解析函数,解析出来的lua脚本可读性高。原创 2024-08-29 10:38:14 · 1484 阅读 · 0 评论 -
LuaJit分析(三)luajit字节码文件格式
Luajit字节码文件格式的完整信息如上图所示,包括文件头Header和原型Proto,一个原型可以对应lua源码中的一个函数或源文件。原型的字节码指令,每条指令占四个字节,默认对齐时,第一个字节为opcode,占用三个字节,始终是0x1B4C4A,表示这是一个luajit文件。STRIP表示是否去除调试信息,0表示没去除,包含调试信息。uleb128类型,表示整个原型占用字节大小,为0标志结束。upvalue,uint16,个数为原型头中指定的个数。BE表示是否大端对齐,默认0表示小端对齐。原创 2024-08-29 10:59:58 · 1644 阅读 · 0 评论 -
LuaJit分析(四)luajit 64位与32位字节码区别
luajit 64位和32位字节码不一样,体现:1、文件头部的flags表示,64位中有标记 fr2 = 12、原型头中的栈帧大小,当原型中有call指令并有参数时,frame大小会比32位的加13、参数压入的位置,当存在call指令并且有KSTR等指令压入参数时,压入的位置会加14、原因是CALL调用时需要保存返回地址,在32位中,地址占4字节,直接覆盖了栈中压入的函数字段类型的类型部分(4字节),而64位中地址占8字节,因此将栈的大小增加了1,并移动所有参数。原创 2024-08-29 10:55:03 · 1582 阅读 · 0 评论 -
LuaJit分析(五)LuaJit filename分析
参数argx包含了执行的lua脚本文件名,luaL_loadfile加载了一个lua脚本,通过之前的分析可知,luaL_loadfile会加载一个字节码文件或者转换一个源码文件,最终都会得到转换好的原型结构。在还原指针和参数栈后,ins_call开始执行解释器的call指令。原创 2024-08-29 11:15:33 · 639 阅读 · 0 评论 -
LuaJit分析(六)luajit -bl 命令分析
接着调用bc.lua中的bcdump函数,递归解析各个原型,通过bcline函数,解析各个指令,bcline函数中用到了vmdef.lua中定义的opcode和各个库函数的符号名,这些符号名由buildvm.c在编译过程中自动生成。从备注可以看出就是输出字节码指令,这是一个递归函数,先根据传入的第一个参数,使用funcinfo函数获取函数信息,funcinfo是一个库函数,位于jit.util. funcinfo,如果它有孩子,则递归调用全部为原型类型的孩子。原创 2024-08-29 11:09:52 · 1308 阅读 · 0 评论 -
LuaJit分析(七)LuaJit -b 命令分析
由之前对luajit -b 命令的分析可知,readfile函数最终返回原型数据,如果是字节码文件,返回读取后的原型数据,否则进行源码分析再返回原型数据。luajit -b生成字节码,实际上是调用 bcsave.lua脚本中的bcsave函数,该函数通过readfile函数(最终调用loadfile库函数)来完成lua脚本和字节码统一返回原型数据,并通过string.dump库函数生成完整的字节码文件。从这里就可以明显的看出,它通过分别生成头部、原型等数据来完成字节码的生成。原创 2024-08-29 11:12:59 · 709 阅读 · 0 评论 -
LuaJit分析(八)LuaJit预编译库函数加载过程
可以看到,该函数通过调用lj_bcread_proto读取luajit字节码的原型数据,接着使用原型创建一个新函数,然后保存该函数变量。原创 2024-08-29 11:38:58 · 626 阅读 · 0 评论 -
LuaJit分析(九)LuaJit中的JIT原理分析
Luajit存在97个字节码指令,例如 FORL指令对应一个数字类型的for循环语句,同时还有IFORL指令(强制解释模式执行)和JFORL指令(Jit模式执行),同时解释器实现了对各个字节码指令的翻译,这里以X86的翻译器为例。它将当前指令的地址右移一位,并与HOTCOUNT_PCMASK与操作,得到一个索引(哈希运算),根据这个索引在数值中找到计数值,减去HOTCOUNT_LOOP,当这个计数值小于0时,跳转到vm_hotloop继续执行。多种情况都会出现结束记录的情况,如遇到了已经编译的指令。原创 2024-08-29 11:35:30 · 2182 阅读 · 0 评论 -
LuaJit分析(十)luajit自定义修改
通过分析luajit字节码文件格式可知,luajit文件由文件头和原型数组组成,而原型又包括原型头和原型体,文件头中包含了字节码文件的一些关键信息,目前的反编译工具根据标准的luajit2.0文件格式解析文件,如果对字节码文件的信息自定义,将直接导致反编译过程中出现异常。字节码指令中,第一个字节存放的是opcode,实质是该字节码的opcode在BCOp中的下标,因此修改上述BCDEF宏定义的顺序后,对应字节码opcode的顺序也跟着改变,即生成的字节码文件与标准的字节码文件中指令的opcode会改变。原创 2024-08-29 11:51:02 · 1224 阅读 · 0 评论 -
LuaJit分析(十一)去除string.dump函数
因此即使我们的指令顺序被打乱,通过loadfile系统调用,再通过string.dump调用,可以得到字节码文件,再通过与标准的luajit生成的字节码文件比对,即可找出差异所在。Lua脚本中的string.dump函数用于生成字节码文件,根据对 luajit -b命令的分析可以得出,最终dump出字节码文件都是使用的string.dump函数。同时lj_libdef.h和lj_ffdef.h这两个文件都是自动生成的,在msvcbuild.bat中,使用如下命令生成。原创 2024-08-29 12:03:10 · 761 阅读 · 0 评论