00003 不思议迷宫.0011.2:Android新版中的Lua加密(下)

00003 不思议迷宫.0011.2Android新版中的Lua加密()

         好久没发文章了,并不是我停止了研究,而是一直在忙些修复bug的工作。今天在研究精英服的时候,本打算对比一下和正式服的代码的,但无奈时间不足,就不多说了。这儿简单点,向大伙介绍一下对游戏的Android版本中的的luac文件的解密研究的过程和成果。

         在上一篇文章中(好吧,按时间上不是上一篇,按标题才是),我已介绍过,游戏Android版中的luac文件是被xxtea加密的,并且解说了如何获得xxteakey。如果有人继续研究下去,会发现解密出来的文件还是加密的:

00003 不思议迷宫.0011.2:Android新版中的Lua加密(下)_第1张图片

         当然,这并不是真的加密,它其实是lua的字节码。但是呢,它不是普通的lua字节码,而是一个叫做LuaJIT的东东生成的变种lua字节码。知道它是字节码就基本可以放心了:java字节码,被人破解了;C#字节码,结果也被人破解了;那么lua字节码,会幸免吗?

         我就从网上搜,找找各种反编译LuaJIT/Lua字节码的工具,还真找到那么几个。在这个过程中,还发现有其他的变种lua字节码(具体名字我已忘了,哎,瞅瞅我这破记性)。

         抛开不能用的、反编译lua原版字节码的不谈,我找到的确定能用的、反编译LuaJIT字节的工具有两个(严格来说只是一个):luajit-decompljd

         luajit-decomp这个东西有点差:下载下来的exe在我的电脑上不能运行(我猜测可能是需要将字节码文件拷贝在某个特定目录。它告诉我说:“If you have any questions on how to use it then read the wiki”。可是鬼才知道这个wiki在哪儿)。经研究呢,这个工具反编译并没有干啥,也只是利用LuaJIT自身的命令而已:

luajit -bl in.luac out.txt

         这个能得到啥?一种类似汇编代码的东西,可读性也就比字节码好上一点:

-- BYTECODE -- UIDungeonMgr.lua:18-26

0001    GGET     0   0      ; "DungeonM"

0002    TGETS    0   0   1  ; "getDungeonId"

0003    CALL     0   2   1

0004    GGET     1   2      ; "DungeonAreaM"

0005    TGETS    1   1   3  ; "getParentId"

0006    MOV      2   0

0007    CALL     1   2   2

0008    GGET     2   2      ; "DungeonAreaM"

0009    TGETS    2   2   4  ; "isAllSubAreaPassed"

0010    GGET     3   5      ; "ME"

0011    TGETS    3   3   6  ; "user"

0012    MOV      4   1

0013    CALL     2   2   3

0014    ISF          2

0015    JMP      3 => 0036

         找本luac指令手册,对照着看,应当可以看懂。但是,谁闲得蛋疼去这么看?

         我幸运地找到了第二个能用的工具。

         ljdgit上下来之后,按照它的说明,执行:

python main.py UIDungeonMgr.luac > UIDungeonMgr.txt

         错误了:

    complex_constants.append(string.decode("ascii"))

         UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal

         not in range(128)

         明明是utf-8的,你给我说ascii?也许是UIDungeonMgr.luac没有BOM头?加上BOM之后,结果又说:

         Invalid magic, not a LuaJIT format

         Failed to read raw-dump header

         看看magic是啥:

def _check_magic(state):

         if state.stream.read_bytes(3) != _MAGIC:

                  errprint("Invalid magic, not a LuaJIT format")

                  return False

 

         return True

         我是很不喜欢python的,居然用空格或者tab的数量作为块控制。上面的这个函数定义怎么看都像是少了个end或者},真是让人不习惯。回头看一下_MAGIC:

         _MAGIC = b'\x1bLJ'

         和原始的UIDungeonMgr.luac比较一下,发现是相同的。那看来文件是没错的,回头看看“UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6”这个错:

def _read_complex_constants(parser, complex_constants):

         i = 0

 

         while i < parser.complex_constants_count:

                  constant_type = parser.stream.read_uleb128()

 

                  if constant_type >= BCDUMP_KGC_STR:

                          length = constant_type - BCDUMP_KGC_STR

 

                          string = parser.stream.read_bytes(length)

 

                          complex_constants.append(string.decode("ascii"))

                          ……

 

         原来是这个地方定死的ascii,而没有自动检测。那我定死成utf-8吧:

                          #complex_constants.append(string.decode("ascii"))

                          complex_constants.append(string.decode("utf-8"))

         再试试:python main.py UIDungeonMgr.luac > UIDungeonMgr.txt

         ok,看到了生成的文件:

require("game/ui/form/dungeon/UIDungeonMain")

require("game/ui/form/combat_stat/UICombatStat")

module("UIDungeonMgr", package.seeall)

 

local uiLevel = nil

local SEPERATOR_FORM_NAME = "SeperatorForm"

local BOSS_LOCK_SCREEN_TIME = 7.5

 

EventMgr.register("UIDungeonMgr", event.DUNGEON_PASS, function ()

         local dungeonId = DungeonM.getDungeonId()

         local parentId = DungeonAreaM.getParentId(dungeonId)

 

         if DungeonAreaM.isAllSubAreaPassed(ME.user, parentId) then

                  local nextMainAreaId = DungeonAreaM.getNextMainArea(parentId)

 

                  ME.user.dbase:setTemp("new_passed_area", parentId)

                  ME.user.dbase:setTemp("new_unlock_area", nextMainAreaId)

         end

 

         return

end)

         ……

         大功告成!——好吧,这个工具还不够完善,某些情况会无法正常反编译为源码,这个时候就只能人肉翻译“luajit -bl”产生的“汇编代码”了。

你可能感兴趣的:(游戏破解技术研究,不思议迷宫)