不思議迷宮:逆向後的放置play

  1. 前言
  2. 前置準備
  3. 目標分析
  4. 逆向加密邏輯
  5. 定位sign與key
  6. 解密luac
  7. 反編譯luajit的bytecode
  8. 開啓上帝模式
  • 前言

    看了fatezero的《陰陽師:一個非酋的逆向旅程》後,受益不淺。特別是關於opcode映射關係一節,處理的很精妙。python

對手頭上的遊戲不思議迷宮,技癢的不行。因而上週週六花了整個下午的時間進行了研究。注意本文中針對安卓版本。git

  • 前置準備

    若是讀者也想跟着步驟進行操做,須要準備這些工具:ApkIDE少月版、IDA、python、010editor程序員

 

  • 目標分析

     APKIDE載入以後,首先看一下lib\armeabi\目錄下,發現了libcocos2dlua.sogithub

     

  從字面意思來看,應該是使用cocos2d引擎,而且使用lua腳本,再看assets\src\算法

   

  發現大量的luac腳本,進一步確認了咱們的想法。010editor打開Main.luac,從頭來看,並不是luac文件的頭app

  

  正常的luaca的頭應該是1B 4C 75 61開頭,以下圖函數

  

  因此不思議迷宮必然是對luac進行了加密。工具

  • 逆向加密邏輯

  經過IDA打開libcocos2dlua.so,通常狀況下加密會出現cocos2dx_lua_loader->luaL_loadbuffer的某個過程當中測試

  源碼以下:ui

   

  而在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中(同時存在python二、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,程序員已經實現了自動加天賦,自動撿東西,自動打怪,自動進入下一層等等

  

相關文章
相關標籤/搜索