Browse code

MEW support code added (enabled via configure option) Merge not complete, please don't freeze yet.

git-svn: trunk@2609

aCaB authored on 2007/01/13 02:53:44
Showing 8 changed files
... ...
@@ -1,3 +1,8 @@
1
+Fri Jan 12 18:51:33 CET 2007 (acab)
2
+-----------------------------------
3
+  * libclamav: add MEW support from Michal Spadlinski <gim913 * gmail.com>
4
+  	       Part of the Google Summer of Code program
5
+
1 6
 Fri Jan 12 18:35:02 CET 2007 (tk)
2 7
 ---------------------------------
3 8
   * libclamav/phishcheck.c: add img url link-type filtering (patch from Edwin)
... ...
@@ -95,6 +95,8 @@ libclamav_la_SOURCES = \
95 95
 	packlibs.h \
96 96
 	fsg.c \
97 97
 	fsg.h \
98
+	mew.c \
99
+	mew.h \
98 100
 	line.c \
99 101
 	line.h \
100 102
 	untar.c \
... ...
@@ -83,10 +83,10 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher-ncore.lo \
83 83
 	snprintf.lo table.lo text.lo ole2_extract.lo vba_extract.lo \
84 84
 	msexpand.lo pe.lo upx.lo htmlnorm.lo chmunpack.lo rebuildpe.lo \
85 85
 	petite.lo wwunpack.lo suecrypt.lo unsp.lo packlibs.lo fsg.lo \
86
-	line.lo untar.lo unzip.lo special.lo binhex.lo is_tar.lo \
87
-	tnef.lo unrar15.lo unrarvm.lo unrar.lo unrarfilter.lo \
88
-	unrarppm.lo unrar20.lo unrarcmd.lo pdf.lo spin.lo yc.lo elf.lo \
89
-	sis.lo uuencode.lo pst.lo phishcheck.lo \
86
+	mew.lo line.lo untar.lo unzip.lo special.lo binhex.lo \
87
+	is_tar.lo tnef.lo unrar15.lo unrarvm.lo unrar.lo \
88
+	unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo pdf.lo \
89
+	spin.lo yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \
90 90
 	phish_domaincheck_db.lo phish_whitelist.lo regex_list.lo \
91 91
 	sha256.lo mspack.lo cab.lo entconv.lo hashtab.lo dconf.lo
92 92
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
... ...
@@ -307,6 +307,8 @@ libclamav_la_SOURCES = \
307 307
 	packlibs.h \
308 308
 	fsg.c \
309 309
 	fsg.h \
310
+	mew.c \
311
+	mew.h \
310 312
 	line.c \
311 313
 	line.h \
312 314
 	untar.c \
