Browse code

UPX decompression

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@601 77e5149b-7576-45b1-b177-96237e5ba77b

Tomasz Kojm authored on 2004/06/12 09:16:01
Showing 6 changed files
... ...
@@ -1,3 +1,11 @@
1
+Sat Jun 12 02:11:12 CEST 2004 (tk)
2
+----------------------------------
3
+  * libclamav: pe: integrate with UPX decompressor from aCaB <acab*clamav.net>
4
+	           (with support for NRV2B, NRV2D and NRV2E compression).
5
+		   To protect against compressed files with hacked headers,
6
+		   the PE parser tries to find a signature of the UPX
7
+		   decompression routine at EP + 0x78.
8
+
1 9
 Fri Jun 11 22:11:31 CEST 2004 (tk)
2 10
 ----------------------------------
3 11
   * libclamav: pe: add dumper; RVA calculation; fix error codes
... ...
@@ -94,6 +94,8 @@ libclamav_la_SOURCES = \
94 94
 	mspack/qtmd.c \
95 95
 	mspack/qtm.h \
96 96
 	mspack/system.c \
97
-	mspack/system.h
97
+	mspack/system.h \
98
+	upx.c \
99
+	upx.h
98 100
 
99 101
 lib_LTLIBRARIES = libclamav.la
... ...
@@ -1,4 +1,4 @@
1
-# Makefile.in generated by automake 1.6.3 from Makefile.am.
1
+# Makefile.in generated by automake 1.6.1 from Makefile.am.
2 2
 # @configure_input@
3 3
 
4 4
 # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
... ...
@@ -66,7 +66,6 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
66 66
 INSTALL_DATA = @INSTALL_DATA@
67 67
 install_sh_DATA = $(install_sh) -c -m 644
68 68
 install_sh_PROGRAM = $(install_sh) -c
69
-install_sh_SCRIPT = $(install_sh) -c
70 69
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
71 70
 INSTALL_HEADER = $(INSTALL_DATA)
72 71
 transform = @program_transform_name@
... ...
@@ -196,7 +195,9 @@ libclamav_la_SOURCES = \
196 196
 	mspack/qtmd.c \
197 197
 	mspack/qtm.h \
198 198
 	mspack/system.c \
199
-	mspack/system.h
199
+	mspack/system.h \
200
+	upx.c \
201
+	upx.h
200 202
 
201 203
 
202 204
 lib_LTLIBRARIES = libclamav.la
... ...
@@ -212,7 +213,7 @@ am_libclamav_la_OBJECTS = matcher.lo md5.lo others.lo readdb.lo cvd.lo \
212 212
 	zzip-file.lo zzip-info.lo zzip-io.lo zzip-stat.lo zzip-zip.lo \
213 213
 	strc.lo blob.lo mbox.lo message.lo snprintf.lo strrcpy.lo \
214 214
 	table.lo text.lo ole2_extract.lo vba_extract.lo msexpand.lo \
215
-	pe.lo cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo
215
+	pe.lo cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo
216 216
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
217 217
 
218 218
 DEFS = @DEFS@
... ...
@@ -234,7 +235,7 @@ am__depfiles_maybe = depfiles
234 234
 @AMDEP_TRUE@	./$(DEPDIR)/str.Plo ./$(DEPDIR)/strc.Plo \
235 235
 @AMDEP_TRUE@	./$(DEPDIR)/strrcpy.Plo ./$(DEPDIR)/system.Plo \
236 236
 @AMDEP_TRUE@	./$(DEPDIR)/table.Plo ./$(DEPDIR)/text.Plo \
237
-@AMDEP_TRUE@	./$(DEPDIR)/unrarlib.Plo \
237
+@AMDEP_TRUE@	./$(DEPDIR)/unrarlib.Plo ./$(DEPDIR)/upx.Plo \
238 238
 @AMDEP_TRUE@	./$(DEPDIR)/vba_extract.Plo \
239 239
 @AMDEP_TRUE@	./$(DEPDIR)/zzip-dir.Plo ./$(DEPDIR)/zzip-err.Plo \
