Bug Summary

File:libclamav/aspack.c
Location:line 149, column 3
Description:Value stored to 'i' is never read

Annotated Source Code

1/*
2 * Copyright (C) 2007-2008 Sourcefire, Inc.
3 *
4 * Authors: Luciano Giuseppe 'Pnluck', Alberto Wu
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21#include <string.h>
22
23#include "clamav.h"
24#include "cltypes.h"
25#include "execs.h"
26#include "others.h"
27#include "rebuildpe.h"
28#include "aspack.h"
29
30
31struct DICT_HELPER {
32 uint32_t *starts;
33 uint8_t *ends;
34 uint32_t size;
35};
36
37struct ASPK {
38 uint32_t bitpos;
39 uint32_t hash;
40 uint32_t init_array[58];
41 struct DICT_HELPER dict_helper[4];
42 uint8_t *input;
43 uint8_t *iend;
44 uint8_t *decrypt_dict;
45 uint32_t decarray3[4][24];
46 uint32_t decarray4[4][24];
47 int dict_ok;
48 uint8_t array2[758];
49 uint8_t array1[19];
50};
51
52
53static inline int readstream(struct ASPK *stream) {
54 while (stream->bitpos >= 8) {
55 if (stream->input>=stream->iend) return 0;
56 stream->hash = (stream->hash << 8) | *stream->input;
57 stream->input++;
58 stream->bitpos -= 8;
59 }
60 return 1;
61}
62
63static uint32_t getdec(struct ASPK *stream, uint8_t which, int *err) {
64 uint32_t ret;
65 uint8_t pos;
66 uint32_t *d3 = stream->decarray3[which];
67 uint32_t *d4 = stream->decarray4[which];
68
69 *err=1;
70
71 if (!readstream(stream)) return 0;
72
73 ret = (stream->hash >> (8 - stream->bitpos)) & 0xfffe00;
74
75 if (ret < d3[8]) {
76 if ((ret>>16) >= 0x100) return 0;
77 if (!(pos=stream->dict_helper[which].ends[ret>>16]) || pos>= 24) return 0; /* 0<pos<24 */
78 } else {
79 if (ret < d3[10]) {
80 if (ret < d3[9]) pos = 9;
81 else pos = 10;
82 } else {
83 if (ret < d3[11] ) pos = 11;
84 else {
85 if (ret < d3[12]) pos = 12;
86 else {
87 if (ret < d3[13]) pos = 13;
88 else {
89 if (ret < d3[14]) pos = 14;
90 else pos = 15;
91 }
92 }
93 }
94 }
95 }
96
97 stream->bitpos += pos;
98 ret = ((ret - d3[pos-1]) >> (24 - pos)) + d4[pos];
99
100 if (ret >= stream->dict_helper[which].size) return 0;
101 ret = stream->dict_helper[which].starts[ret];
102
103 *err=0;
104 return ret;
105}
106
107
108static uint8_t build_decrypt_array(struct ASPK *stream, uint8_t* array, uint8_t which) {
109 uint32_t sum = 0, counter = 23, i, endoff = 0, bus[18], dict[18];
110
111 uint32_t *d3 = stream->decarray3[which];
112 uint32_t *d4 = stream->decarray4[which];
113
114 memset(bus,0,sizeof(bus));
115 memset(dict,0,sizeof(dict));
116
117 for (i = 0; i < stream->dict_helper[which].size; i++) {
118 /* within bounds - see comments in build_decrypt_dictionaries */
119 if (array[i] > 17) return 0;
120 bus[array[i]]++;
121 }
122
123 d3[0] = 0;
124 d4[0] = 0;
125
126 i = 0;
127 while (counter >= 9) { /* 0<=i<=14 */
128 sum += (bus[i+1] << counter);
129 if (sum > 0x1000000) return 0;
130
131 d3[i+1] = sum;
132 d4[i+1] = dict[i+1] = bus[i] + d4[i];
133
134 if (counter >= 0x10) {
135 uint32_t old = endoff;
136 endoff = d3[i+1] >> 0x10;
137 if (endoff-old) {
138 if (!CLI_ISCONTAINED(stream->dict_helper[which].ends, 0x100, stream->dict_helper[which].ends+old, endoff-old)((0x100) > 0 && (endoff-old) > 0 && (size_t
)(endoff-old) <= (size_t)(0x100) && (stream->dict_helper
[which].ends+old) >= (stream->dict_helper[which].ends) &&
((stream->dict_helper[which].ends+old) + (endoff-old)) <=
((stream->dict_helper[which].ends) + (0x100)) && (
(stream->dict_helper[which].ends+old) + (endoff-old)) >
(stream->dict_helper[which].ends) && (stream->
dict_helper[which].ends+old) < ((stream->dict_helper[which
].ends) + (0x100)))
) return 0;
139 memset((stream->dict_helper[which].ends + old), i+1, endoff-old);
140 }
141 }
142
143 i++;
144 counter--;
145 }
146
147 if (sum != 0x1000000) return 0;
148
149 i = 0;
Value stored to 'i' is never read
150 for (i=0; i < stream->dict_helper[which].size; i++) {
151 if (array[i]) { /* within bounds - see above */
152 if (array[i] > 17) return 0;
153 if (dict[array[i]]>=stream->dict_helper[which].size) return 0;
154 stream->dict_helper[which].starts[dict[array[i]]] = i;
155 dict[array[i]]++;
156 }
157 }
158
159 return 1;
160}
161
162
163static uint8_t getbits(struct ASPK *stream, uint32_t num, int *err) {
164 uint8_t retvalue;
165
166 if (!readstream(stream)) {
167 *err=1;
168 return 0;
169 }
170
171 *err = 0;
172 retvalue = ((stream->hash >> (8 - stream->bitpos))&0xffffff) >> (24 - num);
173 stream->bitpos += num;
174
175 return retvalue;
176}
177
178
179static int build_decrypt_dictionaries(struct ASPK *stream) {
180 unsigned int counter;
181 uint32_t ret;
182 int oob;
183
184 if (!getbits(stream, 1, &oob)) memset(stream->decrypt_dict, 0, 0x2f5);
185 if (oob) return 0;
186
187 for (counter = 0; counter < 19; counter++) {
188 stream->array1[counter]=getbits(stream, 4, &oob);
189 if (oob) return 0;
190 }
191
192 if (!build_decrypt_array(stream, stream->array1, 3)) return 0; /* array1[19] - [3].size=19 */
193
194 counter = 0;
195 while (counter < 757) {
196 ret = getdec(stream, 3, &oob);
197 if (oob) return 0;
198 if (ret >= 16) {
199 if (ret != 16) {
200 if (ret == 17) ret = 3 + getbits(stream, 3, &oob);
201 else ret = 11 + getbits(stream, 7, &oob);
202 if (oob) return 0;
203 while (ret) {
204 if (counter >= 757) break;
205 stream->array2[1+counter] = 0;
206 counter++;
207 ret--;
208 }
209 } else {
210 ret = 3 + getbits(stream, 2, &oob);
211 if (oob) return 0;
212 while (ret) {
213 if (counter >= 757) break;
214 stream->array2[1+counter] = stream->array2[counter];
215 counter++;
216 ret--;
217 }
218 }
219 } else {
220 stream->array2[1+counter] = (stream->decrypt_dict[counter] + ret) & 0xF;
221 counter++;
222 }
223 }
224
225 if (!build_decrypt_array(stream, &stream->array2[1], 0) /* array2[758-1=757] - [0].size=721 */ || !build_decrypt_array(stream, &stream->array2[722], 1) /* array2[758-722=36] - [1].size=28 */ || !build_decrypt_array(stream, &stream->array2[750], 2) /* array2[758-750=8] - [2].size=8 */ ) return 0;
226
227 stream->dict_ok = 0;
228 for (counter = 0; counter < 8; counter++) {
229 if (stream->array2[750+counter] != 3) {
230 stream->dict_ok = 1;
231 break;
232 }
233 }
234
235 memcpy(stream->decrypt_dict,&stream->array2[1],757);
236
237 return 1;
238}
239
240
241static int decrypt(struct ASPK *stream, uint8_t *stuff, uint32_t size, uint8_t *output) {
242 /* ep+6d6 -> ep+748 = 0x72*/
243 uint32_t gen, backsize, backbytes, useold, counter = 0;
244 uint32_t hist[4]={0,0,0,0};
245 int oob;
246
247 while (counter < size) {
248 gen = getdec(stream, 0, &oob);
249 if (oob) return 0;
250 if (gen < 256) { /* implied within bounds */
251 output[counter] = (uint8_t)gen;
252 counter++;
253 continue;
254 }
255 if (gen >= 720) {
256 if (!build_decrypt_dictionaries(stream)) return 0;
257 continue;
258 }
259 if ((backbytes = (gen - 256) >> 3)>=58) return 0; /* checks init_array + stuff */
260 backsize = ((gen - 256) & 7) + 2;
261 if ((backsize-2)==7) {
262 uint8_t hlp;
263 gen = getdec(stream, 1, &oob);
264 if (oob || gen>=0x56) return 0;
265 hlp = stuff[gen + 0x1c];
266 if (!readstream(stream)) return 0;
267 backsize += stuff[gen] + (( (stream->hash >> (8 - stream->bitpos)) & 0xffffff ) >> (0x18 - hlp));
268 stream->bitpos += hlp;
269 }
270
271 useold = stream->init_array[backbytes];
272 gen = stuff[backbytes + 0x38];
273
274 if (!stream->dict_ok || gen < 3) {
275 if (!readstream(stream)) return 0;
276 useold += ((stream->hash >> ( 8 - stream->bitpos) ) & 0xffffff) >> (24 - gen);
277 stream->bitpos += gen;
278 } else {
279 gen -= 3;
280 if (!readstream(stream)) return 0;
281 useold += ((((stream->hash >> ( 8 - stream->bitpos)) & 0xffffff) >> (24 - gen)) * 8);
282 stream->bitpos += gen;
283 useold += getdec(stream, 2, &oob);
284 if (oob) return 0;
285 }
286
287 if (useold < 3) {
288 backbytes = hist[useold];
289 if (useold != 0) {
290 hist[useold] = hist[0];
291 hist[0] = backbytes;
292 }
293 } else {
294 hist[2] = hist[1];
295 hist[1] = hist[0];
296 hist[0] = backbytes = useold-3;
297 }
298
299 backbytes++;
300
301 if (!backbytes || backbytes>counter || backsize>size-counter) return 0;
302 while (backsize--) {
303 output[counter] = output[counter-backbytes];
304 counter++;
305 }
306 }
307
308 return 1;
309}
310
311
312static int decomp_block(struct ASPK *stream, uint32_t size, uint8_t *stuff, uint8_t *output) {
313 memset(stream->decarray3,0,sizeof(stream->decarray3));
314 memset(stream->decarray4,0,sizeof(stream->decarray4));
315 memset(stream->decrypt_dict, 0, 757);
316 stream->bitpos = 0x20;
317 if (!build_decrypt_dictionaries(stream)) return 0;
318 return decrypt(stream, stuff, size, output);
319}
320
321#define INIT_DICT_HELPER(n,sz)stream.dict_helper[n].starts = (uint32_t *)wrkbuf; stream.dict_helper
[n].ends = &wrkbuf[sz * sizeof(uint32_t)]; stream.dict_helper
[n].size = sz; wrkbuf = &wrkbuf[sz * sizeof(uint32_t) + 0x100
];
\
322 stream.dict_helper[n].starts = (uint32_t *)wrkbuf; \
323 stream.dict_helper[n].ends = &wrkbuf[sz * sizeof(uint32_t)]; \
324 stream.dict_helper[n].size = sz; \
325 wrkbuf = &wrkbuf[sz * sizeof(uint32_t) + 0x100];
326
327int unaspack212(uint8_t *image, unsigned int size, struct cli_exe_section *sections, uint16_t sectcount, uint32_t ep, uint32_t base, int f) {
328 struct ASPK stream;
329 uint32_t i=0, j=0;
330 uint8_t *blocks = image+ep+0x57c, *wrkbuf;
331 uint32_t block_rva = 1, block_size;
332 struct cli_exe_section *outsects;
333
334 if (!(wrkbuf = cli_calloc(0x1800, sizeof(uint8_t)))) {
335 cli_dbgmsg(!__builtin_expect(!!(cli_debug_flag), 0)) ? (void)0 : cli_dbgmsg_internal("Aspack: Unable to allocate dictionary\n");
336 return 0;
337 }
338
339 INIT_DICT_HELPER(0, 721)stream.dict_helper[0].starts = (uint32_t *)wrkbuf; stream.dict_helper
[0].ends = &wrkbuf[721 * sizeof(uint32_t)]; stream.dict_helper
[0].size = 721; wrkbuf = &wrkbuf[721 * sizeof(uint32_t) +
0x100];
; /* dictionary -> dictionary + b44 */
340 INIT_DICT_HELPER(1, 28)stream.dict_helper[1].starts = (uint32_t *)wrkbuf; stream.dict_helper
[1].ends = &wrkbuf[28 * sizeof(uint32_t)]; stream.dict_helper
[1].size = 28; wrkbuf = &wrkbuf[28 * sizeof(uint32_t) + 0x100
];
; /* dictionary + c44 -> dictionary + cb4 */
341 INIT_DICT_HELPER(2, 8)stream.dict_helper[2].starts = (uint32_t *)wrkbuf; stream.dict_helper
[2].ends = &wrkbuf[8 * sizeof(uint32_t)]; stream.dict_helper
[2].size = 8; wrkbuf = &wrkbuf[8 * sizeof(uint32_t) + 0x100
];
; /* dictionary + db4 -> dictionary + dd4 */
342 INIT_DICT_HELPER(3, 19)stream.dict_helper[3].starts = (uint32_t *)wrkbuf; stream.dict_helper
[3].ends = &wrkbuf[19 * sizeof(uint32_t)]; stream.dict_helper
[3].size = 19; wrkbuf = &wrkbuf[19 * sizeof(uint32_t) + 0x100
];
; /* dictionary + ed4 -> dictionary + f20 */
343 stream.decrypt_dict = wrkbuf;
344
345 stream.hash = 0x10000;
346
347 for (i = 0; i < 58; i++) {
348 stream.init_array[i] = j;
349 j += ( 1 << image[ep+i+0x70e]); /* boundchecked in pe.c */
350 }
351
352 memset(stream.array1,0,sizeof(stream.array1));
353 memset(stream.array2,0,sizeof(stream.array2));
354
355 i=0;
356 while (CLI_ISCONTAINED(image, size, blocks, 8)((size) > 0 && (8) > 0 && (size_t)(8) <=
(size_t)(size) && (blocks) >= (image) && (
(blocks) + (8)) <= ((image) + (size)) && ((blocks)
+ (8)) > (image) && (blocks) < ((image) + (size
)))
&& (block_rva = cli_readint32(blocks)(((const union unaligned_32 *)(blocks))->una_s32)) && (block_size = cli_readint32(blocks+4)(((const union unaligned_32 *)(blocks+4))->una_s32)) && CLI_ISCONTAINED(image, size, image+block_rva, block_size)((size) > 0 && (block_size) > 0 && (size_t
)(block_size) <= (size_t)(size) && (image+block_rva
) >= (image) && ((image+block_rva) + (block_size))
<= ((image) + (size)) && ((image+block_rva) + (block_size
)) > (image) && (image+block_rva) < ((image) + (
size)))
) {
357 wrkbuf = (uint8_t *)cli_calloc(block_size+0x10e, sizeof(uint8_t));
358 if (!wrkbuf) break;
359
360 stream.input = wrkbuf;
361 stream.iend = &wrkbuf[block_size+0x10e];
362
363 memcpy(wrkbuf, image + block_rva, block_size);
364
365 cli_dbgmsg(!__builtin_expect(!!(cli_debug_flag), 0)) ? (void)0 : cli_dbgmsg_internal("Aspack: unpacking block rva:%x - sz:%x\n", block_rva, block_size);
366 if (!decomp_block(&stream, block_size, &image[ep+0x6d6], image + block_rva)) {
367 free(wrkbuf);
368 break;
369 }
370
371 free(wrkbuf);
372
373 if (i==0 && block_size>7) { /* first sect j/c unrolling */
374 while (i < block_size - 6) {
375 uint8_t curbyte = image[block_rva+i];
376 if (curbyte == 0xe8 || curbyte == 0xe9) {
377 wrkbuf = &image[block_rva+i+1];
378 if (*wrkbuf == image[ep+0x148]) {
379 uint32_t target = cli_readint32(wrkbuf)(((const union unaligned_32 *)(wrkbuf))->una_s32) & 0xffffff00;
380 CLI_ROL(target, 0x18)target = ( target << ((0x18) & ((sizeof(target)<<
3)-1)) ) | ( target >> (((sizeof(target)<<3) - (0x18
)) & ((sizeof(target)<<3)-1)) )
;
381 cli_writeint32(wrkbuf, target - i)(((union unaligned_32 *)(wrkbuf))->una_u32=(uint32_t)(target
- i))
;
382 i+=4;
383 }
384 }
385 i++;
386 }
387 }
388 blocks+=8;
389 }
390
391 free(stream.dict_helper[0].starts);
392 if (block_rva) {
393 cli_dbgmsg(!__builtin_expect(!!(cli_debug_flag), 0)) ? (void)0 : cli_dbgmsg_internal("Aspack: unpacking failure\n");
394 return 0;
395 }
396
397 if(sectcount>2 && ep == sections[sectcount-2].rva && !sections[sectcount-1].rsz) {
398 sectcount-=2;
399 }
400 if(!(outsects=cli_malloc(sizeof(struct cli_exe_section)*sectcount))) {
401 cli_dbgmsg(!__builtin_expect(!!(cli_debug_flag), 0)) ? (void)0 : cli_dbgmsg_internal("Aspack: OOM - rebuild failed\n");
402 cli_writen(f, image, size);
403 return 1; /* No whatsoheader - won't infloop in pe.c */
404 }
405 memcpy(outsects, sections, sizeof(struct cli_exe_section)*sectcount);
406 for(i=0; i<sectcount; i++) {
407 outsects[i].raw=outsects[i].rva;
408 outsects[i].rsz=outsects[i].vsz;
409 }
410 if (!cli_rebuildpe((char *)image, outsects, sectcount, base, cli_readint32(image + ep + 0x39b)(((const union unaligned_32 *)(image + ep + 0x39b))->una_s32
)
, 0, 0, f)) {
411 cli_dbgmsg(!__builtin_expect(!!(cli_debug_flag), 0)) ? (void)0 : cli_dbgmsg_internal("Aspack: rebuild failed\n");
412 cli_writen(f, image, size);
413 } else {
414 cli_dbgmsg(!__builtin_expect(!!(cli_debug_flag), 0)) ? (void)0 : cli_dbgmsg_internal("Aspack: successfully rebuilt\n");
415 }
416 free(outsects);
417 return 1;
418}
419