...
|
...
|
@@ -38,12 +38,13 @@
|
38
|
38
|
#include "upx.h"
|
39
|
39
|
|
40
|
40
|
#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */
|
|
41
|
+#define IMAGE_DOS_SIGNATURE_OLD 0x4d5a /* ZM */
|
41
|
42
|
#define IMAGE_NT_SIGNATURE 0x00004550
|
42
|
43
|
#define IMAGE_OPTIONAL_SIGNATURE 0x010b
|
43
|
44
|
|
44
|
|
-#define UPX_NRV2B "\x11\xc9\x75\x20\x41\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x73\xef\x75\x09"
|
45
|
|
-#define UPX_NRV2D "\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x75\x20"
|
46
|
|
-#define UPX_NRV2E "\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x72\xcc"
|
|
45
|
+#define UPX_NRV2B "\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x11\xc9\x75\x20\x41\x01\xdb"
|
|
46
|
+#define UPX_NRV2D "\x83\xf0\xff\x74\x78\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9"
|
|
47
|
+#define UPX_NRV2E "\xeb\x52\x31\xc9\x83\xe8\x03\x72\x11\xc1\xe0\x08\x8a\x06\x46\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5"
|
47
|
48
|
|
48
|
49
|
#if WORDS_BIGENDIAN == 0
|
49
|
50
|
#define EC16(v) (v)
|
...
|
...
|
@@ -234,7 +235,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
234
|
234
|
struct pe_image_section_hdr *section_hdr;
|
235
|
235
|
struct stat sb;
|
236
|
236
|
char sname[9], buff[24], *tempfile;
|
237
|
|
- int i, found, upx_success = 0;
|
|
237
|
+ int i, found, upx_success = 0, broken = 0;
|
238
|
238
|
int (*upxfn)(char *, int , char *, int) = NULL;
|
239
|
239
|
|
240
|
240
|
|
...
|
...
|
@@ -243,7 +244,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
243
|
243
|
return CL_EIO;
|
244
|
244
|
}
|
245
|
245
|
|
246
|
|
- if(EC16(e_magic) != IMAGE_DOS_SIGNATURE) {
|
|
246
|
+ if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
|
247
|
247
|
cli_dbgmsg("Invalid DOS signature\n");
|
248
|
248
|
return CL_CLEAN;
|
249
|
249
|
}
|
...
|
...
|
@@ -375,6 +376,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
375
|
375
|
strncpy(sname, section_hdr[i].Name, 8);
|
376
|
376
|
sname[8] = 0;
|
377
|
377
|
cli_dbgmsg("------------------------------------\n");
|
|
378
|
+ cli_dbgmsg("Section %d of %d\n", i, nsections);
|
378
|
379
|
cli_dbgmsg("Section name: %s\n", sname);
|
379
|
380
|
cli_dbgmsg("VirtualSize: %d\n", EC32(section_hdr[i].VirtualSize));
|
380
|
381
|
cli_dbgmsg("VirtualAddress: 0x%x\n", EC32(section_hdr[i].VirtualAddress));
|
...
|
...
|
@@ -414,11 +416,18 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
414
|
414
|
return CL_EIO;
|
415
|
415
|
}
|
416
|
416
|
|
417
|
|
- ep = cli_rawaddr(EC32(optional_hdr.AddressOfEntryPoint), section_hdr, nsections);
|
|
417
|
+ if((ep = cli_rawaddr(EC32(optional_hdr.AddressOfEntryPoint), section_hdr, nsections)) == -1) {
|
|
418
|
+ cli_dbgmsg("Possibly broken PE file - Entry Point @%d out of file.\n", ep);
|
|
419
|
+ broken = 1;
|
|
420
|
+ }
|
418
|
421
|
|
419
|
422
|
/* simple sanity check */
|
420
|
|
- if(EC32(section_hdr[nsections - 1].PointerToRawData) + EC32(section_hdr[nsections - 1].SizeOfRawData) > sb.st_size || ep == -1) {
|
421
|
|
- cli_dbgmsg("Possibly broken PE file\n");
|
|
423
|
+ if(!broken && EC32(section_hdr[nsections - 1].PointerToRawData) + EC32(section_hdr[nsections - 1].SizeOfRawData) > sb.st_size) {
|
|
424
|
+ cli_dbgmsg("Possibly broken PE file - Section %d out of file (Offset@ %d, Rsize %d, Total filesize %d, EP@ %d)\n", i, EC32(section_hdr[i].PointerToRawData), EC32(section_hdr[i].SizeOfRawData), sb.st_size, ep);
|
|
425
|
+ broken = 1;
|
|
426
|
+ }
|
|
427
|
+
|
|
428
|
+ if(broken) {
|
422
|
429
|
free(section_hdr);
|
423
|
430
|
return CL_CLEAN;
|
424
|
431
|
}
|
...
|
...
|
@@ -431,7 +440,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
431
|
431
|
/* try to find the first section with physical size == 0 */
|
432
|
432
|
found = 0;
|
433
|
433
|
for(i = 0; i < nsections - 1; i++) {
|
434
|
|
- if(!section_hdr[i].SizeOfRawData) {
|
|
434
|
+ if(!section_hdr[i].SizeOfRawData && section_hdr[i].VirtualSize && section_hdr[i+1].SizeOfRawData && section_hdr[i+1].VirtualSize) {
|
435
|
435
|
found = 1;
|
436
|
436
|
cli_dbgmsg("UPX: empty section found - assuming UPX compression\n");
|
437
|
437
|
break;
|
...
|
...
|
@@ -484,23 +493,23 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
484
|
484
|
|
485
|
485
|
/* try to detect UPX code */
|
486
|
486
|
|
487
|
|
- if(lseek(desc, ep + 0x78, SEEK_SET) == -1) {
|
|
487
|
+ if(lseek(desc, ep + 0x69, SEEK_SET) == -1) {
|
488
|
488
|
cli_dbgmsg("lseek() failed\n");
|
489
|
489
|
free(section_hdr);
|
490
|
490
|
return CL_EIO;
|
491
|
491
|
}
|
492
|
492
|
|
493
|
|
- if(read(desc, buff, 13) != 13) {
|
494
|
|
- cli_dbgmsg("UPX: Can't read 13 bytes at 0x%x (%d)\n", ep + 0x78, ep + 0x78);
|
|
493
|
+ if(read(desc, buff, 21) != 21) {
|
|
494
|
+ cli_dbgmsg("UPX: Can't read 21 bytes at 0x%x (%d)\n", ep + 0x69, ep + 0x78);
|
495
|
495
|
return CL_EIO;
|
496
|
496
|
} else {
|
497
|
|
- if(cli_memstr(UPX_NRV2B, 24, buff, 13)) {
|
|
497
|
+ if(cli_memstr(UPX_NRV2B, 24, buff, 13) || cli_memstr(UPX_NRV2B, 24, buff + 8, 13)) {
|
498
|
498
|
cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
|
499
|
499
|
upxfn = upx_inflate2b;
|
500
|
|
- } else if(cli_memstr(UPX_NRV2D, 24, buff, 13)) {
|
|
500
|
+ } else if(cli_memstr(UPX_NRV2D, 24, buff, 13) || cli_memstr(UPX_NRV2D, 24, buff + 8, 13)) {
|
501
|
501
|
cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n");
|
502
|
502
|
upxfn = upx_inflate2d;
|
503
|
|
- } else if(cli_memstr(UPX_NRV2E, 24, buff, 13)) {
|
|
503
|
+ } else if(cli_memstr(UPX_NRV2E, 24, buff, 13) || cli_memstr(UPX_NRV2E, 24, buff + 8, 13)) {
|
504
|
504
|
cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n");
|
505
|
505
|
upxfn = upx_inflate2e;
|
506
|
506
|
}
|
...
|
...
|
@@ -511,7 +520,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
511
|
511
|
cli_dbgmsg("UPX: Prefered decompressor failed\n");
|
512
|
512
|
} else {
|
513
|
513
|
upx_success = 1;
|
514
|
|
- cli_dbgmsg("UPX: Successfuly decompressed\n");
|
|
514
|
+ cli_dbgmsg("UPX: Successfully decompressed\n");
|
515
|
515
|
}
|
516
|
516
|
}
|
517
|
517
|
|
...
|
...
|
@@ -520,7 +529,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
520
|
520
|
cli_dbgmsg("UPX: NRV2B decompressor failed\n");
|
521
|
521
|
} else {
|
522
|
522
|
upx_success = 1;
|
523
|
|
- cli_dbgmsg("UPX: Successfuly decompressed with NRV2B\n");
|
|
523
|
+ cli_dbgmsg("UPX: Successfully decompressed with NRV2B\n");
|
524
|
524
|
}
|
525
|
525
|
}
|
526
|
526
|
|
...
|
...
|
@@ -529,7 +538,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
529
|
529
|
cli_dbgmsg("UPX: NRV2D decompressor failed\n");
|
530
|
530
|
} else {
|
531
|
531
|
upx_success = 1;
|
532
|
|
- cli_dbgmsg("UPX: Successfuly decompressed with NRV2D\n");
|
|
532
|
+ cli_dbgmsg("UPX: Successfully decompressed with NRV2D\n");
|
533
|
533
|
}
|
534
|
534
|
}
|
535
|
535
|
|
...
|
...
|
@@ -538,7 +547,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
|
538
|
538
|
cli_dbgmsg("UPX: NRV2E decompressor failed\n");
|
539
|
539
|
} else {
|
540
|
540
|
upx_success = 1;
|
541
|
|
- cli_dbgmsg("UPX: Successfuly decompressed with NRV2E\n");
|
|
541
|
+ cli_dbgmsg("UPX: Successfully decompressed with NRV2E\n");
|
542
|
542
|
}
|
543
|
543
|
}
|
544
|
544
|
|