碧蓝航线1.5相关

2017-12-20 19,613 ℃

Salt.dll解密

关键函数libmono.somono_set_data,此函数已加密,直接选择附加调试,F5
照抄一份c#

var bytes = File.ReadAllBytes("Salt.dll");
bytes[0] = 0x4D;
bytes[1] = 0x5A;
bytes[2] = 0x90;
bytes[3] = 0x00;
var result = 4;
var v4 = 12312;
do
{
    var v5 = bytes[result];
    bytes[result++] = (byte)(v5 ^ (v4 >> 8));
    v4 = -12691 * (v5 + v4) + 11719;
}
while (result != bytes.Length);
File.WriteAllBytes("Salt.dll", bytes);

用dnspy打开解密后的dll,发现已混淆,不过有个熟悉的老朋友

使用工具NoFuserEx

再使用de4dot进行重命名,导出Salt类代码

scripts加解密

直接调用函数
解密

Salt.Make(File.ReadAllBytes("scripts"), false);

加密

Salt.Make(File.ReadAllBytes("scripts"), true);

LuaJIT opcode加解密

libtolua.so下两个关键函数lj_bclock用于加密,lj_bcunlock用于解密,这两个函数也被加密了,依旧直接附加调试,F5
lj_bclock

lj_bcunlock

传入参数1是instructions段,参数2是段内opcode的数量

两个key长度都为256字节

参考ljd源码写一个简单的程序批量加解密

    static class Program
    {
        static byte[] lockkey;//自行从libtolua.so中取出
        static byte[] unlockkey;//自行从libtolua.so中取出

        static void Main(string[] args)
        {
            var bytes = File.ReadAllBytes(args[0]);
            var reader = new BinaryReader(new MemoryStream(bytes));
            //_read_header
            var magic = reader.ReadBytes(3);
            var version = reader.ReadByte();
            var bits = reader.ReadUleb128();
            var is_stripped = ((bits & 2u) != 0u);
            if (!is_stripped)
            {
                var length = reader.ReadUleb128();
                var name = Encoding.UTF8.GetString(reader.ReadBytes((int)length));
            }
            //_read_prototypes
            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                var size = reader.ReadUleb128();
                if (size == 0)
                    break;
                var next = reader.BaseStream.Position + size;
                bits = reader.ReadByte();//_read_flags
                var arguments_count = reader.ReadByte();//_read_counts_and_sizes
                var framesize = reader.ReadByte();
                var upvalues_count = reader.ReadByte();
                var complex_constants_count = reader.ReadUleb128();
                var numeric_constants_count = reader.ReadUleb128();
                var instructions_count = reader.ReadUleb128();
                var start = (int)reader.BaseStream.Position;
                //加密
                /*bytes[3] = 0x80;
                bytes = lj_bclock(start, bytes, (int)instructions_count);*/
                //解密
                bytes[3] = 2;
                bytes = lj_bcunlock(start, bytes, (int)instructions_count);
                //
                reader.BaseStream.Position = next;
            }
            File.WriteAllBytes(args[0], bytes);
        }

        static byte[] lj_bclock(int start, byte[] bytes, int count)
        {
            var result = start;
            result += 4;
            var v2 = 0;
            do
            {
                var v3 = bytes[result - 4];
                result += 4;
                var v4 = bytes[result - 7] ^ v2++;
                bytes[result - 8] = (byte)(lockkey[v3] ^ v4);
            }
            while (v2 != count);
            return bytes;
        }

        static byte[] lj_bcunlock(int start, byte[] bytes, int count)
        {
            var result = start;
            result += 4;
            var v2 = 0;
            do
            {
                var v3 = bytes[result - 4];
                result += 4;
                var v4 = bytes[result - 7] ^ v3 ^ (v2++ & 0xFF);
                bytes[result - 8] = unlockkey[v4];
            }
            while (v2 != count);
            return bytes;
        }

        static public uint ReadUleb128(this BinaryReader reader)
        {
            uint value = reader.ReadByte();
            if (value >= 0x80)
            {
                var bitshift = 0;
                value &= 0x7f;
                while (true)
                {
                    var b = reader.ReadByte();
                    bitshift += 7;
                    value |= (uint)((b & 0x7f) << bitshift);
                    if (b < 0x80)
                        break;
                }
            }
            return value;
        }
    }

完工~

使用云服务器和云手机运行AzurLaneAutoScript