... ...
@@ -466,6 +468,7 @@ distclean-compile:
466 466
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbox.Plo@am__quote@
467 467
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@
468 468
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@
469
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mew.Plo@am__quote@
469 470
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msexpand.Plo@am__quote@
470 471
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mspack.Plo@am__quote@
471 472
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ole2_extract.Plo@am__quote@
472 473
new file mode 100644
... ...
@@ -0,0 +1,764 @@
0
+/*
1
+ *  Copyright (C) 2006 Michal 'GiM' Spadlinski http://gim.org.pl/
2
+ *
3
+ *  This program is free software; you can redistribute it and/or modify
4
+ *  it under the terms of the GNU General Public License as published by
5
+ *  the Free Software Foundation; either version 2 of the License, or
6
+ *  (at your option) any later version.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
+ *  MA 02110-1301, USA.
17
+ */
18
+
19
+/*
20
+ * lzma.c
21
+ *
22
+ * o2:28:18 CEST 2oo6-25-o6 		- initial 0xA4/0x536
23
+ * oo:29:4o CEST 2oo6-26-o6 		- 0x1cd/0x536 [+0x129]
24
+ * o2:13:19 CEST 2oo6-o1-o7, 2oo6-3o-o6 - 0x536/0x536
25
+ *
26
+ */
27
+
28
+#if HAVE_CONFIG_H
29
+#include "clamav-config.h"
30
+#endif
31
+
32
+#ifdef CL_EXPERIMENTAL
33
+#include <stdio.h>
34
+#include <stdlib.h>
35
+#include <sys/types.h>
36
+#include <sys/stat.h>
37
+#include <unistd.h>
38
+#include <string.h>
39
+
40
+#include "cltypes.h"
41
+#include "pe.h"
42
+#include "rebuildpe.h"
43
+#include "others.h"
44
+#include "mew.h"
45
+#include "packlibs.h"
46
+
47
+#define EC32(x) le32_to_host(x) /* Convert little endian to host */
48
+#define CE32(x) be32_to_host(x) /* Convert big endian to host */
49
+
50
+/* modifies all parameters */
51
+/* northfox does this shitty way,
52
+ * this should be done with just a bswap
53
+ */
54
+char *lzma_bswap_4861dc(struct lzmastate *p, char *old_edx)
55
+{
56
+	/* dumb_dump_start
57
+	 *
58
+
59
+	old_edx was 'uint32_t *' before and in mew_lzma there was
60
+	&new_edx where new_edx = var1C
61
+
62
+	uint32_t loc_esi, loc_edi;
63
+	uint8_t *loc_eax;
64
+
65
+	p->p2 = loc_esi = 0;
66
+	p->p0 = loc_eax = (uint8_t *)*old_edx;
67
+	*old_edx = 5;
68
+	do {
69
+		loc_esi = p->p2 << 8;
70
+		loc_edi = *(uint8_t *)((loc_eax)++);
71
+		loc_esi |= loc_edi;
72
+		(*old_edx)--;
73
+		p->p2 = loc_esi;
74
+	} while (*old_edx);
75
+	p->p0 = loc_eax;
76
+	p->p1 = 0xffffffff;
77
+
78
+	* dumb_dump_end
79
+	*/
80
+
81
+	/* XXX, mine replacement */
82
+	p->p2 = EC32(CE32(((uint32_t)cli_readint32(old_edx + 1))));
83
+	p->p1 = 0xffffffff;
84
+	p->p0 = old_edx + 5;
85
+
86
+	return p->p0;
87
+}
88
+
89
+int lzma_486248 (struct lzmastate *p, char **old_ecx, char *src, uint32_t size)
90
+{
91
+	uint32_t loc_esi, loc_edi, loc_eax, loc_ecx, ret;
92
+	if (!CLI_ISCONTAINED(src, size, *old_ecx, 4) || !CLI_ISCONTAINED(src, size, p->p0, 1))
93
+		return -1;
94
+	loc_esi = p->p1;
95
+	loc_eax = loc_esi >> 0xb;
96
+	loc_ecx = cli_readint32(*old_ecx);
97
+	ret = loc_ecx&0xffff;
98
+	(loc_eax) *=  ret;
99
+	loc_edi = p->p2;
100
+	if (loc_edi < loc_eax)
101
+	{
102
+		/* 48625f */
103
+		p->p1 = loc_eax;
104
+		loc_esi = ret;
105
+		loc_edi = ((int32_t)(0x800 - ret) >> 5) + ((loc_eax&0xffff0000) | ret); 
106
+								/* signed<-sar, &|<-mov ax, [ecx] */
107
+		loc_ecx = (loc_ecx&0xffff0000)|(loc_edi&0xffff);
108
+		cli_writeint32(*old_ecx, loc_ecx);
109
+
110
+		ret = 0;
111
+	} else {
112
+		/* 48629e */
113
+		loc_esi -= loc_eax;
114
+		loc_edi -= loc_eax;
115
+		p->p1 = loc_esi;
116
+		p->p2 = loc_edi;
117
+		loc_eax = (loc_eax & 0xffff0000) | ret;
118
+		loc_esi = (loc_esi & 0xffff0000) | (ret >> 5);
119
+		loc_eax -= loc_esi;
120
+
121
+		loc_ecx = (loc_ecx&0xffff0000)|(loc_eax&0xffff);
122
+		cli_writeint32(*old_ecx, loc_ecx);
123
+
124
+		ret = 1;
125
+	}
126
+	loc_eax = p->p1;
127
+	if (loc_eax < 0x1000000)
128
+	{
129
+		*old_ecx = p->p0;
130
+		loc_edi = (*(uint8_t *)(p->p0));
131
+		loc_esi = ((p->p2) << 8) | loc_edi;
132
+		(*old_ecx)++;
133
+		loc_eax <<= 8;
134
+		p->p2 = loc_esi;
135
+		p->p1 = loc_eax;
136
+		p->p0 = *old_ecx;
137
+	}
138
+	return ret;
139
+
140
+}
141
+
142
+uint32_t lzma_48635C(uint8_t znaczek, char **old_ecx, struct lzmastate *p, uint32_t *retval, char *src, uint32_t size)
143
+{
144
+	uint32_t loc_esi = (znaczek&0xff) >> 7, /* msb */
145
+		loc_ebx, ret;
146
+	char *loc_edi;
147
+	znaczek <<= 1;
148
+	ret = loc_esi << 9;
149
+	loc_edi = *old_ecx;
150
+	*old_ecx = loc_edi + ret + 0x202;
151
+	if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
152
+		return -1;
153
+	loc_ebx = ret | 2;
154
+
155
+	while (loc_esi == ret)
156
+	{
157
+		if (loc_ebx >= 0x100)
158
+		{
159
+			ret = (ret&0xffffff00) | (loc_ebx&0xff);
160
+			*retval = ret;
161
+			return 0;
162
+		}
163
+		loc_esi = (znaczek&0xff) >> 7;
164
+		znaczek <<= 1;
165
+		ret = ((loc_esi + 1) << 8) + loc_ebx;
166
+		*old_ecx = loc_edi + ret*2;
167
+		if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
168
+			return -1;
169
+		loc_ebx += loc_ebx;
170
+		loc_ebx |= ret;
171
+	}
172
+	loc_esi = 0x100;
173
+	while (loc_ebx < loc_esi)
174
+	{
175
+		loc_ebx += loc_ebx;
176
+		*old_ecx = loc_edi + loc_ebx;
177
+		if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
178
+			return -1;
179
+		loc_ebx |= ret;
180
+	}
181
+	ret = (ret&0xffffff00) | (loc_ebx&0xff);
182
+	*retval = ret;
183
+	return 0;
184
+}
185
+
186
+uint32_t lzma_4862e0 (struct lzmastate *p, char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
187
+{
188
+	uint32_t loc_ebx, loc_esi, stack_ecx, ret;
189
+	char *loc_edi;
190
+
191
+	loc_ebx = *old_edx;
192
+	ret = 1;
193
+	loc_edi = *old_ecx;
194
+	if (loc_ebx && !(loc_ebx&0x80000000))
195
+	{
196
+		/* loc_4862f1 */
197
+		stack_ecx = loc_ebx;
198
+		do {
199
+			loc_esi = ret+ret;
200
+			*old_ecx = loc_edi + loc_esi;
201
+			if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
202
+				return -1;
203
+			ret += loc_esi;
204
+			stack_ecx--;
205
+		} while (stack_ecx);
206
+	} 
207
+	/* loc_48630b */
208
+	  /* unneeded
209
+	*old_ecx = (uint8_t *)loc_ebx;
210
+	  */
211
+	
212
+	*old_edx = 1 << (loc_ebx&0xff);
213
+	ret -= *old_edx;
214
+	*retval = ret;
215
+	return 0;
216
+}
217
+
218
+/* old_edx - write only */
219
+uint32_t lzma_4863da (uint32_t var0, struct lzmastate *p, char  **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
220
+{
221
+	uint32_t ret;
222
+	char *loc_esi = *old_ecx;
223
+
224
+	if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
225
+		return -1;
226
+	if (ret)
227
+	{
228
+		/* loc_4863ff */
229
+		*old_ecx = loc_esi+2;
230
+		if ((ret = lzma_486248 (p, old_ecx, src, size)) == -1)
231
+			return -1;
232
+		if (ret)
233
+		{
234
+			/* loc_486429 */
235
+			*old_edx = 8;
236
+			*old_ecx = loc_esi + 0x204;
237
+			if (lzma_4862e0 (p, old_ecx, old_edx, &ret, src, size) == -1)
238
+				return -1;
239
+			ret += 0x10;
240
+		} else {
241
+			/* loc_48640e */
242
+			ret = var0 << 4;
243
+			*old_edx = 3;
244
+			*old_ecx = loc_esi + 0x104 + ret;
245
+			if (lzma_4862e0 (p, old_ecx, old_edx, &ret, src, size) == -1)
246
+				return -1;
247
+			ret += 0x8;
248
+		}
249
+	} else {
250
+		/* loc_4863e9 */
251
+		ret = var0 << 4;
252
+		*old_edx = 3;
253
+		*old_ecx = loc_esi + 0x4 + ret;
254
+		if (lzma_4862e0 (p, old_ecx, old_edx, &ret, src, size) == -1)
255
+			return -1;
256
+	}
257
+	*retval = ret;
258
+	return 0;
259
+}
260
+
261
+uint32_t lzma_486204 (struct lzmastate *p, uint32_t old_edx, uint32_t *retval, char *src, uint32_t size)
262
+{
263
+	uint32_t loc_esi, loc_edi, loc_ebx, loc_eax;
264
+	char *loc_edx;
265
+	loc_esi = p->p1;
266
+	loc_edi = p->p2;
267
+	loc_eax = 0;
268
+	if (old_edx && !(old_edx&0x80000000))
269
+	{
270
+		/* loc_4866212 */
271
+		loc_ebx = old_edx;
272
+		do {
273
+			loc_esi >>= 1;
274
+			loc_eax <<= 1;
275
+			if (loc_edi >= loc_esi)
276
+			{
277
+				loc_edi -= loc_esi;
278
+				loc_eax |= 1;
279
+			}
280
+			/* loc_486222 */
281
+			if (loc_esi < 0x1000000)
282
+			{
283
+				if (!CLI_ISCONTAINED(src, size, p->p0, 1))
284
+					return -1;
285
+				loc_edx = p->p0;
286
+				loc_edi <<= 8;
287
+				loc_esi <<= 8;
288
+				loc_edi |= (*loc_edx)&0xff; /* movzx ebp, byte ptr [edx] */
289
+				p->p0 = ++loc_edx;
290
+			}
291
+			loc_ebx--;
292
+		} while (loc_ebx);
293
+
294
+	}
295
+	p->p2 = loc_edi;
296
+	p->p1 = loc_esi;
297
+	*retval = loc_eax;
298
+	return 0;
299
+}
300
+
301
+uint32_t lzma_48631a (struct lzmastate *p, char **old_ecx, uint32_t *old_edx, uint32_t *retval, char *src, uint32_t size)
302
+{
303
+	uint32_t copy1, copy2;
304
+	uint32_t loc_esi, loc_edi, ret;
305
+	char *loc_ebx;
306
+
307
+	copy1 = *old_edx;
308
+	loc_edi = 0;
309
+	loc_ebx = *old_ecx;
310
+	*old_edx = 1;
311
+	copy2 = (uint32_t)loc_edi;
312
+
313
+	if (copy1 <= (uint32_t)loc_edi)
314
+	{
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)) == -1)
323
+			return -1;
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
+
336
+int mew_lzma(struct pe_image_section_hdr *section_hdr, char *orgsource, char *buf, uint32_t size_sum, uint32_t vma, uint32_t special)
337
+{
338
+	uint32_t var08, var0C, var10, var14, var18, var20, var24, var28, var34;
339
+	struct lzmastate var40;
340
+	uint32_t new_eax, new_edx, temp, loc_edi, loc_esi;
341
+	int i, mainloop;
342
+	char var1, var30;
343
+	char *source = buf, *dest, *new_ebx, *new_ecx, *var0C_ecxcopy, *var2C;
344
+	char *pushed_esi = NULL, *pushed_ebx = NULL;
345
+	uint32_t pushed_edx=0;
346
+
347
+	if (special)
348
+	{
349
+		pushed_edx = cli_readint32(source);
350
+		source += 4;
351
+	}
352
+	temp = cli_readint32(source) - vma;
353
+	source += 4;
354
+	if (!special) pushed_ebx = source;
355
+	new_ebx = orgsource + temp;
356
+
357
+    do {
358
+        mainloop = 1;
359
+	do {
360
+		/* loc_486450 */
361
+		if (!special)
362
+		{
363
+			source = pushed_ebx;
364
+			if (cli_readint32(source) == 0)
365
+			{
366
+				return 0;
367
+			}
368
+		}
369
+		var28 = cli_readint32 (source);
370
+		source += 4;
371
+		temp = cli_readint32 (source) - vma;
372
+		var18 = (uint32_t)orgsource + temp;
373
+		if (special) pushed_esi = orgsource + temp;
374
+		source += 4;
375
+		temp = cli_readint32 (source);
376
+		source += 5; /* yes, five */
377
+		var2C = source;
378
+		source += temp;
379
+		if (special) pushed_ebx = source;
380
+		else pushed_ebx = source;
381
+		var1 = 0;
382
+		dest = new_ebx;
383
+		
384
+		if(!CLI_ISCONTAINED(orgsource, size_sum, dest, 0x6E6C))
385
+			return -1;
386
+		for (i=0; i<0x1b9b; i++)
387
+		{
388
+			cli_writeint32(dest, 0x4000400);
389
+			dest += 4;
390
+		}
391
+		loc_esi = 0;
392
+		var08 = var20 = 0;
393
+		loc_edi = 1;
394
+		var14 = var10 = var24 = 1;
395
+
396
+		lzma_bswap_4861dc(&var40, var2C);
397
+		new_edx = 0;
398
+	} while (var28 <= loc_esi); /* source = 0 */
399
+
400
+	cli_dbgmsg("MEWlzma: entering do while loop\n");
401
+	do {
402
+		/* loc_4864a5 */
403
+		new_eax = var08 & 3;
404
+		new_ecx = (((loc_esi << 4) + new_eax)*2) + new_ebx;
405
+		var0C = new_eax;
406
+		if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
407
+			return -1;
408
+		if (new_eax)
409
+		{
410
+			/* loc_486549 */
411
+			new_ecx = new_ebx + loc_esi*2 + 0x180;
412
+			var20 = 1;
413
+			/* eax=1 */
414
+			if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
415
+				return -1;
416
+			if (new_eax != 1)
417
+			{
418
+				/* loc_486627 */
419
+				var24 = var10;
420
+				var10 = var14;
421
+				/* xor eax,eax; cmp esi, 7; setnl al; dec eax; add eax, 0Ah */
422
+				/* new_eax = (((loc_esi >= 7)-1)&0xFFFFFFFD) + 0xA; */
423
+				new_eax = loc_esi>=7 ? 10:7;
424
+				new_ecx = new_ebx + 0x664;
425
+				var14 = loc_edi;
426
+				loc_esi = new_eax;
427
+				if (lzma_4863da (var0C, &var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
428
+					return -1;
429
+				var0C = new_eax;
430
+				if (var0C >= 4)
431
+					new_eax = 3;
432
+
433
+				/* loc_486662 */
434
+				new_edx = 6;
435
+				new_eax <<= 7;
436
+				new_ecx = new_eax + new_ebx + 0x360;
437
+				if (lzma_4862e0 (&var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
438
+					return -1;
439
+				if (new_eax < 4)
440
+				{ 
441
+					/* loc_4866ca */
442
+					loc_edi = new_eax;
443
+				} else {
444
+					/* loc_48667d */
445
+					uint32_t loc_ecx;
446
+					loc_ecx = ((int32_t)new_eax >> 1)-1; /* sar */
447
+					loc_edi = ((new_eax&1)|2) << (loc_ecx&0xff);
448
+					if (new_eax >= 0xe)
449
+					{
450
+						/* loc_4866ab */
451
+						new_edx = loc_ecx - 4;
452
+						if (lzma_486204 (&var40, new_edx, &new_eax, orgsource, size_sum) == -1)
453
+							return -1;
454
+						loc_edi += new_eax << 4;
455
+
456
+						new_edx = 4;
457
+						new_ecx = new_ebx + 0x644;
458
+					} else {
459
+						/* loc_486691 */
460
+						new_edx = loc_ecx;
461
+						loc_ecx = loc_edi - new_eax;
462
+						new_ecx =  new_ebx + loc_ecx*2 + 0x55e;
463
+					}
464
+					/* loc_4866a2 */
465
+					if (lzma_48631a (&var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
466
+						return -1;
467
+					loc_edi += new_eax;
468
+				}
469
+				loc_edi++;
470
+			} else {
471
+				/* loc_486568 */
472
+				new_ecx = new_ebx + loc_esi*2 + 0x198;
473
+				if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
474
+					return -1;
475
+				if (new_eax)
476
+				{
477
+					/* loc_4865bd */
478
+					new_ecx = new_ebx + loc_esi*2 + 0x1B0;
479
+					if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
480
+						return -1;
481
+					if (new_eax)
482
+					{
483
+						/* loc_4865d2 */
484
+						new_ecx = new_ebx + loc_esi*2 + 0x1C8;
485
+						if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
486
+							return -1;
487
+						if (new_eax) {
488
+							/* loc_4865ea */
489
+							new_eax = var24;
490
+							var24 = var10;
491
+						} else {
492
+							/* loc_4865e5 */
493
+							new_eax = var10;
494
+						}
495
+						/* loc_4865f3 */
496
+						var10 = var14;
497
+					} else {
498
+						/* loc_4865cd */
499
+						new_eax = var14;
500
+					}
501
+					/* loc_4865f9 */
502
+					var14 = loc_edi;
503
+					loc_edi = new_eax;
504
+				} else {
505
+					/* loc_48657e */
506
+					new_eax = ((loc_esi + 0xf) << 4) + var0C;
507
+					new_ecx = new_ebx + new_eax*2;
508
+					if ((new_eax = lzma_486248 (&var40, &new_ecx, orgsource, size_sum)) == -1)
509
+						return -1;
510
+					if (!new_eax) {
511
+						uint32_t loc_ecx;
512
+						/* loc_486593 */
513
+						loc_ecx = var08;
514
+						loc_ecx -= loc_edi;
515
+						/* loc_esi = ((((loc_esi >= 7)-1)&0xFFFFFFFE) + 0xB); */
516
+						loc_esi = loc_esi>=7 ? 11:9;
517
+						new_eax = var18;
518
+						if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + loc_ecx), 1))
519
+							return -1;
520
+						var1 = *(uint8_t *)(new_eax + loc_ecx);
521
+						loc_ecx = (loc_ecx&0xffffff00) | var1;
522
+						/* loc_4865af */
523
+						new_edx = var08++;
524
+						if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + new_edx), 1))
525
+							return -1;
526
+						*(uint8_t *)(new_eax + new_edx) = loc_ecx & 0xff;
527
+
528
+						new_ecx = (char*)loc_ecx;
529
+
530
+						/* loc_4866fe */
531
+						new_eax = var08;
532
+						continue; /* !!! */
533
+					}
534
+
535
+				}
536
+				/* loc_4865fe */
537
+				new_ecx = new_ebx + 0xa68;
538
+				if (lzma_4863da (var0C, &var40, &new_ecx, &new_edx, &new_eax, orgsource, size_sum) == -1)
539
+					return -1;
540
+				var0C = new_eax;
541
+				/* new_eax = (((loc_esi >= 7)-1)&0xFFFFFFFD) + 0xB; */
542
+				new_eax = loc_esi>=7 ? 11:8;
543
+				loc_esi = new_eax;
544
+			}
545
+			/* loc_4866cd */
546
+			if (!loc_edi)
547
+			{
548
+				break;
549
+			} else {
550
+				var0C += 2;
551
+				new_ecx = (char*)var18;
552
+				new_edx = new_eax = var08;
553
+				new_eax -= loc_edi;
554
+				if ( ((var0C < var28 - new_edx) &&
555
+						(!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_eax), var0C) || 
556
+						 !CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_edx), var0C))) ||
557
+						(!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_eax), var28 - new_edx) ||
558
+						 !CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_ecx + new_edx), var28 - new_edx)) )
559
+					return -1;
560
+				do {
561
+					var1 = *(uint8_t *)(new_ecx + new_eax);
562
+					*(uint8_t *)(new_ecx + new_edx) = var1;
563
+
564
+					new_edx++;
565
+					new_eax++;
566
+					var0C--;
567
+					if (var0C <= 0)
568
+						break;
569
+				} while (new_edx < var28);
570
+				var08 = new_edx;
571
+			}
572
+		} else {
573
+			/* loc_4864C8 */
574
+			new_eax = (((var1 & 0xff) >> 4)*3) << 9;
575
+			new_ecx = new_eax + new_ebx + 0xe6c;
576
+			var0C_ecxcopy = new_ecx;
577
+			if (loc_esi >= 4)
578
+			{
579
+				/* loc_4864e8 */
580
+				if (loc_esi >= 10)
581
+					loc_esi -= 6;
582
+				else
583
+					loc_esi -= 3;
584
+
585
+			} else {
586
+				/* loc_4864e4 */
587
+				loc_esi = 0;
588
+			}
589
+
590
+			if (var20 == 0)	{
591
+				/* loc_48651D */
592
+				new_eax = 1;
593
+				do {
594
+					/* loc_486525 */
595
+					/*new_ecx = var0C_ecxcopy;*/
596
+					new_eax += new_eax;
597
+					new_ecx += new_eax;
598
+					var34 = new_eax;
599
+					if ((new_eax = lzma_486248(&var40, &new_ecx, orgsource, size_sum)) == -1)
600
+						return -1;
601
+					new_eax |= var34;
602
+					/* loc_486522 */
603
+					/* keeping it here instead of at the top
604
+					 * seems to work faster
605
+					 */
606
+					if (new_eax < 0x100)
607
+					{
608
+						new_ecx = var0C_ecxcopy;
609
+					}
610
+				} while (new_eax < 0x100);
611
+				/* loc_48653e */
612
+				var1 = (uint8_t)(new_eax & 0xff);
613
+			} else {
614
+				int t;
615
+				/* loc_4864FB */
616
+				new_edx = var18;
617
+				new_eax = var08 - loc_edi;
618
+				if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + new_edx), 1))
619
+					return -1;
620
+				t = *(uint8_t *)(new_eax+new_edx);
621
+				new_eax = (new_eax&0xffffff00) | t;
622
+				/*new_edx = (uint32_t)&var40;*/
623
+				var30 = t;
624
+				if (lzma_48635C (t, &new_ecx, &var40, &new_eax, orgsource, size_sum) == -1)
625
+					return -1;
626
+				var20 = 0;
627
+				var1 = new_eax&0xff;
628
+			}
629
+
630
+			/* loc_486541 */
631
+			new_eax = var18;
632
+			/* unneeded: new_ecx = (new_ecx&0xffffff00) | var1; */
633
+
634
+			/* loc_4865af */
635
+			new_edx = var08++;
636
+
637
+			if (!CLI_ISCONTAINED(orgsource, size_sum, (char*)(new_eax + new_edx), 1))
638
+				return -1;
639
+			*(uint8_t *)(new_eax + new_edx) = var1;
640
+		}
641
+		/* loc_4866fe */
642
+		new_eax = var08;
643
+	} while (new_eax < var28);
644
+
645
+    	if (special) {
646
+		uint32_t loc_ecx;
647
+		/* let's fix calls */
648
+		loc_ecx = 0;
649
+		cli_dbgmsg("MEWlen: %08x ? %08x\n", new_edx, pushed_edx);
650
+
651
+		if (!CLI_ISCONTAINED(orgsource, size_sum, pushed_esi, pushed_edx))
652
+			return -1;
653
+		do {
654
+			/* 0xe8, 0xe9 call opcodes */
655
+			if (pushed_esi[loc_ecx] == '\xe8' || pushed_esi[loc_ecx] == '\xe9')
656
+			{
657
+				char *adr = (char *)(pushed_esi + loc_ecx + 1);
658
+				loc_ecx++;
659
+				
660
+				cli_writeint32(adr, EC32(CE32((uint32_t)cli_readint32(adr)))-loc_ecx);
661
+				loc_ecx += 4;
662
+			} else 
663
+				loc_ecx++;
664
+		} while (loc_ecx != pushed_edx);
665
+		return 0; /*pushed_edx;*/
666
+	}
667
+    } while (mainloop);
668
+
669
+    return 0xbadc0de;
670
+}
671
+
672
+
673
+/* UPack lzma */
674
+
675
+/* compare with 486248 */
676
+uint32_t lzma_upack_esi_00(struct lzmastate *p, char *old_ecx, char *bb, uint32_t bl)
677
+{
678
+	uint32_t loc_eax, ret, loc_edi;
679
+	loc_eax = p->p1 >> 0xb;
680
+	if (!CLI_ISCONTAINED(bb, bl, old_ecx, 4) || !CLI_ISCONTAINED(bb, bl, p->p0, 4))
681
+	{
682
+		if (!CLI_ISCONTAINED(bb, bl, old_ecx, 4))
683
+			cli_dbgmsg("contain error! %08x %08x ecx: %08x [%08x]\n", bb, bl, old_ecx,bb+bl);
684
+		else
685
+			cli_dbgmsg("contain error! %08x %08x p0: %08x [%08x]\n", bb, bl, p->p0,bb+bl);
686
+		return -1;
687
+	}
688
+	ret = cli_readint32(old_ecx);
689
+	loc_eax *= ret;
690
+	loc_edi = cli_readint32((char *)p->p0);
691
+	loc_edi = EC32(CE32(loc_edi)); /* bswap */
692
+	loc_edi -= p->p2;
693
+	if (loc_edi < loc_eax)
694
+	{
695
+		p->p1 = loc_eax;
696
+		loc_eax = (0x800 - ret) >> 5;
697
+		cli_writeint32(old_ecx, cli_readint32(old_ecx) + loc_eax);
698
+		ret = 0;
699
+	} else {
700
+		p->p2 += loc_eax;
701
+		p->p1 -= loc_eax;
702
+		loc_eax = ret >> 5;
703
+		cli_writeint32(old_ecx, cli_readint32(old_ecx) - loc_eax);
704
+		ret = 1;
705
+	}
706
+	if(((p->p1)&0xff000000) == 0)
707
+	{
708
+		p->p2 <<= 8;
709
+		p->p1 <<= 8;
710
+		p->p0++;
711
+	}
712
+	return ret;
713
+}
714
+
715
+/* compare with lzma_4862e0 */
716
+/* lzma_upack_esi_4c 0x1 as eax!
717
+ */
718
+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)
719
+{
720
+	uint32_t loc_eax = old_eax, original = old_eax, ret;
721
+
722
+	do {
723
+		*old_edx = old_ebp + (loc_eax<<2);
724
+		if ((ret = lzma_upack_esi_00(p, *old_edx, bs, bl)) == -1)
725
+			return -1;
726
+		loc_eax += loc_eax;
727
+		loc_eax += ret;
728
+	} while (loc_eax < old_ecx);
729
+
730
+/*	cli_dbgmsg("loc_eax: %08x - ecx: %08x = %08x || original: %08x\n", loc_eax, old_ecx, loc_eax - old_ecx, original); */
731
+	*retval = loc_eax - old_ecx;
732
+	return 0;
733
+}
734
+
735
+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)
736
+{
737
+	uint32_t ret, loc_eax = old_eax;
738
+
739
+	*old_ecx = ((*old_ecx)&0xffffff00)|8;
740
+	ret = lzma_upack_esi_00 (p, *old_edx, bs, bl);
741
+	*old_edx = ((*old_edx) + 4);
742
+	loc_eax = (loc_eax&0xffffff00)|1;
743
+	if (ret)
744
+	{
745
+		ret = lzma_upack_esi_00 (p, *old_edx, bs, bl);
746
+		loc_eax |= 8; /* mov al, 9 */
747
+		if (ret)
748
+		{
749
+			*old_ecx <<= 5;
750
+			loc_eax = 0x11; /* mov al, 11 */
751
+		}
752
+	}
753
+	ret = loc_eax;
754
+	if (lzma_upack_esi_50(p, 1, *old_ecx, old_edx, *old_edx + (loc_eax << 2), &loc_eax, bs, bl) == -1)
755
+		return -1;
756
+
757
+	*retval = ret + loc_eax;
758
+	return 0;
759
+}
760
+
761
+
762
+#endif
763
+
0 764
new file mode 100644
... ...
@@ -0,0 +1,38 @@
0
+/*
1
+ *  Copyright (C) 2006 Michal 'GiM' Spadlinski http://gim.org.pl/
2
+ *
3
+ *  This program is free software; you can redistribute it and/or modify
4
+ *  it under the terms of the GNU General Public License as published by
5
+ *  the Free Software Foundation; either version 2 of the License, or
6
+ *  (at your option) any later version.
7
+ *
8
+ *  This program is distributed in the hope that it will be useful,
9
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ *  GNU General Public License for more details.
12
+ *
13
+ *  You should have received a copy of the GNU General Public License
14
+ *  along with this program; if not, write to the Free Software
15
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
+ *  MA 02110-1301, USA.
17
+ */
18
+
19
+#ifndef __MEW_H
20
+#define __MEW_H
21
+
22
+struct lzmastate {
23
+	char *p0;
24
+	uint32_t p1, p2;
25
+};
26
+
27
+int mew_lzma(struct pe_image_section_hdr *, char *, char *, uint32_t, uint32_t, uint32_t);
28
+
29
+uint32_t lzma_upack_esi_00(struct lzmastate *, char *, char *, uint32_t);
30
+uint32_t lzma_upack_esi_50(struct lzmastate *, uint32_t, uint32_t, char **, char *, uint32_t *, char *, uint32_t);
31
+uint32_t lzma_upack_esi_54(struct lzmastate *, uint32_t, uint32_t *, char **, uint32_t *, char *, uint32_t);
32
+
33
+#endif
34
+
35
+
36
+
37
+
... ...
@@ -23,6 +23,9 @@
23 23
 #endif
