蓝月传奇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;
}
}
本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。