蓝月传奇BT版本全套资源解密算法

蓝月传奇BT版本全套资源解密算法,由于游戏APK中的角色怪我地图等资源进行了打包加密,我们有的时候想进行一些修改,那么就需要把资源全部解密出来。

直接上代码吧,使用java实现的,亲测可以完美把资源解包出来。蓝月传奇BT的apk文件可以在本站下载到。


import org.apache.commons.compress.compressors.deflate.DeflateCompressorOutputStream;
import org.apache.commons.compress.compressors.deflate.DeflateParameters;

import java.io.*;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;


public  class ZLibUtil {


    /**
     * zlib打包
     */
    public static void compressZlib(File raw, File compressed){
        try {
            InputStream in = new FileInputStream(raw);

            if(compressed.exists()){
                compressed.deleteOnExit();
            }
            compressed.createNewFile();

            OutputStream os = new DeflaterOutputStream(new FileOutputStream(compressed));
            int length = 0;
            byte buffer[] = new byte[1024];
            while((length = in.read(buffer)) > 0){
                os.write(buffer,0,length);
            }
            in.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * zlib解压
     */
    public static void decompressZlib(File compressed, File raw){
        try {
            InflaterInputStream in = new InflaterInputStream(new FileInputStream(compressed));
            if(raw.exists()){
                raw.deleteOnExit();
            }
            raw.createNewFile();

            OutputStream out = new FileOutputStream(raw);
            byte[] buffer = new byte[1000];
            int len;
            while((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
            in.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void decompressZlib2(File compressed, File raw) {
        try {

            createFile(raw.getPath());

            OutputStream out = new FileOutputStream(raw);

            Inflater decompresser = new Inflater();
            decompresser.reset();
            decompresser.setInput(file2byte(compressed));

            byte[] buf = new byte[1024];
            while (!decompresser.finished()) {
                int i = decompresser.inflate(buf);
                out.write(buf, 0, i);
            }
            out.close();
            decompresser.end();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static String createFile(String path){
        try{
            File file = new File(path);

            if(!new File(file.getParent()).exists()){
                file.getParentFile().mkdirs();
            }
            if(file.exists()){
                file.deleteOnExit();
            }
            file.createNewFile();

            return file.getPath();
        }catch(Exception e){
            e.printStackTrace();
        }
        return "";
    }

    public static byte[] file2byte(File file){
        byte[] buffer = null;
        try{
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1){
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
        return buffer;
    }

    /**
     * 蓝月传奇BT版本,资源解密代码
	 * pack1.myd    4d 59 44 la  ..... 0d 0a 0d 0a
     * 单个文件的结尾 ae 42 60 82
     * @param fileName
     * @param dist
     */
    public static void decPack(String fileName,String dist) {
        try {
            FileInputStream fis = new FileInputStream(fileName);
            FileOutputStream fos = null;
            int fileCount = 0;
            int type = 0;
            int length = 0;
            int fileSize = 0;
            StringBuffer sb = new StringBuffer();
            byte[] buffer = new byte[4];
            while ((length = fis.read(buffer)) > 0) {
                System.out.println(".....................................................................");
                String item = HexUtils.toHexString(buffer,true);
                //System.out.println(item);
                sb.append(" " + item);
                if(type == 0) {
                    System.out.println("MYD格式头");
                    type = 1;
                }else if(type == 1){
                    // 01 00 00 00   0.0.0.1
                    String version = Integer.parseInt(HexUtils.toHexString(buffer[1]), 16) + "." +
                            Integer.parseInt(HexUtils.toHexString(buffer[0]), 16);
                    System.out.println("版本号:" + version);
                    type = 2;
                }else if (type == 2){
                    int count = Integer.parseInt(HexUtils.toHexString(buffer[3]) + HexUtils.toHexString(buffer[2]) + HexUtils.toHexString(buffer[1]) + HexUtils.toHexString(buffer[0]), 16);
                    System.out.println("文件数量:" + count);
                    type = 3;
                }else if (type == 3){
                    int totalSize = Integer.parseInt(HexUtils.toHexString(buffer[3]) + HexUtils.toHexString(buffer[2]) + HexUtils.toHexString(buffer[1]) + HexUtils.toHexString(buffer[0]), 16);
                    System.out.println("文件块大小" + totalSize);
                    type = 4;
                }else if (type == 4){
                    System.out.println("文件标识.............04 00 00 00................................");
                    type = 5;
                }else if (type == 5){
                    //高位在后 低位在前
                    fileSize = Integer.parseInt(HexUtils.toHexString(buffer[3]) + HexUtils.toHexString(buffer[2]) + HexUtils.toHexString(buffer[1]) + HexUtils.toHexString(buffer[0]), 16);
                    System.out.println("文件内容大小:" + fileSize);
                    //读取路径长度 1个字节
                    buffer = new byte[1];
                    type = 6;
                }else if(type == 6){
                    int count = Integer.parseInt(HexUtils.toHexString(buffer[0]), 16);
                    System.out.println("文件路径的长度:" + count);
                    buffer = new byte[count];
                    type = 7;
                }else if(type == 7){
                    String path = HexUtils.asciiToString(buffer);
                    System.out.println("文件路径:" + path);
                    String outPath = createFile(dist + path);
                    fos = new FileOutputStream(outPath);
                    //文件内容长度
                    buffer = new byte[fileSize];
                    type = 8;
                }else if(type == 8){

                    fos.write(buffer,0,length);

                    System.out.println("文件写入完成................................");

                    fos.flush();
                    fos.close();

                    fileCount ++;
                    //下一个文件开始 先是4个字节 第一个文件块的大小
                    buffer = new byte[4];
                    type = 3;

                    if(fileCount == 1){
                        System.out.println(sb.toString().toLowerCase());
                        break;
                    }
                }
            }
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void pack(String path){
        //4d 59 44 1a 文件类型
        //01 00 00 00 版本号
        //32 2a 00 00 包中文件数量
        //a6 00 00 00 第一个文件大小
        //04 00 00 00 文件内容开始标识
        //8e 00 00 00 文件内容大小
        //0b 路径长度
        //文件名
        //文件内容
        String hex = "4d 59 44 1a 01 00 00 00 01 00 00 00 a6 00 00 00 04 00 00 00 8e 00 00 00 0b 64 65 66 61 75 6c 74 2e 70 6e 67 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 c8 00 00 00 c8 01 03 00 00 00 97 96 3c dd 00 00 00 04 67 41 4d 41 00 00 b1 8f 0b fc 61 05 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 00 03 50 4c 54 45 00 00 00 a7 7a 3d da 00 00 00 01 74 52 4e 53 00 40 e6 d8 66 00 00 00 1c 49 44 41 54 58 c3 ed c1 81 00 00 00 00 c3 a0 f9 53 5f e1 00 55 01 00 00 00 00 7c 06 14 50 00 01 00 9f 23 15 00 00 00 00 49 45 4e 44 ae 42 60 82";

        try{
            File file = new File(path);
            if(file.exists()){
                file.deleteOnExit();
            }
            file.createNewFile();

            FileOutputStream fos = new FileOutputStream(path);
            byte[] buffer = HexUtils.toBytes(hex.replace(" ",""));
            fos.write(buffer,0,buffer.length);
            fos.flush();
            fos.close();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    public static void main(String[] args)  {

        String filename1 = "F:/workspace/lycq/pack1.myd";
        String filename2 = "F:/workspace/lycq/pack1/";
        String filename3 = "F:/workspace/lycq/pack1_new.myd";
        String filename4 = "F:/workspace/lycq/pack1_new/";

        String zlib = "F:/workspace/lycq/filelist.zlib";
        String zlibNew = "F:/workspace/lycq/filelist2.text";
        System.out.println("文件打包解包");

        try {
            ZLibUtil.pack(filename3);
            ZLibUtil.decPack(filename3,filename4);

            //ZLibUtil.decompressZlib2(new File(zlib),new File(zlibNew));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


HexUtils,java 二进制工具类

import java.util.List;

/**
 * Copyright ymbok.com
 * Author 还如一梦中
 * Date 2018/04/13 09:13
 * Info 二进制工具类
 */

public class HexUtils {

    /**
     * byte[]转16进制字符串
     * @param data
     * @return
     */
    public static String toHexString(byte[] data,boolean blank){
        final StringBuffer sb = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            sb.append(toHexString(data[i]));

            if(blank){
                if(i < data.length -1){
                    sb.append(" ");
                }
                /*if(i!=0 && (i+1)%4==0){
                    sb.append(" ");
                }*/
            }


        }
        return sb.toString();
    }

    /**
     * byte转16进制字符串
     * @param data
     * @return
     */
    public static String toHexString(byte data){
        String hex = Integer.toHexString(data & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        return hex.toUpperCase();
    }


    /**
     * 16进制字符串转byte[]
     * @param hexString
     * @return
     */
    public static byte[] toBytes(String hexString) {
        if(hexString == null || hexString.trim().equals("")) {
            return new byte[0];
        }

        byte[] bytes = new byte[hexString.length() / 2];
        for(int i = 0; i < hexString.length() / 2; i++) {
            String subStr = hexString.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    /**
     * byte表示的ascii转String
     * @param ascii
     * @return
     */
    public static String asciiToString(byte ascii) {
        StringBuffer sbu = new StringBuffer();
        sbu.append((char)ascii);
        return sbu.toString();
    }

/**
     * byte表示的ascii转String
     * @param asciis
     * @return
     */
    public static String asciiToString(byte[] asciis) {
        StringBuffer sbu = new StringBuffer();
        for(int i=0;i<asciis.length;i++){
            sbu.append((char)asciis[i]);
        }
        return sbu.toString();
    }

    /**
     * 数据连接
     * @param dataRow
     * @return
     */
    public static byte[] linkData(List<byte[]> dataRow){

        int length = 0;
        for(byte[] byteDataItem : dataRow){
            length += byteDataItem.length;
        }
        byte[] data = new byte[length];
        int index = 0;
        for(int i=0;i<dataRow.size();i++){
            byte[] bs = dataRow.get(i);
            for(byte b:bs){
                data[index++] = b;
            }
        }
        return  data;
    }

    /**
     * 字符串不足长度补足
     * @param str
     * @param strLength
     * @return
     */
    public static String addZeroForNum(String str, int strLength) {
        int strLen = str.length();
        if (strLen < strLength) {
            while (strLen < strLength) {
                StringBuffer sb = new StringBuffer();
                sb.append("0").append(str);
                str = sb.toString();
                strLen = str.length();
            }
        }

        return str;
    }

    /**
     * 校验和
     * @param data
     * @return
     */
    public static String sum(byte [] data){
        int sum = 0;
        for(byte b:data){
            sum += (int)(b & 0xFF);
        }
        //不足8位补0
        String sumStr = String.format("%08x",sum);
        //每2位哟个空格拆分
        String regex = "(.{2})";
        sumStr = sumStr.replaceAll (regex, "$1 ").trim();
        return sumStr;
    }

    /**
     * 校验和
     * @param hexString  16进制字符串
     * @return
     */
    public static int sum(String hexString){
        byte[] data = toBytes(hexString);
        int sum = 0;
        for(byte b:data){
            sum += (int)(b & 0xFF);
        }
        return sum;
    }
}


本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。

 关于作者
 热门教程
蓝月传奇BT版本全套资源解密算法
蓝月传奇BT版本全套资源解密算法,由于游戏APK中的角色怪我地图等资源进行了打包加密,我们有的时候想进行一些修改,那么
2023-08-15
剑道仙尊
109
能用于cocos2d-x NDK的wstring和string的转换代码
std::string WString2String(const std::wstring&amp; wstr){
2022-12-19
剑道仙尊
115
《传奇世界》手游修改教程之怪物掉落设置
下面讲解如何修改传世世界手游中的物品掉落,再原始的版本中,掉落的设置无法满足玩家的喜欢,我们需要自己修改,有简单的
2022-07-06
剑道仙尊
318
《传奇世界》手游修改教程之道士BB召唤
道士控制自己技能召唤的宝宝,服务端/data/sbin/resource/script/system/skill
2022-07-06
剑道仙尊
219
《传奇世界》手游修改教程之攻沙时间修改
客户端和服务端ShaWarDB,关键的字段是时间逗号后面那个数字: --攻沙时间设置 改为3天后 local It
2022-07-06
剑道仙尊
158
《传奇世界》手游修改教程之Luac4加密
Lua是游戏的脚本一般不会直接打包到app里,要先加密为luac4,在传奇世界手游里android可以支持luac
2022-07-06
剑道仙尊
455
《一梦传世》元神版本纯源码手工编译教程
《一梦传世》 元神 版本纯源码手工编译 全部文件包含服务端与客户端(其中包含AndroidStudio工程,E
2022-07-06
剑道仙尊
678
白鹭冰雪源码编译服务端VIP教程
2022-07-02
剑道仙尊
371
白鹭冰雪源码编译客户端VIP教程
2022-07-02
剑道仙尊
263
刺客传奇引擎架设教程
荐服务端系统环境 Win Server 2008 64位 一、将服务端拷贝到服务器,解压YmcqServer.zip。
2022-06-07
剑道仙尊
257