Browse code

Tolerate different LZMA parameters in UPX compression

Signed-off-by: Steven Morgan <stevmorg@cisco.com>

Jonas Zaddach authored on 2017/04/29 00:59:23
Showing 3 changed files
... ...
@@ -98,7 +98,9 @@
98 98
 #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"
99 99
 #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"
100 100
 #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"
101
-#define UPX_LZMA1 "\x56\x83\xc3\x04\x53\x50\xc7\x03\x03\x00\x02\x00\x90\x90\x90\x55\x57\x56\x53\x83"
101
+#define UPX_LZMA1_FIRST  "\x56\x83\xc3\x04\x53\x50\xc7\x03"
102
+#define UPX_LZMA1_SECOND "\x90\x90\x90\x55\x57\x56\x53\x83"
103
+#define UPX_LZMA0 "\x56\x83\xc3\x04\x53\x50\xc7\x03\x03\x00\x00\x00\x90\x90\x90\x55\x57\x56\x53\x83"
102 104
 #define UPX_LZMA2 "\x56\x83\xc3\x04\x53\x50\xc7\x03\x03\x00\x02\x00\x90\x90\x90\x90\x90\x55\x57\x56"
103 105
 
104 106
 #define PE_MAXNAMESIZE 256
... ...
@@ -4478,9 +4480,10 @@ int cli_scanpe(cli_ctx *ctx)
4478 4478
             }
4479 4479
 
4480 4480
             if(strictdsize<=dsize)
4481
-                upx_success = upx_inflatelzma(src+skew, ssize-skew, dest, &strictdsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >=0;
4482
-        } else if (cli_memstr(UPX_LZMA1, 20, epbuff + 0x39, 20)) {
4481
+                upx_success = upx_inflatelzma(src+skew, ssize-skew, dest, &strictdsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep, 0x20003) >=0;
4482
+        } else if (cli_memstr(UPX_LZMA1_FIRST, 8, epbuff + 0x39, 8) && cli_memstr(UPX_LZMA1_SECOND, 8, epbuff + 0x45, 8)) {
4483 4483
             uint32_t strictdsize=cli_readint32(epbuff+0x2b), skew = 0;
4484
+            uint32_t properties=cli_readint32(epbuff+0x41);
4484 4485
             if(ssize > 0x15 && epbuff[0] == '\x60' && epbuff[1] == '\xbe') {
4485 4486
                 skew = cli_readint32(epbuff+2) - exe_sections[i + 1].rva - optional_hdr32.ImageBase;
4486 4487
                 if(skew!=0x15)
... ...
@@ -4488,7 +4491,7 @@ int cli_scanpe(cli_ctx *ctx)
4488 4488
             }
4489 4489
 
4490 4490
             if(strictdsize<=dsize)
4491
-                upx_success = upx_inflatelzma(src+skew, ssize-skew, dest, &strictdsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >=0;
4491
+                upx_success = upx_inflatelzma(src+skew, ssize-skew, dest, &strictdsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep, properties) >=0;
4492 4492
         }
4493 4493
 
4494 4494
         if(!upx_success) {
... ...
@@ -543,14 +543,19 @@ int upx_inflate2e(const char *src, uint32_t ssize, char *dst, uint32_t *dsize, u
543 543
   return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur);
544 544
 }
545 545
 
546
-int upx_inflatelzma(const char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) {
546
+int upx_inflatelzma(const char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep, uint32_t properties) {
547 547
   struct CLI_LZMA l;
548 548
   uint32_t magic[]={0xb16,0xb1e,0};
549 549
   unsigned char fake_lzmahdr[5];
550 550
 
551 551
   memset(&l, 0, sizeof(l));
552 552
   cli_writeint32(fake_lzmahdr + 1, *dsize);
553
-  *fake_lzmahdr = 3 /* lc */ + 9* ( 5* 2 /* pb */ + 0 /* lp */);
553
+  uint8_t lc = properties & 0xff;
554
+  uint8_t pb = (properties >> 16) & 0xff; 
555
+  if (lc >= 9 || pb >= 5)
556
+      return 0;
557
+
558
+  *fake_lzmahdr = lc + 9* ( 5* pb + 0 /* lp */);
554 559
   l.next_in = fake_lzmahdr;
555 560
   l.avail_in = 5;
556 561
   if(cli_LzmaInit(&l, *dsize) != LZMA_RESULT_OK)
... ...
@@ -27,6 +27,6 @@
27 27
 int upx_inflate2b(const char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t);
28 28
 int upx_inflate2d(const char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t);
29 29
 int upx_inflate2e(const char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t);
30
-int upx_inflatelzma(const char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t);
30
+int upx_inflatelzma(const char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t, uint32_t);
31 31
 
32 32
 #endif