LZNT1 decompress error
Closed this issue · 1 comments
Tupler commented
Tupler commented
this is my code
package main
import (
"encoding/binary"
"errors"
"log"
"os"
)
/*
Decompression support for the LZNT1 compression algorithm.
Reference:
http://msdn.microsoft.com/en-us/library/jj665697.aspx
(2.5 LZNT1 Algorithm Details)
https://github.com/libyal/reviveit/
https://github.com/sleuthkit/sleuthkit/blob/develop/tsk/fs/ntfs.c
*/
var (
COMPRESSED_MASK = uint16(1 << 15)
SIGNATURE_MASK = uint16(3 << 12)
SIZE_MASK = uint16(1<<12) - 1
shiftTooLargeError = errors.New(
"Decompression error - shift is too large")
blockTooSmallError = errors.New("Block too small!")
)
func get_displacement(offset uint16) byte {
result := byte(0)
for {
if offset < 0x10 {
return result
}
offset >>= 1
result += 1
}
}
func LZNT1Decompress(in []byte) ([]byte, error) {
// Index into the in buffer
i := 0
out := []byte{}
for {
if len(in) < i+2 {
break
}
uncompressed_chunk_offset := len(out)
block_offset := i
block_header := binary.LittleEndian.Uint16(in[i:])
i += 2
size := int(block_header & SIZE_MASK)
block_end := block_offset + size + 3
if size == 0 {
break
}
if len(in) < i+size {
return nil, blockTooSmallError
}
if block_header&COMPRESSED_MASK != 0 {
for i < block_end {
header := uint8(in[i])
i++
for mask_idx := uint8(0); mask_idx < 8 && i < block_end; mask_idx++ {
if (header & 1) == 0 {
out = append(out, in[i])
i++
} else {
pointer := binary.LittleEndian.Uint16(in[i:])
i += 2
displacement := get_displacement(
uint16(len(out) - uncompressed_chunk_offset - 1))
symbol_offset := int(pointer>>(12-displacement)) + 1
symbol_length := int(pointer&(0xFFF>>displacement)) + 2
start_offset := len(out) - symbol_offset
for j := 0; j < symbol_length+1; j++ {
idx := start_offset + j
if idx < 0 || idx >= len(out) {
return out, shiftTooLargeError
}
out = append(out, out[idx])
}
}
header >>= 1
}
}
// Block is not compressed.
} else {
out = append(out, in[i:i+size+1]...)
i += size + 1
}
}
return out, nil
}
func main() {
source, err := os.ReadFile("PX_dec.TXT")
if err != nil {
log.Fatalln(err)
}
result, err := LZNT1Decompress(source)
if err != nil {
panic(err)
}
if err = os.WriteFile("PXX.TXT", result, 0666); err != nil {
log.Fatalln(err)
}
}