... | ... |
@@ -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 |
|