... | ... |
@@ -2572,7 +2572,7 @@ int cli_scanpe(cli_ctx *ctx) |
2572 | 2572 |
|
2573 | 2573 |
cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset); |
2574 | 2574 |
CLI_UNPTEMP("yC",(spinned,exe_sections,0)); |
2575 |
- CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0)); |
|
2575 |
+ CLI_UNPRESULTS("yC",(yc_decrypt(ctx, spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0)); |
|
2576 | 2576 |
} |
2577 | 2577 |
} |
2578 | 2578 |
|
... | ... |
@@ -39,10 +39,26 @@ |
39 | 39 |
|
40 | 40 |
#define EC16(x) le16_to_host(x) /* Convert little endian to host */ |
41 | 41 |
|
42 |
+#define DO_HEURISTIC 1 |
|
43 |
+ |
|
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_errmsg("yC: Attempted out of bounds. Bailing.\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 |
+ |
|
42 | 58 |
/* ========================================================================== */ |
43 | 59 |
/* "Emulates" the poly decryptors */ |
44 | 60 |
|
45 |
-static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx, uint32_t max_emu) |
|
61 |
+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) |
|
46 | 62 |
{ |
47 | 63 |
|
48 | 64 |
/* |
... | ... |
@@ -68,15 +84,25 @@ static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx |
68 | 68 |
|
69 | 69 |
for(i=0;i<ecx&&i<max_emu;i++) /* Byte looper - Decrypts every byte and write it back */ |
70 | 70 |
{ |
71 |
+ if (yc_bounds_check(ctx, base, filesize, code, i)) { |
|
72 |
+ return 1; |
|
73 |
+ } |
|
71 | 74 |
al = code[i]; |
72 | 75 |
|
73 | 76 |
for(j=0;j<0x30;j++) /* Poly Decryptor "Emulator" */ |
74 | 77 |
{ |
78 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
79 |
+ return 1; |
|
80 |
+ } |
|
81 |
+ |
|
75 | 82 |
switch(decryptor_offset[j]) |
76 | 83 |
{ |
77 | 84 |
|
78 | 85 |
case '\xEB': /* JMP short */ |
79 | 86 |
j++; |
87 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
88 |
+ return 1; |
|
89 |
+ } |
|
80 | 90 |
j = j + decryptor_offset[j]; |
81 | 91 |
break; |
82 | 92 |
|
... | ... |
@@ -102,36 +128,57 @@ static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx |
102 | 102 |
; |
103 | 103 |
case '\x04': /* ADD AL,num */ |
104 | 104 |
j++; |
105 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
106 |
+ return 1; |
|
107 |
+ } |
|
105 | 108 |
al = al + decryptor_offset[j]; |
106 | 109 |
break; |
107 | 110 |
; |
108 | 111 |
case '\x34': /* XOR AL,num */ |
109 | 112 |
j++; |
113 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
114 |
+ return 1; |
|
115 |
+ } |
|
110 | 116 |
al = al ^ decryptor_offset[j]; |
111 | 117 |
break; |
112 | 118 |
|
113 | 119 |
case '\x2C': /* SUB AL,num */ |
114 | 120 |
j++; |
121 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
122 |
+ return 1; |
|
123 |
+ } |
|
115 | 124 |
al = al - decryptor_offset[j]; |
116 | 125 |
break; |
117 | 126 |
|
118 | 127 |
|
119 | 128 |
case '\xC0': |
120 | 129 |
j++; |
130 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
131 |
+ return 1; |
|
132 |
+ } |
|
121 | 133 |
if(decryptor_offset[j]=='\xC0') /* ROL AL,num */ |
122 | 134 |
{ |
123 | 135 |
j++; |
136 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
137 |
+ return 1; |
|
138 |
+ } |
|
124 | 139 |
CLI_ROL(al,decryptor_offset[j]); |
125 | 140 |
} |
126 | 141 |
else /* ROR AL,num */ |
127 | 142 |
{ |
128 | 143 |
j++; |
144 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
145 |
+ return 1; |
|
146 |
+ } |
|
129 | 147 |
CLI_ROR(al,decryptor_offset[j]); |
130 | 148 |
} |
131 | 149 |
break; |
132 | 150 |
|
133 | 151 |
case '\xD2': |
134 | 152 |
j++; |
153 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
154 |
+ return 1; |
|
155 |
+ } |
|
135 | 156 |
if(decryptor_offset[j]=='\xC8') /* ROR AL,CL */ |
136 | 157 |
{ |
137 | 158 |
j++; |
... | ... |
@@ -150,11 +197,16 @@ static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx |
150 | 150 |
break; |
151 | 151 |
|
152 | 152 |
default: |
153 |
+ if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) { |
|
154 |
+ return 1; |
|
155 |
+ } |
|
153 | 156 |
cli_dbgmsg("yC: Unhandled opcode %x\n", (unsigned char)decryptor_offset[j]); |
154 | 157 |
return 1; |
155 | 158 |
} |
156 | 159 |
} |
157 | 160 |
cl--; |
161 |
+ if (yc_bounds_check(ctx, base, filesize, code, i)) |
|
162 |
+ return 1; |
|
158 | 163 |
code[i] = al; |
159 | 164 |
} |
160 | 165 |
return 0; |
... | ... |
@@ -165,7 +217,7 @@ static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx |
165 | 165 |
/* ========================================================================== */ |
166 | 166 |
/* Main routine which calls all others */ |
167 | 167 |
|
168 |
-int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sections, unsigned int sectcount, uint32_t peoffset, int desc, uint32_t ecx,int16_t offset) { |
|
168 |
+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) { |
|
169 | 169 |
uint32_t ycsect = sections[sectcount].raw+offset; |
170 | 170 |
unsigned int i; |
171 | 171 |
struct pe_image_file_hdr *pe = (struct pe_image_file_hdr*) (fbuf + peoffset); |
... | ... |
@@ -182,7 +234,7 @@ int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sectio |
182 | 182 |
*/ |
183 | 183 |
cli_dbgmsg("yC: offset: %x, length: %x\n", offset, ecx); |
184 | 184 |
cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount); |
185 |
- if (yc_poly_emulator(fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx)) |
|
185 |
+ if (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx)) |
|
186 | 186 |
return 1; |
187 | 187 |
filesize-=sections[sectcount].ursz; |
188 | 188 |
|
... | ... |
@@ -218,7 +270,7 @@ int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sectio |
218 | 218 |
cli_dbgmsg("yC: bad emulation length limit %u\n", max_emu); |
219 | 219 |
return 1; |
220 | 220 |
} |
221 |
- if (yc_poly_emulator(fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), |
|
221 |
+ if (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), |
|
222 | 222 |
fbuf + sections[i].raw, |
223 | 223 |
sections[i].ursz, |
224 | 224 |
max_emu)) |
... | ... |
@@ -25,6 +25,6 @@ |
25 | 25 |
#include "execs.h" |
26 | 26 |
#include "cltypes.h" |
27 | 27 |
|
28 |
-int yc_decrypt(char *, unsigned int, struct cli_exe_section *, unsigned int, uint32_t, int,uint32_t,int16_t); |
|
28 |
+int yc_decrypt(cli_ctx *, char *, unsigned int, struct cli_exe_section *, unsigned int, uint32_t, int,uint32_t,int16_t); |
|
29 | 29 |
|
30 | 30 |
#endif |