簡體   English   中英

使用python的gzip出現問題/“如何知道正在使用哪種壓縮?”

[英]Trouble using python's gzip/“How do I know what compression is being used?”

好的,所以我有一個使用數據包進行通信的開源Java客戶端/服務器程序。 我正在嘗試為上述程序編寫python客戶端,但數據包的內容似乎已壓縮。 快速瀏覽源代碼建議使用gzip作為壓縮模式(因為這是我在代碼中可以找到的唯一導入的壓縮模塊),但是當我將其中一個數據包中的數據保存到wireshark中並嘗試執行時,

import gzip
f = gzip.open('compressed_file')
f.read()

它告訴我這不是gzip文件,因為標題錯誤。 有人可以告訴我我在這里做錯了什么嗎? 保存后是否更改或弄亂了格式? 在嘗試在數據包上運行此塊之前,是否需要從數據包中剝離一些多余的數據?

    if (zipped) {

        // XML encode the data and GZIP it.
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Writer zipOut = new BufferedWriter(new OutputStreamWriter(
                new GZIPOutputStream(baos)));
        PacketEncoder.encodeData(packet, zipOut);
        zipOut.close();

        // Base64 encode the commpressed data.
        // Please note, I couldn't get anything other than a
        // straight stream-to-stream encoding to work.
        byte[] zipData = baos.toByteArray();
        ByteArrayOutputStream base64 = new ByteArrayOutputStream(
                (4 * zipData.length + 2) / 3);
        Base64.encode(new ByteArrayInputStream(zipData), base64, false);

編輯:好的,抱歉,我在這里要求提供信息。 這是使用Wireshark收集的,以偵聽不同計算機上原始程序的兩個運行副本之間的通信。 為了獲得下面的十六進制流,我在Wireshark中使用了“復制->十六進制(字節流)”選項。

001321cdc68ff4ce46e4f00d0800450000832a85400080061e51ac102cceac102cb004f8092a9909b32c10e81cb25018f734823e00000100000000000000521f8b08000000000000005bf39681b59c85818121a0b4884138da272bb12c512f27312f5dcf3f292b35b9c47ac2b988f902c59a394c0c0c150540758c250c5c2ea5b9b9950a2e89258900aa4c201a3f000000

我知道這將在其中包含字符串“虛擬數據”。 我相信它還應該包含“ Jonathanb”(我用來發送消息的玩家名稱)和整數80(就我從代碼中收集的而言,“ 80”是“ Chat”的命令#)。

您可以嘗試直接使用標准庫模塊zlibgzip將其用於壓縮/解壓縮部分。 如果整個數據包不被喜歡的解壓縮功能,你可以嘗試使用不同的值wbits和/或割掉該數據包的前幾個字節(如果你可以“反向工程”究竟是如何在Java代碼壓縮該包-甚至只是了解正在使用的wbits數,或者是否在壓縮數據之前放置了任何前綴-當然,這將極大地幫助您。

您可能會對文件本身造成的唯一“損壞”是在Windows上,如果您在未指定'wb'使用二進制模式的情況下編寫了該文件-在Windows上以“文本模式”編寫該文件將使該文件無法使用。 只是說...!-)

如果您泄露以下內容,將大有幫助:

(0)導致您得出以下結論:“數據包的內容似乎已壓縮”

(1)用於寫數據包的軟件包的(a)源和(b)文檔的URL

(2)樣本包的內容

(a) print repr(open('file_saved_from_wireshark', 'rb').read())

(b)萬一通過Wireshk進行的長途旅行使水變得渾濁,請將其插入您的Python客戶端中:

print repr(a_sample_packet)

(3)您收到的確切錯誤消息(復制/粘貼)

OP提供了數據包的十六進制轉儲后進行更新

這段代碼:

import binascii, sys, cStringIO, gzip, struct, zlib
# guff is allegedly a "packet", formatted as 2 hex characters per byte
guff = "001321cdc68ff4ce46e4f00d0800450000832a85400080061e51ac102cceac102cb004f8092a9909b32c10e81cb25018f734823e00000100000000000000521f8b08000000000000005bf39681b59c85818121a0b4884138da272bb12c512f27312f5dcf3f292b35b9c47ac2b988f902c59a394c0c0c150540758c250c5c2ea5b9b9950a2e89258900aa4c201a3f000000"
guff2 = binascii.unhexlify(guff)
print "raw input: len=%d repr=%r" % (len(guff2), guff2)
# gzip spec: http://www.faqs.org/rfcs/rfc1952.html
GZIP_HDR = "\x1F\x8B\x08"
gzpos = guff2.find(GZIP_HDR)
if gzpos == -1:
    print "Can't find gzip header"
    sys.exit(1)
print gzpos, "bytes before gzipped data"
gzipped = guff2[gzpos:]
packet_crc, packet_orig_len = struct.unpack("<II", gzipped[-8:])
print "packet_crc, packet_orig_len:", hex(packet_crc), packet_orig_len
fobj = cStringIO.StringIO(gzipped)
zf = gzip.GzipFile(fileobj=fobj)
payload = zf.read()
print "payload: len=%d repr=%r" % (len(payload), payload)
print "crc32(payload):", hex(zlib.crc32(payload))

當使用Python 2.6.4運行時,產生了此輸出(由Windows的“命令提示符”終端在col 80處包裝):

raw input: len=145 repr="\x00\x13!\xcd\xc6\x8f\xf4\xceF\xe4\xf0\r\x08\x00E\x00\x
00\x83*\x85@\x00\x80\x06\x1eQ\xac\x10,\xce\xac\x10,\xb0\x04\xf8\t*\x99\t\xb3,\x1
0\xe8\x1c\xb2P\x18\xf74\x82>\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00R\x1f\x8b\x0
8\x00\x00\x00\x00\x00\x00\x00[\xf3\x96\x81\xb5\x9c\x85\x81\x81!\xa0\xb4\x88A8\xd
a'+\xb1,Q/'1/]\xcf?)+5\xb9\xc4z\xc2\xb9\x88\xf9\x02\xc5\x9a9L\x0c\x0c\x15\x05@u\
x8c%\x0c\\.\xa5\xb9\xb9\x95\n.\x89%\x89\x00\xaaL \x1a?\x00\x00\x00"
63 bytes before gzipped data
packet_crc, packet_orig_len: 0x1a204caa 63
payload: len=63 repr='\xac\xed\x00\x05w\x04\x00\x00\x00Pur\x00\x13[Ljava.lang.Ob
ject;\x90\xceX\x9f\x10s)l\x02\x00\x00xp\x00\x00\x00\x01t\x00\nDummy Data'
crc32(payload): 0x1a204caa

