Browse code

added SUE decryptor (enable via CONFIG_EXPERIMENTAL)

git-svn: trunk@2190

aCaB authored on 2006/08/12 03:30:35
Showing 6 changed files
... ...
@@ -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
... ...
@@ -94,6 +94,8 @@ libclamav_la_SOURCES = \
94 94
 	petite.h \
95 95
 	wwunpack.c \
96 96
 	wwunpack.h \
97
+	suecrypt.c \
98
+	suecrypt.h \
97 99
 	packlibs.c \
98 100
 	packlibs.h \
99 101
 	fsg.c \
... ...
@@ -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