Browse code

added yC support

git-svn: trunk@1814

aCaB authored on 2006/01/14 22:58:35
Showing 6 changed files
... ...
@@ -1,3 +1,8 @@
1
+Fri Jan 14 14:51:01 CET 2006 (acab)
2
+---------------------------------
3
+  * libclamav: added yC support
4
+  		thanks a lot to Ivan Zlatev <pumqara*gmail.com>
5
+  
1 6
 Fri Jan 13 14:53:45 CET 2006 (tk)
2 7
 ---------------------------------
3 8
   * libclamav/vba_extract.c: fix possible memory leak, reported by  Cesar
... ...
@@ -141,6 +141,8 @@ libclamav_la_SOURCES = \
141 141
 	pdf.h \
142 142
 	spin.c \
143 143
 	spin.h \
144
+	yc.c \
145
+	yc.h \
144 146
 	elf.c \
145 147
 	elf.h \
146 148
 	execs.h \
... ...
@@ -86,7 +86,7 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
86 86
 	chmunpack.lo rebuildpe.lo petite.lo fsg.lo line.lo untar.lo \
87 87
 	special.lo binhex.lo is_tar.lo tnef.lo unrar15.lo unrarvm.lo \
88 88
 	unrar.lo unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo \
89
-	pdf.lo spin.lo elf.lo sis.lo
89
+	pdf.lo spin.lo yc.lo elf.lo sis.lo
90 90
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
91 91
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
92 92
 depcomp = $(SHELL) $(top_srcdir)/depcomp
... ...
@@ -335,6 +335,8 @@ libclamav_la_SOURCES = \
335 335
 	pdf.h \
336 336
 	spin.c \
337 337
 	spin.h \
338
+	yc.c \
339
+	yc.h \
338 340
 	elf.c \
339 341
 	elf.h \
340 342
 	execs.h \
... ...
@@ -462,6 +464,7 @@ distclean-compile:
462 462
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/untar.Plo@am__quote@
463 463
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@
464 464
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vba_extract.Plo@am__quote@
465
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yc.Plo@am__quote@
465 466
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-dir.Plo@am__quote@
466 467
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-err.Plo@am__quote@
467 468
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-file.Plo@am__quote@
... ...
@@ -35,10 +35,11 @@
35 35
 #include "clamav.h"
36 36
 #include "others.h"
37 37
 #include "pe.h"
38
-#include "upx.h"
39 38
 #include "petite.h"
40 39
 #include "fsg.h"
41 40
 #include "spin.h"
41
+#include "upx.h"
42
+#include "yc.h"
42 43
 #include "scanners.h"
43 44
 #include "rebuildpe.h"
44 45
 #include "str.h"
... ...
@@ -1581,6 +1582,79 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
1581 1581
 	}
1582 1582
     }
1583 1583
 
