~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/upx.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2008 Sourcefire, Inc.
3
 
 *
4
 
 *  Authors: Alberto Wu
 
2
 *  Copyright (C) 2004 aCaB <acab@clamav.net>
5
3
 *
6
4
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License version 2 as
8
 
 *  published by the Free Software Foundation.
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation; either version 2 of the License, or
 
7
 *  (at your option) any later version.
9
8
 *
10
9
 *  This program is distributed in the hope that it will be useful,
11
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27
26
** 04/06/2k4 - Now we handle 2B, 2D and 2E :D
28
27
** 28/08/2k4 - PE rebuild for nested packers
29
28
** 12/12/2k4 - Improved PE rebuild code and added some debug info on failure
30
 
** 23/03/2k7 - New approach for rebuilding:
31
 
               o Get imports via magic
32
 
               o Get imports via leascan
33
 
               o if (!pe) pe=scan4pe();
34
 
               o if (!pe) forgepe();
35
29
*/
36
30
 
37
31
/*
55
49
#include "cltypes.h"
56
50
#include "others.h"
57
51
#include "upx.h"
58
 
#include "str.h"
59
 
#include "lzma_iface.h"
60
52
 
61
53
#define PEALIGN(o,a) (((a))?(((o)/(a))*(a)):(o))
62
54
#define PESALIGN(o,a) (((a))?(((o)/(a)+((o)%(a)!=0))*(a)):(o))
76
68
\x65\x72\x20\x2D\x20\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\
77
69
\x63\x6C\x61\x6D\x61\x76\x2E\x6E\x65\x74\x0D\x0A\x24\x00\x00\x00\
78
70
"
79
 
#define FAKEPE "\
80
 
\x50\x45\x00\x00\x4C\x01\x01\x00\x43\x4C\x41\x4D\x00\x00\x00\x00\
81
 
\x00\x00\x00\x00\xE0\x00\x83\x8F\x0B\x01\x00\x00\x00\x10\x00\x00\
82
 
\x00\x10\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x10\x00\x00\
83
 
\x00\x10\x00\x00\x00\x00\x40\x00\x00\x10\x00\x00\x00\x02\x00\x00\
84
 
\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x0A\x00\x00\x00\x00\x00\
85
 
\xFF\xFF\xFF\xFF\x00\x02\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\
86
 
\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\
87
 
\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
88
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
89
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
90
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
91
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
92
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
93
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
94
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
95
 
\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x63\x6c\x61\x6d\x30\x31\x00\
96
 
\xFF\xFF\xFF\xFF\x00\x10\x00\x00\xFF\xFF\xFF\xFF\x00\x02\x00\x00\
97
 
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\
98
 
"
99
 
 
100
 
static char *checkpe(char *dst, uint32_t dsize, char *pehdr, uint32_t *valign, unsigned int *sectcnt)
101
 
{
102
 
  char *sections;
103
 
  if (!CLI_ISCONTAINED(dst, dsize,  pehdr, 0xf8)) return NULL;
104
 
 
105
 
  if (cli_readint32(pehdr) != 0x4550 ) return NULL;
106
 
  
107
 
  if (!(*valign=cli_readint32(pehdr+0x38))) return NULL;
108
 
  
109
 
  sections = pehdr+0xf8;
110
 
  if (!(*sectcnt = (unsigned char)pehdr[6] + (unsigned char)pehdr[7]*256)) return NULL;
111
 
  
112
 
  if (!CLI_ISCONTAINED(dst, dsize, sections, *sectcnt*0x28)) return NULL;
113
 
 
114
 
  return sections;
115
 
}
116
71
 
117
72
/* PE from UPX */
118
73
 
119
 
static int pefromupx (char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t *magic, uint32_t dend)
 
