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