1584
+
1585
+    /* yC 1.3 */
1586
+
1587
+    if(nsections > 1 &&
1588
+       EC32(optional_hdr32.AddressOfEntryPoint) == EC32(section_hdr[nsections - 1].VirtualAddress) + 0x60 &&
1589
+       memcmp(buff, "\x55\x8B\xEC\x53\x56\x57\x60\xE8\x00\x00\x00\x00\x5D\x81\xED\x6C\x28\x40\x00\xB9\x5D\x34\x40\x00\x81\xE9\xC6\x28\x40\x00\x8B\xD5\x81\xC2\xC6\x28\x40\x00\x8D\x3A\x8B\xF7\x33\xC0\xEB\x04\x90\xEB\x01\xC2\xAC", 51) == 0)  {
1590
+
1591
+	    struct stat fstats;
1592
+	    char *spinned;
1593
+
1594
+	if(fstat(desc, &fstats) == -1) {
1595
+	    free(section_hdr);
1596
+	    return CL_EIO;
1597
+	}
1598
+
1599
+	if ( fstats.st_size >= EC32(section_hdr[nsections - 1].PointerToRawData) + 0xC6 + 0xb97 ) { /* size check on yC sect */
1600
+	  if((spinned = (char *) cli_malloc(fstats.st_size)) == NULL) {
1601
+	    free(section_hdr);
1602
+	    return CL_EMEM;
1603
+	  }
1604
+
1605
+	  lseek(desc, 0, SEEK_SET);
1606
+	  if(read(desc, spinned, fstats.st_size) != fstats.st_size) {
1607
+	    cli_dbgmsg("yC: Can't read %d bytes\n", fstats.st_size);
1608
+	    free(spinned);
1609
+	    free(section_hdr);
1610
+	    return CL_EIO;
1611
+	  }
1612
+	  
1613
+	  tempfile = cli_gentemp(NULL);
1614
+	  if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1615
+	    cli_dbgmsg("yC: Can't create file %s\n", tempfile);
1616
+	    free(tempfile);
1617
+	    free(spinned);
1618
+	    free(section_hdr);
1619
+	    return CL_EIO;
1620
+	  }
1621
+	  
1622
+	  if(!yc_decrypt(spinned, fstats.st_size, section_hdr, nsections-1, e_lfanew, ndesc)) {
1623
+	    free(spinned);
1624
+	    cli_dbgmsg("yC: Unpacked and rebuilt executable saved in %s\n", tempfile);
1625
+	    fsync(ndesc);
1626
+	    lseek(ndesc, 0, SEEK_SET);
1627
+	    
1628
+	    if(cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
1629
+	      free(section_hdr);
1630
+	      close(ndesc);
1631
+	      if(!cli_leavetemps_flag) {
1632
+		unlink(tempfile);
1633
+		free(tempfile);
1634
+	      } else {
1635
+		free(tempfile);
1636
+	      }
1637
+	      return CL_VIRUS;
1638
+	    }
1639
+	    
1640
+	  } else {
1641
+	    free(spinned);
1642
+	    cli_dbgmsg("yC: Rebuilding failed\n");
1643
+	  }
1644
+	  
1645
+	  close(ndesc);
1646
+	  if(!cli_leavetemps_flag) {
1647
+	    unlink(tempfile);
1648
+	    free(tempfile);
1649
+	  } else {
1650
+	    free(tempfile);
1651
+	  }
1652
+
1653
+
1654
+	}
1655
+    }
1656
+
1584 1657
     /* to be continued ... */
1585 1658
 
1586 1659
     free(section_hdr);
