丰满岳翻云覆雨呻吟_亚洲色偷拍区另类无码专区_亚洲综合欧 ,四虎影视a片永久免费网址_午夜美女性高潮视频_亚操日韩美

珠海鋼絞線_天津瑞通預(yù)應(yīng)力鋼絞線

連云港預(yù)應(yīng)力鋼絞線價(jià)格 某棋游戲lua逆向破解修改(一)

發(fā)布日期:2026-01-15 23:54點(diǎn)擊次數(shù):192

鋼絞線背景

近朋友在玩幾個(gè)棋游戲,我花了點(diǎn)時(shí)間研究了一下,雖然破解失敗連云港預(yù)應(yīng)力鋼絞線價(jià)格,但是過程感覺還是有收獲,分享給大

天津市瑞通預(yù)應(yīng)力鋼絞線有限公司

這篇文章主要分享 如何找key

破解思路后面有空再分享

cocos2dlua

棋游戲的邏輯一般是使用lua編寫的,lua腳本加載一般是用 cocos2d 加載的,我的破解方向集中在這里,如果你要破解的棋游戲不是這個(gè)技術(shù)棧,那就不能照搬

lua腳本常見情況如下:

luac(編輯器打開腳本,前面幾個(gè)字節(jié)是lua) cocos2dlua(編輯器打開腳本,前面幾個(gè)字節(jié),不是lua,多打開幾個(gè)會(huì)發(fā)現(xiàn)是固定的)

我這里遇到的就是 cocos2dlua (看一下lib文件有沒有叫類似名字的so)

cocos2dlua 加密原理給大簡(jiǎn)單介紹一下

寫好lua腳本 使用key進(jìn)行加密(加密算法叫 xxtea) 加密完成之后在前面拼接sign

這個(gè)sign就是剛剛提到的固定字符串

解密步驟如下:

讀取腳本,切掉前綴,也就是sign 使用找到的key進(jìn)行解密

那么解密難點(diǎn)就是找key

key一般來說都在 libcocos2dlua.so里面, 有以下幾種玩法:

不修改 cocos2d 代碼,明文存儲(chǔ) 修改  cocos2d 代碼,明文存儲(chǔ) 修改  cocos2d 代碼,代碼計(jì)算得到 不修改 cocos2d 代碼,明文存儲(chǔ)

這種簡(jiǎn)單了,編輯器打開lua腳本,直接搜前綴,key就在附近

為什么在附近?因?yàn)樵创a要求sign和key作為參數(shù)一起傳

bool AppDelegate::applicationDidFinishLaunching()
{
    // set default FPS
    Director::getInstance()->setAnimationInterval(1.0 / 60.0f);

    // register lua module
    auto engine = LuaEngine::getInstance();
    ScriptEngineManager::getInstance()->setScriptEngine(engine);
    lua_State* L = engine->getLuaStack()->getLuaState();
    lua_module_register(L);

    register_all_packages();

    LuaStack* stack = engine->getLuaStack();
    stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));

上面的 2dxlua 就是sign連云港預(yù)應(yīng)力鋼絞線價(jià)格,XXTEA 就是 key (加密算法也叫 xxtea)

源碼在 github

修改cocos2d 代碼,明文存儲(chǔ)

不修改源碼,直接記事本打開就能找到key,所以一些開發(fā)者為了提升安全,修改了 cocos2d代碼,讓sign和key遠(yuǎn)離(比如寫一個(gè)函數(shù)獲取key),增加破解難度

這里列舉幾個(gè)可能的變形點(diǎn),依次在 ida里找就可能找到

以下均為 function

applicationDidFinishLaunching 入口點(diǎn),默認(rèn)sign和key在這里 setXXTEAKeyAndSign 如函數(shù)名所示,設(shè)置sign和key xxtea_decrypt 算法解密點(diǎn),因?yàn)樾枰獋魅雓ey進(jìn)行解密,按x看調(diào)用的地方,有key的蹤跡

下面舉一個(gè)例子

010打開lua腳本

看到了一個(gè)前綴 ida分析 libcocos2dlua.so 搜索 applicationDidFinishLaunching,沒有看到明文

搜索 setXXTEAKeyAndSign,也沒有看到明文

搜索 xxtea_decrypt,出現(xiàn)兩個(gè),有戲,因?yàn)橐话闶且粋€(gè)

依次按x看調(diào)用的地方,一個(gè)比較正經(jīng),是正常調(diào)用關(guān)系 二個(gè)是自定義的函數(shù),鋼絞線廠家進(jìn)去看看

經(jīng)過分析源碼,得知 key 是 圖中的 v21 (這里就不貼明文了,避免被搜索到,哈哈)

到這里,key就找到了

修改  cocos2d 代碼,代碼計(jì)算得到

另外一種變形就是key不是明文存的,是計(jì)算得到,下面舉一個(gè)例子說明

步驟類似 010打開

搜索 applicationDidFinishLaunching,看到明文了,但是有好幾個(gè)字符串,到底是哪一個(gè)呢?

上面出現(xiàn)好幾個(gè)字符串的那一行,實(shí)際調(diào)用的是函數(shù) setXXTEAKeyAndSign 搜索 setXXTEAKeyAndSign,

經(jīng)過閱讀代碼,慢慢扣偏移,后得知 key 是 v21 (上面的例子也是v21,這個(gè)只是巧合,不用在意)

