~ubuntu-branches/ubuntu/jaunty/clamav/jaunty-backports

« back to all changes in this revision

Viewing changes to libclamav/autoit.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-10-02 15:36:00 UTC
  • mfrom: (10.1.6 sid)
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: james.westby@ubuntu.com-20101002153600-2tx3vki1u55cdrjy
Tags: 0.96.3+dfsg-2ubuntu0.10.04.1
Microversion update to 0.96.3 for Lucid (LP: #653738)

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include "others.h"
39
39
#include "scanners.h"
40
40
#include "autoit.h"
 
41
#include "fmap.h"
41
42
 
42
43
 
43
44
/* FIXME: use unicode detection and normalization from edwin */
175
176
*********************/
176
177
 
177
178
 
178
 
static int ea05(int desc, cli_ctx *ctx, char *tmpd) {
 
179
static int ea05(cli_ctx *ctx, uint8_t *base, char *tmpd) {
179
180
  uint8_t b[300], comp;
180
 
  uint8_t *buf = b;
181
181
  uint32_t s, m4sum=0;
182
182
  int i, ret;
183
183
  unsigned int files=0;
184
184
  char tempfile[1024];
185
185
  struct UNP UNP;
 
186
  fmap_t *map = *ctx->fmap;
186
187
 
187
 
  if (cli_readn(desc, buf, 16)!=16)
 
188
  if(!fmap_need_ptr_once(map, base, 16))
188
189
    return CL_CLEAN;
189
190
 
190
191
  for (i=0; i<16; i++)
191
 
    m4sum += buf[i];
 
192
    m4sum += *base++;
192
193
 
193
194
  while((ret=cli_checklimits("autoit", ctx, 0, 0, 0))==CL_CLEAN) {
194
 
    buf = b;
195
 
    if (cli_readn(desc, buf, 8)!=8)
 
195
    if(!fmap_need_ptr_once(map, base, 8))
196
196
      return CL_CLEAN;
197
197
 
198
198
    /*     MT_decrypt(buf,4,0x16fa);  waste of time */
199
 
    if((uint32_t)cli_readint32((char *)buf) != 0xceb06dff) {
 
199
    if((uint32_t)cli_readint32(base) != 0xceb06dff) {
200
200
      cli_dbgmsg("autoit: no FILE magic found, extraction complete\n");
201
201
      return CL_CLEAN;
202
202
    }
203
203
 
204
 
    s = cli_readint32((char *)buf+4) ^ 0x29bc;
 
204
    s = cli_readint32(base+4) ^ 0x29bc;
205
205
    if ((int32_t)s<0)
206
206
      return CL_CLEAN; /* the original code wouldn't seek back here */
 
207
    base += 8;
207
208
    if(cli_debug_flag && s<sizeof(b)) {
208
 
      if (cli_readn(desc, buf, s)!=(int)s)
 
209
      if (!fmap_need_ptr_once(map, base, s))
209
210
        return CL_CLEAN;
210
 
      buf[s]='\0';
211
 
      MT_decrypt(buf,s,s+0xa25e);
212
 
      cli_dbgmsg("autoit: magic string '%s'\n", buf);
213
 
    } else {
214
 
      lseek(desc, s, SEEK_CUR);
 
211
      memcpy(b, base, s);
 
212
      MT_decrypt(b,s,s+0xa25e);
 
213
      b[s]='\0';
 
214
      cli_dbgmsg("autoit: magic string '%s'\n", b);
215
215
    }
 
216
    base += s;
216
217
 
217
 
    if (cli_readn(desc, buf, 4)!=4)
 
218
    if (!fmap_need_ptr_once(map, base, 4))
218
219
      return CL_CLEAN;
219
 
    s = cli_readint32((char *)buf) ^ 0x29ac;
 
220
    s = cli_readint32(base) ^ 0x29ac;
220
221
    if ((int32_t)s<0)
221
222
      return CL_CLEAN; /* the original code wouldn't seek back here */
 
223
    base += 4;
222
224
    if (cli_debug_flag && s<sizeof(b)) {
223
 
      if (cli_readn(desc, buf, s)!=(int)s)
 
225
      if (!fmap_need_ptr_once(map, base, s))
224
226
        return CL_CLEAN;
225
 
      MT_decrypt(buf,s,s+0xf25e);
226
 
      buf[s]='\0';
227
 
      cli_dbgmsg("autoit: original filename '%s'\n", buf);
228
 
    } else {
229
 
      lseek(desc, s, SEEK_CUR);
 
227
      memcpy(b, base, s);
 
228
      MT_decrypt(b,s,s+0xf25e);
 
229
      b[s]='\0';
 
230
      cli_dbgmsg("autoit: original filename '%s'\n", b);
230
231
    }
 
232
    base += s;
231
233
 
232
 
    if (cli_readn(desc, buf, 13)!=13)
 
234
    if (!fmap_need_ptr_once(map, base, 13))
233
235
      return CL_CLEAN;
234
 
    comp = *buf;
235
 
    UNP.csize = cli_readint32((char *)buf+1) ^ 0x45aa;
 
236
    comp = *base;
 
237
    UNP.csize = cli_readint32(base+1) ^ 0x45aa;
236
238
    if ((int32_t)UNP.csize<0) {
237
239
      cli_dbgmsg("autoit: bad file size - giving up\n");
238
240
      return CL_CLEAN;
239
241
    }
240
242
 
241
 
    lseek(desc, 16, SEEK_CUR);
242
 
 
243
243
    if(!UNP.csize) {
244
244
      cli_dbgmsg("autoit: skipping empty file\n");
 
245
      base += 13 + 16;
245
246
      continue;
246
247
    }
247
248
    cli_dbgmsg("autoit: compressed size: %x\n", UNP.csize);
248
 
    cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32((char *)buf+5) ^ 0x45aa);
249
 
    cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32((char *)buf+9) ^ 0xc3d2);
250
 
 
251
 
    
 
249
    cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32(base+5) ^ 0x45aa);
 
250
    cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32(base+9) ^ 0xc3d2);
 
251
 
 
252
    base += 13 + 16;
 
253
 
252
254
    if(cli_checklimits("autoit", ctx, UNP.csize, 0, 0)!=CL_CLEAN) {
253
 
      lseek(desc, UNP.csize, SEEK_CUR);
 
255
      base += UNP.csize;
254
256
      continue;
255
257
    }
256
258
 
257
 
    if (!(buf = cli_malloc(UNP.csize)))
 
259
    if (!(UNP.inputbuf = cli_malloc(UNP.csize)))
258
260
      return CL_EMEM;
259
 
    if (cli_readn(desc, buf, UNP.csize)!=(int)UNP.csize) {
 
261
    if (!fmap_need_ptr_once(map, base, UNP.csize)) {
260
262
      cli_dbgmsg("autoit: failed to read compressed stream. broken/truncated file?\n");
261
 
      free(buf);
 
263
      free(UNP.inputbuf);
262
264
      return CL_CLEAN;
263
265
    }
264
 
    MT_decrypt(buf,UNP.csize,0x22af+m4sum);
 
266
    memcpy(UNP.inputbuf, base, UNP.csize);
 
267
    base += UNP.csize;
 
268
    MT_decrypt(UNP.inputbuf,UNP.csize,0x22af+m4sum);
265
269
 
266
270
    if (comp == 1) {
267
271
      cli_dbgmsg("autoit: file is compressed\n");
268
 
      if (cli_readint32((char *)buf)!=0x35304145) {
 
272
      if (cli_readint32(UNP.inputbuf)!=0x35304145) {
269
273
        cli_dbgmsg("autoit: bad magic or unsupported version\n");
270
 
        free(buf);
 
274
        free(UNP.inputbuf);
271
275
        continue;
272
276
      }
273
277
 
274
 
      if(!(UNP.usize = be32_to_host(*(uint32_t *)(buf+4))))
 
278
      if(!(UNP.usize = be32_to_host(*(uint32_t *)(UNP.inputbuf+4))))
275
279
        UNP.usize = UNP.csize; /* only a specifically crafted or badly corrupted sample should land here */
276
280
      if(cli_checklimits("autoit", ctx, UNP.usize, 0, 0)!=CL_CLEAN) {
277
 
        free(buf);
 
281
        free(UNP.inputbuf);
278
282
        continue;
279
283
      }
280
284
 
281
285
      if (!(UNP.outputbuf = cli_malloc(UNP.usize))) {
282
 
        free(buf);
 
286
        free(UNP.inputbuf);
283
287
        return CL_EMEM;
284
288
      }
285
289
      cli_dbgmsg("autoit: uncompressed size again: %x\n", UNP.usize);
286
290
 
287
 
      UNP.inputbuf = buf;
288
291
      UNP.cur_output = 0;
289
292
      UNP.cur_input = 8;
290
293
      UNP.bitmap.full = 0;
328
331
        }
329
332
      }
330
333
 
331
 
      free(buf);
 
334
      free(UNP.inputbuf);
332
335
      /* Sometimes the autoit exe is in turn packed/lamed with a runtime compressor and similar shit.
333
336
       * However, since the autoit script doesn't compress a second time very well, chances are we're
334
337
       * still able to match the headers and unpack something (see sample 0811129)
340
343
        cli_dbgmsg("autoit: decompression error - partial file may exist\n");
341
344
    } else {
342
345
      cli_dbgmsg("autoit: file is not compressed\n");
343
 
      UNP.outputbuf = buf;
 
346
      UNP.outputbuf = UNP.inputbuf;
344
347
      UNP.usize = UNP.csize;
345
348
    }
346
349
 
469
472
 autoit3 EA06 handler 
470
473
*********************/
471
474
 
472
 
static int ea06(int desc, cli_ctx *ctx, char *tmpd) {
473
 
  uint8_t b[600], comp, script;
474
 
  uint8_t *buf;
 
475
static int ea06(cli_ctx *ctx, uint8_t *base, char *tmpd) {
 
476
  uint8_t b[600], comp, script, *buf;
475
477
  uint32_t s;
476
478
  int i, ret;
477
479
  unsigned int files=0;
479
481
  const char prefixes[] = { '\0', '\0', '@', '$', '\0', '.', '"', '#' };
480
482
  const char *opers[] = { ",", "=", ">", "<", "<>", ">=", "<=", "(", ")", "+", "-", "/", "*", "&", "[", "]", "==", "^", "+=", "-=", "/=", "*=", "&=" };
481
483
  struct UNP UNP;
 
484
  fmap_t *map = *ctx->fmap;
 
485
 
482
486
 
483
487
  /* Useless due to a bug in CRC calculation - LMAO!!1 */
484
488
  /*   if (cli_readn(desc, buf, 24)!=24) */
485
489
  /*     return CL_CLEAN; */
486
490
  /*   LAME_decrypt(buf, 0x10, 0x99f2); */
487
491
  /*   buf+=0x10; */
488
 
  lseek(desc, 16, SEEK_CUR);   /* for now we just skip the garbage */
 
492
  base += 16;   /* for now we just skip the garbage */
489
493
 
490
494
  while((ret=cli_checklimits("cli_autoit", ctx, 0, 0, 0))==CL_CLEAN) {
491
 
    buf = b;
492
 
    if (cli_readn(desc, buf, 8)!=8)
 
495
    if(!fmap_need_ptr_once(map, base, 8))
493
496
      return CL_CLEAN;
494
497
    /*     LAME_decrypt(buf, 4, 0x18ee); waste of time */
495
 
    if(cli_readint32((char *)buf) != 0x52ca436b) {
 
498
    if(cli_readint32(base) != 0x52ca436b) {
496
499
      cli_dbgmsg("autoit: no FILE magic found, giving up\n");
497
500
      return CL_CLEAN;
498
501
    }
499
502
 
500
503
    script = 0;
501
504
 
502
 
    s = cli_readint32((char *)buf+4) ^ 0xadbc;
 
505
    s = cli_readint32(base+4) ^ 0xadbc;
503
506
    if ((int32_t)(s*2)<0)
504
507
      return CL_CLEAN; /* the original code wouldn't seek back here */
505
 
    if(s<300) {
506
 
      if (cli_readn(desc, buf, s*2)!=(int)s*2)
 
508
    base += 8;
 
509
    if(s < sizeof(b) / 2) {
 
510
      if(!fmap_need_ptr_once(map, base, s*2))
507
511
        return CL_CLEAN;
508
 
      LAME_decrypt(buf,s*2,s+0xb33f);
509
 
      u2a(buf,s*2);
510
 
      cli_dbgmsg("autoit: magic string '%s'\n", buf);
511
 
      if (s==19 && !memcmp(">>>AUTOIT SCRIPT<<<", buf, 19))
 
512
      memcpy(b, base, s*2);
 
513
      LAME_decrypt(b,s*2,s+0xb33f);
 
514
      u2a(b,s*2);
 
515
      cli_dbgmsg("autoit: magic string '%s'\n", b);
 
516
      if (s==19 && !memcmp(">>>AUTOIT SCRIPT<<<", b, 19))
512
517
        script = 1;
513
518
    } else {
514
519
      cli_dbgmsg("autoit: magic string too long to print\n");
515
 
      lseek(desc, s*2, SEEK_CUR);
516
520
    }
 
521
    base += s*2;
517
522
 
518
 
    if (cli_readn(desc, buf, 4)!=4)
 
523
    if (!fmap_need_ptr_once(map, base, 4))
519
524
      return CL_CLEAN;
520
 
    s = cli_readint32((char *)buf) ^ 0xf820;
 
525
    s = cli_readint32(base) ^ 0xf820;
521
526
    if ((int32_t)(s*2)<0)
522
527
      return CL_CLEAN; /* the original code wouldn't seek back here */
523
 
    if(cli_debug_flag && s<300) {
524
 
      if (cli_readn(desc, buf, s*2)!=(int)s*2)
 
528
    base += 4;
 
529
    if(cli_debug_flag && s<sizeof(b) / 2) {
 
530
      if(!fmap_need_ptr_once(map, base, s*2))
525
531
        return CL_CLEAN;
526
 
      LAME_decrypt(buf,s*2,s+0xf479);
527
 
      buf[s*2]='\0'; buf[s*2+1]='\0';
528
 
      u2a(buf,s*2);
529
 
      cli_dbgmsg("autoit: original filename '%s'\n", buf);
530
 
    } else {
531
 
      lseek(desc, s*2, SEEK_CUR);
 
532
      memcpy(b, base, s*2);
 
533
      LAME_decrypt(b,s*2,s+0xf479);
 
534
      b[s*2]='\0'; b[s*2+1]='\0';
 
535
      u2a(b,s*2);
 
536
      cli_dbgmsg("autoit: original filename '%s'\n", b);
532
537
    }
 
538
    base += s*2;
533
539
 
534
 
    if (cli_readn(desc, buf, 13)!=13)
 
540
    if(!fmap_need_ptr_once(map, base, 13))
535
541
      return CL_CLEAN;
536
 
    comp = *buf;
537
 
    UNP.csize = cli_readint32((char *)buf+1) ^ 0x87bc;
 
542
    comp = *base;
 
543
    UNP.csize = cli_readint32(base+1) ^ 0x87bc;
538
544
    if ((int32_t)UNP.csize<0) {
539
545
      cli_dbgmsg("autoit: bad file size - giving up\n");
540
546
      return CL_CLEAN;
541
547
    }
542
548
 
543
 
    lseek(desc, 16, SEEK_CUR);
544
 
 
545
549
    if(!UNP.csize) {
546
550
      cli_dbgmsg("autoit: skipping empty file\n");
 
551
      base += 13 + 16;
547
552
      continue;
548
553
    }
549
554
    cli_dbgmsg("autoit: compressed size: %x\n", UNP.csize);
550
 
    cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32((char *)buf+5) ^ 0x87bc);
551
 
    cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32((char *)buf+9) ^ 0xa685);
 
555
    cli_dbgmsg("autoit: advertised uncompressed size %x\n", cli_readint32(base+5) ^ 0x87bc);
 
556
    cli_dbgmsg("autoit: ref chksum: %x\n", cli_readint32(base+9) ^ 0xa685);
 
557
 
 
558
    base += 13 + 16;
552
559
 
553
560
    if(cli_checklimits("autoit", ctx, UNP.csize, 0, 0)!=CL_CLEAN) {
554
 
      lseek(desc, UNP.csize, SEEK_CUR);
 
561
      base += UNP.csize;
555
562
      continue;
556
563
    }
557
564
 
558
565
    files++;
559
 
    if (!(buf = cli_malloc(UNP.csize)))
 
566
    if (!(UNP.inputbuf = cli_malloc(UNP.csize)))
560
567
      return CL_EMEM;
561
 
    if (cli_readn(desc, buf, UNP.csize)!=(int)UNP.csize) {
 
568
    if (!fmap_need_ptr_once(map, base, UNP.csize)) {
562
569
      cli_dbgmsg("autoit: failed to read compressed stream. broken/truncated file?\n");
563
 
      free(buf);
 
570
      free(UNP.inputbuf);
564
571
      return CL_CLEAN;
565
572
    }
566
 
    LAME_decrypt(buf,UNP.csize,0x2477 /* + m4sum (broken by design) */ );
 
573
    memcpy(UNP.inputbuf, base, UNP.csize);
 
574
    base += UNP.csize;
 
575
    LAME_decrypt(UNP.inputbuf,UNP.csize,0x2477 /* + m4sum (broken by design) */ );
567
576
 
568
577
    if (comp == 1) {
569
578
      cli_dbgmsg("autoit: file is compressed\n");
570
 
      if (cli_readint32((char *)buf)!=0x36304145) {
 
579
      if (cli_readint32(UNP.inputbuf)!=0x36304145) {
571
580
        cli_dbgmsg("autoit: bad magic or unsupported version\n");
572
 
        free(buf);
 
581
        free(UNP.inputbuf);
573
582
        continue;
574
583
      }
575
584
 
576
 
      if(!(UNP.usize = be32_to_host(*(uint32_t *)(buf+4))))
 
585
      if(!(UNP.usize = be32_to_host(*(uint32_t *)(UNP.inputbuf+4))))
577
586
        UNP.usize = UNP.csize; /* only a specifically crafted or badly corrupted sample should land here */
578
587
      if(cli_checklimits("autoit", ctx, UNP.usize, 0, 0)!=CL_CLEAN) {
579
 
        free(buf);
 
588
        free(UNP.inputbuf);
580
589
        continue;
581
590
      }
582
591
      if (!(UNP.outputbuf = cli_malloc(UNP.usize))) {
583
 
        free(buf);
 
592
        free(UNP.inputbuf);
584
593
        return CL_EMEM;
585
594
      }
586
595
      cli_dbgmsg("autoit: uncompressed size again: %x\n", UNP.usize);
587
596
 
588
 
      UNP.inputbuf = buf;
589
597
      UNP.cur_output = 0;
590
598
      UNP.cur_input = 8;
591
599
      UNP.bitmap.full = 0;
629
637
        }
630
638
      }
631
639
 
632
 
      free(buf);
 
640
      free(UNP.inputbuf);
633
641
      if (UNP.error) 
634
642
        cli_dbgmsg("autoit: decompression error - partial file may exist\n");
635
643
    } else {
636
644
      cli_dbgmsg("autoit: file is not compressed\n");
637
 
      UNP.outputbuf = buf;
 
645
      UNP.outputbuf = UNP.inputbuf;
638
646
      UNP.usize = UNP.csize;
639
647
    }
640
648
 
897
905
   autoit3 wrapper 
898
906
*********************/
899
907
 
900
 
int cli_scanautoit(int desc, cli_ctx *ctx, off_t offset) {
901
 
  uint8_t version;
 
908
int cli_scanautoit(cli_ctx *ctx, off_t offset) {
 
909
  uint8_t *version;
902
910
  int r;
903
911
  char *tmpd;
904
 
 
905
 
  lseek(desc, offset, SEEK_SET);
906
 
  if (cli_readn(desc, &version, 1)!=1)
 
912
  fmap_t *map = *ctx->fmap;
 
913
 
 
914
  cli_dbgmsg("in scanautoit()\n");
 
915
 
 
916
  if(!(version = fmap_need_off_once(map, offset, sizeof(*version))))
907
917
    return CL_EREAD;
908
918
 
909
 
  cli_dbgmsg("in scanautoit()\n");
910
 
 
911
919
  if (!(tmpd = cli_gentemp(ctx->engine->tmpdir)))    
912
920
    return CL_ETMPDIR;
913
921
  if (mkdir(tmpd, 0700)) {
918
926
  if (ctx->engine->keeptmp)
919
927
    cli_dbgmsg("autoit: Extracting files to %s\n", tmpd);
920
928
 
921
 
  switch(version) {
 
929
  switch(*version) {
922
930
  case 0x35:
923
 
    r = ea05(desc, ctx, tmpd);
 
931
    r = ea05(ctx, version + 1, tmpd);
924
932
    break;
925
933
  case 0x36:
926
934
#ifdef FPU_WORDS_BIGENDIAN
927
 
    r = ea06(desc, ctx, tmpd);
 
935
    r = ea06(ctx, version + 1, tmpd);
928
936
#else
929
937
    cli_dbgmsg("autoit: EA06 support not available\n");
930
938
    r = CL_CLEAN;