1587 1660
new file mode 100644
... ...
@@ -0,0 +1,253 @@
0
+/*
1
+ *  Copyright (C) 2005 Ivan Zlatev <pumqara@gmail.com>
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
+/* Decrypts files, protected by Y0da Cryptor 1.3 */
19
+
20
+/* aCaB:
21
+ * 13/01/2006 - merged standalone unpacker into libclamav
22
+ * 14/01/2006 - major rewrite and bugfix
23
+ */
24
+ 
25
+
26
+#include <string.h>
27
+
28
+#if HAVE_CONFIG_H
29
+#include "clamav-config.h"
30
+#endif
31
+
32
+#include "cltypes.h"
33
+#include "pe.h"
34
+#include "others.h"
35
+
36
+
37
+// Macros were created by aCaB
38
+#define ROL(a,b) a = ( a << (b % (sizeof(a)<<3) ))  |  (a >> (  (sizeof(a)<<3)  -  (b % (sizeof(a)<<3 )) ) )
39
+#define ROR(a,b) a = ( a >> (b % (sizeof(a)<<3) ))  |  (a << (  (sizeof(a)<<3)  -  (b % (sizeof(a)<<3 )) ) )
40
+
41
+#if WORDS_BIGENDIAN == 0
42
+#define EC16(v)	(v)
43
+#define EC32(v) (v)
44
+#else
45
+static inline uint16_t EC16(uint16_t v)
46
+{
47
+  return ((v >> 8) + (v << 8));
48
+}
49
+
50
+static inline uint32_t EC32(uint32_t v)
51
+{
52
+  return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24));
53
+}
54
+#endif
55
+
56
+//==================================================================================
57
+// "Emulates" the poly decryptors
58
+//
59
+static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx)
60
+{
61
+
62
+  /* 
63
+     This is the instruction set of the poly code.
64
+     Numbers stand for example only.
65
+
66
+     2C 05            SUB AL,5
67
+     2AC1             SUB AL,CL
68
+     34 10            XOR AL,10
69
+     32C1             XOR AL,CL
70
+     FEC8             DEC AL
71
+     04 10            ADD AL,10
72
+     02C1             ADD AL,CL
73
+     C0C0 06          ROL AL,6
74
+     C0C8 05          ROR AL,5
75
+     D2C8             ROR AL,CL
76
+     D2C0             ROL AL,CL
77
+
78
+  */
79
+  //	unsigned int ecx = len2decrypt;
80
+  unsigned char al;
81
+  unsigned char cl = ecx & 0xff;
82
+  unsigned int j=0,i=0;
83
+
84
+  for(i;i<ecx;i++) // Byte looper - Decrypts every byte and write it back
85
+    {
86
+      al = code[i];
87
+
88
+      for(j=0;j<0x30;j++)   // Poly Decryptor "Emulator"
89
+	{
90
+	  switch(decryptor_offset[j])
91
+	    {
92
+
93
+	    case '\xEB':	// JMP short
94
+	      j++;
95
+	      j = j + decryptor_offset[j];
96
+	      break;
97
+
98
+	    case '\xFE':	// DEC  AL
99
+	      al--;
100
+	      j++;
101
+	      break;
102
+
103
+	    case '\x2A':	// SUB AL,CL
104
+	      al = al - cl;
105
+	      j++;
106
+	      break;
107
+
108
+	    case '\x02':	// ADD AL,CL
109
+	      al = al + cl;
110
+	      j++;
111
+	      break
112
+		;
113
+	    case '\x32':	// XOR AL,CL
114
+	      al = al ^ cl;
115
+	      j++;
116
+	      break;
117
+	      ;
118
+	    case '\x04':	// ADD AL,num
119
+	      j++;
120
+	      al = al + decryptor_offset[j];
121
+	      break;
122
+	      ;
123
+	    case '\x34':	// XOR AL,num
124
+	      j++;
125
+	      al = al ^ decryptor_offset[j];
126
+	      break;
127
+
128
+	    case '\x2C':	// SUB AL,num
129
+	      j++;
130
+	      al = al - decryptor_offset[j];
131
+	      break;
132
+
133
+			
134
+	    case '\xC0':
135
+	      j++;
136
+	      if(decryptor_offset[j]=='\xC0') // ROL AL,num
137
+		{
138
+		  j++;
139
+		  al = ROL(al,decryptor_offset[j]);
140
+		}
141
+	      else			// ROR AL,num
142
+		{
143
+		  j++;
144
+		  ROR(al,decryptor_offset[j]);
145
+		}
146
+	      break;
147
+
148
+	    case '\xD2':
149
+	      j++;
150
+	      if(decryptor_offset[j]=='\xC8') // ROR AL,CL
151
+		{
152
+		  j++;
153
+		  ROR(al,cl);
154
+		}
155
+	      else			// ROL AL,CL
156
+		{
157
+		  j++;
158
+		  ROL(al,cl);
159
+		}
160
+	      break;
161
+
162
+	    case '\x90':
163
+	    case '\xf8':
164
+	    case '\xf9':
165
+	      break;
166
+
167
+	    default:
168
+	      cli_dbgmsg("yC: Unhandled opcode %x\n", (unsigned char)decryptor_offset[j]);
169
+	    }
170
+	}
171
+      cl--;
172
+      code[i] = al;
173
+    }
174
+  return 0;
175
+
176
+}
177
+
178
+
179
+//==================================================================================
180
+// Main routine which calls all others
181
+//
182
+int yc_decrypt(char *fbuf, unsigned int filesize, struct pe_image_section_hdr *sections, unsigned int sectcount, uint32_t peoffset, int desc)
183
+{
184
+  uint32_t ycsect = EC32(sections[sectcount].PointerToRawData);
185
+  int i = 0;
186
+  struct pe_image_file_hdr *pe = (struct pe_image_file_hdr*) (fbuf + peoffset);
187
+
188
+  /* 
189
+
190
+  First layer (decryptor of the section decryptor) in last section 
191
+
192
+  Start offset for analyze: Start of yC Section + 0x93
193
+  End offset for analyze: Start of yC Section + 0xC3
194
+  Lenght to decrypt - ECX = 0xB97
195
+
196
+  */
197
+  cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount); 
198
+  if (yc_poly_emulator(fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6 ,0xB97))
199
+    return 1;
200
+  filesize-=EC32(sections[sectcount].SizeOfRawData);
201
+
202
+  /* 
203
+
204
+  Second layer (decryptor of the sections) in last section 
205
+
206
+  Start offset for analyze: Start of yC Section + 0x457
207
+  End offset for analyze: Start of yC Section + 0x487
208
+  Lenght to decrypt - ECX = Raw Size of Section
209
+
210
+  */
211
+
212
+
213
+  // Loop through all sections and decrypt them...
214
+  for(i;i<sectcount;i++)
215
+    {
216
+      uint32_t name = (uint32_t) cli_readint32((char *)sections[i].Name);
217
+      if ( name == 0x63727372 || // rsrc
218
+	   name == 0x7273722E || // .rsr
219
+	   name == 0x6F6C6572 || // relo
220
+	   name == 0x6C65722E || // .rel
221
+	   name == 0x6164652E || // .eda
222
+	   name == 0x6164722E || // .rda
223
+	   name == 0x6164692E || // .ida
224
+	   name == 0x736C742E || // .tls
225
+	   name&0xffff == 0x4379 || // yC
226
+	   EC32(sections[i].PointerToRawData) == 0 ||
227
+	   EC32(sections[i].SizeOfRawData) == 0 ) continue;
228
+      cli_dbgmsg("yC: decrypting sect%d\n",i); 
229
+      if (yc_poly_emulator(fbuf + ycsect + 0x457, fbuf + EC32(sections[i].PointerToRawData), EC32(sections[i].SizeOfRawData)))
230
+	return 1;
231
+    }
232
+
233
+  // Remove yC section
234
+  pe->NumberOfSections=EC16(EC16(pe->NumberOfSections)-1);
235
+
236
+  // Remove IMPORT_DIRECTORY information
237
+  memset((char *)pe + sizeof(struct pe_image_file_hdr) + 0x68, 0, 8);
238
+
239
+  // OEP resolving
240
+  // OEP = DWORD PTR [ Start of yC section+ A0F]
241
+  cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 16, cli_readint32(fbuf + ycsect + 0xa0f));
242
+
243
+  // Fix SizeOfImage
244
+  cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38, cli_readint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38) - EC32(sections[sectcount].VirtualSize));
245
+
246
+  if (cli_writen(desc, fbuf, filesize)==-1) {
247
+    cli_dbgmsg("yc: Cannot write unpacked file\n");
248
+    return 1;
249
+  }
250
+  return 0;
251
+}
252
+
0 253
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+/*
1
+ *  Copyright (C) 2005 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 __YC_H
19
+#define __YC_H
20
+
21
+#include "pe.h"
22
+#include "cltypes.h"
23
+
24
+int yc_decrypt(char *, unsigned int, struct pe_image_section_hdr *, unsigned int, uint32_t, int);
25
+
26
+#endif