mirror of https://github.com/x64dbg/btparser
185 lines
5.6 KiB
Plaintext
185 lines
5.6 KiB
Plaintext
//--------------------------------------
|
|
//--- 010 Editor v4.0.3 Binary Template
|
|
//
|
|
// File: GZipTemplate.bt
|
|
// Author: Tim "diff" Strazzere <diff@lookout.com> <strazz@gmail.com>
|
|
// Revision: 1.2
|
|
// Purpose: Quick template for parsing GZip data/files
|
|
//--------------------------------------
|
|
//
|
|
// Version 1.2
|
|
// - Fix processing of part numbers for continuation based gzips
|
|
// - Added some notes on the encrypted header information
|
|
//
|
|
// Version 1.1
|
|
// - Fix small typos
|
|
// - Added comments to fields
|
|
// - Fix compression/flag names according to gzip 1.2.4 source
|
|
// - Added uncompressed length and CRC32
|
|
// - Check for different common magic bytes, and display properly
|
|
// - Minor code clean up
|
|
//
|
|
// Version 1.0
|
|
// - First implementation of the template
|
|
//
|
|
// TODO:
|
|
// - Parse encrypted header information
|
|
|
|
// GZip's should be Little Endian only
|
|
LittleEndian();
|
|
|
|
// utility type to show the magic bytes in the value column
|
|
typedef ubyte MAGIC[2] <read=MAGICRead, format=hex>;
|
|
|
|
string MAGICRead(MAGIC magic) {
|
|
string ret;
|
|
string tmp;
|
|
int i;
|
|
|
|
for(i = 0; i<2; i++) {
|
|
SPrintf(tmp, "%.2X", magic[i]);
|
|
ret += tmp;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
typedef enum <ubyte> {
|
|
// All below, except DEFLATE are reserved
|
|
STORED = 0,
|
|
COMPRESSED = 1,
|
|
PACKED = 2,
|
|
LZHED = 3,
|
|
RESERVED_4 = 4,
|
|
RESERVED_5 = 5,
|
|
RESERVED_6 = 6,
|
|
RESERVED_7 = 7,
|
|
// Default (and most common)
|
|
DEFLATE = 8
|
|
} COMPRESSION;
|
|
|
|
|
|
// TODO : Probably some better way to do this
|
|
typedef struct {
|
|
// File is probably ascii text (determined by compressor)
|
|
byte FLAG_ASCII_TEXT : 1;
|
|
|
|
// Continuation of multi-part gzip file
|
|
byte FLAG_CONTINUATION : 1;
|
|
|
|
// Generic extra field present
|
|
byte FLAG_EXTRA : 1;
|
|
|
|
// Original filename present
|
|
byte FLAG_NAME : 1;
|
|
|
|
// File comment present
|
|
byte FLAG_COMMENT : 1;
|
|
|
|
// Is file encrypted?
|
|
byte FLAG_ENCRYPTED : 1;
|
|
|
|
// Reserved for future use (nothing as of gzip 1.2.4
|
|
byte FLAG_RESERVED : 1;
|
|
byte FLAG_RESERVED : 1;
|
|
} FLAGS;
|
|
|
|
typedef enum <byte> {
|
|
FAT_FILESYSTEM = 0,
|
|
AMIGA = 1,
|
|
VMS = 2,
|
|
UNIX = 3,
|
|
VM_CMS = 4,
|
|
ATARI_TOS = 5,
|
|
HPFS_FILESYSTEM = 6,
|
|
MACINTOSH = 7,
|
|
Z_SYSTEM = 8,
|
|
CPM = 9,
|
|
TOPS_20 = 10,
|
|
NTFS_FILESYSTEM = 11,
|
|
QDOS = 12,
|
|
ACORN_RISCOS = 13,
|
|
UNKNOWN = 255
|
|
} OS;
|
|
|
|
typedef struct {
|
|
MAGIC magic_bytes <format=hex, comment="Magic bytes for the file">;
|
|
|
|
// Should be a better way to parse the magic bytes and complain to user...
|
|
if(magic_bytes[0] == 0x1F) {
|
|
if(magic_bytes[1] == 0x8B) {
|
|
// GZIP_MAGIC
|
|
Printf("Appears to be a valid GZIP compressed file, attempting to parse.\n");
|
|
} else if(magic_bytes[1] == 0x1E) {
|
|
// PACK_MAGIC
|
|
Printf("Appears to be a generic compressed file, attempting to parse - don't expect much though.\n");
|
|
} else if(magic_bytes[1] == 0x9E) {
|
|
// OLD_GZIP_MAGIC
|
|
Printf("Appears to be an old GZip compressed file, attempting to parse - don't expect much though.\n");
|
|
} else if(magic_bytes[1] == 0xA0) {
|
|
// LZH_MAGIC
|
|
Printf("Appears to be a LZH compressed file, attempting to parse - don't expect much though.\n");
|
|
}
|
|
} else if(magic_bytes[0] == 0x50 && magic_bytes[1] == 0x4B) {
|
|
Warning("Appears to be a possible ZIP file - unable to parse with this template!");
|
|
Exit(-1);
|
|
} else {
|
|
Warning("Does not appear to be a GZip file!");
|
|
Exit(-1);
|
|
}
|
|
|
|
COMPRESSION compression_method <comment="Compression method used by engine">;
|
|
FLAGS flags <comment="Optional flags for compressed section">;
|
|
|
|
// Convert to proper timestamp
|
|
uint modification_time <comment="Unix timestamp of the file modification time">;
|
|
|
|
// Extra flags
|
|
ubyte extra_flags <comment="Extra flags, dependant on compression method">;
|
|
|
|
// OS where compression took place
|
|
OS operating_system <comment="Operating system compression took place on">;
|
|
|
|
// The file is marked as a continuation, so it should have a part number
|
|
if(flags.FLAG_CONTINUATION == 1) {
|
|
ushort part <comment="Part number of the continuation">;
|
|
}
|
|
|
|
// Read in extras from flags
|
|
if(flags.FLAG_EXTRA == 1) {
|
|
ushort extra_length <comment="Length of extra field">;
|
|
byte extra_bytes[extra_length] <comment="Data for extra field">;
|
|
}
|
|
|
|
if(flags.FLAG_NAME == 1) {
|
|
string original_file_name <comment="Original file name">;
|
|
}
|
|
|
|
if(flags.FLAG_COMMENT == 1) {
|
|
string file_comment <comment="File comment">;
|
|
}
|
|
|
|
// TODO: Parse encrypted header info
|
|
// -- according to the docs this is grabbed from the zip lib (crypt.h/crypt.c)
|
|
// which according to their docs is hardly used or fully supported.
|
|
// It would appear you would need to compile this directly into your gzip
|
|
// sources for it to properly work, even though it's considered "valid".
|
|
if(flags.FLAG_ENCRYPTED == 1) {
|
|
// 12 bytes of encryption header data
|
|
}
|
|
} gzip_header;
|
|
|
|
// Structure of gzip file
|
|
struct {
|
|
// Header information
|
|
gzip_header header <comment="GZip header information">;
|
|
|
|
// Everything else should just be compress bytes, less the last 8 bytes
|
|
// which contain the CRC32 and uncompressed size
|
|
byte compressed[FileSize() - FTell() - 8] <comment="compressed data section">;
|
|
|
|
uint CRC32 <format=hex, comment="CRC of the data section">;
|
|
|
|
// 4 bytes uncompressed input size modulo 2^32
|
|
uint uncompressed_sized <comment="Size of the uncompressed input">;
|
|
} gzip_file; |