Browse code

bb#11210: Apply a basic fix for y0da

Shawn Webb authored on 2014/12/03 05:15:55
Showing 4 changed files
... ...
@@ -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
31 31
Binary files a/test/.split/split.clam-yc.exeab and b/test/.split/split.clam-yc.exeab differ