Browse code

Aspack support (experimental) The OEP is messed up - will be fixed ASAP

git-svn: trunk@3101

aCaB authored on 2007/06/18 05:55:02
Showing 6 changed files
... ...
@@ -1,3 +1,8 @@
1
+Sun Jun 17 22:23:35 CEST 2007 (acab)
2
+------------------------------------
3
+  * libclamav/pe.c: minor typo in wwpack32
4
+  * libclamav: add support for aspack 2.12 (experimental) - thanks PN Luck
5
+
1 6
 Sat Jun 16 19:41:00 EEST 2007 (edwin)
2 7
 ------------------------------------
3 8
   * libclamav/htmlnorm.c, entconv.c: handle & in URLs, even with
... ...
@@ -90,6 +90,8 @@ libclamav_la_SOURCES = \
90 90
 	suecrypt.h \
91 91
 	unsp.c \
92 92
 	unsp.h \
93
+	aspack.c \
94
+	aspack.h \
93 95
 	packlibs.c \
94 96
 	packlibs.h \
95 97
 	fsg.c \
... ...
@@ -82,10 +82,10 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher-ncore.lo \
82 82
 	scanners.lo filetypes.lo rtf.lo blob.lo mbox.lo message.lo \
83 83
 	snprintf.lo table.lo text.lo ole2_extract.lo vba_extract.lo \
84 84
 	msexpand.lo pe.lo upx.lo htmlnorm.lo chmunpack.lo rebuildpe.lo \
85
-	petite.lo wwunpack.lo suecrypt.lo unsp.lo packlibs.lo fsg.lo \
86
-	mew.lo upack.lo line.lo untar.lo unzip.lo special.lo binhex.lo \
87
-	is_tar.lo tnef.lo unrar15.lo unrarvm.lo unrar.lo \
88
-	unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo \
85
+	petite.lo wwunpack.lo suecrypt.lo unsp.lo aspack.lo \
86
+	packlibs.lo fsg.lo mew.lo upack.lo line.lo untar.lo unzip.lo \
87
+	special.lo binhex.lo is_tar.lo tnef.lo unrar15.lo unrarvm.lo \
88
+	unrar.lo unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo \
89 89
 	LZMADecode.lo bzlib.lo infblock.lo nulsft.lo pdf.lo spin.lo \
90 90
 	yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \
91 91
 	phish_domaincheck_db.lo phish_whitelist.lo regex_list.lo \
... ...
@@ -304,6 +304,8 @@ libclamav_la_SOURCES = \
304 304
 	suecrypt.h \
305 305
 	unsp.c \
306 306
 	unsp.h \
307
+	aspack.c \
308
+	aspack.h \
307 309
 	packlibs.c \
308 310
 	packlibs.h \
309 311
 	fsg.c \
... ...
@@ -463,6 +465,7 @@ distclean-compile:
463 463
 	-rm -f *.tab.c
464 464
 