240 240
 @AMDEP_TRUE@	./$(DEPDIR)/zzip-file.Plo ./$(DEPDIR)/zzip-info.Plo \
... ...
@@ -285,12 +286,6 @@ uninstall-libLTLIBRARIES:
285 285
 
286 286
 clean-libLTLIBRARIES:
287 287
 	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
288
-	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
289
-	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
290
-	  test -z "$dir" && dir=.; \
291
-	  echo "rm -f \"$${dir}/so_locations\""; \
292
-	  rm -f "$${dir}/so_locations"; \
293
-	done
294 288
 zzip-dir.lo: zziplib/zzip-dir.c
295 289
 zzip-err.lo: zziplib/zzip-err.c
296 290
 zzip-file.lo: zziplib/zzip-file.c
... ...
@@ -338,6 +333,7 @@ distclean-compile:
338 338
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@
339 339
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@
340 340
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarlib.Plo@am__quote@
341
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@
341 342
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vba_extract.Plo@am__quote@
342 343
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-dir.Plo@am__quote@
343 344
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-err.Plo@am__quote@
... ...
@@ -672,7 +668,7 @@ top_distdir = ..
672 672
 distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
673 673
 
674 674
 distdir: $(DISTFILES)
675
-	@list='$(DISTFILES)'; for file in $$list; do \
675
+	@for file in $(DISTFILES); do \
676 676
 	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
677 677
 	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
678 678
 	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
... ...
@@ -718,7 +714,7 @@ mostlyclean-generic:
718 718
 clean-generic:
719 719
 
720 720
 distclean-generic:
721
-	-rm -f Makefile $(CONFIG_CLEAN_FILES)
721
+	-rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
722 722
 
723 723
 maintainer-clean-generic:
724 724
 	@echo "This command is intended for maintainers to use"
... ...
@@ -35,11 +35,16 @@
35 35
 #include "cltypes.h"
36 36
 #include "clamav.h"
37 37
 #include "others.h"
38
+#include "upx.h"
38 39
 
39 40
 #define IMAGE_DOS_SIGNATURE	    0x5a4d	    /* MZ */
40 41
 #define IMAGE_NT_SIGNATURE	    0x00004550
41 42
 #define IMAGE_OPTIONAL_SIGNATURE    0x010b
42 43
 
44
+#define UPX_NRV2B "\x11\xc9\x75\x20\x41\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x73\xef\x75\x09"
45
+#define UPX_NRV2D "\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x75\x20"
46
+#define UPX_NRV2E "\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x72\xcc"
47
+
43 48
 struct pe_image_file_hdr {
44 49
     uint32_t Magic;
45 50
     uint16_t Machine;
... ...
@@ -109,7 +114,6 @@ struct pe_image_section_hdr {
109 109
     uint32_t Characteristics;
110 110
 };
111 111
 
112
-
113 112
 static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos)
