mirror of
https://github.com/you0708/lznt1
synced 2026-06-08 18:32:11 +00:00
Add PyPI support
This commit is contained in:
@@ -4,25 +4,30 @@ Python implementation of LZNT1 compression/decompression.
|
||||
Note that the compression algorithm is not perfect, but compressed data can be decompressed by RtlDecompressBuffer.
|
||||
|
||||
# How to use
|
||||
## Install
|
||||
```
|
||||
pip install lznt1
|
||||
```
|
||||
|
||||
## Compress / decompress
|
||||
```
|
||||
>>> import lznt1
|
||||
>>> compressed = lznt1.compress(data)
|
||||
>>> decompressed = lznt1.decompress(data)
|
||||
>>> decompressed = lznt1.decompress(compressed)
|
||||
```
|
||||
|
||||
## Test
|
||||
```
|
||||
C:\Users\you\Desktop>lznt1.py lznt1.py
|
||||
[*] input size = 6610 bytes, sha1 hash = 933dffa94c6ad78fb7f0396b2b1c39aa90065d57
|
||||
[*] size of compressed1: 2961
|
||||
[*] size of compressed2: 2512
|
||||
[*] sha1 hash of compressed1: d1116a2e5b0471de956e0df031466231c8cc7831
|
||||
[*] sha1 hash of compressed2: 6e8262dbe4988fe9b6d119b203c94201b0f6a4c4
|
||||
[*] sha1 hash of decompressed11: 933dffa94c6ad78fb7f0396b2b1c39aa90065d57
|
||||
[*] sha1 hash of decompressed12: 933dffa94c6ad78fb7f0396b2b1c39aa90065d57
|
||||
[*] sha1 hash of decompressed21: 933dffa94c6ad78fb7f0396b2b1c39aa90065d57
|
||||
[*] sha1 hash of decompressed22: 933dffa94c6ad78fb7f0396b2b1c39aa90065d57
|
||||
C:\Users\you\Desktop\ln>python test.py lznt1.py
|
||||
[*] input size = 4067 bytes, sha1 hash = 9887522d4088152ca434a5f275adcd99c2de338d
|
||||
[*] size of compressed1: 1280
|
||||
[*] size of compressed2: 1553
|
||||
[*] sha1 hash of compressed1: 64b9b5f92274e60d10f3ef0e517f563cc8d46bd6
|
||||
[*] sha1 hash of compressed2: 92e737ee1d2b468800169cc7b28854b392ac8395
|
||||
[*] sha1 hash of decompressed11: 9887522d4088152ca434a5f275adcd99c2de338d
|
||||
[*] sha1 hash of decompressed12: 9887522d4088152ca434a5f275adcd99c2de338d
|
||||
[*] sha1 hash of decompressed21: 9887522d4088152ca434a5f275adcd99c2de338d
|
||||
[*] sha1 hash of decompressed22: 9887522d4088152ca434a5f275adcd99c2de338d
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import struct
|
||||
import sys
|
||||
import copy
|
||||
import ctypes
|
||||
from hashlib import sha1
|
||||
|
||||
def _decompress_chunk(chunk):
|
||||
size = len(chunk)
|
||||
@@ -103,7 +101,7 @@ def _compress_chunk(chunk):
|
||||
|
||||
# try to find more compressed pattern
|
||||
offset2, length2 = _find(chunk[:len(chunk) - len(blob)+1], blob[1:], max_len)
|
||||
if length < length2+1:
|
||||
if length < length2:
|
||||
length = 0
|
||||
|
||||
if length > 0:
|
||||
@@ -138,48 +136,3 @@ def compress(buf, chunk_size=0x1000):
|
||||
buf = buf[chunk_size:]
|
||||
|
||||
return out
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='LZNT1 tester (You must run this on Windows)')
|
||||
parser.add_argument("FILE", help="Specify a file for compression/decompression test")
|
||||
args = parser.parse_args()
|
||||
with open(args.FILE, 'rb') as fp:
|
||||
data = fp.read()
|
||||
#data = "Hello world!" * 800
|
||||
print('[*] input size = {} bytes, sha1 hash = {}'.format(len(data), sha1(data).hexdigest()))
|
||||
compressed1 = compress(data)
|
||||
decompressed11 = decompress(compressed1)
|
||||
|
||||
buf_decompressed = ctypes.create_string_buffer(len(data)*2)
|
||||
final_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlDecompressBuffer(2, buf_decompressed, ctypes.sizeof(buf_decompressed), ctypes.c_char_p(compressed1), len(compressed1), ctypes.byref(final_size))
|
||||
decompressed12 = buf_decompressed.raw[:final_size.value]
|
||||
|
||||
buf_compressed = ctypes.create_string_buffer(len(data)*2)
|
||||
work_size = ctypes.c_ulong(0)
|
||||
work_frag_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlGetCompressionWorkSpaceSize(2, ctypes.byref(work_size), ctypes.byref(work_frag_size))
|
||||
workspace = ctypes.create_string_buffer(work_size.value)
|
||||
final_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlCompressBuffer(2, ctypes.c_char_p(data), len(data), buf_compressed, ctypes.sizeof(buf_compressed), 4096, ctypes.byref(final_size), workspace)
|
||||
compressed2 = buf_compressed.raw[:final_size.value]
|
||||
|
||||
decompressed21 = decompress(compressed2)
|
||||
|
||||
buf_decompressed = ctypes.create_string_buffer(len(data)*2)
|
||||
final_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlDecompressBuffer(2, buf_decompressed, ctypes.sizeof(buf_decompressed), buf_compressed, ctypes.sizeof(buf_compressed), ctypes.byref(final_size))
|
||||
decompressed22 = buf_decompressed.raw[:final_size.value]
|
||||
|
||||
print('[*] size of compressed1: {}'.format(len(compressed1)))
|
||||
print('[*] size of compressed2: {}'.format(len(compressed2)))
|
||||
print('[*] sha1 hash of compressed1: {}'.format(sha1(compressed1).hexdigest()))
|
||||
print('[*] sha1 hash of compressed2: {}'.format(sha1(compressed2).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed11: {}'.format(sha1(decompressed11).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed12: {}'.format(sha1(decompressed12).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed21: {}'.format(sha1(decompressed21).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed22: {}'.format(sha1(decompressed22).hexdigest()))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name="lznt1",
|
||||
version="0.1.2",
|
||||
author="You Nakatsuru",
|
||||
author_email="you0708@users.noreply.github.com",
|
||||
license="Apache License 2.0",
|
||||
description="Python module for LZNT1 compression/decompression",
|
||||
long_description="A Python module which provides compress/decompress features uzing LZNT1 algorithm. This doesn't reuqire ntdll.RtlCompressBuffer/RtlDecompressBuffer",
|
||||
py_modules=["lznt1"],
|
||||
url="https://github.com/you0708/lznt1/",
|
||||
)
|
||||
@@ -0,0 +1,49 @@
|
||||
import argparse
|
||||
import ctypes
|
||||
from hashlib import sha1
|
||||
import lznt1
|
||||
|
||||
parser = argparse.ArgumentParser(description='LZNT1 tester (You must run this on Windows)')
|
||||
parser.add_argument("FILE", help="Specify a file for compression/decompression test")
|
||||
args = parser.parse_args()
|
||||
|
||||
def main():
|
||||
with open(args.FILE, 'rb') as fp:
|
||||
data = fp.read()
|
||||
#data = "Hello world!" * 800
|
||||
print('[*] input size = {} bytes, sha1 hash = {}'.format(len(data), sha1(data).hexdigest()))
|
||||
compressed1 = lznt1.compress(data)
|
||||
decompressed11 = lznt1.decompress(compressed1)
|
||||
|
||||
buf_decompressed = ctypes.create_string_buffer(len(data)*2)
|
||||
final_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlDecompressBuffer(2, buf_decompressed, ctypes.sizeof(buf_decompressed), ctypes.c_char_p(compressed1), len(compressed1), ctypes.byref(final_size))
|
||||
decompressed12 = buf_decompressed.raw[:final_size.value]
|
||||
|
||||
buf_compressed = ctypes.create_string_buffer(len(data)*2)
|
||||
work_size = ctypes.c_ulong(0)
|
||||
work_frag_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlGetCompressionWorkSpaceSize(2, ctypes.byref(work_size), ctypes.byref(work_frag_size))
|
||||
workspace = ctypes.create_string_buffer(work_size.value)
|
||||
final_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlCompressBuffer(2, ctypes.c_char_p(data), len(data), buf_compressed, ctypes.sizeof(buf_compressed), 4096, ctypes.byref(final_size), workspace)
|
||||
compressed2 = buf_compressed.raw[:final_size.value]
|
||||
|
||||
decompressed21 = lznt1.decompress(compressed2)
|
||||
|
||||
buf_decompressed = ctypes.create_string_buffer(len(data)*2)
|
||||
final_size = ctypes.c_ulong(0)
|
||||
ctypes.windll.ntdll.RtlDecompressBuffer(2, buf_decompressed, ctypes.sizeof(buf_decompressed), buf_compressed, ctypes.sizeof(buf_compressed), ctypes.byref(final_size))
|
||||
decompressed22 = buf_decompressed.raw[:final_size.value]
|
||||
|
||||
print('[*] size of compressed1: {}'.format(len(compressed1)))
|
||||
print('[*] size of compressed2: {}'.format(len(compressed2)))
|
||||
print('[*] sha1 hash of compressed1: {}'.format(sha1(compressed1).hexdigest()))
|
||||
print('[*] sha1 hash of compressed2: {}'.format(sha1(compressed2).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed11: {}'.format(sha1(decompressed11).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed12: {}'.format(sha1(decompressed12).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed21: {}'.format(sha1(decompressed21).hexdigest()))
|
||||
print('[*] sha1 hash of decompressed22: {}'.format(sha1(decompressed22).hexdigest()))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user