-
Notifications
You must be signed in to change notification settings - Fork 14
/
ace.bt
210 lines (197 loc) · 5.67 KB
/
ace.bt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//------------------------------------------------
//--- 010 Editor v7.0 Binary Template
//
// File: ace.bt
// Authors: dengxun@360A-Team
// Version: 0.1
// Purpose: WinACE format parser, study CVE-2018-20250, just support header type MAIN, FILE32
// Category:
// File Mask:
// ID Bytes:
// History:
// Path notice: C:\C:C:../AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
//------------------------------------------------
typedef enum {
TYPE_MAIN, TYPE_FILE32
} ACE_HDR_TYPE;
typedef struct {
switch(hdr_type) {
case TYPE_MAIN:
byte length;
break;
case TYPE_FILE32:
short length;
break;
}
char buffer[length];
} ACE_STR <read=display_ace_str, write=writer_ace_str>;
void writer_ace_str(ACE_STR &str, string val) {
int len_old = str.length;
int len_new = Strlen(val);
int offset = startof(str) + sizeof(str.length);
str.length = len_new;
if(len_new > len_old) {
Strncpy(str.buffer, val, len_old);
offset += len_old;
int i = 0;
for(i = 0;i < len_new - len_old;i ++) {
InsertBytes(offset + i, 1, val[len_old + i]);
}
}
if(len_new <= len_old) {
Strncpy(str.buffer, val, len_new);
DeleteBytes(offset + len_new, len_old - len_new);
}
}
typedef struct {
char magic[7];
byte eversion; //extract version
byte cversion; //creator version
byte host <read=display_platform>; //platform
byte volume; //volume number
DOSTIME dostime; //date/time in MS-DOS format
DOSDATE dosdate;
byte reserved1[8] <format=hex>;
if(flags.has_advert == 1) {
ACE_STR advert; //optional
}
if(flags.has_comment == 1) {
ushort comment; //optional, compressed
}
if(false) {
ushort reserved2; //optional, unknow what condition????
}
} ACE_BLOCK_MAIN;
typedef struct {
long packsize; //uint32|64 packed size
long origsize; //uint32|64 original size
DOSTIME ctime; //create date/time in MS-DOS format
DOSDATE cdate;
long attrib; //file attributes, same as winnt.h defines
ulong crc32<format=hex>; //checksum over compressed file, crc32
byte comptype <read=display_ace_compresstype>; //compression type
byte compquality; //compression quality
short params; //decompression parameters
short reserved1;
ACE_STR filename;
if(flags.has_comment == 1) {
ushort comment; //optional, compressed
}
if(flags.limit2ntsec == 1) {
ushort ntsecurity; //optional
}
if(false) {
ushort reserved2; //unknow size and what condition
}
} ACE_BLOCK_FILE32;
typedef struct {
ushort hdr_crc <format=hex>; //header crc, crc16
short hdr_size;
byte hdr_type <read=display_type>;
//output checksum
local ushort ace_crc16 = 0xFFFF & Checksum(CHECKSUM_CRC32, startof(hdr_type),hdr_size) ^ 0xFFFF;
Printf("Header ACE_CRC16: %x\r\n", ace_crc16);
if(ace_crc16 != hdr_crc) {
Printf("Header ACE_CRC16 is not match the hdr_crc(%x), archive will be not work?\r\n", hdr_crc);
}
struct {
ushort has_addsize: 1;
ushort has_comment: 1;
ushort is_64bit: 1;
ushort :5;
ushort is_v20format: 1; //Is ACE 2.0 FORMAT?
ushort is_sfx: 1; //Is self extracting archive?
ushort limit2ntsec: 1; //dict size limited to 256K
//NTFS security data present
ushort has_multivol: 1; //has multiple volumes
ushort has_advert: 1; //advert string present
//continued from previous volume
ushort recovery: 1; //recovery record present
//continued in next volume
ushort is_lock2password: 1; //archive is locked & password encryped
ushort is_solid: 1; //archive is solid
} flags;
switch(hdr_type) {
case TYPE_MAIN:
ACE_BLOCK_MAIN hdr;
break;
case TYPE_FILE32:
ACE_BLOCK_FILE32 hdr;
local short size = sizeof(hdr) + 3;
Printf("FILE32 block header size is %d\r\n", size);
if(size != hdr_size) {
Printf("FILE32 block header size is not match the hdr_size(%d), archive will be not work?\r\n", hdr_size);
}
ubyte data[hdr.packsize];
break;
default:
Printf("only support header type MAIN, FILE32\r\n");
Exit(0);
}
} ACE_BLOCK;
struct {
while(!FEof()) {
ACE_BLOCK block;
}
} ACE;
string display_platform(byte host) {
switch(host) {
case 0:
return "MS-DOS";
case 1:
return "OS/2";
case 2:
return "Win32";
case 3:
return "Unix";
case 4:
return "Mac OS";
case 5:
return "Win NT";
case 6:
return "Primos";
case 7:
return "Apple GS";
case 8:
return "ATARI";
case 9:
return "VAX VMS";
case 10:
return "AMIGA";
case 11:
return "NeXT";
case 12:
return "Linux";
default:
return "Unknown";
}
}
string display_type(byte type) {
switch(type) {
case 0:
return "MAIN";
case 1:
return "FILE32";
case 2:
return "RECOVERY32";
case 3:
return "FILE64";
case 4:
return "RECOVERY64A";
case 5:
return "RECOVERY64B";
default:
return "unknown type";
}
}
string display_ace_str(ACE_STR &str) {
return str.buffer;
}
string display_ace_compresstype(byte type) {
switch(type) {
case 0: return "stored";
case 1: return "lz77";
case 2: return "blocked";
default: return "unknown compress type";
}
}