當(dāng)然了,這里也不用慢慢扣代碼,可以寫代碼梭哈,輸入4個(gè)字符串,前兩個(gè)用 0x2019%s%s 組合起來了,后面兩個(gè)也是一樣的組合方式,加起來6個(gè)可能,依次遍歷,看看到底是哪個(gè)就行

這里是梭哈的golang代碼

解密

上面是找key的方法,找到之后就要解密了 薦自己寫,我找了一些成品,只能說差強(qiáng)人意

薦用golang寫,無需亂七八糟的依賴,寫完就運(yùn)行 對(duì)golang不熟悉,也可以用 python,但是要依賴 特定版本 visual studio, 有多惡心,我就不多說了

以下是 golang代碼

package main

import (
        "flag"
        "fmt"
        "io/ioutil"
        "os"
        "path/filepath"
        "time"

        "github.com/xxtea/xxtea-go/xxtea"
)

type CMD struct {
        encrypt_file string
        decrypt_file string
}

var prefix string = "xxxx"
var lua_key string = "xxxx"

func main() {

        cmd, r := initFlag()
        if r {
                return
        }

        if cmd.decrypt_file != "" {
                err := decrypt(cmd.decrypt_file)
                if err != nil {
                        fmt.Println(err)
                }
                return
        }

        if cmd.encrypt_file != "" {
                err := encrypt(cmd.encrypt_file)
                if err != nil {
                        fmt.Println(err)
                }

                return
        }

        fmt.Println("error, empty input")
}

func encrypt(path string) error {

        by, err := os.ReadFile(path)

        if err != nil {
                fmt.Println("read fail", err)
                return err
        }

        encrypt_data := xxtea.Encrypt(by, []byte(lua_key))

        // 拼接前綴
        data := append([]byte(prefix), encrypt_data...)

        // fileInfo, err := os.Stat(path)
        // if err != nil {
        //         return err
        // }

        name := filepath.Base(path)
        x1 := name[:len(name)-len(filepath.Ext(name))]

        newName := x1 + "_" + time.Now().Format("2006-01-02_15-04-05") + ".luac"

        fmt.Println("output file: ", newName)

        err = os.WriteFile(newName, data, 0666)
        if err != nil {
                fmt.Println("write fail")
        }

        return nil
}

func decrypt(path string) error {

        by, err := ioutil.ReadFile(path)

        if err != nil {
                fmt.Println("read fail")
                return err
        }

        // 去除前綴
        data := by[len(prefix):]

        decrypt_data := string(xxtea.Decrypt(data, []byte(lua_key)))
        fmt.Println(decrypt_data)
        return nil
}

func initFlag() (CMD, bool) {
        var decrypt_file = flag.String("d", "", "解密path")
        var encrypt_file = flag.String("e", "", "加密path")
        var help = flag.Bool("h", false, "help")

        flag.Parse()

        if *help {
                flag.Usage()

                return CMD{}, true
        }

        if *decrypt_file == "" && *encrypt_file == "" {
                flag.Usage()

                return CMD{}, true
        }

        c := CMD{*encrypt_file, *decrypt_file}
        return c, false

}

再貼一個(gè)python的(只有解密的,文件是寫死的,所以代碼行數(shù)少很多)

#coding: utf-8

# lua 解密單個(gè)文件

import os
import sys
import xxtea
import logging
import pathlib

a = "xxxx"
b = "0x201xxxx"

def decrypt(filename):
    f = open(filename, mode='rb')

    data = f.read()

    data2 = data[len(a):]

    data3 = xxtea.decrypt(data2, b)
    return data3

inputName = r"X:\007-project\003-lua\xxx\main.lua"

x = decrypt(inputName)
print(x)
frida

以上是通過 ida 分析得到key,比較花時(shí)間,也看運(yùn)氣,因?yàn)榭梢孕薷牡狞c(diǎn)太多了 這里再介紹一個(gè)釜底抽薪的方式

經(jīng)過上面的分析得知,只要開發(fā)者沒有喪心病狂的去修改 xxtea 算法,那么后key一定會(huì)傳到 xxtea_decrypt 里面,我們可以通過 frida 觀察入?yún)⒕湍艿玫?key

function xx() {
    console.log("===============================================================");

    var coco = Process.findModuleByName("libcocos2dlua.so");
    var exports = coco.enumerateExports();
    for(var i = 0; i < exports.length; i++) {
        var name = exports[i].name;

        // 不一定叫這個(gè)名字,匹配一下
        if (name.indexOf("xxtea_decrypt")!=-1) {
            console.log("name:", name);

            console.log("exports[i]:", JSON.stringify(exports[i]));

            var addr = exports[i].address;
            Interceptor.attach(addr, {
                onEnter: function (args) {

                    console.log('[+] args0,r0: ' + args[0]);//data數(shù)據(jù)

                    console.log('[+] args1,r1: ' + args[1]);//data長(zhǎng)度

                    //密鑰
                    console.log('[+] args2,r2: ' + args[2]);
                    console.log(Memory.readCString(args[2]));

                    console.log('[+] args2,r3: ' + args[3]);//密鑰長(zhǎng)度
                } onLeave: function (retval) {

                }
            }
        });
    }

}

setImmediate(xx,0);

這里貼一下反編譯之后的果圖 連云港預(yù)應(yīng)力鋼絞線價(jià)格

相關(guān)詞條:鋁皮保溫施工
隔熱條PA66
鋼絞線