Welcome to Yumao′s Blog.
續上一個拆包記錄
獲得文件塊地址之後
我們就可以從對應的dat0文檔中
找到對應的文件塊了
這章就著重講下文件塊頭的解析
我們還是以前面例子的0a0000.win32.dat0文檔做例子
從前文寫的代碼中有幫我們找出三個地址
那麽我們就從第一個地址 53 B1 80 開始
附近的塊内容如下:
1 2 3 4 | 53b170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 53b180: 80 00 00 00 02 00 00 00 8c 1a 00 00 16 00 00 00 53b190: 13 00 00 00 01 00 00 00 00 00 00 00 80 09 8c 1a 53b1a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
接著還是給出個人對此段代碼的理解吧
1 2 3 4 5 6 7 8 9 10 11 12 13 | 0x53b180-0x53b183 文件頭的長度 0x53b184-0x53b187 未知 0x53b188-0x53b18b 解壓后的文件長度 0x53b80c-0x53b80f 未知 0x53b190-0x53b193 未知 0x53b194-0x53b197 文件塊中文件個數 之後的每八字節為一組 内容為塊内各個文件的説明 例如:本代碼塊只包含一個文件 所以有數據的部分只有0x53b198-0x53b19f 0x53b198-0x53b19b 文件起始相對第一個文件的偏移值 因爲是單文件所以這裡值為0 0x53b19c-0x53b19d 未知 0x53b19e-0x53b19f 單文件解壓后的大小 |
然後我們按照文件頭的長度偏移到文件開始部分
每個文件開始都會有長度為0x10也就是十六字節的文件頭
下面是此文件頭的例子:
1 | 53b200: 10 00 00 00 00 00 00 00 2d 09 00 00 8c 1a 00 00 |
依然是羽毛的解析時間
從多條案例來看是這樣的理解:
1 2 3 4 | 0x53b200-0x53b203 此條文件頭的長度 固定為0x10 0x53b204-0x53b207 全空 0x53b208-0x53b20b 文件壓縮前的長度 0x53b20e-0x53b20f 文件解壓后的長度 |
老樣子給出代碼
代碼實現的的功能暫時為
尋址到文件内容
獲取文件内容以及壓縮前後的大小
解密的話..下節講喔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | private static void getFileContent( long addr, String filePatch2) throws Exception { //解析同文件夾內的dat0文件地址 String dat0Path = filePath.substring( 0 ,filePath.indexOf( ".index" ))+ ".dat0" ; //開始讀取 RandomAccessFile randomAccessFile = new RandomAccessFile(dat0Path, "r" ); randomAccessFile.seek(addr); //進行標准數據頭格式判斷 if (addr<randomAccessFile.length()&&randomAccessFile.readByte()==( byte ) 0x80 ){ //數據頭長度獲取 long headerLength = getHeaderLength(randomAccessFile,addr); //數據段內文件個數獲取 int fileCount = getFileCount(randomAccessFile,addr); System.out.print( "\r該數據塊內文件個數爲:" + fileCount + " " ); //多文件讀取 先將指針偏移到說明頭 獲取文件長度 randomAccessFile.seek(addr+headerLength); //循環幹的事情 for ( int i= 0 ;i<fileCount;i++){ int count = i+ 1 ; System.out.print( "正在處理第 " + count + "個文件 " ); while (randomAccessFile.readByte()!=( byte ) 0x10 ){ //什麽都不做 就是偏移指針 直到跳到下壹段數據的開始 } //獲取指針 然後處理文件輸出 long nowAddr = randomAccessFile.getFilePointer()- 1 ; //搞定文件即可 System.out.print( "地址爲:" +Long.toHexString(nowAddr)+ " " ); outputFile(randomAccessFile,nowAddr); } } else { System.out.println(); } randomAccessFile.close(); } private static int getHeaderLength(RandomAccessFile randomAccessFile, long addr) throws Exception{ //按照分析前面四位應該是文件頭的長度 2^7對齊 randomAccessFile.seek(addr); byte [] tmp = new byte [ 4 ]; for ( int i= 3 ;i> 0 ;i--){ tmp[i] = randomAccessFile.readByte(); } return Integer.parseInt(HexUtils.Bytes2HexString(tmp).replace( " " , "" ), 16 ); } |
輸出結果參考:
1 2 3 4 | 文件塊地址爲: 53 B1 80 該數據塊內文件個數爲:1 正在處理第 1個文件 地址爲:53b200 文件大小爲:[2349, 6796] 文件塊地址爲: 18 文件塊地址爲: 64 00 |