Welcome to Yumao′s Blog.
這章應該算是SqPack的最終拆解記錄了
在之前的幾篇文章中已經說了
如何定位到各種文件塊
並且解析文件頭以獲取文件大小
以下需要做到的僅僅是提取文件而已
按照上一章的内容來説
我們分析到的各個文件都是有一個
0x10長度的文件頭
記錄了文件的大小
那麽我們就從文件頭之後
開始轉儲文件内容 按照解壓前的大小
順帶這裡講一個小段子吧
因爲之前從文件頭分析出文件壓縮過
但是不清楚是否壓縮以及加密
就找了個朋友發了幾段内容給他
在即將發出第二段内容的時候
這個朋友就回我是Zlib壓縮了
說這麽明顯的尾部特徵…
看來我真的是雞丁~
言歸正傳
既然知道只是Zlib加密的話
獲取到文件内容之後
並且知道文件壓縮前後大小
那麽直接調用Zlib解壓就好
順帶説明下
這裡提取的文件塊内容
的的確確是Zlib壓縮產物
不過不帶Zlib的標準頭和AB32尾巴
所以需要自己加上頭尾
然後交給Zlib解壓導出文件即可
老樣子 代碼如下:
private static void outputFile(RandomAccessFile randomAccessFile,long addr) throws Exception{ //進行壓縮前後文件長度獲取 int[] size = getFileLength(randomAccessFile,addr); System.out.println("文件大小爲:"+Arrays.toString(size)); // TODO之後再寫有問題的處理塊方法 先跳過 if(size[0]/size[1]<250){ //將指針偏移到數據開始部分 randomAccessFile.seek(addr+0x10); //開始讀取到壹個臨時數組 byte[] tmp = new byte[size[0]]; for(int i=0;i<(int)size[0];i++){ tmp[i] = randomAccessFile.readByte(); } //准備好頭和尾 byte header[] = {(byte) 0x58,(byte) 0x85}; byte footer[] = HexUtils.HexString2Bytes(Long.toHexString(adler32(tmp,(int)size[0]))); //組合數組 byte[] hexBytes = new byte[header.length+tmp.length+footer.length]; System.arraycopy(header, 0, hexBytes, 0, header.length); System.arraycopy(tmp, 0, hexBytes, header.length , tmp.length); System.arraycopy(footer, 0, hexBytes, header.length+tmp.length , footer.length); //解壓 byte[] uncompr=uncompress(hexBytes,(int)size[1]); //提取解壓之後的文件頭說明 設置爲文件的擴展名 byte[] extension = new byte[8]; System.arraycopy(uncompr, 0, extension, 0, 8); //輸出文件 File fileOut = new File("D:\\sqdat\\"+Long.toHexString(addr)+".dat"); FileOutputStream fos = new FileOutputStream(fileOut); fos.write(uncompr); fos.flush(); fos.close(); } } //Mark工具 private static int adler32(byte[] inB,int size){ final int a32mod=65521; int s1=1,s2=0; for(int i=0;i<size;i++){ int b = inB[i]; s1 = (s1 + b )%a32mod; s2 = (s2 + s1)%a32mod; } return (int)((s2<<16)+s1); } //Zlib解壓工具 private static byte[] uncompress(byte[] data,int length){ int err; int uncomprLen = length; byte[] uncompr = new byte[uncomprLen]; ZStream d_stream = new ZStream(); err = d_stream.inflateInit(); CHECK_ERR(d_stream, err, "inflateInit"); d_stream.next_in = data; d_stream.next_in_index = 0; d_stream.next_out = uncompr; d_stream.next_out_index = 0; while (d_stream.total_out < uncomprLen && d_stream.total_in < uncomprLen) { d_stream.avail_in = d_stream.avail_out = 1; err = d_stream.inflate(JZlib.Z_NO_FLUSH); if (err == JZlib.Z_STREAM_END) { break; } CHECK_ERR(d_stream, err, "inflate"); } err = d_stream.inflateEnd(); CHECK_ERR(d_stream, err, "inflateEnd"); byte[] unzipfile = new byte[(int) d_stream.total_out]; System.arraycopy(uncompr, 0, unzipfile, 0, unzipfile.length); return unzipfile; } //Zlib解壓檢錯工具 static void CHECK_ERR(ZStream z, int err, String msg) { if(err!=JZlib.Z_OK){ if(z.msg!=null) System.out.print(z.msg+" "); System.out.println(msg+" error: "+err); System.exit(1); } }
至於運行之後的内容
大家去找輸出文件夾吧
順帶說下文本文件是使用UTF-8編碼的喔~
最後給出Zlib的jar包:JZlib
以上 轉載請説明出處喔~
英雄放一下源码到git吧
請問是有什麼不明白的地方嗎
有問題的話可以找我探討喔
好的,我将您的代码重新封装成c++的工程,将一些异常抛出,但是在000000.win32.dat0里面并不能很好的运行,zlib解压的时候会提示Z_DATA_ERROR,我检查了偏移和大小都没发现问题,请帮助我
个人认为这个解包方式还是有点误差的
但是毕竟没有得到真正的解包方案
所以纯粹就是靠个人猜测而已
事实表明拆包也是有一点的成果
欢迎找我一起探讨下深入拆包方案
联系方案在博客footer中有