Browse code

Improved rebuilding of UPX compressed files

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1172 77e5149b-7576-45b1-b177-96237e5ba77b

aCaB authored on 2004/12/13 04:43:49
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Sun Dec 12 19:40:10 UTC 2004 (acab)
2
+-----------------------------------
3
+  * libclamav: upx:  improved PE rebuild - debug info on failure
4
+  
1 5
 Fri Dec 10 15:21:48 GMT 2004 (njh)
2 6
 ----------------------------------
3 7
   * libclamav/message.c:	Warn if the content-type contains a blank entry
... ...
@@ -24,6 +24,7 @@
24 24
 ** 09/05/2k4 - Moved code outta main(), got rid of globals for thread safety, added bound checking, minor cleaning
25 25
 ** 04/06/2k4 - Now we handle 2B, 2D and 2E :D
26 26
 ** 28/08/2k4 - PE rebuild for nested packers
27
+** 12/12/2k4 - Improved PE rebuild code and added some debug info on failure
27 28
 */
28 29
 
29 30
 /*
... ...
@@ -90,8 +91,10 @@ int pefromupx (char *src, char *dst, int *dsize, uint32_t ep, uint32_t upx0, uin
90 90
 
91 91
   realstuffsz = imports-dst;
92 92
   
93
-  if ( realstuffsz < 0 || realstuffsz > *dsize )
93
+  if ( realstuffsz < 0 || realstuffsz > *dsize ) {
94
+    cli_dbgmsg("UPX: wrong realstuff size - giving up rebuild\n");
94 95
     return 0;
96
+  }
95 97
   
96 98
   pehdr = imports;
97 99
   while (pehdr+7 < dst+*dsize && cli_readint32(pehdr)) {
... ...
@@ -106,23 +109,33 @@ int pefromupx (char *src, char *dst, int *dsize, uint32_t ep, uint32_t upx0, uin
106 106
   }
107 107
 
108 108
   pehdr+=4;
109
-  if (pehdr+0xf8 > dst+*dsize)
109
+  if (pehdr+0xf8 > dst+*dsize) {
110
+    cli_dbgmsg("UPX: sections out of bounds - giving up rebuild\n");
110 111
     return 0;
112
+  }
111 113
   
112
-  if ( cli_readint32(pehdr) != 0x4550 )
114
+  if ( cli_readint32(pehdr) != 0x4550 ) {
115
+    cli_dbgmsg("UPX: No magic for PE - giving up rebuild\n");
113 116
     return 0;
117
+  }
114 118
   
115
-  if (! (align = cli_readint32(pehdr+0x38)))
119
+  if (! (align = cli_readint32(pehdr+0x38))) {
120
+    cli_dbgmsg("UPX: Cant align to a NULL bound - giving up rebuild\n");
116 121
     return 0;
122
+  }
117 123
   
118 124
   sections = pehdr+0xf8;
119
-  if ( ! (sectcnt = pehdr[6]+256*pehdr[7]))
125
+  if ( ! (sectcnt = pehdr[6]+256*pehdr[7])) {
126
+    cli_dbgmsg("UPX: No sections? - giving up rebuild\n");
120 127
     return 0;
128
+  }
121 129
   
122 130
   foffset+=0x28*sectcnt;
123 131
   
124
-  if (pehdr + 0xf8 + 0x28*sectcnt >= dst + *dsize)
132
+  if (pehdr + 0xf8 + 0x28*sectcnt >= dst + *dsize) {
133
+    cli_dbgmsg("UPX: Not enough space for all sects - giving up rebuild\n");
125 134
     return 0;
135
+  }
126 136
   
127 137
   for (upd = 0; upd <sectcnt ; upd++) {
128 138
     uint32_t vsize=cli_readint32(sections+8)-1;
... ...
@@ -132,16 +145,22 @@ int pefromupx (char *src, char *dst, int *dsize, uint32_t ep, uint32_t upx0, uin
132 132
     vsize=(((vsize/0x1000)+1)*0x1000); /* FIXME: get bounds from header */
133 133
     
134 134
     /* Within bounds ? */
135
-    if ( urva < upx0 || urva + vsize > upx0 + realstuffsz)
135
+    if ( urva < upx0 || urva + vsize > upx0 + realstuffsz) {
136
+      cli_dbgmsg("UPX: Sect %d out of bounds - giving up rebuild\n", upd);
136 137
       return 0;
138
+    }
137 139
     
138 140
     /* Rsize -gt Vsize ? */
139
-    if ( rsize > vsize )
141
+    if ( rsize > vsize ) {
142
+      cli_dbgmsg("UPX: Raw size for sect %d is greater than virtual (%x / %x) - giving up rebuild\n", upd, rsize, vsize);
140 143
       return 0;
144
+    }
141 145
     
142 146
     /* Am i been fooled? There are better ways ;) */