24 24
 
25 25
 #include "others.h"
26
+#include "execs.h"
27
+#include "pe.h"
28
+#include "rebuildpe.h"
26 29
 
27 30
 static int doubledl(char **scur, uint8_t *mydlptr, char *buffer, uint32_t buffersize)
28 31
 {
... ...
@@ -166,3 +169,256 @@ int cli_unfsg(char *source, char *dest, int ssize, int dsize, char **endsrc, cha
166 166
   if (enddst) *enddst = cdst;
167 167
   return 0;
168 168
 }
169
+
170
+#ifdef CL_EXPERIMENTAL
171
+static int unmew(char *source, char *dest, int ssize, int dsize, char **endsrc, char **enddst) {
172
+  uint8_t mydl=0x80;
173
+  uint32_t myeax_backbytes, myecx_backsize, oldback = 0;
174
+  char *csrc = source, *cdst = dest;
175
+  int oob, lostbit = 1;
176
+
177
+  *cdst++=*csrc++;
178
+
179
+  while ( 1 ) {
180
+    if ((oob=doubledl(&csrc, &mydl, source, ssize))) {
181
+      if (oob == -1)
182
+	return -1;
183
+      /* 164 */
184
+      myecx_backsize = 0;
185
+      if ((oob=doubledl(&csrc, &mydl, source, ssize))) {
186
+	if (oob == -1)
187
+	  return -1;
188
+	/* 16a */
189
+	myeax_backbytes = 0;
190
+	if ((oob=doubledl(&csrc, &mydl, source, ssize))) {
191
+	  if (oob == -1)
192
+	    return -1;
193
+	  /* 170 */
194
+	  lostbit = 1;
195
+	  myecx_backsize++;
196
+	  myeax_backbytes = 0x10;
197
+	  while ( myeax_backbytes < 0x100 ) {
198
+	    if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
199
+	      return -1;
200
+	    myeax_backbytes = myeax_backbytes*2+oob;
201
+	  }
202
+	  myeax_backbytes &= 0xff;
203
+	  if ( ! myeax_backbytes ) {
204
+	    if (cdst >= dest+dsize)
205
+	      return -1;
206
+	    *cdst++=0x00;
207
+	    /*cli_dbgmsg("X%02x  ", *(cdst-1)&0xff);*/
208
+	    continue;
209
+	  }
210
+	} else {
211
+	  /* 18f */
212
+	  if (csrc >= source+ssize)
213
+	    return -1;
214
+	  myeax_backbytes = *(unsigned char*)csrc;
215
+	  myecx_backsize = myecx_backsize * 2 + (myeax_backbytes & 1);
216
+	  myeax_backbytes = (myeax_backbytes & 0xff)>>1;
217
+	  csrc++;
218
+	  if (! myeax_backbytes)
219
+	  {
220
+	    /* cli_dbgmsg("\nBREAK \n"); */
221
+	    break;
222
+	  }
223
+	  myecx_backsize+=2;
224
+	  oldback = myeax_backbytes;
225
+	  lostbit = 0;
226
+	}
227
+      } else {
228
+	/* 180 */
229
+	myecx_backsize = 1;
230
+	do {
231
+	  if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
232
+	    return -1;
233
+	  myecx_backsize = myecx_backsize*2+oob;
234
+	  if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
235
+	    return -1;
236
+	} while (oob);
237
+
238
+	myecx_backsize = myecx_backsize - 1 - lostbit;
239
+	if (! myecx_backsize) {
240
+	  /* 18a */
241
+	  myecx_backsize = 1;
242
+	  do {
243
+	    if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
244
+	      return -1;
245
+	    myecx_backsize = myecx_backsize*2+oob;
246
+	    if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
247
+	      return -1;
248
+	  } while (oob);
249
+
250
+	  myeax_backbytes = oldback;
251
+	} else {
252
+	  /* 198 */
253
+	  if (csrc >= source+ssize)
254
+	    return -1;
255
+	  myeax_backbytes = *(unsigned char*)csrc;
256
+	  myeax_backbytes += (myecx_backsize-1)<<8;
257
+	  myecx_backsize = 1;
258
+	  csrc++;
259
+	  do {
260
+	    if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
261
+	      return -1;
262
+	    myecx_backsize = myecx_backsize*2+oob;
263
+	    if ((oob=doubledl(&csrc, &mydl, source, ssize)) == -1)
264
+	      return -1;
265
+	  } while (oob);
266
+
267
+          if (myeax_backbytes >= 0x7d00)
268
+            myecx_backsize++;
269
+          if (myeax_backbytes >= 0x500)
270
+            myecx_backsize++;
271
+          if (myeax_backbytes <= 0x7f)
272
+            myecx_backsize += 2;
273
+
274
+	  oldback = myeax_backbytes;
275
+	}
276
+	lostbit = 0;
277
+      }
278
+      if (!CLI_ISCONTAINED(dest, dsize, cdst, myecx_backsize) || !CLI_ISCONTAINED(dest, dsize, cdst-myeax_backbytes, myecx_backsize))
279
+      {
280
+	cli_dbgmsg("MEW: rete: %d %d %d %d %d || %d %d %d %d %d\n", dest, dsize, cdst, myecx_backsize,
281
+			CLI_ISCONTAINED(dest, dsize, cdst, myecx_backsize),
282
+			dest, dsize, cdst-myeax_backbytes, myecx_backsize,
283
+      			CLI_ISCONTAINED(dest, dsize, cdst-myeax_backbytes, myecx_backsize) );
284
+	return -1;
285
+      }
286
+      while(myecx_backsize--) {
287
+	*cdst=*(cdst-myeax_backbytes);
288
+	cdst++;
289
+      }
290
+
291
+    } else {
292
+      /* 15d */
293
+      if (cdst < dest || cdst >= dest+dsize || csrc < source || csrc >= source+ssize)
294
+      {
295
+	cli_dbgmsg("MEW: retf %08x %08x+%08x=%08x, %08x %08x+%08x=%08x\n",
296
+			cdst, dest, dsize, dest+dsize, csrc, source, ssize, source+ssize);
297
+	return -1;
298
+      }
299
+      *cdst++=*csrc++;
300
+      /* cli_dbgmsg("Z%02x  ", *(cdst-1)&0xff); */
301
+      lostbit=1;
302
+    }
303
+  }
304
+
305
+  *endsrc = csrc;
306
+  *enddst = cdst;
307
+  return 0;
308
+}
309
+
310
+
311
+int unmew11(struct pe_image_section_hdr *section_hdr, int sectnum, char *src, int off, int ssize, int dsize, uint32_t base, uint32_t vadd, int uselzma, char **endsrc, char **enddst, int filedesc)
312
+{
313
+	uint32_t entry_point, newedi, loc_ds=dsize, loc_ss=ssize;
314
+	char *source = src + dsize + off; /*EC32(section_hdr[sectnum].VirtualSize) + off;*/
315
+	char *lesi = source + 12, *ledi;
316
+	char *f1, *f2;
317
+	int i;
318
+	struct cli_exe_section *section = NULL;
319
+	uint32_t vma = base + vadd, size_sum = ssize + dsize;
320
+
321
+	entry_point  = cli_readint32(source + 4); /* 2vGiM: ate these safe enough?
322
+						   * yup, if (EC32(section_hdr[i + 1].SizeOfRawData) < ...
323
+						   * ~line #879 in pe.c
324
+						   */
325
+	newedi = cli_readint32(source + 8);
326
+	ledi = src + (newedi - vma);
327
+
328
+	i = 0;
329
+	ssize -= 12;
330
+	while (1)
331
+	{
332
+  		cli_dbgmsg("MEW unpacking section %d (%08x->%08x)\n", i, lesi, ledi);
333
+		if (!CLI_ISCONTAINED(src, size_sum, lesi, 4) || !CLI_ISCONTAINED(src, size_sum, ledi, 4))
334
+		{
335
+			cli_dbgmsg("Possibly programmer error or hand-crafted PE file, report to clamav team\n");
336
+			return -1;
337
+		}
338
+		if (unmew(lesi, ledi, loc_ss, loc_ds, &f1, &f2))
339
+		{
340
+			free(section);
341
+			return -1;
342
+		}
343
+
344
+		/* we don't need last section in sections since this is information for fixing imptbl */
345
+		if (!CLI_ISCONTAINED(src, size_sum, f1, 4))
346
+		{
347
+			free(section);
348
+			return -1;
349
+		}
350
+
351
+		/* XXX */
352
+		loc_ss -= (f1+4-lesi);
353
+		loc_ds -= (f2-ledi);
354
+		ledi = src + (cli_readint32(f1) - vma);
355
+		lesi = f1+4;
356
+
357
+		if (!uselzma)
358
+		{
359
+			uint32_t val = f2 - src;
360
+			/* round-up to 4k boundary, I'm not sure of this XXX */
361
+			val >>= 12;
362
+			val <<= 12;
363
+			val += 0x1000;
364
+
365
+			/* eeevil XXX */
366
+			section = cli_realloc(section, (i+2)*sizeof(struct cli_exe_section));
367
+			section[0].raw = 0; section[0].rva = vadd;
368
+			section[i+1].raw = val;
369
+			section[i+1].rva = val + vadd;
370
+			section[i].rsz = section[i].vsz = i?val - section[i].raw:val;
371
+		}
372
+		i++;
373
+
374
+		if (!cli_readint32(f1))
375
+			break;
376
+	}
377
+
378
+	/* LZMA stuff */
379
+	if (uselzma) {
380
+		/* put everything in one section */
381
+		i = 1;
382
+		if (!CLI_ISCONTAINED(src, size_sum, src+uselzma+8, 1))
383
+		{
384
+			cli_dbgmsg("MEW: couldn't access lzma 'special' tag\n");
385
+			free(section);
386
+			return -1;
387
+		}
388
+		/* 0x50 -> push eax */
389
+		cli_dbgmsg("MEW: lzma %swas used, unpacking\n", (*(src + uselzma+8) == '\x50')?"special ":"");
390
+		if (!CLI_ISCONTAINED(src, size_sum, f1+4, 20 + 4 + 5))
391
+		{
392
+			cli_dbgmsg("MEW: lzma initialization data not available!\n");
393
+			free(section);
394
+			return -1;
395
+		}
396
+		if(mew_lzma(&(section_hdr[sectnum]), src, f1+4, size_sum, vma, *(src + uselzma+8) == '\x50'))
397
+		{
398
+			free(section);
399
+			return -1;
400
+		}
401
+		loc_ds >>= 12; loc_ds <<= 12; loc_ds += 0x1000;
402
+		/* I have EP but no section's information, so I weren't sure what to do with that */ /* 2vGiM: sounds fair */
403
+		section = cli_calloc(1, sizeof(struct cli_exe_section));
404
+		section[0].raw = 0; section[0].rva = vadd;
405
+		section[0].rsz = section[0].vsz = dsize;
406
+	}
407
+	if ((f1 = cli_rebuildpe(src, section, i, base, entry_point - base, 0, 0, filedesc)))
408
+	{
409
+		if (cli_writen(filedesc, f1, 0x148+0x80+0x28*i+dsize) == -1) {
410
+			free(f1);
411
+			return -1;
412
+		}
413
+	} else {
414
+		cli_dbgmsg("MEW: Rebuilding failed\n");
415
+		return -1;
416
+	}
417
+
418
+	return 1;
419
+}
420
+#endif
421
+
... ...
@@ -20,6 +20,10 @@
20 20
 #ifndef __PACKLIBS_H
21 21
 #define __PACKLIBS_H
22 22
 
23
+#include "cltypes.h"
24
+#include "rebuildpe.h"
25
+
23 26
 int cli_unfsg(char *, char *, int, int, char **, char **);
27
+int unmew11(struct pe_image_section_hdr *, int, char *, int, int, int, uint32_t, uint32_t, int, char **, char **, int);
24 28
 
25 29
 #endif
... ...
@@ -49,6 +49,9 @@
49 49
 #include "str.h"
50 50
 #include "execs.h"
51 51
 #include "md5.h"
52
+#ifdef CL_EXPERIMENTAL
53
+#include "mew.h"
54
+#endif
52 55
 
53 56
 #ifndef	O_BINARY
54 57
 #define	O_BINARY	0
... ...
@@ -1071,7 +1074,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1071 1071
 
1072 1072
     }
