某传奇手游封包和数据分析

本文详细记录了传奇手游封包解密的过程,包括使用tcpdump进行抓包,通过IDA分析libMyGame.so找到关键函数SendMsg,以及Lua脚本的加密解密方法。通过frida hook导出明文脚本和编写Python解密函数,实现了对游戏脚本的修改和测试,探讨了服务端对传送配置的验证。
摘要由CSDN通过智能技术生成

一、简介:

偶然在看雪看到一篇传奇手游封包解密的文章:

[原创]某传奇封包解密-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com

但是内容说的太简略,所以我上手实战一番,此贴为实战记录。

文章中没有说是哪款传奇手游,根据图标我们去百度搜图锁定到一款《yscq》的手游。

二、抓包:

我们第一步就是进行抓包,确认是否和文章中说的是一款手游。

charles、Drony代理、r0capture、frida hook 关键发包位置

com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream -> write

libc.so -> write

libssl.so -> SSL_write

以上方法我都尝试了。无法抓取socket数据。最后只能祭出通天神器 -> tcpdump

将文件放到 /data/local/tmp/tcpdump 并给予权限 chmod 777 tcpdump

tcpdump -p -vv -s 0 -w /sdcard/capture.pcap

抓包并记录到文件

这个头和文章里是不是很像,那么基本可以肯定就是这个游戏了。

解压APK 来到lib目录下,发现libMyGame.so文件最大,有20M。那么就它了。拖入IDA

确实可以搜索到文章中提到的函数,下面我们来具体分析一下,并打印调用栈。

 根据调用栈我们追出大致调用流程

SendMsg -> SendNetMessage -> Encode6BitBuf -> send

其中hook SendMsg 就可以获取到明文发包内容。


function hookSend(){

    // _ZN20LuaNetworkController7SendMsgEiiiiiPKcj
    var libcmodule = Process.getModuleByName("libMyGame.so");
    var SendMsg = libcmodule.getExportByName("_ZN20LuaNetworkController7SendMsgEiiiiiPKcj");

    console.log("SendMsg:",SendMsg);
    //void __fastcall LuaNetworkController::SendMsg(LuaNetworkController *this, int a2, int a3, int a4, int a5, int a6, const char *a7, size_t a8)
    Interceptor.attach(SendMsg, {
        onEnter: function (args) {

            this.arg0 = args[0];
            this.arg1 = args[1];
            this.arg2 = args[2];
            this.arg3 = args[3];
            this.arg4 = args[4];
            this.arg5 = args[5];
            this.arg6 = args[6];
            this.arg7 = args[7];

            console.log("SendMsg ",this.arg6);
            console.log("SendMsg ",this.arg7);

            console.log("SendMsg this.arg1: " + ptr(this.arg6).readCString());

            LogPrint("go into libMyGame.so->SendMsg");

            printNativeStack(this.context, "SendMsg");
        }, onLeave(retval) {

            LogPrint("leave libMyGame.so->SendMsg " );
        }
    });
}

 这里有个小知识点,判断so加载后在加载hook代码,这样就不会出现找不到so文件的错误。

function testInit(){

    var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
    console.log(android_dlopen_ext);
    if(android_dlopen_ext != null){
        Interceptor.attach(android_dlopen_ext,{
            onEnter: function(args){
                var soName = args[0].readCString();
                console.log(soName);
                // libconnectionbase
                // if(soName.indexOf("MyGame.so") != -1){
                if(soName.indexOf("connectionbase.so") != -1){
                    this.hook = true;
                }
            },
            onLeave: function(retval){
                if(this.hook) {

                    hookSend();
                };
            }
        });
    }
}

 使用回城石SendMsg的传参!

第二部分:

Lua脚本加密解密:

首先我们先看看是cocos2d哪个版本,

在IDA中 shift+F12 调出Strings window窗口

Cocos2d-x对于lua脚本加密提供了一种轻量级解决方案, 加密算法是xxtea,具体可以github搜索xxtea开源算法

主要就是两个部分,sign和key,sign是加密标记,用于判断脚本是否加密,key是xxtea解密时候的秘钥

这里就是通过对比文件开头的字符串是否为所设置的sign判断是否加密,如果加密的话就解密,解密后才加载脚本

