Browse code

Actually flag the heuristic if the y0da bounds check failed

Shawn Webb authored on 2014/12/09 05:06:15
Showing 2 changed files
... ...
@@ -2570,9 +2570,26 @@ int cli_scanpe(cli_ctx *ctx)
2570 2570
             cli_jsonstr(pe_json, "Packer", "yC");
2571 2571
 #endif
2572 2572
 
2573
-            cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset);
2574
-            CLI_UNPTEMP("yC",(spinned,exe_sections,0));
2575
-            CLI_UNPRESULTS("yC",(yc_decrypt(ctx, spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0));
2573
+            do {
2574
+                unsigned int yc_unp_num_viruses = ctx->num_viruses;
2575
+                const char *yc_unp_virname = NULL;
2576
+
2577
+                if (ctx->virname)
2578
+                    yc_unp_virname = ctx->virname[0];
2579
+
2580
+                cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset);
2581
+                CLI_UNPTEMP("yC",(spinned,exe_sections,0));
2582
+                CLI_UNPRESULTS("yC",(yc_decrypt(ctx, spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0));
2583
+
2584
+                if (SCAN_ALL && yc_unp_num_viruses != ctx->num_viruses) {
2585
+                    free(exe_sections);
2586
+                    return CL_VIRUS;
2587
+                }
2588
+                else if (ctx->virname && yc_unp_virname != ctx->virname[0]) {
2589
+                    free(exe_sections);
2590
+                    return CL_VIRUS;
2591
+                }
2592
+            } while(0);
2576 2593
         }
2577 2594
     }
2578 2595
 
... ...
@@ -44,6 +44,7 @@
44 44
 static int yc_bounds_check(cli_ctx *ctx, char *base, unsigned int filesize, char *offset, unsigned int bound)
45 45
 {
46 46
       if ((unsigned int)((offset+bound)-base) > filesize) {
47
+          cli_dbgmsg("%s: Bounds check assertion.\n", __func__);
47 48
 #if DO_HEURISTIC
48 49
           cli_append_virus(ctx, "Heuristics.BoundsCheck");
49 50
 #endif
... ...
@@ -84,14 +85,14 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
84 84
   for(i=0;i<ecx&&i<max_emu;i++) /* Byte looper - Decrypts every byte and write it back */
85 85
     {
86 86
         if (yc_bounds_check(ctx, base, filesize, code, i)) {
87
-            return 1;
87
+            return 2;
88 88
         }
89 89
       al = code[i];
90 90
 
91 91
       for(j=0;j<0x30;j++)   /* Poly Decryptor "Emulator" */
92 92
 	{
93 93
         if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
94
-            return 1;
94
+            return 2;
95 95
         }
96 96
 
97 97
 	  switch(decryptor_offset[j])
... ...
@@ -100,7 +101,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
100 100
 	    case '\xEB':	/* JMP short */
101 101
 	      j++;
102 102
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
103
-                return 1;
103
+                return 2;
104 104
             }
105 105
 	      j = j + decryptor_offset[j];
106 106
 	      break;
... ...
@@ -128,7 +129,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
128 128
 	    case '\x04':	/* ADD AL,num */
129 129
 	      j++;
130 130
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
131
-                return 1;
131
+                return 2;
132 132
             }
133 133
 	      al = al + decryptor_offset[j];
134 134
 	      break;
... ...
@@ -136,7 +137,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
136 136
 	    case '\x34':	/* XOR AL,num */
137 137
 	      j++;
138 138
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
139
-                return 1;
139
+                return 2;
140 140
             }
141 141
 	      al = al ^ decryptor_offset[j];
142 142
 	      break;
... ...
@@ -144,7 +145,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
144 144
 	    case '\x2C':	/* SUB AL,num */
145 145
 	      j++;
146 146
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
147
-                return 1;
147
+                return 2;
148 148
             }
149 149
 	      al = al - decryptor_offset[j];
150 150
 	      break;
... ...
@@ -153,13 +154,13 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
153 153
 	    case '\xC0':
154 154
 	      j++;
155 155
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
156
-                return 1;
156
+                return 2;
157 157
             }
158 158
 	      if(decryptor_offset[j]=='\xC0') /* ROL AL,num */
159 159
 		{
160 160
 		  j++;
161 161
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
162
-                return 1;
162
+                return 2;
163 163
             }
164 164
 		  CLI_ROL(al,decryptor_offset[j]);
165 165
 		}
... ...
@@ -167,7 +168,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
167 167
 		{
168 168
 		  j++;
169 169
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
170
-                return 1;
170
+                return 2;
171 171
             }
172 172
 		  CLI_ROR(al,decryptor_offset[j]);
173 173
 		}
... ...
@@ -176,7 +177,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
176 176
 	    case '\xD2':
177 177
 	      j++;
178 178
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
179
-                return 1;
179
+                return 2;
180 180
             }
181 181
 	      if(decryptor_offset[j]=='\xC8') /* ROR AL,CL */
182 182
 		{
... ...
@@ -197,7 +198,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
197 197
 
198 198
 	    default:
199 199
             if (yc_bounds_check(ctx, base, filesize, decryptor_offset, j)) {
200
-                return 1;
200
+                return 2;
201 201
             }
202 202
 	      cli_dbgmsg("yC: Unhandled opcode %x\n", (unsigned char)decryptor_offset[j]);
203 203
 	      return 1;
... ...
@@ -205,7 +206,7 @@ static int yc_poly_emulator(cli_ctx *ctx, char *base, unsigned int filesize, cha
205 205
 	}
206 206
       cl--;
207 207
             if (yc_bounds_check(ctx, base, filesize, code, i))
208
-                return 1;
208
+                return 2;
209 209
       code[i] = al;
210 210
     }
211 211
   return 0;
... ...
@@ -233,8 +234,12 @@ int yc_decrypt(cli_ctx *ctx, char *fbuf, unsigned int filesize, struct cli_exe_s
233 233
   */
234 234
   cli_dbgmsg("yC: offset: %x, length: %x\n", offset, ecx);
235 235
   cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount);
236
-  if (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx))
237
-    return 1;
236
+  switch (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx)) {
237
+  case 2:
238
+      return CL_VIRUS;
239
+  case 1:
240
+      return CL_EUNPACK;
241
+  }
238 242
   filesize-=sections[sectcount].ursz;
239 243
 
240 244
   /* 
... ...
@@ -269,11 +274,15 @@ int yc_decrypt(cli_ctx *ctx, char *fbuf, unsigned int filesize, struct cli_exe_s
269 269
       cli_dbgmsg("yC: bad emulation length limit %u\n", max_emu);
270 270
       return 1;
271 271
     }
272
-    if (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), 
272
+    switch (yc_poly_emulator(ctx, fbuf, filesize, fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), 
273 273
 			 fbuf + sections[i].raw, 
274 274
 			 sections[i].ursz, 
275
-			 max_emu))
276
-      return 1;
275
+			 max_emu)) {
276
+    case 2:
277
+        return CL_VIRUS;
278
+    case 1:
279
+        return CL_EUNPACK;
280
+    }
277 281
   }
278 282
 
279 283
   /* Remove yC section */
... ...
@@ -291,7 +300,7 @@ int yc_decrypt(cli_ctx *ctx, char *fbuf, unsigned int filesize, struct cli_exe_s
291 291
 
292 292
   if (cli_writen(desc, fbuf, filesize)==-1) {
293 293
     cli_dbgmsg("yC: Cannot write unpacked file\n");
294
-    return 1;
294
+    return CL_EUNPACK;
295 295
   }
296
-  return 0;
296
+  return CL_SUCCESS;
297 297
 }