• 不思议迷宫:逆向后的放置play


    1. 前言
    2. 前置准备
    3. 目标分析
    4. 逆向加密逻辑
    5. 定位sign与key
    6. 解密luac
    7. 反编译luajit的bytecode
    8. 开启上帝模式
    • 前言

        看了fatezero的《阴阳师:一个非酋的逆向旅程》后,受益匪浅。特别是关于opcode映射关系一节,处理的很精妙。

    对手头上的游戏不思议迷宫,技痒的不行。于是上周周六花了整个下午的时间进行了研究。注意本文中针对安卓版本。

    • 前置准备

        如果读者也想跟着步骤进行操作,需要准备这些工具:ApkIDE少月版、IDA、python、010editor

    • 目标分析

         APKIDE载入之后,首先看一下libarmeabi目录下,发现了libcocos2dlua.so

         

      从字面意思来看,应该是使用cocos2d引擎,并且使用lua脚本,再看assetssrc

       

      发现大量的luac脚本,进一步确认了我们的想法。010editor打开Main.luac,从头来看,并非luac文件的头

      

      正常的luaca的头应该是1B 4C 75 61开头,如下图

      

      所以不思议迷宫必然是对luac进行了加密。

    • 逆向加密逻辑

      通过IDA打开libcocos2dlua.so,一般情况下加密会出现cocos2dx_lua_loader->luaL_loadbuffer的某个过程中

      源码如下:

       

      而在IDA中,luaL_loadbuffer之前出现了srcDecrypt函数,这可是源码中没有出现了。

      

      数据的流向是:从文件读入->v51->v25->luaL_loadbuffer,再分析srcDecrypt函数

      

      当一个文件的头为11 12 13 的时候,就用charMapList进行替换,而charMapList,通过引用查找

      又是从buildEncrypyMap中初始化的,显然这是一组“静态”的置换表,完全可逆而且没有任何难度。

      

      但是回过头来看apk中的luac文件,没有一个的文件头是11 12 13,文件头全部是applicationWillEnterForeground

      并没有给我们带来任何帮助,只能继续分析luaLoadBuffer,看到了第二个加密的地方xxtea_decrypt

      

      google,baidu之后,找到非常类似的一段源码

       

      通过sign对文件进行标记,符合条件用key进行解密,梳理一下luac的整体解密过程

      

      由于没有使用srcDecrypt的流程,所以实际上只有xxtea_decrypt,只要找到sign和key,问题就解决了。

    • 定位sign与key 

       通过分析,可以确定加密的最终文件格式。文件头都有固定长度的sign

    xxtea_decrypt(buf+decode->m_xxteaSignLen, (xxtea_long)size -(xxtea_long)decode->m_xxteaSignLen, (unsigned char*)decode->m_xxteaKey, (xxtea_long)decode->m_xxteaKeyLen, &len); 

      再次打开另外一个luac文件,二者相同的文件头如图,所以sign为applicationWillEnterForeground

      

      在IDA中,我们也找到了这个字符串

      

      查找引用之后,这个字符串在initLuaStack中被调用了。

      

      再通过资料搜索,发现一般使用xxtea算法的,都会使用setXXTEAKeyAndSign来设置sign和key,图中v3就是setXXTEAKeyAndSign函数

    stack->setXXTEAKeyAndSign("123", strlen("123"), "cloud", strlen("cloud"));  

      那么自然key就是:applicationDidEnterBackground

    • 解密luac

      首先pip install xxtea-py,安装python的xxtea的库

      编写脚本如下:

    import xxtea
    import os
    sign = 'applicationWillEnterForeground'
    key = 'applicationDidEnterBackground'
    def decode(filename):
        luacdata = open(filename,'rb').read()
        decrypt_data = xxtea.decrypt(luacdata[len(sign):],key[:16])
        open(filename.replace('.luac','.luacx'),'wb').write(decrypt_data)

      解密后如下,出现的文件头为1B 4C 4A 01,也并非luac标准头,难道还有名堂?

      

      经过一番资料查询之后,这是luajit编译的bytecode,并非标准lua。其头为1B 4C 4A


      


    • 反编译luajit的bytecode

      在github上找到用于反编译luajit的项目:https://github.com/NightNord/ljd

       由于该库只能在python3上跑起来,而我懒得改脚本,于是直接通过命令执行方式,在kali中(同时存在python2、python3)运行了如下脚本

    #coding=utf-8
    import os
    sign = 'applicationWillEnterForeground'
    key = 'applicationDidEnterBackground'
    path = os.path.join(os.getcwd(),'src') 
    def decode(filename):
        luacdata = open(filename,'rb').read()
        decrypt_data = xxtea.decrypt(luacdata[len(sign):],key[:16])
        open(filename.replace('.luac','.luacx'),'wb').write(decrypt_data)
    
    def decomplie(filename):
        os.system('python3 ./ljdm/main.py '+filename+' > '+filename.replace('.luacx','.luacxs'))
    
        
    for path,d,filelist in os.walk(path):  
        for filename in filelist:
            filename = os.path.join(path, filename)
            if filename.endswith('.luac') and not os.path.isfile(filename.replace('.luac','.luac')):
                print( filename)
                decode(filename)
            if filename.endswith('.luacx') and (not os.path.isfile(filename.replace('.luacx','.luacxs')) or os.path.getsize(filename.replace('.luacx','.luacxs'))==0):
                print(filename)
                decomplie(filename)

      src目录对应生成的luacxs就是最终反编译好的lua源代码了。

    • 开启上帝模式

      通过大量的分析之后,我发现程序员在代码中,没有去掉测试用的上帝模式,只是简单的隐藏

      我在UIAccountBind.luacxs:380行中加入打开上帝模式的一行代码openGdUI().

      这样当我点击复制账号id的时候就会弹出上帝模式窗口

        local function onCopyClick(sender, eventType)
            if eventType == ccui.TouchEventType.ended then
                copyToClipBoard(rid, getLocStr("text_copied"))
            end
            openGdUI()
            return 
        end

      以及GDM.luacxs:24中的check_mode,让其始终返回为true,保证上帝模式功能可正常开启

    function check_mode()
        return true 
    end

      然后通过luajit编译,再进行xxtea加密,打包成APK放入手机。

      最终效果图为:全自动放置play,程序员已经实现了自动加天赋,自动捡东西,自动打怪,自动进入下一层等等

      

  • 相关阅读:
    字典
    字符串常用的方法
    切片,集合、文件处理
    蓝桥杯练习 Day6 题解
    spoj-ORDERS
    spoj-SUBSUMS
    spoj
    spoj --- ABCDEF
    C. Andryusha and Colored Balloons
    B. The Meeting Place Cannot Be Changed
  • 原文地址:https://www.cnblogs.com/howmp/p/6528355.html
Copyright © 2020-2023  润新知