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... | ... |
@@ -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 |
... | ... |
@@ -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, §ion_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 |