更新日志: 2023-5-24 添加frp 2023-4-7 添加Tailscale 2022-8-1 添加WireGuard 起因 某日趁着某家云手机厂商打折的时候换了台新的...

阅读全文

【2019-6-14】碧蓝航线Live2D提取

程序已过时,请使用UnityLive2DExtractor 2019-6-14 v1.3 大量改进 2018-10-27 v1.2 完善4种Segment 2018-10-23 v1.1 修复易拉罐等SteppedSegment问题 正文 ...

阅读全文

【2017-9-29】碧蓝航线音频提取

2017-9-29更新: 今天有人发现hca中文文件名乱码问题,还好vgm是用c#写的能够方便修改代码,扫了遍代码后发现是编码问题,把vgmtutil.dll里的Encoding改成Enc...

阅读全文

60 条评论

    1. NT一样的发言,真是lj加密你搁这无能狂怒啥,搞开发的程序员没工夫成天想着怎么防逆向,肯定怎么懒怎么来。
      宁真是纯NT,没点B水平就知道瞎j2叫,逆向不适合你gun回去种田吧,孩子。

  1. 大佬,今天日韩美服更新apk改了LuaJIT opcode加解密方法, 有办法更新此贴吗?

  2. 9102年了,现在的教程基本上都过时了,能否请大佬重新指明一下修改思路

  3. 大佬 为什么用这个解包出的碧蓝航线立绘是各种碎片状的啊 要怎么还原呢

  4. 有部分文件不能反编译成明文,比如BossBattleActivityPanel.lua.txt,有办法解决吗?

  5. 大佬,在dnspy修改方法后编译出现的一堆the name Debugger&AssetBundle%time does not exist,该怎么解决?

  6. 大佬,改完后怎么打包回去啊?US解压出来的ship_data_xxxxx.lua什么的在UABE里根本搜索不到。求助。

  7. Perfare大大您好,
    听说您以前有制作Last Period的数据库,
    想请教您,
    有没有办法取得Last Period全部人物立绘的下载地址呢?
    因为Last Period的人物立绘后面都跟有一串随机数数字码,
    没有办法直接推测下载,
    想请问大佬有没有办法?
    至少可以知道所有人物立绘后面的随机数数字码,
    问题就可以基本解决了~
    如果有相关方法,
    还麻烦大佬教教小弟~~

    拜托您了QwQ

    1. 大佬您好。感谢您的解答
      小弟以前没有解析过dll档案,
      能请教大佬有推荐的解析软件吗?
      感谢您~

  8. 大佬好
    ljd_bclock和ljd_bcunclock如果直接f5附加调试的话,出现的是这个..

    void __noreturn lj_bclock()
    {
    __asm { STC2 p5, c8, [R0,#0x258] }
    if ( !_CF )
    __asm { LDCCCL p1, c3, [R8,#0x3E4]! }
    JUMPOUT(0x122C020u);
    }

    这是加密的原因吗?

  9. 大佬你好,
    static byte[] unlockkey;//自行从libtolua.so中取出
    我把这里的unlockkey替换成解出来的0xB2,0x9D,那段256字节的key并运行后,结果显示输入的标记“0xb2”无效
    学着动态调试里那样加{}也不行,
    请问大佬我解出来的KEY应该写在代码的什么地方,有什么格式要求没,还是说我用的编程软件有问题?

  10. 问一下大佬用哪个版本的IDA,我用6.6的老是弹出错误提示框:bogus or irresponseble remote server,重新转发android_server也不行,求助

  11. 2个key都找到了,运行大佬的代码后,解密出来的文件还是不对,有点懵逼

    1. 大佬,lua解密始终不是明文,卡这块几天了,方不方便加我企鹅号帮我看看代码。。
      企鹅号447986571 :!:

    2. 你该不会以为用我这代码能解出明文lua?不存在的。也别问我解出来的文件是什么,自己研究

    3. 原来是我搞错了。。闹笑话了
      看了大佬这回复再回去仔细看了看正文,果断明白了
      现在已经成功解密lua了,感谢大佬

  12. P大你好JIT已经按你的方法解开了,可是我scripts是按照冰大的方法提取出来的,所以能问问你这个Salt.dll是在哪吗?

  13. 大佬,有些腳本似乎是多個prototypes組起來的,例如AddShipCommand.lua,執行的結果好像不如預期

欢迎留言

6 + 9 =