1073 1073
 
1074
-    /* UPX & FSG support */
1074
+    /* UPX, FSG, MEW support */
1075 1075
 
1076 1076
     /* try to find the first section with physical size == 0 */
1077 1077
     found = 0;
... ...
@@ -1079,12 +1082,167 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1079 1079
 	for(i = 0; i < (unsigned int) nsections - 1; i++) {
1080 1080
 	    if(!section_hdr[i].SizeOfRawData && section_hdr[i].VirtualSize && section_hdr[i + 1].SizeOfRawData && section_hdr[i + 1].VirtualSize) {
1081 1081
 		found = 1;
1082
-		cli_dbgmsg("UPX/FSG: empty section found - assuming compression\n");
1082
+		cli_dbgmsg("UPX/FSG/MEW: empty section found - assuming compression\n");
1083 1083
 		break;
1084 1084
 	    }
1085 1085
 	}
1086 1086
     }
1087 1087
 
1088
+
1089
+    /* MEW support */
1090
+#ifdef CL_EXPERIMENTAL
1091
+    if (found) {
1092
+	uint32_t fileoffset;
1093
+	/* Check EP for MEW */
1094
+	if(lseek(desc, ep, SEEK_SET) == -1) {
1095
+	    cli_dbgmsg("MEW: lseek() failed\n");
1096
+	    free(section_hdr);
1097
+	    return CL_EIO;
1098
+	}
1099
+
1100
+        if((bytes = read(desc, buff, 25)) != 25 && bytes < 16) {
1101
+	    cli_dbgmsg("MEW: Can't read at least 16 bytes at 0x%x (%d) %d\n", ep, ep, bytes);
1102
+	    cli_dbgmsg("MEW: Broken or not compressed file\n");
1103
+            free(section_hdr);
1104
+	    return CL_CLEAN;
1105
+	}
1106
+
1107
+	fileoffset = (vep + cli_readint32(buff + 1) + 5);
1108
+	do {
1109
+	    if (found && (buff[0] == '\xe9') && (fileoffset == 0x154 || fileoffset == 0x158))
1110
+	    {
1111
+		uint32_t offdiff, uselzma;
1112
+
1113
+		cli_dbgmsg ("MEW characteristics found: %08X + %08X + 5 = %08X\n", 
1114
+			cli_readint32(buff + 1), vep, cli_readint32(buff + 1) + vep + 5);
1115
+
1116
+		if(lseek(desc, fileoffset, SEEK_SET) == -1) {
1117
+		    cli_dbgmsg("MEW: lseek() failed\n");
1118
+		    free(section_hdr);
1119
+		    return CL_EIO;
1120
+		}
1121
+
1122
+		if((bytes = read(desc, buff, 0xb0)) != 0xb0) {
1123
+		    cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %d\n", fileoffset, fileoffset, bytes);
1124
+		    break;
1125
+		}
1126
+
1127
+		if (fileoffset == 0x154) 
1128
+		    cli_dbgmsg("MEW: Win9x compatibility was set!\n");
1129
+		else
1130
+		    cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
1131
+
1132
+		/* is it always 0x1C and 0x21C or not */
1133
+		if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= EC32(section_hdr[i + 1].VirtualAddress) || offdiff >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 4)
1134
+		{
1135
+		    cli_dbgmsg("MEW: ESI is not in proper section\n");
1136
+		    break;
1137
+		}
1138
+		offdiff -= EC32(section_hdr[i + 1].VirtualAddress);
1139
+
1140
+		if(lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET) == -1) {
1141
+		    cli_dbgmsg("MEW: lseek() failed\n"); /* ACAB: lseek won't fail here but checking doesn't hurt even */
1142
+		    free(section_hdr);
1143
+		    return CL_EIO;
1144
+		}
1145
+		ssize = EC32(section_hdr[i + 1].VirtualSize);
1146
+		dsize = EC32(section_hdr[i].VirtualSize);
1147
+
1148
+		cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff);
1149
+		if(ctx->limits && ctx->limits->maxfilesize && (ssize + dsize > ctx->limits->maxfilesize || EC32(section_hdr[i + 1].SizeOfRawData) > ctx->limits->maxfilesize)) {
1150
+		    cli_dbgmsg("MEW: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
1151
+		    free(section_hdr);
1152
+		    if(BLOCKMAX) {
1153
+			*ctx->virname = "PE.MEW.ExceededFileSize";
1154
+			return CL_VIRUS;
1155
+		    } else {
1156
+			return CL_CLEAN;
1157
+		    }
1158
+		}
1159
+
1160
+		/* allocate needed buffer */
1161
+		if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
1162
+		    free(section_hdr);
1163
+		    return CL_EMEM;
1164
+		}
1165
+
1166
+		if (EC32(section_hdr[i + 1].SizeOfRawData) < offdiff + 12 || EC32(section_hdr[i + 1].SizeOfRawData) > ssize)
1167
+		{
1168
+		    cli_dbgmsg("MEW: Size mismatch: %08x\n", EC32(section_hdr[i + 1].SizeOfRawData));
1169
+		    free(src);
1170
+		    break;
1171
+		}
1172
+
1173
+		if((bytes = read(desc, src + dsize, EC32(section_hdr[i + 1].SizeOfRawData))) != EC32(section_hdr[i + 1].SizeOfRawData)) {
1174
+		    cli_dbgmsg("MEW: Can't read %d bytes [readed: %d]\n", EC32(section_hdr[i + 1].SizeOfRawData), bytes);
1175
+		    free(section_hdr);
1176
+		    free(src);
1177
+		    return CL_EIO;
1178
+		}
1179
+		cli_dbgmsg("MEW: %d (%08x) bytes read\n", bytes, bytes);
1180
+		/* count offset to lzma proc, if lzma used, 0xe8 -> call */
1181
+		if (buff[0x7b] == '\xe8')
1182
+		{
1183
+		    if (!CLI_ISCONTAINED(EC32(section_hdr[1].VirtualAddress), EC32(section_hdr[1].VirtualSize), cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4))
1184
+		    {
1185
+			cli_dbgmsg("MEW: lzma proc out of bounds!\n");
1186
+			free(src);
1187
+			break; /* to next unpacker in chain */
1188
+		    }
1189
+		    uselzma = cli_readint32(buff + 0x7c) - (EC32(section_hdr[0].VirtualAddress) - fileoffset - 0x80);
1190
+		} else
1191
+		    uselzma = 0;
1192
+
1193
+		if(!(tempfile = cli_gentemp(NULL))) {
1194
+		    free(section_hdr);
1195
+		    free(src);
1196
+		    return CL_EMEM;
1197
+		}
1198
+		if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1199
+		    cli_dbgmsg("MEW: Can't create file %s\n", tempfile);
1200
+		    free(tempfile);
1201
+		    free(section_hdr);
1202
+		    free(src);
1203
+		    return CL_EIO;
1204
+		}
1205
+		dest = src;
1206
+		switch(unmew11(section_hdr, i, src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), EC32(section_hdr[0].VirtualAddress), uselzma, NULL, NULL, ndesc)) {
1207
+		    case 1: /* Everything OK */
1208
+			cli_dbgmsg("MEW: Unpacked and rebuilt executable saved in %s\n", tempfile);
1209
+			free(src);
1210
+			fsync(ndesc);
1211
+			lseek(ndesc, 0, SEEK_SET);
1212
+
1213
+			cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
1214
+			if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
1215
+			    free(section_hdr);
1216
+			    close(ndesc);
1217
+			    if(!cli_leavetemps_flag)
1218
+				unlink(tempfile);
1219
+			    free(tempfile);
1220
+			    return CL_VIRUS;
1221
+			}
1222
+			close(ndesc);
1223
+			if(!cli_leavetemps_flag)
1224
+			    unlink(tempfile);
1225
+			free(tempfile);
1226
+			free(section_hdr);
1227
+			return CL_CLEAN;
1228
+		    default: /* Everything gone wrong */
1229
+			cli_dbgmsg("MEW: Unpacking failed\n");
1230
+			close(ndesc);
1231
+			unlink(tempfile); /* It's empty anyway */
1232
+			free(tempfile);
1233
+			free(src);
1234
+			break;
1235
+		}
1236
+	    }
1237
+	} while (0);
1238
+    }
1239
+#endif
1240
+
1241
+
1242
+
1088 1243
     if(found) {
1089 1244
 
1090 1245
 	/* Check EP for UPX vs. FSG */