pedump 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +90 -0
- data/LICENSE.txt +20 -0
- data/README.md +410 -0
- data/Rakefile +179 -0
- data/VERSION +1 -0
- data/bin/pedump +7 -0
- data/data/fs.txt +224 -0
- data/data/jc-userdb.txt +14371 -0
- data/data/sig.bin +0 -0
- data/data/signatures.txt +678 -0
- data/data/userdb.txt +14083 -0
- data/lib/pedump.rb +868 -0
- data/lib/pedump/cli.rb +804 -0
- data/lib/pedump/comparer.rb +147 -0
- data/lib/pedump/composite_io.rb +56 -0
- data/lib/pedump/core.rb +38 -0
- data/lib/pedump/core_ext/try.rb +57 -0
- data/lib/pedump/loader.rb +393 -0
- data/lib/pedump/loader/minidump.rb +351 -0
- data/lib/pedump/loader/section.rb +57 -0
- data/lib/pedump/logger.rb +67 -0
- data/lib/pedump/ne.rb +425 -0
- data/lib/pedump/ne/version_info.rb +171 -0
- data/lib/pedump/packer.rb +173 -0
- data/lib/pedump/pe.rb +121 -0
- data/lib/pedump/resources.rb +436 -0
- data/lib/pedump/security.rb +58 -0
- data/lib/pedump/sig_parser.rb +507 -0
- data/lib/pedump/tls.rb +17 -0
- data/lib/pedump/unpacker.rb +26 -0
- data/lib/pedump/unpacker/aspack.rb +858 -0
- data/lib/pedump/unpacker/upx.rb +13 -0
- data/lib/pedump/version.rb +10 -0
- data/lib/pedump/version_info.rb +171 -0
- data/misc/aspack/Makefile +3 -0
- data/misc/aspack/aspack_unlzx.c +92 -0
- data/misc/aspack/lzxdec.c +479 -0
- data/misc/aspack/lzxdec.h +56 -0
- data/misc/nedump.c +751 -0
- data/pedump.gemspec +109 -0
- metadata +227 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: binary
|
3
|
+
require 'pedump/loader'
|
4
|
+
require 'pedump/cli'
|
5
|
+
|
6
|
+
module PEdump::Unpacker; end
|
7
|
+
|
8
|
+
class PEdump::Unpacker::UPX
|
9
|
+
def self.unpack src_fname, dst_fname, log = ''
|
10
|
+
log << `upx -dqq #{src_fname} -o #{dst_fname} 2>&1`
|
11
|
+
$?.success?
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
class PEdump
|
2
|
+
class VS_VERSIONINFO < IOStruct.new( 'v3a32v',
|
3
|
+
:wLength,
|
4
|
+
:wValueLength,
|
5
|
+
:wType,
|
6
|
+
:szKey, # The Unicode string L"VS_VERSION_INFO".
|
7
|
+
:Padding1,
|
8
|
+
# manual:
|
9
|
+
:Value, # VS_FIXEDFILEINFO
|
10
|
+
:Padding2,
|
11
|
+
:Children
|
12
|
+
)
|
13
|
+
def self.read f, size = SIZE
|
14
|
+
super.tap do |vi|
|
15
|
+
vi.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
|
16
|
+
vi.Padding1 = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
17
|
+
vi.Value = VS_FIXEDFILEINFO.read(f,vi.wValueLength)
|
18
|
+
# As many zero words as necessary to align the Children member on a 32-bit boundary.
|
19
|
+
# These bytes are not included in wValueLength. This member is optional.
|
20
|
+
vi.Padding2 = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
21
|
+
vi.Children = [] # An array of zero or one StringFileInfo structures,
|
22
|
+
# and zero or one VarFileInfo structures
|
23
|
+
|
24
|
+
2.times do
|
25
|
+
pos = f.tell
|
26
|
+
f.seek(pos+6) # seek 6 bytes forward
|
27
|
+
t = f.read(6)
|
28
|
+
f.seek(pos) # return back
|
29
|
+
case t
|
30
|
+
when "V\x00a\x00r\x00"
|
31
|
+
vi.Children << VarFileInfo.read(f)
|
32
|
+
when "S\x00t\x00r\x00"
|
33
|
+
vi.Children << StringFileInfo.read(f)
|
34
|
+
else
|
35
|
+
PEdump.logger.warn "[?] invalid VS_VERSIONINFO child type #{t.inspect}"
|
36
|
+
break
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VS_FIXEDFILEINFO < IOStruct.new( 'V13',
|
44
|
+
:dwSignature,
|
45
|
+
:dwStrucVersion,
|
46
|
+
:dwFileVersionMS,
|
47
|
+
:dwFileVersionLS,
|
48
|
+
:dwProductVersionMS,
|
49
|
+
:dwProductVersionLS,
|
50
|
+
:dwFileFlagsMask,
|
51
|
+
:dwFileFlags,
|
52
|
+
:dwFileOS,
|
53
|
+
:dwFileType,
|
54
|
+
:dwFileSubtype,
|
55
|
+
:dwFileDateMS,
|
56
|
+
:dwFileDateLS,
|
57
|
+
# manual:
|
58
|
+
:valid
|
59
|
+
)
|
60
|
+
def self.read f, size = SIZE
|
61
|
+
super.tap do |ffi|
|
62
|
+
ffi.valid = (ffi.dwSignature == 0xFEEF04BD)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class StringFileInfo < IOStruct.new( 'v3a30',
|
68
|
+
:wLength,
|
69
|
+
:wValueLength, # always 0
|
70
|
+
:wType, # 1 => text data, 0 => binary data
|
71
|
+
:szKey, # The Unicode string L"StringFileInfo"
|
72
|
+
:Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
|
73
|
+
:Children # An array of one or more StringTable structures
|
74
|
+
)
|
75
|
+
def self.read f, size = SIZE
|
76
|
+
pos0 = f.tell
|
77
|
+
super.tap do |x|
|
78
|
+
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
|
79
|
+
x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
80
|
+
x.Children = []
|
81
|
+
while !f.eof? && f.tell < pos0+x.wLength
|
82
|
+
x.Children << StringTable.read(f)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class StringTable < IOStruct.new( 'v3a16v',
|
89
|
+
:wLength, # The length, in bytes, of this StringTable structure,
|
90
|
+
# including all structures indicated by the Children member.
|
91
|
+
:wValueLength, # always 0
|
92
|
+
:wType, # 1 => text data, 0 => binary data
|
93
|
+
:szKey, # An 8-digit hexadecimal number stored as a Unicode string
|
94
|
+
:Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
|
95
|
+
:Children # An array of one or more String structures.
|
96
|
+
)
|
97
|
+
def self.read f, size = SIZE
|
98
|
+
pos0 = f.tell
|
99
|
+
super.tap do |x|
|
100
|
+
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
|
101
|
+
x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
102
|
+
x.Children = []
|
103
|
+
while !f.eof? && f.tell < pos0+x.wLength
|
104
|
+
x.Children << VersionString.read(f)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class VersionString < IOStruct.new( 'v3',
|
111
|
+
:wLength, # The length, in bytes, of this String structure.
|
112
|
+
:wValueLength, # The size, in words, of the Value member
|
113
|
+
:wType, # 1 => text data, 0 => binary data
|
114
|
+
:szKey, # An arbitrary Unicode string
|
115
|
+
:Padding, # As many zero words as necessary to align the Value member on a 32-bit boundary
|
116
|
+
:Value # A zero-terminated string. See the szKey member description for more information
|
117
|
+
)
|
118
|
+
def self.read f, size = SIZE
|
119
|
+
pos = f.tell
|
120
|
+
super.tap do |x|
|
121
|
+
x.szKey = ''
|
122
|
+
x.szKey << f.read(2) until x.szKey[-2..-1] == "\x00\x00" || f.eof?
|
123
|
+
x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
124
|
+
|
125
|
+
value_len = [x.wValueLength*2, x.wLength - (f.tell-pos)].min
|
126
|
+
value_len = 0 if value_len < 0
|
127
|
+
|
128
|
+
x.Value = f.read(value_len)
|
129
|
+
if f.tell%4 > 0
|
130
|
+
f.read(4-f.tell%4) # undoc padding?
|
131
|
+
end
|
132
|
+
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
|
133
|
+
x.Value.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class VarFileInfo < IOStruct.new( 'v3a24v',
|
139
|
+
:wLength,
|
140
|
+
:wValueLength, # always 0
|
141
|
+
:wType, # 1 => text data, 0 => binary data
|
142
|
+
:szKey, # The Unicode string L"VarFileInfo"
|
143
|
+
:Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
|
144
|
+
:Children # Typically contains a list of languages that the application or DLL supports
|
145
|
+
)
|
146
|
+
def self.read f, size = SIZE
|
147
|
+
super.tap do |x|
|
148
|
+
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
|
149
|
+
x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
150
|
+
x.Children = Var.read(f)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class Var < IOStruct.new( 'v3a24',
|
156
|
+
:wLength,
|
157
|
+
:wValueLength, # The length, in bytes, of the Value member
|
158
|
+
:wType, # 1 => text data, 0 => binary data
|
159
|
+
:szKey, # The Unicode string L"Translation"
|
160
|
+
:Padding, # As many zero words as necessary to align the Children member on a 32-bit boundary
|
161
|
+
:Value # An array of one or more values that are language and code page identifier pairs
|
162
|
+
)
|
163
|
+
def self.read f, size = SIZE
|
164
|
+
super.tap do |x|
|
165
|
+
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000$/,'') rescue nil
|
166
|
+
x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
167
|
+
x.Value = f.read(x.wValueLength).unpack('v*')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <strings.h> // for bzero()
|
4
|
+
|
5
|
+
#include "lzxdec.c"
|
6
|
+
|
7
|
+
// based on ASPack Unpacker v1.00 by Dr.Golova (thx! :)
|
8
|
+
|
9
|
+
/* error codes for unpacker thread */
|
10
|
+
#define ERR_OK (0)
|
11
|
+
#define ERR_NO_FILE (1)
|
12
|
+
#define ERR_FILE_OPEN (2)
|
13
|
+
#define ERR_NO_MEM (3)
|
14
|
+
#define ERR_CANT_MAP (4)
|
15
|
+
#define ERR_FILE_CREATE (5)
|
16
|
+
#define ERR_FILE_WRITE (6)
|
17
|
+
#define ERR_COPY_OVL (7)
|
18
|
+
#define ERR_CORRUPT (8)
|
19
|
+
#define ERR_UNKNOWN (9)
|
20
|
+
#define ERR_SKIPPED (10)
|
21
|
+
#define ERR_UNPACK (11)
|
22
|
+
#define ERR_FAILED (12)
|
23
|
+
|
24
|
+
|
25
|
+
void write_result(void*buf, int size){
|
26
|
+
fwrite(buf,1,size,stdout);
|
27
|
+
}
|
28
|
+
|
29
|
+
int unpack(BYTE*packed_data, size_t packed_size, size_t unpacked_size){
|
30
|
+
LZX_CONTEXT LZX;
|
31
|
+
BYTE* unpacked_data = NULL;
|
32
|
+
size_t decoded_size;
|
33
|
+
|
34
|
+
bzero(&LZX, sizeof(LZX));
|
35
|
+
|
36
|
+
if ( NULL == (unpacked_data = calloc(1, unpacked_size + 300)) ){
|
37
|
+
perror("no mem");
|
38
|
+
return(ERR_NO_MEM);
|
39
|
+
}
|
40
|
+
|
41
|
+
decoded_size = DecodeLZX(&LZX, packed_data, unpacked_data, packed_size, unpacked_size);
|
42
|
+
if ( decoded_size < 0 || decoded_size < unpacked_size ) {
|
43
|
+
free(unpacked_data);
|
44
|
+
fprintf(stderr,"ERR_UNPACK\n");
|
45
|
+
return(ERR_UNPACK);
|
46
|
+
}
|
47
|
+
|
48
|
+
write_result(unpacked_data, decoded_size);
|
49
|
+
free(unpacked_data);
|
50
|
+
return 0;
|
51
|
+
}
|
52
|
+
|
53
|
+
int main(int argc, char*argv[]){
|
54
|
+
size_t packed_size, unpacked_size;
|
55
|
+
BYTE* packed_data = NULL;
|
56
|
+
int r;
|
57
|
+
|
58
|
+
if(argc != 3){
|
59
|
+
fprintf(stderr, "ASPack unLZX\n");
|
60
|
+
fprintf(stderr, "usage: %s <packed_size> <unpacked_size>\n", argv[0]);
|
61
|
+
fprintf(stderr, "(data is read from stdin and written to stdout)\n", argv[0]);
|
62
|
+
return 1;
|
63
|
+
}
|
64
|
+
|
65
|
+
sscanf(argv[1],"%zu",&packed_size);
|
66
|
+
if( packed_size < 1 || packed_size > 0x10000000 ){ // 256 Mb max
|
67
|
+
fprintf(stderr, "invalid packed_size: %zu\n", packed_size);
|
68
|
+
return 1;
|
69
|
+
}
|
70
|
+
|
71
|
+
sscanf(argv[2],"%zu",&unpacked_size);
|
72
|
+
if( unpacked_size < 1 || unpacked_size > 0x10000000 ){ // 256 Mb max
|
73
|
+
fprintf(stderr, "invalid unpacked_size: %zu\n", unpacked_size);
|
74
|
+
return 1;
|
75
|
+
}
|
76
|
+
|
77
|
+
/* alloc buffer */
|
78
|
+
if ( NULL == (packed_data = calloc(1, packed_size + 300)) ){
|
79
|
+
perror("no mem");
|
80
|
+
return(ERR_NO_MEM);
|
81
|
+
}
|
82
|
+
|
83
|
+
if( packed_size != fread(packed_data, 1, packed_size, stdin)){
|
84
|
+
free(packed_data);
|
85
|
+
perror("read");
|
86
|
+
return(ERR_NO_FILE);
|
87
|
+
}
|
88
|
+
|
89
|
+
r = unpack(packed_data, packed_size, unpacked_size);
|
90
|
+
free(packed_data);
|
91
|
+
return r;
|
92
|
+
}
|
@@ -0,0 +1,479 @@
|
|
1
|
+
//#include <windows.h>
|
2
|
+
|
3
|
+
typedef unsigned char BYTE;
|
4
|
+
typedef int INT;
|
5
|
+
typedef unsigned int UINT;
|
6
|
+
typedef unsigned long DWORD;
|
7
|
+
typedef int BOOL;
|
8
|
+
|
9
|
+
#define FALSE 0
|
10
|
+
#define TRUE 1
|
11
|
+
|
12
|
+
#include "lzxdec.h"
|
13
|
+
|
14
|
+
/* #define LZX_DEBUG_LOG */
|
15
|
+
|
16
|
+
#if defined _DEBUG && defined LZX_DEBUG_LOG
|
17
|
+
# include <stdio.h>
|
18
|
+
static FILE* FDebLog = NULL;
|
19
|
+
#endif
|
20
|
+
|
21
|
+
/* ##### *** COMMON FUNCTIONS *** ########################################## */
|
22
|
+
|
23
|
+
/* memset local redefinition */
|
24
|
+
static void lzx_memset(void* dst, int val, unsigned int count)
|
25
|
+
{
|
26
|
+
while( count-- )
|
27
|
+
{
|
28
|
+
*(char*)(dst) = val;
|
29
|
+
dst = (char*)(dst) + 1;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
/* memcpy local redefinition */
|
34
|
+
static void lzx_memcpy(void* dst, void* src, unsigned int count)
|
35
|
+
{
|
36
|
+
while( count-- )
|
37
|
+
{
|
38
|
+
*(char*)(dst) = *(char*)(src);
|
39
|
+
dst = (char*)(dst) + 1;
|
40
|
+
src = (char*)(src) + 1;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
/* ##### *** BIT READER FUNCTIONS *** ###################################### */
|
45
|
+
|
46
|
+
/* init bit reader */
|
47
|
+
#define BITRDR_INIT(BitRdr, RawSrc, RawLen) { \
|
48
|
+
(BitRdr)->SrcData = (RawSrc); \
|
49
|
+
(BitRdr)->SrcSize = (RawLen); \
|
50
|
+
(BitRdr)->CurOffs = 0; \
|
51
|
+
(BitRdr)->BitBuff = 0; \
|
52
|
+
(BitRdr)->BitFree = 32; \
|
53
|
+
}
|
54
|
+
|
55
|
+
/* read input byte (can be rewritten for file io) */
|
56
|
+
#define BITRDR_GETBYTE(BitRdr, RetVal) { \
|
57
|
+
if ( (BitRdr)->CurOffs < (BitRdr)->SrcSize ) \
|
58
|
+
RetVal = (BitRdr)->SrcData[(BitRdr)->CurOffs++]; \
|
59
|
+
else \
|
60
|
+
return(-1); /* error */ \
|
61
|
+
}
|
62
|
+
|
63
|
+
/* remove number of bits from bit buffer */
|
64
|
+
#define BITRDR_DROPBITS(BitRdr, BitNum) { \
|
65
|
+
(BitRdr)->BitFree += (BitNum); \
|
66
|
+
}
|
67
|
+
|
68
|
+
/* extract integer from bit buffer */
|
69
|
+
#define BITRDR_GETINT(BitRdr, RetVal) { \
|
70
|
+
DWORD BitBuff = (BitRdr)->BitBuff; \
|
71
|
+
UINT BitFree = (BitRdr)->BitFree; \
|
72
|
+
UINT UVal; \
|
73
|
+
while( BitFree >= 8 ) { \
|
74
|
+
BITRDR_GETBYTE(BitRdr, UVal); \
|
75
|
+
BitBuff = (BitBuff << 8) | UVal; \
|
76
|
+
BitFree -= 8; \
|
77
|
+
} \
|
78
|
+
RetVal = (BitBuff >> (8 - BitFree)) & 0x00ffffff; \
|
79
|
+
(BitRdr)->BitFree = BitFree; \
|
80
|
+
(BitRdr)->BitBuff = BitBuff; \
|
81
|
+
}
|
82
|
+
|
83
|
+
/* read number of bits from bit buffer */
|
84
|
+
#define BITRDR_GETBITS(BitRdr, BitNum, RetVal) { \
|
85
|
+
DWORD BitBuff = (BitRdr)->BitBuff; \
|
86
|
+
UINT BitFree = (BitRdr)->BitFree; \
|
87
|
+
UINT UVal; \
|
88
|
+
while( BitFree >= 8 ) { \
|
89
|
+
BITRDR_GETBYTE(BitRdr, UVal); \
|
90
|
+
BitBuff = (BitBuff << 8) | UVal; \
|
91
|
+
BitFree -= 8; \
|
92
|
+
} \
|
93
|
+
RetVal = (BitBuff >> (8 - BitFree)); \
|
94
|
+
RetVal = (RetVal & 0x00ffffff) >> (24 - (BitNum)); \
|
95
|
+
(BitRdr)->BitFree = (BitFree + (BitNum)); \
|
96
|
+
(BitRdr)->BitBuff = BitBuff; \
|
97
|
+
}
|
98
|
+
|
99
|
+
/* ##### *** SLIDING WINDOW DICTIONARY FUNCTIONS *** ####################### */
|
100
|
+
|
101
|
+
/* init swd context */
|
102
|
+
#define SWD_INIT(Wnd, Mem, Len) { \
|
103
|
+
(Wnd)->Window = (Mem); \
|
104
|
+
(Wnd)->WndLen = (Len); \
|
105
|
+
(Wnd)->CurOfs = 0; \
|
106
|
+
}
|
107
|
+
|
108
|
+
/* put byte to dictionary */
|
109
|
+
#define SWD_PUTBYTE(Wnd, DVal) { \
|
110
|
+
if ( (Wnd)->CurOfs < (Wnd)->WndLen ) \
|
111
|
+
(Wnd)->Window[(Wnd)->CurOfs++] = (BYTE)(DVal); \
|
112
|
+
else \
|
113
|
+
return(-1); /* error */ \
|
114
|
+
}
|
115
|
+
|
116
|
+
/* copy lz phrase in window */
|
117
|
+
#define SWD_DELTACOPY(Wnd, DOfs, DLen) { \
|
118
|
+
BYTE* WndPtr; \
|
119
|
+
if ( (Wnd)->CurOfs < (DOfs) ) \
|
120
|
+
return(-1); /* error */ \
|
121
|
+
if ( (Wnd)->CurOfs + (DLen) > (Wnd)->WndLen ) \
|
122
|
+
return(-1); /* error */ \
|
123
|
+
WndPtr = (Wnd)->Window + (Wnd)->CurOfs; \
|
124
|
+
lzx_memcpy(WndPtr, WndPtr - (DOfs), (DLen)); \
|
125
|
+
(Wnd)->CurOfs += (DLen); \
|
126
|
+
}
|
127
|
+
|
128
|
+
/* ##### *** HUFFMAN DECODERS FUNCTIONS *** ################################ */
|
129
|
+
|
130
|
+
/* init huffman decoder, return next table address */
|
131
|
+
static BYTE* LzxHuf_Init(LZX_HUFF* Huf, LZX_BITRDR* BitRdr, UINT SymNum,
|
132
|
+
BYTE* HufTbl)
|
133
|
+
{
|
134
|
+
Huf->BitRdr = BitRdr;
|
135
|
+
Huf->SymNum = SymNum;
|
136
|
+
Huf->Symbol = (UINT*)(HufTbl);
|
137
|
+
HufTbl += (SymNum * sizeof(Huf->Symbol[0]));
|
138
|
+
Huf->Length = HufTbl;
|
139
|
+
HufTbl += (256 * sizeof(Huf->Length[0]));
|
140
|
+
return(HufTbl);
|
141
|
+
}
|
142
|
+
|
143
|
+
/* decode one huffman symbol */
|
144
|
+
static INT LzxHuf_DecodeSymbol(LZX_HUFF* Huf)
|
145
|
+
{
|
146
|
+
UINT HVal, BNum, IOfs;
|
147
|
+
|
148
|
+
BITRDR_GETINT(Huf->BitRdr, HVal);
|
149
|
+
HVal &= 0x00fffe00;
|
150
|
+
|
151
|
+
if ( HVal < Huf->SymLim[8] )
|
152
|
+
BNum = Huf->Length[HVal >> 16];
|
153
|
+
else if ( HVal < Huf->SymLim[10] )
|
154
|
+
BNum = (HVal < Huf->SymLim[9]) ? (9) : (10);
|
155
|
+
else if ( HVal < Huf->SymLim[11] )
|
156
|
+
BNum = 11;
|
157
|
+
else if ( HVal < Huf->SymLim[12] )
|
158
|
+
BNum = 12;
|
159
|
+
else if ( HVal < Huf->SymLim[13] )
|
160
|
+
BNum = 13;
|
161
|
+
else
|
162
|
+
BNum = (HVal < Huf->SymLim[14]) ? (14) : (15);
|
163
|
+
|
164
|
+
BITRDR_DROPBITS(Huf->BitRdr, BNum);
|
165
|
+
IOfs = (HVal - Huf->SymLim[BNum-1]) >> (24 - BNum);
|
166
|
+
return(Huf->Symbol[Huf->SymIdx[BNum] + IOfs]);
|
167
|
+
}
|
168
|
+
|
169
|
+
/* construct huffman tables */
|
170
|
+
static INT LzxHuf_HufTblBuild(LZX_HUFF* Huf, BYTE* CodeLen)
|
171
|
+
{
|
172
|
+
UINT LenCnt[16];
|
173
|
+
UINT CurIdx[16];
|
174
|
+
UINT SymIdx, I;
|
175
|
+
UINT Lim, Idx;
|
176
|
+
UINT Ofs;
|
177
|
+
|
178
|
+
for ( I = 0; I < 16; I++ )
|
179
|
+
LenCnt[I] = 0;
|
180
|
+
for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
|
181
|
+
LenCnt[CodeLen[SymIdx]]++;
|
182
|
+
|
183
|
+
#ifdef LZX_DEBUG_LOG
|
184
|
+
if ( NULL == FDebLog )
|
185
|
+
FDebLog = fopen("lzxdeb.log", "wt");
|
186
|
+
#endif
|
187
|
+
|
188
|
+
LenCnt[0] = 0;
|
189
|
+
CurIdx[0] = 0;
|
190
|
+
Huf->SymIdx[0] = 0;
|
191
|
+
Huf->SymLim[0] = 0;
|
192
|
+
Lim = 0;
|
193
|
+
Idx = 0;
|
194
|
+
|
195
|
+
for ( I = 1; I < 16; I++ )
|
196
|
+
{
|
197
|
+
Lim += (LenCnt[I] << (24 - I));
|
198
|
+
if ( Lim > 0x1000000 )
|
199
|
+
return(-1); /* overrun */
|
200
|
+
|
201
|
+
Huf->SymLim[I] = Lim;
|
202
|
+
Huf->SymIdx[I] = Huf->SymIdx[I-1] + LenCnt[I-1];
|
203
|
+
CurIdx[I] = Huf->SymIdx[I];
|
204
|
+
|
205
|
+
if ( I <= 8 )
|
206
|
+
{
|
207
|
+
Ofs = (Huf->SymLim[I] >> 16);
|
208
|
+
lzx_memset(&Huf->Length[Idx], I, Ofs - Idx);
|
209
|
+
Idx = Ofs;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
if ( Lim != 0x1000000 )
|
214
|
+
return(-1); /* not full set */
|
215
|
+
|
216
|
+
#ifdef LZX_DEBUG_LOG
|
217
|
+
fprintf(FDebLog, "Huf->SymNum == %u\n", Huf->SymNum);
|
218
|
+
fprintf(FDebLog, "Huf->SymIdx == ");
|
219
|
+
for ( I = 0; I < 16; I++ )
|
220
|
+
fprintf(FDebLog, "%u ", Huf->SymIdx[I]);
|
221
|
+
fprintf(FDebLog, "\n");
|
222
|
+
fprintf(FDebLog, "Huf->SymLim == ");
|
223
|
+
for ( I = 0; I < 16; I++ )
|
224
|
+
fprintf(FDebLog, "%u ", Huf->SymLim[I]);
|
225
|
+
fprintf(FDebLog, "\n");
|
226
|
+
fflush(FDebLog);
|
227
|
+
#endif
|
228
|
+
|
229
|
+
for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
|
230
|
+
{
|
231
|
+
if ( CodeLen[SymIdx] )
|
232
|
+
{
|
233
|
+
#ifdef LZX_DEBUG_LOG
|
234
|
+
fprintf(FDebLog, "%u\n", SymIdx);
|
235
|
+
fflush(FDebLog);
|
236
|
+
#endif
|
237
|
+
Huf->Symbol[CurIdx[CodeLen[SymIdx]]++] = SymIdx;
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
return(0); /* all ok */
|
242
|
+
}
|
243
|
+
|
244
|
+
/* ##### *** LZX DECODER FUNCTIONS *** ##################################### */
|
245
|
+
|
246
|
+
/* basic lzx tables */
|
247
|
+
static const UINT LzxTblLenBits[28] = {
|
248
|
+
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
|
249
|
+
5, 5, 5, 5
|
250
|
+
};
|
251
|
+
static const UINT LzxTblLenBase[28] = {
|
252
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32,
|
253
|
+
40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224
|
254
|
+
};
|
255
|
+
static const UINT LzxTblOfsBits[58] = {
|
256
|
+
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
|
257
|
+
8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
|
258
|
+
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18,
|
259
|
+
18, 18, 18, 18
|
260
|
+
};
|
261
|
+
static const UINT LzxTblOfsBase[58] = {
|
262
|
+
0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000006,
|
263
|
+
0x00000008, 0x0000000C, 0x00000010, 0x00000018, 0x00000020, 0x00000030,
|
264
|
+
0x00000040, 0x00000060, 0x00000080, 0x000000C0, 0x00000100, 0x00000180,
|
265
|
+
0x00000200, 0x00000300, 0x00000400, 0x00000600, 0x00000800, 0x00000C00,
|
266
|
+
0x00001000, 0x00001800, 0x00002000, 0x00003000, 0x00004000, 0x00006000,
|
267
|
+
0x00008000, 0x0000C000, 0x00010000, 0x00018000, 0x00020000, 0x00030000,
|
268
|
+
0x00040000, 0x00060000, 0x00080000, 0x000A0000, 0x000C0000, 0x000E0000,
|
269
|
+
0x00100000, 0x00120000, 0x00140000, 0x00160000, 0x00180000, 0x001A0000,
|
270
|
+
0x001C0000, 0x001E0000, 0x00200000, 0x00240000, 0x00280000, 0x002C0000,
|
271
|
+
0x00300000, 0x00340000, 0x00380000, 0x003C0000
|
272
|
+
};
|
273
|
+
|
274
|
+
/* ------------------------------------------------------------------------- */
|
275
|
+
|
276
|
+
/* build lzx tables */
|
277
|
+
static INT Lzx_LzxTblBuild(LZX_CONTEXT* Ctx)
|
278
|
+
{
|
279
|
+
BYTE* Heap;
|
280
|
+
BYTE LenTbl[19];
|
281
|
+
BYTE HufSym[757];
|
282
|
+
UINT Val, I, Sym;
|
283
|
+
INT ISym;
|
284
|
+
|
285
|
+
Heap = Ctx->LstMem;
|
286
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 1, Val);
|
287
|
+
if ( !Val ) lzx_memset(Heap, 0, 757);
|
288
|
+
|
289
|
+
for ( I = 0; I < 19; I++ )
|
290
|
+
{
|
291
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 4, Val);
|
292
|
+
LenTbl[I] = (BYTE)(Val);
|
293
|
+
}
|
294
|
+
|
295
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufSpec, LenTbl) )
|
296
|
+
return(-1); /* error */
|
297
|
+
|
298
|
+
I = 0;
|
299
|
+
while ( I < 757 )
|
300
|
+
{
|
301
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufSpec)) == -1 )
|
302
|
+
return(-1); /* error */
|
303
|
+
|
304
|
+
if ( (Sym = (UINT)(ISym)) < 16 )
|
305
|
+
{
|
306
|
+
HufSym[I] = (BYTE)((Heap[I] + Sym) & 15); I++;
|
307
|
+
continue;
|
308
|
+
}
|
309
|
+
|
310
|
+
if ( Sym == 16 )
|
311
|
+
{
|
312
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 2, Val); Val += 3;
|
313
|
+
while ( Val > 0 && I < 757 )
|
314
|
+
{
|
315
|
+
HufSym[I] = HufSym[I-1];
|
316
|
+
Val--; I++;
|
317
|
+
}
|
318
|
+
continue;
|
319
|
+
}
|
320
|
+
|
321
|
+
if ( Sym == 17 )
|
322
|
+
{
|
323
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 3, Val);
|
324
|
+
Val += 3;
|
325
|
+
}
|
326
|
+
else
|
327
|
+
{
|
328
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 7, Val);
|
329
|
+
Val += 11;
|
330
|
+
}
|
331
|
+
|
332
|
+
while ( Val > 0 && I < 757 )
|
333
|
+
{
|
334
|
+
HufSym[I] = 0;
|
335
|
+
Val--; I++;
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufBase, &HufSym[0]) )
|
340
|
+
return(-1);
|
341
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufLens, &HufSym[721]) )
|
342
|
+
return(-1);
|
343
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufOffs, &HufSym[749]) )
|
344
|
+
return(-1);
|
345
|
+
|
346
|
+
Ctx->HasOffs = FALSE;
|
347
|
+
for ( I = 0; I < 8; I++ )
|
348
|
+
{
|
349
|
+
if ( HufSym[749+I] != 3 )
|
350
|
+
{
|
351
|
+
Ctx->HasOffs = TRUE;
|
352
|
+
break;
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
lzx_memcpy(Heap, &HufSym[0], 757);
|
357
|
+
return(0); /* all ok */
|
358
|
+
}
|
359
|
+
|
360
|
+
/* ------------------------------------------------------------------------- */
|
361
|
+
|
362
|
+
INT DecodeLZX(LZX_CONTEXT* Ctx, BYTE* Src, BYTE* Dst, UINT PSize, UINT USize)
|
363
|
+
{
|
364
|
+
UINT Written;
|
365
|
+
UINT Symbol;
|
366
|
+
BYTE* HufMem;
|
367
|
+
UINT Ofs;
|
368
|
+
UINT Len;
|
369
|
+
UINT Num;
|
370
|
+
UINT Val;
|
371
|
+
INT ISym;
|
372
|
+
|
373
|
+
/* check params */
|
374
|
+
if ( !Ctx || !Src || !Dst || !USize )
|
375
|
+
return(-1); /* invalid param */
|
376
|
+
|
377
|
+
/* init lzx context */
|
378
|
+
BITRDR_INIT(&Ctx->BitRdr, Src, PSize);
|
379
|
+
SWD_INIT(&Ctx->Window, Dst, USize);
|
380
|
+
Ctx->HasOffs = FALSE;
|
381
|
+
Ctx->LstOfs[0] = 0;
|
382
|
+
Ctx->LstOfs[1] = 0;
|
383
|
+
Ctx->LstOfs[2] = 0;
|
384
|
+
|
385
|
+
/* init huffman coders */
|
386
|
+
HufMem = &Ctx->HufTbl[0];
|
387
|
+
HufMem = LzxHuf_Init(&Ctx->HufBase, &Ctx->BitRdr, 721, HufMem);
|
388
|
+
HufMem = LzxHuf_Init(&Ctx->HufLens, &Ctx->BitRdr, 28, HufMem);
|
389
|
+
HufMem = LzxHuf_Init(&Ctx->HufOffs, &Ctx->BitRdr, 8, HufMem);
|
390
|
+
HufMem = LzxHuf_Init(&Ctx->HufSpec, &Ctx->BitRdr, 19, HufMem);
|
391
|
+
lzx_memset(Ctx->LstMem = HufMem, 0, 757);
|
392
|
+
|
393
|
+
/* build lzx tables */
|
394
|
+
if ( Lzx_LzxTblBuild(Ctx) )
|
395
|
+
return(-1);
|
396
|
+
|
397
|
+
/* decode */
|
398
|
+
Written = 0;
|
399
|
+
while ( Written < USize )
|
400
|
+
{
|
401
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufBase)) == -1 )
|
402
|
+
return(-1);
|
403
|
+
|
404
|
+
if ( (Symbol = (UINT)(ISym)) < 256 )
|
405
|
+
{
|
406
|
+
/* literal */
|
407
|
+
SWD_PUTBYTE(&Ctx->Window, Symbol);
|
408
|
+
Written++;
|
409
|
+
continue;
|
410
|
+
}
|
411
|
+
|
412
|
+
if ( Symbol < 720 )
|
413
|
+
{
|
414
|
+
/* phrase */
|
415
|
+
Symbol -= 256;
|
416
|
+
Ofs = (Symbol >> 3);
|
417
|
+
Len = (Symbol & 7) + 2;
|
418
|
+
|
419
|
+
if ( Len == 9 )
|
420
|
+
{
|
421
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufLens)) == -1 )
|
422
|
+
return(-1);
|
423
|
+
|
424
|
+
Symbol = (UINT)(ISym);
|
425
|
+
Num = LzxTblLenBits[Symbol];
|
426
|
+
BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
|
427
|
+
Len += (Val + LzxTblLenBase[Symbol]);
|
428
|
+
}
|
429
|
+
|
430
|
+
Num = LzxTblOfsBits[Ofs];
|
431
|
+
Ofs = LzxTblOfsBase[Ofs];
|
432
|
+
|
433
|
+
if ( Num < 3 || !Ctx->HasOffs )
|
434
|
+
{
|
435
|
+
BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
|
436
|
+
Ofs += Val;
|
437
|
+
}
|
438
|
+
else
|
439
|
+
{
|
440
|
+
Num -= 3;
|
441
|
+
BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
|
442
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufOffs)) == -1 )
|
443
|
+
return(-1);
|
444
|
+
Ofs += ((UINT)(ISym) + (Val << 3));
|
445
|
+
}
|
446
|
+
|
447
|
+
if ( Ofs < 3 )
|
448
|
+
{
|
449
|
+
/* use saved last offset */
|
450
|
+
Ofs = Ctx->LstOfs[Num = Ofs];
|
451
|
+
if ( Num )
|
452
|
+
{
|
453
|
+
Ctx->LstOfs[Num] = Ctx->LstOfs[0];
|
454
|
+
Ctx->LstOfs[0] = Ofs;
|
455
|
+
}
|
456
|
+
}
|
457
|
+
else
|
458
|
+
{
|
459
|
+
/* update last offset */
|
460
|
+
Ctx->LstOfs[2] = Ctx->LstOfs[1];
|
461
|
+
Ctx->LstOfs[1] = Ctx->LstOfs[0];
|
462
|
+
Ctx->LstOfs[0] = (Ofs -= 3);
|
463
|
+
}
|
464
|
+
|
465
|
+
/* copy phrase */
|
466
|
+
SWD_DELTACOPY(&Ctx->Window, Ofs+1, Len);
|
467
|
+
Written += Len;
|
468
|
+
continue;
|
469
|
+
}
|
470
|
+
|
471
|
+
/* update trees */
|
472
|
+
if ( Lzx_LzxTblBuild(Ctx) )
|
473
|
+
return(-1);
|
474
|
+
}
|
475
|
+
|
476
|
+
return(Written); /* all ok */
|
477
|
+
}
|
478
|
+
|
479
|
+
/* ------------------------------------------------------------------------- */
|