74
static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t magic)
120
75
{
121
 
  char *imports, *sections=NULL, *pehdr=NULL, *newbuf;
122
 
  unsigned int sectcnt=0, upd=1;
123
 
  uint32_t realstuffsz=0, valign=0;
 
76
  char *imports, *sections, *pehdr, *newbuf;
 
77
  int sectcnt, upd=1;
 
78
  uint32_t realstuffsz, valign;
124
79
  uint32_t foffset=0xd0+0xf8;
125
80
 
126
81
  if((dst == NULL) || (src == NULL))
127
82
    return 0;
128
83
 
129
 
  while ((valign=magic[sectcnt++])) {
130
 
    if ( ep - upx1 + valign <= ssize-5  &&    /* Wondering how we got so far?! */
131
 
         src[ep - upx1 + valign - 2] == '\x8d' && /* lea edi, ...                  */
132
 
         src[ep - upx1 + valign - 1] == '\xbe' )  /* ... [esi + offset]          */
133
 
      break;
134
 
  }
135
 
 
136
 
  if (!valign && ep - upx1 + 0x80 < ssize-8) {
137
 
    const char *pt = &src[ep - upx1 + 0x80];
138
 
    cli_dbgmsg("UPX: bad magic - scanning for imports\n");
139
 
    
140
 
    while ((pt=cli_memstr(pt, ssize - (pt-src) - 8, "\x8d\xbe", 2))) {
141
 
      if (pt[6] == '\x8b' && pt[7] == '\x07') { /* lea edi, [esi+imports] / mov eax, [edi] */
142
 
        valign=pt-src+2-ep+upx1;
143
 
        break;
144
 
      }
145
 
      pt++;
146
 
    }
147
 
  }
148
 
 
149
 
  if (valign && CLI_ISCONTAINED(src, ssize, src + ep - upx1 + valign, 4)) {
150
 
    imports = dst + cli_readint32(src + ep - upx1 + valign);
151
 
    
152
 
    realstuffsz = imports-dst;
153
 
    
154
 
    if (realstuffsz >= *dsize ) {
155
 
      cli_dbgmsg("UPX: wrong realstuff size\n");
156
 
      /* fallback and eventually craft */
157
 
    } else {
158
 
      pehdr = imports;
159
 
      while (CLI_ISCONTAINED(dst, *dsize,  pehdr, 8) && cli_readint32(pehdr)) {
160
 
        pehdr+=8;
161
 
        while(CLI_ISCONTAINED(dst, *dsize,  pehdr, 2) && *pehdr) {
162
 
          pehdr++;
163
 
          while (CLI_ISCONTAINED(dst, *dsize,  pehdr, 2) && *pehdr)
164
 
            pehdr++;
165
 
          pehdr++;
166
 
        }
 
84
  imports = dst + cli_readint32(src + ep - upx1 + magic);
 
85
 
 
86
  realstuffsz = imports-dst;
 
87
  
 
88
  if (realstuffsz >= *dsize ) {
 
89
    cli_dbgmsg("UPX: wrong realstuff size - giving up rebuild\n");
 
90
    return 0;
 
91
  }
 
92
  
 
93
  pehdr = imports;
 
94
  while (CLI_ISCONTAINED(dst, *dsize,  pehdr, 8) && cli_readint32(pehdr)) {
 
95
    pehdr+=8;
 
96
    while(CLI_ISCONTAINED(dst, *dsize,  pehdr, 2) && *pehdr) {
 
97
      pehdr++;
 
98
      while (CLI_ISCONTAINED(dst, *dsize,  pehdr, 2) && *pehdr)
167
99
        pehdr++;
168
 
      }
169
 
      
170
 
      pehdr+=4;
171
 
      if (!(sections=checkpe(dst, *dsize, pehdr, &valign, &sectcnt))) pehdr=NULL;
172
 
    }
173
 
  }
174
 
 
175
 
  if (!pehdr && dend>0xf8+0x28) {
176
 
    cli_dbgmsg("UPX: no luck - scanning for PE\n");
177
 
    pehdr = &dst[dend-0xf8-0x28];
178
 
    while (pehdr>dst) {
179
 
      if ((sections=checkpe(dst, *dsize, pehdr, &valign, &sectcnt)))
180
 
        break;
181
 
      pehdr--;
182
 
    }
183
 
    if (!(realstuffsz = pehdr-dst)) pehdr=NULL;
184
 
  }
185
 
 
186
 
  if (!pehdr) {
187
 
    uint32_t rebsz = PESALIGN(dend, 0x1000);
188
 
    cli_dbgmsg("UPX: no luck - brutally crafing a reasonable PE\n");
189
 
    if (!(newbuf = (char *)cli_calloc(rebsz+0x200, sizeof(char)))) {
190
 
      cli_dbgmsg("UPX: malloc failed - giving up rebuild\n");
191
 
      return 0;
192
 
    }
193
 
    memcpy(newbuf, HEADERS, 0xd0);
194
 
    memcpy(newbuf+0xd0, FAKEPE, 0x120);
195
 
    memcpy(newbuf+0x200, dst, dend);
196
 
    memcpy(dst, newbuf, dend+0x200);
197
 
    free(newbuf);
198
 
    cli_writeint32(dst+0xd0+0x50, rebsz+0x1000);
199
 
    cli_writeint32(dst+0xd0+0x100, rebsz);
200
 
    cli_writeint32(dst+0xd0+0x108, rebsz);
201
 
    *dsize=rebsz+0x200;
202
 
    cli_dbgmsg("UPX: PE structure added to uncompressed data\n");
203
 
    return 1;
 
100
      pehdr++;
 
101
    }
 
102
    pehdr++;
 
103
  }
 
104
 
 
105
  pehdr+=4;
 
106
  if (!CLI_ISCONTAINED(dst, *dsize,  pehdr, 0xf8)) {
 
107
    cli_dbgmsg("UPX: sections out of bounds - giving up rebuild\n");
 
108
    return 0;
 
109
  }
 
110
  
 
111
  if ( cli_readint32(pehdr) != 0x4550 ) {
 
112
    cli_dbgmsg("UPX: No magic for PE - giving up rebuild\n");
 
113
    return 0;
 
114
  }
 
115
  
 
116
  if (!(valign=cli_readint32(pehdr+0x38))) {
 
117
    cli_dbgmsg("UPX: Cant align to a NULL bound - giving up rebuild\n");
 
118
    return 0;
 
119
  }
 
120
  
 
121
  sections = pehdr+0xf8;
 
122
  if ( ! (sectcnt = (unsigned char)pehdr[6]+256*(unsigned char)pehdr[7])) {
 
123
    cli_dbgmsg("UPX: No sections? - giving up rebuild\n");
 
124
    return 0;
204
125
  }
205
126
  
206
127
  foffset = PESALIGN(foffset+0x28*sectcnt, valign);
207
128
  
 
129
  if (!CLI_ISCONTAINED(dst, *dsize, sections, 0x28*sectcnt)) {
 
130
    cli_dbgmsg("UPX: Not enough space for all sects - giving up rebuild\n");
 
131
    return 0;
 
132
  }
 
133
  
208
134
  for (upd = 0; upd <sectcnt ; upd++) {
209
 
    uint32_t vsize=PESALIGN((uint32_t)cli_readint32(sections+8), valign);
210
 
    uint32_t urva=PEALIGN((uint32_t)cli_readint32(sections+12), valign);
 
135
    uint32_t vsize=PESALIGN(cli_readint32(sections+8), valign);
 
136
    uint32_t urva=PEALIGN(cli_readint32(sections+12), valign);
211
137
    
212
138
    /* Within bounds ? */
213
139
    if (!CLI_ISCONTAINED(upx0, realstuffsz, urva, vsize)) {
259
185
 
260
186
/* [doubleebx] */
261
187
 
262
 
static int doubleebx(char *src, uint32_t *myebx, uint32_t *scur, uint32_t ssize)
 
188
static int doubleebx(char *src, int32_t *myebx, int *scur, int ssize)
263
189
{
264
 
  uint32_t oldebx = *myebx;
 
190
  int32_t oldebx = *myebx;
265
191
 
266
192
  *myebx*=2;
267
193
  if ( !(oldebx & 0x7fffffff)) {
271
197
    *myebx = oldebx*2+1;
272
198
    *scur+=4;
273
199
  }
274
 
  return (oldebx>>31);
 
200
  return (oldebx>>31)&1;
275
201
}
276
202
 
277
203
/* [inflate] */
278
204
 
279
205
int upx_inflate2b(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep)
280
206
{
281
 
  int32_t backbytes, unp_offset = -1;
282
 
  uint32_t backsize, myebx = 0, scur=0, dcur=0, i, magic[]={0x108,0x110,0xd5,0};
283
 
  int oob;
284
 
  
 
207
  int32_t backbytes, unp_offset = -1, myebx = 0;
 
208
  int scur=0, dcur=0, i, backsize, oob;
 
209
 
285
210
  while (1) {
286
211
    while ((oob = doubleebx(src, &myebx, &scur, ssize)) == 1) {
287
 
      if (scur>=ssize || dcur>=*dsize)
 
212
      if (scur<0 || scur>=ssize || dcur<0 || dcur>=*dsize)
288
213
        return -1;
289
214
      dst[dcur++] = src[scur++];
290
215
    }
304
229
        break;
305
230
    }
306
231
 
 
232
    backsize = 0;
307
233
    backbytes-=3;
308
234
  
309
235
    if ( backbytes >= 0 ) {
310
236
 
311
 
      if (scur>=ssize)
 
237
      if (scur<0 || scur>=ssize)
312
238
        return -1;
313
239
      backbytes<<=8;
314
240
      backbytes+=(unsigned char)(src[scur++]);
319
245
      unp_offset = backbytes;
320
246
    }
321
247
 
322
 
    if ( (backsize = (uint32_t)doubleebx(src, &myebx, &scur, ssize)) == 0xffffffff)
 
248
    if ( (oob = doubleebx(src, &myebx, &scur, ssize)) == -1)
323
249
      return -1;
 
250
    backsize = oob;
324
251
    if ( (oob = doubleebx(src, &myebx, &scur, ssize)) == -1)
325
252
      return -1;
326
253
    backsize = backsize*2 + oob;
341
268
 
342
269
    backsize++;
343
270
 
344
 
    if (!CLI_ISCONTAINED(dst, *dsize, dst+dcur+unp_offset, backsize) || !CLI_ISCONTAINED(dst, *dsize, dst+dcur, backsize) || unp_offset >=0)
345
 
      return -1;
346
 
    for (i = 0; i < backsize; i++)
 
271
    for (i = 0; i < backsize; i++) {
 
272
      if (dcur+i<0 || dcur+i>=*dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=*dsize)
 
273
        return -1;
347
274
      dst[dcur + i] = dst[dcur + unp_offset + i];
 
275
    }
348
276
    dcur+=backsize;
349
277
  }
350
278
 
351
 
  return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur);
 
279
 
 
280
  if ( ep - upx1 + 0x108 <= ssize-5  &&    /* Wondering how we got so far?! */
 
281
       src[ep - upx1 + 0x106] == '\x8d' && /* lea edi, ...                  */
 
282
       src[ep - upx1 + 0x107] == '\xbe' )  /* ... [esi + offset]          */
 
283
    return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x108);
 
284
 
 
285
  cli_dbgmsg("UPX: bad magic for 2b\n");
 
286
  return 0;
352
287
}
353
288
 
354
289
int upx_inflate2d(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep)
355
290
{
356
 
  int32_t backbytes, unp_offset = -1;
357
 
  uint32_t backsize, myebx = 0, scur=0, dcur=0, i, magic[]={0x11c,0x124,0};
358
 
  int oob;
 
291
  int32_t backbytes, unp_offset = -1, myebx = 0;
 
292
  int scur=0, dcur=0, i, backsize, oob;
359
293
 
360
294
  while (1) {
361
295
    while ( (oob = doubleebx(src, &myebx, &scur, ssize)) == 1) {
362
 
      if (scur>=ssize || dcur>=*dsize)
 
296
      if (scur<0 || scur>=ssize || dcur<0 || dcur>=*dsize)
363
297
        return -1;
364
298
      dst[dcur++] = src[scur++];
365
299
    }
388
322
  
389
323
    if ( backbytes >= 0 ) {
390
324
 
391
 
      if (scur>=ssize)
 
325
      if (scur<0 || scur>=ssize)
392
326
        return -1;
393
327
      backbytes<<=8;
394
328
      backbytes+=(unsigned char)(src[scur++]);
397
331
      if (!backbytes)
398
332
        break;
399
333
      backsize = backbytes & 1;
400
 
      CLI_SAR(backbytes,1);
 
334
      backbytes>>=1;
401
335
      unp_offset = backbytes;
402
 
    } else {
403
 
      if ( (backsize = (uint32_t)doubleebx(src, &myebx, &scur, ssize)) == 0xffffffff )
 
336
    }
 
337
    else {
 
338
      if ( (backsize = doubleebx(src, &myebx, &scur, ssize)) == -1 )
404
339
        return -1;
405
340
    }
406
341
 
423
358
      backsize++;
424
359
 
425
360
    backsize++;
426
 
    if (!CLI_ISCONTAINED(dst, *dsize, dst+dcur+unp_offset, backsize) || !CLI_ISCONTAINED(dst, *dsize, dst+dcur, backsize) || unp_offset >=0 )
427
 
      return -1;
428
 
    for (i = 0; i < backsize; i++)
 
361
    for (i = 0; i < backsize; i++) {
 
362
      if (dcur+i<0 || dcur+i>=*dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=*dsize)
 
363
        return -1;
429
364
      dst[dcur + i] = dst[dcur + unp_offset + i];
 
365
    }
430
366
    dcur+=backsize;
431
367
  }
432
368
 
433
 
  return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur);
 
369
  if ( ep - upx1 + 0x124 <= ssize-5 ) {   /* Wondering how we got so far?! */
 
370
    if ( src[ep - upx1 + 0x11a] == '\x8d' && src[ep - upx1 + 0x11b] == '\xbe' )
 
371
      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x11c);
 
372
    if ( src[ep - upx1 + 0x122] == '\x8d' && src[ep - upx1 + 0x123] == '\xbe' )
 
373
      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x124);
 