465 465
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LZMADecode.Plo@am__quote@
466
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aspack.Plo@am__quote@
466 467
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binhex.Plo@am__quote@
467 468
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blob.Plo@am__quote@
468 469
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bzlib.Plo@am__quote@
469 470
new file mode 100644
... ...
@@ -0,0 +1,416 @@
0
+/*
1
+ *  Copyright (C) 2007 Amaketos, LLC
2
+ *  Authors: Luciano Giuseppe 'Pnluck' <pnluck@virgilio.it>
3
+ *           aCaB <acab@clamav.net>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#include <string.h>
21
+#include "cltypes.h"
22
+#include "execs.h"
23
+#include "others.h"
24
+#include "rebuildpe.h"
25
+
26
+
27
+struct DICT_HELPER {
28
+  uint32_t *starts;
29
+  uint8_t *ends;
30
+  uint32_t size;
31
+};
32
+
33
+struct ASPK {
34
+  uint32_t bitpos;
35
+  uint32_t hash;
36
+  uint8_t array1[19];
37
+  uint8_t array2[758];
38
+  uint32_t init_array[58];
39
+  struct DICT_HELPER dict_helper[4];
40
+  uint8_t *input;
41
+  uint8_t *iend;
42
+  uint8_t *decrypt_dict;
43
+  uint32_t decarray3[4][24];
44
+  uint32_t decarray4[4][24];
45
+  int dict_ok;
46
+};
47
+
48
+
49
+static inline int readstream(struct ASPK *stream) {
50
+  while (stream->bitpos >= 8) {
51
+    if (stream->input>=stream->iend) return 0;
52
+    stream->hash = (stream->hash << 8) | *stream->input;
53
+    stream->input++;
54
+    stream->bitpos -= 8;
55
+  }
56
+  return 1;
57
+}
58
+
59
+static uint32_t getdec(struct ASPK *stream, uint8_t which, int *err) {
60
+  uint32_t ret;
61
+  uint8_t pos;
62
+  uint32_t *d3 = stream->decarray3[which];
63
+  uint32_t *d4 = stream->decarray4[which];
64
+
65
+  *err=1;
66
+
67
+  if (!readstream(stream)) return 0;
68
+
69
+  ret = (stream->hash >> (8 - stream->bitpos)) & 0xfffe00;
70
+
71
+  if (ret < d3[8]) {
72
+    if ((ret>>16) >= 0x100) return 0;
73
+    if (!(pos=stream->dict_helper[which].ends[ret>>16]) || pos>= 24) return 0; /* 0<pos<24 */
74
+  } else {
75
+    if (ret < d3[10]) {
76
+      if (ret < d3[9]) pos = 9;
77
+      else pos = 10;
78
+    } else {
79
+      if (ret < d3[11] ) pos = 11;
80
+      else {
81
+	if (ret < d3[12]) pos = 12;
82
+	else {
83
+	  if (ret < d3[13]) pos = 13;
84
+	  else {
85
+	    if (ret < d3[14]) pos = 14;
86
+	    else pos = 15;
87
+	  }
88
+	}
89
+      }
90
+    }
91
+  }
92
+
93
+  stream->bitpos += pos;
94
+  ret = ((ret - d3[pos-1]) >> (24 - pos)) + d4[pos];
95
+
96
+  if (ret >= stream->dict_helper[which].size) return 0;
97
+  ret = stream->dict_helper[which].starts[ret];
98
+
99
+  *err=0;
100
+  return ret;
101
+}
102
+
103
+
104
+static uint8_t build_decrypt_array(struct ASPK *stream, uint8_t* array, uint8_t which) {
105
+  uint32_t sum = 0, counter = 23, i, endoff = 0, bus[18], dict[18];
106
+
107
+  uint32_t *d3 = stream->decarray3[which];
108
+  uint32_t *d4 = stream->decarray4[which];
109
+
110
+  memset(bus,0,sizeof(bus));
111
+  memset(dict,0,sizeof(dict));
112
+
113
+  for (i = 0; i < stream->dict_helper[which].size; i++) {
114
+    /* within bounds - see comments in build_decrypt_dictionaries */
115
+    if (array[i] > 17) return 0;
116
+    bus[array[i]]++;
117
+  }
118
+
119
+  d3[0] = 0;
120
+  d4[0] = 0;
121
+
122
+  i = 0;
123
+  while (counter >= 9) { /* 0<=i<=14 */
124
+    sum += (bus[i+1] << counter);
125
+    if (sum > 0x1000000) return 0;
126
+
127
+    d3[i+1] = sum;
128
+    d4[i+1] = dict[i+1] = bus[i] + d4[i];
129
+      
130
+    if (counter >= 0x10) {
131
+      uint32_t old = endoff;
132
+      endoff = d3[i+1] >> 0x10;
133
+      if (endoff-old) {
134
+	if (!CLI_ISCONTAINED(stream->dict_helper[which].ends, 0x100, stream->dict_helper[which].ends+old, endoff-old)) return 0;
135
+	memset((stream->dict_helper[which].ends + old), i+1, endoff-old);
136
+      }
137
+    }
138
+
139
+    i++;
140
+    counter--;
141
+  }
142
+
143
+  if (sum != 0x1000000) return 0;
144
+
145
+  i = 0;
146
+  for (i=0; i < stream->dict_helper[which].size; i++) {
147
+    if (array[i]) { /* within bounds - see above */
148
+      if (array[i] > 17) return 0;
149
+      if (dict[array[i]]>=stream->dict_helper[which].size) return 0;
150
+      stream->dict_helper[which].starts[dict[array[i]]] = i;
151
+      dict[array[i]]++;
152
+    }
153
+  }
154
+
155
+  return 1;
156
+}
157
+
158
+
159
+static uint8_t getbits(struct ASPK *stream, uint32_t num, int *err) {
160
+  uint8_t retvalue;
161
+
162
+  if (!readstream(stream)) {
163
+    *err=1;
164
+    return 0;
165
+  }
166
+
167
+  *err = 0;
168
+  retvalue = ((stream->hash >> (8 - stream->bitpos))&0xffffff) >> (24 - num);
169
+  stream->bitpos += num;
170
+
171
+  return retvalue;
172
+}
173
+
174
+
175
+static int build_decrypt_dictionaries(struct ASPK *stream) {
176
+  unsigned int counter;
177
+  uint32_t ret;
178
+  int oob;
179
+
180
+  if (!getbits(stream, 1, &oob)) memset(stream->decrypt_dict, 0, 0x2f5);
181
+  if (oob) return 0;
182
+
183
+  for (counter = 0; counter < 19; counter++) {
184
+    stream->array1[counter]=getbits(stream, 4, &oob);
185
+    if (oob) return 0;
186
+  }
187
+
188
+  if (!build_decrypt_array(stream, stream->array1, 3)) return 0; /* array1[19] - [3].size=19 */
189
+
190
+  counter = 0;
191
+  while (counter < 757) {
192
+    ret = getdec(stream, 3, &oob);
193
+    if (oob) return 0;
194
+    if (ret >= 16) {
195
+      if (ret != 16) {
196
+	if (ret == 17) ret = 3 + getbits(stream, 3, &oob);
197
+	else ret = 11 + getbits(stream, 7, &oob);
198
+	if (oob) return 0;
199
+	while (ret) {
200
+	  if (counter >= 757) break;
201
+	  stream->array2[1+counter] = 0;
202
+	  counter++;
203
+	  ret--;
204
+	}
205
+      } else {
206
+	ret = 3 + getbits(stream, 2, &oob);
207
+	if (oob) return 0;
208
+	while (ret) {
209
+	  if (counter >= 757) break;
210
+	  stream->array2[1+counter] = stream->array2[counter];
211
+	  counter++;
212
+	  ret--;
213
+	}
214
+      }
215
+    } else {
216
+      stream->array2[1+counter] = (stream->decrypt_dict[counter] + ret) & 0xF;
217
+      counter++;
218
+    }
219
+  }
220
+  
221
+  if (!build_decrypt_array(stream, &stream->array2[1], 0) /* array2[758-1=757] - [0].size=721 */ || !build_decrypt_array(stream, &stream->array2[722], 1) /* array2[758-722=36] - [1].size=28 */ || !build_decrypt_array(stream, &stream->array2[750], 2) /* array2[758-750=8] - [2].size=8 */ ) return 0;
222
+  
223
+  stream->dict_ok = 0;
224
+  for (counter = 0; counter < 8; counter++) {
225
+    if (stream->array2[750+counter] != 3) {
226
+      stream->dict_ok = 1;
227
+      break;
228
+    }
229
+  }
230
+
231
+  memcpy(stream->decrypt_dict,&stream->array2[1],757);
232
+
233
+  return 1;
234
+}
235
+
236
+
237
+static int decrypt(struct ASPK *stream, uint8_t *stuff, uint32_t size, uint8_t *output) {
238
+  /* ep+6d6 -> ep+748  = 0x72*/
239
+  uint32_t gen, backsize, backbytes, useold, counter = 0;
240
+  uint32_t hist[4]={0,0,0,0};
241
+  int oob;
242
+
243
+  while (counter < size) {
244
+    gen = getdec(stream, 0, &oob);
245
+    if (oob) return 0;
246
+    if (gen < 256) { /* implied within bounds */
247
+      output[counter] = (uint8_t)gen;
248
+      counter++;
249
+      continue;
250
+    }
251
+    if (gen >= 720) {
252
+      if (!build_decrypt_dictionaries(stream)) return 0;
253
+      continue;
254
+    }
255
+    if ((backbytes = (gen - 256) >> 3)>=58) return 0; /* checks init_array + stuff */
256
+    backsize =  ((gen - 256) & 7) + 2;
257
+    if ((backsize-2)==7) {
258
+      uint8_t hlp;
259
+      gen = getdec(stream, 1, &oob);
260
+      if (oob || gen>=0x56) return 0;
261
+      hlp = stuff[gen + 0x1c];
262
+      if (!readstream(stream)) return 0;
263
+      backsize += stuff[gen] + (( (stream->hash >> (8 - stream->bitpos)) & 0xffffff ) >> (0x18 - hlp));
264
+      stream->bitpos += hlp;
265
+    }
266
+
267
+    useold = stream->init_array[backbytes];
268
+    gen = stuff[backbytes + 0x38];
269
+
270
+    if (!stream->dict_ok || gen < 3) {
271
+      if (!readstream(stream)) return 0;
272
+      useold += ((stream->hash >> ( 8 - stream->bitpos) ) & 0xffffff) >> (24 - gen);
273
+      stream->bitpos += gen;
274
+    } else {
275
+      gen -= 3;
276
+      if (!readstream(stream)) return 0;
277
+      useold += ((((stream->hash >> ( 8 - stream->bitpos)) & 0xffffff) >> (24 - gen)) * 8);
278
+      stream->bitpos += gen;
279
+      useold += getdec(stream, 2, &oob);
280
+      if (oob) return 0;
281
+    }
282
+    
283
+    if (useold < 3) {
284
+      backbytes = hist[useold];
285
+      if (useold != 0) {
286
+	hist[useold] = hist[0];
287
+	hist[0] = backbytes;
288
+      }
289
+    } else {
290
+      hist[2] = hist[1];
291
+      hist[1] = hist[0];
292
+      hist[0] = backbytes = useold-3;
293
+    }
294
+
295
+    backbytes++;
296
+
297
+    if (!backbytes || backbytes>counter || backsize>size-counter) return 0;
298
+    while (backsize--) {
299
+      output[counter] = output[counter-backbytes];
300
+      counter++;
301
+    }
302
+  }
303
+
304
+  return 1;
305
+}
306
+
307
+
308
+static int decomp_block(struct ASPK *stream, uint32_t size, uint8_t *stuff, uint8_t *output) {
309
+  memset(stream->decarray3,0,sizeof(stream->decarray3));
310
+  memset(stream->decarray4,0,sizeof(stream->decarray4));
311
+  memset(stream->decrypt_dict, 0, 757);
312
+  stream->bitpos = 0x20;
313
+  if (!build_decrypt_dictionaries(stream)) return 0;
314
+  return decrypt(stream, stuff, size, output);
315
+}
316
+
317
+#define INIT_DICT_HELPER(n,sz)					\
318
+  stream.dict_helper[n].starts = (uint32_t *)wrkbuf;		\
319
+  stream.dict_helper[n].ends = &wrkbuf[sz * sizeof(uint32_t)];	\
320
+  stream.dict_helper[n].size = sz;				\
321
+  wrkbuf = &wrkbuf[sz * sizeof(uint32_t) + 0x100];
322
+
323
+int unaspack212(uint8_t *image, unsigned int size, struct cli_exe_section *sections, uint16_t sectcount, uint32_t ep, uint32_t base, int f) {
324
+  struct ASPK stream;
325
+  uint32_t i=0, j=0;
326
+  uint8_t *blocks = image+ep+0x57c, *wrkbuf;
327
+  uint32_t block_rva, block_size;
328
+  struct cli_exe_section *outsects;
329
+
330
+  if (!(wrkbuf = cli_calloc(0x1800, sizeof(uint8_t)))) {
331
+    cli_dbgmsg("Aspack: Unable to allocate dictionary\n");
332
+    return 0;
333
+  }
334
+
335
+  INIT_DICT_HELPER(0, 721); /* dictionary -> dictionary + b44 */
336
+  INIT_DICT_HELPER(1, 28);  /* dictionary + c44 -> dictionary + cb4 */
337
+  INIT_DICT_HELPER(2, 8);   /* dictionary + db4 -> dictionary + dd4 */
338
+  INIT_DICT_HELPER(3, 19);  /* dictionary + ed4 -> dictionary + f20 */
339
+  stream.decrypt_dict = wrkbuf;
340
+
341
+  stream.hash = 0x10000;
342
+
343
+  for (i = 0; i < 58; i++) {
344
+    stream.init_array[i] = j;
345
+    j += ( 1 << image[ep+i+0x70e]); /* boundchecked in pe.c */
346
+  }
347
+
348
+  memset(stream.array1,0,sizeof(stream.array1));
349
+  memset(stream.array2,0,sizeof(stream.array2));
350
+
351
+  i=0;
352
+  while (CLI_ISCONTAINED(image, size, blocks, 8) && (block_rva = cli_readint32(blocks)) && (block_size = cli_readint32(blocks+4)) && CLI_ISCONTAINED(image, size, image+block_rva, block_size)) {
353
+    wrkbuf = (uint8_t *)cli_malloc(block_size);
354
+    if (!wrkbuf) break;
355
+
356
+    stream.input = wrkbuf;
357
+    stream.iend = &wrkbuf[block_size];
358
+
359
+    memcpy(wrkbuf, image + block_rva, block_size);
360
+
361
+    cli_dbgmsg("Aspack: unpacking block rva:%x - sz:%x\n", block_rva, block_size);
362
+    if (!decomp_block(&stream, block_size, &image[ep+0x6d6], image + block_rva)) {
363
+      free(wrkbuf);
364
+      break;
365
+    }
366
+
367
+    free(wrkbuf);
368
+    
369
+    if (i==0 && block_size>7) { /* first sect j/c unrolling */
370
+      while (i < block_size - 6) {
371
+	uint8_t curbyte = image[block_rva+i];
372
+	if (curbyte == 0xe8 || curbyte == 0xe9) {
373
+	  wrkbuf = &image[block_rva+i+1];
374
+	  if (*wrkbuf == image[ep+0x148]) {
375
+	    uint32_t target = cli_readint32(wrkbuf) & 0xffffff00;
376
+	    ROL(target, 0x18);
377
+	    cli_writeint32(wrkbuf, target - i);
378
+	    i+=4;
379
+	  }
380
+	}
381
+	i++;
382
+      }
383
+    }
384
+    blocks+=8;
385
+  }
386
+  
387
+  free(stream.dict_helper[0].starts);
388
+  if (block_rva) {
389
+    cli_dbgmsg("Aspack: unpacking failure\n");
390
+    return 0;
391
+  }
392
+
393
+  if(sectcount>2 && ep == sections[sectcount-2].rva && !sections[sectcount-1].rsz) {
394
+    sectcount-=2;
395
+  }
396
+  if(!(outsects=cli_malloc(sizeof(struct cli_exe_section)*sectcount))) {
397
+    cli_dbgmsg("Aspack: OOM - rebuild failed\n");
398
+    cli_writen(f, image, size);
399
+    return 1; /* No whatsoheader - won't infloop in pe.c */
400
+  }
401
+  memcpy(outsects, sections, sizeof(struct cli_exe_section)*sectcount);
402
+  for(i=0; i<sectcount; i++) {
403
+    outsects[i].raw=outsects[i].rva;
404
+    outsects[i].rsz=outsects[i].vsz;
405
+  }
406
+  if (!cli_rebuildpe((char *)image, outsects, sectcount, base, cli_readint32(image + ep + 0x279), 0, 0, f)) {
407
+    cli_dbgmsg("Aspack: rebuild failed\n");
408
+    cli_writen(f, image, size);
409
+  } else {
410
+    cli_dbgmsg("Aspack: successfully rebuilt\n");
411
+  }
412
+  free(outsects);
413
+  return 1;
414
+}
415
+
0 416
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+/*
1
+ *  Copyright (C) 2007 Amaketos, LLC
2
+ *  Authors: Luciano Giuseppe 'Pnluck' <pnluck@virgilio.it>
3
+ *           aCaB <acab@clamav.net>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __ASPACK_H
21
+#define __ASPACK_H
22
+
23
+#include "cltypes.h"
24
+#include "execs.h"
25
+
26
+int unaspack212(uint8_t *, unsigned int, struct cli_exe_section *, uint16_t, uint32_t, uint32_t, int);
27
+
28
+#endif
... ...
@@ -42,6 +42,7 @@
42 42
 #include "spin.h"
43 43
 #include "upx.h"
44 44
 #include "yc.h"
45
+#include "aspack.h"
45 46
 #include "wwunpack.h"
46 47
 #include "suecrypt.h"
47 48
 #include "unsp.h"
... ...
@@ -2458,7 +2459,7 @@ skip_upack_and_go_to_next_unpacker:
2458 2458
       char *dest, *wwp;
2459 2459
 
2460 2460
       for(i = 0 ; i < (unsigned int)nsections-1; i++)
2461
-	if (!err && exe_sections[i].raw<headsize) headsize=exe_sections[i].raw;
2461
+	if (exe_sections[i].raw<headsize) headsize=exe_sections[i].raw;
2462 2462
       
2463 2463
       dsize = max-min+headsize-exe_sections[nsections - 1].rsz;
2464 2464
 
... ...
@@ -2491,7 +2492,7 @@ skip_upack_and_go_to_next_unpacker:
2491 2491
 	if(exe_sections[i].rsz) {
2492 2492
 	  uint32_t offset = exe_sections[i].raw;
2493 2493
 	  
2494
-	  if(err || lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) {
2494
+	  if(lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) {
2495 2495
 	    free(dest);
2496 2496
 	    free(exe_sections);
2497 2497
 	    return CL_EIO;
... ...
@@ -2571,6 +2572,82 @@ skip_upack_and_go_to_next_unpacker:
2571 2571
       }
2572 2572
     }
2573 2573
 
2574
+    /* ASPACK support */
2575
+#ifdef CL_EXPERIMENTAL
2576
+    while(ep+58+0x70e < fsize && !memcmp(buff,"\x60\xe8\x03\x00\x00\x00\xe9\xeb",8)) {
2577
+        char nbuff[6];
2578
+
2579
+        if(lseek(desc, ep+0x3b9, SEEK_SET) == -1) break;
2580
+        if(cli_readn(desc, nbuff, 6)!=6) break;
2581
+        if(memcmp(nbuff, "\x68\x00\x00\x00\x00\xc3",6)) break;
2582
+	ssize = 0;
2583
+	for(i=0 ; i< nsections ; i++)
2584
+	  if(ssize<exe_sections[i].rva+exe_sections[i].vsz)
2585
+	    ssize=exe_sections[i].rva+exe_sections[i].vsz;
2586
+	if(!ssize) break;
2587
+        if(ctx->limits && ctx->limits->maxfilesize && ssize > ctx->limits->maxfilesize) {
2588
+            cli_dbgmsg("Pe.Aspack: Size exceeded\n");
2589
+            free(exe_sections);
2590
+            if(BLOCKMAX) {
2591
+                *ctx->virname = "Pe.Aspack.ExceededFileSize";
2592
+                return CL_VIRUS;
2593
+            } else {
2594
+              return CL_CLEAN;
2595
+            }
2596
+        }
2597
+        if(!(src=(char *)cli_calloc(ssize, sizeof(char)))) {
2598
+	    free(exe_sections);
2599
+	    return CL_EMEM;
2600
+	}
2601
+        for(i = 0 ; i < (unsigned int)nsections; i++) {
2602
+	    if(!exe_sections[i].rsz) continue;
2603
+	    if(lseek(desc, exe_sections[i].raw, SEEK_SET) == -1) break;
2604
+            if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
2605
+            if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2606
+        }
2607
+        if(i!=nsections) {
2608
+            cli_dbgmsg("Aspack: Probably hacked/damaged Aspack file.\n");
2609
+            free(src);
2610
+            break;
2611
+        }
2612
+	if(!(tempfile = cli_gentemp(NULL))) {
2613
+	  free(exe_sections);
2614
+	  free(src);
2615
+	  return CL_EMEM;
2616
+	}
2617
+	if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
2618
+	  cli_dbgmsg("Aspack: Can't create file %s\n", tempfile);
2619
+	  free(tempfile);
2620
+	  free(exe_sections);
2621
+	  free(src);
2622
+	  return CL_EIO;
2623
+	}
2624
+	if (unaspack212((uint8_t *)src, ssize, exe_sections, nsections, vep-1, EC32(optional_hdr32.ImageBase), ndesc)) {
2625
+	  free(src);
2626
+	  cli_dbgmsg("Aspack: Dumped to %s\n", tempfile);
2627
+	  fsync(ndesc);
2628
+	  lseek(ndesc, 0, SEEK_SET);
2629
+	  if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
2630
+	      free(exe_sections);
2631
+	      close(ndesc);
2632
+	      if(!cli_leavetemps_flag)
2633
+		  unlink(tempfile);
2634
+	      free(tempfile);
2635
+	      return CL_VIRUS;
2636
+	  }
2637
+	} else {
2638
+	  free(src);
2639
+	}
2640
+
2641
+	close(ndesc);
2642
+	if(!cli_leavetemps_flag)
2643
+	  unlink(tempfile);
2644
+	free(tempfile);
2645
+
2646
+	break;
2647
+    }
2648
+#endif /* CL_EXPERIMENTAL */
2649
+
2574 2650
     /* NsPack */
2575 2651
 
2576 2652
     while (DCONF & PE_CONF_NSPACK) {