首页
社区
课程
招聘
[原创]《我叫mt》数据包解包记录(java版)
发表于: 2013-6-14 11:47 14157

[原创]《我叫mt》数据包解包记录(java版)

2013-6-14 11:47
14157

临时会员,希望这个可以成为转正贴。

看到用ida获取key,然后用npk方法解包的帖子,但是本人是java出身,而且汇编也不好,gdb也不会用,就想到用代码直接解包。

思路:
1、找到文件列表。(# ID处就是文件列表开始的地方。)
2、把文件数据和文件列表数据分开。
3、根据文件列表还原文件数据。   

首先,第一步,找# ID,

第二步,写代码分离后面和前面的数据。
结果如图

部分关键代码:
//首先分离文件索引
                        args = ("cutfile -out "+INDEX_FILE+" -in "+DATA_FILE+" -off 0x3982e19 -len 0x39a0090").split(" ");
                        cutdata = new CutData();
                        result = cutdata.parseParams(args);//这里就是解析参数,输入文件,输入文件,数据开始位置和长度
                        if (result.equals(Tool.PARSE_SUC)) {
                                cutdata.excute();
                        } else {
                                cutdata.failed();
                        }

//分离出数据包
                        args = ("cutfile -out "+RESOURCE_FILE+" -in "+DATA_FILE+" -off 0 -len 0x3982e19").split(" ");
                        cutdata = new CutData();
                        result = cutdata.parseParams(args);//这里就是解析参数,输入文件,输入文件,数据开始位置和长度
                        if (result.equals(Tool.PARSE_SUC)) {
                                cutdata.excute();
                        } else {
                                cutdata.failed();
                        }

//分离方法
public void excute() {
                //这里的参数就是从上面那个方法解析出来的。
                String outfile = mparams[OUT_FILE];
                String infile = mparams[IN_FILE];
                String start = mparams[START_FILE];
                String end = mparams[FILE_LEN];
                int dataoff = Utils.parseString(start);
                int dataLen = Utils.parseString(end);

//                Utils.makeFile(outfile);

                byte[] data = Utils.getArrayByte(infile);//这个是读取文件,转成数组。
                if (data != null) {
                        if (dataLen > data.length - dataoff) {
                                dataLen = data.length - dataoff;
                        }
                        byte[] dest = new byte[dataLen];
                        System.arraycopy(data, dataoff, dest, 0, dataLen);//拷贝数组

                        Utils.writeFile(dest, outfile);//写入输出文件。
                } else {
                        Debug.print("没有获取到数据呢。");
                }
        }

第三步,根据数据文件从里面还原文件。
                        //从数据包里面分离数据文件。
                        args = ("splitmt -outfolder "+OUT_FOLDER+" -infile " +RESOURCE_FILE+" -indexfile "+INDEX_FILE).split(" ");
                        cutdata = new SplitMTData();
                        result = cutdata.parseParams(args);//解析参数,就是输出文件夹,解析文件路径,索引文件路径。
                        if (result.equals(Tool.PARSE_SUC)) {
                                cutdata.excute();
                        } else {
                                cutdata.failed();
                        }

//还原方法
public void excute() {
                //从上面参数取得
                String root = params[IDX_OUT];
                String infile = params[IDX_IN];
                String indexfile = params[IDX_INDEX];
                Utils.makeFolder(root);

                byte[] inarray = Utils.getArrayByte(infile);
                String index = new String(Utils.getArrayByte(indexfile));
                StringBuffer sb = new StringBuffer();
                sb.append((char)0x0d);
                sb.append((char)0x0a);
                String[] lines = index.split(sb.toString());
                sb = new StringBuffer();
                sb.append((char)9);
                //获取总长度,因为需要从后往前读文件。
                int endpoint = Utils.parseString("0x3982e19");
                /////////////////////////////////
                int size = lines.length;
                for (int i=size-1;i>=0;i--) {//这里需要从后面往前面读,最前面的是npk的文件头吧。
                        String[] cell = lines[i].split(sb.toString());
                        if (cell != null && cell.length > 3) {
                                if (cell[ID].trim().startsWith("#") || cell[ID].trim().equals("INT")) {//跳过索引文件的头2行
                                        continue;
                                }
                                int len = Integer.valueOf(cell[Size].trim());//读取此文件的大小。
                                String filename =  cell[Path].trim() + cell[Name].trim();
                                byte[] file = new byte[len];
                                endpoint -= len;
                                int srcpos = endpoint;
                                System.arraycopy(inarray, srcpos, file, 0, len);//拷贝
                                Utils.writeFile(file, root+"\\"+filename);//写入文件
//                                totalLen += len;
                        }
                }
        }
文件结构:


整个包太大,附上文件索引表和战斗的表。
fight.lua= ui.zip
file index = index .txt


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 5
支持
分享
最新回复 (12)
雪    币: 29
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
顶JAVA,只需一点付出她就会为你到处服务
2013-6-14 14:29
0
雪    币: 68
活跃值: (30)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
JAVA所有平台同吃呀。
2013-6-14 14:32
0
雪    币: 217
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这游戏现在挺火的!
2013-6-16 02:51
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
大神 ,不知道修改好之后怎么还原进去?
2013-6-29 21:19
0
雪    币: 319
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢 学习了。。。。
2013-6-30 13:14
0
雪    币: 124
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
还原后如何打包?是否按照这个思路逆序做就可?
2013-7-1 11:35
0
雪    币: 217
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
如何确定npk文件头的?木有懂
2013-7-1 11:52
0
雪    币: 7
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
嗯。是的。
2013-7-5 10:27
0
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
...各种学习了。不过java代码看的头大啊
2013-7-10 15:27
0
雪    币: 257
活跃值: (105)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
11
mark一下
2013-7-17 10:51
0
雪    币: 228
活跃值: (75)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
学习一下,不过看不懂java代码。。
2013-7-23 16:21
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
继续MARK
2013-8-20 01:14
0
游客
登录 | 注册 方可回帖
返回
//