git-svn: trunk@2088
aCaB authored on 2006/07/17 08:20:13... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Mon Jul 17 01:17:40 CEST 2006 (acab) |
|
2 |
+------------------------------------ |
|
3 |
+ * libclamav: wwpack32 handler secured and activated |
|
4 |
+ |
|
1 | 5 |
Sun Jul 16 21:42:58 CEST 2006 (acab) |
2 | 6 |
------------------------------------ |
3 | 7 |
* libclamav: added support for wwpack32 - not yet activated |
... | ... |
@@ -41,9 +41,7 @@ |
41 | 41 |
#include "spin.h" |
42 | 42 |
#include "upx.h" |
43 | 43 |
#include "yc.h" |
44 |
-#ifdef WWP32 |
|
45 | 44 |
#include "wwunpack.h" |
46 |
-#endif |
|
47 | 45 |
#include "scanners.h" |
48 | 46 |
#include "rebuildpe.h" |
49 | 47 |
#include "str.h" |
... | ... |
@@ -1858,7 +1856,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1858 | 1858 |
} |
1859 | 1859 |
} |
1860 | 1860 |
|
1861 |
-#ifdef WWP32 |
|
1861 |
+ |
|
1862 | 1862 |
/* WWPack */ |
1863 | 1863 |
|
1864 | 1864 |
if(nsections > 1 && |
... | ... |
@@ -1870,7 +1868,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1870 | 1870 |
uint32_t headsize=EC32(section_hdr[nsections - 1].PointerToRawData); |
1871 | 1871 |
char *dest, *wwp; |
1872 | 1872 |
|
1873 |
- for(i = 0 ; i < nsections-1; i++) { |
|
1873 |
+ for(i = 0 ; i < (unsigned int)nsections-1; i++) { |
|
1874 | 1874 |
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err); |
1875 | 1875 |
if (!err && offset<headsize) headsize=offset; |
1876 | 1876 |
} |
... | ... |
@@ -1903,7 +1901,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1903 | 1903 |
return CL_EIO; |
1904 | 1904 |
} |
1905 | 1905 |
|
1906 |
- for(i = 0 ; i < nsections-1; i++) { |
|
1906 |
+ for(i = 0 ; i < (unsigned int)nsections-1; i++) { |
|
1907 | 1907 |
if(section_hdr[i].SizeOfRawData) { |
1908 | 1908 |
uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err); |
1909 | 1909 |
|
... | ... |
@@ -1979,7 +1977,6 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1979 | 1979 |
cli_dbgmsg("WWPpack: Decompression failed\n"); |
1980 | 1980 |
} |
1981 | 1981 |
} |
1982 |
-#endif |
|
1983 | 1982 |
|
1984 | 1983 |
|
1985 | 1984 |
/* to be continued ... */ |
... | ... |
@@ -19,10 +19,12 @@ |
19 | 19 |
|
20 | 20 |
/* |
21 | 21 |
** wwunpack.c |
22 |
+** |
|
22 | 23 |
** 09/07/2k6 - Campioni del mondo!!! |
23 | 24 |
** 14/07/2k6 - RCE'ed + standalone sect unpacker |
24 | 25 |
** 15/07/2k6 - Merge started |
25 | 26 |
** 17/07/2k6 - Rebuild |
27 |
+** 18/07/2k6 - Secured (well, hopefully...) |
|
26 | 28 |
** |
27 | 29 |
*/ |
28 | 30 |
|
... | ... |
@@ -37,13 +39,14 @@ |
37 | 37 |
/* |
38 | 38 |
** TODO: |
39 | 39 |
** |
40 |
-** use cli_readint32 |
|
41 |
-** add bound checks |
|
40 |
+** review |
|
42 | 41 |
** check eax vs al |
42 |
+** check the missed samples |
|
43 |
+** (check for dll's) |
|
44 |
+** (have a look at older versions) |
|
43 | 45 |
** |
44 | 46 |
*/ |
45 | 47 |
|
46 |
-#ifdef WWP32 |
|
47 | 48 |
|
48 | 49 |
#if HAVE_CONFIG_H |
49 | 50 |
#include "clamav-config.h" |
... | ... |
@@ -62,7 +65,19 @@ |
62 | 62 |
#include "others.h" |
63 | 63 |
#include "wwunpack.h" |
64 | 64 |
|
65 |
-static void getbits(uint8_t X, uint32_t *eax, uint32_t *bitmap, uint8_t *bits, char **src) { |
|
65 |
+#define VAALIGN(s) (((s)/0x1000+((s)%0x1000!=0))*0x1000) |
|
66 |
+#define FIXVS(v, r) (VAALIGN((r>v)?r:v)) |
|
67 |
+ |
|
68 |
+ |
|
69 |
+static int getbitmap(uint32_t *bitmap, char **src, uint8_t *bits, char *buf, unsigned int size) { |
|
70 |
+ if (! CLI_ISCONTAINED(buf, size, *src, 4)) return 1; |
|
71 |
+ *bitmap=cli_readint32(*src); |
|
72 |
+ *src+=4; |
|
73 |
+ *bits=32; |
|
74 |
+ return 0; |
|
75 |
+} |
|
76 |
+ |
|
77 |
+static int getbits(uint8_t X, uint32_t *eax, uint32_t *bitmap, uint8_t *bits, char **src, char *buf, unsigned int size) { |
|
66 | 78 |
*eax=*bitmap>>(32-X); |
67 | 79 |
if (*bits>X) { |
68 | 80 |
*bitmap<<=X; |
... | ... |
@@ -70,21 +85,19 @@ static void getbits(uint8_t X, uint32_t *eax, uint32_t *bitmap, uint8_t *bits, c |
70 | 70 |
} else if (*bits<X) { |
71 | 71 |
X-=*bits; |
72 | 72 |
*eax>>=X; |
73 |
- *bitmap=*(uint32_t *)(*src); |
|
74 |
- *src+=4; |
|
73 |
+ if (getbitmap(bitmap, src, bits, buf, size)) return 1; |
|
75 | 74 |
*eax<<=X; |
76 | 75 |
*eax|=*bitmap>>(32-X); |
77 | 76 |
*bitmap<<=X; |
78 |
- *bits=32-X; |
|
77 |
+ *bits-=X; |
|
79 | 78 |
} else { |
80 |
- *bitmap=*(uint32_t *)(*src); |
|
81 |
- *src+=4; |
|
82 |
- *bits=32; |
|
79 |
+ if (getbitmap(bitmap, src, bits, buf, size)) return 1; |
|
83 | 80 |
} |
81 |
+ return 0; |
|
84 | 82 |
} |
85 | 83 |
|
86 |
- |
|
87 |
-static void wunpsect(char *src, char *dst) { |
|
84 |
+static int wunpsect(char *packed, char *unpacked, unsigned int psize, unsigned int usize) { |
|
85 |
+ char *src=packed, *dst=unpacked; |
|
88 | 86 |
uint32_t bitmap, eax; |
89 | 87 |
uint8_t bits; |
90 | 88 |
unsigned int lostbit, getmorestuff; |
... | ... |
@@ -92,37 +105,36 @@ static void wunpsect(char *src, char *dst) { |
92 | 92 |
uint16_t backsize; |
93 | 93 |
uint8_t oal; |
94 | 94 |
|
95 |
- eax=bitmap=*(uint32_t *)src; |
|
96 |
- src+=4; |
|
97 |
- bits=32; |
|
98 |
- |
|
95 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
96 |
+ eax=bitmap; |
|
99 | 97 |
|
100 | 98 |
while (1) { |
101 | 99 |
lostbit=bitmap>>31; |
102 | 100 |
bitmap<<=1; |
103 | 101 |
bits--; |
104 | 102 |
if (!lostbit && bits) { |
103 |
+ if (!(CLI_ISCONTAINED(packed, psize, src, 1) && CLI_ISCONTAINED(unpacked, usize, dst, 1))) return 1; |
|
105 | 104 |
*dst++=*src++; |
106 | 105 |
continue; |
107 | 106 |
} |
108 | 107 |
|
109 | 108 |
if (!bits) { |
110 |
- eax=bitmap=*(uint32_t *)src; |
|
111 |
- bits=32; |
|
112 |
- src+=4; |
|
109 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
110 |
+ eax=bitmap; |
|
113 | 111 |
if (!lostbit) { |
112 |
+ if (!(CLI_ISCONTAINED(packed, psize, src, 1) && CLI_ISCONTAINED(unpacked, usize, dst, 1))) return 1; |
|
114 | 113 |
*dst++=*src++; |
115 | 114 |
continue; |
116 | 115 |
} |
117 | 116 |
} |
118 | 117 |
|
119 |
- getbits(2, &eax, &bitmap, &bits, &src); |
|
118 |
+ if (getbits(2, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
120 | 119 |
|
121 | 120 |
if ((eax&0xff)>=3) { |
122 | 121 |
/* 50ff - two_bytes */ |
123 | 122 |
uint8_t fetchbits; |
124 | 123 |
|
125 |
- getbits(2, &eax, &bitmap, &bits, &src); |
|
124 |
+ if (getbits(2, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
126 | 125 |
fetchbits=(eax&0xff)+5; |
127 | 126 |
eax--; |
128 | 127 |
if ((int16_t)(eax&0xffff)<=0) { |
... | ... |
@@ -136,10 +148,11 @@ static void wunpsect(char *src, char *dst) { |
136 | 136 |
backbytes-=0x9f; |
137 | 137 |
} |
138 | 138 |
/* 5125 */ |
139 |
- getbits(fetchbits, &eax, &bitmap, &bits, &src); |
|
139 |
+ if (getbits(fetchbits, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
140 | 140 |
if ((eax&0xffff)==0x1ff) break; |
141 | 141 |
eax&=0xffff; |
142 | 142 |
backbytes+=eax; |
143 |
+ if (!(CLI_ISCONTAINED(unpacked, usize, dst-backbytes, 2) && CLI_ISCONTAINED(unpacked, usize, dst, 2))) return 1; |
|
143 | 144 |
*dst=*(dst-backbytes); |
144 | 145 |
dst++; |
145 | 146 |
*dst=*(dst-backbytes); |
... | ... |
@@ -150,9 +163,9 @@ static void wunpsect(char *src, char *dst) { |
150 | 150 |
/* 5143 - more_backbytes */ |
151 | 151 |
oal=eax&0xff; |
152 | 152 |
getmorestuff=1; |
153 |
- /* FIXME: pushf */ |
|
153 |
+ |
|
154 | 154 |
|
155 |
- getbits(3, &eax, &bitmap, &bits, &src); |
|
155 |
+ if (getbits(3, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
156 | 156 |
if ((eax&0xff)<=3) { |
157 | 157 |
lostbit=0; |
158 | 158 |
if ((eax&0xff)==3) { |
... | ... |
@@ -160,14 +173,12 @@ static void wunpsect(char *src, char *dst) { |
160 | 160 |
lostbit=bitmap>>31; |
161 | 161 |
bitmap<<=1; |
162 | 162 |
bits--; |
163 |
- if (!bits) { |
|
164 |
- bitmap=*(uint32_t *)src; |
|
165 |
- bits=32; |
|
166 |
- src+=4; |
|
163 |
+ if (!bits) { |
|
164 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
167 | 165 |
} |
168 | 166 |
} |
169 | 167 |
eax=eax+lostbit+5; |
170 |
- /* FIXME: jmp more_bb_commondock */ |
|
168 |
+ /* jmp more_bb_commondock */ |
|
171 | 169 |
} else { /* >3 */ |
172 | 170 |
/* 5160 - more_bb_morethan3 */ |
173 | 171 |
if ((eax&0xff)==4) { |
... | ... |
@@ -175,27 +186,25 @@ static void wunpsect(char *src, char *dst) { |
175 | 175 |
lostbit=bitmap>>31; |
176 | 176 |
bitmap<<=1; |
177 | 177 |
bits--; |
178 |
- if (!bits) { |
|
179 |
- bitmap=*(uint32_t *)src; |
|
180 |
- bits=32; |
|
181 |
- src+=4; |
|
178 |
+ if (!bits) { |
|
179 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
182 | 180 |
} |
183 | 181 |
eax=eax+lostbit+6; |
184 |
- /* FIXME: jmp more_bb_commondock */ |
|
182 |
+ /* jmp more_bb_commondock */ |
|
185 | 183 |
} else { /* !=4 */ |
186 | 184 |
eax+=7; |
187 | 185 |
if ((eax&0xff)>=0x0d) { |
188 | 186 |
getmorestuff=0; /* jmp more_bb_PASTcommondock */ |
189 | 187 |
if ((eax&0xff)==0x0d) { |
190 | 188 |
/* 5179 */ |
191 |
- getbits(0x0e, &eax, &bitmap, &bits, &src); |
|
189 |
+ if (getbits(0x0e, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
192 | 190 |
eax+=0x1fe1; |
193 | 191 |
} else { |
194 | 192 |
/* 516c */ |
195 |
- getbits(0x0f, &eax, &bitmap, &bits, &src); |
|
193 |
+ if (getbits(0x0f, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
196 | 194 |
eax+=0x5fe1; |
197 | 195 |
} |
198 |
- /* FIXME: jmp more_bb_PASTcommondock */ |
|
196 |
+ /* jmp more_bb_PASTcommondock */ |
|
199 | 197 |
} /* al >= 0d */ |
200 | 198 |
} /* al != 4 */ |
201 | 199 |
} /* >3 */ |
... | ... |
@@ -203,14 +212,14 @@ static void wunpsect(char *src, char *dst) { |
203 | 203 |
if (getmorestuff) { |
204 | 204 |
/* 5192 - more_bb_commondock */ |
205 | 205 |
uint16_t bk=(1<<(eax&0xff))-0x1f; |
206 |
- getbits((eax&0xff), &eax, &bitmap, &bits, &src); |
|
206 |
+ if (getbits((eax&0xff), &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
207 | 207 |
eax+=bk; |
208 | 208 |
} |
209 | 209 |
|
210 | 210 |
/* 51a7 - more_bb_pastcommondock */ |
211 | 211 |
eax&=0xffff; |
212 | 212 |
backbytes=eax; |
213 |
- backsize=3+(oal!=1); /* FIXME: move up and remove oal */ |
|
213 |
+ backsize=3+(oal!=1); |
|
214 | 214 |
|
215 | 215 |
if (oal<1) { /* overrides backsize */ |
216 | 216 |
/* 51bb - more_bb_again */ |
... | ... |
@@ -219,10 +228,8 @@ static void wunpsect(char *src, char *dst) { |
219 | 219 |
lostbit=bitmap>>31; |
220 | 220 |
bitmap<<=1; |
221 | 221 |
bits--; |
222 |
- if (!bits) { |
|
223 |
- bitmap=*(uint32_t *)src; |
|
224 |
- bits=32; |
|
225 |
- src+=4; |
|
222 |
+ if (!bits) { |
|
223 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
226 | 224 |
} |
227 | 225 |
if (!lostbit) { |
228 | 226 |
/* 51c2 */ |
... | ... |
@@ -230,26 +237,24 @@ static void wunpsect(char *src, char *dst) { |
230 | 230 |
lostbit=bitmap>>31; |
231 | 231 |
bitmap<<=1; |
232 | 232 |
bits--; |
233 |
- if (!bits) { |
|
234 |
- bitmap=*(uint32_t *)src; |
|
235 |
- bits=32; |
|
236 |
- src+=4; |
|
233 |
+ if (!bits) { |
|
234 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
237 | 235 |
} |
238 | 236 |
eax=5+lostbit; |
239 |
- /* FIXME: jmp setsize_and_backcopy */ |
|
237 |
+ /* jmp setsize_and_backcopy */ |
|
240 | 238 |
} else { |
241 | 239 |
/* 51ce - more_bb_again_and_again */ |
242 |
- getbits(3, &eax, &bitmap, &bits, &src); |
|
240 |
+ if (getbits(3, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
243 | 241 |
if (eax&0xff) { |
244 | 242 |
/* 51e6 */ |
245 | 243 |
eax+=6; |
246 |
- /* FIXME: jmp setsize_and_backcopy */ |
|
244 |
+ /* jmp setsize_and_backcopy */ |
|
247 | 245 |
} else { |
248 |
- getbits(4, &eax, &bitmap, &bits, &src); |
|
246 |
+ if (getbits(4, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
249 | 247 |
if (eax&0xff) { |
250 | 248 |
/* 51e4 */ |
251 | 249 |
eax+=7+6; |
252 |
- /* FIXME: jmp setsize_and_backcopy */ |
|
250 |
+ /* jmp setsize_and_backcopy */ |
|
253 | 251 |
} else { |
254 | 252 |
/* 51ea - OMGWTF */ |
255 | 253 |
uint8_t c=4; |
... | ... |
@@ -265,19 +270,17 @@ static void wunpsect(char *src, char *dst) { |
265 | 265 |
lostbit=bitmap>>31; |
266 | 266 |
bitmap<<=1; |
267 | 267 |
bits--; |
268 |
- if (!bits) { |
|
269 |
- bitmap=*(uint32_t *)src; |
|
270 |
- bits=32; |
|
271 |
- src+=4; |
|
268 |
+ if (!bits) { |
|
269 |
+ if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1; |
|
272 | 270 |
} |
273 | 271 |
c++; |
274 | 272 |
if (!lostbit) continue; |
275 |
- getbits(c, &eax, &bitmap, &bits, &src); |
|
273 |
+ if (getbits(c, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
276 | 274 |
d+=eax&0xff; |
277 | 275 |
eax&=0xffffff00; |
278 | 276 |
eax|=d&0xff; |
279 | 277 |
} else { |
280 |
- getbits(14, &eax, &bitmap, &bits, &src); |
|
278 |
+ if (getbits(14, &eax, &bitmap, &bits, &src, packed, psize)) return 1; |
|
281 | 279 |
} |
282 | 280 |
break; |
283 | 281 |
} /* while */ |
... | ... |
@@ -289,13 +292,15 @@ static void wunpsect(char *src, char *dst) { |
289 | 289 |
} |
290 | 290 |
|
291 | 291 |
/* 521e - backcopy */ |
292 |
+ if (!(CLI_ISCONTAINED(unpacked, usize, dst-backbytes, backsize) && CLI_ISCONTAINED(unpacked, usize, dst, backsize))) return 1; |
|
292 | 293 |
while(backsize--){ |
293 | 294 |
*dst=*(dst-backbytes); |
294 | 295 |
dst++; |
295 | 296 |
} |
296 | 297 |
|
297 | 298 |
} /* while true */ |
298 |
- |
|
299 |
+ |
|
300 |
+ return 0; |
|
299 | 301 |
} |
300 | 302 |
|
301 | 303 |
int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_t wwprva, uint32_t e_lfanew, char *wwp, uint32_t wwpsz, uint16_t sects) { |
... | ... |
@@ -310,7 +315,7 @@ int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_ |
310 | 310 |
cli_dbgmsg("WWPack: next chunk out ouf file, giving up.\n"); |
311 | 311 |
return 1; |
312 | 312 |
} |
313 |
- if ((csize=cli_readint32(stuff+8)*4)!=cli_readint32(stuff+12)+4) { |
|
313 |
+ if ((csize=cli_readint32(stuff+8)*4)!=(uint32_t)cli_readint32(stuff+12)+4) { |
|
314 | 314 |
cli_dbgmsg("WWPack: inconsistent/hacked data, go figure!\n"); |
315 | 315 |
return 1; |
316 | 316 |
} |
... | ... |
@@ -325,7 +330,11 @@ int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_ |
325 | 325 |
return 1; |
326 | 326 |
} |
327 | 327 |
memcpy(packed, unpacked, csize); |
328 |
- wunpsect(packed, unpacked); |
|
328 |
+ if (wunpsect(packed, unpacked, csize, exesz-(unpacked-exe))) { |
|
329 |
+ free(packed); |
|
330 |
+ cli_dbgmsg("WWPack: unpacking failed.\n"); |
|
331 |
+ return 1; |
|
332 |
+ } |
|
329 | 333 |
free(packed); |
330 | 334 |
if (!stuff[16]) break; |
331 | 335 |
stuff+=17; |
... | ... |
@@ -339,9 +348,6 @@ int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_ |
339 | 339 |
cli_dbgmsg("WWPack: found OEP @%x\n", csize); |
340 | 340 |
cli_writeint32(stuff+0x28, csize); |
341 | 341 |
|
342 |
-#define VAALIGN(s) (((s)/0x1000+((s)%0x1000!=0))*0x1000) |
|
343 |
-#define FIXVS(v, r) (VAALIGN((r>v)?r:v)) |
|
344 |
- |
|
345 | 342 |
stuff+=0xf8; |
346 | 343 |
while (sects--) { |
347 | 344 |
uint32_t v=cli_readint32(stuff+8); |
... | ... |
@@ -354,8 +360,5 @@ int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_ |
354 | 354 |
} |
355 | 355 |
memset(stuff, 0, 0x28); |
356 | 356 |
|
357 |
- cli_dbgmsg("WWPack: Successfully rebuilt\n", csize); |
|
358 | 357 |
return 0; |
359 | 358 |
} |
360 |
- |
|
361 |
-#endif |