143
-    if ( rsize+4 < vsize && cli_readint32(dst+urva-upx0+rsize) )
147
+    if ( rsize+4 < vsize && cli_readint32(dst+urva-upx0+rsize) ) {
148
+      cli_dbgmsg("UPX: Am i been fooled? - giving up rebuild\n", upd);
144 149
       return 0;
150
+    }
145 151
     
146 152
     cli_writeint32(sections+8, vsize);
147 153
     cli_writeint32(sections+20, foffset);
... ...
@@ -152,9 +171,11 @@ int pefromupx (char *src, char *dst, int *dsize, uint32_t ep, uint32_t upx0, uin
152 152
 
153 153
   cli_writeint32(pehdr+8, 0x4d414c43);
154 154
 
155
-  if (!(newbuf = (char *) cli_malloc(foffset)))
155
+  if (!(newbuf = (char *) cli_malloc(foffset))) {
156
+    cli_dbgmsg("UPX: malloc failed - giving up rebuild\n", upd);
156 157
     return 0;
157
-
158
+  }
159
+  
158 160
   memcpy(newbuf, HEADERS, 0xd0);
159 161
   memcpy(newbuf+0xd0, pehdr,0xf8+0x28*sectcnt);
160 162
   sections = pehdr+0xf8;
... ...
@@ -283,12 +304,12 @@ int upx_inflate2b(char *src, int ssize, char *dst, int *dsize, uint32_t upx0, ui
283 283
   }
284 284
 
285 285
 
286
-  if ( ep - upx1 + 0x14f <= ssize-5  &&    /* Wondering how we got so far?! */
287
-       src[ep - upx1 + 0x14f] == '\xe9' && /* JMP OldEip                    */
286
+  if ( ep - upx1 + 0x108 <= ssize-5  &&    /* Wondering how we got so far?! */
288 287
        src[ep - upx1 + 0x106] == '\x8d' && /* lea edi, ...                  */
289 288
        src[ep - upx1 + 0x107] == '\xbe' )  /* ... [esi + offset]          */
290 289
     return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x108);
291 290
 
291
+  cli_dbgmsg("UPX: bad magic for 2b\n");
292 292
   return 0;
293 293
 }
294 294
 
... ...
@@ -372,12 +393,13 @@ int upx_inflate2d(char *src, int ssize, char *dst, int *dsize, uint32_t upx0, ui
372 372
     dcur+=backsize;
373 373
   }
374 374
 
375
-  if ( ep - upx1 + 0x139 <= ssize-5  &&    /* Wondering how we got so far?! */
376
-       src[ep - upx1 + 0x139] == '\xe9' && /* JMP OldEip                    */
377
-       src[ep - upx1 + 0xe7] == '\x8d' && /* lea edi, ...                  */
378
-       src[ep - upx1 + 0xe8] == '\xbe' )  /* ... [esi + offset]          */
379
-    return pefromupx (src, dst, dsize, ep, upx0, upx1, 0xe9);
380
-
375
+  if ( ep - upx1 + 0x124 <= ssize-5 ) {   /* Wondering how we got so far?! */
376
+    if ( src[ep - upx1 + 0x11a] == '\x8d' && src[ep - upx1 + 0x11b] == '\xbe' )
377
+      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x11c);
378
+    if ( src[ep - upx1 + 0x122] == '\x8d' && src[ep - upx1 + 0x123] == '\xbe' )
379
+      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x124);
380
+  }
381
+  cli_dbgmsg("UPX: bad magic for 2d\n");
381 382
   return 0;
382 383
 }
383 384
 
... ...
@@ -470,11 +492,12 @@ int upx_inflate2e(char *src, int ssize, char *dst, int *dsize, uint32_t upx0, ui
470 470
     dcur+=backsize;
471 471
   }
472 472
 
473
-  if ( ep - upx1 + 0x145 <= ssize-5  &&    /* Wondering how we got so far?! */
474
-       src[ep - upx1 + 0x145] == '\xe9' && /* JMP OldEip                    */
475
-       src[ep - upx1 + 0xf3] == '\x8d' && /* lea edi, ...                  */
476
-       src[ep - upx1 + 0xf4] == '\xbe' )  /* ... [esi + offset]          */
477
-    return pefromupx (src, dst, dsize, ep, upx0, upx1, 0xf5);
478
-
473
+  if ( ep - upx1 + 0x130 <= ssize-5 ) {   /* Wondering how we got so far?! */
474
+    if ( src[ep - upx1 + 0x126] == '\x8d' && src[ep - upx1 + 0x127] == '\xbe' )
475
+      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x128);
476
+    if ( src[ep - upx1 + 0x12e] == '\x8d' && src[ep - upx1 + 0x12f] == '\xbe' )
477
+      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x130);
478
+  }
479
+  cli_dbgmsg("UPX: bad magic for 2e\n");
479 480
   return 0;
480 481
 }