1 /*
2 * Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3 * Copyright (C) 2007-2013 Sourcefire, Inc.
4 *
5 * Authors: Ivan Zlatev
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 /* Decrypts files, protected by Y0da Cryptor 1.3 */
23
24 /* aCaB:
25 * 13/01/2006 - merged standalone unpacker into libclamav
26 * 14/01/2006 - major rewrite and bugfix
27 */
28
29 #include <string.h>
30
31 #if HAVE_CONFIG_H
32 #include "clamav-config.h"
33 #endif
34
35 #include "clamav.h"
36 #include "pe.h"
37 #include "others.h"
38 #include "yc.h"
39
40 #define EC16(x) le16_to_host(x) /* Convert little endian to host */
41
42 #define DO_HEURISTIC 1
43
yc_bounds_check(cli_ctx * ctx,char * base,unsigned int filesize,char * offset,unsigned int bound)44 static int yc_bounds_check(cli_ctx *ctx, char *base, unsigned int filesize, char *offset, unsigned int bound)
45 {
46 if ((unsigned int)((offset + bound) - base) > filesize) {
47 cli_dbgmsg("yC: Bounds check assertion.\n");
48 #if DO_HEURISTIC
49 cli_append_virus(ctx, "Heuristics.BoundsCheck");
50 #endif
51 return 1;
52 }
53
54 return 0;
55 }
56
57 /* ========================================================================== */
58 /* "Emulates" the poly decryptors */
59
yc_poly_emulator(cli_ctx * ctx,char * base,unsigned int filesize,char * decryptor_offset,char * code,unsigned int ecx,uint32_t max_emu)60 static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, char *decryptor_offset, char *code, unsigned int ecx, uint32_t max_emu)
61 {
62
63 /*
64 This is the instruction set of the poly code.
65 Numbers stand for example only.
66
67 2C 05 SUB AL,5
68 2AC1 SUB AL,CL
69 34 10 XOR AL,10
70 32C1 XOR AL,CL
71 FEC8 DEC AL
72 04 10 ADD AL,10
73 02C1 ADD AL,CL
74 C0C0 06 ROL AL,6
75 C0C8 05 ROR AL,5
76 D2C8 ROR AL,CL
77 D2C0 ROL AL,CL
78
79 */
80 unsigned char al;
81 unsigned char cl = ecx & 0xff;
82 unsigned int j, i;
83 unsigned int max_jmp_loop = 100000000;
84
85 for (i = 0; i < ecx && i < max_emu; i++) /* Byte looper - Decrypts every byte and write it back */
86 {
87 if (yc_bounds_check(ctx, base, filesize, code, i)) {
88 return 2;
89 }
90 al = code[i];
91
92 for (j = 0; j < 0x30; j++) /* Poly Decryptor "Emulator" */
93 {
94 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
95 return 2;
96 }
97
98 switch (decryptor_offset[j]) {
99
100 case '\xEB': /* JMP short */
101 j++;
102 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
103 return 2;
104 }
105 if (!max_jmp_loop)
106 return 2;
107 max_jmp_loop--;
108 j = j + decryptor_offset[j];
109 break;
110
111 case '\xFE': /* DEC AL */
112 al--;
113 j++;
114 break;
115
116 case '\x2A': /* SUB AL,CL */
117 al = al - cl;
118 j++;
119 break;
120
121 case '\x02': /* ADD AL,CL */
122 al = al + cl;
123 j++;
124 break;
125 case '\x32': /* XOR AL,CL */
126 al = al ^ cl;
127 j++;
128 break;
129 ;
130 case '\x04': /* ADD AL,num */
131 j++;
132 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
133 return 2;
134 }
135 al = al + decryptor_offset[j];
136 break;
137 ;
138 case '\x34': /* XOR AL,num */
139 j++;
140 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
141 return 2;
142 }
143 al = al ^ decryptor_offset[j];
144 break;
145
146 case '\x2C': /* SUB AL,num */
147 j++;
148 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
149 return 2;
150 }
151 al = al - decryptor_offset[j];
152 break;
153
154 case '\xC0':
155 j++;
156 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
157 return 2;
158 }
159 if (decryptor_offset[j] == '\xC0') /* ROL AL,num */
160 {
161 j++;
162 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
163 return 2;
164 }
165 CLI_ROL(al, decryptor_offset[j]);
166 } else /* ROR AL,num */
167 {
168 j++;
169 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
170 return 2;
171 }
172 CLI_ROR(al, decryptor_offset[j]);
173 }
174 break;
175
176 case '\xD2':
177 j++;
178 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
179 return 2;
180 }
181 if (decryptor_offset[j] == '\xC8') /* ROR AL,CL */
182 {
183 j++;
184 CLI_ROR(al, cl);
185 } else /* ROL AL,CL */
186 {
187 j++;
188 CLI_ROL(al, cl);
189 }
190 break;
191
192 case '\x90':
193 case '\xf8':
194 case '\xf9':
195 break;
196
197 default:
198 if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
199 return 2;
200 }
201 cli_dbgmsg("yC: Unhandled opcode %x\n", (unsigned char)decryptor_offset[j]);
202 return 1;
203 }
204 }
205 cl--;
206 if (yc_bounds_check(ctx, base, filesize, code, i))
207 return 2;
208 code[i] = al;
209 }
210 return 0;
211 }
212
213 /* ========================================================================== */
214 /* Main routine which calls all others */
215
yc_decrypt(cli_ctx * ctx,char * fbuf,unsigned int filesize,struct cli_exe_section * sections,unsigned int sectcount,uint32_t peoffset,int desc,uint32_t ecx,int16_t offset)216 int yc_decrypt(cli_ctx *ctx, char *fbuf, unsigned int filesize, struct cli_exe_section *sections, unsigned int sectcount, uint32_t peoffset, int desc, uint32_t ecx, int16_t offset)
217 {
218 uint32_t ycsect = sections[sectcount].raw + offset;
219 unsigned int i;
220 struct pe_image_file_hdr *pe = (struct pe_image_file_hdr *)(fbuf + peoffset);
221 char *sname = (char *)pe + EC16(pe->SizeOfOptionalHeader) + 0x18;
222 uint32_t max_emu;
223 unsigned int ofilesize = filesize;
224 /*
225
226 First layer (decryptor of the section decryptor) in last section
227
228 Start offset for analyze: Start of yC Section + 0x93
229 End offset for analyze: Start of yC Section + 0xC3
230 Length to decrypt - ECX = 0xB97
231
232 */
233 cli_dbgmsg("yC: offset: %x, length: %x\n", offset, ecx);
234 cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount);
235 switch (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx)) {
236 case 2:
237 return CL_VIRUS;
238 case 1:
239 return CL_EUNPACK;
240 }
241 filesize -= sections[sectcount].ursz;
242
243 /*
244
245 Second layer (decryptor of the sections) in last section
246
247 Start offset for analyze: Start of yC Section + 0x457
248 End offset for analyze: Start of yC Section + 0x487
249 Length to decrypt - ECX = Raw Size of Section
250
251 */
252
253 /* Loop through all sections and decrypt them... */
254 for (i = 0; i < sectcount; i++) {
255 uint32_t name = (uint32_t)cli_readint32(sname + i * 0x28);
256 if (!sections[i].raw ||
257 !sections[i].rsz ||
258 name == 0x63727372 || /* rsrc */
259 name == 0x7273722E || /* .rsr */
260 name == 0x6F6C6572 || /* relo */
261 name == 0x6C65722E || /* .rel */
262 name == 0x6164652E || /* .eda */
263 name == 0x6164722E || /* .rda */
264 name == 0x6164692E || /* .ida */
265 name == 0x736C742E || /* .tls */
266 (name & 0xffff) == 0x4379 /* yC */
267 ) continue;
268 cli_dbgmsg("yC: decrypting sect%d\n", i);
269 max_emu = filesize - sections[i].raw;
270 if (max_emu > filesize) {
271 cli_dbgmsg("yC: bad emulation length limit %u\n", max_emu);
272 return 1;
273 }
274 switch (yc_poly_emulator(ctx, fbuf, ofilesize, fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457),
275 fbuf + sections[i].raw,
276 sections[i].ursz,
277 max_emu)) {
278 case 2:
279 return CL_VIRUS;
280 case 1:
281 return CL_EUNPACK;
282 }
283 }
284
285 /* Remove yC section */
286 pe->NumberOfSections = EC16(sectcount);
287
288 /* Remove IMPORT_DIRECTORY information */
289 memset((char *)pe + sizeof(struct pe_image_file_hdr) + 0x68, 0, 8);
290
291 /* OEP resolving */
292 /* OEP = DWORD PTR [ Start of yC section+ A0F] */
293 cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 16, cli_readint32(fbuf + ycsect + 0xa0f));
294
295 /* Fix SizeOfImage */
296 cli_writeint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38, cli_readint32((char *)pe + sizeof(struct pe_image_file_hdr) + 0x38) - sections[sectcount].vsz);
297
298 if (cli_writen(desc, fbuf, filesize) == (size_t)-1) {
299 cli_dbgmsg("yC: Cannot write unpacked file\n");
300 return CL_EUNPACK;
301 }
302 return CL_SUCCESS;
303 }
304