Coverage Report

Created: 2023-12-08 06:48

/src/clamav/libclamav/mew.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Copyright (C) 2013-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3
 *  Copyright (C) 2007-2013 Sourcefire, Inc.
4
 *
5
 *  Authors: Michal 'GiM' Spadlinski
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License version 2 as
9
 *  published by the Free Software Foundation.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 *  MA 02110-1301, USA.
20
 */
21
22
/*
23
 * lzma.c
24
 *
25
 * o2:28:18 CEST 2oo6-25-o6     - initial 0xA4/0x536
26
 * oo:29:4o CEST 2oo6-26-o6     - 0x1cd/0x536 [+0x129]
27
 * o2:13:19 CEST 2oo6-o1-o7, 2oo6-3o-o6 - 0x536/0x536
28
 *
29
 */
30
31
#if HAVE_CONFIG_H
32
#include "clamav-config.h"
33
#endif
34
35
#include <stdio.h>
36
#ifdef HAVE_STDLIB_H
37
#include <stdlib.h>
38
#endif
39
#ifdef HAVE_SYS_TYPES_H
40
#include <sys/types.h>
41
#endif
42
#ifdef HAVE_SYS_STAT_H
43
#include <sys/stat.h>
44
#endif
45
#ifdef HAVE_UNISTD_H
46
#include <unistd.h>
47
#endif
48
#ifdef HAVE_STRING_H
49
#include <string.h>
50
#endif
51
52
#include "clamav.h"
53
#include "pe.h"
54
#include "others.h"
55
#include "mew.h"
56
#include "packlibs.h"
57
#include "rebuildpe.h"
58
59
373
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
60
#define CE32(x) be32_to_host(x) /* Convert big endian to host */
61
#define PEALIGN(o, a) (((a)) ? (((o) / (a)) * (a)) : (o))
62
133
#define PESALIGN(o, a) (((a)) ? (((o) / (a) + ((o) % (a) != 0)) * (a)) : (o))
63
64
/* modifies all parameters */
65
/* northfox does this shitty way,
66
 * this should be done with just a bswap
67
 */