114 113
 {
115 114
 	int i, found = 0;
... ...
@@ -140,19 +144,19 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
140 140
 
141 141
     if((pos = lseek(desc, 0, SEEK_CUR)) == -1) {
142 142
 	cli_dbgmsg("Invalid descriptor\n");
143
-	return -1;
143
+	return CL_EIO;
144 144
     }
145 145
 
146 146
     if(lseek(desc, offset, SEEK_SET) == -1) {
147 147
 	cli_dbgmsg("lseek() failed\n");
148 148
 	lseek(desc, pos, SEEK_SET);
149
-	return -1;
149
+	return CL_EIO;
150 150
     }
151 151
 
152 152
     if((ndesc = open(file, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
153 153
 	cli_dbgmsg("Can't create file %s\n", file);
154 154
 	lseek(desc, pos, SEEK_SET);
155
-	return -1;
155
+	return CL_EIO;
156 156
     }
157 157
 
158 158
     while((bread = read(desc, buff, FILEBUFF)) > 0) {
... ...
@@ -162,7 +166,7 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
162 162
 		lseek(desc, pos, SEEK_SET);
163 163
 		close(ndesc);
164 164
 		unlink(file);
165
-		return -1;
165
+		return CL_EIO;
166 166
 	    }
167 167
 	    break;
168 168
 	} else {
... ...
@@ -171,7 +175,7 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
171 171
 		lseek(desc, pos, SEEK_SET);
172 172
 		close(ndesc);
173 173
 		unlink(file);
174
-		return -1;
174
+		return CL_EIO;
175 175
 	    }
176 176
 	}
177 177
 	sum += bread;
... ...
@@ -191,8 +195,9 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
191 191
 	struct pe_image_optional_hdr optional_hdr;
192 192
 	struct pe_image_section_hdr *section_hdr;
193 193
 	struct stat sb;
194
-	char sname[9];
195
-	int i;
194
+	char sname[9], buff[24], *tempfile;
195
+	int i, found;
196
+	int (*upxfn)(char *, int , char *, int) = NULL;
196 197
 
197 198
 
198 199
     if(read(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
... ...
@@ -321,8 +326,9 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
321 321
 
322 322
 	if(read(desc, &section_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) {
323 323
 	    cli_dbgmsg("Can't read section header\n");
324
+	    cli_warnmsg("Possibly broken PE file\n");
324 325
 	    free(section_hdr);
325
-	    return -1;
326
+	    return CL_CLEAN;
326 327
 	}
327 328
 
328 329
 	strncpy(sname, section_hdr[i].Name, 8);
... ...
@@ -364,7 +370,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
364 364
     if(fstat(desc, &sb) == -1) {
365 365
 	cli_dbgmsg("fstat failed\n");
366 366
 	free(section_hdr);
367
-	return -1;
367
+	return CL_EIO;
368 368
     }
369 369
 
370 370
     ep = cli_rawaddr(optional_hdr.AddressOfEntryPoint, section_hdr, file_hdr.NumberOfSections);
... ...
@@ -372,13 +378,114 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
372 372
     if(section_hdr[i].PointerToRawData + section_hdr[i].SizeOfRawData > sb.st_size || ep == -1) {
373 373
 	cli_warnmsg("Possibly broken PE file\n");
374 374
 	free(section_hdr);
375
-	return -1;
375
+	return CL_CLEAN;
376 376
     }
377 377
 
378
-    cli_dbgmsg("EntryPoint: 0x%x (%d)\n", ep, ep);
378
+    cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
379
+
380
+    if(lseek(desc, ep + 0x78, SEEK_SET) == -1) {
381
+	cli_dbgmsg("lseek() failed\n");
382
+	free(section_hdr);
383
+	return CL_EIO;
384
+    }
385
+
386
+    if(read(desc, buff, 24) != 24) {
387
+	cli_dbgmsg("Can't read 24 bytes at 0x%x (%d)\n", ep + 0x78, ep + 0x78);
388
+    } else {
389
+	if(!memcmp(buff, UPX_NRV2B, 24)) {
390
+	    cli_dbgmsg("UPX: NRV2B decompressor detected\n");
391
+	    upxfn = upx_inflate2b;
392
+	} else if(!memcmp(buff, UPX_NRV2D, 24)) {
393
+	    cli_dbgmsg("UPX: NRV2D decompressor detected\n");
394
+	    upxfn = upx_inflate2d;
395
+	} else if(!memcmp(buff, UPX_NRV2E, 24)) {
396
+            cli_dbgmsg("UPX: NRV2E decompressor detected\n");
397
+	    upxfn = upx_inflate2e;
398
+	}
399
+    }
400
+
401
+    if(upxfn) {
402
+	/* try to find the first section with physical size == 0 */
403
+	found = 0;
404
+	for(i = 0; i < file_hdr.NumberOfSections; i++) {
405
+	    if(!section_hdr[i].SizeOfRawData) {
406
+		found = 1;
407
+		break;
408
+	    }
409
+	}
410
+
411
+	if(found) {
412
+		uint32_t ssize, dsize;
413
+		char *src, *dest;
414
+
415
+	    /* we assume (i + 1) is UPX1 */
416
+	    if(strncmp(section_hdr[i].Name, "UPX0", 4) || strncmp(section_hdr[i + 1].Name, "UPX1", 4))
417
+		cli_dbgmsg("Possibly hacked UPX section headers\n");
418
+
419
+	    /* FIXME: use file operations in case of big files */
420
+	    ssize = section_hdr[i + 1].SizeOfRawData;
421
+	    dsize = section_hdr[i].VirtualSize + section_hdr[i + 1].VirtualSize;
422
+	    if((src = (char *) malloc(ssize)) == NULL) {
423
+		free(section_hdr);
424
+		return CL_EMEM;
425
+	    }
426
+
427
+	    if((dest = (char *) malloc(dsize)) == NULL) {
428
+		free(section_hdr);
429
+		free(src);
430
+		return CL_EMEM;
431
+	    }
432
+
433
+	    lseek(desc, section_hdr[i + 1].PointerToRawData, SEEK_SET);
434
+	    if(read(desc, src, ssize) != ssize) {
435
+		cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
436
+		free(section_hdr);
437
+		free(src);
438
+		free(dest);
439
+		return CL_EMEM;
440
+	    }
441
+
442
+	    if(upxfn(src, ssize, dest, dsize)) {
443
+		cli_dbg("UPX decompression failed\n");
444
+	    } else {
445
+		    int ndesc;
446
+
447
+		tempfile = cl_gentemp(NULL);
448
+
449
+		if((ndesc = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
450
+		    cli_dbgmsg("Can't create file %s\n", tempfile);
451
+		    free(section_hdr);
452
+		    free(src);
453
+		    free(dest);
454
+		    return CL_EIO;
455
+		}
456
+
457
+		if(write(ndesc, dest, dsize) != dsize) {
458
+		    cli_dbgmsg("Can't write %d bytes\n", dsize);
459
+		    free(section_hdr);
460
+		    free(src);
461
+		    free(dest);
462
+		    return CL_EIO;
463
+		}
464
+
465
+		close(ndesc);
466
+
467
+		/* TODO: scan and unlink file */
468
+
469
+		/* unlink(tempfile); */
470
+		free(tempfile);
471
+	    }
472
+
473
+	    free(src);
474
+	    free(dest);
475
+
476
+	} else {
477
+	    cli_dbgmsg("UPX sections not found\n");
478
+	}
479
+    }
379 480
 
380 481
     /* to be continued ... */
381 482
 
382 483
     free(section_hdr);
383
-    return 0;
484
+    return CL_CLEAN;
384 485
 }
385 486
new file mode 100644
... ...
@@ -0,0 +1,263 @@
0
+/*
1
+ *  Copyright (C) 2004 aCaB <acab@clamav.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
16
+ */
17
+
18
+/*
19
+** upxdec.c
20
+**
21
+** 05/05/2k4 - 1st attempt
22
+** 08/05/2k4 - Now works as a charm :D
23
+** 09/05/2k4 - Moved code outta main(), got rid of globals for thread safety, added bound checking, minor cleaning
24
+** 04/06/2k4 - Now we handle 2B, 2D and 2E :D
25
+*/
26
+
27
+/*
28
+** This code unpacks a dumped UPX1 section to a file.
29
+** It was written reversing the loader found on some Win32 UPX compressed trojans; while porting
30
+** it to C i've kinda followed the asm flow so it will probably be a bit hard to read.
31
+** This code DOES NOT revert the uncompressed section to its original state as no E8/E9 fixup and
32
+** of cause no IAT rebuild are performed.
33
+**
34
+** The Win32 asm unpacker is really a little programming jewel, pretty damn rare in these days of
35
+** bloatness. My gratitude to whoever wrote it.
36
+*/
37
+
38
+
39
+#include <stdio.h>
40
+#include <stdlib.h>
41
+#include <sys/types.h>
42
+#include <sys/stat.h>
43
+#include <unistd.h>
44
+#include <string.h>
45
+
46
+/* [doubleebx] */
47
+
48
+static int doubleebx(char *src, int *myebx, int *scur, int ssize)
49
+{
50
+  int oldebx = *myebx;
51
+
52
+  *myebx*=2;
53
+  if ( !(oldebx & 0x7fffffff)) {
54
+    if (*scur<0 || ssize-*scur<4)
55
+      return 0;
56
+    oldebx = *(int*)(src+*scur);
57
+    *myebx = oldebx*2+1;
58
+    *scur+=4;
59
+  }
60
+  return (oldebx>>31)&1;
61
+}
62
+
63
+/* [inflate] */
64
+
65
+int upx_inflate2b(char *src, int ssize, char *dst, int dsize)
66
+{
67
+  int backbytes, backsize, unp_offset = -1, i;
68
+  int myebx = 0;
69
+  int scur=0, dcur=0;
70
+
71
+  while (1) {
72
+    while (doubleebx(src, &myebx, &scur, ssize)) {
73
+      if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize)
74
+	return -1;
75
+      dst[dcur++] = src[scur++];
76
+    }
77
+
78
+    backbytes = 1;
79
+
80
+    while (1) {
81
+      backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize);
82
+      if (doubleebx(src, &myebx, &scur, ssize))
83
+	break;
84
+    }
85
+
86
+    backsize = 0;	
87
+    backbytes-=3;
88
+  
89
+    if ( backbytes >= 0 ) {
90
+
91
+      if (scur<0 || scur>=ssize)
92
+	return -1;
93
+      backbytes<<=8;
94
+      backbytes+=(unsigned char)(src[scur++]);
95
+      backbytes^=0xffffffff;
96
+
97
+      if (!backbytes)
98
+	break;
99
+      unp_offset = backbytes;
100
+    }
101
+
102
+    backsize = doubleebx(src, &myebx, &scur, ssize);
103
+    backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
104
+    if (!backsize) {
105
+      backsize++;
106
+      do {
107
+	backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
108
+      } while (!doubleebx(src, &myebx, &scur, ssize));
109
+      backsize+=2;
110
+    }
111
+
112
+    if ( (unsigned int)unp_offset < 0xfffff300 )
113
+      backsize++;
114
+
115
+    backsize++;
116
+    for (i = 0; i < backsize; i++) {
117
+      if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize)
118
+	return -1;
119
+      dst[dcur + i] = dst[dcur + unp_offset + i];
120
+    }
121
+    dcur+=backsize;
122
+  }
123
+  return 0;
124
+}
125
+
126
+int upx_inflate2d(char *src, int ssize, char *dst, int dsize)
127
+{
128
+  int backbytes, backsize, unp_offset = -1, i;
129
+  int myebx = 0;
130
+  int scur=0, dcur=0;
131
+
132
+  while (1) {
133
+    while (doubleebx(src, &myebx, &scur, ssize)) {
134
+      if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize)
135
+	return -1;
136
+      dst[dcur++] = src[scur++];
137
+    }
138
+
139
+    backbytes = 1;
140
+
141
+    while (1) {
142
+      backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize);
143
+      if (doubleebx(src, &myebx, &scur, ssize))
144
+	break;
145
+      backbytes--;
146
+      backbytes=backbytes*2+doubleebx(src, &myebx, &scur, ssize);
147
+    }
148
+
149
+    backsize = 0;	
150
+    backbytes-=3;
151
+  
152
+    if ( backbytes >= 0 ) {
153
+
154
+      if (scur<0 || scur>=ssize)
155
+	return -1;
156
+      backbytes<<=8;
157
+      backbytes+=(unsigned char)(src[scur++]);
158
+      backbytes^=0xffffffff;
159
+
160
+      if (!backbytes)
161
+	break;
162
+      backsize = backbytes & 1;
163
+      backbytes>>=1;
164
+      unp_offset = backbytes;
165
+    }
166
+    else
167
+      backsize = doubleebx(src, &myebx, &scur, ssize);
168
+ 
169
+    backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
170
+    if (!backsize) {
171
+      backsize++;
172
+      do {
173
+	backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize);
174
+      } while (!doubleebx(src, &myebx, &scur, ssize));
175
+      backsize+=2;
176
+    }
177
+
178
+    if ( (unsigned int)unp_offset < 0xfffffb00 ) 
179
+      backsize++;
180
+
181
+    backsize++;
182
+    for (i = 0; i < backsize; i++) {
183
+      if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize)
184
+	return -1;
185
+      dst[dcur + i] = dst[dcur + unp_offset + i];
186
+    }
187
+    dcur+=backsize;
188
+  }
189
+  return 0;
190
+}
191
+
192
+int upx_inflate2e(char *src, int ssize, char *dst, int dsize)
193
+{
194
+  int backbytes, backsize, unp_offset = -1, i;
195
+  int myebx = 0;
196
+  int scur=0, dcur=0;
197
+
198
+  while (1) {
199
+    while (doubleebx(src, &myebx, &scur, ssize)) {
200
+      if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize)
201
+	return -1;
202
+      dst[dcur++] = src[scur++];
203
+    }
204
+
205
+    backbytes = 1;
206
+
207
+    while (1) {
208
+      backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize);
209
+      if (doubleebx(src, &myebx, &scur, ssize))
210
+	break;
211
+      backbytes--;
212
+      backbytes=backbytes*2+doubleebx(src, &myebx, &scur, ssize);
213
+    }
214
+
215
+    backsize = 0;
216
+    backbytes-=3;
217
+  
218
+    if ( backbytes >= 0 ) {
219
+
220
+      if (scur<0 || scur>=ssize)
221
+	return -1;
222
+      backbytes<<=8;
223
+      backbytes+=(unsigned char)(src[scur++]);
224
+      backbytes^=0xffffffff;
225
+
226
+      if (!backbytes)
227
+	break;
228
+      backsize = backbytes & 1; /* Using backsize to carry on the shifted out bit (UPX uses CF) */
229
+      backbytes>>=1;
230
+      unp_offset = backbytes;
231
+    }
232
+    else
233
+      backsize = doubleebx(src, &myebx, &scur, ssize); /* Using backsize to carry on the doubleebx result (UPX uses CF) */
234
+
235
+    if (backsize) { /* i.e. IF ( last sar shifted out 1 bit || last doubleebx()==1 ) */
236
+      backsize = doubleebx(src, &myebx, &scur, ssize);
237
+    }
238
+    else {
239
+      backsize = 1;
240
+      if (doubleebx(src, &myebx, &scur, ssize))
241
+	backsize = 2 + doubleebx(src, &myebx, &scur, ssize);
242
+      else {
243
+	do {
244
+	  backsize = backsize * 2 + doubleebx(src, &myebx, &scur, ssize);
245
+	} while (!doubleebx(src, &myebx, &scur, ssize));
246
+	backsize+=2;
247
+      }
248
+    }
249
+ 
250
+    if ( (unsigned int)unp_offset < 0xfffffb00 ) 
251
+      backsize++;
252
+
253
+    backsize+=2;
254
+    for (i = 0; i < backsize; i++) {
255
+      if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize)
256
+	return -1;
257
+      dst[dcur + i] = dst[dcur + unp_offset + i];
258
+    }
259
+    dcur+=backsize;
260
+  }
261
+  return 0;
262
+}
0 263
new file mode 100644
... ...
@@ -0,0 +1,26 @@
0
+/*
1
+ *  Copyright (C) 2004 aCaB <acab@clamav.net>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
16
+ */
17
+
18
+#ifndef __UPX_H
19
+#define __UPX_H
20
+
21
+int upx_inflate2b(char *, int , char *, int);
22
+int upx_inflate2d(char *, int , char *, int);
23
+int upx_inflate2e(char *, int , char *, int);
24
+
25
+#endif