压在透明的玻璃上c-国产精品国产一级A片精品免费-国产精品视频网-成人黄网站18秘 免费看|www.tcsft.com

修復損壞的gz或tar.gz壓縮文件之方法篇

  接修復損壞的gzip壓縮文件之原理篇,再次引用GZIP結構圖:

修復損壞的gz或tar.gz壓縮文件之方法篇

  在上一篇中已知,修復一個損壞的gzip文件的關鍵環節在于找到下一個正常壓縮包的起始點。根據結構圖中的信息可知,每個壓縮包的開始結構中有是否到達尾部標志、使用的哈夫曼樹類型、以及3個哈夫曼樹的樹元素個數等。如果某個gzip文件中間有一個壞扇區,要找到壞扇區后的一個正常起點,僅需按位右移,一直移位到可以正常解壓的某個位,就可能找到了正確的壓縮包起始。而根據gzip文件的壓縮作業窗口為32KB大小推算,這個遍歷不會超過64KB即可找到。在內存中快速循環可以很快找到,但需要有明確的判斷錯誤的方法。

  首先可以明確的是結尾標志,應該為0(我們是從損壞的點向后查)。而哈夫曼樹類型也大致應該是動態哈夫曼(0x02),cl1的元素個數應該取值為257到286之間(包含邊界),cl2的元素個數應小于等于30,ccl的元素個數取值可為1-15(包含邊界)。

  其實,還可以參考的東西有,解開的哈夫曼樹是否異常,或者通過規律性原則找到最后一個取值為256的值,但這些算法應該是較為麻煩的,有上面的算法連續校驗幾個壓縮塊就足夠了。

  具體方法是對gzip的源碼做修改,進行遍歷。因時間關系,未做成通用工程,僅快速修改了部分代碼。大致的修改點為:

  一、找到損壞點:

  在unzip.c中,

  error("invalid compressed data–format violated");

  這一行前,獲取當前解碼字節位置即可。

  二、遍歷找到損壞點:

  1、inflate.c文件中,改

  if (nl > 286 || nd > 30)

  #endif

  return 1;

  為:

  if (nl > 286 || nd > 30||nl <257 || nd <1)

  #endif

  return 1;

  2、inflate.c文件中,在int inflate_block(e)函數中

  在如下代碼前

  bb = b;

  bk = k;

  加入代碼:

  if ((t != 2) || (*e != 0))

  return 2;

  3、inflate.c文件中,在int inflate_block(e)函數尾部

  把if (t == 0) 與if (t == 1)的情況都直接返回錯誤值2。

  4、inflate.c文件中,函數int inflate()中,改

  if ((r = inflate_block(&e)) != 0)

  return r;

  end

  為:

  unsigned t;           /* block type */

  register ulg b;       /* bit buffer */

  register unsigned k;  /* number of bits in bit buffer */

  while (inptr <= insize)

  {

  unsigned int tptr = inptr;

  unsigned int tbk = bk;

  unsigned long tbb = bb;

  unsigned int twp = wp;

  long long tstart = *(long long*)(inbuf + tptr);

  if ((r = inflate_block(&e)) != 0)

  {

  inptr = tptr;

  bb = tbb;

  bk = tbk;

  wp = twp;

  b = bb;

  k = bk;

  NEEDBITS(1)

  DUMPBITS(1)

  }

  else

  {

  printf("get by www.sjhf.net!"); //也可輸出tstart,bb,bk 值,轉載時請保留版權信息:www.sjhf.net 張宇

  }

  }

  此4步完成后,試著調試這個錯誤的.gz文件,當然,也可以在代碼中解釋完頭部結構后加一個seek,直接seek到損壞位置。

  通常情況下,輸出printf(“get by www.sjhf.net!”)這行代碼時,已經找到了正確的起始位。

  找到起始位后,也可以構造或拷貝一個正常的gzip文件頭,再拼接好找到的位流,即可解壓了。(如果位流不是字節對齊的,可能要全部做位移)。拼接后很多壓縮文件就可以打開甚至于解壓了,不過,有可能會報錯,主要是尾部的校驗和大小錯,其實可以忽略。

  如果拼接好了linux下,不能直接用“gzip –d”解壓,因其crc有錯誤,會導致解壓到99%后報錯,然后把文件刪除,換成管道命令即可:

  gunzip < damaged.gz > damaged

  文章來源:http://zhangyu.blog.51cto.com/197148/1592611

上一篇:安卓防火墻 PS DroidWall

下一篇:改造 Cydia Substrate 框架用于函數內代碼的HOOK