方法一、利用frida hook导出明文Lua脚本(最好在加载so完成第一时间hook哦~)

// 获取lua脚本文件
function hooklua(){
// luaL_loadbuffer

    var libMyGame = Process.getModuleByName("libMyGame.so");
    console.log("libMyGame:",libMyGame);
    // var SendMsg = libcmodule.getExportByName("luaL_loadbuffer");
    if (libMyGame){

        //加载lua文件函数
        Interceptor.attach(Module.findExportByName("libMyGame.so" , "luaL_loadbuffer"),{
            onEnter:function (args){
                // 文件保存路径
                this.fileout = "/storage/emulated/0/frida/lua/" + Memory.readCString(args[3]).split("/").join(".");
                console.log("read file from: "+this.fileout);
                var tmp = Memory.readByteArray(args[1], args[2].toInt32());
                var file = new File(this.fileout, "w");
                file.write(tmp);
                file.flush();
                file.close();

                console.log("lual_loadbuffer (" +Memory.readCString (args[3] ) +" ," +Memory.readCString (args[1])+")");
            },
            onLeave:function (retval){
                //console.log(retval)
            }
        });
    }
}

将文件夹复制到电脑,随便打开一个.lua文件

哇哦~哇哦~~!明文脚本。成功了。

方法二、找到sign和key,使用python编写加密解密函数

在解压文件中找到lua脚本文件(\assets\mod_launcher\stab\scripts),用记事本打开:

头部就是sign,在IDA中 ALT+T 字符串搜索sign(一般情况下key就在sign附近)。

 好啦,现在sign和key都有了。让我们编写代码吧

import xxtea

def luaDecode(orig_path,new_path):

    xxtea_sign="!ltcszip"
    xxtea_key="QvnHJr3kl6"
    orig_file = open(orig_path, "rb")
    encrypt_bytes = orig_file.read()
    orig_file.close()
    decrypt_bytes = xxtea.decrypt(encrypt_bytes[len(xxtea_sign):], xxtea_key)
    new_file = open(new_path, "wb")
    new_file.write(decrypt_bytes)
    new_file.close()


def luaEncode(orig_path,new_path):
    xxtea_sign=b"!ltcszip"
    xxtea_key="QvnHJr3kl6"
    orig_file = open(orig_path, "rb")
    encrypt_bytes = orig_file.read()
    orig_file.close()
    decrypt_bytes = xxtea.encrypt(encrypt_bytes, xxtea_key)
    new_file = open(new_path, "wb")
    new_file.write(xxtea_sign + decrypt_bytes)
    new_file.close()



if __name__ == '__main__':
    #解密
    orig_path= r"D:\base\assets\mod_launcher\stab\scripts\main.lua"
    new_path= r"D:\test\main.lua"

    luaDecode(orig_path,new_path)

    #加密
    orig_path= r"D:\lua\scripts.config.cfg_item.lua"
    new_path= r"D:\test\cfg_item.lua"

    luaEncode(orig_path,new_path)

好啦,加密解密都完成了。让我们来测试一下吧。

我们先来改个传送配置文件,看看是否有效果。例如:传送玛雅六层,需要5转和玛雅卷轴

	[124] = { 
		id=124,
		group=11,
		name="玛雅神殿",
		button=6,
		name1="玛雅六层",
		costitem=1,
		mapid="M019",
		positionx=83,
		positiony=84,
		condition="300005#400006",
	},

我们把id为1的传送改成玛雅六层,并去除condition字段

	[1] = { 
		id=1,
		group=1,
		name="主城传送",
		button=1,
		name1="玛雅六层",
		costitem=1,
		mapid="M019",
		positionx=83,
		positiony=84,

	},

现在需要把改过的.lua文件再加密回去,然后用MT放到指定目录。(如果加密后重新打包,进游戏时更新文件可能覆盖掉我们更改的文件)。

正常情况传送玛雅六层:

点我们更改的ID为1的传送:

其实这里是需要玛雅卷轴,不再需要转生5了。这个提示是因为我把本地提示的字符串改了。消耗物品这种应该是服务端有判断,所以改配置文件不太行。

好啦,基本的内容就是这些啦。感谢观看。 

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人工智能-肥鹅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值