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