zlib DEFLATE एल्गोरिथ्म के साथ संकुचित डेटा चारों ओर एक पतली आवरण है और RFC1950 में परिभाषित किया गया है:
A zlib stream has the following structure:
0 1
+---+---+
|CMF|FLG| (more-->)
+---+---+
(if FLG.FDICT set)
0 1 2 3
+---+---+---+---+
| DICTID | (more-->)
+---+---+---+---+
+=====================+---+---+---+---+
|...compressed data...| ADLER32 |
+=====================+---+---+---+---+
तो यह पहले कम से कम दो, संभवतः छह बाइट्स और एक साथ 4 बाइट कहते हैं कच्चे डिफलेट संपीड़ित डेटा के बाद ADLER32 चेकसम।
पहले बाइट सीएमएफ (संपीड़न विधि और झंडे) है, जो मुख्यमंत्री (संपीड़न विधि) (पहले 4 बिट्स) और CINFO (संपीड़न जानकारी) (पिछले 4 बिट्स) में विभाजित है शामिल ।
इससे यह स्पष्ट है कि दुर्भाग्यवश पहले से ही पहले दो बाइट्स ज़्लिब स्ट्रीम के संपीड़न विधि और सेटिंग्स के आधार पर बहुत भिन्न हो सकते हैं।
सौभाग्य से, मैं ADLER32 एल्गोरिदम के लेखक मार्क एडलर द्वारा एक पोस्ट पर ठोकर खाई, जहां वह lists the most common and less common combinations of those two starting bytes।
कि रास्ते से बाहर के साथ
, चलो हम कैसे zlib जांच करने के लिए अजगर का उपयोग कर सकते पर ध्यान दें:
>>> import zlib
>>> msg = 'foo'
>>> [hex(ord(b)) for b in zlib.compress(msg)]
['0x78', '0x9c', '0x4b', '0xcb', '0xcf', '0x7', '0x0', '0x2', '0x82', '0x1', '0x45']
तो पायथन के zlib
मॉड्यूल के द्वारा बनाई गई (डिफ़ॉल्ट विकल्पों का उपयोग कर) zlib डेटा 78 9c
साथ शुरू होता है । हम उस स्क्रिप्ट को बनाने के लिए इसका उपयोग करेंगे जो एक कस्टम फ़ाइल प्रारूप लिखने के लिए एक प्रस्तावना को जोड़ता है, कुछ zlib संपीड़ित डेटा और एक पाद लेख।
हम तो एक दूसरे स्क्रिप्ट है कि दो बाइट पैटर्न के लिए एक फ़ाइल को स्कैन करता है लिखने सब कुछ है कि एक zlib धारा के रूप में इस प्रकार है और का पता लगा लेता decompressing शुरू होता है जहां धारा समाप्त होता है और पाद लेख शुरू होता है।
create.py
import zlib
msg = 'foo'
filename = 'foo.compressed'
compressed_msg = zlib.compress(msg)
data = 'HEADER' + compressed_msg + 'FOOTER'
with open(filename, 'wb') as outfile:
outfile.write(data)
यहाँ हम msg
ले, zlib के साथ यह सेक, और एक शीर्ष लेख और पाद लेख इससे पहले कि हम यह एक फाइल करने के लिए लिखने के साथ उसके दोनों ओर।
शीर्षलेख और पाद लेख इस उदाहरण में निश्चित लंबाई के हैं, लेकिन वे निश्चित रूप से मनमाने ढंग से, अज्ञात लंबाई हो सकते हैं।
अब ऐसी स्क्रिप्ट के लिए जो ऐसी फ़ाइल में zlib स्ट्रीम ढूंढने का प्रयास करता है। क्योंकि के लिए यह उदाहरण हम जानते हैं कि मार्कर को उम्मीद है कि मैं केवल एक का उपयोग कर रहा हूं, लेकिन स्पष्ट रूप से सूची ZLIB_MARKERS
ऊपर वर्णित पोस्ट के सभी मार्करों से भरी जा सकती है।
फ़ाइल की शुरुआत में
प्रारंभ और एक दो बाइट खोज खिड़की बनाने के लिए:
ident.py
import zlib
ZLIB_MARKERS = ['\x78\x9c']
filename = 'foo.compressed'
infile = open(filename, 'r')
data = infile.read()
pos = 0
found = False
while not found:
window = data[pos:pos+2]
for marker in ZLIB_MARKERS:
if window == marker:
found = True
start = pos
print "Start of zlib stream found at byte %s" % pos
break
if pos == len(data):
break
pos += 1
if found:
header = data[:start]
rest_of_data = data[start:]
decomp_obj = zlib.decompressobj()
uncompressed_msg = decomp_obj.decompress(rest_of_data)
footer = decomp_obj.unused_data
print "Header: %s" % header
print "Message: %s" % uncompressed_msg
print "Footer: %s" % footer
if not found:
print "Sorry, no zlib streams starting with any of the markers found."
विचार यह है।
एक-बाइट वृद्धि में खोज विंडो को आगे ले जाएं।
प्रत्येक विंडो के लिए जांच करें कि क्या यह दो बाइट मार्करों में से किसी एक से मेल खाता है, जिसे हम परिभाषित करते हैं।
यदि कोई मिलान मिलता है, तो प्रारंभिक स्थिति रिकॉर्ड करें, खोज बंद करें और निम्नानुसार होने वाली सभी चीज़ों को कम करने का प्रयास करें।
अब, धारा के अंत खोजने दो मार्कर बाइट्स की तलाश के रूप में के रूप में तुच्छ नहीं है। zlib धाराओं को न तो एक निश्चित बाइट अनुक्रम द्वारा समाप्त किया जाता है और न ही उनकी लंबाई किसी भी शीर्ष लेख फ़ील्ड में इंगित होती है। इसकी बजाय इसे द्वारा चार बाइट ADLER32 चेकसम समाप्त कर दिया गया है जो इस बिंदु तक डेटा से मेल खाना चाहिए।
तरह से यह काम करता है कि आंतरिक सी समारोह inflate()
लगातार धारा को संपीड़ित के रूप में यह इसे पढ़ता है की कोशिश कर रहा है, और रहता है अगर यह एक मिलान चेकसम, संकेत भर आता है कि अपनी कॉलर को, जो यह दर्शाता है कि के बाकी डेटा ज़्लिब स्ट्रीम का हिस्सा नहीं है।
पायथन में यह व्यवहार zlib.decompress()
पर कॉल करने के बजाय डिकंप्रेशन ऑब्जेक्ट्स का उपयोग करते समय सामने आया है। पर Decompress
ऑब्जेक्ट पर कॉलिंग string
में एक zlib स्ट्रीम को डिक्रप्रेस करेगा और स्ट्रीम का हिस्सा था जो डिकंप्रेस्ड डेटा वापस कर देगा। स्ट्रीम का पालन करने वाली हर चीज unused_data
में संग्रहीत की जाएगी और बाद में पुनर्प्राप्त की जा सकती है।
यह पहली स्क्रिप्ट के साथ बनाई गई एक फ़ाइल पर निम्नलिखित उत्पादन का उत्पादन करना चाहिए:
Start of zlib stream found at byte 6
Header: HEADER
Message: foo
Footer: FOOTER
उदाहरण आसानी से इसे मुद्रण के बजाय एक फ़ाइल असंपीड़ित संदेश लिखने के लिए संशोधित किया जा सकता। फिर आप पहले zlib संपीड़ित डेटा का विश्लेषण कर सकते हैं, और हेडर और पाद लेख में मेटाडेटा में ज्ञात फ़ील्ड को पहचानने का प्रयास कर सकते हैं।
क्या मैं आपके प्रश्न को सही समझ रहा हूं: आपके पास फ़ाइल प्रारूप का कोई उचित विनिर्देश नहीं है और फ़ाइल प्रारूप की संरचना और लेआउट की पहचान करने के लिए रिवर्स इंजीनियरिंग तकनीकों के बारे में जानना चाहते हैं? –
@ लुकासग्राफ मुझ पर बहुत मुश्किल नहीं लग रहा है, लेकिन जवाब है ... हाँ! यह इस फ़ाइल प्रारूप के साथ हमारी कंपनी का आखिरी प्रयास है, लेकिन हमारे लिए कोई भी प्रगति महत्वपूर्ण होगी। – heltonbiker
ठीक है, बस इतना चाहता था कि मैं सही तरीके से प्रश्न समझूं। मेरा निर्णय लेने का मतलब नहीं था :) लेकिन पाइथन तो संभवतः कार्यान्वयन के लिए भाषा के रूप में लागू होता है, एक बार जब आप रिवर्स इंजीनियरिंग को फ़ाइल प्रारूप (एक बार कार्यान्वयन से अधिक समय लेते हैं) कर लेते हैं। –