374
  }
 
375
  cli_dbgmsg("UPX: bad magic for 2d\n");
 
376
  return 0;
434
377
}
435
378
 
436
379
int upx_inflate2e(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep)
437
380
{
438
 
  int32_t backbytes, unp_offset = -1;
439
 
  uint32_t backsize, myebx = 0, scur=0, dcur=0, i, magic[]={0x128,0x130,0};
440
 
  int oob;
 
381
  int32_t backbytes, unp_offset = -1, myebx = 0;
 
382
  int scur=0, dcur=0, i, backsize, oob;
441
383
 
442
384
  for(;;) {
443
385
    while ( (oob = doubleebx(src, &myebx, &scur, ssize)) ) {
444
386
      if (oob == -1)
445
387
        return -1;
446
 
      if (scur>=ssize || dcur>=*dsize)
 
388
      if (scur<0 || scur>=ssize || dcur<0 || dcur>=*dsize)
447
389
        return -1;
448
390
      dst[dcur++] = src[scur++];
449
391
    }
464
406
      backbytes=backbytes*2+oob;
465
407
    }
466
408
 
 
409
    backsize = 0;
467
410
    backbytes-=3;
468
411
  
469
412
    if ( backbytes >= 0 ) {
470
413
 
471
 
      if (scur>=ssize)
 
414
      if (scur<0 || scur>=ssize)
472
415
        return -1;
473
416
      backbytes<<=8;
474
417
      backbytes+=(unsigned char)(src[scur++]);
477
420
      if (!backbytes)
478
421
        break;
479
422
      backsize = backbytes & 1; /* Using backsize to carry on the shifted out bit (UPX uses CF) */
480
 
      CLI_SAR(backbytes,1);
 
423
      backbytes>>=1;
481
424
      unp_offset = backbytes;
482
 
    } else {
483
 
      if ( (backsize = (uint32_t)doubleebx(src, &myebx, &scur, ssize)) == 0xffffffff )
 
425
    }
 
426
    else {
 
427
      if ( (backsize = doubleebx(src, &myebx, &scur, ssize)) == -1 )
484
428
        return -1;
485
429
    } /* Using backsize to carry on the doubleebx result (UPX uses CF) */
486
430
 
487
431
    if (backsize) { /* i.e. IF ( last sar shifted out 1 bit || last doubleebx()==1 ) */
488
 
      if ( (backsize = (uint32_t)doubleebx(src, &myebx, &scur, ssize)) == 0xffffffff )
 
432
      if ( (backsize = doubleebx(src, &myebx, &scur, ssize)) == -1 )
489
433
        return -1;
490
 
    } else {
 
434
    }
 
435
    else {
491
436
      backsize = 1;
492
437
      if ((oob = doubleebx(src, &myebx, &scur, ssize)) == -1)
493
438
        return -1;
495
440
        if ((oob = doubleebx(src, &myebx, &scur, ssize)) == -1)
496
441
          return -1;
497
442
          backsize = 2 + oob;
498
 
        } else {
499
 
          do {
500
 
            if ((oob = doubleebx(src, &myebx, &scur, ssize)) == -1)
501
 
              return -1;
502
 
            backsize = backsize * 2 + oob;
503
 
          } while ((oob = doubleebx(src, &myebx, &scur, ssize)) == 0);
504
 
          if (oob == -1)
505
 
            return -1;
506
 
          backsize+=2;
507
443
        }
 
444
      else {
 
445
        do {
 
446
          if ((oob = doubleebx(src, &myebx, &scur, ssize)) == -1)
 
447
          return -1;
 
448
          backsize = backsize * 2 + oob;
 
449
        } while ((oob = doubleebx(src, &myebx, &scur, ssize)) == 0);
 
450
        if (oob == -1)
 
451
          return -1;
 
452
        backsize+=2;
 
453
      }
508
454
    }