68
static const char *lzma_bswap_4861dc(struct lzmastate *p, const char *old_edx)
69
373
{
70
    /* dumb_dump_start
71
         *
72
73
        old_edx was 'uint32_t *' before and in mew_lzma there was
74
        &new_edx where new_edx = var1C
75
76
        uint32_t loc_esi, loc_edi;
77
        uint8_t *loc_eax;
78
79
        p->p2 = loc_esi = 0;
80
        p->p0 = loc_eax = (uint8_t *)*old_edx;
81
        *old_edx = 5;
82
        do {
83
                loc_esi = p->p2 << 8;
84
                loc_edi = *(uint8_t *)((loc_eax)++);
85
                loc_esi |= loc_edi;
86
                (*old_edx)--;
87
                p->p2 = loc_esi;
88
        } while (*old_edx);
89
        p->p0 = loc_eax;
90
        p->p1 = 0xffffffff;
91
92
        * dumb_dump_end
93
        */
94
95
    /* XXX, mine replacement */
96
373
    p->p2 = EC32(CE32(((uint32_t)cli_readint32(old_edx + 1))));
97
373
    p->p1 = 0xffffffff;
98
373
    p->p0 = old_edx + 5;
99
100
373
    return p->p0;
101
373
}
102
103
static uint32_t lzma_486248(struct lzmastate *p, const char **old_ecx, char *src, uint32_t size)
104
1.07M
{
105
1.07M
    uint32_t loc_esi, loc_edi, loc_eax, loc_ecx, ret;
106
1.07M
    if (!CLI_ISCONTAINED(src, size, *old_ecx, 4) || !CLI_ISCONTAINED(src, size, p->p0, 1))
107
12
        return 0xffffffff;
108
1.07M
    loc_esi = p->p1;
109
1.07M
    loc_eax = loc_esi >> 0xb;
110
1.07M
    loc_ecx = cli_readint32(*old_ecx);
111
1.07M
    ret     = loc_ecx & 0xffff;
112
1.07M
    (loc_eax) *= ret;
113
1.07M
    loc_edi = p->p2;
114
1.07M
    if (loc_edi < loc_eax) {
115
        /* 48625f */
116
693k
        p->p1   = loc_eax;
117
693k
        loc_esi = ret;
118
693k
        loc_edi = ((int32_t)(0x800 - ret) >> 5) + ((loc_eax & 0xffff0000) | ret);
119
        /* signed<-sar, &|<-mov ax, [ecx] */
120
693k
        loc_ecx = (loc_ecx & 0xffff0000) | (loc_edi & 0xffff);
121
693k
        cli_writeint32(*old_ecx, loc_ecx);
122
123
693k
        ret = 0;
124
693k
    } else {
125
        /* 48629e */
126
379k
        loc_esi -= loc_eax;
127
379k
        loc_edi -= loc_eax;
128
379k
        p->p1   = loc_esi;
129
379k
        p->p2   = loc_edi;
130
379k
        loc_eax = (loc_eax & 0xffff0000) | ret;
131
379k
        loc_esi = (loc_esi & 0xffff0000) | (ret >> 5);
132
379k
        loc_eax -= loc_esi;
133
134
379k
        loc_ecx = (loc_ecx & 0xffff0000) | (loc_eax & 0xffff);
135
379k
        cli_writeint32(*old_ecx, loc_ecx);
136
137
379k
        ret = 1;
138
379k
    }
139
1.07M
    loc_eax = p->p1;
140
1.07M
    if (loc_eax < 0x1000000) {
141
20.3k
        *old_ecx = p->p0;
142
20.3k
        loc_edi  = (*(uint8_t *)(p->p0));
143
20.3k
        loc_esi  = ((p->p2) << 8) | loc_edi;
144
20.3k
        (*old_ecx)++;
145
20.3k
        loc_eax <<= 8;
146
20.3k
        p->p2 = loc_esi;
147
20.3k
        p->p1 = loc_eax;
148
20.3k
        p->p0 = *old_ecx;
149
20.3k
    }
150
1.07M
    return ret;
151
1.07M
}
152
153
static uint32_t lzma_48635C(uint8_t znaczek, const char **old_ecx, struct lzmastate *p, uint32_t *retval, char *src, uint32_t size)
154
3.02k
{
155
3.02k
    uint32_t loc_esi = (znaczek & 0xff) >> 7, /* msb */
156
3.02k
        loc_ebx, ret;
157
3.02k
    const char *loc_edi;
158
3.02k
    znaczek <<= 1;
159
3.02k
    ret      = loc_esi << 9;
160
3.02k
    loc_edi  = *old_ecx;
161
3.02k
    *old_ecx = loc_edi + ret + 0x202;
162
3.02k
    if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
163
0
        return 0xffffffff;
164
3.02k
    loc_ebx = ret | 2;
165
166
12.1k
    while (loc_esi == ret) {
167
9.67k
        if (loc_ebx >= 0x100) {
168
554
            ret     = (ret & 0xffffff00) | (loc_ebx & 0xff);
169
554
            *retval = ret;
170
554
            return 0;
171
554
        }
172
9.11k
        loc_esi = (znaczek & 0xff) >> 7;
173
9.11k
        znaczek <<= 1;
174
9.11k
        ret      = ((loc_esi + 1) << 8) + loc_ebx;
175
9.11k
        *old_ecx = loc_edi + ret * 2;
176
9.11k
        if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
177
0
            return 0xffffffff;
178
9.11k
        loc_ebx += loc_ebx;
179
9.11k
        loc_ebx |= ret;
180
9.11k
    }
181
2.46k
    loc_esi = 0x100;
182
14.5k
    while (loc_ebx < loc_esi) {
183
12.0k
        loc_ebx += loc_ebx;
184
12.0k
        *old_ecx = loc_edi + loc_ebx;
185
12.0k
        if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
186
0
            return 0xffffffff;
187
12.0k
        loc_ebx |= ret;
188
12.0k
    }
189
2.46k
    ret     = (ret & 0xffffff00) | (loc_ebx & 0xff);
190
2.46k
    *retval = ret;
191
2.46k
    return 0;
192
2.46k
}
193
194
static uint32_t lzma_4862e0(struct lzmastate *p, const char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
195
106k
{
196
106k
    uint32_t loc_ebx, loc_esi, stack_ecx, ret;
197
106k
    const char *loc_edi;
198
199
106k
    loc_ebx = *old_edx;
200
106k
    ret     = 1;
201
106k
    loc_edi = *old_ecx;
202
106k
    if (loc_ebx && !(loc_ebx & 0x80000000)) {
203
        /* loc_4862f1 */
204
106k
        stack_ecx = loc_ebx;
205
328k
        do {
206
328k
            loc_esi  = ret + ret;
207
328k
            *old_ecx = loc_edi + loc_esi;
208
328k
            if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
209
0
                return 0xffffffff;
210
328k
            ret += loc_esi;
211
328k
            stack_ecx--;
212
328k
        } while (stack_ecx);
213
106k
    }
214
    /* loc_48630b */
215
    /* unneeded
216
     *old_ecx = (uint8_t *)loc_ebx;
217
     */
218
219
106k
    *old_edx = 1 << (loc_ebx & 0xff);
220
106k
    ret -= *old_edx;
221
106k
    *retval = ret;
222
106k
    return 0;
223
106k
}
224
225
/* old_edx - write only */
226
static uint32_t lzma_4863da(uint32_t var0, struct lzmastate *p, const char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
227
104k
{
228
104k
    uint32_t ret;
229
104k
    const char *loc_esi = *old_ecx;
230
231
104k
    if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
232
3
        return -1;
233
104k
    if (ret) {
234
        /* loc_4863ff */
235
1.84k
        *old_ecx = loc_esi + 2;
236
1.84k
        if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
237
0
            return -1;
238
1.84k
        if (ret) {
239
            /* loc_486429 */
240
1.02k
            *old_edx = 8;
241
1.02k
            *old_ecx = loc_esi + 0x204;
242
1.02k
            if (lzma_4862e0(p, old_ecx, old_edx, &ret, src, size) == 0xffffffff)
243
0
                return -1;
244
1.02k
            ret += 0x10;
245
1.02k
        } else {
246
            /* loc_48640e */
247
823
            ret      = var0 << 4;
248
823
            *old_edx = 3;
249
823
            *old_ecx = loc_esi + 0x104 + ret;
250
823
            if (lzma_4862e0(p, old_ecx, old_edx, &ret, src, size) == 0xffffffff)
251
0
                return -1;
252
823
            ret += 0x8;
253
823
        }
254
102k
    } else {
255
        /* loc_4863e9 */
256
102k
        ret      = var0 << 4;
257
102k
        *old_edx = 3;
258
102k
        *old_ecx = loc_esi + 0x4 + ret;
259
102k
        if (lzma_4862e0(p, old_ecx, old_edx, &ret, src, size) == 0xffffffff)
260
0
            return -1;
261
102k
    }
262
104k
    *retval = ret;
263
104k
    return 0;
264
104k
}
265
266
static uint32_t lzma_486204(struct lzmastate *p, uint32_t old_edx, uint32_t *retval, char *src, uint32_t size)
267
350
{
268
350
    uint32_t loc_esi, loc_edi, loc_ebx, loc_eax;
269
350
    const char *loc_edx;
270
350
    loc_esi = p->p1;
271
350
    loc_edi = p->p2;
272
350
    loc_eax = 0;
273
350
    if (old_edx && !(old_edx & 0x80000000)) {
274
        /* loc_4866212 */
275
350
        loc_ebx = old_edx;
276
4.00k
        do {
277
4.00k
            loc_esi >>= 1;
278
4.00k
            loc_eax <<= 1;
279
4.00k
            if (loc_edi >= loc_esi) {
280
1.89k
                loc_edi -= loc_esi;
281
1.89k
                loc_eax |= 1;
282
1.89k
            }
283
            /* loc_486222 */
284
4.00k
            if (loc_esi < 0x1000000) {
285
474
                if (!CLI_ISCONTAINED(src, size, p->p0, 1))
286
0
                    return 0xffffffff;
287
474
                loc_edx = p->p0;
288
474
                loc_edi <<= 8;
289
474
                loc_esi <<= 8;
290
474
                loc_edi |= (*loc_edx) & 0xff; /* movzx ebp, byte ptr [edx] */
291
474
                p->p0 = ++loc_edx;
292
474
            }
293
4.00k
            loc_ebx--;
294
4.00k
        } while (loc_ebx);
295
350
    }
296
350
    p->p2   = loc_edi;
297
350
    p->p1   = loc_esi;
298
350
    *retval = loc_eax;
299
350
    return 0;
300
350
}
301
302
static uint32_t lzma_48631a(struct lzmastate *p, const char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
303
415
{
304
415
    uint32_t copy1, copy2;
305
415
    uint32_t loc_esi, loc_edi, ret;
306
415
    const char *loc_ebx;
307
308
415
    copy1    = *old_edx;
309
415
    loc_edi  = 0;
310
415
    loc_ebx  = *old_ecx;
311
415
    *old_edx = 1;
312
415
    copy2    = (uint32_t)loc_edi;
313
314
415
    if (copy1 <= (uint32_t)loc_edi) {
315
0
        *retval = copy2;
316
0
        return 0;
317
0
    }
318
319
1.54k
    do {
320
1.54k
        loc_esi  = *old_edx + *old_edx;
321
1.54k
        *old_ecx = loc_esi + loc_ebx;
322
1.54k
        if ((ret = lzma_486248(p, old_ecx, src, size)) == 0xffffffff)
323
0
            return 0xffffffff;
324
        /* unneeded *old_ecx  = loc_edi; */
325
1.54k
        *old_edx = loc_esi + ret;
326
        /* ret <<= (uint32_t)(*old_ecx)&0xff; */
327
1.54k
        ret <<= (loc_edi & 0xff);
328
1.54k
        copy2 |= ret;
329
1.54k
        loc_edi++;
330
1.54k
    } while (loc_edi < copy1);
331
332
415
    *retval = copy2;
333
415
    return 0;
334
415
}
335
336
int mew_lzma(char *orgsource, const char *buf, uint32_t size_sum, uint32_t vma, uint32_t special)
337
396
{
338
396
    uint32_t var08, var0C, var10, var14, var20, var24, var28, var34;
339
396
    struct lzmastate var40;
340
396
    uint32_t new_eax, new_edx, temp;
341
396
    int i, mainloop;
342
343
396
    char var1;
344
396
    const char *source = buf;
345
396
    char *dest, *new_ebx;
346
396
    const char *new_ecx, *var0C_ecxcopy;
347
396
    const char *var2C;
348
396
    char *pushed_esi       = NULL;
349
396
    const char *pushed_ebx = NULL;
350
396
    uint32_t pushed_edx    = 0;
351
352
396
    uint32_t loc_esi, loc_edi;
353
396
    uint8_t *var18;
354
355
396
    if (special) {
356
0
        pushed_edx = cli_readint32(source);
357
0
        source += 4;
358
0
    }
359
396
    temp = cli_readint32(source) - vma;
360
396
    source += 4;
361
396
    if (!special) pushed_ebx = source;
362
396
    new_ebx = orgsource + temp;
363
364
408
    do {
365
408
        mainloop = 1;
366
408
        do {
367
            /* loc_486450 */
368
408
            if (!special) {
369
408
                source = pushed_ebx;
370
408
                if (!CLI_ISCONTAINED(orgsource, size_sum, source, 16))
371
6
                    return -1;
372
373
402
                if (cli_readint32(source) == 0) {
374
19
                    return 0;
375
19
                }
376
402
            } else {
377
0
                if (!CLI_ISCONTAINED(orgsource, size_sum, source, 12))
378
0
                    return -1;
379
0
            }
380
381
383
            var28 = cli_readint32(source);
382
383
            source += 4;
383
383
            temp  = cli_readint32(source) - vma;
384
383
            var18 = (uint8_t *)(orgsource + temp);
385
383
            if (special) pushed_esi = orgsource + temp;
386
383
            source += 4;
387
383
            temp = cli_readint32(source);
388
383
            source += 5; /* yes, five */
389
383
            var2C = source;
390
383
            source += temp;
391
383
            if (special)
392
0
                pushed_ebx = source;
393
383
            else
394
383
                pushed_ebx = source;
395
383
            var1 = 0;
396
383
            dest = new_ebx;
397
398
383
            if (!CLI_ISCONTAINED(orgsource, size_sum, dest, 0x6E6C))
399
10
                return -1;
400
2.63M
            for (i = 0; i < 0x1b9b; i++) {
401
2.63M
                cli_writeint32(dest, 0x4000400);
402
2.63M
                dest += 4;
403
2.63M
            }
404
373
            loc_esi = 0;
405
373
            var08 = var20 = 0;
406
373
            loc_edi       = 1;
407
373
            var14 = var10 = var24 = 1;
408
409
373
            if (!CLI_ISCONTAINED(orgsource, size_sum, var2C, 5))
410
0
                return -1;
411
373
            lzma_bswap_4861dc(&var40, var2C);
412
373
            new_edx = 0;
413
373
        } while (var28 <= loc_esi); /* source = 0 */
414
415
373
        cli_dbgmsg("MEWlzma: entering do while loop\n");
416
127k
        do {
417
            /* loc_4864a5 */
418
127k
            new_eax = var08 & 3;
419
127k
            new_ecx = (((loc_esi << 4) + new_eax) * 2) + new_ebx;
420
127k
            var0C   = new_eax;
421
127k
            if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
422
1
                return -1;
423
127k
            if (new_eax) {
424
                /* loc_486549 */
425
105k
                new_ecx = new_ebx + loc_esi * 2 + 0x180;
426
105k
                var20   = 1;
427
                /* eax=1 */
428
105k
                if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
429
0
                    return -1;
430
105k
                if (new_eax != 1) {
431
                    /* loc_486627 */
432
1.61k
                    var24 = var10;
433
1.61k
                    var10 = var14;
434
                    /* xor eax,eax; cmp esi, 7; setnl al; dec eax; add eax, 0Ah */
435
                    /* new_eax = (((loc_esi >= 7)-1)&0xFFFFFFFD) + 0xA; */
436
1.61k
                    new_eax = loc_esi >= 7 ? 10 : 7;
437
1.61k
                    new_ecx = new_ebx + 0x664;
438
1.61k
                    var14   = loc_edi;
439
1.61k
                    loc_esi = new_eax;
440
1.61k
                    if (lzma_4863da(var0C, &var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == 0xffffffff)
441
1
                        return -1;
442
1.60k
                    var0C = new_eax;
443
1.60k
                    if (var0C >= 4)
444
580
                        new_eax = 3;
445
446
                    /* loc_486662 */
447
1.60k
                    new_edx = 6;
448
1.60k
                    new_eax <<= 7;
449
1.60k
                    new_ecx = new_eax + new_ebx + 0x360;
450
1.60k
                    if (lzma_4862e0(&var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == 0xffffffff)
451
0
                        return -1;
452
1.60k
                    if (new_eax < 4) {
453
                        /* loc_4866ca */
454
1.19k
                        loc_edi = new_eax;
455
1.19k
                    } else {
456
                        /* loc_48667d */
457
415
                        uint32_t loc_ecx;
458
415
                        loc_ecx = ((int32_t)new_eax >> 1) - 1; /* sar */
459
415
                        loc_edi = ((new_eax & 1) | 2) << (loc_ecx & 0xff);
460
415
                        if (new_eax >= 0xe) {
461
                            /* loc_4866ab */
462
350
                            new_edx = loc_ecx - 4;
463
350
                            if (lzma_486204(&var40, new_edx, &new_eax, orgsource, size_sum) == 0xffffffff)
464
0
                                return -1;
465
350
                            loc_edi += new_eax << 4;
466
467
350
                            new_edx = 4;
468
350
                            new_ecx = new_ebx + 0x644;
469
350
                        } else {
470
                            /* loc_486691 */
471
65
                            new_edx = loc_ecx;
472
65
                            loc_ecx = loc_edi - new_eax;
473
65
                            new_ecx = new_ebx + loc_ecx * 2 + 0x55e;
474
65
                        }
475
                        /* loc_4866a2 */
476
415
                        if (lzma_48631a(&var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == 0xffffffff)
477
0
                            return -1;
478
415
                        loc_edi += new_eax;
479
415
                    }
480
1.60k
                    loc_edi++;
481
103k
                } else {
482
                    /* loc_486568 */
483
103k
                    new_ecx = new_ebx + loc_esi * 2 + 0x198;
484
103k
                    if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
485
0
                        return -1;
486
103k
                    if (new_eax) {
487
                        /* loc_4865bd */
488
102k
                        new_ecx = new_ebx + loc_esi * 2 + 0x1B0;
489
102k
                        if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
490
1
                            return -1;
491
102k
                        if (new_eax) {
492
                            /* loc_4865d2 */
493
14.3k
                            new_ecx = new_ebx + loc_esi * 2 + 0x1C8;
494
14.3k
                            if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
495
1
                                return -1;
496
14.3k
                            if (new_eax) {
497
                                /* loc_4865ea */
498
3.80k
                                new_eax = var24;
499
3.80k
                                var24   = var10;
500
10.5k
                            } else {
501
                                /* loc_4865e5 */
502
10.5k
                                new_eax = var10;
503
10.5k
                            }
504
                            /* loc_4865f3 */
505
14.3k
                            var10 = var14;
506
88.2k
                        } else {
507
                            /* loc_4865cd */
508
88.2k
                            new_eax = var14;
509
88.2k
                        }
510
                        /* loc_4865f9 */
511
102k
                        var14   = loc_edi;
512
102k
                        loc_edi = new_eax;
513
102k
                    } else {
514
                        /* loc_48657e */
515
925
                        new_eax = ((loc_esi + 0xf) << 4) + var0C;
516
925
                        new_ecx = new_ebx + new_eax * 2;
517
925
                        if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
518
1
                            return -1;
519
924
                        if (!new_eax) {
520
510
                            uint32_t loc_ecx;
521
                            /* loc_486593 */
522
510
                            loc_ecx = var08;
523
510
                            loc_ecx -= loc_edi;
524
                            /* loc_esi = ((((loc_esi >= 7)-1)&0xFFFFFFFE) + 0xB); */
525
510
                            loc_esi = loc_esi >= 7 ? 11 : 9;
526
510
                            if (!CLI_ISCONTAINED((uint8_t *)orgsource, size_sum, var18 + loc_ecx, 1))
527
0
                                return -1;
528
510
                            var1    = *(var18 + loc_ecx);
529
510
                            loc_ecx = (loc_ecx & 0xffffff00) | var1;
530
                            /* loc_4865af */
531
510
                            new_edx = var08++;
532
510
                            if (!CLI_ISCONTAINED((uint8_t *)orgsource, size_sum, var18 + new_edx, 1))
533
0
                                return -1;
534
510
                            *(var18 + new_edx) = loc_ecx & 0xff;
535
536
                            /* loc_4866fe */
537
510
                            new_eax = var08;
538
510
                            continue; /* !!! */
539
510
                        }
540
924
                    }
541
                    /* loc_4865fe */
542
102k
                    new_ecx = new_ebx + 0xa68;
543
102k
                    if (lzma_4863da(var0C, &var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == 0xffffffff)
544
2
                        return -1;
545
102k
                    var0C = new_eax;
546
                    /* new_eax = (((loc_esi >= 7)-1)&0xFFFFFFFD) + 0xB; */
547
102k
                    new_eax = loc_esi >= 7 ? 11 : 8;
548
102k
                    loc_esi = new_eax;
549
102k
                }
550
                /* loc_4866cd */
551
104k
                if (!loc_edi) {
552
0
                    break;
553
104k
                } else {
554
104k
                    var0C += 2;
555
104k
                    new_ecx = (char *)var18;
556
104k
                    new_edx = new_eax = var08;
557
104k
                    new_eax -= loc_edi;
558
104k
                    if (((var0C < var28 - new_edx) &&
559
104k
                         (!CLI_ISCONTAINED(orgsource, size_sum, (char *)(new_ecx + new_eax), var0C) ||
560
104k
                          !CLI_ISCONTAINED(orgsource, size_sum, (char *)(new_ecx + new_edx), var0C))) ||
561
104k
                        (!CLI_ISCONTAINED(orgsource, size_sum, (char *)(new_ecx + new_eax), var28 - new_edx) ||
562
104k
                         !CLI_ISCONTAINED(orgsource, size_sum, (char *)(new_ecx + new_edx), var28 - new_edx)))
563
344
                        return -1;
564
323k
                    do {
565
323k
                        var1                            = *(uint8_t *)(new_ecx + new_eax);
566
323k
                        *(uint8_t *)(new_ecx + new_edx) = var1;
567
568
323k
                        new_edx++;
569
323k
                        new_eax++;
570
323k
                        var0C--;
571
323k
                        if (var0C <= 0)
572
104k
                            break;
573
323k
                    } while (new_edx < var28);
574
0
                    var08 = new_edx;
575
104k
                }
576
104k
            } else {
577
                /* loc_4864C8 */
578
22.7k
                new_eax       = (((var1 & 0xff) >> 4) * 3) << 9;
579
22.7k
                new_ecx       = new_eax + new_ebx + 0xe6c;
580
22.7k
                var0C_ecxcopy = new_ecx;
581
22.7k
                if (loc_esi >= 4) {
582
                    /* loc_4864e8 */
583
5.22k
                    if (loc_esi >= 10)
584
587
                        loc_esi -= 6;
585
4.63k
                    else
586
4.63k
                        loc_esi -= 3;
587
588
17.5k
                } else {
589
                    /* loc_4864e4 */
590
17.5k
                    loc_esi = 0;
591
17.5k
                }
592
593
22.7k
                if (var20 == 0) {
594
                    /* loc_48651D */
595
19.7k
                    new_eax = 1;
596
158k
                    do {
597
                        /* loc_486525 */
598
                        /*new_ecx = var0C_ecxcopy;*/
599
158k
                        new_eax += new_eax;
600
158k
                        new_ecx += new_eax;
601
158k
                        var34 = new_eax;
602
158k
                        if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == 0xffffffff)
603
5
                            return -1;
604
158k
                        new_eax |= var34;
605
                        /* loc_486522 */
606
                        /* keeping it here instead of at the top
607
                         * seems to work faster
608
                         */
609
158k
                        if (new_eax < 0x100) {
610
138k
                            new_ecx = var0C_ecxcopy;
611
138k
                        }
612
158k
                    } while (new_eax < 0x100);
613
                    /* loc_48653e */
614
19.7k
                    var1 = (uint8_t)(new_eax & 0xff);
615
19.7k
                } else {
616
3.02k
                    int t;
617
                    /* loc_4864FB */
618
3.02k
                    new_eax = var08 - loc_edi;
619
3.02k
                    if (!CLI_ISCONTAINED((uint8_t *)orgsource, size_sum, var18 + new_eax, 1))
620
0
                        return -1;
621
3.02k
                    t       = *(var18 + new_eax);
622
3.02k
                    new_eax = (new_eax & 0xffffff00) | t;
623
624
3.02k
                    if (lzma_48635C(t, &new_ecx, &var40, &new_eax, orgsource, size_sum) == 0xffffffff)
625
0
                        return -1;
626
3.02k
                    var20 = 0;
627
3.02k
                    var1  = new_eax & 0xff;
628
3.02k
                }
629
630
                /* loc_486541 */
631
632
                /* unneeded: new_ecx = (new_ecx&0xffffff00) | var1; */
633
634
                /* loc_4865af */
635
22.7k
                new_edx = var08++;
636
637
22.7k
                if (!CLI_ISCONTAINED((uint8_t *)orgsource, size_sum, var18 + new_edx, 1))
638
5
                    return -1;
639
22.7k
                *(var18 + new_edx) = var1;
640
22.7k
            }
641
            /* loc_4866fe */
642
127k
            new_eax = var08;
643
127k
        } while (new_eax < var28);
644
645
12
        while (special) {
646
0
            uint32_t loc_ecx;
647
            /* let's fix calls */
648
0
            cli_dbgmsg("MEWlen: %08x ? %08x\n", new_edx, pushed_edx);
649
650
0
            if (pushed_edx < 5 || !CLI_ISCONTAINED(orgsource, size_sum, pushed_esi, pushed_edx))
651
0
                return 0; /* No point in full failing just because we can't fixxup the calls */
652
653
0
            for (loc_ecx = 0; loc_ecx < pushed_edx - 5; loc_ecx++) {
654
                /* 0xe8, 0xe9 call opcodes */
655
0
                if (pushed_esi[loc_ecx] == '\xe8' || pushed_esi[loc_ecx] == '\xe9') {
656
0
                    char *adr = (char *)(pushed_esi + loc_ecx + 1);
657
658
0
                    cli_writeint32(adr, EC32(CE32((uint32_t)cli_readint32(adr))) - loc_ecx - 1);
659
0
                    loc_ecx += 4;
660
0
                }
661
0
            }
662
0
            return 0; /*pushed_edx;*/
663
0
        }
664
12
    } while (mainloop);
665
666
0
    return 0xbadc0de;
667
396
}
668
669
/* UPack lzma */
670
671
/* compare with 486248 */
672
uint32_t lzma_upack_esi_00(struct lzmastate *p, char *old_ecx, char *bb, uint32_t bl)
673
0
{
674
0
    uint32_t loc_eax, ret, loc_edi;
675
0
    loc_eax = p->p1 >> 0xb;
676
0
    if (!CLI_ISCONTAINED(bb, bl, old_ecx, 4) || !CLI_ISCONTAINED(bb, bl, p->p0, 4)) {
677
0
        if (!CLI_ISCONTAINED(bb, bl, old_ecx, 4))
678
0
            cli_dbgmsg("contain error! %p %08x ecx: %p [%p]\n", bb, bl, old_ecx, bb + bl);
679
0
        else
680
0
            cli_dbgmsg("contain error! %p %08x p0: %p [%p]\n", bb, bl, p->p0, bb + bl);
681
0
        return 0xffffffff;
682
0
    }
683
0
    ret = cli_readint32(old_ecx);
684
0
    loc_eax *= ret;
685
0
    loc_edi = cli_readint32((char *)p->p0);
686
0
    loc_edi = EC32(CE32(loc_edi)); /* bswap */
687
0
    loc_edi -= p->p2;
688
0
    if (loc_edi < loc_eax) {
689
0
        p->p1   = loc_eax;
690
0
        loc_eax = (0x800 - ret) >> 5;
691
0
        cli_writeint32(old_ecx, cli_readint32(old_ecx) + loc_eax);
692
0
        ret = 0;
693
0
    } else {
694
0
        p->p2 += loc_eax;
695
0
        p->p1 -= loc_eax;
696
0
        loc_eax = ret >> 5;
697
0
        cli_writeint32(old_ecx, cli_readint32(old_ecx) - loc_eax);
698
0
        ret = 1;
699
0
    }
700
0
    if (((p->p1) & 0xff000000) == 0) {
701
0
        p->p2 <<= 8;
702
0
        p->p1 <<= 8;
703
0
        p->p0++;
704
0
    }
705
0
    return ret;
706
0
}
707
708
/* compare with lzma_4862e0 */
709
/* lzma_upack_esi_4c 0x1 as eax!
710
 */
711
uint32_t lzma_upack_esi_50(struct lzmastate *p, uint32_t old_eax, uint32_t old_ecx, char **old_edx, char *old_ebp, uint32_t *retval, char *bs, uint32_t bl)
712
0
{
713
0
    uint32_t loc_eax = old_eax, ret;
714
715
0
    do {
716
0
        *old_edx = old_ebp + (loc_eax << 2);
717
0
        if ((ret = lzma_upack_esi_00(p, *old_edx, bs, bl)) == 0xffffffff)
718
0
            return 0xffffffff;
719
0
        loc_eax += loc_eax;
720
0
        loc_eax += ret;
721
0
    } while (loc_eax < old_ecx);
722
723
0
    *retval = loc_eax - old_ecx;
724
0
    return 0;
725
0
}
726
727
uint32_t lzma_upack_esi_54(struct lzmastate *p, uint32_t old_eax, uint32_t *old_ecx, char **old_edx, uint32_t *retval, char *bs, uint32_t bl)
728
0
{
729
0
    uint32_t ret, loc_eax = old_eax;
730
731
0
    *old_ecx = ((*old_ecx) & 0xffffff00) | 8;
732
0
    ret      = lzma_upack_esi_00(p, *old_edx, bs, bl);
733
0
    *old_edx = ((*old_edx) + 4);
734
0
    loc_eax  = (loc_eax & 0xffffff00) | 1;
735
0
    if (ret) {
736
0
        ret = lzma_upack_esi_00(p, *old_edx, bs, bl);
737
0
        loc_eax |= 8; /* mov al, 9 */
738
0
        if (ret) {
739
0
            *old_ecx <<= 5;
740
0
            loc_eax = 0x11; /* mov al, 11 */
741
0
        }
742
0
    }
743
0
    ret = loc_eax;
744
0
    if (lzma_upack_esi_50(p, 1, *old_ecx, old_edx, *old_edx + (loc_eax << 2), &loc_eax, bs, bl) == 0xffffffff)
745
0
        return 0xffffffff;
746
747
0
    *retval = ret + loc_eax;
748
0
    return 0;
749
0
}
750
751
/**
752
 * @brief   Unpack MEW 11 packed PE file
753
 *
754
 * @param src     buffer to unpack
755
 * @param off     offset of diff
756
 * @param ssize   pe section size
757
 * @param dsize   diff size
758
 * @param base    OPTIONAL_HEADER32.ImageBase
759
 * @param vadd    RVA of pe section
760
 * @param uselzma   Bool - use LZMA
761
 * @param filedesc  File descriptor
762
 * @return int    Returns -1 on failure, 1 on success.
763
 */
764
int unmew11(char *src, uint32_t off, uint32_t ssize, uint32_t dsize, uint32_t base, uint32_t vadd, int uselzma, int filedesc)
765
1.04k
{
766
1.04k
    uint32_t entry_point, newedi, loc_ds = dsize, loc_ss = ssize;
767
1.04k
    char *source     = NULL;
768
1.04k
    const char *lesi = NULL;
769
1.04k
    char *ledi;
770
1.04k
    const char *f1;
771
1.04k
    char *f2;
772
1.04k
    int i;
773
1.04k
    struct cli_exe_section *section = NULL;
774
1.04k
    uint32_t vma                    = base + vadd;
775
1.04k
    uint32_t size_sum               = ssize + dsize;
776
777
    /* Guard against integer overflows */
778
1.04k
    if (base + vadd < base) {
779
1
        cli_dbgmsg("MEW: base (%08x) + PE section RVA (%08x) exceeds max size of unsigned int (%08x)\n",
780
1
                   base, vadd, UINT32_MAX);
781
1
        return -1;
782
1
    }
783
1.04k
    if (ssize + dsize < ssize) {
784
0
        cli_dbgmsg("MEW: section size (%08x) + diff size (%08x) exceeds max size of unsigned int (%08x)\n",
785
0
                   ssize, dsize, UINT32_MAX);
786
0
        return -1;
787
0
    }
788
1.04k
    if (((size_t)(src + off) < (size_t)(src)) ||
789
1.04k
        ((size_t)(src + off) < (size_t)(off))) {
790
0
        cli_dbgmsg("MEW: Buffer pointer (%08zx) + offset (%08zx) exceeds max size of pointer (%08lx)\n",
791
0
                   (size_t)src, (size_t)off, SIZE_MAX);
792
0
        return -1;
793
0
    }
794
795
    /* Ensure that off + required data exists within buffer */
796
1.04k
    if (!CLI_ISCONTAINED(src, size_sum, src + off, 12)) {
797
0
        cli_dbgmsg("MEW: Data reference exceeds size of provided buffer.\n");
798
0
        return -1;
799
0
    }
800
801
1.04k
    source = src + dsize + off;
802
1.04k
    lesi   = source + 12;
803
804
1.04k
    entry_point = cli_readint32(source + 4);
805
1.04k
    newedi      = cli_readint32(source + 8);
806
1.04k
    ledi        = src + (newedi - vma);
807
1.04k
    loc_ds      = size_sum - (newedi - vma);
808
809
1.04k
    i = 0;
810
1.04k
    loc_ss -= 12;
811
1.04k
    loc_ss -= off;
812
1.15k
    while (1) {
813
1.15k
        cli_dbgmsg("MEW unpacking section %d (%p->%p)\n", i, lesi, ledi);
814
1.15k
        if (!CLI_ISCONTAINED(src, size_sum, lesi, loc_ss) || !CLI_ISCONTAINED(src, size_sum, ledi, loc_ds)) {
815
262
            cli_dbgmsg("Possibly programmer error or hand-crafted PE file, report to clamav team\n");
816
262
            if (section != NULL)
817
26
                free(section);
818
262
            return -1;
819
262
        }
820
892
        if (unmew(lesi, ledi, loc_ss, loc_ds, &f1, &f2)) {
821
335
            free(section);
822
335
            return -1;
823
335
        }
824
825
        /* we don't need last section in sections since this is information for fixing imptbl */
826
557
        if (!CLI_ISCONTAINED(src, size_sum, f1, 4)) {
827
0
            free(section);
828
0
            return -1;
829
0
        }
830
831
        /* XXX */
832
557
        loc_ss -= (f1 + 4 - lesi);
833
557
        lesi = f1 + 4;
834
835
557
        ledi   = src + (cli_readint32(f1) - vma);
836
557
        loc_ds = size_sum - (cli_readint32(f1) - vma);
837
838
557
        if (!uselzma) {
839
114
            uint32_t val = PESALIGN(f2 - src, 0x1000);
840
114
            void *newsect;
841
842
114
            if (i && val < section[i].raw) {
843
8
                cli_dbgmsg("MEW: WTF - please report\n");
844
8
                free(section);
845
8
                return -1;
846
8
            }
847
848
106
            if (!(newsect = cli_realloc(section, (i + 2) * sizeof(struct cli_exe_section)))) {
849
0
                cli_dbgmsg("MEW: Out of memory\n");
850
0
                free(section);
851
0
                return -1;
852
0
            }
853
854
106
            section            = (struct cli_exe_section *)newsect;
855
106
            section[0].raw     = 0;
856
106
            section[0].rva     = vadd;
857
106
            section[i + 1].raw = val;
858
106
            section[i + 1].rva = val + vadd;
859
106
            section[i].rsz = section[i].vsz = ((i) ? (val - section[i].raw) : val);
860
861
            /*
862
             * bb#11212 - alternate fix, buffer is aligned
863
             * must validate that sections do not intersect with source
864
             * or, in other words, exceed the specified size of destination
865
             */
866
106
            if (section[i].raw + section[i].rsz > dsize) {
867
20
                cli_dbgmsg("MEW: Section %i [%d, %d] exceeds destination size %u\n",
868
20
                           i, section[i].raw, section[i].raw + section[i].rsz, dsize);
869
20
                free(section);
870
20
                return -1;
871
20
            }
872
106
        }
873
529
        i++;
874
875
529
        if (!cli_readint32(f1))
876
420
            break;
877
529
    }
878
879
    /* LZMA stuff */
880
420
    if (uselzma) {
881
396
        free(section);
882
883
        /* put everything in one section */
884
396
        i = 1;
885
396
        if (!CLI_ISCONTAINED(src, size_sum, src + uselzma + 8, 1)) {
886
0
            cli_dbgmsg("MEW: couldn't access lzma 'special' tag\n");
887
0
            return -1;
888
0
        }
889
        /* 0x50 -> push eax */
890
396
        cli_dbgmsg("MEW: lzma %swas used, unpacking\n", (*(src + uselzma + 8) == '\x50') ? "special " : "");
891
396
        if (!CLI_ISCONTAINED(src, size_sum, f1 + 4, 20 + 4 + 5)) {
892
0
            cli_dbgmsg("MEW: lzma initialization data not available!\n");
893
0
            return -1;
894
0
        }
895
896
396
        if (mew_lzma(src, f1 + 4, size_sum, vma, *(src + uselzma + 8) == '\x50')) {
897
377
            return -1;
898
377
        }
899
19
        loc_ds = PESALIGN(loc_ds, 0x1000);
900
901
19
        section = cli_calloc(1, sizeof(struct cli_exe_section));
902
19
        if (!section) {
903
0
            cli_dbgmsg("MEW: Out of memory\n");
904
0
            return -1;
905
0
        }
906
907
19
        section[0].raw = 0;
908
19
        section[0].rva = vadd;
909
19
        section[0].rsz = section[0].vsz = dsize;
910
19
    }
911
43
    if (!cli_rebuildpe_align(src, section, i, base, entry_point - base, 0, 0, filedesc, 0x1000)) {
912
0
        cli_dbgmsg("MEW: Rebuilding failed\n");
913
0
        free(section);
914
0
        return -1;
915
0
    }
916
43
    free(section);
917
43
    return 1;
918
43
}