Browse code

Integrated new PE file unpacking capabilities for versions of Aspack up to 2.42, courtesy of Emmanuel Tacheau.

Micah Snyder (micasnyd) authored on 2018/09/17 22:58:33
Showing 3 changed files
... ...
@@ -29,6 +29,22 @@
29 29
 #include "aspack.h"
30 30
 
31 31
 
32
+#define ASPACK_BLOCKS_OFFSET_212          0x57c
33
+#define ASPACK_BLOCKS_OFFSET_OTHER        0x5d8
34
+#define ASPACK_BLOCKS_OFFSET_242          0x5e4
35
+
36
+#define ASPACK_STR_INIT_MLT_OFFSET_212    0x70e
37
+#define ASPACK_STR_INIT_MLT_OFFSET_OTHER  0x76a
38
+#define ASPACK_STR_INIT_MLT_OFFSET_242    0x776
39
+
40
+#define ASPACK_COMP_BLOCK_OFFSET_212      0x6d6
41
+#define ASPACK_COMP_BLOCK_OFFSET_OTHER    0x732
42
+#define ASPACK_COMP_BLOCK_OFFSET_242      0x73e
43
+
44
+#define ASPACK_WRKBUF_OFFSET_212          0x148
45
+#define ASPACK_WRKBUF_OFFSET_OTHER        0x13a
46
+#define ASPACK_WRKBUF_OFFSET_242          0x148
47
+
32 48
 struct DICT_HELPER {
33 49
   uint32_t *starts;
34 50
   uint8_t *ends;
... ...
@@ -245,6 +261,7 @@ static int decrypt(struct ASPK *stream, uint8_t *stuff, uint32_t size, uint8_t *
245 245
   uint32_t hist[4]={0,0,0,0};
246 246
   int oob;
247 247
 
248
+  cli_dbgmsg("Aspack: decrypt size:%x\n", size);
248 249
   while (counter < size) {
249 250
     gen = getdec(stream, 0, &oob);
250 251
     if (oob) return 0;
... ...
@@ -325,13 +342,45 @@ static int decomp_block(struct ASPK *stream, uint32_t size, uint8_t *stuff, uint
325 325
   stream.dict_helper[n].size = sz;				\
326 326
   wrkbuf = &wrkbuf[sz * sizeof(uint32_t) + 0x100];
327 327
 
328
-int unaspack212(uint8_t *image, unsigned int size, struct cli_exe_section *sections, uint16_t sectcount, uint32_t ep, uint32_t base, int f) {
328
+int unaspack(uint8_t *image, unsigned int size, struct cli_exe_section *sections, uint16_t sectcount, uint32_t ep, uint32_t base, int f, aspack_version_t version)
329
+{
329 330
   struct ASPK stream;
330 331
   uint32_t i=0, j=0;
331
-  uint8_t *blocks = image+ep+0x57c, *wrkbuf;
332
+  uint8_t *blocks = NULL, *wrkbuf;
332 333
   uint32_t block_rva = 1, block_size;
333 334
   struct cli_exe_section *outsects;
334 335
 
336
+  uint32_t blocks_offset, stream_init_multiplier_offset, comp_block_offset, wrkbuf_offset;
337
+
338
+  switch (version) {
339
+    case ASPACK_VER_212:
340
+      cli_dbgmsg("Aspack: Attempting to unpack Aspack 2.12.\n");
341
+      blocks_offset = ASPACK_BLOCKS_OFFSET_212;
342
+      stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_212;
343
+      comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_212;
344
+      wrkbuf_offset = ASPACK_WRKBUF_OFFSET_212;
345
+      break;
346
+    case ASPACK_VER_OTHER:
347
+      cli_dbgmsg("Aspack: Attempting to unpack Aspack >2.12, <2.42.\n");
348
+      blocks_offset = ASPACK_BLOCKS_OFFSET_OTHER;
349
+      stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_OTHER;
350
+      comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_OTHER;
351
+      wrkbuf_offset = ASPACK_WRKBUF_OFFSET_OTHER;
352
+      break;
353
+    case ASPACK_VER_242:
354
+      cli_dbgmsg("Aspack: Attempting to unpack Aspack 2.42.\n");
355
+      blocks_offset = ASPACK_BLOCKS_OFFSET_242;
356
+      stream_init_multiplier_offset = ASPACK_STR_INIT_MLT_OFFSET_242;
357
+      comp_block_offset = ASPACK_COMP_BLOCK_OFFSET_242;
358
+      wrkbuf_offset = ASPACK_WRKBUF_OFFSET_242;
359
+      break;
360
+    default:
361
+      cli_dbgmsg("Aspack: Unexpected/Unknown version number.\n");
362
+      return 0;
363
+  }
364
+
365
+  blocks = image+ep+blocks_offset;
366
+
335 367
   if (!(wrkbuf = cli_calloc(0x1800, sizeof(uint8_t)))) {
336 368
     cli_dbgmsg("Aspack: Unable to allocate dictionary\n");
337 369
     return 0;
... ...
@@ -347,7 +396,7 @@ int unaspack212(uint8_t *image, unsigned int size, struct cli_exe_section *secti
347 347
 
348 348
   for (i = 0; i < 58; i++) {
349 349
     stream.init_array[i] = j;
350
-    j += ( 1 << image[ep+i+0x70e]); /* boundchecked in pe.c */
350
+    j += ( 1 << image[ep+i+stream_init_multiplier_offset]); /* boundchecked in pe.c */
351 351
   }
352 352
 
353 353
   memset(stream.array1,0,sizeof(stream.array1));
... ...
@@ -355,40 +404,59 @@ int unaspack212(uint8_t *image, unsigned int size, struct cli_exe_section *secti
355 355
 
356 356
   i=0;
357 357
   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)) {
358
+
359
+    cli_dbgmsg("Aspack: unpacking block rva:%x - sz:%x\n", block_rva, block_size);
358 360
     wrkbuf = (uint8_t *)cli_calloc(block_size+0x10e, sizeof(uint8_t));
359
-    if (!wrkbuf) break;
360 361
 
362
+    if (!wrkbuf) {
363
+      cli_dbgmsg("Aspack: Null work buff\n");
364
+      break;
365
+    }
361 366
     stream.input = wrkbuf;
362 367
     stream.iend = &wrkbuf[block_size+0x10e];
363 368
 
364 369
     memcpy(wrkbuf, image + block_rva, block_size);
365 370
 
366
-    cli_dbgmsg("Aspack: unpacking block rva:%x - sz:%x\n", block_rva, block_size);
367
-    if (!decomp_block(&stream, block_size, &image[ep+0x6d6], image + block_rva)) {
371
+    if (!decomp_block(&stream, block_size, &image[ep+comp_block_offset], image + block_rva)) {
372
+      cli_dbgmsg("Aspack: decomp_block failed\n");
368 373
       free(wrkbuf);
369 374
       break;
370 375
     }
376
+    else
377
+      cli_dbgmsg("Aspack: decomp block succeed\n");
371 378
 
372 379
     free(wrkbuf);
373 380
     
374 381
     if (i==0 && block_size>7) { /* first sect j/c unrolling */
375 382
       while (i < block_size - 6) {
376
-	uint8_t curbyte = image[block_rva+i];
377
-	if (curbyte == 0xe8 || curbyte == 0xe9) {
378
-	  wrkbuf = &image[block_rva+i+1];
379
-	  if (*wrkbuf == image[ep+0x148]) {
380
-	    uint32_t target = cli_readint32(wrkbuf) & 0xffffff00;
381
-	    CLI_ROL(target, 0x18);
382
-	    cli_writeint32(wrkbuf, target - i);
383
-	    i+=4;
384
-	  }
385
-	}
386
-	i++;
383
+        uint8_t curbyte = image[block_rva+i];
384
+        if (curbyte == 0xe8 || curbyte == 0xe9) {
385
+          wrkbuf = &image[block_rva+i+1];
386
+          if (*wrkbuf == image[ep+wrkbuf_offset]) {
387
+            uint32_t target = cli_readint32(wrkbuf) & 0xffffff00;
388
+            CLI_ROL(target, 0x18);
389
+            cli_writeint32(wrkbuf, target - i);
390
+            i+=4;
391
+          }
392
+        }
393
+        i++;
394
+      }
395
+    }
396
+    if (version == ASPACK_VER_212) {
397
+      blocks+=8;
398
+    } else {
399
+      blocks += 12;
400
+      block_size = cli_readint32(blocks+4);
401
+      while (!((block_size +0x10e) & 0xffffffff))
402
+      {	
403
+        blocks += 12;
404
+        block_size = cli_readint32(blocks+4);
387 405
       }
388 406
     }
389
-    blocks+=8;
390 407
   }
391
-  
408
+
409
+  cli_dbgmsg("Aspack: leaving loop all uncompressed\n");
410
+
392 411
   free(stream.dict_helper[0].starts);
393 412
   if (block_rva) {
394 413
     cli_dbgmsg("Aspack: unpacking failure\n");
... ...
@@ -25,6 +25,21 @@
25 25
 #include "cltypes.h"
26 26
 #include "execs.h"
27 27
 
28
-int unaspack212(uint8_t *, unsigned int, struct cli_exe_section *, uint16_t, uint32_t, uint32_t, int);
28
+#define ASPACK_EP_OFFSET_212    (58+0x70e)
29
+#define ASPACK_EP_OFFSET_OTHER  (58+0x76a)
30
+#define ASPACK_EP_OFFSET_242    (58+0x776)
31
+
32
+#define ASPACK_EPBUFF_OFFSET_212    (0x3b9)
33
+#define ASPACK_EPBUFF_OFFSET_OTHER  (0x41f)
34
+#define ASPACK_EPBUFF_OFFSET_242    (0x42B)
35
+
36
+typedef enum aspack_version_tag {
37
+    ASPACK_VER_NONE=0,
38
+    ASPACK_VER_212,
39
+    ASPACK_VER_OTHER,
40
+    ASPACK_VER_242
41
+} aspack_version_t;
42
+
43
+int unaspack(uint8_t *image, unsigned int size, struct cli_exe_section *sections, uint16_t sectcount, uint32_t ep, uint32_t base, int f, aspack_version_t version);
29 44
 
30 45
 #endif
... ...
@@ -4821,11 +4821,26 @@ out_no_petite:
4821 4821
 
4822 4822
 
4823 4823
     /* ASPACK support */
4824
-    while((DCONF & PE_CONF_ASPACK) && ep+58+0x70e < fsize && !memcmp(epbuff,"\x60\xe8\x03\x00\x00\x00\xe9\xeb",8)) {
4824
+    while((DCONF & PE_CONF_ASPACK) && 
4825
+          ((ep+ASPACK_EP_OFFSET_212 < fsize) || 
4826
+           (ep+ASPACK_EP_OFFSET_OTHER < fsize) || 
4827
+           (ep+ASPACK_EP_OFFSET_242 < fsize)) && 
4828
+          (!memcmp(epbuff,"\x60\xe8\x03\x00\x00\x00\xe9\xeb",8))) {
4825 4829
         char *src;
4830
+        aspack_version_t aspack_ver = ASPACK_VER_NONE;
4826 4831
 
4827
-        if(epsize<0x3bf || memcmp(epbuff+0x3b9, "\x68\x00\x00\x00\x00\xc3",6))
4832
+        if(epsize<0x3bf)
4828 4833
             break;
4834
+        
4835
+        if ( 0 == memcmp(epbuff+ASPACK_EPBUFF_OFFSET_212, "\x68\x00\x00\x00\x00\xc3",6)) {
4836
+            aspack_ver = ASPACK_VER_212;
4837
+        } else if ( 0 == memcmp(epbuff+ASPACK_EPBUFF_OFFSET_OTHER, "\x68\x00\x00\x00\x00\xc3",6)) {
4838
+            aspack_ver = ASPACK_VER_OTHER;
4839
+        } else if ( 0 == memcmp(epbuff+ASPACK_EPBUFF_OFFSET_242, "\x68\x00\x00\x00\x00\xc3",6)) {
4840
+            aspack_ver = ASPACK_VER_242;
4841
+        } else {
4842
+            break;
4843
+        }
4829 4844
         ssize = 0;
4830 4845
         for(i=0 ; i< nsections ; i++)
4831 4846
             if(ssize<exe_sections[i].rva+exe_sections[i].vsz)
... ...
@@ -4863,7 +4878,7 @@ out_no_petite:
4863 4863
 #endif
4864 4864
 
4865 4865
         CLI_UNPTEMP("Aspack",(src,exe_sections,0));
4866
-        CLI_UNPRESULTS("Aspack",(unaspack212((uint8_t *)src, ssize, exe_sections, nsections, vep-1, EC32(optional_hdr32.ImageBase), ndesc)),1,(src,0));
4866
+        CLI_UNPRESULTS("Aspack",(unaspack((uint8_t *)src, ssize, exe_sections, nsections, vep-1, EC32(optional_hdr32.ImageBase), ndesc, aspack_ver)),1,(src,0));
4867 4867
         break;
4868 4868
     }
4869 4869