評論/問題:

  1. 該數據包長145個字節。 一個數據包約為2900字節的想法發生了什么?

  2. 該數據包是尚未分析的63字節數據,后跟一個82字節的gzip流,該流將(!)解壓縮為63字節。 gzip流之后沒有數據-通過將數據包的最后8個字節與計算出的gzip值進行比較來驗證。 它包含預期的“虛擬數據”,但用戶標識“ johnathonb”不存在(或混淆或加密)。

  3. 數據包結構與我們猜測正在使用的代碼不匹配(沒有XML,沒有base64)。

  4. 壓縮后的數據包含字符串“ java.lang.Object”,這可能是某些Java序列化協議的症狀。 Lasciate ogni speranza,voi qu'entrate

這可能與RFC之一兼容1950年1951年1952年

由於名稱為GZIP,因此我首先檢查1952。然后嘗試ZLIB,1950。最后是DEFLATE(1951)。

DotNetZip是一個.NET庫,它允許.NET應用程序讀取符合任何這些格式的數據流。 如果您有一個符合以上條件之一的流,則可以通過依次嘗試使用每個DotNetZip的流讀取該流來非常快速地確定是哪個流。 GZipStreamZlibStreamDeflateStream 其中一個將工作,而其他則不會。

我不知道有那些流的Java庫。 並不意味着它不存在。 只是我不知道一個。

DotNetZip是免費的,可在Windows + Mono,Linux + Mono以及Windows + .NET上運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM