Browse code

Upack handler merged (experiemntal). MEW minor cosmetics.

git-svn: trunk@2619

aCaB authored on 2007/01/13 23:40:59
Showing 7 changed files
... ...
@@ -1,3 +1,8 @@
1
+Sat Jan 13 15:37:51 CET 2007 (acab)
2
+-----------------------------------
3
+  * libclamav: add Upack support from Michal Spadlinski <gim913 * gmail.com>
4
+  	       Part of the Google Summer of Code program
5
+
1 6
 Sat Jan 13 13:33:53 CET 2007 (tk)
2 7
 ---------------------------------
3 8
   * libclamav/scanners.c: print temp filenames in cli_scanzip() (bb#138)
... ...
@@ -97,6 +97,8 @@ libclamav_la_SOURCES = \
97 97
 	fsg.h \
98 98
 	mew.c \
99 99
 	mew.h \
100
+	upack.c \
101
+	upack.h \
100 102
 	line.c \
101 103
 	line.h \
102 104
 	untar.c \
... ...
@@ -83,7 +83,7 @@ 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
-	mew.lo line.lo untar.lo unzip.lo special.lo binhex.lo \
86
+	mew.lo upack.lo line.lo untar.lo unzip.lo special.lo binhex.lo \
87 87
 	is_tar.lo tnef.lo unrar15.lo unrarvm.lo unrar.lo \
88 88
 	unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo pdf.lo \
89 89
 	spin.lo yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \
... ...
@@ -309,6 +309,8 @@ libclamav_la_SOURCES = \
309 309
 	fsg.h \
310 310
 	mew.c \
311 311
 	mew.h \
312
+	upack.c \
313
+	upack.h \
312 314
 	line.c \
313 315
 	line.h \
314 316
 	untar.c \
... ...
@@ -506,6 +508,7 @@ distclean-compile:
506 506
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unsp.Plo@am__quote@
507 507
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/untar.Plo@am__quote@
508 508
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unzip.Plo@am__quote@
509
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upack.Plo@am__quote@
509 510
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@
510 511
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uuencode.Plo@am__quote@
511 512
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vba_extract.Plo@am__quote@
... ...
@@ -40,7 +40,6 @@
40 40
 
41 41
 #include "cltypes.h"
42 42
 #include "pe.h"
43
-#include "rebuildpe.h"
44 43
 #include "others.h"
45 44
 #include "mew.h"
46 45
 #include "packlibs.h"
... ...
@@ -335,7 +334,7 @@ uint32_t lzma_48631a (struct lzmastate *p, char **old_ecx, uint32_t *old_edx, ui
335 335
 	return 0;
336 336
 }
337 337
 
338
-//int mew_lzma(struct pe_image_section_hdr *section_hdr, char *orgsource, char *buf, uint32_t size_sum, uint32_t vma, uint32_t special)
338
+
339 339
 int mew_lzma(char *orgsource, char *buf, uint32_t size_sum, uint32_t vma, uint32_t special)
340 340
 {
341 341
 	uint32_t var08, var0C, var10, var14, var18, var20, var24, var28, var34;
... ...
@@ -762,7 +761,6 @@ uint32_t lzma_upack_esi_54(struct lzmastate *p, uint32_t old_eax, uint32_t *old_
762 762
 }
763 763
 
764 764
 
765
-//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)
766 765
 int unmew11(int sectnum, char *src, int off, int ssize, int dsize, uint32_t base, uint32_t vadd, int uselzma, char **endsrc, char **enddst, int filedesc)
767 766
 {
768 767
 	uint32_t entry_point, newedi, loc_ds=dsize, loc_ss=ssize;
... ...
@@ -845,7 +843,7 @@ int unmew11(int sectnum, char *src, int off, int ssize, int dsize, uint32_t base
845 845
 			free(section);
846 846
 			return -1;
847 847
 		}
848
-		//		if(mew_lzma(&(section_hdr[sectnum]), src, f1+4, size_sum, vma, *(src + uselzma+8) == '\x50'))
848
+
849 849
 		if(mew_lzma(src, f1+4, size_sum, vma, *(src + uselzma+8) == '\x50'))
850 850
 		{
851 851
 			free(section);
... ...
@@ -51,6 +51,7 @@
51 51
 #include "md5.h"
52 52
 #ifdef CL_EXPERIMENTAL
53 53
 #include "mew.h"
54
+#include "upack.h"
54 55
 #endif
55 56
 
56 57
 #ifndef	O_BINARY
... ...
@@ -253,7 +254,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
253 253
 	unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
254 254
 	int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
255 255
 	char *src = NULL, *dest = NULL;
256
-	int ndesc, ret = CL_CLEAN;
256
+	int ndesc, ret = CL_CLEAN, upack = 0;
257 257
 	size_t fsize;
258 258
 	uint32_t valign, falign;
259 259
 	struct cli_exe_section *exe_sections;
... ...
@@ -483,6 +484,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
483 483
 	    lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
484 484
 	}
485 485
 
486
+	upack = (EC16(file_hdr.SizeOfOptionalHeader)==0x148);
486 487
 	vep = EC32(optional_hdr32.AddressOfEntryPoint);
487 488
 	cli_dbgmsg("File format: PE\n");
488 489
 
... ...
@@ -1250,13 +1252,13 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1250 1250
 	    }
1251 1251
 	} while (0);
1252 1252
     }
1253
-#endif
1254
-
1255 1253
 
1256 1254
 
1255
+    if(found || upack) {
1256
+#else
1257 1257
     if(found) {
1258
-
1259
-	/* Check EP for UPX vs. FSG */
1258
+#endif
1259
+	/* Check EP for UPX vs. FSG vs. Upack */
1260 1260
 	if(lseek(desc, ep, SEEK_SET) == -1) {
1261 1261
 	    cli_dbgmsg("UPX/FSG: lseek() failed\n");
1262 1262
 	    free(section_hdr);
... ...
@@ -1272,6 +1274,158 @@ int cli_scanpe(int desc, cli_ctx *ctx)
1272 1272
 	    return CL_CLEAN;
1273 1273
 	}
1274 1274
 
1275
+#ifdef CL_EXPERIMENTAL
1276
+	/* Upack 0.39 produces 2 types of executables
1277
+	 * 3 sections:           | 2 sections (one empty, I don't chech found if !upack, since it's in OR above):
1278
+	 *   mov esi, value      |   pusha
1279
+	 *   lodsd               |   call $+0x9
1280
+	 *   push eax            |
1281
+	 *
1282
+	 * Upack 1.1/1.2 Beta produces [based on 2 samples (sUx) provided by aCaB]:
1283
+	 * 2 sections
1284
+	 *   mov esi, value
1285
+	 *   loads
1286
+	 *   mov edi, eax
1287
+	 *
1288
+	 * Upack unknown [sample 0297729]
1289
+	 * 3 sections
1290
+	 *   mov esi, value
1291
+	 *   push [esi]
1292
+	 *   jmp
1293
+	 * 
1294
+	 */
1295
+	/* upack 0.39-3s + sample 0151477*/
1296
+ 	if((upack && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
1297
+				buff[5] == '\xad' && buff[6] == '\x50' && /* lodsd; push eax */
1298
+				EC16(file_hdr.NumberOfSections) == 3) || /* 3 sections */
1299
+			/* based on 0297729 sample from aCaB */
1300
+			(upack && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
1301
+			 buff[5] == '\xff' && buff[6] == '\x36' && /* push [esi] */
1302
+			 EC16(file_hdr.NumberOfSections) == 3) ||
1303
+			/* upack 0.39-2s */
1304
+			(!upack && buff[0] == '\x60' && buff[1] == '\xe8' && cli_readint32(buff+2) == 0x9 && /* pusha; call+9 */
1305
+			 EC16(file_hdr.NumberOfSections) == 2) || /* 2 sections */
1306
+			/* upack 1.1/1.2, based on 2 samples */
1307
+			(!upack && buff[0] == '\xbe' && cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase) < min &&  /* mov esi */
1308
+			 cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > 0 && 
1309
+			 buff[5] == '\xad' && buff[6] == '\x8b' && buff[7] == '\xf8' && /* loads;  mov edi, eax */
1310
+			 EC16(file_hdr.NumberOfSections) == 2)) { /* 2 sections */
1311
+		uint32_t vma, off;
1312
+		int a,b,c, file;
1313
+
1314
+		cli_dbgmsg("Upack characteristics found.\n");
1315
+		a = EC32(section_hdr[0].VirtualSize);
1316
+		b = EC32(section_hdr[1].VirtualSize);
1317
+		if (upack) {
1318
+			cli_dbgmsg("upack var set\n");
1319
+			c = EC32(section_hdr[2].VirtualSize);
1320
+			ssize = EC32(section_hdr[0].SizeOfRawData) + EC32(section_hdr[0].PointerToRawData);
1321
+			off = EC32(section_hdr[0].VirtualAddress);
1322
+			vma = EC32(optional_hdr32.ImageBase) + EC32(section_hdr[0].VirtualAddress);
1323
+		} else {
1324
+			cli_dbgmsg("upack var NOT set\n");
1325
+			c = EC32(section_hdr[1].VirtualAddress);
1326
+			ssize = EC32(section_hdr[1].PointerToRawData);
1327
+			off = 0;
1328
+			vma = EC32(section_hdr[1].VirtualAddress) - EC32(section_hdr[1].PointerToRawData);
1329
+		}
1330
+
1331
+		dsize = a+b+c;
1332
+		if (ctx->limits && ctx->limits->maxfilesize && (dsize > ctx->limits->maxfilesize || ssize > ctx->limits->maxfilesize || EC32(section_hdr[1].SizeOfRawData) > ctx->limits->maxfilesize))
1333
+		{
1334
+		    cli_dbgmsg("Upack: Sizes exceeded (a: %u, b: %u, c: %ux, max: %lu)\n", a, b, c, ctx->limits->maxfilesize);
1335
+		    free(section_hdr);
1336
+		    if(BLOCKMAX) {
1337
+			*ctx->virname = "PE.Upack.ExceededFileSize";
1338
+			return CL_VIRUS;
1339
+		    } else {
1340
+			return CL_CLEAN;
1341
+		    }
1342
+		}
1343
+		/* these are unsigned so if vaddr - off < 0, it should be ok */
1344
+		if (EC32(section_hdr[1].VirtualAddress) - off > dsize || EC32(section_hdr[1].VirtualAddress) - off > dsize - EC32(section_hdr[1].SizeOfRawData) || (upack && (EC32(section_hdr[2].VirtualAddress) - EC32(section_hdr[0].VirtualAddress) > dsize || EC32(section_hdr[2].VirtualAddress) - EC32(section_hdr[0].VirtualAddress) > dsize - ssize)) || ssize > dsize)
1345
+		{
1346
+		    cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n");
1347
+		    goto skip_upack_and_go_to_next_unpacker; /* I didn't want to add additional do while + break, can it be this way ? */
1348
+		}
1349
+			
1350
+		if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1351
+		    free(section_hdr);
1352
+		    return CL_EMEM;
1353
+		}
1354
+		src = NULL;
1355
+		cli_dbgmsg("Upack: min: %08x %08x max: %08x\n", dest, a+b+c, dest+a+b+c);
1356
+	
1357
+		lseek(desc, 0, SEEK_SET);
1358
+		if(read(desc, dest, ssize) != ssize) { /* 2vGiM: i think this can be overflowed - should you check for ssize < dsize ?
1359
+		                                        * yup, I think you're right, added above
1360
+							*/
1361
+		    cli_dbgmsg("Upack: Can't read raw data of section 0\n");
1362
+		    free(section_hdr);
1363
+		    free(dest);
1364
+		    return CL_EIO;
1365
+		}
1366
+
1367
+		if (upack)
1368
+			memmove(dest + EC32(section_hdr[2].VirtualAddress) - EC32(section_hdr[0].VirtualAddress), dest, ssize);
1369
+
1370
+		lseek(desc, EC32(section_hdr[1].PointerToRawData), SEEK_SET);
1371
+
1372
+		if(read(desc, dest+EC32(section_hdr[1].VirtualAddress) - off, EC32(section_hdr[1].SizeOfRawData)) != EC32(section_hdr[1].SizeOfRawData)) {
1373
+		    cli_dbgmsg("Upack: Can't read raw data of section 1\n");
1374
+		    free(section_hdr);
1375
+		    free(dest);
1376
+		    return CL_EIO;
1377
+		}
1378
+
1379
+		if(!(tempfile = cli_gentemp(NULL)))
1380
+		    return CL_EMEM;
1381
+
1382
+		if((file = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1383
+		    cli_dbgmsg("Upack: Can't create file %s\n", tempfile);
1384
+		    free(tempfile);
1385
+		    free(section_hdr);
1386
+		    free(dest);
1387
+		    return CL_EIO;
1388
+		}
1389
+
1390
+		switch (unupack(upack, dest, dsize, buff, vma, ep, EC32(optional_hdr32.ImageBase), EC32(section_hdr[0].VirtualAddress), file))
1391
+		{
1392
+			case 1: /* Everything OK */
1393
+				cli_dbgmsg("Upack: Unpacked and rebuilt executable saved in %s\n", tempfile);
1394
+				free(dest);
1395
+				fsync(file);
1396
+				lseek(file, 0, SEEK_SET);
1397
+
1398
+				cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
1399
+				if(cli_magic_scandesc(file, ctx) == CL_VIRUS) {
1400
+					free(section_hdr);
1401
+					close(file);
1402
+					if(!cli_leavetemps_flag)
1403
+						unlink(tempfile);
1404
+					free(tempfile);
1405
+					return CL_VIRUS;
1406
+				}
1407
+
1408
+				close(file);
1409
+				if(!cli_leavetemps_flag)
1410
+					unlink(tempfile);
1411
+				free(tempfile);
1412
+				free(section_hdr);
1413
+				return CL_CLEAN;
1414
+
1415
+			default: /* Everything gone wrong */
1416
+				cli_dbgmsg("Upack: Unpacking failed\n");
1417
+				close(file);
1418
+				unlink(tempfile); /* It's empty anyway */
1419
+				free(tempfile);
1420
+				free(dest);
1421
+				break;
1422
+		}
1423
+	}
1424
+skip_upack_and_go_to_next_unpacker:
1425
+#endif
1426
+
1275 1427
 	if((DCONF & PE_CONF_FSG) && buff[0] == '\x87' && buff[1] == '\x25') {
1276 1428
 
1277 1429
 	    /* FSG v2.0 support - thanks to aCaB ! */
1278 1430
new file mode 100644
... ...
@@ -0,0 +1,676 @@
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
+ * upack.c
21
+ *
22
+ *
23
+ */
24
+
25
+#if HAVE_CONFIG_H
26
+#include "clamav-config.h"
27
+#endif
28
+
29
+#ifdef CL_EXPERIMENTAL
30
+#include <stdio.h>
31
+#include <stdlib.h>
32
+#include <sys/types.h>
33
+#include <sys/stat.h>
34
+#include <unistd.h>
35
+#include <string.h>
36
+
37
+#include "cltypes.h"
38
+#include "pe.h"
39
+#include "rebuildpe.h"
40
+#include "others.h"
41
+#include "mew.h"
42
+
43
+#define EC32(x) le32_to_host(x) /* Convert little endian to host */
44
+#define CE32(x) be32_to_host(x) /* Convert big endian to host */
45
+
46
+int unupack399(char *, uint32_t, uint32_t, char *, uint32_t, char *, char *, uint32_t, char *);
47
+
48
+enum { UPACK_399, UPACK_11_12, UPACK_0151477, UPACK_0297729 };
49
+
50
+int unupack(int upack, char *dest, uint32_t dsize, char *buff, uint32_t vma, uint32_t ep, uint32_t base, uint32_t va, int file)
51
+{
52
+	int j, searchval;
53
+	char *loc_esi, *loc_edi, *loc_ebx, *end_edi, *save_edi, *rpeb, *alvalue;
54
+	char *paddr, *pushed_esi, *save2;
55
+	uint32_t save1, save3, loc_ecx, count, shlsize, original_ep, ret, loc_ebx_u;
56
+	struct cli_exe_section section;
57
+	int upack_version = UPACK_399;
58
+
59
+	/* buff [168 bytes] doesn't have to be checked, since it was checked in pe.c */
60
+	if (upack)
61
+	{
62
+		uint32_t aljump, shroff, lngjmpoff;
63
+
64
+		/* dummy characteristics ;/ */
65
+		if (buff[5] == '\xff' && buff[6] == '\x36')
66
+			upack_version = UPACK_0297729;
67
+		loc_esi = dest + (cli_readint32(buff + 1) -  vma);
68
+
69
+		if (!CLI_ISCONTAINED(dest, dsize, loc_esi, 12))
70
+			return -1;
71
+		original_ep = cli_readint32(loc_esi);
72
+		loc_esi += 4;
73
+		/*cli_readint32(loc_esi);*/
74
+		loc_esi += 4;
75
+
76
+		original_ep -= vma;
77
+		cli_dbgmsg("Upack: EP: %08x original:  %08X || %08x\n", ep, original_ep, cli_readint32(loc_esi-8));
78
+
79
+		if (upack_version == UPACK_399)
80
+		{
81
+			/* jmp 1 */
82
+			loc_edi = dest + (cli_readint32(loc_esi) -  vma);
83
+			if (!CLI_ISCONTAINED(dest, dsize, dest+ep+0xa, 2) || dest[ep+0xa] != '\xeb')
84
+				return -1;
85
+			loc_esi = dest + *(dest + ep + 0xb) + ep + 0xc;
86
+
87
+			/* use this as a temp var */
88
+			/* jmp 2 + 0xa */
89
+			alvalue = loc_esi+0x1a;
90
+			if (!CLI_ISCONTAINED(dest, dsize, alvalue, 2) || *alvalue != '\xeb')
91
+				return -1;
92
+			alvalue++;
93
+			alvalue += (*alvalue&0xff) + 1 + 0xa;
94
+			lngjmpoff = 8;
95
+		} else {
96
+			if (!CLI_ISCONTAINED(dest, dsize, dest+ep+7, 5) || dest[ep+7] != '\xe9')
97
+				return -1;
98
+			loc_esi = dest + cli_readint32(dest + ep + 8) + ep + 0xc;
99
+			alvalue = loc_esi + 0x25;
100
+			lngjmpoff = 10;
101
+		}
102
+
103
+		if (!CLI_ISCONTAINED(dest, dsize, alvalue, 2) || *alvalue != '\xb5')
104
+			return -1;
105
+		alvalue++;
106
+		count = *alvalue&0xff;
107
+
108
+		if (!CLI_ISCONTAINED(dest, dsize, alvalue, lngjmpoff+5) || *(alvalue+lngjmpoff) != '\xe9')
109
+			return -1;
110
+		/* use this as a temp to make a long jmp to head of unpacking proc */
111
+		shlsize = cli_readint32(alvalue + lngjmpoff+1);
112
+		/* upack_399 + upack_0151477 */
113
+		if (upack_version == UPACK_399)
114
+			shlsize = shlsize + (loc_esi - dest) + *(loc_esi+0x1b) + 0x1c + 0x018; /* read checked above */
115
+		else
116
+			/* there is no additional jump in upack_0297729 */
117
+			shlsize = shlsize + (loc_esi - dest) + 0x035;
118
+		/* do the jump, 43 - point to jecxz */
119
+		alvalue = dest+shlsize+43;
120
+
121
+		/* 0.39 */
122
+		aljump = 8;
123
+		shroff = 24;
124
+		if (!CLI_ISCONTAINED(dest, dsize, alvalue-1, 2) || *(alvalue-1) != '\xe3')
125
+		{
126
+			/* in upack_0297729 and upack_0151477 jecxz is at offset: 46 */
127
+			alvalue = dest+shlsize+46;
128
+			if (!CLI_ISCONTAINED(dest, dsize, alvalue-1, 2) || *(alvalue-1) != '\xe3')
129
+				return -1;
130
+			else {
131
+				if (upack_version != UPACK_0297729)
132
+					upack_version = UPACK_0151477;
133
+				aljump = 7;
134
+				shroff = 26;
135
+			}
136
+			
137
+		}
138
+		/* do jecxz */
139
+		alvalue += (*alvalue&0xff) + 1;
140
+		/* is there a long jump ? */
141
+		if (!CLI_ISCONTAINED(dest, dsize, alvalue, aljump+5) || *(alvalue+aljump) != '\xe9')
142
+			return -1;
143
+		/* do jmp, 1+4 - size of jmp instruction, aljump - instruction offset, 27 offset to cmp al,xx*/
144
+		ret = cli_readint32(alvalue+aljump+1);
145
+		alvalue += ret + aljump+1+4 + 27;
146
+		if (upack_version == UPACK_0297729)
147
+			alvalue += 2;
148
+		/* shr ebp */
149
+		if (!CLI_ISCONTAINED(dest, dsize, dest+shlsize+shroff, 3) || *(dest+shlsize+shroff) != '\xc1' || *(dest+shlsize+shroff+1) != '\xed')
150
+			return -1;
151
+		shlsize = (*(dest + shlsize + shroff+2))&0xff;
152
+		count *= 0x100;
153
+		if (shlsize < 2 || shlsize > 8)
154
+		{
155
+			cli_dbgmsg ("Upack: context bits out of bounds\n");
156
+			return -1;
157
+		}
158
+		cli_dbgmsg("Upack: Context Bits parameter used with lzma: %02x, %02x\n", shlsize, count);
159
+		/* check if loc_esi + .. == 0xbe -> mov esi */
160
+		/* upack_0297729 has mov esi, .. + mov edi, .., in upack_0151477 and upack_399 EDI has been already set before */
161
+		if (upack_version == UPACK_0297729)
162
+		{
163
+			if (!CLI_ISCONTAINED(dest, dsize, loc_esi+6, 10) || *(loc_esi+6) != '\xbe' || *(loc_esi+11) != '\xbf')
164
+				return -1;
165
+			if (cli_readint32(loc_esi + 7) < base || cli_readint32(loc_esi+7) > vma)
166
+				return -1;
167
+			loc_edi = dest + (cli_readint32(loc_esi + 12) - vma);
168
+			loc_esi = dest + (cli_readint32(loc_esi + 7) - base);
169
+		} else {
170
+			if (!CLI_ISCONTAINED(dest, dsize, loc_esi+7, 5) || *(loc_esi+7) != '\xbe')
171
+				return -1;
172
+			loc_esi = dest + (cli_readint32(loc_esi + 8) - vma);
173
+		}
174
+
175
+		if (upack_version == UPACK_0297729)
176
+		{
177
+			/* 0x16*4=0x58, 6longs*4 = 24, 0x64-last loc_esi read location */
178
+			if (!CLI_ISCONTAINED(dest, dsize, loc_edi, (0x58 + 24 + 4*count)) || !CLI_ISCONTAINED(dest, dsize, loc_esi, (0x58 + 0x64 + 4)))
179
+				return -1;
180
+
181
+			/* XXX I don't know if this [0x16] is constant number, not enough samples provided */
182
+			for (j=0; j<0x16; j++, loc_esi+=4, loc_edi+=4)
183
+				cli_writeint32(loc_edi, cli_readint32(loc_esi)); 
184
+		} else {
185
+			/* 0x27*4=0x9c, 6longs*4 = 24, 0x34-last loc_esi read location */
186
+			if (!CLI_ISCONTAINED(dest, dsize, loc_edi, (0x9c + 24 + 4*count)) || !CLI_ISCONTAINED(dest, dsize, loc_esi, (0x9c + 0x34 + 4)))
187
+				return -1;
188
+			for (j=0; j<0x27; j++, loc_esi+=4, loc_edi+=4)
189
+				cli_writeint32(loc_edi, cli_readint32(loc_esi)); 
190
+		}
191
+		save3 = cli_readint32(loc_esi + 4);
192
+		paddr = dest + ((uint32_t)cli_readint32(loc_edi - 4)) - vma;
193
+		loc_ebx = loc_edi;
194
+		cli_writeint32(loc_edi, 0xffffffff);
195
+		loc_edi+=4;
196
+		cli_writeint32(loc_edi, 0);
197
+		loc_edi+=4;
198
+		for (j=0; j<4; j++, loc_edi+=4)
199
+		    cli_writeint32(loc_edi, (1));
200
+
201
+		for (j=0; j<count; j++, loc_edi+=4)
202
+		    cli_writeint32(loc_edi, 0x400);
203
+		
204
+		loc_edi = dest + cli_readint32(loc_esi + 0xc) - vma;
205
+		if (upack_version == UPACK_0297729)
206
+			loc_edi = dest+vma-base; /* XXX not enough samples provided to be sure of it! */
207
+
208
+		pushed_esi = loc_edi;
209
+		end_edi = dest + cli_readint32(loc_esi + 0x34) - vma;
210
+		if (upack_version == UPACK_0297729)
211
+		{
212
+			end_edi = dest + cli_readint32(loc_esi + 0x64) - vma;
213
+			save3 = cli_readint32(loc_esi + 0x40);
214
+		}
215
+		/* begin end */
216
+		cli_dbgmsg("data initialized, before upack lzma call!\n");
217
+		if ((ret = unupack399(dest, dsize, 0, loc_ebx, 0, loc_edi, end_edi, shlsize, paddr)) == -1)
218
+			return -1;
219
+	/* alternative begin */
220
+	} else {
221
+		int ep_jmp_offs, rep_stosd_count_offs, context_bits_offs;
222
+		loc_esi = dest + vma + ep;
223
+		/* yet another dummy characteristics ;/ */
224
+		if (buff[0] == '\xbe' && buff[5] == '\xad' && buff[6] == '\x8b' && buff[7] == '\xf8')
225
+			upack_version = UPACK_11_12;
226
+
227
+		if (upack_version == UPACK_11_12)
228
+		{
229
+			ep_jmp_offs = 0x1a4;
230
+			rep_stosd_count_offs = 0x1b;
231
+			context_bits_offs = 0x41;
232
+			alvalue = loc_esi + 0x184;
233
+		} else {
234
+			ep_jmp_offs = 0x217;
235
+			rep_stosd_count_offs = 0x3a;
236
+			context_bits_offs = 0x5f;
237
+			alvalue = loc_esi + 0x1c1;
238
+		}
239
+
240
+		if (!CLI_ISCONTAINED(dest, dsize, loc_esi, ep_jmp_offs+4))
241
+			return -1;
242
+		save1 = cli_readint32(loc_esi + ep_jmp_offs);
243
+		original_ep = (loc_esi - dest) + ep_jmp_offs + 4;
244
+		original_ep += (int32_t)save1;
245
+		cli_dbgmsg("Upack: EP: %08x original %08x\n", ep, original_ep);
246
+
247
+		/* this are really ugly hacks,
248
+		 * rep_stosd_count_offs & context_bits_offs are < ep_jmp_offs,
249
+		 * so checked in CLI_ISCONTAINED above */
250
+		count = (*(loc_esi + rep_stosd_count_offs))&0xff;
251
+		shlsize = (*(loc_esi + context_bits_offs))&0xff;
252
+		shlsize = 8 - shlsize;
253
+		if (shlsize < 2 || shlsize > 8)
254
+		{
255
+			cli_dbgmsg ("Upack: context bits out of bounds\n");
256
+			return -1;
257
+		}
258
+		count *= 0x100;
259
+		cli_dbgmsg("Upack: Context Bits parameter used with lzma: %02x, %02x\n", shlsize, count);
260
+		if (upack_version == UPACK_399)
261
+		{
262
+			loc_esi += 4;
263
+			loc_ecx = cli_readint32(loc_esi+2);
264
+			cli_writeint32(loc_esi+2,0);
265
+			if (!loc_ecx)
266
+			{
267
+				cli_dbgmsg("Upack: something's wrong, report back\n");
268
+				return -1;/* XXX XXX XXX XXX */
269
+			}
270
+			loc_esi -= (loc_ecx - 2);
271
+			if (!CLI_ISCONTAINED(dest, dsize, loc_esi, 12))
272
+				return -1;
273
+
274
+			cli_dbgmsg("%08x %08x %08x %08x\n", loc_esi, dest, cli_readint32(loc_esi), base);
275
+			loc_ebx_u = loc_esi - (dest + cli_readint32(loc_esi) - base);
276
+			cli_dbgmsg("EBX: %08x\n", loc_ebx_u);
277
+			loc_esi += 4;
278
+			save2 = loc_edi = dest + cli_readint32(loc_esi) - base;
279
+			cli_dbgmsg("DEST: %08x, %08x\n", cli_readint32(loc_esi), cli_readint32(loc_esi) - base);
280
+			loc_esi += 4;
281
+			/* 2vGiM: j is signed. Is that really what you want? Will it cause problems with the following checks?
282
+			 * yes! this is wrong! how did you notice that?!
283
+			 */
284
+			j = cli_readint32(loc_esi);
285
+			if (j<0)
286
+			{
287
+				cli_dbgmsg("Upack: probably hand-crafted data, report back\n");
288
+				return -1;
289
+			}
290
+			loc_esi += 4;
291
+			cli_dbgmsg("ecx counter: %08x\n", j);
292
+
293
+			if (!CLI_ISCONTAINED(dest, dsize, loc_esi, (j*4)) || !CLI_ISCONTAINED(dest, dsize, loc_edi, ((j+count)*4)))
294
+				return -1;
295
+			for (;j--; loc_edi+=4, loc_esi+=4)
296
+				cli_writeint32(loc_edi, cli_readint32(loc_esi));
297
+			if (!CLI_ISCONTAINED(dest, dsize, save2, 8))
298
+				return -1;
299
+			loc_ecx = cli_readint32(save2);
300
+			save2 += 4;
301
+			loc_esi = save2;
302
+			/* I could probably do simple loc_esi+= (0xe<<2),
303
+			 *  but I'm not sure if there is always 0xe and is always ebx =0
304
+			 */
305
+			do {
306
+				loc_esi += loc_ebx_u;
307
+				loc_esi += 4;
308
+			} while (--loc_ecx);
309
+			if (!CLI_ISCONTAINED(dest, dsize, loc_esi, 4))
310
+				return -1;
311
+			save1 = cli_readint32(loc_esi); /* loc_eax = 0x400 */
312
+			loc_esi += 4;
313
+
314
+			for (j=0; j<count; j++, loc_edi+=4) /* checked above */
315
+				cli_writeint32(loc_edi, (save1));
316
+
317
+			if (!CLI_ISCONTAINED(dest, dsize, (loc_esi+0x10), 4))
318
+				return -1;
319
+			cli_writeint32(loc_esi+0x10, (uint32_t)cli_readint32(loc_esi+0x10)+loc_ebx_u);
320
+			loc_ebx = loc_esi+0x14;
321
+			loc_esi = save2;
322
+			/* loc_ebx_u gets saved */
323
+			/* checked above, (...save2, 8) */
324
+			save_edi = loc_edi = dest + ((uint32_t)cli_readint32(loc_esi) - base);
325
+			loc_esi +=4;
326
+			cli_dbgmsg("before_fixing\n");
327
+			/* fix values */
328
+			if (!CLI_ISCONTAINED(dest, dsize, loc_ebx-4, (12 + 4*4)) || !CLI_ISCONTAINED(dest, dsize, loc_esi+0x24, 4) || !CLI_ISCONTAINED(dest, dsize, loc_esi+0x40, 4))
329
+				return -1;
330
+			for (j=2; j<6; j++)
331
+			      cli_writeint32(loc_ebx+(j<<2), cli_readint32(loc_ebx+(j<<2)));
332
+			paddr = dest + cli_readint32(loc_ebx - 4) - base;
333
+			save1 = loc_ecx;
334
+			pushed_esi = loc_edi;
335
+			end_edi = dest + cli_readint32(loc_esi+0x24) - base;
336
+			vma = cli_readint32(loc_ebx); cli_writeint32(loc_ebx, cli_readint32(loc_ebx + 4)); cli_writeint32((loc_ebx + 4), vma);
337
+		/* Upack 1.1/1.2 is something between 0.39 2-section and 0.39 3-section */
338
+		} else if (upack_version == UPACK_11_12) {
339
+			cli_dbgmsg("Upack v 1.1/1.2\n");
340
+			loc_esi = dest + 0x148; /* always constant? */
341
+			loc_edi = dest + cli_readint32(loc_esi) - base; /* read checked above */
342
+			loc_esi += 4;
343
+			save_edi = loc_edi;
344
+			/* movsd */
345
+			paddr = dest + ((uint32_t)cli_readint32(loc_esi)) - base;
346
+			loc_esi += 4;
347
+			loc_edi += 4;
348
+			loc_ebx = loc_edi;
349
+		
350
+			if (!CLI_ISCONTAINED(dest, dsize, loc_edi, ((6+count)*4)))
351
+				return -1;
352
+			cli_writeint32(loc_edi, 0xffffffff);
353
+			loc_edi += 4;
354
+			cli_writeint32(loc_edi, 0);
355
+			loc_edi += 4;
356
+			for (j=0; j<4; j++, loc_edi+=4)
357
+				cli_writeint32(loc_edi, (1));
358
+
359
+			for (j=0; j<count; j++, loc_edi+=4)
360
+				cli_writeint32(loc_edi, 0x400);
361
+			
362
+			loc_edi = dest + cli_readint32(loc_esi) - base; /* read checked above */
363
+			pushed_esi = loc_edi;
364
+			loc_esi += 4;
365
+			loc_ecx = 0;
366
+
367
+			loc_esi += 4;
368
+
369
+			end_edi = dest + cli_readint32(loc_esi-0x28) - base; /* read checked above */
370
+			loc_esi = save_edi;
371
+		}
372
+		cli_dbgmsg("data initialized, before upack lzma call!\n");
373
+		if ((ret = unupack399(dest, dsize, loc_ecx, loc_ebx, loc_ecx, loc_edi, end_edi, shlsize, paddr)) == -1)
374
+			return -1;
375
+		if (upack_version == UPACK_399)
376
+			save3 = cli_readint32(loc_esi + 0x40);
377
+		else if (upack_version == UPACK_11_12)
378
+			save3 = cli_readint32(dest + vma + ep + 0x174);
379
+	}
380
+
381
+	/* let's fix calls */
382
+	loc_ecx = 0;
383
+	searchval = *alvalue&0xff;
384
+	cli_dbgmsg("Upack: loops: %08x search value: %02x\n", save3, searchval);
385
+	while(save3) {
386
+		if (!CLI_ISCONTAINED(dest, dsize, pushed_esi + loc_ecx, 1))
387
+		{
388
+			cli_dbgmsg("callfixerr %08x %08x = %08x, %08x\n", dest, dsize, dest+dsize, pushed_esi+loc_ecx);
389
+			return -1;
390
+		}
391
+		if (pushed_esi[loc_ecx] == '\xe8' || pushed_esi[loc_ecx] == '\xe9')
392
+		{
393
+			char *adr = (pushed_esi + loc_ecx + 1);
394
+			loc_ecx++;
395
+			if (!CLI_ISCONTAINED(dest, dsize, adr, 4))
396
+			{
397
+				cli_dbgmsg("callfixerr\n");
398
+				return -1;
399
+			}
400
+			if ((cli_readint32(adr)&0xff) != searchval)
401
+				continue;
402
+			cli_writeint32(adr, EC32(CE32((uint32_t)(cli_readint32(adr)&0xffffff00)))-loc_ecx-4);
403
+			loc_ecx += 4;
404
+			save3--;
405
+		} else 
406
+			loc_ecx++;
407
+	}
408
+
409
+	section.raw = 0;
410
+	section.rva = va;
411
+	section.rsz = end_edi-loc_edi;
412
+	section.vsz = end_edi-loc_edi;
413
+
414
+	if (!cli_rebuildpe(dest + (upack?0:va), &section, 1, base, original_ep, 0, 0, file)) {
415
+		cli_dbgmsg("Upack: Rebuilding failed\n");
416
+		return 0;
417
+	}
418
+	return 1;
419
+}
420
+
421
+
422
+int unupack399(char *bs, uint32_t bl, uint32_t init_eax, char *init_ebx, uint32_t init_ecx, char *init_edi, char *end_edi, uint32_t shlsize, char *paddr)
423
+{
424
+	struct lzmastate p;
425
+	uint32_t loc_eax, ret, loc_al, loc_ecx = init_ecx, loc_ebp, eax_copy = init_eax, temp, i, jakas_kopia;
426
+	uint32_t state[6], temp_ebp;
427
+	char *loc_edx, *loc_ebx = init_ebx, *loc_edi = init_edi, *loc_ebp8, *edi_copy;
428
+	p.p0 = paddr;
429
+	p.p1 = cli_readint32(init_ebx);
430
+	p.p2 = cli_readint32(init_ebx + 4);
431
+
432
+	cli_dbgmsg("\n\tp0: %08x\n\tp1: %08x\n\tp2: %08x\n", p.p0, p.p1, p.p2);
433
+	for (i = 0; i<6; i++)
434
+		state[i] = cli_readint32(loc_ebx + (i<<2)),
435
+		cli_dbgmsg("state[%d] = %08x\n", i, state[i]);
436
+	do {
437
+		loc_eax = eax_copy;
438
+		loc_edx = loc_ebx + (loc_eax<<2) + 0x58;
439
+
440
+		if ((ret = lzma_upack_esi_00(&p, loc_edx, bs, bl)))
441
+		{
442
+			/* loc_483927 */
443
+			loc_al = loc_eax&0xff;
444
+			loc_al = ((loc_al + 0xf9) > 0xff)?(3+8):8;
445
+			loc_eax = (loc_eax&0xffffff00)|(loc_al&0xff);
446
+			loc_ebp = state[2];
447
+			loc_ecx = (loc_ecx&0xffffff00)|0x30;
448
+			loc_edx += loc_ecx;
449
+			/* *(uint32_t *)(loc_ebx + 14) = loc_ebp; ???? */
450
+			if (!(ret = lzma_upack_esi_00(&p, loc_edx, bs, bl))) {
451
+				/* loc_48397c */
452
+				loc_eax--;
453
+				/*
454
+				temp_ebp = loc_ebp; loc_ebp = cli_readint32(loc_ebx+0x0c); cli_writeint32(loc_ebx+0x0c, temp_ebp);
455
+				temp_ebp = loc_ebp; loc_ebp = cli_readint32(loc_ebx+0x10); cli_writeint32(loc_ebx+0x10, temp_ebp);
456
+				*/
457
+				temp_ebp = loc_ebp;
458
+				loc_ebp = state[4];
459
+				state[4] = state[3];
460
+				state[3] = temp_ebp;
461
+				eax_copy = loc_eax;
462
+				loc_edx = loc_ebx + 0xbc0;
463
+				state[5] = loc_ebp;
464
+				if (lzma_upack_esi_54(&p, loc_eax, &loc_ecx, &loc_edx, &temp, bs, bl) == -1)
465
+					return -1;
466
+				loc_ecx = 3;
467
+				jakas_kopia = temp;
468
+				loc_eax = temp-1;
469
+				if (loc_eax >= loc_ecx)
470
+					loc_eax = loc_ecx;
471
+				loc_ecx = 0x40;
472
+				loc_eax <<= 6; /* ecx=0x40, mul cl */
473
+				loc_ebp8 = loc_ebx + ((loc_eax<<2) + 0x378);
474
+				if (lzma_upack_esi_50(&p, 1, loc_ecx, &loc_edx, loc_ebp8, &loc_eax, bs, bl) == -1)
475
+					return -1;
476
+				loc_ebp = loc_eax;
477
+				if ((loc_eax&0xff) >= 4)
478
+				{
479
+					/* loc_4839af */
480
+					loc_ebp = 2 + (loc_eax&1);
481
+					loc_eax >>= 1;
482
+					loc_eax--;
483
+					temp_ebp = loc_eax; loc_eax = loc_ecx; loc_ecx = temp_ebp;
484
+					loc_ebp <<= (loc_ecx&0xff);
485
+					loc_edx = loc_ebx + (loc_ebp<<2) + 0x178;
486
+					if ((loc_ecx&0xff) > 5)
487
+					{
488
+						/* loc_4839c6 */
489
+						loc_ecx = (loc_ecx&0xffffff00)|(((loc_ecx&0xff)-4)&0xff);
490
+						loc_eax = 0;
491
+						do {
492
+							uint32_t temp_edx;
493
+							/* compare with lzma_upack_esi_00 */
494
+							/* do not put in one statment because of difference in signedness */
495
+							if (!CLI_ISCONTAINED(bs, bl, p.p0, 4))
496
+								return -1;
497
+							temp_edx = cli_readint32((char *)p.p0);
498
+							temp_edx = EC32(CE32(temp_edx));
499
+							p.p1 >>= 1;
500
+							temp_edx -= p.p2;
501
+							loc_eax <<= 1;
502
+							if (temp_edx >= p.p1)
503
+							{
504
+								temp_edx = p.p1;
505
+								loc_eax++;
506
+								p.p2 += temp_edx;
507
+							}
508
+							if(((p.p1)&0xff000000) == 0)
509
+							{
510
+								p.p2 <<= 8;
511
+								p.p1 <<= 8;
512
+								p.p0++;
513
+							}
514
+						} while (--loc_ecx);
515
+						/* loc_4839e8 */
516
+						loc_ecx = (loc_ecx&0xffffff00)|4;
517
+						loc_eax <<= 4;
518
+						loc_ebp += loc_eax;
519
+						loc_edx = loc_ebx + 0x18;
520
+					}
521
+					/* loc4839f1 */
522
+					loc_eax = 1;
523
+					loc_eax <<= (loc_ecx&0xff);
524
+					loc_ebp8 = loc_edx;
525
+					temp_ebp = loc_ecx; loc_ecx = loc_eax; loc_eax = temp_ebp;
526
+					if (lzma_upack_esi_50(&p, 1, loc_ecx, &loc_edx, loc_ebp8, &loc_eax, bs, bl) == -1)
527
+						return -1;
528
+					/* cdq, loc_edx = (loc_eax&0x80000000)?0xffffffff:0; */
529
+					loc_ecx = temp_ebp;
530
+					temp_ebp = (int32_t)loc_eax >> 31; /* thx, desp */
531
+					/* loc_483a00 */
532
+					do {
533
+						temp_ebp += temp_ebp;
534
+						temp_ebp += (loc_eax&1);
535
+						loc_eax >>= 1;
536
+					} while (--loc_ecx);
537
+					loc_ebp += temp_ebp;
538
+					/* loc_483a06 */
539
+				}
540
+				/* loc_483a09 */
541
+				loc_ebp++;
542
+				loc_ecx = jakas_kopia;
543
+			} else {
544
+				/* loc_48393a */
545
+				loc_edx += loc_ecx;
546
+				if ((ret = lzma_upack_esi_00(&p, loc_edx, bs, bl))) {
547
+					/* loc_483954 */
548
+					loc_edx += 0x60;
549
+					if ((ret = lzma_upack_esi_00(&p, loc_edx, bs, bl))) {
550
+						/* loc_48395e */
551
+						loc_edx += loc_ecx;
552
+						ret = lzma_upack_esi_00(&p, loc_edx, bs, bl);
553
+						temp_ebp = loc_ebp;
554
+						loc_ebp = state[4];
555
+						state[4] = state[3];
556
+						state[3] = temp_ebp;
557
+						if (ret)
558
+						{
559
+							temp_ebp = loc_ebp; loc_ebp = state[5]; state[5] = temp_ebp;
560
+						}
561
+					} else {
562
+						temp_ebp = loc_ebp; loc_ebp = state[3]; state[3] = temp_ebp;
563
+					}
564
+				} else {
565
+					/* loc_483940 */
566
+					loc_edx += loc_ecx;
567
+					if ((ret = lzma_upack_esi_00(&p, loc_edx, bs, bl))) {
568
+					} else {
569
+						/* loc_483946 */
570
+						loc_eax |= 1;
571
+						eax_copy = loc_eax;
572
+						edi_copy = loc_edi;
573
+						edi_copy -= state[2];
574
+						loc_ecx = (loc_ecx&0xffffff00)|0x80;
575
+						if (!CLI_ISCONTAINED(bs, bl, edi_copy, 1) || !CLI_ISCONTAINED(bs, bl, loc_edi, 1))
576
+							return -1;
577
+						loc_al = (*(uint8_t *)edi_copy)&0xff;
578
+						/* loc_483922 */
579
+						/* ok jmp to 483a19 */
580
+						/* loc_483a19 */
581
+						*loc_edi++ = loc_al;
582
+						continue;
583
+					}
584
+				}
585
+				/* loc_48396a */
586
+				eax_copy = loc_eax;
587
+				loc_edx = loc_ebx + 0x778;
588
+				if (lzma_upack_esi_54(&p, loc_eax, &loc_ecx, &loc_edx, &temp, bs, bl) == -1)
589
+					return -1;
590
+				loc_eax = loc_ecx;
591
+				loc_ecx = temp;
592
+			}
593
+			/* loc_483a0b */
594
+			if (!CLI_ISCONTAINED(bs, bl, loc_edi, loc_ecx) || !CLI_ISCONTAINED(bs, bl, loc_edi-loc_ebp, loc_ecx+1))
595
+				return -1;
596
+			state[2] = loc_ebp;
597
+			for (i=0; i<loc_ecx; i++, loc_edi++)
598
+				*loc_edi = *(loc_edi - loc_ebp);
599
+			loc_eax = (loc_eax&0xffffff00)|*(uint8_t *)(loc_edi - loc_ebp);
600
+			loc_ecx = 0x80;
601
+		} else {
602
+			/* loc_4838d8 */
603
+			do {
604
+				if ( (loc_al = (loc_eax&0xff)) + 0xfd > 0xff)
605
+					loc_al -= 3; /* 0x100 - 0xfd = 3 */
606
+				else
607
+					loc_al = 0;
608
+				loc_eax = (loc_eax&0xffffff00)|loc_al;
609
+			} while (loc_al >= 7);
610
+			/* loc_4838e2 */
611
+			eax_copy = loc_eax;
612
+			if (loc_edi > init_edi && loc_edi < bl+bs)
613
+			{
614
+				loc_ebp = (*(uint8_t *)(loc_edi - 1)) >> shlsize;
615
+			} else {
616
+				loc_ebp = 0;
617
+			}
618
+			loc_ebp *= (int)0x300; /* XXX */
619
+			loc_ebp8 = loc_ebx + ((loc_ebp<<2) + 0x1008);
620
+			/* XXX save edi */
621
+			edi_copy = loc_edi;
622
+
623
+			loc_eax = (loc_eax&0xffffff00)|1;
624
+			if (loc_ecx) {
625
+				uint8_t loc_cl = loc_ecx&0xff;
626
+				loc_edi -= state[2];
627
+				if (!CLI_ISCONTAINED(bs, bl, loc_edi, 1))
628
+					return -1;
629
+				do {
630
+					loc_eax = (loc_eax&0xffff00ff)|((*loc_edi & loc_cl)?0x200:0x100);
631
+
632
+					loc_edx = loc_ebp8 + (loc_eax<<2);
633
+					ret = lzma_upack_esi_00(&p, loc_edx, bs, bl);
634
+					loc_al = loc_eax&0xff;
635
+					loc_al += loc_al;
636
+					loc_al += ret;
637
+					loc_al &= 0xff;
638
+					loc_eax = (loc_eax&0xffffff00)|loc_al;
639
+					loc_cl >>= 1;
640
+					if (loc_cl) {
641
+						uint8_t loc_ah = (loc_eax>>8)&0xff;
642
+						loc_ah -= loc_al;
643
+						loc_ah &= 1;
644
+						if (!loc_ah)
645
+						{
646
+							loc_eax = (loc_eax&0xffff0000)|(loc_ah<<8)|loc_al;
647
+							/* loc_483918, loc_48391a */
648
+							if (lzma_upack_esi_50(&p, loc_eax, 0x100, &loc_edx, loc_ebp8, &loc_eax, bs, bl) == -1)
649
+								return -1;
650
+							break;
651
+						}
652
+					} else
653
+						break;
654
+				} while(1);
655
+			} else {
656
+				/* loc_48391a */
657
+				loc_ecx = (loc_ecx&0xffff00ff)|0x100;
658
+				if (lzma_upack_esi_50(&p, loc_eax, loc_ecx, &loc_edx, loc_ebp8, &loc_eax, bs, bl) == -1)
659
+					return -1;
660
+			}
661
+			/* loc_48391f */
662
+			loc_ecx = 0;
663
+			loc_edi = edi_copy;
664
+		}
665
+		/* loc_483a19 */
666
+		/* 2GiM: i think this one is not properly checked, 2aCaB: true */
667
+		if (!CLI_ISCONTAINED(bs, bl, loc_edi, 1))
668
+			return -1;
669
+		*loc_edi++ = (loc_eax&0xff);
670
+	} while (loc_edi < end_edi);
671
+
672
+	return 1;
673
+}
674
+
675
+#endif
0 676
new file mode 100644
... ...
@@ -0,0 +1,31 @@
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 __UPACK_H
20
+#define __UPACK_H
21
+
22
+#if HAVE_CONFIG_H
23
+#include "clamav-config.h"
24
+#endif
25
+
26
+#ifdef CL_EXPERIMENTAL
27
+int unupack(int, char *, uint32_t, char *, uint32_t, uint32_t, uint32_t, uint32_t, int);
28
+
29
+#endif
30
+#endif