git-svn: trunk@2190
aCaB authored on 2006/08/12 03:30:35... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Fri Aug 11 19:37:24 CEST 2006 (acab) |
|
2 |
+------------------------------------ |
|
3 |
+ * libclamav: add support for SUE decryption (disabled) |
|
4 |
+ |
|
1 | 5 |
Fri Aug 11 18:09:00 CEST 2006 (tk) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav/others.c: apply win32 support patch from NJH |
... | ... |
@@ -82,9 +82,9 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \ |
82 | 82 |
filetypes.lo blob.lo mbox.lo message.lo snprintf.lo table.lo \ |
83 | 83 |
text.lo ole2_extract.lo vba_extract.lo msexpand.lo pe.lo \ |
84 | 84 |
cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo htmlnorm.lo \ |
85 |
- chmunpack.lo rebuildpe.lo petite.lo wwunpack.lo packlibs.lo \ |
|
86 |
- fsg.lo line.lo untar.lo unzip.lo special.lo binhex.lo \ |
|
87 |
- is_tar.lo tnef.lo unrar15.lo unrarvm.lo unrar.lo \ |
|
85 |
+ chmunpack.lo rebuildpe.lo petite.lo wwunpack.lo suecrypt.lo \ |
|
86 |
+ packlibs.lo fsg.lo line.lo untar.lo unzip.lo special.lo \ |
|
87 |
+ binhex.lo 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 |
90 | 90 |
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS) |
... | ... |
@@ -293,6 +293,8 @@ libclamav_la_SOURCES = \ |
293 | 293 |
petite.h \ |
294 | 294 |
wwunpack.c \ |
295 | 295 |
wwunpack.h \ |
296 |
+ suecrypt.c \ |
|
297 |
+ suecrypt.h \ |
|
296 | 298 |
packlibs.c \ |
297 | 299 |
packlibs.h \ |
298 | 300 |
fsg.c \ |
... | ... |
@@ -448,6 +450,7 @@ distclean-compile: |
448 | 448 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/special.Plo@am__quote@ |
449 | 449 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spin.Plo@am__quote@ |
450 | 450 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@ |
451 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suecrypt.Plo@am__quote@ |
|
451 | 452 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Plo@am__quote@ |
452 | 453 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@ |
453 | 454 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@ |
... | ... |
@@ -29,7 +29,9 @@ |
29 | 29 |
#include <sys/stat.h> |
30 | 30 |
#include <fcntl.h> |
31 | 31 |
#include <sys/stat.h> |
32 |
+#ifdef HAVE_UNISTD_H |
|
32 | 33 |
#include <unistd.h> |
34 |
+#endif |
|
33 | 35 |
#include <time.h> |
34 | 36 |
|
35 | 37 |
#include "cltypes.h" |
... | ... |
@@ -42,6 +44,7 @@ |
42 | 42 |
#include "upx.h" |
43 | 43 |
#include "yc.h" |
44 | 44 |
#include "wwunpack.h" |
45 |
+#include "suecrypt.h" |
|
45 | 46 |
#include "scanners.h" |
46 | 47 |
#include "rebuildpe.h" |
47 | 48 |
#include "str.h" |
... | ... |
@@ -812,6 +815,82 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
812 | 812 |
} |
813 | 813 |
|
814 | 814 |
|
815 |
+#ifdef CONFIG_EXPERIMENTAL |
|
816 |
+ /* SUE */ |
|
817 |
+ |
|
818 |
+ if(nsections > 2 && EC32(optional_hdr32.AddressOfEntryPoint) == EC32(section_hdr[nsections - 1].VirtualAddress) && EC32(section_hdr[nsections - 1].SizeOfRawData) > 0x350 && EC32(section_hdr[nsections - 1].SizeOfRawData) < 0x292+0x350+1000) { |
|
819 |
+ |
|
820 |
+ |
|
821 |
+ char *sue=buff+0x74; |
|
822 |
+ uint32_t key; |
|
823 |
+ |
|
824 |
+ if(lseek(desc, ep-4, SEEK_SET) == -1) { |
|
825 |
+ cli_dbgmsg("SUE: lseek() failed - EP out of file\n"); |
|
826 |
+ free(section_hdr); |
|
827 |
+ return CL_EIO; |
|
828 |
+ } |
|
829 |
+ if((unsigned int) cli_readn(desc, buff, EC32(section_hdr[nsections - 1].SizeOfRawData)+4) == EC32(section_hdr[nsections - 1].SizeOfRawData)+4) { |
|
830 |
+ found=0; |
|
831 |
+ while(CLI_ISCONTAINED(buff+4, EC32(section_hdr[nsections - 1].SizeOfRawData), sue, 4*3)) { |
|
832 |
+ if((cli_readint32(sue)^cli_readint32(sue+4))==0x5c41090e && (cli_readint32(sue)^cli_readint32(sue+8))==0x021e0145) { |
|
833 |
+ found=1; |
|
834 |
+ key=(cli_readint32(sue)^0x6e72656b); |
|
835 |
+ break; |
|
836 |
+ } |
|
837 |
+ sue++; |
|
838 |
+ } |
|
839 |
+ cli_dbgmsg("SUE: key(%x) found @%x\n", key, sue-buff); |
|
840 |
+ if (found && CLI_ISCONTAINED(buff, EC32(section_hdr[nsections - 1].SizeOfRawData), sue-0x74, 0xbe) && |
|
841 |
+ (sue=sudecrypt(desc, fsize, section_hdr, nsections-1, sue, key, cli_readint32(buff), e_lfanew))) { |
|
842 |
+ if(!(tempfile = cli_gentemp(NULL))) { |
|
843 |
+ free(sue); |
|
844 |
+ free(section_hdr); |
|
845 |
+ return CL_EMEM; |
|
846 |
+ } |
|
847 |
+ |
|
848 |
+ if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
849 |
+ cli_dbgmsg("sue: Can't create file %s\n", tempfile); |
|
850 |
+ free(tempfile); |
|
851 |
+ free(sue); |
|
852 |
+ free(section_hdr); |
|
853 |
+ return CL_EIO; |
|
854 |
+ } |
|
855 |
+ |
|
856 |
+ if((unsigned int) write(ndesc, sue, ep) != ep) { |
|
857 |
+ cli_dbgmsg("sue: Can't write %d bytes\n", ep); |
|
858 |
+ close(ndesc); |
|
859 |
+ free(tempfile); |
|
860 |
+ free(sue); |
|
861 |
+ free(section_hdr); |
|
862 |
+ return CL_EIO; |
|
863 |
+ } |
|
864 |
+ |
|
865 |
+ free(sue); |
|
866 |
+ if (cli_leavetemps_flag) |
|
867 |
+ cli_dbgmsg("SUE: Decrypted executable saved in %s\n", tempfile); |
|
868 |
+ else |
|
869 |
+ cli_dbgmsg("SUE: Executable decrypted\n"); |
|
870 |
+ fsync(ndesc); |
|
871 |
+ lseek(ndesc, 0, SEEK_SET); |
|
872 |
+ |
|
873 |
+ if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
874 |
+ free(section_hdr); |
|
875 |
+ close(ndesc); |
|
876 |
+ if(!cli_leavetemps_flag) |
|
877 |
+ unlink(tempfile); |
|
878 |
+ free(tempfile); |
|
879 |
+ return CL_VIRUS; |
|
880 |
+ } |
|
881 |
+ close(ndesc); |
|
882 |
+ if(!cli_leavetemps_flag) |
|
883 |
+ unlink(tempfile); |
|
884 |
+ free(tempfile); |
|
885 |
+ } |
|
886 |
+ } |
|
887 |
+ |
|
888 |
+ } |
|
889 |
+#endif |
|
890 |
+ |
|
815 | 891 |
/* UPX & FSG support */ |
816 | 892 |
|
817 | 893 |
/* try to find the first section with physical size == 0 */ |
... | ... |
@@ -1961,7 +2040,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1961 | 1961 |
} |
1962 | 1962 |
|
1963 | 1963 |
if((unsigned int) write(ndesc, dest, dsize) != dsize) { |
1964 |
- cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize); |
|
1964 |
+ cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize); |
|
1965 | 1965 |
close(ndesc); |
1966 | 1966 |
free(tempfile); |
1967 | 1967 |
free(dest); |
... | ... |
@@ -1970,7 +2049,11 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1970 | 1970 |
} |
1971 | 1971 |
|
1972 | 1972 |
free(dest); |
1973 |
- cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1973 |
+ if (cli_leavetemps_flag) |
|
1974 |
+ cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1975 |
+ else |
|
1976 |
+ cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n"); |
|
1977 |
+ |
|
1974 | 1978 |
fsync(ndesc); |
1975 | 1979 |
lseek(ndesc, 0, SEEK_SET); |
1976 | 1980 |
|
1977 | 1981 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,139 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, |
|
16 |
+ * MA 02110-1301, USA. |
|
17 |
+ */ |
|
18 |
+ |
|
19 |
+/* |
|
20 |
+** suecrypt.c |
|
21 |
+** |
|
22 |
+** 05/08/2k6 - Quick RCE, started coding. |
|
23 |
+** 06/08/2k6 - There were large drops of black rain. |
|
24 |
+** 07/08/2k6 - Found more versions, back to reversing. |
|
25 |
+** 11/08/2k6 - Generic and special cases handler. Release. |
|
26 |
+** |
|
27 |
+*/ |
|
28 |
+ |
|
29 |
+/* |
|
30 |
+** Unpacks and rebuilds suecrypt(*) |
|
31 |
+** |
|
32 |
+** Not sure at all what this stuff is, couldn't find any reference to it |
|
33 |
+** Seems to be popular in dialers, can't say more except... |
|
34 |
+** Christoph asked for it and that's enough :) |
|
35 |
+** |
|
36 |
+** (*) some versions or maybe only some samples |
|
37 |
+*/ |
|
38 |
+ |
|
39 |
+ |
|
40 |
+/* |
|
41 |
+** TODO: |
|
42 |
+** |
|
43 |
+** needs performance tests |
|
44 |
+** |
|
45 |
+*/ |
|
46 |
+ |
|
47 |
+#ifdef CONFIG_EXPERIMENTAL |
|
48 |
+#if HAVE_CONFIG_H |
|
49 |
+#include "clamav-config.h" |
|
50 |
+#endif |
|
51 |
+ |
|
52 |
+#include <sys/types.h> |
|
53 |
+#ifdef HAVE_UNISTD_H |
|
54 |
+#include <unistd.h> |
|
55 |
+#endif |
|
56 |
+#include <stdlib.h> |
|
57 |
+#include <string.h> |
|
58 |
+ |
|
59 |
+#include "cltypes.h" |
|
60 |
+#include "others.h" |
|
61 |
+#include "pe.h" |
|
62 |
+ |
|
63 |
+#define EC32(x) le32_to_host(x) /* Convert little endian to host */ |
|
64 |
+#define EC16(x) le16_to_host(x) |
|
65 |
+#define VAALIGN(s) (((s)/0x1000+((s)%0x1000!=0))*0x1000) |
|
66 |
+ |
|
67 |
+char *sudecrypt(int desc, size_t fsize, struct pe_image_section_hdr *section_hdr, uint16_t sects, char *buff, uint32_t bkey, uint32_t pkey, uint32_t e_lfanew) { |
|
68 |
+ char *file, *hunk; |
|
69 |
+ uint32_t va,sz,key; |
|
70 |
+ int i, j; |
|
71 |
+ |
|
72 |
+ cli_dbgmsg("in suecrypt\n"); |
|
73 |
+ |
|
74 |
+ if (!(file=cli_calloc(fsize, 1))) return 0; |
|
75 |
+ lseek(desc, 0, SEEK_SET); |
|
76 |
+ if((size_t) cli_readn(desc, file, fsize) != fsize) { |
|
77 |
+ cli_dbgmsg("SUE: Can't read %d bytes\n", fsize); |
|
78 |
+ free(file); |
|
79 |
+ return 0; |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ va=(bkey>>16)|(bkey<<16); |
|
83 |
+ key=((sz=cli_readint32(buff+0x3e))^va); |
|
84 |
+ if (!key || key==0x208 || key==0x3bc) key=((sz=cli_readint32(buff+0x46))^va); /* FIXME: black magic */ |
|
85 |
+ |
|
86 |
+ if (key!=pkey) { |
|
87 |
+ cli_dbgmsg("SUE: Key seems not (entirely) encrypted\n\tpossible key: 0%08x\n\tcrypted key: 0%08x\n\tplain key: 0%08x\n", pkey, key, sz); |
|
88 |
+ va=0; |
|
89 |
+ for (i=0; i<4; i++) { |
|
90 |
+ va=(va<<8)|0xff; |
|
91 |
+ if (((key&va)|(sz&(~va)))==pkey) { |
|
92 |
+ key=pkey; |
|
93 |
+ break; |
|
94 |
+ } |
|
95 |
+ } |
|
96 |
+ if (i==4) cli_dbgmsg("SUE: let's roll the dice...\n"); |
|
97 |
+ } |
|
98 |
+ cli_dbgmsg("SUE: Decrypting with 0%08x\n", key); |
|
99 |
+ |
|
100 |
+ i=0; |
|
101 |
+ while(1) { |
|
102 |
+ if (!CLI_ISCONTAINED(buff-0x74, 0xbe, buff-0x58+i*8, 8)) { |
|
103 |
+ free(file); |
|
104 |
+ return 0; |
|
105 |
+ } |
|
106 |
+ va=(cli_readint32(buff-0x58+i*8)^bkey); |
|
107 |
+ sz=(cli_readint32(buff-0x58+4+i*8)^bkey); |
|
108 |
+ if (!va) break; |
|
109 |
+ cli_dbgmsg("SUE: Hunk #%d RVA:%x size:%d\n", i, va, sz); |
|
110 |
+ for (j=0; j<sects; j++) { |
|
111 |
+ if(!CLI_ISCONTAINED(EC32(section_hdr[j].VirtualAddress), EC32(section_hdr[j].SizeOfRawData), va, sz)) continue; |
|
112 |
+ hunk=file+EC32(section_hdr[j].VirtualAddress)-va+EC32(section_hdr[j].PointerToRawData); |
|
113 |
+ while(sz>=4) { |
|
114 |
+ cli_writeint32(hunk, cli_readint32(hunk)^key); |
|
115 |
+ hunk+=4; |
|
116 |
+ sz-=4; |
|
117 |
+ } |
|
118 |
+ break; |
|
119 |
+ } |
|
120 |
+ if (j==sects) { |
|
121 |
+ cli_dbgmsg("SUE: Hunk out of file or cross sections\n"); |
|
122 |
+ free(file); |
|
123 |
+ return 0; |
|
124 |
+ } |
|
125 |
+ i++; |
|
126 |
+ } |
|
127 |
+ va=(cli_readint32(buff-0x74)^bkey); |
|
128 |
+ cli_dbgmsg("SUE: found OEP: @%x\n", va); |
|
129 |
+ |
|
130 |
+ hunk=file+e_lfanew; |
|
131 |
+ hunk[6]=sects&0xff; |
|
132 |
+ hunk[7]=sects>>8; |
|
133 |
+ cli_writeint32(hunk+0x28, va); |
|
134 |
+ memset(hunk+0xf8+0x28*sects, 0, 0x28); |
|
135 |
+ |
|
136 |
+ return file; |
|
137 |
+} |
|
138 |
+#endif |
0 | 139 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
0 |
+/* |
|
1 |
+ * Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, |
|
16 |
+ * MA 02110-1301, USA. |
|
17 |
+ */ |
|
18 |
+ |
|
19 |
+#ifdef CONFIG_EXPERIMENTAL |
|
20 |
+#ifndef __UNSUE_H |
|
21 |
+#define __UNSUE_H |
|
22 |
+ |
|
23 |
+#include "cltypes.h" |
|
24 |
+#include "rebuildpe.h" |
|
25 |
+ |
|
26 |
+char *sudecrypt(int, size_t, struct pe_image_section_hdr *, uint16_t, char *, uint32_t, uint32_t, uint32_t); |
|
27 |
+ |
|
28 |
+#endif |
|
29 |
+#endif |