509
455
 
510
456
    if ( (uint32_t)unp_offset < 0xfffffb00 ) 
511
457
      backsize++;
512
458
 
513
459
    backsize+=2;
514
 
 
515
 
    if (!CLI_ISCONTAINED(dst, *dsize, dst+dcur+unp_offset, backsize) || !CLI_ISCONTAINED(dst, *dsize, dst+dcur, backsize) || unp_offset >=0 )
516
 
      return -1;
517
 
    for (i = 0; i < backsize; i++)
 
460
    for (i = 0; i < backsize; i++) {
 
461
      if (dcur+i<0 || dcur+i>=*dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=*dsize)
 
462
        return -1;
518
463
      dst[dcur + i] = dst[dcur + unp_offset + i];
 
464
    }
519
465
    dcur+=backsize;
520
466
  }
521
467
 
522
 
  return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur);
523
 
}
524
 
 
525
 
int upx_inflatelzma(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) {
526
 
  struct CLI_LZMA l;
527
 
  uint32_t magic[]={0xb16,0xb1e,0};
528
 
  unsigned char fake_lzmahdr[5];
529
 
 
530
 
  memset(&l, 0, sizeof(l));
531
 
  cli_writeint32(fake_lzmahdr + 1, *dsize);
532
 
  *fake_lzmahdr = 3 /* lc */ + 9* ( 5* 2 /* pb */ + 0 /* lp */);
533
 
  l.next_in = fake_lzmahdr;
534
 
  l.avail_in = 5;
535
 
  if(cli_LzmaInit(&l, *dsize) != LZMA_RESULT_OK)
536
 
      return 0;
537
 
  l.avail_in = ssize;
538
 
  l.avail_out = *dsize;
539
 
  l.next_in = (unsigned char*)src+2;
540
 
  l.next_out = (unsigned char*)dst;
541
 
 
542
 
  if(cli_LzmaDecode(&l)==LZMA_RESULT_DATA_ERROR) {
543
 
/*     __asm__ __volatile__("int3"); */
544
 
    cli_LzmaShutdown(&l);
545
 
    return -1;
 
468
  if ( ep - upx1 + 0x130 <= ssize-5 ) {   /* Wondering how we got so far?! */
 
469
    if ( src[ep - upx1 + 0x126] == '\x8d' && src[ep - upx1 + 0x127] == '\xbe' )
 
470
      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x128);
 
471
    if ( src[ep - upx1 + 0x12e] == '\x8d' && src[ep - upx1 + 0x12f] == '\xbe' )
 
472
      return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x130);
546
473
  }
547
 
  cli_LzmaShutdown(&l);
548
 
 
549
 
  return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, *dsize);
 
474
  cli_dbgmsg("UPX: bad magic for 2e\n");
 
475
  return 0;
550
476
}