git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1692 77e5149b-7576-45b1-b177-96237e5ba77b
aCaB authored on 2005/08/14 02:17:14... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sat Aug 13 19:08:55 CEST 2005 (acab) |
|
2 |
+----------------------------------- |
|
3 |
+ * libclamav/spin.c: improvements and fixups |
|
4 |
+ |
|
1 | 5 |
Fri Aug 12 18:17:59 CEST 2005 (tk) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav/filetypes.c: update zip-sfx type signature (Sven Strickroth) |
... | ... |
@@ -75,16 +75,16 @@ static inline uint32_t EC32(uint32_t v) |
75 | 75 |
#define ROR(a,b) a = ( a >> (b % (sizeof(a)<<3) )) | (a << ( (sizeof(a)<<3) - (b % (sizeof(a)<<3 )) ) ) |
76 | 76 |
|
77 | 77 |
|
78 |
-/* FIXME: poly block is fixed size */ |
|
79 |
-static char exec86(uint8_t aelle, uint8_t cielle, char *curremu) { |
|
80 |
- while (*curremu!='\xaa') { |
|
81 |
- uint8_t opcode = *curremu, support; |
|
82 |
- curremu++; |
|
78 |
+static char exec86(uint8_t aelle, uint8_t cielle, char *curremu) { |
|
79 |
+ int len = 0; |
|
80 |
+ while (len <0x24) { |
|
81 |
+ uint8_t opcode = curremu[len], support; |
|
82 |
+ len++; |
|
83 | 83 |
switch (opcode) { |
84 | 84 |
case 0xeb: |
85 |
- curremu++; |
|
85 |
+ len++; |
|
86 | 86 |
case 0x0a: |
87 |
- curremu++; |
|
87 |
+ len++; |
|
88 | 88 |
case 0x90: |
89 | 89 |
case 0xf8: |
90 | 90 |
case 0xf9: |
... | ... |
@@ -92,47 +92,49 @@ static char exec86(uint8_t aelle, uint8_t cielle, char *curremu) { |
92 | 92 |
|
93 | 93 |
case 0x02: /* add al, cl */ |
94 | 94 |
aelle+=cielle; |
95 |
- curremu++; |
|
95 |
+ len++; |
|
96 | 96 |
break; |
97 | 97 |
case 0x2a: /* sub al, cl */ |
98 | 98 |
aelle-=cielle; |
99 |
- curremu++; |
|
99 |
+ len++; |
|
100 | 100 |
break; |
101 | 101 |
case 0x04: /* add al, ?? */ |
102 |
- aelle+=*curremu; |
|
103 |
- curremu++; |
|
102 |
+ aelle+=curremu[len]; |
|
103 |
+ len++; |
|
104 | 104 |
break; |
105 | 105 |
case 0x2c: /* sub al, ?? */ |
106 |
- aelle-=*curremu; |
|
107 |
- curremu++; |
|
106 |
+ aelle-=curremu[len]; |
|
107 |
+ len++; |
|
108 | 108 |
break; |
109 | 109 |
case 0x32: /* xor al, cl */ |
110 | 110 |
aelle^=cielle; |
111 |
- curremu++; |
|
111 |
+ len++; |
|
112 | 112 |
break; |
113 | 113 |
case 0x34: /* xor al, ?? */ |
114 |
- aelle^=*curremu; |
|
115 |
- curremu++; |
|
114 |
+ aelle^=curremu[len]; |
|
115 |
+ len++; |
|
116 | 116 |
break; |
117 | 117 |
|
118 | 118 |
case 0xfe: /* inc/dec al */ |
119 |
- if ( *curremu == '\xc0' ) aelle++; |
|
119 |
+ if ( curremu[len] == '\xc0' ) aelle++; |
|
120 | 120 |
else aelle--; |
121 |
- curremu++; |
|
121 |
+ len++; |
|
122 | 122 |
break; |
123 | 123 |
|
124 | 124 |
case 0xc0: /* ror/rol al, ?? */ |
125 |
- support = *curremu; |
|
126 |
- curremu++; |
|
127 |
- if ( support == 0xc0 ) ROL(aelle, *curremu); |
|
128 |
- else ROR(aelle, *curremu); |
|
129 |
- curremu++; |
|
125 |
+ support = curremu[len]; |
|
126 |
+ len++; |
|
127 |
+ if ( support == 0xc0 ) ROL(aelle, curremu[len]); |
|
128 |
+ else ROR(aelle, curremu[len]); |
|
129 |
+ len++; |
|
130 | 130 |
break; |
131 | 131 |
|
132 | 132 |
default: |
133 | 133 |
cli_dbgmsg("Bogus opcode %x\n", opcode); |
134 | 134 |
} |
135 | 135 |
} |
136 |
+ if ( len!=0x24 || curremu[len]!='\xaa' ) |
|
137 |
+ cli_dbgmsg("spin: bad emucode\n"); // FIXME: I should really give up here |
|
136 | 138 |
return aelle; |
137 | 139 |
} |
138 | 140 |
|
... | ... |
@@ -261,7 +263,7 @@ static int unfsg(char *source, char *dest, int ssize, int dsize) { |
261 | 261 |
} |
262 | 262 |
lostbit = 0; |
263 | 263 |
} |
264 |
- if ((backsize >= dest + dsize - cdst) || (backbytes > cdst - dest)) |
|
264 |
+ if ((backsize > dest + dsize - cdst) || (backbytes > cdst - dest)) |
|
265 | 265 |
return -1; |
266 | 266 |
while(backsize--) { |
267 | 267 |
*cdst=*(cdst-backbytes); |
... | ... |
@@ -346,12 +348,20 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
346 | 346 |
|
347 | 347 |
cli_dbgmsg("spin: Key8 is %x, Len is %x\n", key8, len); |
348 | 348 |
|
349 |
- if ( ep - spinned >= EC32(sections[sectcnt].SizeOfRawData) - len - 0x1fe5 ) { |
|
349 |
+ if ( ep - spinned >= EC32(sections[sectcnt].SizeOfRawData) - len - 0x1fe5 ) { |
|
350 | 350 |
free(spinned); |
351 | 351 |
cli_dbgmsg("spin: len out of bounds, giving up\n"); |
352 | 352 |
return 1; // Outta bounds - HELP: i suppose i should check for wraps.. not sure though |
353 | 353 |
} |
354 | 354 |
|
355 |
+ |
|
356 |
+ if ( ep[0x1e0]!='\xb8' ) |
|
357 |
+ cli_dbgmsg("spin: prolly not spinned, expect failure\n"); |
|
358 |
+ |
|
359 |
+ if ( (cli_readint32(ep+0x1e1) & 0x00200000) ) |
|
360 |
+ cli_dbgmsg("spin: password protected, expect failure\n"); |
|
361 |
+ |
|
362 |
+ |
|
355 | 363 |
curr = ep+0x1fe5+len-1; |
356 | 364 |
while ( len-- ) { |
357 | 365 |
*curr=(*curr)^(key8--); |
... | ... |
@@ -363,7 +373,7 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
363 | 363 |
if ( (len = cli_readint32(curr+5)) != 0x5a0) { |
364 | 364 |
free(spinned); |
365 | 365 |
cli_dbgmsg("spin: Not spinned or bad version\n"); |
366 |
- return 1; // FIXME: apparently static |
|
366 |
+ return 1; |
|
367 | 367 |
} |
368 | 368 |
|
369 | 369 |
curr = ep+0x2d5; // 0x2d5+5a0 < 0x3217 - still within bounds (checked by caller) |
... | ... |
@@ -380,8 +390,6 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
380 | 380 |
curr++; |
381 | 381 |
} |
382 | 382 |
|
383 |
- |
|
384 |
- cli_dbgmsg("spin: here\n"); |
|
385 | 383 |
len = ssize - cli_readint32(ep+0x429); // sub size, value |
386 | 384 |
if ( len >= ssize ) { |
387 | 385 |
free(spinned); |
... | ... |
@@ -394,11 +402,10 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
394 | 394 |
free(spinned); // done CRC'ing - can have a dirty buffer now |
395 | 395 |
ep = src + nep + sections[sectcnt].PointerToRawData - sections[sectcnt].VirtualAddress; // Fix the helper |
396 | 396 |
|
397 |
- cli_dbgmsg("spin: Key32 is %x\n", key32); |
|
398 |
- |
|
399 | 397 |
bitmap = cli_readint32(ep+0x3207); |
400 |
- cli_dbgmsg("spin: XORbitmap is %x\n", bitmap); |
|
401 |
- |
|
398 |
+ cli_dbgmsg("spin: Key32 is %x - XORbitmap is %x\n", key32, bitmap); |
|
399 |
+ |
|
400 |
+ cli_dbgmsg("spin: Decrypting sects (xor)\n"); |
|
402 | 401 |
for (j=0; j<sectcnt; j++) { |
403 | 402 |
if (bitmap&1) { |
404 | 403 |
uint32_t size = EC32(sections[j].SizeOfRawData); |
... | ... |
@@ -424,9 +431,10 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
424 | 424 |
bitmap = bitmap >>1 & 0x7fffffff; /* HELP: clear sign bit for unsigned values too? */ |
425 | 425 |
} |
426 | 426 |
} |
427 |
+ |
|
427 | 428 |
cli_dbgmsg("spin: done\n"); |
428 | 429 |
|
429 |
- |
|
430 |
+ |
|
430 | 431 |
curr = ep+0x644; // 0x28d3+0x180 < 0x3217 - still within bounds (checked by caller) |
431 | 432 |
if ( (len = cli_readint32(curr)) != 0x180) { |
432 | 433 |
cli_dbgmsg("spin: Not spinned or bad version\n"); |
... | ... |
@@ -465,8 +473,9 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
465 | 465 |
emu++; |
466 | 466 |
} |
467 | 467 |
|
468 |
+ |
|
468 | 469 |
bitmap = cli_readint32(ep+0x6f1); |
469 |
- cli_dbgmsg("spin: POLYbitmap is %x\n", bitmap); |
|
470 |
+ cli_dbgmsg("spin: POLYbitmap is %x - decrypting sects (poly)\n", bitmap); |
|
470 | 471 |
curr = ep+0x755; |
471 | 472 |
|
472 | 473 |
for (j=0; j<sectcnt; j++) { |
... | ... |
@@ -489,6 +498,8 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
489 | 489 |
|
490 | 490 |
} |
491 | 491 |
} |
492 |
+ |
|
493 |
+ cli_dbgmsg("spin: done\n"); |
|
492 | 494 |
|
493 | 495 |
bitmap = cli_readint32(ep+0x3061); |
494 | 496 |
bitman = bitmap; |
... | ... |
@@ -500,13 +511,17 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
500 | 500 |
for (j=0; j<sectcnt; j++) { |
501 | 501 |
if (bitmap&1) { |
502 | 502 |
if ( (sects[j] = (char *) cli_malloc(EC32(sections[j].VirtualSize)) ) == NULL ) { // FIXME: use "static" maxmalloc @4380b6 instead??? |
503 |
+ cli_dbgmsg("spin: malloc(%d) failed\n", EC32(sections[j].VirtualSize)); |
|
503 | 504 |
len = 1; |
504 | 505 |
break; |
505 | 506 |
} |
506 | 507 |
blobsz+=EC32(sections[j].VirtualSize); |
507 | 508 |
memset(sects[j], 0, EC32(sections[j].VirtualSize)); |
508 | 509 |
cli_dbgmsg("spin: Growing sect%d: was %x will be %x\n", j, EC32(sections[j].SizeOfRawData), EC32(sections[j].VirtualSize)); |
509 |
- len = unfsg(src + EC32(sections[j].PointerToRawData), sects[j], EC32(sections[j].SizeOfRawData), EC32(sections[j].VirtualSize)); // FIXME: checr retval |
|
510 |
+ if ( unfsg(src + EC32(sections[j].PointerToRawData), sects[j], EC32(sections[j].SizeOfRawData), EC32(sections[j].VirtualSize)) == -1 ) { |
|
511 |
+ len++; |
|
512 |
+ cli_dbgmsg("spin: Unpack failure\n"); |
|
513 |
+ } |
|
510 | 514 |
// sections[j].rsz = sections[j].vsz; FIXME: can't hack the caller, gotta find a better way! |
511 | 515 |
} else { |
512 | 516 |
blobsz+=EC32(sections[j].SizeOfRawData); |
... | ... |
@@ -515,12 +530,16 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
515 | 515 |
} |
516 | 516 |
bitmap = bitmap >>1 & 0x7fffffff; |
517 | 517 |
} |
518 |
- |
|
518 |
+ |
|
519 |
+ cli_dbgmsg("spin: decompression complete\n"); |
|
520 |
+ |
|
519 | 521 |
if ( len ) { |
520 | 522 |
int t; |
521 |
- for (t=0 ; t<j ; t++) |
|
523 |
+ for (t=0 ; t<j ; t++) { |
|
522 | 524 |
if (bitman&1) |
523 | 525 |
free(sects[t]); |
526 |
+ bitman = bitman >>1 & 0x7fffffff; |
|
527 |
+ } |
|
524 | 528 |
free(sects); |
525 | 529 |
return 1; |
526 | 530 |
} |
... | ... |
@@ -535,10 +554,10 @@ int unspin(char *src, int ssize, struct pe_image_section_hdr *sections, int sect |
535 | 535 |
break; |
536 | 536 |
} |
537 | 537 |
|
538 |
- cli_dbgmsg("spin: --- %x < %x < %x %d / %d\n", EC32(sections[j].VirtualAddress), key32, EC32(sections[j].VirtualAddress)+EC32(sections[j].SizeOfRawData), j, sectcnt); |
|
538 |
+// cli_dbgmsg("spin: --- %x < %x < %x %d / %d\n", EC32(sections[j].VirtualAddress), key32, EC32(sections[j].VirtualAddress)+EC32(sections[j].SizeOfRawData), j, sectcnt); |
|
539 | 539 |
|
540 | 540 |
if (j!=sectcnt && ((bitman & (1<<j)) == 0)) { // FIXME: not really sure either the res sect is lamed or just compressed, but this'll save some major headakes |
541 |
- cli_dbgmsg("spin: Resources (sect%d) appear to be compressed\n uncompressed offset %x, len %x\n compressed offset %x, len %x\n", j, EC32(sections[j].VirtualAddress), key32 - EC32(sections[j].VirtualAddress), key32, EC32(sections[j].VirtualSize) - (key32 - EC32(sections[j].VirtualAddress))); |
|
541 |
+ cli_dbgmsg("spin: Resources (sect%d) appear to be compressed\n\tuncompressed offset %x, len %x\n\tcompressed offset %x, len %x\n", j, EC32(sections[j].VirtualAddress), key32 - EC32(sections[j].VirtualAddress), key32, EC32(sections[j].VirtualSize) - (key32 - EC32(sections[j].VirtualAddress))); |
|
542 | 542 |
|
543 | 543 |
if ( (curr=(char *)cli_malloc(EC32(sections[j].VirtualSize))) != NULL ) { |
544 | 544 |
memcpy(curr, src + EC32(sections[j].PointerToRawData), key32 - EC32(sections[j].VirtualAddress)); // Uncompressed part |