~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/pe.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2008 Sourcefire, Inc.
3
 
 *
4
 
 *  Authors: Alberto Wu, Tomasz Kojm
 
2
 *  Copyright (C) 2004 - 2006 Tomasz Kojm <tkojm@clamav.net>
 
3
 *                            aCaB <acab@clamav.net>
5
4
 *
6
5
 *  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.
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
9
9
 *
10
10
 *  This program is distributed in the hope that it will be useful,
11
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
21
#if HAVE_CONFIG_H
22
22
#include "clamav-config.h"
23
23
#endif
24
 
#define _XOPEN_SOURCE 500
 
24
 
25
25
#include <stdio.h>
26
 
#if HAVE_STRING_H
27
26
#include <string.h>
28
 
#endif
29
27
#include <sys/types.h>
30
28
#include <sys/stat.h>
31
29
#include <fcntl.h>
 
30
#include <sys/stat.h>
32
31
#ifdef HAVE_UNISTD_H
33
32
#include <unistd.h>
34
33
#endif
35
34
#include <time.h>
36
 
#include <stdarg.h>
37
35
 
38
36
#include "cltypes.h"
39
37
#include "clamav.h"
44
42
#include "spin.h"
45
43
#include "upx.h"
46
44
#include "yc.h"
47
 
#include "aspack.h"
48
45
#include "wwunpack.h"
 
46
#include "suecrypt.h"
49
47
#include "unsp.h"
50
48
#include "scanners.h"
51
49
#include "str.h"
53
51
#include "md5.h"
54
52
#include "mew.h"
55
53
#include "upack.h"
56
 
#include "matcher.h"
57
 
#include "matcher-hash.h"
58
 
#include "disasm.h"
59
 
#include "special.h"
60
 
#include "ishield.h"
 
54
 
 
55
#ifndef O_BINARY
 
56
#define O_BINARY        0
 
57
#endif
61
58
 
62
59
#define DCONF ctx->dconf->pe
63
60
 
64
 
#define PE_IMAGE_DOS_SIGNATURE      0x5a4d          /* MZ */
65
 
#define PE_IMAGE_DOS_SIGNATURE_OLD  0x4d5a          /* ZM */
66
 
#define PE_IMAGE_NT_SIGNATURE       0x00004550
 
61
#define IMAGE_DOS_SIGNATURE         0x5a4d          /* MZ */
 
62
#define IMAGE_DOS_SIGNATURE_OLD     0x4d5a          /* ZM */
 
63
#define IMAGE_NT_SIGNATURE          0x00004550
67
64
#define PE32_SIGNATURE              0x010b
68
65
#define PE32P_SIGNATURE             0x020b
69
66
 
73
70
#define UPX_NRV2B "\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x11\xc9\x75\x20\x41\x01\xdb"
74
71
#define UPX_NRV2D "\x83\xf0\xff\x74\x78\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9"
75
72
#define UPX_NRV2E "\xeb\x52\x31\xc9\x83\xe8\x03\x72\x11\xc1\xe0\x08\x8a\x06\x46\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5"
76
 
#define UPX_LZMA1 "\x56\x83\xc3\x04\x53\x50\xc7\x03\x03\x00\x02\x00\x90\x90\x90\x55\x57\x56\x53\x83"
77
 
#define UPX_LZMA2 "\x56\x83\xc3\x04\x53\x50\xc7\x03\x03\x00\x02\x00\x90\x90\x90\x90\x90\x55\x57\x56"
78
73
 
79
74
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
80
75
#define EC16(x) le16_to_host(x)
82
77
#define PEALIGN(o,a) (((a))?(((o)/(a))*(a)):(o))
83
78
#define PESALIGN(o,a) (((a))?(((o)/(a)+((o)%(a)!=0))*(a)):(o))
84
79
 
85
 
#define CLI_UNPSIZELIMITS(NAME,CHK) \
86
 
if(cli_checklimits(NAME, ctx, (CHK), 0, 0)!=CL_CLEAN) { \
87
 
    free(exe_sections);                                 \
88
 
    return CL_CLEAN;                                    \
89
 
}
90
 
 
91
 
#define CLI_UNPTEMP(NAME,FREEME) \
92
 
if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) { \
93
 
    cli_multifree FREEME; \
94
 
    return CL_EMEM; \
95
 
} \
96
 
if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { \
97
 
    cli_dbgmsg(NAME": Can't create file %s\n", tempfile); \
98
 
    free(tempfile); \
99
 
    cli_multifree FREEME; \
100
 
    return CL_ECREAT; \
101
 
}
102
 
 
103
 
#define CLI_TMPUNLK() if(!ctx->engine->keeptmp) { \
104
 
    if (cli_unlink(tempfile)) { \
105
 
        free(tempfile); \
106
 
        return CL_EUNLINK; \
107
 
    } \
108
 
}
109
 
 
110
 
#ifdef HAVE__INTERNAL__SHA_COLLECT
111
 
#define SHA_OFF do { ctx->sha_collect = -1; } while(0)
112
 
#define SHA_RESET do { ctx->sha_collect = sha_collect; } while(0)
113
 
#else
114
 
#define SHA_OFF do {} while(0)
115
 
#define SHA_RESET do {} while(0)
116
 
#endif
117
 
 
118
 
#define FSGCASE(NAME,FREESEC) \
119
 
    case 0: /* Unpacked and NOT rebuilt */ \
120
 
        cli_dbgmsg(NAME": Successfully decompressed\n"); \
121
 
        close(ndesc); \
122
 
        if (cli_unlink(tempfile)) { \
123
 
            free(exe_sections); \
124
 
            free(tempfile); \
125
 
            FREESEC; \
126
 
            return CL_EUNLINK; \
127
 
        } \
128
 
        free(tempfile); \
129
 
        FREESEC; \
130
 
        found = 0; \
131
 
        upx_success = 1; \
132
 
        break; /* FSG ONLY! - scan raw data after upx block */
133
 
 
134
 
#define SPINCASE() \
135
 
    case 2: \
136
 
        free(spinned); \
137
 
        close(ndesc); \
138
 
        if (cli_unlink(tempfile)) { \
139
 
            free(exe_sections); \
140
 
            free(tempfile); \
141
 
            return CL_EUNLINK; \
142
 
        } \
143
 
        cli_dbgmsg("PESpin: Size exceeded\n"); \
144
 
        free(tempfile); \
145
 
        break; \
146
 
 
147
 
#define CLI_UNPRESULTS_(NAME,FSGSTUFF,EXPR,GOOD,FREEME) \
148
 
    switch(EXPR) { \
149
 
    case GOOD: /* Unpacked and rebuilt */ \
150
 
        if(ctx->engine->keeptmp) \
151
 
            cli_dbgmsg(NAME": Unpacked and rebuilt executable saved in %s\n", tempfile); \
152
 
        else \
153
 
            cli_dbgmsg(NAME": Unpacked and rebuilt executable\n"); \
154
 
        cli_multifree FREEME; \
155
 
        free(exe_sections); \
156
 
        lseek(ndesc, 0, SEEK_SET); \
157
 
        cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); \
158
 
        SHA_OFF; \
159
 
        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { \
160
 
            close(ndesc); \
161
 
            CLI_TMPUNLK(); \
162
 
            free(tempfile); \
163
 
            SHA_RESET; \
164
 
            return CL_VIRUS; \
165
 
        } \
166
 
        SHA_RESET; \
167
 
        close(ndesc); \
168
 
        CLI_TMPUNLK(); \
169
 
        free(tempfile); \
170
 
        return CL_CLEAN; \
171
 
\
172
 
FSGSTUFF; \
173
 
\
174
 
    default: \
175
 
        cli_dbgmsg(NAME": Unpacking failed\n"); \
176
 
        close(ndesc); \
177
 
        if (cli_unlink(tempfile)) { \
178
 
            free(exe_sections); \
179
 
            free(tempfile); \
180
 
            cli_multifree FREEME; \
181
 
            return CL_EUNLINK; \
182
 
        } \
183
 
        cli_multifree FREEME; \
184
 
        free(tempfile); \
185
 
    }
186
 
 
187
 
 
188
 
#define CLI_UNPRESULTS(NAME,EXPR,GOOD,FREEME) CLI_UNPRESULTS_(NAME,(void)0,EXPR,GOOD,FREEME)
189
 
#define CLI_UNPRESULTSFSG1(NAME,EXPR,GOOD,FREEME) CLI_UNPRESULTS_(NAME,FSGCASE(NAME,free(sections)),EXPR,GOOD,FREEME)
190
 
#define CLI_UNPRESULTSFSG2(NAME,EXPR,GOOD,FREEME) CLI_UNPRESULTS_(NAME,FSGCASE(NAME,(void)0),EXPR,GOOD,FREEME)
191
 
 
192
 
#define DETECT_BROKEN_PE (DETECT_BROKEN && !ctx->corrupted_input)
 
80
extern short cli_leavetemps_flag;
193
81
 
194
82
struct offset_list {
195
83
    uint32_t offset;
196
84
    struct offset_list *next;
197
85
};
198
86
 
199
 
static void cli_multifree(void *f, ...) {
200
 
    void *ff;
201
 
    va_list ap;
202
 
    free(f);
203
 
    va_start(ap, f);
204
 
    while((ff=va_arg(ap, void*))) free(ff);
205
 
    va_end(ap);
206
 
}
207
 
 
208
 
struct vinfo_list {
209
 
    uint32_t rvas[16];
210
 
    unsigned int count;
211
 
};
212
 
 
213
 
int versioninfo_cb(void *opaque, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
214
 
    struct vinfo_list *vlist = (struct vinfo_list *)opaque;
215
 
 
216
 
    cli_dbgmsg("versioninfo_cb: type: %x, name: %x, lang: %x, rva: %x\n", type, name, lang, rva);
217
 
    vlist->rvas[vlist->count] = rva;
218
 
    if(++vlist->count == sizeof(vlist->rvas) / sizeof(vlist->rvas[0]))
219
 
        return 1;
220
 
    return 0;
221
 
}
222
 
 
223
 
 
224
 
uint32_t cli_rawaddr(uint32_t rva, const struct cli_exe_section *shp, uint16_t nos, unsigned int *err, size_t fsize, uint32_t hdr_size)
 
87
static uint32_t cli_rawaddr(uint32_t rva, struct cli_exe_section *shp, uint16_t nos, unsigned int *err, size_t fsize)
225
88
{
226
 
    int i, found = 0;
227
 
    uint32_t ret;
 
89
        int i, found = 0;
 
90
        uint32_t ret;
228
91
 
229
 
    if (rva<hdr_size) { /* Out of section EP - mapped to imagebase+rva */
230
 
        if (rva >= fsize) {
 
92
    if (rva<0x1000) { /* Out of section EP - mapped to imagebase+rva */
 
93
        if (rva >= fsize) {
231
94
            *err=1;
232
95
            return 0;
233
96
        }
252
115
    return ret;
253
116
}
254
117
 
 
118
static void xckriz(char **opcode, int *len, int checksize, int reg) {
 
119
    while(*len>6) {
 
120
        if (**opcode>='\x48' && **opcode<='\x4f' && **opcode!='\x4c') {
 
121
            if ((char)(**opcode-reg)=='\x48') break;
 
122
            (*len)--;
 
123
            (*opcode)++;
 
124
            continue;
 
125
        }
 
126
        if (**opcode>='\xb8' && **opcode<='\xbf' && **opcode!='\xbc') {
 
127
            if (checksize && cli_readint32(*opcode+1)==0x0fd2) break;
 
128
            (*len)-=5;
 
129
            (*opcode)+=5;
 
130
            continue;
 
131
        }
 
132
        if (**opcode=='\x81') {
 
133
            (*len)-=6;
 
134
            (*opcode)+=6;
 
135
            continue;
 
136
        }
 
137
        break;
 
138
    }
 
139
}
 
140
 
255
141
 
256
142
/*
257
 
static int cli_ddump(int desc, int offset, int size, const char *file) {
 
143
static int cli_ddump(int desc, int offset, int size, const char *file)
 
144
{
258
145
        int pos, ndesc, bread, sum = 0;
259
146
        char buff[FILEBUFF];
260
147
 
284
171
                cli_dbgmsg("Can't write to file\n");
285
172
                lseek(desc, pos, SEEK_SET);
286
173
                close(ndesc);
287
 
                cli_unlink(file);
 
174
                unlink(file);
288
175
                return -1;
289
176
            }
290
177
            break;
293
180
                cli_dbgmsg("Can't write to file\n");
294
181
                lseek(desc, pos, SEEK_SET);
295
182
                close(ndesc);
296
 
                cli_unlink(file);
 
183
                unlink(file);
297
184
                return -1;
298
185
            }
299
186
        }
306
193
}
307
194
*/
308
195
 
309
 
 
310
 
/* 
311
 
   void findres(uint32_t by_type, uint32_t by_name, uint32_t res_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size, int (*cb)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *opaque)
312
 
   callback based res lookup
313
 
 
314
 
   by_type: lookup type
315
 
   by_name: lookup name or (unsigned)-1 to look for any name
316
 
   res_rva: base resource rva (i.e. dirs[2].VirtualAddress)
317
 
   ctx, exe_sections, nsections, hdr_size: same as in scanpe
318
 
   cb: the callback function executed on each successful match
319
 
   opaque: an opaque pointer passed to the callback
320
 
 
321
 
   the callback proto is
322
 
   int pe_res_cballback (void *opaque, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva);
323
 
   the callback shall return 0 to continue the lookup or 1 to abort
324
 
*/
325
 
void findres(uint32_t by_type, uint32_t by_name, uint32_t res_rva, fmap_t *map, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size, int (*cb)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *opaque) {
326
 
    unsigned int err = 0;
327
 
    uint32_t type, type_offs, name, name_offs, lang, lang_offs;
328
 
    uint8_t *resdir, *type_entry, *name_entry, *lang_entry ;
329
 
    uint16_t type_cnt, name_cnt, lang_cnt;
330
 
 
331
 
    if (!(resdir = fmap_need_off_once(map, cli_rawaddr(res_rva, exe_sections, nsections, &err, map->len, hdr_size), 16)) || err)
332
 
        return;
333
 
 
334
 
    type_cnt = (uint16_t)cli_readint16(resdir+12);
335
 
    type_entry = resdir+16;
336
 
    if(!(by_type>>31)) {
337
 
        type_entry += type_cnt * 8;
338
 
        type_cnt = (uint16_t)cli_readint16(resdir+14);
339
 
    }
340
 
 
341
 
    while(type_cnt--) {
342
 
        if(!fmap_need_ptr_once(map, type_entry, 8))
343
 
            return;
344
 
        type = cli_readint32(type_entry);
345
 
        type_offs = cli_readint32(type_entry+4);
346
 
        if(type == by_type && (type_offs>>31)) {
347
 
            type_offs &= 0x7fffffff;
348
 
            if (!(resdir = fmap_need_off_once(map, cli_rawaddr(res_rva + type_offs, exe_sections, nsections, &err, map->len, hdr_size), 16)) || err)
349
 
                return;
350
 
 
351
 
            name_cnt = (uint16_t)cli_readint16(resdir+12);
352
 
            name_entry = resdir+16;
353
 
            if(by_name == 0xffffffff)
354
 
                name_cnt += (uint16_t)cli_readint16(resdir+14);
355
 
            else if(!(by_name>>31)) {
356
 
                name_entry += name_cnt * 8;
357
 
                name_cnt = (uint16_t)cli_readint16(resdir+14);
358
 
            }
359
 
            while(name_cnt--) {
360
 
                if(!fmap_need_ptr_once(map, name_entry, 8))
361
 
                    return;
362
 
                name = cli_readint32(name_entry);
363
 
                name_offs = cli_readint32(name_entry+4);
364
 
                if((by_name == 0xffffffff || name == by_name) && (name_offs>>31)) {
365
 
                    name_offs &= 0x7fffffff;
366
 
                    if (!(resdir = fmap_need_off_once(map, cli_rawaddr(res_rva + name_offs, exe_sections, nsections, &err, map->len, hdr_size), 16)) || err)
367
 
                        return;
368
 
                    
369
 
                    lang_cnt = (uint16_t)cli_readint16(resdir+12) + (uint16_t)cli_readint16(resdir+14);
370
 
                    lang_entry = resdir+16;
371
 
                    while(lang_cnt--) {
372
 
                        if(!fmap_need_ptr_once(map, lang_entry, 8))
373
 
                            return;
374
 
                        lang = cli_readint32(lang_entry);
375
 
                        lang_offs = cli_readint32(lang_entry+4);
376
 
                        if(!(lang_offs >>31)) {
377
 
                            if(cb(opaque, type, name, lang, res_rva + lang_offs))
378
 
                                return;
379
 
                        }
380
 
                        lang_entry += 8;
381
 
                    }
382
 
                }
383
 
                name_entry += 8;
384
 
            }
385
 
            return; /* FIXME: unless we want to find ALL types */
 
196
static unsigned int cli_md5sect(int fd, uint32_t offset, uint32_t size, unsigned char *digest)
 
197
{
 
198
        size_t bread, sum = 0;
 
199
        off_t pos;
 
200
        char buff[FILEBUFF];
 
201
        cli_md5_ctx md5ctx;
 
202
 
 
203
 
 
204
    if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
 
205
        cli_dbgmsg("cli_md5sect: Invalid descriptor %d\n", fd);
 
206
        return 0;
 
207
    }
 
208
 
 
209
    if(lseek(fd, offset, SEEK_SET) == -1) {
 
210
        cli_dbgmsg("cli_md5sect: lseek() failed\n");
 
211
        lseek(fd, pos, SEEK_SET);
 
212
        return 0;
 
213
    }
 
214
 
 
215
    cli_md5_init(&md5ctx);
 
216
 
 
217
    while((bread = cli_readn(fd, buff, FILEBUFF)) > 0) {
 
218
        if(sum + bread >= size) {
 
219
            cli_md5_update(&md5ctx, buff, size - sum);
 
220
            break;
 
221
        } else {
 
222
            cli_md5_update(&md5ctx, buff, bread);
 
223
            sum += bread;
386
224
        }
387
 
        type_entry += 8;
388
 
    }
389
 
}
390
 
 
391
 
static unsigned int cli_md5sect(fmap_t *map, struct cli_exe_section *s, unsigned char *digest) {
392
 
    void *hashme;
393
 
    cli_md5_ctx md5;
394
 
 
395
 
    if (s->rsz > CLI_MAX_ALLOCATION) {
396
 
        cli_dbgmsg("cli_md5sect: skipping md5 calculation for too big section\n");
397
 
        return 0;
398
 
    }
399
 
 
400
 
    if(!s->rsz) return 0;
401
 
    if(!(hashme=fmap_need_off_once(map, s->raw, s->rsz))) {
402
 
        cli_dbgmsg("cli_md5sect: unable to read section data\n");
403
 
        return 0;
404
 
    }
405
 
 
406
 
    cli_md5_init(&md5);
407
 
    cli_md5_update(&md5, hashme, s->rsz);
408
 
    cli_md5_final(digest, &md5);
 
225
    }
 
226
 
 
227
    cli_md5_final(digest, &md5ctx);
 
228
    lseek(fd, pos, SEEK_SET);
409
229
    return 1;
410
230
}
411
231
 
412
 
static void cli_parseres_special(uint32_t base, uint32_t rva, fmap_t *map, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
413
 
    unsigned int err = 0, i;
414
 
    uint8_t *resdir;
415
 
    uint8_t *entry, *oentry;
416
 
    uint16_t named, unnamed;
417
 
    uint32_t rawaddr = cli_rawaddr(rva, exe_sections, nsections, &err, fsize, hdr_size);
418
 
    uint32_t entries;
419
 
 
420
 
    if(level>2 || !*maxres) return;
421
 
    *maxres-=1;
422
 
    if(err || !(resdir = fmap_need_off_once(map, rawaddr, 16)))
423
 
            return;
424
 
    named = (uint16_t)cli_readint16(resdir+12);
425
 
    unnamed = (uint16_t)cli_readint16(resdir+14);
426
 
 
427
 
    entries = /*named+*/unnamed;
428
 
    if (!entries)
429
 
            return;
430
 
    rawaddr += named*8; /* skip named */
431
 
    /* this is just used in a heuristic detection, so don't give error on failure */
432
 
    if(!(entry = fmap_need_off(map, rawaddr+16, entries*8))) {
433
 
            cli_dbgmsg("cli_parseres_special: failed to read resource directory at:%lu\n", (unsigned long)rawaddr+16);
434
 
            return;
435
 
    }
436
 
    oentry = entry;
437
 
    /*for (i=0; i<named; i++) {
438
 
        uint32_t id, offs;
439
 
        id = cli_readint32(entry);
440
 
        offs = cli_readint32(entry+4);
441
 
        if(offs>>31)
442
 
            cli_parseres( base, base + (offs&0x7fffffff), srcfd, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
443
 
        entry+=8;
444
 
    }*/
445
 
    for (i=0; i<unnamed; i++, entry += 8) {
446
 
        uint32_t id, offs;
447
 
        if (stats->errors >= SWIZZ_MAXERRORS) {
448
 
            cli_dbgmsg("cli_parseres_special: resources broken, ignoring\n");
449
 
            return;
450
 
        }
451
 
        id = cli_readint32(entry)&0x7fffffff;
452
 
        if(level==0) {
453
 
                type = 0;
454
 
                switch(id) {
455
 
                        case 4: /* menu */
456
 
                        case 5: /* dialog */
457
 
                        case 6: /* string */
458
 
                        case 11:/* msgtable */
459
 
                                type = id;
460
 
                                break;
461
 
                        case 16:
462
 
                                type = id;
463
 
                                /* 14: version */
464
 
                                stats->has_version = 1;
465
 
                                break;
466
 
                        case 24: /* manifest */
467
 
                                stats->has_manifest = 1;
468
 
                                break;
469
 
                        /* otherwise keep it 0, we don't want it */
470
 
                }
471
 
        }
472
 
        if (!type) {
473
 
                /* if we are not interested in this type, skip */
474
 
                continue;
475
 
        }
476
 
        offs = cli_readint32(entry+4);
477
 
        if(offs>>31)
478
 
                cli_parseres_special(base, base + (offs&0x7fffffff), map, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
479
 
        else {
480
 
                        offs = cli_readint32(entry+4);
481
 
                        rawaddr = cli_rawaddr(base + offs, exe_sections, nsections, &err, fsize, hdr_size);
482
 
                        if (!err && (resdir = fmap_need_off_once(map, rawaddr, 16))) {
483
 
                                uint32_t isz = cli_readint32(resdir+4);
484
 
                                uint8_t *str;
485
 
                                rawaddr = cli_rawaddr(cli_readint32(resdir), exe_sections, nsections, &err, fsize, hdr_size);
486
 
                                if (err || !isz || isz >= fsize || rawaddr+isz >= fsize) {
487
 
                                        cli_dbgmsg("cli_parseres_special: invalid resource table entry: %lu + %lu\n", 
488
 
                                                        (unsigned long)rawaddr, 
489
 
                                                        (unsigned long)isz);
490
 
                                        stats->errors++;
491
 
                                        continue;
492
 
                                }
493
 
                                if ((id&0xff) != 0x09) /* english res only */
494
 
                                    continue;
495
 
                                if((str = fmap_need_off_once(map, rawaddr, isz)))
496
 
                                        cli_detect_swizz_str(str, isz, stats, type);
497
 
                        }
498
 
        }
499
 
    }
500
 
    fmap_unneed_ptr(map, oentry, entries*8);
501
 
}
502
 
 
503
 
int cli_scanpe(cli_ctx *ctx)
 
232
int cli_scanpe(int desc, cli_ctx *ctx)
504
233
{
505
234
        uint16_t e_magic; /* DOS signature ("MZ") */
506
235
        uint16_t nsections;
514
243
            struct pe_image_optional_hdr32 opt32;
515
244
        } pe_opt;
516
245
        struct pe_image_section_hdr *section_hdr;
517
 
        char sname[9], epbuff[4096], *tempfile;
518
 
        uint32_t epsize;
519
 
        ssize_t bytes, at;
520
 
        unsigned int i, found, upx_success = 0, min = 0, max = 0, err, overlays = 0;
 
246
        struct cli_md5_node *md5_sect;
 
247
        struct stat sb;
 
248
        char sname[9], buff[4096], *tempfile;
 
249
        unsigned char *ubuff;
 
250
        ssize_t bytes;
 
251
        unsigned int i, found, upx_success = 0, min = 0, max = 0, err;
521
252
        unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
522
253
        int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
523
254
        char *src = NULL, *dest = NULL;
524
 
        int ndesc, ret = CL_CLEAN, upack = 0, native=0;
 
255
        int ndesc, ret = CL_CLEAN, upack = 0;
525
256
        size_t fsize;
526
 
        uint32_t valign, falign, hdr_size, j;
 
257
        uint32_t valign, falign;
527
258
        struct cli_exe_section *exe_sections;
528
 
        struct cli_matcher *md5_sect;
529
 
        char timestr[32];
530
 
        struct pe_image_data_dir *dirs;
531
 
        struct cli_bc_ctx *bc_ctx;
532
 
        fmap_t *map;
533
 
        struct cli_pe_hook_data pedata;
534
 
#ifdef HAVE__INTERNAL__SHA_COLLECT
535
 
        int sha_collect = ctx->sha_collect;
536
 
#endif
537
 
 
538
 
    if(!ctx) {
539
 
        cli_errmsg("cli_scanpe: ctx == NULL\n");
540
 
        return CL_ENULLARG;
541
 
    }
542
 
    map = *ctx->fmap;
543
 
    if(fmap_readn(map, &e_magic, 0, sizeof(e_magic)) != sizeof(e_magic)) {
 
259
 
 
260
 
 
261
    if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
544
262
        cli_dbgmsg("Can't read DOS signature\n");
545
263
        return CL_CLEAN;
546
264
    }
547
265
 
548
 
    if(EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE && EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE_OLD) {
 
266
    if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
549
267
        cli_dbgmsg("Invalid DOS signature\n");
550
268
        return CL_CLEAN;
551
269
    }
552
270
 
553
 
    if(fmap_readn(map, &e_lfanew, 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
 
271
    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
 
272
 
 
273
    if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
554
274
        cli_dbgmsg("Can't read new header address\n");
555
275
        /* truncated header? */
556
 
        if(DETECT_BROKEN_PE) {
 
276
        if(DETECT_BROKEN) {
557
277
            if(ctx->virname)
558
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
278
                *ctx->virname = "Broken.Executable";
559
279
            return CL_VIRUS;
560
280
        }
561
281
        return CL_CLEAN;
568
288
        return CL_CLEAN;
569
289
    }
570
290
 
571
 
    if(fmap_readn(map, &file_hdr, e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
 
291
    if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
 
292
        /* probably not a PE file */
 
293
        cli_dbgmsg("Can't lseek to e_lfanew\n");
 
294
        return CL_CLEAN;
 
295
    }
 
296
 
 
297
    if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
572
298
        /* bad information in e_lfanew - probably not a PE file */
573
299
        cli_dbgmsg("Can't read file header\n");
574
300
        return CL_CLEAN;
575
301
    }
576
302
 
577
 
    if(EC32(file_hdr.Magic) != PE_IMAGE_NT_SIGNATURE) {
 
303
    if(EC32(file_hdr.Magic) != IMAGE_NT_SIGNATURE) {
578
304
        cli_dbgmsg("Invalid PE signature (probably NE file)\n");
579
305
        return CL_CLEAN;
580
306
    }
589
315
    switch(EC16(file_hdr.Machine)) {
590
316
        case 0x0:
591
317
            cli_dbgmsg("Machine type: Unknown\n");
592
 
            break;
593
318
        case 0x14c:
594
319
            cli_dbgmsg("Machine type: 80386\n");
595
320
            break;
678
403
            cli_dbgmsg("Machine type: AMD64\n");
679
404
            break;
680
405
        default:
681
 
            cli_dbgmsg("Machine type: ** UNKNOWN ** (0x%x)\n", EC16(file_hdr.Machine));
 
406
            cli_warnmsg("Unknown machine type in PE header (0x%x)\n", EC16(file_hdr.Machine));
682
407
    }
683
408
 
684
409
    nsections = EC16(file_hdr.NumberOfSections);
685
410
    if(nsections < 1 || nsections > 96) {
686
 
        if(DETECT_BROKEN_PE) {
 
411
        if(DETECT_BROKEN) {
687
412
            if(ctx->virname)
688
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
413
                *ctx->virname = "Broken.Executable";
689
414
            return CL_VIRUS;
690
415
        }
691
 
        if(!ctx->corrupted_input) {
692
 
            if(nsections)
693
 
                cli_warnmsg("PE file contains %d sections\n", nsections);
694
 
            else
695
 
                cli_warnmsg("PE file contains no sections\n");
696
 
        }
 
416
        if(nsections)
 
417
            cli_warnmsg("PE file contains %d sections\n", nsections);
 
418
        else
 
419
            cli_warnmsg("PE file contains no sections\n");
697
420
        return CL_CLEAN;
698
421
    }
699
422
    cli_dbgmsg("NumberOfSections: %d\n", nsections);
700
423
 
701
424
    timestamp = (time_t) EC32(file_hdr.TimeDateStamp);
702
 
    cli_dbgmsg("TimeDateStamp: %s", cli_ctime(&timestamp, timestr, sizeof(timestr)));
 
425
    cli_dbgmsg("TimeDateStamp: %s", ctime(&timestamp));
703
426
 
704
427
    cli_dbgmsg("SizeOfOptionalHeader: %x\n", EC16(file_hdr.SizeOfOptionalHeader));
705
428
 
706
429
    if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) {
707
430
        cli_dbgmsg("SizeOfOptionalHeader too small\n");
708
 
        if(DETECT_BROKEN_PE) {
 
431
        if(DETECT_BROKEN) {
709
432
            if(ctx->virname)
710
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
433
                *ctx->virname = "Broken.Executable";
711
434
            return CL_VIRUS;
712
435
        }
713
436
        return CL_CLEAN;
714
437
    }
715
438
 
716
 
    at = e_lfanew + sizeof(struct pe_image_file_hdr);
717
 
    if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
 
439
    if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
718
440
        cli_dbgmsg("Can't read optional file header\n");
719
 
        if(DETECT_BROKEN_PE) {
 
441
        if(DETECT_BROKEN) {
720
442
            if(ctx->virname)
721
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
443
                *ctx->virname = "Broken.Executable";
722
444
            return CL_VIRUS;
723
445
        }
724
446
        return CL_CLEAN;
725
447
    }
726
 
    at += sizeof(struct pe_image_optional_hdr32);
727
448
 
728
449
    /* This will be a chicken and egg problem until we drop 9x */
729
 
    if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) {
 
450
    if(EC32(optional_hdr64.Magic)==PE32P_SIGNATURE) {
730
451
        if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) {
731
452
            /* FIXME: need to play around a bit more with xp64 */
732
453
            cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
733
 
            if(DETECT_BROKEN_PE) {
 
454
            if(DETECT_BROKEN) {
734
455
                if(ctx->virname)
735
 
                    *ctx->virname = "Heuristics.Broken.Executable";
 
456
                    *ctx->virname = "Broken.Executable";
736
457
                return CL_VIRUS;
737
458
            }
738
459
            return CL_CLEAN;
745
466
            either way it's a 32bit thingy
746
467
        */
747
468
        if(EC16(optional_hdr32.Magic) != PE32_SIGNATURE) {
748
 
            if(!ctx->corrupted_input)
749
 
                cli_warnmsg("Incorrect magic number in optional header\n");
750
 
            if(DETECT_BROKEN_PE) {
 
469
            cli_warnmsg("Incorrect magic number in optional header\n");
 
470
            if(DETECT_BROKEN) {
751
471
                if(ctx->virname)
752
 
                    *ctx->virname = "Heuristics.Broken.Executable";
 
472
                    *ctx->virname = "Broken.Executable";
753
473
                return CL_VIRUS;
754
474
            }
755
475
            cli_dbgmsg("9x compatibility mode\n");
759
479
    if(!pe_plus) { /* PE */
760
480
        if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
761
481
            /* Seek to the end of the long header */
762
 
            at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
 
482
            lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
763
483
        }
764
484
 
765
485
        if(DCONF & PE_CONF_UPACK)
766
486
            upack = (EC16(file_hdr.SizeOfOptionalHeader)==0x148);
767
487
 
768
488
        vep = EC32(optional_hdr32.AddressOfEntryPoint);
769
 
        hdr_size = EC32(optional_hdr32.SizeOfHeaders);
770
489
        cli_dbgmsg("File format: PE\n");
771
490
 
772
491
        cli_dbgmsg("MajorLinkerVersion: %d\n", optional_hdr32.MajorLinkerVersion);
781
500
        cli_dbgmsg("MajorSubsystemVersion: %d\n", EC16(optional_hdr32.MajorSubsystemVersion));
782
501
        cli_dbgmsg("MinorSubsystemVersion: %d\n", EC16(optional_hdr32.MinorSubsystemVersion));
783
502
        cli_dbgmsg("SizeOfImage: 0x%x\n", EC32(optional_hdr32.SizeOfImage));
784
 
        cli_dbgmsg("SizeOfHeaders: 0x%x\n", hdr_size);
 
503
        cli_dbgmsg("SizeOfHeaders: 0x%x\n", EC32(optional_hdr32.SizeOfHeaders));
785
504
        cli_dbgmsg("NumberOfRvaAndSizes: %d\n", EC32(optional_hdr32.NumberOfRvaAndSizes));
786
 
        dirs = optional_hdr32.DataDirectory;
787
505
 
788
506
    } else { /* PE+ */
789
507
        /* read the remaining part of the header */
790
 
        if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
 
508
        if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
791
509
            cli_dbgmsg("Can't read optional file header\n");
792
 
            if(DETECT_BROKEN_PE) {
 
510
            if(DETECT_BROKEN) {
793
511
                if(ctx->virname)
794
 
                    *ctx->virname = "Heuristics.Broken.Executable";
 
512
                    *ctx->virname = "Broken.Executable";
795
513
                return CL_VIRUS;
796
514
            }
797
515
            return CL_CLEAN;
798
516
        }
799
 
        at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
 
517
 
800
518
        vep = EC32(optional_hdr64.AddressOfEntryPoint);
801
 
        hdr_size = EC32(optional_hdr64.SizeOfHeaders);
802
519
        cli_dbgmsg("File format: PE32+\n");
803
520
 
804
521
        cli_dbgmsg("MajorLinkerVersion: %d\n", optional_hdr64.MajorLinkerVersion);
813
530
        cli_dbgmsg("MajorSubsystemVersion: %d\n", EC16(optional_hdr64.MajorSubsystemVersion));
814
531
        cli_dbgmsg("MinorSubsystemVersion: %d\n", EC16(optional_hdr64.MinorSubsystemVersion));
815
532
        cli_dbgmsg("SizeOfImage: 0x%x\n", EC32(optional_hdr64.SizeOfImage));
816
 
        cli_dbgmsg("SizeOfHeaders: 0x%x\n", hdr_size);
 
533
        cli_dbgmsg("SizeOfHeaders: 0x%x\n", EC32(optional_hdr64.SizeOfHeaders));
817
534
        cli_dbgmsg("NumberOfRvaAndSizes: %d\n", EC32(optional_hdr64.NumberOfRvaAndSizes));
818
 
        dirs = optional_hdr64.DataDirectory;
819
 
    }
820
 
 
 
535
    }
 
536
 
 
537
    if (DETECT_BROKEN && (!(pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment)) || (pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment))%0x1000)) {
 
538
        cli_dbgmsg("Bad virtual alignemnt\n");
 
539
        if(ctx->virname)
 
540
            *ctx->virname = "Broken.Executable";
 
541
        return CL_VIRUS;
 
542
    }
 
543
 
 
544
    if (DETECT_BROKEN && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) {
 
545
        cli_dbgmsg("Bad file alignemnt\n");
 
546
        if(ctx->virname)
 
547
            *ctx->virname = "Broken.Executable";
 
548
        return CL_VIRUS;
 
549
    }
821
550
 
822
551
    switch(pe_plus ? EC16(optional_hdr64.Subsystem) : EC16(optional_hdr32.Subsystem)) {
823
552
        case 0:
824
553
            cli_dbgmsg("Subsystem: Unknown\n");
825
554
            break;
826
555
        case 1:
827
 
            cli_dbgmsg("Subsystem: Native (svc)\n");
828
 
            native = 1;
 
556
            cli_dbgmsg("Subsystem: Native (a driver ?)\n");
829
557
            break;
830
558
        case 2:
831
559
            cli_dbgmsg("Subsystem: Win32 GUI\n");
854
582
        case 12:
855
583
            cli_dbgmsg("Subsystem: EFI runtime driver\n");
856
584
            break;
857
 
        case 13:
858
 
            cli_dbgmsg("Subsystem: EFI ROM image\n");
859
 
            break;
860
 
        case 14:
861
 
            cli_dbgmsg("Subsystem: Xbox\n");
862
 
            break;
863
 
        case 16:
864
 
            cli_dbgmsg("Subsystem: Boot application\n");
865
 
            break;
866
585
        default:
867
 
            cli_dbgmsg("Subsystem: ** UNKNOWN ** (0x%x)\n", pe_plus ? EC16(optional_hdr64.Subsystem) : EC16(optional_hdr32.Subsystem));
 
586
            cli_warnmsg("Unknown subsystem in PE header (0x%x)\n", pe_plus ? EC16(optional_hdr64.Subsystem) : EC16(optional_hdr32.Subsystem));
868
587
    }
869
588
 
870
589
    cli_dbgmsg("------------------------------------\n");
871
590
 
872
 
    if (DETECT_BROKEN_PE && !native && (!(pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment)) || (pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment))%0x1000)) {
873
 
        cli_dbgmsg("Bad virtual alignemnt\n");
874
 
        if(ctx->virname)
875
 
            *ctx->virname = "Heuristics.Broken.Executable";
876
 
        return CL_VIRUS;
877
 
    }
878
 
 
879
 
    if (DETECT_BROKEN_PE && !native && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) {
880
 
        cli_dbgmsg("Bad file alignemnt\n");
881
 
        if(ctx->virname)
882
 
            *ctx->virname = "Heuristics.Broken.Executable";
883
 
        return CL_VIRUS;
884
 
    }
885
 
 
886
 
    fsize = map->len;
 
591
    if(fstat(desc, &sb) == -1) {
 
592
        cli_dbgmsg("fstat failed\n");
 
593
        return CL_EIO;
 
594
    }
 
595
 
 
596
    fsize = sb.st_size;
887
597
 
888
598
    section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr));
889
599
 
903
613
    valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment);
904
614
    falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment);
905
615
 
906
 
    if(fmap_readn(map, section_hdr, at, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
 
616
    if(cli_readn(desc, section_hdr, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
907
617
        cli_dbgmsg("Can't read section header\n");
908
618
        cli_dbgmsg("Possibly broken PE file\n");
909
619
        free(section_hdr);
910
620
        free(exe_sections);
911
 
        if(DETECT_BROKEN_PE) {
 
621
        if(DETECT_BROKEN) {
912
622
            if(ctx->virname)
913
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
623
                *ctx->virname = "Broken.Executable";
914
624
            return CL_VIRUS;
915
625
        }
916
626
        return CL_CLEAN;
917
627
    }
918
 
    at += sizeof(struct pe_image_section_hdr)*nsections;
919
 
 
 
628
    
920
629
    for(i = 0; falign!=0x200 && i<nsections; i++) {
921
630
        /* file alignment fallback mode - blah */
922
631
        if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) {
925
634
        }
926
635
    }
927
636
 
928
 
    hdr_size = PESALIGN(hdr_size, valign); /* Aligned headers virtual size */
929
 
 
930
637
    for(i = 0; i < nsections; i++) {
931
638
        strncpy(sname, (char *) section_hdr[i].Name, 8);
932
639
        sname[8] = 0;
933
640
        exe_sections[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign);
934
641
        exe_sections[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign);
 
642
        exe_sections[i].uvsz = EC32(section_hdr[i].VirtualSize);
935
643
        exe_sections[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign);
936
644
        exe_sections[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign);
937
 
        exe_sections[i].chr = EC32(section_hdr[i].Characteristics);
938
 
        exe_sections[i].urva = EC32(section_hdr[i].VirtualAddress); /* Just in case */
939
 
        exe_sections[i].uvsz = EC32(section_hdr[i].VirtualSize);
940
 
        exe_sections[i].uraw = EC32(section_hdr[i].PointerToRawData);
941
645
        exe_sections[i].ursz = EC32(section_hdr[i].SizeOfRawData);
942
 
 
943
 
        if (!exe_sections[i].vsz && exe_sections[i].rsz)
944
 
            exe_sections[i].vsz=PESALIGN(exe_sections[i].ursz, valign);
945
 
 
946
646
        if (exe_sections[i].rsz && fsize>exe_sections[i].raw && !CLI_ISCONTAINED(0, (uint32_t) fsize, exe_sections[i].raw, exe_sections[i].rsz))
947
647
            exe_sections[i].rsz = fsize - exe_sections[i].raw;
948
648
        
949
649
        cli_dbgmsg("Section %d\n", i);
950
650
        cli_dbgmsg("Section name: %s\n", sname);
951
651
        cli_dbgmsg("Section data (from headers - in memory)\n");
952
 
        cli_dbgmsg("VirtualSize: 0x%x 0x%x\n", exe_sections[i].uvsz, exe_sections[i].vsz);
953
 
        cli_dbgmsg("VirtualAddress: 0x%x 0x%x\n", exe_sections[i].urva, exe_sections[i].rva);
954
 
        cli_dbgmsg("SizeOfRawData: 0x%x 0x%x\n", exe_sections[i].ursz, exe_sections[i].rsz);
955
 
        cli_dbgmsg("PointerToRawData: 0x%x 0x%x\n", exe_sections[i].uraw, exe_sections[i].raw);
 
652
        cli_dbgmsg("VirtualSize: 0x%x 0x%x\n", EC32(section_hdr[i].VirtualSize), exe_sections[i].vsz);
 
653
        cli_dbgmsg("VirtualAddress: 0x%x 0x%x\n", EC32(section_hdr[i].VirtualAddress), exe_sections[i].rva);
 
654
        cli_dbgmsg("SizeOfRawData: 0x%x 0x%x\n", EC32(section_hdr[i].SizeOfRawData), exe_sections[i].rsz);
 
655
        cli_dbgmsg("PointerToRawData: 0x%x 0x%x\n", EC32(section_hdr[i].PointerToRawData), exe_sections[i].raw);
956
656
 
957
 
        if(exe_sections[i].chr & 0x20) {
 
657
        if(EC32(section_hdr[i].Characteristics) & 0x20) {
958
658
            cli_dbgmsg("Section contains executable code\n");
959
659
 
960
660
            if(exe_sections[i].vsz < exe_sections[i].rsz) {
967
667
            }
968
668
        }
969
669
 
970
 
        if(exe_sections[i].chr & 0x20000000)
 
670
        if(EC32(section_hdr[i].Characteristics) & 0x20000000)
971
671
            cli_dbgmsg("Section's memory is executable\n");
972
672
 
973
 
        if(exe_sections[i].chr & 0x80000000)
 
673
        if(EC32(section_hdr[i].Characteristics) & 0x80000000)
974
674
            cli_dbgmsg("Section's memory is writeable\n");
975
675
 
976
676
        cli_dbgmsg("------------------------------------\n");
977
677
 
978
 
        if (DETECT_BROKEN_PE && (!valign || (exe_sections[i].urva % valign))) { /* Bad virtual alignment */
 
678
        if (DETECT_BROKEN && EC32(section_hdr[i].VirtualAddress)%valign) { /* Bad virtual alignment */
979
679
            cli_dbgmsg("VirtualAddress is misaligned\n");
980
680
            if(ctx->virname)
981
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
681
                *ctx->virname = "Broken.Executable";
982
682
            free(section_hdr);
983
683
            free(exe_sections);
984
684
            return CL_VIRUS;
985
685
        }
986
686
 
987
687
        if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
 
688
            unsigned char md5_dig[16];
988
689
            if (exe_sections[i].raw >= fsize) { /* really broken */
989
 
              cli_dbgmsg("Broken PE file - Section %d starts beyond the end of file (Offset@ %lu, Total filesize %lu)\n", i, (unsigned long)exe_sections[i].raw, (unsigned long)fsize);
 
690
                cli_dbgmsg("Broken PE file - Section %d starts beyond the end of file (Offset@ %d, Total filesize %d)\n", i, exe_sections[i].raw, fsize);
990
691
                free(section_hdr);
991
692
                free(exe_sections);
992
 
                if(DETECT_BROKEN_PE) {
 
693
                if(DETECT_BROKEN) {
993
694
                    if(ctx->virname)
994
 
                        *ctx->virname = "Heuristics.Broken.Executable";
 
695
                        *ctx->virname = "Broken.Executable";
995
696
                    return CL_VIRUS;
996
697
                }
997
698
                return CL_CLEAN; /* no ninjas to see here! move along! */
998
699
            }
999
 
 
1000
 
            if(SCAN_ALGO && (DCONF & PE_CONF_POLIPOS) && !*sname && exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000 && exe_sections[i].chr == 0xe0000060) polipos = i;
1001
 
 
 
700
            
1002
701
            /* check MD5 section sigs */
1003
 
            md5_sect = ctx->engine->hm_mdb;
1004
 
            if((DCONF & PE_CONF_MD5SECT) && md5_sect) {
1005
 
                unsigned char md5_dig[16];
1006
 
                if(cli_hm_have_size(md5_sect, CLI_HASH_MD5, exe_sections[i].rsz) && 
1007
 
                   cli_md5sect(map, &exe_sections[i], md5_dig) &&
1008
 
                   cli_hm_scan(md5_dig, exe_sections[i].rsz, ctx->virname, md5_sect, CLI_HASH_MD5) == CL_VIRUS) {
1009
 
                    if(cli_hm_scan(md5_dig, fsize, NULL, ctx->engine->hm_fp, CLI_HASH_MD5) != CL_VIRUS) {
1010
 
                        free(section_hdr);
1011
 
                        free(exe_sections);
1012
 
                        return CL_VIRUS;
 
702
            if(DCONF & PE_CONF_MD5SECT)
 
703
                md5_sect = ctx->engine->md5_sect;
 
704
            else
 
705
                md5_sect = NULL;
 
706
 
 
707
            while(md5_sect && md5_sect->size < exe_sections[i].rsz)
 
708
                md5_sect = md5_sect->next;
 
709
 
 
710
            if(md5_sect && md5_sect->size == exe_sections[i].rsz) {
 
711
                if(!cli_md5sect(desc, exe_sections[i].raw, exe_sections[i].rsz, md5_dig)) {
 
712
                    cli_errmsg("PE: Can't calculate MD5 for section %d\n", i);
 
713
                } else {
 
714
                    while(md5_sect && md5_sect->size == exe_sections[i].rsz) {
 
715
                        if(!memcmp(md5_dig, md5_sect->md5, 16)) {
 
716
                            if(ctx->virname)
 
717
                                *ctx->virname = md5_sect->virname;
 
718
                            free(section_hdr);
 
719
                            free(exe_sections);
 
720
                            return CL_VIRUS;
 
721
                        }
 
722
                        md5_sect = md5_sect->next;
1013
723
                    }
1014
724
                }
1015
725
            }
1016
 
 
1017
 
        }
1018
 
 
1019
 
        if (exe_sections[i].urva>>31 || exe_sections[i].uvsz>>31 || (exe_sections[i].rsz && exe_sections[i].uraw>>31) || exe_sections[i].ursz>>31) {
1020
 
            cli_dbgmsg("Found PE values with sign bit set\n");
1021
 
            free(section_hdr);
1022
 
            free(exe_sections);
1023
 
            if(DETECT_BROKEN_PE) {
1024
 
                if(ctx->virname)
1025
 
                    *ctx->virname = "Heuristics.Broken.Executable";
1026
 
                return CL_VIRUS;
1027
 
            }
1028
 
            return CL_CLEAN;
1029
726
        }
1030
727
 
1031
728
        if(!i) {
1032
 
            if (DETECT_BROKEN_PE && exe_sections[i].urva!=hdr_size) { /* Bad first section RVA */
 
729
            if (DETECT_BROKEN && EC32(section_hdr[i].VirtualAddress)!=valign) { /* Bad first section RVA */
1033
730
                cli_dbgmsg("First section is in the wrong place\n");
1034
731
                if(ctx->virname)
1035
 
                    *ctx->virname = "Heuristics.Broken.Executable";
 
732
                    *ctx->virname = "Broken.Executable";
1036
733
                free(section_hdr);
1037
734
                free(exe_sections);
1038
735
                return CL_VIRUS;
1040
737
            min = exe_sections[i].rva;
1041
738
            max = exe_sections[i].rva + exe_sections[i].rsz;
1042
739
        } else {
1043
 
            if (DETECT_BROKEN_PE && exe_sections[i].urva - exe_sections[i-1].urva != exe_sections[i-1].vsz) { /* No holes, no overlapping, no virtual disorder */
 
740
            if (DETECT_BROKEN && EC32(section_hdr[i].VirtualAddress)-EC32(section_hdr[i-1].VirtualAddress)!= exe_sections[i-1].vsz) { /* No holes, no overlapping, no virtual disorder */
1044
741
                cli_dbgmsg("Virtually misplaced section (wrong order, overlapping, non contiguous)\n");
1045
742
                if(ctx->virname)
1046
 
                    *ctx->virname = "Heuristics.Broken.Executable";
 
743
                    *ctx->virname = "Broken.Executable";
1047
744
                free(section_hdr);
1048
745
                free(exe_sections);
1049
746
                return CL_VIRUS;
1051
748
            if(exe_sections[i].rva < min)
1052
749
                min = exe_sections[i].rva;
1053
750
 
1054
 
            if(exe_sections[i].rva + exe_sections[i].rsz > max) {
 
751
            if(exe_sections[i].rva + exe_sections[i].rsz > max)
1055
752
                max = exe_sections[i].rva + exe_sections[i].rsz;
1056
 
                overlays = exe_sections[i].raw + exe_sections[i].rsz;
 
753
        }
 
754
 
 
755
        if(SCAN_ALGO && (DCONF & PE_CONF_POLIPOS) && !strlen(sname)) {
 
756
            if(exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000) {
 
757
                if(EC32(section_hdr[i].Characteristics) == 0xe0000060) {
 
758
                    polipos = i;
 
759
                }
1057
760
            }
1058
761
        }
 
762
 
1059
763
    }
1060
764
 
1061
 
    free(section_hdr);
1062
 
 
1063
 
    if(!(ep = cli_rawaddr(vep, exe_sections, nsections, &err, fsize, hdr_size)) && err) {
 
765
    if(!(ep = cli_rawaddr(vep, exe_sections, nsections, &err, fsize)) && err) {
1064
766
        cli_dbgmsg("EntryPoint out of file\n");
 
767
        free(section_hdr);
1065
768
        free(exe_sections);
1066
 
        if(DETECT_BROKEN_PE) {
 
769
        if(DETECT_BROKEN) {
1067
770
            if(ctx->virname)
1068
 
                *ctx->virname = "Heuristics.Broken.Executable";
 
771
                *ctx->virname = "Broken.Executable";
1069
772
            return CL_VIRUS;
1070
773
        }
1071
774
        return CL_CLEAN;
1074
777
    cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
1075
778
 
1076
779
    if(pe_plus) { /* Do not continue for PE32+ files */
 
780
        free(section_hdr);
1077
781
        free(exe_sections);
1078
782
        return CL_CLEAN;
1079
783
    }
1080
784
 
1081
 
    epsize = fmap_readn(map, epbuff, ep, 4096);
1082
 
 
1083
 
 
1084
 
    /* Disasm scan disabled since it's now handled by the bytecode */
1085
 
 
1086
 
    /* CLI_UNPTEMP("DISASM",(exe_sections,0)); */
1087
 
    /* if(disasmbuf((unsigned char*)epbuff, epsize, ndesc)) */
1088
 
    /*  ret = cli_scandesc(ndesc, ctx, CL_TYPE_PE_DISASM, 1, NULL, AC_SCAN_VIR); */
1089
 
    /* close(ndesc); */
1090
 
    /* CLI_TMPUNLK(); */
1091
 
    /* free(tempfile); */
1092
 
    /* if(ret == CL_VIRUS) { */
1093
 
    /*  free(exe_sections); */
1094
 
    /*  return ret; */
1095
 
    /* } */
1096
 
 
1097
 
    if(overlays) {
1098
 
        int overlays_sz = fsize - overlays;
1099
 
        if(overlays_sz > 0) {
1100
 
            ret = cli_scanishield(ctx, overlays, overlays_sz);
1101
 
            if(ret != CL_CLEAN) {
1102
 
                free(exe_sections);
1103
 
                return ret;
1104
 
            }
1105
 
        }
1106
 
    }
1107
 
 
1108
 
    pedata.nsections = nsections;
1109
 
    pedata.ep = ep;
1110
 
    pedata.offset = 0;
1111
 
    memcpy(&pedata.file_hdr, &file_hdr, sizeof(file_hdr));
1112
 
    memcpy(&pedata.opt32, &pe_opt.opt32, sizeof(pe_opt.opt32));
1113
 
    memcpy(&pedata.opt64, &pe_opt.opt64, sizeof(pe_opt.opt64));
1114
 
    memcpy(&pedata.dirs, dirs, sizeof(pedata.dirs));
1115
 
    pedata.e_lfanew = e_lfanew;
1116
 
    pedata.overlays = overlays;
1117
 
    pedata.overlays_sz = fsize - overlays;
1118
 
    pedata.hdr_size = hdr_size;
1119
 
 
1120
 
    /* Bytecode BC_PE_ALL hook */
1121
 
    bc_ctx = cli_bytecode_context_alloc();
1122
 
    if (!bc_ctx) {
1123
 
        cli_errmsg("cli_scanpe: can't allocate memory for bc_ctx\n");
1124
 
        return CL_EMEM;
1125
 
    }
1126
 
    cli_bytecode_context_setpe(bc_ctx, &pedata, exe_sections);
1127
 
    cli_bytecode_context_setctx(bc_ctx, ctx);
1128
 
    ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_ALL, map, ctx->virname);
1129
 
    if (ret == CL_VIRUS || ret == CL_BREAK) {
1130
 
        free(exe_sections);
1131
 
        cli_bytecode_context_destroy(bc_ctx);
1132
 
        return ret == CL_VIRUS ? CL_VIRUS : CL_CLEAN;
1133
 
    }
1134
 
    cli_bytecode_context_destroy(bc_ctx);
1135
 
 
1136
785
    /* Attempt to detect some popular polymorphic viruses */
1137
786
 
1138
787
    /* W32.Parite.B */
1139
 
    if(SCAN_ALGO && (DCONF & PE_CONF_PARITE) && !dll && epsize == 4096 && ep == exe_sections[nsections - 1].raw) {
1140
 
        const char *pt = cli_memstr(epbuff, 4040, "\x47\x65\x74\x50\x72\x6f\x63\x41\x64\x64\x72\x65\x73\x73\x00", 15);
1141
 
        if(pt) {
1142
 
            pt += 15;
1143
 
            if((((uint32_t)cli_readint32(pt) ^ (uint32_t)cli_readint32(pt + 4)) == 0x505a4f) && (((uint32_t)cli_readint32(pt + 8) ^ (uint32_t)cli_readint32(pt + 12)) == 0xffffb) && (((uint32_t)cli_readint32(pt + 16) ^ (uint32_t)cli_readint32(pt + 20)) == 0xb8)) {
1144
 
                *ctx->virname = "Heuristics.W32.Parite.B";
1145
 
                free(exe_sections);
1146
 
                return CL_VIRUS;
 
788
    if(SCAN_ALGO && (DCONF & PE_CONF_PARITE) && !dll && ep == exe_sections[nsections - 1].raw) {
 
789
        lseek(desc, ep, SEEK_SET);
 
790
        if(cli_readn(desc, buff, 4096) == 4096) {
 
791
                const char *pt = cli_memstr(buff, 4040, "\x47\x65\x74\x50\x72\x6f\x63\x41\x64\x64\x72\x65\x73\x73\x00", 15);
 
792
            if(pt) {
 
793
                    uint32_t dw1, dw2;
 
794
 
 
795
                pt += 15;
 
796
                if(((dw1 = cli_readint32(pt)) ^ (dw2 = cli_readint32(pt + 4))) == 0x505a4f && ((dw1 = cli_readint32(pt + 8)) ^ (dw2 = cli_readint32(pt + 12))) == 0xffffb && ((dw1 = cli_readint32(pt + 16)) ^ (dw2 = cli_readint32(pt + 20))) == 0xb8) {
 
797
                    *ctx->virname = "W32.Parite.B";
 
798
                    free(section_hdr);
 
799
                    free(exe_sections);
 
800
                    return CL_VIRUS;
 
801
                }
1147
802
            }
1148
803
        }
1149
804
    }
1150
805
 
1151
806
    /* Kriz */
1152
 
    if(SCAN_ALGO && (DCONF & PE_CONF_KRIZ) && epsize >= 200 && CLI_ISCONTAINED(exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz, ep, 0x0fd2) && epbuff[1]=='\x9c' && epbuff[2]=='\x60') {
1153
 
        enum {KZSTRASH,KZSCDELTA,KZSPDELTA,KZSGETSIZE,KZSXORPRFX,KZSXOR,KZSDDELTA,KZSLOOP,KZSTOP};
1154
 
        uint8_t kzs[] = {KZSTRASH,KZSCDELTA,KZSPDELTA,KZSGETSIZE,KZSTRASH,KZSXORPRFX,KZSXOR,KZSTRASH,KZSDDELTA,KZSTRASH,KZSLOOP,KZSTOP};
1155
 
        uint8_t *kzstate = kzs;
1156
 
        uint8_t *kzcode = (uint8_t *)epbuff + 3;
1157
 
        uint8_t kzdptr=0xff, kzdsize=0xff;
1158
 
        int kzlen = 197, kzinitlen=0xffff, kzxorlen=-1;
 
807
    if(SCAN_ALGO && (DCONF & PE_CONF_KRIZ) && CLI_ISCONTAINED(exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz, ep, 0x0fd2)) {
1159
808
        cli_dbgmsg("in kriz\n");
 
809
        lseek(desc, ep, SEEK_SET);
 
810
        if(cli_readn(desc, buff, 200) == 200) {
 
811
            while (1) {
 
812
                char *krizpos=buff+3;
 
813
                char *krizmov, *krizxor;
 
814
                int krizleft = 200-3;
 
815
                int krizrega,krizregb;
1160
816
 
1161
 
        while(*kzstate!=KZSTOP) {
1162
 
            uint8_t op;
1163
 
            if(kzlen<=6) break;
1164
 
            op = *kzcode++;
1165
 
            kzlen--;
1166
 
            switch (*kzstate) {
1167
 
            case KZSTRASH: case KZSGETSIZE: {
1168
 
                int opsz=0;
1169
 
                switch(op) {
1170
 
                case 0x81:
1171
 
                    kzcode+=5;
1172
 
                    kzlen-=5;
1173
 
                    break;
1174
 
                case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbd: case 0xbe: case 0xbf:
1175
 
                    if(*kzstate==KZSGETSIZE && cli_readint32(kzcode)==0x0fd2) {
1176
 
                        kzinitlen = kzlen-5;
1177
 
                        kzdsize=op-0xb8;
1178
 
                        kzstate++;
1179
 
                        op=4; /* fake the register to avoid breaking out */
1180
 
                        cli_dbgmsg("kriz: using #%d as size counter\n", kzdsize);
1181
 
                    }
1182
 
                    opsz=4;
1183
 
                case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4d: case 0x4e: case 0x4f:
1184
 
                    op&=7;
1185
 
                    if(op!=kzdptr && op!=kzdsize) {
1186
 
                        kzcode+=opsz;
1187
 
                        kzlen-=opsz;
1188
 
                        break;
1189
 
                    }
1190
 
                default:
1191
 
                    kzcode--;
1192
 
                    kzlen++;
1193
 
                    kzstate++;
1194
 
                }
1195
 
                break;
1196
 
            }
1197
 
            case KZSCDELTA:
1198
 
                if(op==0xe8 && (uint32_t)cli_readint32(kzcode) < 0xff) {
1199
 
                    kzlen-=*kzcode+4;
1200
 
                    kzcode+=*kzcode+4;
1201
 
                    kzstate++;
1202
 
                } else *kzstate=KZSTOP;
1203
 
                break;
1204
 
            case KZSPDELTA:
1205
 
                if((op&0xf8)==0x58 && (kzdptr=op-0x58)!=4) {
1206
 
                    kzstate++;
1207
 
                    cli_dbgmsg("kriz: using #%d as pointer\n", kzdptr);
1208
 
                } else *kzstate=KZSTOP;
1209
 
                break;
1210
 
            case KZSXORPRFX:
1211
 
                kzstate++;
1212
 
                if(op==0x3e) break;
1213
 
            case KZSXOR:
1214
 
                if (op==0x80 && *kzcode==kzdptr+0xb0) {
1215
 
                    kzxorlen=kzlen;
1216
 
                    kzcode+=+6;
1217
 
                    kzlen-=+6;
1218
 
                    kzstate++;
1219
 
                } else *kzstate=KZSTOP;
1220
 
                break;
1221
 
            case KZSDDELTA:
1222
 
                if (op==kzdptr+0x48) kzstate++;
1223
 
                else *kzstate=KZSTOP;
1224
 
                break;
1225
 
            case KZSLOOP:
1226
 
                if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) {
1227
 
                    *ctx->virname = "Heuristics.W32.Kriz";
1228
 
                    free(exe_sections);
1229
 
                    return CL_VIRUS;
1230
 
                }
1231
 
                cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n");
1232
 
                kzstate++;
 
817
                if (buff[1]!='\x9c' || buff[2]!='\x60') break; /* EP+1 */
 
818
                xckriz(&krizpos, &krizleft, 0, 8);
 
819
                if (krizleft < 6 || *krizpos!='\xe8' || krizpos[2] || krizpos[3] || krizpos[4]) break; /* call DELTA */
 
820
                krizleft-=5+(unsigned char)krizpos[1];
 
821
                if (krizleft < 2) break;
 
822
                krizpos+=5+(unsigned char)krizpos[1];
 
823
                if (*krizpos<'\x58' || *krizpos>'\x5f' || *krizpos=='\x5c') break; /* pop DELTA */
 
824
                krizrega=*krizpos-'\x58';
 
825
                cli_dbgmsg("kriz: pop delta using %d\n", krizrega);
 
826
                krizpos+=1;
 
827
                krizleft-=1;
 
828
                xckriz(&krizpos, &krizleft, 1, 8);
 
829
                if (krizleft <6 || *krizpos<'\xb8' || *krizpos>'\xbf' || *krizpos=='\xbc' || cli_readint32(krizpos+1)!=0x0fd2) break;
 
830
                krizregb=*krizpos-'\xb8';
 
831
                if (krizrega==krizregb) break;
 
832
                cli_dbgmsg("kriz: using %d for size\n", krizregb);
 
833
                krizpos+=5;
 
834
                krizleft-=5;
 
835
                krizmov = krizpos;
 
836
                xckriz(&krizpos, &krizleft, 0, 8);
 
837
                krizxor=krizpos;
 
838
                if (krizleft && *krizpos=='\x3e') {
 
839
                    /* strip ds: */
 
840
                    krizpos++;
 
841
                    krizleft--;
 
842
                }
 
843
                if (krizleft<8 || *krizpos!='\x80' || (char)(krizpos[1]-krizrega)!='\xb0') {
 
844
                    cli_dbgmsg("kriz: bogus opcode or register\n");
 
845
                    break;
 
846
                }
 
847
                krizpos+=7;
 
848
                krizleft-=7;
 
849
                xckriz(&krizpos, &krizleft, 0, krizrega);
 
850
                if (! krizleft || (char)(*krizpos-krizrega)!='\x48') break; /* dec delta */
 
851
                krizpos++;
 
852
                krizleft--;
 
853
                cli_dbgmsg("kriz: dec delta found\n");
 
854
                xckriz(&krizpos, &krizleft, 0, krizregb);
 
855
                if (krizleft <4 || (char)(*krizpos-krizregb)!='\x48' || krizpos[1]!='\x75') break; /* dec size + jne loop */
 
856
                if (krizpos+3+(int)krizpos[2]<krizmov || krizpos+3+(int)krizpos[2]>krizxor) {
 
857
                    cli_dbgmsg("kriz: jmp back out of range (%d>%d>%d)\n", krizmov-(krizpos+3), (int)krizpos[2], krizxor-(krizpos+3));
 
858
                    break;
 
859
                }
 
860
                *ctx->virname = "Win32.Kriz";
 
861
                free(section_hdr);
 
862
                free(exe_sections);
 
863
                return CL_VIRUS;
1233
864
            }
1234
865
        }
1235
866
    }
1236
867
 
1237
868
    /* W32.Magistr.A/B */
1238
 
    if(SCAN_ALGO && (DCONF & PE_CONF_MAGISTR) && !dll && (nsections>1) && (exe_sections[nsections - 1].chr & 0x80000000)) {
1239
 
        uint32_t rsize, vsize, dam = 0;
 
869
    if(SCAN_ALGO && (DCONF & PE_CONF_MAGISTR) && !dll && (EC32(section_hdr[nsections - 1].Characteristics) & 0x80000000)) {
 
870
            uint32_t rsize, vsize, dam = 0;
1240
871
 
1241
872
        vsize = exe_sections[nsections - 1].uvsz;
1242
873
        rsize = exe_sections[nsections - 1].rsz;
1247
878
 
1248
879
        if(vsize >= 0x612c && rsize >= 0x612c && ((vsize & 0xff) == 0xec)) {
1249
880
                int bw = rsize < 0x7000 ? rsize : 0x7000;
1250
 
                char *tbuff;
1251
881
 
1252
 
            if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
1253
 
                if(cli_memstr(tbuff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
1254
 
                    *ctx->virname = dam ? "Heuristics.W32.Magistr.A.dam" : "Heuristics.W32.Magistr.A";
 
882
            lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
 
883
            if(cli_readn(desc, buff, 4096) == 4096) {
 
884
                if(cli_memstr(buff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
 
885
                    *ctx->virname = dam ? "W32.Magistr.A.dam" : "W32.Magistr.A";
 
886
                    free(section_hdr);
1255
887
                    free(exe_sections);
1256
888
                    return CL_VIRUS;
1257
889
                } 
1259
891
 
1260
892
        } else if(rsize >= 0x7000 && vsize >= 0x7000 && ((vsize & 0xff) == 0xed)) {
1261
893
                int bw = rsize < 0x8000 ? rsize : 0x8000;
1262
 
                char *tbuff;
1263
894
 
1264
 
            if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
1265
 
                if(cli_memstr(tbuff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
1266
 
                    *ctx->virname = dam ? "Heuristics.W32.Magistr.B.dam" : "Heuristics.W32.Magistr.B";
 
895
            lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
 
896
            if(cli_readn(desc, buff, 4096) == 4096) {
 
897
                if(cli_memstr(buff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
 
898
                    *ctx->virname = dam ? "W32.Magistr.B.dam" : "W32.Magistr.B";
 
899
                    free(section_hdr);
1267
900
                    free(exe_sections);
1268
901
                    return CL_VIRUS;
1269
902
                } 
1272
905
    }
1273
906
 
1274
907
    /* W32.Polipos.A */
1275
 
    while(polipos && !dll && nsections > 2 && nsections < 13 && e_lfanew <= 0x800 && (EC16(optional_hdr32.Subsystem) == 2 || EC16(optional_hdr32.Subsystem) == 3) && EC16(file_hdr.Machine) == 0x14c && optional_hdr32.SizeOfStackReserve >= 0x80000) {
1276
 
        uint32_t jump, jold, *jumps = NULL;
1277
 
        uint8_t *code;
1278
 
        unsigned int xsjs = 0;
1279
 
 
1280
 
        if(exe_sections[0].rsz > CLI_MAX_ALLOCATION) break;
1281
 
 
1282
 
        if(!exe_sections[0].rsz) break;
1283
 
        if(!(code=fmap_need_off_once(map, exe_sections[0].raw, exe_sections[0].rsz))) break;
1284
 
        for(i=0; i<exe_sections[0].rsz - 5; i++) {
1285
 
            if((uint8_t)(code[i]-0xe8) > 1) continue;
1286
 
            jump = cli_rawaddr(exe_sections[0].rva+i+5+cli_readint32(&code[i+1]), exe_sections, nsections, &err, fsize, hdr_size);
1287
 
            if(err || !CLI_ISCONTAINED(exe_sections[polipos].raw, exe_sections[polipos].rsz, jump, 9)) continue;
1288
 
            if(xsjs % 128 == 0) {
1289
 
                if(xsjs == 1280) break;
1290
 
                if(!(jumps=(uint32_t *)cli_realloc2(jumps, (xsjs+128)*sizeof(uint32_t)))) {
1291
 
                    free(exe_sections);
1292
 
                    return CL_EMEM;
1293
 
                }
1294
 
            }
1295
 
            j=0;
1296
 
            for(; j<xsjs; j++) {
1297
 
                if(jumps[j]<jump) continue;
1298
 
                if(jumps[j]==jump) {
1299
 
                    xsjs--;
 
908
   if(polipos && !dll && nsections > 2 && nsections < 13 && e_lfanew <= 0x800 && (EC16(optional_hdr32.Subsystem) == 2 || EC16(optional_hdr32.Subsystem) == 3) && EC16(file_hdr.Machine) == 0x14c && optional_hdr32.SizeOfStackReserve >= 0x80000) {
 
909
                uint32_t remaining = exe_sections[0].rsz;
 
910
                uint32_t chunk = sizeof(buff);
 
911
                uint32_t val, shift, raddr, total = 0;
 
912
                const char *jpt;
 
913
                struct offset_list *offlist = NULL, *offnode;
 
914
 
 
915
 
 
916
        cli_dbgmsg("Detected W32.Polipos.A characteristics\n");
 
917
 
 
918
        if(remaining < chunk)
 
919
            chunk = remaining;
 
920
 
 
921
        lseek(desc, exe_sections[0].raw, SEEK_SET);
 
922
        while((bytes = cli_readn(desc, buff, chunk)) > 0) {
 
923
            shift = 0;
 
924
            while((uint32_t)bytes - 5 > shift) {
 
925
                jpt = buff + shift;
 
926
                if(*jpt!='\xe9' && *jpt!='\xe8') {
 
927
                    shift++;
 
928
                    continue;
 
929
                }
 
930
                val = cli_readint32(jpt + 1);
 
931
                val += 5 + exe_sections[0].rva + total + shift;
 
932
                raddr = cli_rawaddr(val, exe_sections, nsections, &err, fsize);
 
933
 
 
934
                if(!err && (raddr >= exe_sections[polipos].raw && raddr < exe_sections[polipos].raw + exe_sections[polipos].rsz) && (!offlist || (raddr != offlist->offset))) {
 
935
                    offnode = (struct offset_list *) cli_malloc(sizeof(struct offset_list));
 
936
                    if(!offnode) {
 
937
                        free(section_hdr);
 
938
                        free(exe_sections);
 
939
                        while(offlist) {
 
940
                            offnode = offlist;
 
941
                            offlist = offlist->next;
 
942
                            free(offnode);
 
943
                        }
 
944
                        return CL_EMEM;
 
945
                    }
 
946
                    offnode->offset = raddr;
 
947
                    offnode->next = offlist;
 
948
                    offlist = offnode;
 
949
                }
 
950
 
 
951
                shift++;
 
952
            }
 
953
 
 
954
            if(remaining < chunk) {
 
955
                chunk = remaining;
 
956
            } else {
 
957
                remaining -= bytes;
 
958
                if(remaining < chunk) {
 
959
                    chunk = remaining;
 
960
                }
 
961
            }
 
962
 
 
963
            if(!remaining)
 
964
                break;
 
965
 
 
966
            total += bytes;
 
967
        }
 
968
 
 
969
        offnode = offlist;
 
970
        while(offnode) {
 
971
            cli_dbgmsg("Polipos: Checking offset 0x%x (%u)", offnode->offset, offnode->offset);
 
972
            lseek(desc, offnode->offset, SEEK_SET);
 
973
            if(cli_readn(desc, buff, 9) == 9) {
 
974
                ubuff = (unsigned char *) buff;
 
975
                if(ubuff[0] == 0x55 && ubuff[1] == 0x8b && ubuff[2] == 0xec &&
 
976
                   ((ubuff[3] == 0x83 && ubuff[4] == 0xec && ubuff[6] == 0x60) ||  ubuff[3] == 0x60 ||
 
977
                     (ubuff[3] == 0x81 && ubuff[4] == 0xec && ubuff[7] == 0x00 && ubuff[8] == 0x00))) {
 
978
                    ret = CL_VIRUS;
 
979
                    *ctx->virname = "W32.Polipos.A";
1300
980
                    break;
1301
981
                }
1302
 
                jold=jumps[j];
1303
 
                jumps[j]=jump;
1304
 
                jump=jold;
1305
 
            }
1306
 
            jumps[j]=jump;
1307
 
            xsjs++;
1308
 
        }
1309
 
        if(!xsjs) break;
1310
 
        cli_dbgmsg("Polipos: Checking %d xsect jump(s)\n", xsjs);
1311
 
        for(i=0;i<xsjs;i++) {
1312
 
            if(!(code = fmap_need_off_once(map, jumps[i], 9))) continue;
1313
 
            if((jump=cli_readint32(code))==0x60ec8b55 || (code[4]==0x0ec && ((jump==0x83ec8b55 && code[6]==0x60) || (jump==0x81ec8b55 && !code[7] && !code[8])))) {
1314
 
                *ctx->virname = "Heuristics.W32.Polipos.A";
1315
 
                free(jumps);
1316
 
                free(exe_sections);
1317
 
                return CL_VIRUS;
1318
 
            }
1319
 
        }
1320
 
        free(jumps);
1321
 
        break;
1322
 
    }
1323
 
 
1324
 
    /* Trojan.Swizzor.Gen */
1325
 
    if (SCAN_ALGO && (DCONF & PE_CONF_SWIZZOR) && nsections > 1 && fsize > 64*1024 && fsize < 4*1024*1024) {
1326
 
            if(dirs[2].Size) {
1327
 
                    struct swizz_stats *stats = cli_calloc(1, sizeof(*stats));
1328
 
                    unsigned int m = 1000;
1329
 
                    int ret = CL_CLEAN;
1330
 
 
1331
 
                    if (!stats)
1332
 
                            ret = CL_EMEM;
1333
 
                    else {
1334
 
                            cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), map, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
1335
 
                            if ((ret = cli_detect_swizz(stats)) == CL_VIRUS) {
1336
 
                                    *ctx->virname = "Heuristics.Trojan.Swizzor.Gen";
1337
 
                            }
1338
 
                            free(stats);
1339
 
                    }
1340
 
                    if (ret != CL_CLEAN) {
1341
 
                            free(exe_sections);
1342
 
                            return ret;
1343
 
                    }
1344
 
            }
1345
 
    }
1346
 
 
1347
 
 
1348
 
    /* !!!!!!!!!!!!!!    PACKERS START HERE    !!!!!!!!!!!!!! */
1349
 
    ctx->corrupted_input = 2; /* caller will reset on return */
1350
 
 
 
982
            }
 
983
 
 
984
            offnode = offnode->next;
 
985
        }
 
986
 
 
987
        while(offlist) {
 
988
            offnode = offlist;
 
989
            offlist = offlist->next;
 
990
            free(offnode);
 
991
        }
 
992
 
 
993
        if(ret == CL_VIRUS) {
 
994
            free(section_hdr);
 
995
            free(exe_sections);
 
996
            return CL_VIRUS;
 
997
        }
 
998
    }
 
999
 
 
1000
    /* SUE */
 
1001
    
 
1002
    if((DCONF & PE_CONF_SUE) && nsections > 2 && vep == exe_sections[nsections - 1].rva && exe_sections[nsections - 1].rsz > 0x350 && exe_sections[nsections - 1].rsz < 0x292+0x350+1000) {
 
1003
  
 
1004
      
 
1005
      char *sue=buff+0x74;
 
1006
      uint32_t key = 0;
 
1007
      
 
1008
      if(lseek(desc, ep-4, SEEK_SET) == -1) {
 
1009
        cli_dbgmsg("SUE: lseek() failed\n");
 
1010
        free(section_hdr);
 
1011
        free(exe_sections);
 
1012
        return CL_EIO;
 
1013
      }
 
1014
      if((unsigned int) cli_readn(desc, buff, exe_sections[nsections - 1].rsz+4) == exe_sections[nsections - 1].rsz+4) {
 
1015
        found=0;
 
1016
        while(CLI_ISCONTAINED(buff+4, exe_sections[nsections - 1].rsz, sue, 4*3)) {
 
1017
          if((cli_readint32(sue)^cli_readint32(sue+4))==0x5c41090e && (cli_readint32(sue)^cli_readint32(sue+8))==0x021e0145) {
 
1018
            found=1;
 
1019
            key=(cli_readint32(sue)^0x6e72656b);
 
1020
            break;
 
1021
          }
 
1022
          sue++;
 
1023
        }
 
1024
        cli_dbgmsg("SUE: key(%x) found @%x\n", key, sue-buff);
 
1025
        if (found && CLI_ISCONTAINED(buff, exe_sections[nsections - 1].rsz, sue-0x74, 0xbe) &&
 
1026
            (sue=sudecrypt(desc, fsize, exe_sections, nsections-1, sue, key, cli_readint32(buff), e_lfanew))) {
 
1027
          if(!(tempfile = cli_gentemp(NULL))) {
 
1028
            free(sue);
 
1029
            free(section_hdr);
 
1030
            free(exe_sections);
 
1031
            return CL_EMEM;
 
1032
          }
 
1033
 
 
1034
          if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
1035
            cli_dbgmsg("sue: Can't create file %s\n", tempfile);
 
1036
            free(tempfile);
 
1037
            free(sue);
 
1038
            free(section_hdr);
 
1039
            free(exe_sections);
 
1040
            return CL_EIO;
 
1041
          }
 
1042
          
 
1043
          if((unsigned int) cli_writen(ndesc, sue, ep) != ep) {
 
1044
            cli_dbgmsg("sue: Can't write %d bytes\n", ep);
 
1045
            close(ndesc);
 
1046
            free(tempfile);
 
1047
            free(sue);
 
1048
            free(section_hdr);
 
1049
            free(exe_sections);
 
1050
            return CL_EIO;
 
1051
          }
 
1052
 
 
1053
          free(sue);
 
1054
          if (cli_leavetemps_flag)
 
1055
            cli_dbgmsg("SUE: Decrypted executable saved in %s\n", tempfile);
 
1056
          else
 
1057
            cli_dbgmsg("SUE: Executable decrypted\n");
 
1058
          fsync(ndesc);
 
1059
          lseek(ndesc, 0, SEEK_SET);
 
1060
 
 
1061
          if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
1062
            free(section_hdr);
 
1063
            free(exe_sections);
 
1064
            close(ndesc);
 
1065
            if(!cli_leavetemps_flag)
 
1066
              unlink(tempfile);
 
1067
            free(tempfile);
 
1068
            return CL_VIRUS;
 
1069
          }
 
1070
          close(ndesc);
 
1071
          if(!cli_leavetemps_flag)
 
1072
            unlink(tempfile);
 
1073
          free(tempfile);
 
1074
        }
 
1075
      }
 
1076
 
 
1077
    }
1351
1078
 
1352
1079
    /* UPX, FSG, MEW support */
1353
1080
 
1355
1082
    found = 0;
1356
1083
    if(DCONF & (PE_CONF_UPX | PE_CONF_FSG | PE_CONF_MEW)) {
1357
1084
        for(i = 0; i < (unsigned int) nsections - 1; i++) {
1358
 
            if(!exe_sections[i].rsz && exe_sections[i].vsz && exe_sections[i + 1].rsz && exe_sections[i + 1].vsz) {
 
1085
            if(!section_hdr[i].SizeOfRawData && section_hdr[i].VirtualSize && section_hdr[i + 1].SizeOfRawData && section_hdr[i + 1].VirtualSize) {
1359
1086
                found = 1;
1360
1087
                cli_dbgmsg("UPX/FSG/MEW: empty section found - assuming compression\n");
1361
1088
                break;
1364
1091
    }
1365
1092
 
1366
1093
    /* MEW support */
1367
 
    if (found && (DCONF & PE_CONF_MEW) && epsize>=16 && epbuff[0]=='\xe9') {
 
1094
    if (found && (DCONF & PE_CONF_MEW)) {
1368
1095
        uint32_t fileoffset;
1369
 
        char *tbuff;
1370
 
 
1371
 
        fileoffset = (vep + cli_readint32(epbuff + 1) + 5);
1372
 
        while (fileoffset == 0x154 || fileoffset == 0x158) {
1373
 
            uint32_t offdiff, uselzma;
1374
 
 
1375
 
            cli_dbgmsg ("MEW: found MEW characteristics %08X + %08X + 5 = %08X\n", 
1376
 
                        cli_readint32(epbuff + 1), vep, cli_readint32(epbuff + 1) + vep + 5);
1377
 
 
1378
 
            if(!(tbuff = fmap_need_off_once(map, fileoffset, 0xb0)))
1379
 
                break;
1380
 
            if (fileoffset == 0x154) cli_dbgmsg("MEW: Win9x compatibility was set!\n");
1381
 
            else cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
1382
 
 
1383
 
            if((offdiff = cli_readint32(tbuff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
1384
 
                cli_dbgmsg("MEW: ESI is not in proper section\n");
1385
 
                break;
1386
 
            }
1387
 
            offdiff -= exe_sections[i + 1].rva;
1388
 
 
1389
 
            if(!exe_sections[i + 1].rsz) {
1390
 
                cli_dbgmsg("MEW: mew section is empty\n");
1391
 
                break;
1392
 
            }
1393
 
            ssize = exe_sections[i + 1].vsz;
1394
 
            dsize = exe_sections[i].vsz;
1395
 
 
1396
 
            cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff);
1397
 
 
1398
 
            CLI_UNPSIZELIMITS("MEW", MAX(ssize, dsize));
1399
 
            CLI_UNPSIZELIMITS("MEW", MAX(ssize + dsize, exe_sections[i + 1].rsz));
1400
 
 
1401
 
            if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
1402
 
                cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
1403
 
                break;
1404
 
            }
1405
 
 
1406
 
            /* allocate needed buffer */
1407
 
            if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
1408
 
                free(exe_sections);
1409
 
                return CL_EMEM;
1410
 
            }
1411
 
 
1412
 
            if((bytes = fmap_readn(map, src + dsize, exe_sections[i + 1].raw, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
1413
 
                cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
1414
 
                free(exe_sections);
1415
 
                free(src);
1416
 
                return CL_EREAD;
1417
 
            }
1418
 
            cli_dbgmsg("MEW: %u (%08x) bytes read\n", (unsigned int)bytes, (unsigned int)bytes);
1419
 
 
1420
 
            /* count offset to lzma proc, if lzma used, 0xe8 -> call */
1421
 
            if (tbuff[0x7b] == '\xe8') {
1422
 
                if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(tbuff + 0x7c) + fileoffset + 0x80, 4)) {
1423
 
                    cli_dbgmsg("MEW: lzma proc out of bounds!\n");
1424
 
                    free(src);
1425
 
                    break; /* to next unpacker in chain */
1426
 
                }
1427
 
                uselzma = cli_readint32(tbuff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
1428
 
            } else {
1429
 
                uselzma = 0;
1430
 
            }
1431
 
 
1432
 
            CLI_UNPTEMP("MEW",(src,exe_sections,0));
1433
 
            CLI_UNPRESULTS("MEW",(unmew11(src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, ndesc)),1,(src,0));
1434
 
            break;
1435
 
        }
1436
 
    }
1437
 
 
1438
 
    if(epsize<168) {
1439
 
        free(exe_sections);
1440
 
        return CL_CLEAN;
1441
 
    }
1442
 
 
1443
 
    if (found || upack) {
 
1096
        /* Check EP for MEW */
 
1097
        if(lseek(desc, ep, SEEK_SET) == -1) {
 
1098
            cli_dbgmsg("MEW: lseek() failed\n");
 
1099
            free(section_hdr);
 
1100
            free(exe_sections);
 
1101
            return CL_EIO;
 
1102
        }
 
1103
 
 
1104
        if((bytes = read(desc, buff, 25)) != 25 && bytes < 16) {
 
1105
            cli_dbgmsg("MEW: Can't read at least 16 bytes at 0x%x (%d) %d\n", ep, ep, bytes);
 
1106
            cli_dbgmsg("MEW: Broken or not compressed file\n");
 
1107
            free(section_hdr);
 
1108
            free(exe_sections);
 
1109
            return CL_CLEAN;
 
1110
        }
 
1111
 
 
1112
        fileoffset = (vep + cli_readint32(buff + 1) + 5);
 
1113
        do {
 
1114
            if (found && (buff[0] == '\xe9') && (fileoffset == 0x154 || fileoffset == 0x158))
 
1115
            {
 
1116
                uint32_t offdiff, uselzma;
 
1117
 
 
1118
                cli_dbgmsg ("MEW characteristics found: %08X + %08X + 5 = %08X\n", 
 
1119
                        cli_readint32(buff + 1), vep, cli_readint32(buff + 1) + vep + 5);
 
1120
 
 
1121
                if(lseek(desc, fileoffset, SEEK_SET) == -1) {
 
1122
                    cli_dbgmsg("MEW: lseek() failed\n");
 
1123
                    free(section_hdr);
 
1124
                    free(exe_sections);
 
1125
                    return CL_EIO;
 
1126
                }
 
1127
 
 
1128
                if((bytes = read(desc, buff, 0xb0)) != 0xb0) {
 
1129
                    cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %d\n", fileoffset, fileoffset, bytes);
 
1130
                    break;
 
1131
                }
 
1132
 
 
1133
                if (fileoffset == 0x154) 
 
1134
                    cli_dbgmsg("MEW: Win9x compatibility was set!\n");
 
1135
                else
 
1136
                    cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
 
1137
 
 
1138
                /* is it always 0x1C and 0x21C or not */
 
1139
                if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4)
 
1140
                {
 
1141
                    cli_dbgmsg("MEW: ESI is not in proper section\n");
 
1142
                    break;
 
1143
                }
 
1144
                offdiff -= exe_sections[i + 1].rva;
 
1145
 
 
1146
                if(lseek(desc, exe_sections[i + 1].raw, SEEK_SET) == -1) {
 
1147
                    cli_dbgmsg("MEW: lseek() failed\n"); /* ACAB: lseek won't fail here but checking doesn't hurt even */
 
1148
                    free(section_hdr);
 
1149
                    free(exe_sections);
 
1150
                    return CL_EIO;
 
1151
                }
 
1152
                ssize = exe_sections[i + 1].vsz;
 
1153
                dsize = exe_sections[i].vsz;
 
1154
 
 
1155
                cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff);
 
1156
                if(ctx->limits && ctx->limits->maxfilesize && (ssize + dsize > ctx->limits->maxfilesize || exe_sections[i + 1].rsz > ctx->limits->maxfilesize)) {
 
1157
                    cli_dbgmsg("MEW: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
 
1158
                    free(section_hdr);
 
1159
                    free(exe_sections);
 
1160
                    if(BLOCKMAX) {
 
1161
                        *ctx->virname = "PE.MEW.ExceededFileSize";
 
1162
                        return CL_VIRUS;
 
1163
                    } else {
 
1164
                        return CL_CLEAN;
 
1165
                    }
 
1166
                }
 
1167
 
 
1168
                /* allocate needed buffer */
 
1169
                if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
 
1170
                    free(section_hdr);
 
1171
                    free(exe_sections);
 
1172
                    return CL_EMEM;
 
1173
                }
 
1174
 
 
1175
                if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize)
 
1176
                {
 
1177
                    cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
 
1178
                    free(src);
 
1179
                    break;
 
1180
                }
 
1181
 
 
1182
                if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
 
1183
                    cli_dbgmsg("MEW: Can't read %d bytes [readed: %d]\n", exe_sections[i + 1].rsz, bytes);
 
1184
                    free(section_hdr);
 
1185
                    free(exe_sections);
 
1186
                    free(src);
 
1187
                    return CL_EIO;
 
1188
                }
 
1189
                cli_dbgmsg("MEW: %d (%08x) bytes read\n", bytes, bytes);
 
1190
                /* count offset to lzma proc, if lzma used, 0xe8 -> call */
 
1191
                if (buff[0x7b] == '\xe8')
 
1192
                {
 
1193
                    if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4))
 
1194
                    {
 
1195
                        cli_dbgmsg("MEW: lzma proc out of bounds!\n");
 
1196
                        free(src);
 
1197
                        break; /* to next unpacker in chain */
 
1198
                    }
 
1199
                    uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
 
1200
                } else
 
1201
                    uselzma = 0;
 
1202
 
 
1203
                if(!(tempfile = cli_gentemp(NULL))) {
 
1204
                    free(section_hdr);
 
1205
                    free(exe_sections);
 
1206
                    free(src);
 
1207
                    return CL_EMEM;
 
1208
                }
 
1209
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
 
1210
                    cli_dbgmsg("MEW: Can't create file %s\n", tempfile);
 
1211
                    free(tempfile);
 
1212
                    free(section_hdr);
 
1213
                    free(exe_sections);
 
1214
                    free(src);
 
1215
                    return CL_EIO;
 
1216
                }
 
1217
                dest = src;
 
1218
                switch(unmew11(i, src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, NULL, NULL, ndesc)) {
 
1219
                    case 1: /* Everything OK */
 
1220
                        cli_dbgmsg("MEW: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
1221
                        free(src);
 
1222
                        fsync(ndesc);
 
1223
                        lseek(ndesc, 0, SEEK_SET);
 
1224
 
 
1225
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
1226
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
1227
                            free(section_hdr);
 
1228
                            free(exe_sections);
 
1229
                            close(ndesc);
 
1230
                            if(!cli_leavetemps_flag)
 
1231
                                unlink(tempfile);
 
1232
                            free(tempfile);
 
1233
                            return CL_VIRUS;
 
1234
                        }
 
1235
                        close(ndesc);
 
1236
                        if(!cli_leavetemps_flag)
 
1237
                            unlink(tempfile);
 
1238
                        free(tempfile);
 
1239
                        free(section_hdr);
 
1240
                        free(exe_sections);
 
1241
                        return CL_CLEAN;
 
1242
                    default: /* Everything gone wrong */
 
1243
                        cli_dbgmsg("MEW: Unpacking failed\n");
 
1244
                        close(ndesc);
 
1245
                        unlink(tempfile); /* It's empty anyway */
 
1246
                        free(tempfile);
 
1247
                        free(src);
 
1248
                        break;
 
1249
                }
 
1250
            }
 
1251
        } while (0);
 
1252
    }
 
1253
 
 
1254
    if(found || upack) {
1444
1255
        /* Check EP for UPX vs. FSG vs. Upack */
 
1256
        if(lseek(desc, ep, SEEK_SET) == -1) {
 
1257
            cli_dbgmsg("UPX/FSG: lseek() failed\n");
 
1258
            free(section_hdr);
 
1259
            free(exe_sections);
 
1260
            return CL_EIO;
 
1261
        }
 
1262
 
 
1263
        if(cli_readn(desc, buff, 168) != 168) {
 
1264
            cli_dbgmsg("UPX/FSG: Can't read 168 bytes at 0x%x (%d)\n", ep, ep);
 
1265
            cli_dbgmsg("UPX/FSG: Broken or not UPX/FSG compressed file\n");
 
1266
            free(section_hdr);
 
1267
            free(exe_sections);
 
1268
            return CL_CLEAN;
 
1269
        }
1445
1270
 
1446
1271
        /* Upack 0.39 produces 2 types of executables
1447
1272
         * 3 sections:           | 2 sections (one empty, I don't chech found if !upack, since it's in OR above):
1463
1288
         * 
1464
1289
         */
1465
1290
        /* upack 0.39-3s + sample 0151477*/
1466
 
        while(((upack && nsections == 3) && /* 3 sections */
1467
 
            ((
1468
 
             epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
1469
 
             epbuff[5] == '\xad' && epbuff[6] == '\x50' /* lodsd; push eax */
1470
 
             )
1471
 
            || 
1472
 
            /* based on 0297729 sample from aCaB */
1473
 
            (epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
1474
 
             epbuff[5] == '\xff' && epbuff[6] == '\x36' /* push [esi] */
1475
 
             )
1476
 
           )) 
1477
 
           ||
1478
 
           ((!upack && nsections == 2) && /* 2 sections */
1479
 
            (( /* upack 0.39-2s */
1480
 
             epbuff[0] == '\x60' && epbuff[1] == '\xe8' && cli_readint32(epbuff+2) == 0x9 /* pusha; call+9 */
1481
 
             )
1482
 
            ||
1483
 
            ( /* upack 1.1/1.2, based on 2 samples */
1484
 
             epbuff[0] == '\xbe' && cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase) < min &&  /* mov esi */
1485
 
             cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > 0 &&
1486
 
             epbuff[5] == '\xad' && epbuff[6] == '\x8b' && epbuff[7] == '\xf8' /* loads;  mov edi, eax */
1487
 
             )
1488
 
           ))
1489
 
           ) { 
1490
 
            uint32_t vma, off;
1491
 
            int a,b,c;
1492
 
 
1493
 
            cli_dbgmsg("Upack characteristics found.\n");
1494
 
            a = exe_sections[0].vsz;
1495
 
            b = exe_sections[1].vsz;
1496
 
            if (upack) {
1497
 
                cli_dbgmsg("Upack: var set\n");
1498
 
                c = exe_sections[2].vsz;
1499
 
                ssize = exe_sections[0].ursz + exe_sections[0].uraw;
1500
 
                off = exe_sections[0].rva;
1501
 
                vma = EC32(optional_hdr32.ImageBase) + exe_sections[0].rva;
1502
 
            } else {
1503
 
                cli_dbgmsg("Upack: var NOT set\n");
1504
 
                c = exe_sections[1].rva;
1505
 
                ssize = exe_sections[1].uraw;
1506
 
                off = 0;
1507
 
                vma = exe_sections[1].rva - exe_sections[1].uraw;
1508
 
            }
1509
 
 
1510
 
            dsize = a+b+c;
1511
 
 
1512
 
            CLI_UNPSIZELIMITS("Upack", MAX(MAX(dsize, ssize), exe_sections[1].ursz));
1513
 
 
1514
 
            if (!CLI_ISCONTAINED(0, dsize, exe_sections[1].rva - off, exe_sections[1].ursz) || (upack && !CLI_ISCONTAINED(0, dsize, exe_sections[2].rva - exe_sections[0].rva, ssize)) || ssize > dsize) {
1515
 
                cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n");
1516
 
                break;
1517
 
            }
 
1291
        if((upack && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
 
1292
                                buff[5] == '\xad' && buff[6] == '\x50' && /* lodsd; push eax */
 
1293
                                EC16(file_hdr.NumberOfSections) == 3) || /* 3 sections */
 
1294
                        /* based on 0297729 sample from aCaB */
 
1295
                        (upack && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
 
1296
                         buff[5] == '\xff' && buff[6] == '\x36' && /* push [esi] */
 
1297
                         EC16(file_hdr.NumberOfSections) == 3) ||
 
1298
                        /* upack 0.39-2s */
 
1299
                        (!upack && buff[0] == '\x60' && buff[1] == '\xe8' && cli_readint32(buff+2) == 0x9 && /* pusha; call+9 */
 
1300
                         EC16(file_hdr.NumberOfSections) == 2) || /* 2 sections */
 
1301
                        /* upack 1.1/1.2, based on 2 samples */
 
1302
                        (!upack && buff[0] == '\xbe' && cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase) < min &&  /* mov esi */
 
1303
                         cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > 0 && 
 
1304
                         buff[5] == '\xad' && buff[6] == '\x8b' && buff[7] == '\xf8' && /* loads;  mov edi, eax */
 
1305
                         EC16(file_hdr.NumberOfSections) == 2)) { /* 2 sections */
 
1306
                uint32_t vma, off;
 
1307
                int a,b,c, file;
 
1308
 
 
1309
                cli_dbgmsg("Upack characteristics found.\n");
 
1310
                a = EC32(section_hdr[0].VirtualSize);
 
1311
                b = EC32(section_hdr[1].VirtualSize);
 
1312
                if (upack) {
 
1313
                        cli_dbgmsg("upack var set\n");
 
1314
                        c = EC32(section_hdr[2].VirtualSize);
 
1315
                        ssize = EC32(section_hdr[0].SizeOfRawData) + EC32(section_hdr[0].PointerToRawData);
 
1316
                        off = EC32(section_hdr[0].VirtualAddress);
 
1317
                        vma = EC32(optional_hdr32.ImageBase) + EC32(section_hdr[0].VirtualAddress);
 
1318
                } else {
 
1319
                        cli_dbgmsg("upack var NOT set\n");
 
1320
                        c = EC32(section_hdr[1].VirtualAddress);
 
1321
                        ssize = EC32(section_hdr[1].PointerToRawData);
 
1322
                        off = 0;
 
1323
                        vma = EC32(section_hdr[1].VirtualAddress) - EC32(section_hdr[1].PointerToRawData);
 
1324
                }
 
1325
 
 
1326
                dsize = a+b+c;
 
1327
                if (ctx->limits && ctx->limits->maxfilesize && (dsize > ctx->limits->maxfilesize || ssize > ctx->limits->maxfilesize || EC32(section_hdr[1].SizeOfRawData) > ctx->limits->maxfilesize))
 
1328
                {
 
1329
                    cli_dbgmsg("Upack: Sizes exceeded (a: %u, b: %u, c: %ux, max: %lu)\n", a, b, c, ctx->limits->maxfilesize);
 
1330
                    free(section_hdr);
 
1331
                    if(BLOCKMAX) {
 
1332
                        *ctx->virname = "PE.Upack.ExceededFileSize";
 
1333
                        return CL_VIRUS;
 
1334
                    } else {
 
1335
                        return CL_CLEAN;
 
1336
                    }
 
1337
                }
 
1338
                /* these are unsigned so if vaddr - off < 0, it should be ok */
 
1339
                if (EC32(section_hdr[1].VirtualAddress) - off > dsize || EC32(section_hdr[1].VirtualAddress) - off > dsize - EC32(section_hdr[1].SizeOfRawData) || (upack && (EC32(section_hdr[2].VirtualAddress) - EC32(section_hdr[0].VirtualAddress) > dsize || EC32(section_hdr[2].VirtualAddress) - EC32(section_hdr[0].VirtualAddress) > dsize - ssize)) || ssize > dsize)
 
1340
                {
 
1341
                    cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n");
 
1342
                    goto skip_upack_and_go_to_next_unpacker; /* I didn't want to add additional do while + break, can it be this way ? */
 
1343
                }
1518
1344
                        
1519
 
            if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1520
 
                free(exe_sections);
1521
 
                return CL_EMEM;
1522
 
            }
1523
 
 
1524
 
            if(fmap_readn(map, dest, 0, ssize) != ssize) {
1525
 
                cli_dbgmsg("Upack: Can't read raw data of section 0\n");
1526
 
                free(dest);
1527
 
                break;
1528
 
            }
1529
 
 
1530
 
            if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize);
1531
 
 
1532
 
            if(fmap_readn(map, dest + exe_sections[1].rva - off, exe_sections[1].uraw, exe_sections[1].ursz) != exe_sections[1].ursz) {
1533
 
                cli_dbgmsg("Upack: Can't read raw data of section 1\n");
1534
 
                free(dest);
1535
 
                break;
1536
 
            }
1537
 
 
1538
 
            CLI_UNPTEMP("Upack",(dest,exe_sections,0));
1539
 
            CLI_UNPRESULTS("Upack",(unupack(upack, dest, dsize, epbuff, vma, ep, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, ndesc)),1,(dest,0));
1540
 
            break;
1541
 
        }
1542
 
    }
1543
 
 
1544
 
    
1545
 
    while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\x87' && epbuff[1] == '\x25') {
1546
 
 
1547
 
        /* FSG v2.0 support - thanks to aCaB ! */
1548
 
 
1549
 
        uint32_t newesi, newedi, newebx, newedx;
1550
 
        
1551
 
        ssize = exe_sections[i + 1].rsz;
1552
 
        dsize = exe_sections[i].vsz;
1553
 
 
1554
 
        CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize));
1555
 
 
1556
 
        if(ssize <= 0x19 || dsize <= ssize) {
1557
 
            cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
1558
 
            free(exe_sections);
1559
 
            return CL_CLEAN;
1560
 
        }
1561
 
        
1562
 
        newedx = cli_readint32(epbuff + 2) - EC32(optional_hdr32.ImageBase);
1563
 
        if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
1564
 
            cli_dbgmsg("FSG: xchg out of bounds (%x), giving up\n", newedx);
1565
 
            break;
1566
 
        }
1567
 
        
1568
 
        if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1569
 
            cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
1570
 
            free(exe_sections);
1571
 
            return CL_ESEEK;
1572
 
        }
1573
 
 
1574
 
        dest = src + newedx - exe_sections[i + 1].rva;
1575
 
        if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) {
1576
 
            cli_dbgmsg("FSG: New ESP out of bounds\n");
1577
 
            break;
1578
 
        }
1579
 
 
1580
 
        newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
1581
 
        if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
1582
 
            cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx);
1583
 
            break;
1584
 
        }
 
1345
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
 
1346
                    free(section_hdr);
 
1347
                    return CL_EMEM;
 
1348
                }
 
1349
                src = NULL;
 
1350
                cli_dbgmsg("Upack: min: %08x %08x max: %08x\n", dest, a+b+c, dest+a+b+c);
 
1351
        
 
1352
                lseek(desc, 0, SEEK_SET);
 
1353
                if(read(desc, dest, ssize) != ssize) { /* 2vGiM: i think this can be overflowed - should you check for ssize < dsize ?
 
1354
                                                        * yup, I think you're right, added above
 
1355
                                                        */
 
1356
                    cli_dbgmsg("Upack: Can't read raw data of section 0\n");
 
1357
                    free(section_hdr);
 
1358
                    free(dest);
 
1359
                    return CL_EIO;
 
1360
                }
 
1361
 
 
1362
                if (upack)
 
1363
                        memmove(dest + EC32(section_hdr[2].VirtualAddress) - EC32(section_hdr[0].VirtualAddress), dest, ssize);
 
1364
 
 
1365
                lseek(desc, EC32(section_hdr[1].PointerToRawData), SEEK_SET);
 
1366
 
 
1367
                if(read(desc, dest+EC32(section_hdr[1].VirtualAddress) - off, EC32(section_hdr[1].SizeOfRawData)) != EC32(section_hdr[1].SizeOfRawData)) {
 
1368
                    cli_dbgmsg("Upack: Can't read raw data of section 1\n");
 
1369
                    free(section_hdr);
 
1370
                    free(dest);
 
1371
                    return CL_EIO;
 
1372
                }
 
1373
 
 
1374
                if(!(tempfile = cli_gentemp(NULL)))
 
1375
                    return CL_EMEM;
 
1376
 
 
1377
                if((file = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
 
1378
                    cli_dbgmsg("Upack: Can't create file %s\n", tempfile);
 
1379
                    free(tempfile);
 
1380
                    free(section_hdr);
 
1381
                    free(dest);
 
1382
                    return CL_EIO;
 
1383
                }
 
1384
 
 
1385
                switch (unupack(upack, dest, dsize, buff, vma, ep, EC32(optional_hdr32.ImageBase), EC32(section_hdr[0].VirtualAddress), file))
 
1386
                {
 
1387
                        case 1: /* Everything OK */
 
1388
                                cli_dbgmsg("Upack: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
1389
                                free(dest);
 
1390
                                fsync(file);
 
1391
                                lseek(file, 0, SEEK_SET);
 
1392
 
 
1393
                                cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
1394
                                if(cli_magic_scandesc(file, ctx) == CL_VIRUS) {
 
1395
                                        free(section_hdr);
 
1396
                                        close(file);
 
1397
                                        if(!cli_leavetemps_flag)
 
1398
                                                unlink(tempfile);
 
1399
                                        free(tempfile);
 
1400
                                        return CL_VIRUS;
 
1401
                                }
 
1402
 
 
1403
                                close(file);
 
1404
                                if(!cli_leavetemps_flag)
 
1405
                                        unlink(tempfile);
 
1406
                                free(tempfile);
 
1407
                                free(section_hdr);
 
1408
                                return CL_CLEAN;
 
1409
 
 
1410
                        default: /* Everything gone wrong */
 
1411
                                cli_dbgmsg("Upack: Unpacking failed\n");
 
1412
                                close(file);
 
1413
                                unlink(tempfile); /* It's empty anyway */
 
1414
                                free(tempfile);
 
1415
                                free(dest);
 
1416
                                break;
 
1417
                }
 
1418
        }
 
1419
skip_upack_and_go_to_next_unpacker:
 
1420
 
 
1421
        if((DCONF & PE_CONF_FSG) && buff[0] == '\x87' && buff[1] == '\x25') {
 
1422
 
 
1423
            /* FSG v2.0 support - thanks to aCaB ! */
 
1424
 
 
1425
            ssize = exe_sections[i + 1].rsz;
 
1426
            dsize = exe_sections[i].vsz;
 
1427
 
 
1428
            while(found) {
 
1429
                    uint32_t newesi, newedi, newebx, newedx;
 
1430
 
 
1431
                if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
 
1432
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
 
1433
                    free(section_hdr);
 
1434
                    free(exe_sections);
 
1435
                    if(BLOCKMAX) {
 
1436
                        *ctx->virname = "PE.FSG.ExceededFileSize";
 
1437
                        return CL_VIRUS;
 
1438
                    } else {
 
1439
                        return CL_CLEAN;
 
1440
                    }
 
1441
                }
 
1442
 
 
1443
                if(ssize <= 0x19 || dsize <= ssize) {
 
1444
                    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
 
1445
                    free(section_hdr);
 
1446
                    free(exe_sections);
 
1447
                    return CL_CLEAN;
 
1448
                }
 
1449
 
 
1450
                newedx = cli_readint32(buff + 2) - EC32(optional_hdr32.ImageBase);
 
1451
                if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
 
1452
                    cli_dbgmsg("FSG: xchg out of bounds (%x), giving up\n", newedx);
 
1453
                    break;
 
1454
                }
 
1455
 
 
1456
                if((src = (char *) cli_malloc(ssize)) == NULL) {
 
1457
                    free(section_hdr);
 
1458
                    free(exe_sections);
 
1459
                    return CL_EMEM;
 
1460
                }
 
1461
 
 
1462
                lseek(desc, exe_sections[i + 1].raw, SEEK_SET);
 
1463
                if((unsigned int) cli_readn(desc, src, ssize) != ssize) {
 
1464
                    cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
 
1465
                    free(section_hdr);
 
1466
                    free(exe_sections);
 
1467
                    free(src);
 
1468
                    return CL_EIO;
 
1469
                }
 
1470
 
 
1471
                dest = src + newedx - exe_sections[i + 1].rva;
 
1472
                if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) {
 
1473
                    cli_dbgmsg("FSG: New ESP out of bounds\n");
 
1474
                    free(src);
 
1475
                    break;
 
1476
                }
 
1477
 
 
1478
                newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
 
1479
                if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
 
1480
                    cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx);
 
1481
                    free(src);
 
1482
                    break;
 
1483
                }
1585
1484
 
1586
 
        dest = src + newedx - exe_sections[i + 1].rva;
1587
 
        if(!CLI_ISCONTAINED(src, ssize, dest, 32)) {
1588
 
            cli_dbgmsg("FSG: New stack out of bounds\n");
1589
 
            break;
1590
 
        }
1591
 
 
1592
 
        newedi = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
1593
 
        newesi = cli_readint32(dest + 4) - EC32(optional_hdr32.ImageBase);
1594
 
        newebx = cli_readint32(dest + 16) - EC32(optional_hdr32.ImageBase);
1595
 
        newedx = cli_readint32(dest + 20);
1596
 
 
1597
 
        if(newedi != exe_sections[i].rva) {
1598
 
            cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva);
1599
 
            break;
1600
 
        }
1601
 
 
1602
 
        if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
1603
 
            cli_dbgmsg("FSG: Source buffer out of section bounds\n");
1604
 
            break;
1605
 
        }
1606
 
 
1607
 
        if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) {
1608
 
            cli_dbgmsg("FSG: Array of functions out of bounds\n");
1609
 
            break;
1610
 
        }
1611
 
 
1612
 
        newedx=cli_readint32(newebx + 12 - exe_sections[i + 1].rva + src) - EC32(optional_hdr32.ImageBase);
1613
 
        cli_dbgmsg("FSG: found old EP @%x\n",newedx);
1614
 
 
1615
 
        if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1616
 
            free(exe_sections);
 
1485
                dest = src + newedx - exe_sections[i + 1].rva;
 
1486
                if(!CLI_ISCONTAINED(src, ssize, dest, 32)) {
 
1487
                    cli_dbgmsg("FSG: New stack out of bounds\n");
 
1488
                    free(src);
 
1489
                    break;
 
1490
                }
 
1491
 
 
1492
                newedi = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
 
1493
                newesi = cli_readint32(dest + 4) - EC32(optional_hdr32.ImageBase);
 
1494
                newebx = cli_readint32(dest + 16) - EC32(optional_hdr32.ImageBase);
 
1495
                newedx = cli_readint32(dest + 20);
 
1496
 
 
1497
                if(newedi != exe_sections[i].rva) {
 
1498
                    cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva);
 
1499
                    free(src);
 
1500
                    break;
 
1501
                }
 
1502
 
 
1503
                if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
 
1504
                    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
 
1505
                    free(src);
 
1506
                    break;
 
1507
                }
 
1508
 
 
1509
                if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) {
 
1510
                    cli_dbgmsg("FSG: Array of functions out of bounds\n");
 
1511
                    free(src);
 
1512
                    break;
 
1513
                }
 
1514
 
 
1515
                newedx=cli_readint32(newebx + 12 - exe_sections[i + 1].rva + src) - EC32(optional_hdr32.ImageBase);
 
1516
                cli_dbgmsg("FSG: found old EP @%x\n",newedx);
 
1517
 
 
1518
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
 
1519
                    free(section_hdr);
 
1520
                    free(exe_sections);
 
1521
                    free(src);
 
1522
                    return CL_EMEM;
 
1523
                }
 
1524
 
 
1525
                if(!(tempfile = cli_gentemp(NULL))) {
 
1526
                    free(section_hdr);
 
1527
                    free(exe_sections);
 
1528
                    free(src);
 
1529
                    free(dest);
 
1530
                    return CL_EMEM;
 
1531
                }
 
1532
 
 
1533
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
1534
                    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
 
1535
                    free(tempfile);
 
1536
                    free(section_hdr);
 
1537
                    free(exe_sections);
 
1538
                    free(src);
 
1539
                    free(dest);
 
1540
                    return CL_EIO;
 
1541
                }
 
1542
                
 
1543
                switch (unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)) {
 
1544
                    case 1: /* Everything OK */
 
1545
                        cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
1546
                        free(src);
 
1547
                        free(dest);
 
1548
                        fsync(ndesc);
 
1549
                        lseek(ndesc, 0, SEEK_SET);
 
1550
 
 
1551
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
1552
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
1553
                            free(section_hdr);
 
1554
                            free(exe_sections);
 
1555
                            close(ndesc);
 
1556
                            if(!cli_leavetemps_flag)
 
1557
                                unlink(tempfile);
 
1558
                            free(tempfile);
 
1559
                            return CL_VIRUS;
 
1560
                        }
 
1561
 
 
1562
                        close(ndesc);
 
1563
                        if(!cli_leavetemps_flag)
 
1564
                            unlink(tempfile);
 
1565
                        free(tempfile);
 
1566
                        free(section_hdr);
 
1567
                        free(exe_sections);
 
1568
                        return CL_CLEAN;
 
1569
 
 
1570
                    case 0: /* We've got an unpacked buffer, no exe though */
 
1571
                        cli_dbgmsg("FSG: Successfully decompressed\n");
 
1572
                        close(ndesc);
 
1573
                        unlink(tempfile);
 
1574
                        free(tempfile);
 
1575
                        found = 0;
 
1576
                        upx_success = 1;
 
1577
                        break; /* Go and scan the buffer! */
 
1578
 
 
1579
                    default: /* Everything gone wrong */
 
1580
                        cli_dbgmsg("FSG: Unpacking failed\n");
 
1581
                        close(ndesc);
 
1582
                        unlink(tempfile); /* It's empty anyway */
 
1583
                        free(tempfile);
 
1584
                        free(src);
 
1585
                        free(dest);
 
1586
                        break;
 
1587
                }
 
1588
 
 
1589
                break; /* were done with 2 */
 
1590
            }
 
1591
        }
 
1592
 
 
1593
        if(found && (DCONF & PE_CONF_FSG) && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) < min) {
 
1594
 
 
1595
            /* FSG support - v. 1.33 (thx trog for the many samples) */
 
1596
 
 
1597
            ssize = exe_sections[i + 1].rsz;
 
1598
            dsize = exe_sections[i].vsz;
 
1599
 
 
1600
            while(found) {
 
1601
                    int sectcnt = 0;
 
1602
                    char *support;
 
1603
                    uint32_t newesi, newedi, newebx, oldep, gp, t;
 
1604
                    struct cli_exe_section *sections;
 
1605
 
 
1606
 
 
1607
                if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
 
1608
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, ctx->limits->maxfilesize);
 
1609
                    free(section_hdr);
 
1610
                    free(exe_sections);
 
1611
                    if(BLOCKMAX) {
 
1612
                        *ctx->virname = "PE.FSG.ExceededFileSize";
 
1613
                        return CL_VIRUS;
 
1614
                    } else {
 
1615
                        return CL_CLEAN;
 
1616
                    }
 
1617
                }
 
1618
 
 
1619
                if(ssize <= 0x19 || dsize <= ssize) {
 
1620
                    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
 
1621
                    free(section_hdr);
 
1622
                    free(exe_sections);
 
1623
                    return CL_CLEAN;
 
1624
                }
 
1625
 
 
1626
                if(!(gp = cli_rawaddr(cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize)) && err ) {
 
1627
                    cli_dbgmsg("FSG: Support data out of padding area\n");
 
1628
                    break;
 
1629
                }
 
1630
 
 
1631
                lseek(desc, gp, SEEK_SET);
 
1632
                gp = exe_sections[i + 1].raw - gp;
 
1633
 
 
1634
                if(ctx->limits && ctx->limits->maxfilesize && (unsigned int) gp > ctx->limits->maxfilesize) {
 
1635
                    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, ctx->limits->maxfilesize);
 
1636
                    free(section_hdr);
 
1637
                    free(exe_sections);
 
1638
                    if(BLOCKMAX) {
 
1639
                        *ctx->virname = "PE.FSG.ExceededFileSize";
 
1640
                        return CL_VIRUS;
 
1641
                    } else {
 
1642
                        return CL_CLEAN;
 
1643
                    }
 
1644
                }
 
1645
 
 
1646
                if((support = (char *) cli_malloc(gp)) == NULL) {
 
1647
                    free(section_hdr);
 
1648
                    free(exe_sections);
 
1649
                    return CL_EMEM;
 
1650
                }
 
1651
 
 
1652
                if((int)cli_readn(desc, support, gp) != (int)gp) {
 
1653
                    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
 
1654
                    free(section_hdr);
 
1655
                    free(exe_sections);
 
1656
                    free(support);
 
1657
                    return CL_EIO;
 
1658
                }
 
1659
 
 
1660
                /* newebx = cli_readint32(support) - EC32(optional_hdr32.ImageBase);  Unused */
 
1661
                newedi = cli_readint32(support + 4) - EC32(optional_hdr32.ImageBase); /* 1st dest */
 
1662
                newesi = cli_readint32(support + 8) - EC32(optional_hdr32.ImageBase); /* Source */
 
1663
 
 
1664
                if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
 
1665
                    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
 
1666
                    free(support);
 
1667
                    break;
 
1668
                }
 
1669
 
 
1670
                if(newedi != exe_sections[i].rva) {
 
1671
                    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
 
1672
                    free(support);
 
1673
                    break;
 
1674
                }
 
1675
 
 
1676
                /* Counting original sections */
 
1677
                for(t = 12; t < gp - 4; t += 4) {
 
1678
                        uint32_t rva = cli_readint32(support+t);
 
1679
 
 
1680
                    if(!rva)
 
1681
                        break;
 
1682
 
 
1683
                    rva -= EC32(optional_hdr32.ImageBase)+1;
 
1684
                    sectcnt++;
 
1685
 
 
1686
                    if(rva % 0x1000)
 
1687
                        /* FIXME: really need to bother? */
 
1688
                        cli_dbgmsg("FSG: Original section %d is misaligned\n", sectcnt);
 
1689
 
 
1690
                    if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) {
 
1691
                        cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
 
1692
                        break;
 
1693
                    }
 
1694
                }
 
1695
 
 
1696
                if(t >= gp - 4 || cli_readint32(support + t)) {
 
1697
                    free(support);
 
1698
                    break;
 
1699
                }
 
1700
 
 
1701
                if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
 
1702
                    free(section_hdr);
 
1703
                    free(exe_sections);
 
1704
                    free(support);
 
1705
                    return CL_EMEM;
 
1706
                }
 
1707
 
 
1708
                sections[0].rva = newedi;
 
1709
                for(t = 1; t <= (uint32_t)sectcnt; t++)
 
1710
                    sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase);
 
1711
 
 
1712
                free(support);
 
1713
 
 
1714
                if((src = (char *) cli_malloc(ssize)) == NULL) {
 
1715
                    free(section_hdr);
 
1716
                    free(exe_sections);
 
1717
                    free(sections);
 
1718
                    return CL_EMEM;
 
1719
                }
 
1720
 
 
1721
                lseek(desc, exe_sections[i + 1].raw, SEEK_SET);
 
1722
                if((unsigned int) cli_readn(desc, src, ssize) != ssize) {
 
1723
                    cli_dbgmsg("Can't read raw data of section %d\n", i);
 
1724
                    free(section_hdr);
 
1725
                    free(exe_sections);
 
1726
                    free(sections);
 
1727
                    free(src);
 
1728
                    return CL_EIO;
 
1729
                }
 
1730
 
 
1731
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
 
1732
                    free(section_hdr);
 
1733
                    free(exe_sections);
 
1734
                    free(src);
 
1735
                    free(sections);
 
1736
                    return CL_EMEM;
 
1737
                }
 
1738
 
 
1739
                oldep = vep + 161 + 6 + cli_readint32(buff+163);
 
1740
                cli_dbgmsg("FSG: found old EP @%x\n", oldep);
 
1741
 
 
1742
                if(!(tempfile = cli_gentemp(NULL))) {
 
1743
                    free(section_hdr);
 
1744
                    free(exe_sections);
 
1745
                    free(src);
 
1746
                    free(dest);
 
1747
                    free(sections);
 
1748
                    return CL_EMEM;
 
1749
                }
 
1750
 
 
1751
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
1752
                    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
 
1753
                    free(tempfile);
 
1754
                    free(section_hdr);
 
1755
                    free(exe_sections);
 
1756
                    free(src);
 
1757
                    free(dest);
 
1758
                    free(sections);
 
1759
                    return CL_EIO;
 
1760
                }
 
1761
 
 
1762
                switch(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)) {
 
1763
                    case 1: /* Everything OK */
 
1764
                        cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
1765
                        free(src);
 
1766
                        free(dest);
 
1767
                        free(sections);
 
1768
                        fsync(ndesc);
 
1769
                        lseek(ndesc, 0, SEEK_SET);
 
1770
 
 
1771
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
1772
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
1773
                            free(section_hdr);
 
1774
                            free(exe_sections);
 
1775
                            close(ndesc);
 
1776
                            if(!cli_leavetemps_flag)
 
1777
                                unlink(tempfile);
 
1778
                            free(tempfile);
 
1779
                            return CL_VIRUS;
 
1780
                        }
 
1781
 
 
1782
                        close(ndesc);
 
1783
                        if(!cli_leavetemps_flag)
 
1784
                            unlink(tempfile);
 
1785
                        free(tempfile);
 
1786
                        free(section_hdr);
 
1787
                        free(exe_sections);
 
1788
                        return CL_CLEAN;
 
1789
 
 
1790
                    case 0: /* We've got an unpacked buffer, no exe though */
 
1791
                        cli_dbgmsg("FSG: Successfully decompressed\n");
 
1792
                        close(ndesc);
 
1793
                        unlink(tempfile);
 
1794
                        free(tempfile);
 
1795
                        free(sections);
 
1796
                        found = 0;
 
1797
                        upx_success = 1;
 
1798
                        break; /* Go and scan the buffer! */
 
1799
 
 
1800
                    default: /* Everything gone wrong */
 
1801
                        cli_dbgmsg("FSG: Unpacking failed\n");
 
1802
                        close(ndesc);
 
1803
                        unlink(tempfile); /* It's empty anyway */
 
1804
                        free(tempfile);
 
1805
                        free(src);
 
1806
                        free(dest);
 
1807
                        free(sections);
 
1808
                        break;
 
1809
                }
 
1810
 
 
1811
                break; /* were done with 1.33 */
 
1812
            }
 
1813
        }
 
1814
 
 
1815
        /* FIXME: easy 2 hack */
 
1816
        if(found && (DCONF & PE_CONF_FSG) && buff[0] == '\xbb' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) < min && buff[5] == '\xbf' && buff[10] == '\xbe' && vep >= exe_sections[i + 1].rva && vep - exe_sections[i + 1].rva > exe_sections[i + 1].rva - 0xe0 ) {
 
1817
 
 
1818
            /* FSG support - v. 1.31 */
 
1819
 
 
1820
            ssize = exe_sections[i + 1].rsz;
 
1821
            dsize = exe_sections[i].vsz;
 
1822
 
 
1823
            while(found) {
 
1824
                    int sectcnt = 0;
 
1825
                    uint32_t t;
 
1826
                    uint32_t gp = cli_rawaddr(cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize);
 
1827
                    char *support;
 
1828
                    uint32_t newesi = cli_readint32(buff+11) - EC32(optional_hdr32.ImageBase);
 
1829
                    uint32_t newedi = cli_readint32(buff+6) - EC32(optional_hdr32.ImageBase);
 
1830
                    uint32_t oldep = vep - exe_sections[i + 1].rva;
 
1831
                    struct cli_exe_section *sections;
 
1832
 
 
1833
                if(err) {
 
1834
                    cli_dbgmsg("FSG: Support data out of padding area\n");
 
1835
                    break;
 
1836
                }
 
1837
 
 
1838
                if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].raw) {
 
1839
                    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
 
1840
                    break;
 
1841
                }
 
1842
 
 
1843
                if(newedi != exe_sections[i].rva) {
 
1844
                    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
 
1845
                    break;
 
1846
                }
 
1847
 
 
1848
                if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
 
1849
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, ctx->limits->maxfilesize);
 
1850
                    free(section_hdr);
 
1851
                    free(exe_sections);
 
1852
                    if(BLOCKMAX) {
 
1853
                        *ctx->virname = "PE.FSG.ExceededFileSize";
 
1854
                        return CL_VIRUS;
 
1855
                    } else {
 
1856
                        return CL_CLEAN;
 
1857
                    }
 
1858
                }
 
1859
 
 
1860
                if(ssize <= 0x19 || dsize <= ssize) {
 
1861
                    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
 
1862
                    free(section_hdr);
 
1863
                    free(exe_sections);
 
1864
                    return CL_CLEAN;
 
1865
                }
 
1866
 
 
1867
                lseek(desc, gp, SEEK_SET);
 
1868
                gp = exe_sections[i + 1].raw - gp;
 
1869
 
 
1870
                if(ctx->limits && ctx->limits->maxfilesize && gp > ctx->limits->maxfilesize) {
 
1871
                    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, ctx->limits->maxfilesize);
 
1872
                    free(section_hdr);
 
1873
                    free(exe_sections);
 
1874
                    if(BLOCKMAX) {
 
1875
                        *ctx->virname = "PE.FSG.ExceededFileSize";
 
1876
                        return CL_VIRUS;
 
1877
                    } else {
 
1878
                        return CL_CLEAN;
 
1879
                    }
 
1880
                }
 
1881
 
 
1882
                if((support = (char *) cli_malloc(gp)) == NULL) {
 
1883
                    free(section_hdr);
 
1884
                    free(exe_sections);
 
1885
                    return CL_EMEM;
 
1886
                }
 
1887
 
 
1888
                if(cli_readn(desc, support, gp) != (int)gp) {
 
1889
                    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
 
1890
                    free(section_hdr);
 
1891
                    free(exe_sections);
 
1892
                    free(support);
 
1893
                    return CL_EIO;
 
1894
                }
 
1895
 
 
1896
                /* Counting original sections */
 
1897
                for(t = 0; t < gp - 2; t += 2) {
 
1898
                  uint32_t rva = support[t]|(support[t+1]<<8);
 
1899
                  
 
1900
                  if (rva == 2 || rva == 1)
 
1901
                    break;
 
1902
 
 
1903
                  rva = ((rva-2)<<12) - EC32(optional_hdr32.ImageBase);
 
1904
                  sectcnt++;
 
1905
 
 
1906
                  if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) {
 
1907
                    cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
 
1908
                    break;
 
1909
                  }
 
1910
                }
 
1911
 
 
1912
                if(t >= gp-10 || cli_readint32(support + t + 6) != 2) {
 
1913
                    free(support);
 
1914
                    break;
 
1915
                }
 
1916
 
 
1917
                if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
 
1918
                    free(section_hdr);
 
1919
                    free(exe_sections);
 
1920
                    free(support);
 
1921
                    return CL_EMEM;
 
1922
                }
 
1923
 
 
1924
                sections[0].rva = newedi;
 
1925
                for(t = 0; t <= (uint32_t)sectcnt - 1; t++) {
 
1926
                  sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase);
 
1927
                }
 
1928
 
 
1929
                free(support);
 
1930
 
 
1931
                if((src = (char *) cli_malloc(ssize)) == NULL) {
 
1932
                    free(section_hdr);
 
1933
                    free(exe_sections);
 
1934
                    free(sections);
 
1935
                    return CL_EMEM;
 
1936
                }
 
1937
 
 
1938
                lseek(desc, exe_sections[i + 1].raw, SEEK_SET);
 
1939
                if((unsigned int) cli_readn(desc, src, ssize) != ssize) {
 
1940
                    cli_dbgmsg("FSG: Can't read raw data of section %d\n", i);
 
1941
                    free(section_hdr);
 
1942
                    free(exe_sections);
 
1943
                    free(sections);
 
1944
                    free(src);
 
1945
                    return CL_EIO;
 
1946
                }
 
1947
 
 
1948
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
 
1949
                    free(section_hdr);
 
1950
                    free(exe_sections);
 
1951
                    free(src);
 
1952
                    free(sections);
 
1953
                    return CL_EMEM;
 
1954
                }
 
1955
 
 
1956
                /* Better not increasing buff size any further, let's go the hard way */
 
1957
                gp = 0xda + 6*(buff[16]=='\xe8');
 
1958
                oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep);
 
1959
                cli_dbgmsg("FSG: found old EP @%x\n", oldep);
 
1960
 
 
1961
                if(!(tempfile = cli_gentemp(NULL))) {
 
1962
                    free(section_hdr);
 
1963
                    free(exe_sections);
 
1964
                    free(src);
 
1965
                    free(dest);
 
1966
                    free(sections);
 
1967
                    return CL_EMEM;
 
1968
                }
 
1969
 
 
1970
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
1971
                    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
 
1972
                    free(tempfile);
 
1973
                    free(section_hdr);
 
1974
                    free(exe_sections);
 
1975
                    free(src);
 
1976
                    free(dest);
 
1977
                    free(sections);
 
1978
                    return CL_EIO;
 
1979
                }
 
1980
 
 
1981
                switch(unfsg_133(src + newesi - EC32(section_hdr[i + 1].VirtualAddress), dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)) {
 
1982
                    case 1: /* Everything OK */
 
1983
                        cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
1984
                        free(src);
 
1985
                        free(dest);
 
1986
                        free(sections);
 
1987
                        fsync(ndesc);
 
1988
                        lseek(ndesc, 0, SEEK_SET);
 
1989
 
 
1990
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
1991
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
1992
                            free(section_hdr);
 
1993
                            free(exe_sections);
 
1994
                            close(ndesc);
 
1995
                            if(!cli_leavetemps_flag)
 
1996
                                unlink(tempfile);
 
1997
                            free(tempfile);
 
1998
                            return CL_VIRUS;
 
1999
                        }
 
2000
 
 
2001
                        close(ndesc);
 
2002
                        if(!cli_leavetemps_flag)
 
2003
                            unlink(tempfile);
 
2004
                        free(tempfile);
 
2005
                        free(section_hdr);
 
2006
                        free(exe_sections);
 
2007
                        return CL_CLEAN;
 
2008
 
 
2009
                    case 0: /* We've got an unpacked buffer, no exe though */
 
2010
                        cli_dbgmsg("FSG: FSG: Successfully decompressed\n");
 
2011
                        close(ndesc);
 
2012
                        unlink(tempfile);
 
2013
                        free(tempfile);
 
2014
                        free(sections);
 
2015
                        found = 0;
 
2016
                        upx_success = 1;
 
2017
                        break; /* Go and scan the buffer! */
 
2018
 
 
2019
                    default: /* Everything gone wrong */
 
2020
                        cli_dbgmsg("FSG: Unpacking failed\n");
 
2021
                        close(ndesc);
 
2022
                        unlink(tempfile); /* It's empty anyway */
 
2023
                        free(tempfile);
 
2024
                        free(src);
 
2025
                        free(dest);
 
2026
                        free(sections);
 
2027
                        break;
 
2028
                }
 
2029
 
 
2030
                break; /* were done with 1.31 */
 
2031
            }
 
2032
        }
 
2033
 
 
2034
 
 
2035
        if(found && (DCONF & PE_CONF_UPX)) {
 
2036
 
 
2037
            /* UPX support */
 
2038
 
 
2039
            strncpy(sname, (char *) section_hdr[i].Name, 8);
 
2040
            sname[8] = 0;
 
2041
            cli_dbgmsg("UPX: Section %d name: %s\n", i, sname);
 
2042
            strncpy(sname, (char *) section_hdr[i + 1].Name, 8);
 
2043
            sname[8] = 0;
 
2044
            cli_dbgmsg("UPX: Section %d name: %s\n", i + 1, sname);
 
2045
 
 
2046
            if(strncmp((char *) section_hdr[i].Name, "UPX0", 4) || strncmp((char *) section_hdr[i + 1].Name, "UPX1", 4))
 
2047
                cli_dbgmsg("UPX: Possibly hacked UPX section headers\n");
 
2048
 
 
2049
            /* we assume (i + 1) is UPX1 */
 
2050
            ssize = exe_sections[i + 1].rsz;
 
2051
            dsize = exe_sections[i].vsz + exe_sections[i + 1].vsz;
 
2052
 
 
2053
            if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
 
2054
                cli_dbgmsg("UPX: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
 
2055
                free(section_hdr);
 
2056
                free(exe_sections);
 
2057
                if(BLOCKMAX) {
 
2058
                    *ctx->virname = "PE.UPX.ExceededFileSize";
 
2059
                    return CL_VIRUS;
 
2060
                } else {
 
2061
                    return CL_CLEAN;
 
2062
                }
 
2063
            }
 
2064
 
 
2065
            if(ssize <= 0x19 || dsize <= ssize) { /* FIXME: What are reasonable values? */
 
2066
                cli_dbgmsg("UPX: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
 
2067
                free(section_hdr);
 
2068
                free(exe_sections);
 
2069
                return CL_CLEAN;
 
2070
            }
 
2071
 
 
2072
            /* FIXME: use file operations in case of big files */
 
2073
            if((src = (char *) cli_malloc(ssize)) == NULL) {
 
2074
                free(section_hdr);
 
2075
                free(exe_sections);
 
2076
                return CL_EMEM;
 
2077
            }
 
2078
 
 
2079
            if(dsize > CLI_MAX_ALLOCATION) {
 
2080
                cli_errmsg("UPX: Too big value of dsize\n");
 
2081
                free(section_hdr);
 
2082
                free(exe_sections);
 
2083
                free(src);
 
2084
                return CL_EMEM;
 
2085
            }
 
2086
 
 
2087
            if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) {
 
2088
                free(section_hdr);
 
2089
                free(exe_sections);
 
2090
                free(src);
 
2091
                return CL_EMEM;
 
2092
            }
 
2093
 
 
2094
            lseek(desc, exe_sections[i + 1].raw, SEEK_SET);
 
2095
            if((unsigned int) cli_readn(desc, src, ssize) != ssize) {
 
2096
                cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
 
2097
                free(section_hdr);
 
2098
                free(exe_sections);
 
2099
                free(src);
 
2100
                free(dest);
 
2101
                return CL_EIO;
 
2102
            }
 
2103
 
 
2104
            /* try to detect UPX code */
 
2105
 
 
2106
            if(lseek(desc, ep, SEEK_SET) == -1) {
 
2107
                cli_dbgmsg("UPX: lseek() failed\n");
 
2108
                free(section_hdr);
 
2109
                free(exe_sections);
 
2110
                free(src);
 
2111
                free(dest);
 
2112
                return CL_EIO;
 
2113
            }
 
2114
 
 
2115
            if(cli_readn(desc, buff, 126) != 126) { /* i.e. 0x69 + 13 + 8 */
 
2116
                cli_dbgmsg("UPX: Can't read 126 bytes at 0x%x (%d)\n", ep, ep);
 
2117
                cli_dbgmsg("UPX: Broken or not UPX compressed file\n");
 
2118
                free(section_hdr);
 
2119
                free(exe_sections);
 
2120
                free(src);
 
2121
                free(dest);
 
2122
                return CL_CLEAN;
 
2123
            } else {
 
2124
                if(cli_memstr(UPX_NRV2B, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, buff + 0x69 + 8, 13)) {
 
2125
                    cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
 
2126
                    upxfn = upx_inflate2b;
 
2127
                } else if(cli_memstr(UPX_NRV2D, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2D, 24, buff + 0x69 + 8, 13)) {
 
2128
                    cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n");
 
2129
                    upxfn = upx_inflate2d;
 
2130
                } else if(cli_memstr(UPX_NRV2E, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2E, 24, buff + 0x69 + 8, 13)) {
 
2131
                    cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n");
 
2132
                    upxfn = upx_inflate2e;
 
2133
                }
 
2134
            }
 
2135
 
 
2136
            if(upxfn) {
 
2137
                    int skew = cli_readint32(buff + 2) - EC32(optional_hdr32.ImageBase) - exe_sections[i + 1].rva;
 
2138
 
 
2139
                if(buff[1] != '\xbe' || skew <= 0 || skew > 0xfff) { /* FIXME: legit skews?? */
 
2140
                    skew = 0; 
 
2141
                    if(upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0)
 
2142
                        upx_success = 1;
 
2143
 
 
2144
                } else {
 
2145
                    cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew);
 
2146
                    if(upxfn(src + skew, ssize - skew, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep-skew) >= 0 || upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0)
 
2147
                        upx_success = 1;
 
2148
                }
 
2149
 
 
2150
                if(upx_success)
 
2151
                    cli_dbgmsg("UPX: Successfully decompressed\n");
 
2152
                else
 
2153
                    cli_dbgmsg("UPX: Preferred decompressor failed\n");
 
2154
            }
 
2155
 
 
2156
            if(!upx_success && upxfn != upx_inflate2b) {
 
2157
                if(upx_inflate2b(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2b(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) {
 
2158
 
 
2159
                    cli_dbgmsg("UPX: NRV2B decompressor failed\n");
 
2160
                } else {
 
2161
                    upx_success = 1;
 
2162
                    cli_dbgmsg("UPX: Successfully decompressed with NRV2B\n");
 
2163
                }
 
2164
            }
 
2165
 
 
2166
            if(!upx_success && upxfn != upx_inflate2d) {
 
2167
                if(upx_inflate2d(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2d(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) {
 
2168
 
 
2169
                    cli_dbgmsg("UPX: NRV2D decompressor failed\n");
 
2170
                } else {
 
2171
                    upx_success = 1;
 
2172
                    cli_dbgmsg("UPX: Successfully decompressed with NRV2D\n");
 
2173
                }
 
2174
            }
 
2175
 
 
2176
            if(!upx_success && upxfn != upx_inflate2e) {
 
2177
                if(upx_inflate2e(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2e(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) {
 
2178
                    cli_dbgmsg("UPX: NRV2E decompressor failed\n");
 
2179
                } else {
 
2180
                    upx_success = 1;
 
2181
                    cli_dbgmsg("UPX: Successfully decompressed with NRV2E\n");
 
2182
                }
 
2183
            }
 
2184
 
 
2185
            if(!upx_success) {
 
2186
                cli_dbgmsg("UPX: All decompressors failed\n");
 
2187
                free(src);
 
2188
                free(dest);
 
2189
            }
 
2190
        }
 
2191
 
 
2192
        if(upx_success) {
1617
2193
            free(src);
1618
 
            return CL_EMEM;
1619
 
        }
1620
 
 
1621
 
        CLI_UNPTEMP("FSG",(dest,exe_sections,0));
1622
 
        CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(dest,0));
1623
 
        break;
1624
 
    }
1625
 
 
1626
 
 
1627
 
    while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) < min) {
1628
 
 
1629
 
        /* FSG support - v. 1.33 (thx trog for the many samples) */
1630
 
 
1631
 
        int sectcnt = 0;
1632
 
        char *support;
1633
 
        uint32_t newesi, newedi, oldep, gp, t;
1634
 
        struct cli_exe_section *sections;
1635
 
 
1636
 
        ssize = exe_sections[i + 1].rsz;
1637
 
        dsize = exe_sections[i].vsz;
1638
 
 
1639
 
        CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize));
1640
 
 
1641
 
        if(ssize <= 0x19 || dsize <= ssize) {
1642
 
            cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
1643
 
            free(exe_sections);
1644
 
            return CL_CLEAN;
1645
 
        }
1646
 
 
1647
 
        if(!(t = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
1648
 
            cli_dbgmsg("FSG: Support data out of padding area\n");
1649
 
            break;
1650
 
        }
1651
 
 
1652
 
        gp = exe_sections[i + 1].raw - t;
1653
 
 
1654
 
        CLI_UNPSIZELIMITS("FSG", gp);
1655
 
 
1656
 
        if(!(support = fmap_need_off_once(map, t, gp))) {
1657
 
            cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
1658
 
            free(exe_sections);
1659
 
            return CL_EREAD;
1660
 
        }
1661
 
 
1662
 
        /* newebx = cli_readint32(support) - EC32(optional_hdr32.ImageBase);  Unused */
1663
 
        newedi = cli_readint32(support + 4) - EC32(optional_hdr32.ImageBase); /* 1st dest */
1664
 
        newesi = cli_readint32(support + 8) - EC32(optional_hdr32.ImageBase); /* Source */
1665
 
 
1666
 
        if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
1667
 
            cli_dbgmsg("FSG: Source buffer out of section bounds\n");
1668
 
            break;
1669
 
        }
1670
 
 
1671
 
        if(newedi != exe_sections[i].rva) {
1672
 
            cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
1673
 
            break;
1674
 
        }
1675
 
 
1676
 
        /* Counting original sections */
1677
 
        for(t = 12; t < gp - 4; t += 4) {
1678
 
            uint32_t rva = cli_readint32(support+t);
1679
 
 
1680
 
            if(!rva)
1681
 
                break;
1682
 
 
1683
 
            rva -= EC32(optional_hdr32.ImageBase)+1;
1684
 
            sectcnt++;
1685
 
 
1686
 
            if(rva % 0x1000) cli_dbgmsg("FSG: Original section %d is misaligned\n", sectcnt);
1687
 
 
1688
 
            if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) {
1689
 
                cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
1690
 
                break;
1691
 
            }
1692
 
        }
1693
 
 
1694
 
        if(t >= gp - 4 || cli_readint32(support + t)) {
1695
 
            break;
1696
 
        }
1697
 
 
1698
 
        if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
1699
 
            free(exe_sections);
1700
 
            return CL_EMEM;
1701
 
        }
1702
 
 
1703
 
        sections[0].rva = newedi;
1704
 
        for(t = 1; t <= (uint32_t)sectcnt; t++)
1705
 
            sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase);
1706
 
 
1707
 
        if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1708
 
            cli_dbgmsg("Can't read raw data of section %d\n", i);
1709
 
            free(exe_sections);
1710
 
            free(sections);
1711
 
            return CL_EREAD;
1712
 
        }
1713
 
 
1714
 
        if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1715
 
            free(exe_sections);
1716
 
            free(sections);
1717
 
            return CL_EMEM;
1718
 
        }
1719
 
 
1720
 
        oldep = vep + 161 + 6 + cli_readint32(epbuff+163);
1721
 
        cli_dbgmsg("FSG: found old EP @%x\n", oldep);
1722
 
 
1723
 
        CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
1724
 
        CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
1725
 
        break; /* were done with 1.33 */
1726
 
    }
1727
 
 
1728
 
 
1729
 
    while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\xbb' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) < min && epbuff[5] == '\xbf' && epbuff[10] == '\xbe' && vep >= exe_sections[i + 1].rva && vep - exe_sections[i + 1].rva > exe_sections[i + 1].rva - 0xe0 ) {
1730
 
 
1731
 
        /* FSG support - v. 1.31 */
1732
 
 
1733
 
        int sectcnt = 0;
1734
 
        uint32_t gp, t = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
1735
 
        char *support;
1736
 
        uint32_t newesi = cli_readint32(epbuff+11) - EC32(optional_hdr32.ImageBase);
1737
 
        uint32_t newedi = cli_readint32(epbuff+6) - EC32(optional_hdr32.ImageBase);
1738
 
        uint32_t oldep = vep - exe_sections[i + 1].rva;
1739
 
        struct cli_exe_section *sections;
1740
 
 
1741
 
        ssize = exe_sections[i + 1].rsz;
1742
 
        dsize = exe_sections[i].vsz;
1743
 
 
1744
 
        if(err) {
1745
 
            cli_dbgmsg("FSG: Support data out of padding area\n");
1746
 
            break;
1747
 
        }
1748
 
 
1749
 
        if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].raw) {
1750
 
            cli_dbgmsg("FSG: Source buffer out of section bounds\n");
1751
 
            break;
1752
 
        }
1753
 
 
1754
 
        if(newedi != exe_sections[i].rva) {
1755
 
            cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
1756
 
            break;
1757
 
        }
1758
 
 
1759
 
        CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize));
1760
 
 
1761
 
        if(ssize <= 0x19 || dsize <= ssize) {
1762
 
            cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
1763
 
            free(exe_sections);
1764
 
            return CL_CLEAN;
1765
 
        }
1766
 
 
1767
 
        gp = exe_sections[i + 1].raw - t;
1768
 
 
1769
 
        CLI_UNPSIZELIMITS("FSG", gp)
1770
 
 
1771
 
        if(!(support = fmap_need_off_once(map, t, gp))) {
1772
 
            cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
1773
 
            free(exe_sections);
1774
 
            return CL_EREAD;
1775
 
        }
1776
 
 
1777
 
        /* Counting original sections */
1778
 
        for(t = 0; t < gp - 2; t += 2) {
1779
 
            uint32_t rva = support[t]|(support[t+1]<<8);
1780
 
 
1781
 
            if (rva == 2 || rva == 1)
1782
 
                break;
1783
 
 
1784
 
            rva = ((rva-2)<<12) - EC32(optional_hdr32.ImageBase);
1785
 
            sectcnt++;
1786
 
 
1787
 
            if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) {
1788
 
                cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
1789
 
                break;
1790
 
            }
1791
 
        }
1792
 
 
1793
 
        if(t >= gp-10 || cli_readint32(support + t + 6) != 2) {
1794
 
            break;
1795
 
        }
1796
 
 
1797
 
        if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
1798
 
            free(exe_sections);
1799
 
            return CL_EMEM;
1800
 
        }
1801
 
 
1802
 
        sections[0].rva = newedi;
1803
 
        for(t = 0; t <= (uint32_t)sectcnt - 1; t++) {
1804
 
            sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase);
1805
 
        }
1806
 
 
1807
 
        if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1808
 
            cli_dbgmsg("FSG: Can't read raw data of section %d\n", i);
1809
 
            free(exe_sections);
1810
 
            free(sections);
1811
 
            return CL_EREAD;
1812
 
        }
1813
 
 
1814
 
        if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1815
 
            free(exe_sections);
1816
 
            free(sections);
1817
 
            return CL_EMEM;
1818
 
        }
1819
 
 
1820
 
        gp = 0xda + 6*(epbuff[16]=='\xe8');
1821
 
        oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep);
1822
 
        cli_dbgmsg("FSG: found old EP @%x\n", oldep);
1823
 
 
1824
 
        CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
1825
 
        CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
1826
 
        break; /* were done with 1.31 */
1827
 
    }
1828
 
 
1829
 
 
1830
 
    if(found && (DCONF & PE_CONF_UPX)) {
1831
 
 
1832
 
        /* UPX support */
1833
 
 
1834
 
        /* we assume (i + 1) is UPX1 */
1835
 
        ssize = exe_sections[i + 1].rsz;
1836
 
        dsize = exe_sections[i].vsz + exe_sections[i + 1].vsz;
1837
 
 
1838
 
        CLI_UNPSIZELIMITS("UPX", MAX(dsize, ssize));
1839
 
 
1840
 
        if(ssize <= 0x19 || dsize <= ssize || dsize > CLI_MAX_ALLOCATION ) {
1841
 
            cli_dbgmsg("UPX: Size mismatch or dsize too big (ssize: %d, dsize: %d)\n", ssize, dsize);
1842
 
            free(exe_sections);
1843
 
            return CL_CLEAN;
1844
 
        }
1845
 
 
1846
 
        if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
1847
 
            cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
1848
 
            free(exe_sections);
1849
 
            return CL_EREAD;
1850
 
        }
1851
 
 
1852
 
        if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) {
1853
 
            free(exe_sections);
1854
 
            return CL_EMEM;
1855
 
        }
1856
 
 
1857
 
        /* try to detect UPX code */
1858
 
        if(cli_memstr(UPX_NRV2B, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, epbuff + 0x69 + 8, 13)) {
1859
 
            cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
1860
 
            upxfn = upx_inflate2b;
1861
 
        } else if(cli_memstr(UPX_NRV2D, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2D, 24, epbuff + 0x69 + 8, 13)) {
1862
 
            cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n");
1863
 
            upxfn = upx_inflate2d;
1864
 
        } else if(cli_memstr(UPX_NRV2E, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2E, 24, epbuff + 0x69 + 8, 13)) {
1865
 
            cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n");
1866
 
            upxfn = upx_inflate2e;
1867
 
        }
1868
 
 
1869
 
        if(upxfn) {
1870
 
            int skew = cli_readint32(epbuff + 2) - EC32(optional_hdr32.ImageBase) - exe_sections[i + 1].rva;
1871
 
 
1872
 
            if(epbuff[1] != '\xbe' || skew <= 0 || skew > 0xfff) { /* FIXME: legit skews?? */
1873
 
                skew = 0; 
1874
 
                if(upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0)
1875
 
                    upx_success = 1;
1876
 
 
1877
 
            } else {
1878
 
                cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew);
1879
 
                if(upxfn(src + skew, ssize - skew, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep-skew) >= 0 || upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0)
1880
 
                    upx_success = 1;
1881
 
            }
1882
 
 
1883
 
            if(upx_success)
1884
 
                cli_dbgmsg("UPX: Successfully decompressed\n");
1885
 
            else
1886
 
                cli_dbgmsg("UPX: Preferred decompressor failed\n");
1887
 
        }
1888
 
 
1889
 
        if(!upx_success && upxfn != upx_inflate2b) {
1890
 
            if(upx_inflate2b(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2b(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) {
1891
 
 
1892
 
                cli_dbgmsg("UPX: NRV2B decompressor failed\n");
1893
 
            } else {
1894
 
                upx_success = 1;
1895
 
                cli_dbgmsg("UPX: Successfully decompressed with NRV2B\n");
1896
 
            }
1897
 
        }
1898
 
 
1899
 
        if(!upx_success && upxfn != upx_inflate2d) {
1900
 
            if(upx_inflate2d(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2d(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) {
1901
 
 
1902
 
                cli_dbgmsg("UPX: NRV2D decompressor failed\n");
1903
 
            } else {
1904
 
                upx_success = 1;
1905
 
                cli_dbgmsg("UPX: Successfully decompressed with NRV2D\n");
1906
 
            }
1907
 
        }
1908
 
 
1909
 
        if(!upx_success && upxfn != upx_inflate2e) {
1910
 
            if(upx_inflate2e(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2e(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) {
1911
 
                cli_dbgmsg("UPX: NRV2E decompressor failed\n");
1912
 
            } else {
1913
 
                upx_success = 1;
1914
 
                cli_dbgmsg("UPX: Successfully decompressed with NRV2E\n");
1915
 
            }
1916
 
        }
1917
 
 
1918
 
        if(cli_memstr(UPX_LZMA2, 20, epbuff + 0x2f, 20)) {
1919
 
            uint32_t strictdsize=cli_readint32(epbuff+0x21), skew = 0;
1920
 
            if(ssize > 0x15 && epbuff[0] == '\x60' && epbuff[1] == '\xbe') {
1921
 
                skew = cli_readint32(epbuff+2) - exe_sections[i + 1].rva - optional_hdr32.ImageBase;
1922
 
                if(skew!=0x15) skew = 0;
1923
 
            }
1924
 
            if(strictdsize<=dsize)
1925
 
                upx_success = upx_inflatelzma(src+skew, ssize-skew, dest, &strictdsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >=0;
1926
 
        } else if (cli_memstr(UPX_LZMA1, 20, epbuff + 0x39, 20)) {
1927
 
            uint32_t strictdsize=cli_readint32(epbuff+0x2b), skew = 0;
1928
 
            if(ssize > 0x15 && epbuff[0] == '\x60' && epbuff[1] == '\xbe') {
1929
 
                skew = cli_readint32(epbuff+2) - exe_sections[i + 1].rva - optional_hdr32.ImageBase;
1930
 
                if(skew!=0x15) skew = 0;
1931
 
            }
1932
 
            if(strictdsize<=dsize)
1933
 
                upx_success = upx_inflatelzma(src+skew, ssize-skew, dest, &strictdsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >=0;
1934
 
        }
1935
 
 
1936
 
        if(!upx_success) {
1937
 
            cli_dbgmsg("UPX: All decompressors failed\n");
1938
 
            free(dest);
1939
 
        }
1940
 
    }
1941
 
 
1942
 
    if(upx_success) {
1943
 
        free(exe_sections);
1944
 
 
1945
 
        CLI_UNPTEMP("UPX/FSG",(dest,0));
1946
 
 
1947
 
        if((unsigned int) write(ndesc, dest, dsize) != dsize) {
1948
 
            cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize);
1949
 
            free(tempfile);
1950
 
            free(dest);
1951
 
            close(ndesc);
1952
 
            return CL_EWRITE;
1953
 
        }
1954
 
 
1955
 
        free(dest);
1956
 
        lseek(ndesc, 0, SEEK_SET);
1957
 
 
1958
 
        if(ctx->engine->keeptmp)
1959
 
            cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile);
1960
 
 
1961
 
        cli_dbgmsg("***** Scanning decompressed file *****\n");
1962
 
        SHA_OFF;
1963
 
        if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS) {
1964
 
            close(ndesc);
1965
 
            CLI_TMPUNLK();
1966
 
            free(tempfile);
1967
 
            SHA_RESET;
1968
 
            return CL_VIRUS;
1969
 
        }
1970
 
 
1971
 
        SHA_RESET;
1972
 
        close(ndesc);
1973
 
        CLI_TMPUNLK();
1974
 
        free(tempfile);
1975
 
        return ret;
1976
 
    }
1977
 
 
 
2194
            free(section_hdr);
 
2195
            free(exe_sections);
 
2196
 
 
2197
            if(!(tempfile = cli_gentemp(NULL))) {
 
2198
                free(dest);
 
2199
                return CL_EMEM;
 
2200
            }
 
2201
 
 
2202
            if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
2203
                cli_dbgmsg("UPX/FSG: Can't create file %s\n", tempfile);
 
2204
                free(tempfile);
 
2205
                free(dest);
 
2206
                return CL_EIO;
 
2207
            }
 
2208
 
 
2209
            if((unsigned int) write(ndesc, dest, dsize) != dsize) {
 
2210
                cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize);
 
2211
                free(tempfile);
 
2212
                free(dest);
 
2213
                close(ndesc);
 
2214
                return CL_EIO;
 
2215
            }
 
2216
 
 
2217
            free(dest);
 
2218
            fsync(ndesc);
 
2219
            lseek(ndesc, 0, SEEK_SET);
 
2220
 
 
2221
            if(cli_leavetemps_flag)
 
2222
                cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile);
 
2223
 
 
2224
            cli_dbgmsg("***** Scanning decompressed file *****\n");
 
2225
            if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS) {
 
2226
                close(ndesc);
 
2227
                if(!cli_leavetemps_flag)
 
2228
                    unlink(tempfile);
 
2229
                free(tempfile);
 
2230
                return CL_VIRUS;
 
2231
            }
 
2232
 
 
2233
            close(ndesc);
 
2234
            if(!cli_leavetemps_flag)
 
2235
                unlink(tempfile);
 
2236
            free(tempfile);
 
2237
            return ret;
 
2238
        }
 
2239
    }
1978
2240
 
1979
2241
    /* Petite */
1980
2242
 
1981
 
    if(epsize<200) {
1982
 
        free(exe_sections);
1983
 
        return CL_CLEAN;
1984
 
    }
1985
 
 
1986
2243
    found = 2;
1987
2244
 
1988
 
    if(epbuff[0] != '\xb8' || (uint32_t) cli_readint32(epbuff + 1) != exe_sections[nsections - 1].rva + EC32(optional_hdr32.ImageBase)) {
1989
 
        if(nsections < 2 || epbuff[0] != '\xb8' || (uint32_t) cli_readint32(epbuff + 1) != exe_sections[nsections - 2].rva + EC32(optional_hdr32.ImageBase))
 
2245
    lseek(desc, ep, SEEK_SET);
 
2246
    memset(buff, 0, sizeof(buff));
 
2247
    if(cli_readn(desc, buff, 200) == -1) {
 
2248
        cli_dbgmsg("cli_readn() failed\n");
 
2249
        free(section_hdr);
 
2250
        free(exe_sections);
 
2251
        return CL_EIO;
 
2252
    }
 
2253
 
 
2254
    if(buff[0] != '\xb8' || (uint32_t) cli_readint32(buff + 1) != EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(optional_hdr32.ImageBase)) {
 
2255
        if(nsections < 2 || buff[0] != '\xb8' || (uint32_t) cli_readint32(buff + 1) != EC32(section_hdr[nsections - 2].VirtualAddress) + EC32(optional_hdr32.ImageBase))
1990
2256
            found = 0;
1991
2257
        else
1992
2258
            found = 1;
1993
2259
    }
1994
2260
 
1995
 
    if(found && (DCONF & PE_CONF_PETITE)) {
 
2261
    if((DCONF & PE_CONF_PETITE) && found) {
1996
2262
        cli_dbgmsg("Petite: v2.%d compression detected\n", found);
1997
2263
 
1998
 
        if(cli_readint32(epbuff + 0x80) == 0x163c988d) {
 
2264
        if(cli_readint32(buff + 0x80) == 0x163c988d) {
1999
2265
            cli_dbgmsg("Petite: level zero compression is not supported yet\n");
2000
2266
        } else {
2001
2267
            dsize = max - min;
2002
2268
 
2003
 
            CLI_UNPSIZELIMITS("Petite", dsize);
 
2269
            if(ctx->limits && ctx->limits->maxfilesize && dsize > ctx->limits->maxfilesize) {
 
2270
                cli_dbgmsg("Petite: Size exceeded (dsize: %u, max: %lu)\n", dsize, ctx->limits->maxfilesize);
 
2271
                free(section_hdr);
 
2272
                free(exe_sections);
 
2273
                if(BLOCKMAX) {
 
2274
                    *ctx->virname = "PE.Petite.ExceededFileSize";
 
2275
                    return CL_VIRUS;
 
2276
                } else {
 
2277
                    return CL_CLEAN;
 
2278
                }
 
2279
            }
2004
2280
 
2005
2281
            if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
2006
2282
                cli_dbgmsg("Petite: Can't allocate %d bytes\n", dsize);
 
2283
                free(section_hdr);
2007
2284
                free(exe_sections);
2008
2285
                return CL_EMEM;
2009
2286
            }
2010
2287
 
2011
2288
            for(i = 0 ; i < nsections; i++) {
2012
 
                if(exe_sections[i].raw) {
2013
 
                    if(!exe_sections[i].rsz || fmap_readn(map, dest + exe_sections[i].rva - min, exe_sections[i].raw, exe_sections[i].ursz) != exe_sections[i].ursz) {
 
2289
                if(section_hdr[i].SizeOfRawData) {
 
2290
                  uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), exe_sections, nsections, &err, fsize);
 
2291
 
 
2292
                    if(err || lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + EC32(section_hdr[i].VirtualAddress) - min, EC32(section_hdr[i].SizeOfRawData)) != EC32(section_hdr[i].SizeOfRawData)) {
 
2293
                        free(section_hdr);
2014
2294
                        free(exe_sections);
2015
2295
                        free(dest);
2016
 
                        return CL_CLEAN;
2017
 
                    }
2018
 
                }
2019
 
            }
2020
 
 
2021
 
            CLI_UNPTEMP("Petite",(dest,exe_sections,0));
2022
 
            CLI_UNPRESULTS("Petite",(petite_inflate2x_1to9(dest, min, max - min, exe_sections, nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase),vep, ndesc, found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress),EC32(optional_hdr32.DataDirectory[2].Size))),0,(dest,0));
 
2296
                        return CL_EIO;
 
2297
                    }
 
2298
                }
 
2299
            }
 
2300
 
 
2301
            if(!(tempfile = cli_gentemp(NULL))) {
 
2302
              free(dest);
 
2303
              free(section_hdr);
 
2304
              free(exe_sections);
 
2305
              return CL_EMEM;
 
2306
            }
 
2307
 
 
2308
            if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
2309
                cli_dbgmsg("Petite: Can't create file %s\n", tempfile);
 
2310
                free(tempfile);
 
2311
                free(section_hdr);
 
2312
                free(exe_sections);
 
2313
                free(dest);
 
2314
                return CL_EIO;
 
2315
            }
 
2316
 
 
2317
            /* aCaB: Fixed to allow petite v2.1 unpacking (last section is a ghost) */
 
2318
            if (!petite_inflate2x_1to9(dest, min, max - min, section_hdr,
 
2319
                    nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase),
 
2320
                    vep, ndesc, found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress),
 
2321
                    EC32(optional_hdr32.DataDirectory[2].Size))) {
 
2322
                cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
2323
                cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
 
2324
                free(dest);
 
2325
                fsync(ndesc);
 
2326
                lseek(ndesc, 0, SEEK_SET);
 
2327
                if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
2328
                    free(section_hdr);
 
2329
                    free(exe_sections);
 
2330
                    close(ndesc);
 
2331
                    if(!cli_leavetemps_flag) {
 
2332
                        unlink(tempfile);
 
2333
                    }
 
2334
                    free(tempfile);
 
2335
                    return CL_VIRUS;
 
2336
                }
 
2337
 
 
2338
            } else {
 
2339
                cli_dbgmsg("Petite: Unpacking failed\n");
 
2340
                free(dest);
 
2341
            }
 
2342
            close(ndesc);
 
2343
            if(!cli_leavetemps_flag) {
 
2344
                unlink(tempfile);
 
2345
            }
 
2346
            free(tempfile);
2023
2347
        }
2024
2348
    }
2025
2349
 
2026
2350
    /* PESpin 1.1 */
2027
2351
 
2028
2352
    if((DCONF & PE_CONF_PESPIN) && nsections > 1 &&
2029
 
       vep >= exe_sections[nsections - 1].rva &&
2030
 
       vep < exe_sections[nsections - 1].rva + exe_sections[nsections - 1].rsz - 0x3217 - 4 &&
2031
 
       memcmp(epbuff+4, "\xe8\x00\x00\x00\x00\x8b\x1c\x24\x83\xc3", 10) == 0)  {
2032
 
 
2033
 
        char *spinned;
2034
 
 
2035
 
        CLI_UNPSIZELIMITS("PEspin", fsize);
 
2353
       vep >= EC32(section_hdr[nsections - 1].VirtualAddress) &&
 
2354
       vep < EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(section_hdr[nsections - 1].SizeOfRawData) - 0x3217 - 4 &&
 
2355
       memcmp(buff+4, "\xe8\x00\x00\x00\x00\x8b\x1c\x24\x83\xc3", 10) == 0)  {
 
2356
 
 
2357
            char *spinned;
 
2358
 
 
2359
        if(ctx->limits && ctx->limits->maxfilesize && fsize > ctx->limits->maxfilesize) {
 
2360
            cli_dbgmsg("PEspin: Size exceeded (fsize: %u, max: %lu)\n", fsize, ctx->limits->maxfilesize);
 
2361
            free(section_hdr);
 
2362
            free(exe_sections);
 
2363
            if(BLOCKMAX) {
 
2364
                *ctx->virname = "PE.Pespin.ExceededFileSize";
 
2365
                return CL_VIRUS;
 
2366
            } else {
 
2367
                return CL_CLEAN;
 
2368
            }
 
2369
        }
2036
2370
 
2037
2371
        if((spinned = (char *) cli_malloc(fsize)) == NULL) {
 
2372
            free(section_hdr);
2038
2373
            free(exe_sections);
2039
2374
            return CL_EMEM;
2040
2375
        }
2041
2376
 
2042
 
        if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
2043
 
            cli_dbgmsg("PESpin: Can't read %lu bytes\n", (unsigned long)fsize);
2044
 
            free(spinned);
2045
 
            free(exe_sections);
2046
 
            return CL_EREAD;
2047
 
        }
2048
 
 
2049
 
        CLI_UNPTEMP("PESpin",(spinned,exe_sections,0));
2050
 
        CLI_UNPRESULTS_("PEspin",SPINCASE(),(unspin(spinned, fsize, exe_sections, nsections - 1, vep, ndesc, ctx)),0,(spinned,0));
 
2377
        lseek(desc, 0, SEEK_SET);
 
2378
        if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
 
2379
            cli_dbgmsg("PESpin: Can't read %d bytes\n", fsize);
 
2380
            free(spinned);
 
2381
            free(section_hdr);
 
2382
            free(exe_sections);
 
2383
            return CL_EIO;
 
2384
        }
 
2385
 
 
2386
        if(!(tempfile = cli_gentemp(NULL))) {
 
2387
          free(spinned);
 
2388
          free(section_hdr);
 
2389
          free(exe_sections);
 
2390
          return CL_EMEM;
 
2391
        }
 
2392
 
 
2393
        if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
2394
            cli_dbgmsg("PESpin: Can't create file %s\n", tempfile);
 
2395
            free(tempfile);
 
2396
            free(spinned);
 
2397
            free(section_hdr);
 
2398
            free(exe_sections);
 
2399
            return CL_EIO;
 
2400
        }
 
2401
 
 
2402
        switch(unspin(spinned, fsize, section_hdr, nsections - 1, vep, ndesc, ctx)) {
 
2403
        case 0:
 
2404
            free(spinned);
 
2405
            if(cli_leavetemps_flag)
 
2406
                cli_dbgmsg("PESpin: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
2407
            else
 
2408
                cli_dbgmsg("PESpin: Unpacked and rebuilt executable\n");
 
2409
            fsync(ndesc);
 
2410
            lseek(ndesc, 0, SEEK_SET);
 
2411
            if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
2412
                close(ndesc);
 
2413
                if(!cli_leavetemps_flag)
 
2414
                    unlink(tempfile);
 
2415
                free(tempfile);
 
2416
                free(section_hdr);
 
2417
                free(exe_sections);
 
2418
                return CL_VIRUS;
 
2419
            }
 
2420
            close(ndesc);
 
2421
            if(!cli_leavetemps_flag)
 
2422
                unlink(tempfile);
 
2423
            break;
 
2424
        case 1:
 
2425
            free(spinned);
 
2426
            close(ndesc);
 
2427
            unlink(tempfile);
 
2428
            cli_dbgmsg("PESpin: Rebuilding failed\n");
 
2429
            break;
 
2430
        case 2:
 
2431
            free(spinned);
 
2432
            close(ndesc);
 
2433
            unlink(tempfile);
 
2434
            cli_dbgmsg("PESpin: Size exceeded\n");
 
2435
            if(BLOCKMAX) {
 
2436
                free(tempfile);
 
2437
                free(section_hdr);
 
2438
                free(exe_sections);
 
2439
                *ctx->virname = "PE.Pespin.ExceededFileSize";
 
2440
                return CL_VIRUS;
 
2441
            }
 
2442
        }
 
2443
        free(tempfile);
 
2444
        
2051
2445
    }
2052
2446
 
2053
2447
 
2054
 
    /* yC 1.3 & variants */
 
2448
    /* yC 1.3 */
 
2449
 
2055
2450
    if((DCONF & PE_CONF_YC) && nsections > 1 &&
2056
 
       (EC32(optional_hdr32.AddressOfEntryPoint) == exe_sections[nsections - 1].rva + 0x60)) {
2057
 
 
2058
 
        uint32_t ecx = 0;
2059
 
        int16_t offset;
2060
 
 
2061
 
        /* yC 1.3 */
2062
 
        if (!memcmp(epbuff, "\x55\x8B\xEC\x53\x56\x57\x60\xE8\x00\x00\x00\x00\x5D\x81\xED", 15) &&
2063
 
            !memcmp(epbuff+0x26, "\x8D\x3A\x8B\xF7\x33\xC0\xEB\x04\x90\xEB\x01\xC2\xAC", 13) &&
2064
 
            ((uint8_t)epbuff[0x13] == 0xB9) &&
2065
 
            ((uint16_t)(cli_readint16(epbuff+0x18)) == 0xE981) &&
2066
 
            !memcmp(epbuff+0x1e,"\x8B\xD5\x81\xC2", 4)) {
2067
 
 
2068
 
            offset = 0;
2069
 
            if (0x6c - cli_readint32(epbuff+0xf) + cli_readint32(epbuff+0x22) == 0xC6)
2070
 
                ecx = cli_readint32(epbuff+0x14) - cli_readint32(epbuff+0x1a);
2071
 
        }
2072
 
 
2073
 
        /* yC 1.3 variant */
2074
 
        if (!ecx && !memcmp(epbuff, "\x55\x8B\xEC\x83\xEC\x40\x53\x56\x57", 9) &&
2075
 
            !memcmp(epbuff+0x17, "\xe8\x00\x00\x00\x00\x5d\x81\xed", 8) &&
2076
 
            ((uint8_t)epbuff[0x23] == 0xB9)) {
2077
 
 
2078
 
            offset = 0x10;
2079
 
            if (0x6c - cli_readint32(epbuff+0x1f) + cli_readint32(epbuff+0x32) == 0xC6)
2080
 
                ecx = cli_readint32(epbuff+0x24) - cli_readint32(epbuff+0x2a);
2081
 
        }
2082
 
 
2083
 
        /* yC 1.x/modified */
2084
 
        if (!ecx && !memcmp(epbuff, "\x60\xe8\x00\x00\x00\x00\x5d\x81\xed",9) &&
2085
 
            ((uint8_t)epbuff[0xd] == 0xb9) &&
2086
 
            ((uint16_t)cli_readint16(epbuff + 0x12)== 0xbd8d) &&
2087
 
            !memcmp(epbuff+0x18, "\x8b\xf7\xac", 3)) {
2088
 
 
2089
 
            offset = -0x18;
2090
 
            if (0x66 - cli_readint32(epbuff+0x9) + cli_readint32(epbuff+0x14) == 0xae)
2091
 
                ecx = cli_readint32(epbuff+0xe);
2092
 
        }
2093
 
 
2094
 
        if (ecx > 0x800 && ecx < 0x2000 &&
2095
 
            !memcmp(epbuff+0x63+offset, "\xaa\xe2\xcc", 3) &&
2096
 
            (fsize >= exe_sections[nsections-1].raw + 0xC6 + ecx + offset)) {
2097
 
 
2098
 
        char *spinned;
2099
 
 
2100
 
        if((spinned = (char *) cli_malloc(fsize)) == NULL) {
2101
 
            free(exe_sections);
2102
 
            return CL_EMEM;
2103
 
        }
2104
 
 
2105
 
        if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
2106
 
            cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize);
2107
 
            free(spinned);
2108
 
            free(exe_sections);
2109
 
            return CL_EREAD;
2110
 
        }
2111
 
 
2112
 
        cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset);
2113
 
        CLI_UNPTEMP("yC",(spinned,exe_sections,0));
2114
 
        CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0));
 
2451
       EC32(optional_hdr32.AddressOfEntryPoint) == EC32(section_hdr[nsections - 1].VirtualAddress) + 0x60 &&
 
2452
       memcmp(buff, "\x55\x8B\xEC\x53\x56\x57\x60\xE8\x00\x00\x00\x00\x5D\x81\xED\x6C\x28\x40\x00\xB9\x5D\x34\x40\x00\x81\xE9\xC6\x28\x40\x00\x8B\xD5\x81\xC2\xC6\x28\x40\x00\x8D\x3A\x8B\xF7\x33\xC0\xEB\x04\x90\xEB\x01\xC2\xAC", 51) == 0)  {
 
2453
 
 
2454
            char *spinned;
 
2455
 
 
2456
        if ( fsize >= EC32(section_hdr[nsections - 1].PointerToRawData) + 0xC6 + 0xb97 ) { /* size check on yC sect */
 
2457
          if((spinned = (char *) cli_malloc(fsize)) == NULL) {
 
2458
            free(section_hdr);
 
2459
            free(exe_sections);
 
2460
            return CL_EMEM;
 
2461
          }
 
2462
 
 
2463
          lseek(desc, 0, SEEK_SET);
 
2464
          if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
 
2465
            cli_dbgmsg("yC: Can't read %d bytes\n", fsize);
 
2466
            free(spinned);
 
2467
            free(section_hdr);
 
2468
            free(exe_sections);
 
2469
            return CL_EIO;
 
2470
          }
 
2471
 
 
2472
          if(!(tempfile = cli_gentemp(NULL))) {
 
2473
            free(spinned);
 
2474
            free(section_hdr);
 
2475
            free(exe_sections);
 
2476
            return CL_EMEM;
 
2477
          }
 
2478
 
 
2479
          if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
2480
            cli_dbgmsg("yC: Can't create file %s\n", tempfile);
 
2481
            free(tempfile);
 
2482
            free(spinned);
 
2483
            free(section_hdr);
 
2484
            free(exe_sections);
 
2485
            return CL_EIO;
 
2486
          }
 
2487
 
 
2488
          if(!yc_decrypt(spinned, fsize, section_hdr, nsections-1, e_lfanew, ndesc)) {
 
2489
            free(spinned);
 
2490
            cli_dbgmsg("yC: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
2491
            fsync(ndesc);
 
2492
            lseek(ndesc, 0, SEEK_SET);
 
2493
            
 
2494
            if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
2495
              free(section_hdr);
 
2496
              free(exe_sections);
 
2497
              close(ndesc);
 
2498
              if(!cli_leavetemps_flag) {
 
2499
                unlink(tempfile);
 
2500
                free(tempfile);
 
2501
              } else {
 
2502
                free(tempfile);
 
2503
              }
 
2504
              return CL_VIRUS;
 
2505
            }
 
2506
            
 
2507
          } else {
 
2508
            free(spinned);
 
2509
            cli_dbgmsg("yC: Rebuilding failed\n");
 
2510
          }
 
2511
          
 
2512
          close(ndesc);
 
2513
          if(!cli_leavetemps_flag) {
 
2514
            unlink(tempfile);
 
2515
            free(tempfile);
 
2516
          } else {
 
2517
            free(tempfile);
 
2518
          }
 
2519
 
2115
2520
        }
2116
2521
    }
2117
2522
 
 
2523
 
2118
2524
    /* WWPack */
2119
2525
 
2120
 
    while ((DCONF & PE_CONF_WWPACK) && nsections > 1 &&
 
2526
    if((DCONF & PE_CONF_WWPACK) && nsections > 1 &&
 
2527
       exe_sections[nsections-1].raw>0x2b1 &&
2121
2528
       vep == exe_sections[nsections - 1].rva &&
2122
 
       memcmp(epbuff, "\x53\x55\x8b\xe8\x33\xdb\xeb", 7) == 0 &&
2123
 
       memcmp(epbuff+0x68, "\xe8\x00\x00\x00\x00\x58\x2d\x6d\x00\x00\x00\x50\x60\x33\xc9\x50\x58\x50\x50", 19) == 0)  {
2124
 
        uint32_t head = exe_sections[nsections - 1].raw;
2125
 
        uint8_t *packer;
2126
 
 
2127
 
        ssize = 0;
2128
 
        for(i=0 ; ; i++) {
2129
 
            if(exe_sections[i].raw<head)
2130
 
                head=exe_sections[i].raw;
2131
 
            if(i+1==nsections) break;
2132
 
            if(ssize<exe_sections[i].rva+exe_sections[i].vsz)
2133
 
                ssize=exe_sections[i].rva+exe_sections[i].vsz;
2134
 
        }
2135
 
        if(!head || !ssize || head>ssize) break;
2136
 
 
2137
 
        CLI_UNPSIZELIMITS("WWPack", ssize);
2138
 
 
2139
 
        if(!(src=(char *)cli_calloc(ssize, sizeof(char)))) {
2140
 
            free(exe_sections);
2141
 
            return CL_EMEM;
2142
 
        }
2143
 
        if((size_t) fmap_readn(map, src, 0, head) != head) {
2144
 
            cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", head);
2145
 
            free(src);
2146
 
            free(exe_sections);
2147
 
            return CL_EREAD;
2148
 
        }
2149
 
        for(i = 0 ; i < (unsigned int)nsections-1; i++) {
2150
 
            if(!exe_sections[i].rsz) continue;
2151
 
            if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
2152
 
            if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2153
 
        }
2154
 
        if(i+1!=nsections) {
2155
 
            cli_dbgmsg("WWpack: Probably hacked/damaged file.\n");
2156
 
            free(src);
2157
 
            break;
2158
 
        }
2159
 
        if((packer = (uint8_t *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) {
2160
 
            free(src);
2161
 
            free(exe_sections);
2162
 
            return CL_EMEM;
2163
 
        }
2164
 
        if(!exe_sections[nsections - 1].rsz || (size_t) fmap_readn(map, packer, exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
2165
 
            cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz);
2166
 
            free(src);
2167
 
            free(packer);
2168
 
            free(exe_sections);
2169
 
            return CL_EREAD;
2170
 
        }
2171
 
 
2172
 
        CLI_UNPTEMP("WWPack",(src,packer,exe_sections,0));
2173
 
        CLI_UNPRESULTS("WWPack",(wwunpack((uint8_t *)src, ssize, packer, exe_sections, nsections-1, e_lfanew, ndesc)),0,(src,packer,0));
2174
 
        break;
2175
 
    }
2176
 
 
2177
 
 
2178
 
    /* ASPACK support */
2179
 
    while((DCONF & PE_CONF_ASPACK) && ep+58+0x70e < fsize && !memcmp(epbuff,"\x60\xe8\x03\x00\x00\x00\xe9\xeb",8)) {
2180
 
 
2181
 
        if(epsize<0x3bf || memcmp(epbuff+0x3b9, "\x68\x00\x00\x00\x00\xc3",6)) break;
2182
 
        ssize = 0;
2183
 
        for(i=0 ; i< nsections ; i++)
2184
 
            if(ssize<exe_sections[i].rva+exe_sections[i].vsz)
2185
 
                ssize=exe_sections[i].rva+exe_sections[i].vsz;
2186
 
        if(!ssize) break;
2187
 
 
2188
 
        CLI_UNPSIZELIMITS("Aspack", ssize);
2189
 
 
2190
 
        if(!(src=(char *)cli_calloc(ssize, sizeof(char)))) {
2191
 
            free(exe_sections);
2192
 
            return CL_EMEM;
2193
 
        }
2194
 
        for(i = 0 ; i < (unsigned int)nsections; i++) {
2195
 
            if(!exe_sections[i].rsz) continue;
2196
 
            if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
2197
 
            if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
2198
 
        }
2199
 
        if(i!=nsections) {
2200
 
            cli_dbgmsg("Aspack: Probably hacked/damaged Aspack file.\n");
2201
 
            free(src);
2202
 
            break;
2203
 
        }
2204
 
 
2205
 
        CLI_UNPTEMP("Aspack",(src,exe_sections,0));
2206
 
        CLI_UNPRESULTS("Aspack",(unaspack212((uint8_t *)src, ssize, exe_sections, nsections, vep-1, EC32(optional_hdr32.ImageBase), ndesc)),1,(src,0));
2207
 
        break;
 
2529
       exe_sections[nsections - 1].rva + exe_sections[nsections - 1].rsz == max &&
 
2530
       memcmp(buff, "\x53\x55\x8b\xe8\x33\xdb\xeb", 7) == 0 &&
 
2531
       memcmp(buff+0x68, "\xe8\x00\x00\x00\x00\x58\x2d\x6d\x00\x00\x00\x50\x60\x33\xc9\x50\x58\x50\x50", 19) == 0)  {
 
2532
      uint32_t headsize=exe_sections[nsections - 1].raw;
 
2533
      char *dest, *wwp;
 
2534
 
 
2535
      for(i = 0 ; i < (unsigned int)nsections-1; i++)
 
2536
        if (!err && exe_sections[i].raw<headsize) headsize=exe_sections[i].raw;
 
2537
      
 
2538
      dsize = max-min+headsize-exe_sections[nsections - 1].rsz;
 
2539
 
 
2540
      if(ctx->limits && ctx->limits->maxfilesize && dsize > ctx->limits->maxfilesize) {
 
2541
        cli_dbgmsg("WWPack: Size exceeded (dsize: %u, max: %lu)\n", dsize, ctx->limits->maxfilesize);
 
2542
        free(section_hdr);
 
2543
        free(exe_sections);
 
2544
        if(BLOCKMAX) {
 
2545
          *ctx->virname = "PE.WWPack.ExceededFileSize";
 
2546
          return CL_VIRUS;
 
2547
        } else {
 
2548
          return CL_CLEAN;
 
2549
        }
 
2550
      }
 
2551
 
 
2552
      if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
 
2553
        cli_dbgmsg("WWPack: Can't allocate %d bytes\n", dsize);
 
2554
        free(section_hdr);
 
2555
        free(exe_sections);
 
2556
        return CL_EMEM;
 
2557
      }
 
2558
      memset(dest, 0, dsize);
 
2559
 
 
2560
      lseek(desc, 0, SEEK_SET);
 
2561
      if((size_t) cli_readn(desc, dest, headsize) != headsize) {
 
2562
        cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", headsize);
 
2563
        free(dest);
 
2564
        free(section_hdr);
 
2565
        free(exe_sections);
 
2566
        return CL_EIO;
 
2567
      }
 
2568
 
 
2569
      for(i = 0 ; i < (unsigned int)nsections-1; i++) {
 
2570
        if(exe_sections[i].rsz) {
 
2571
          uint32_t offset = exe_sections[i].raw;
 
2572
          
 
2573
          if(err || lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) {
 
2574
            free(dest);
 
2575
            free(section_hdr);
 
2576
            free(exe_sections);
 
2577
            return CL_EIO;
 
2578
          }
 
2579
        }
 
2580
      }
 
2581
 
 
2582
      if((wwp = (char *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) {
 
2583
        cli_dbgmsg("WWPack: Can't allocate %d bytes\n", exe_sections[nsections - 1].rsz);
 
2584
        free(dest);
 
2585
        free(section_hdr);
 
2586
        free(exe_sections);
 
2587
        return CL_EMEM;
 
2588
      }
 
2589
 
 
2590
      lseek(desc, exe_sections[nsections - 1].raw, SEEK_SET);
 
2591
      if((size_t) cli_readn(desc, wwp, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
 
2592
        cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz);
 
2593
        free(dest);
 
2594
        free(wwp);
 
2595
        free(section_hdr);
 
2596
        free(exe_sections);
 
2597
        return CL_EIO;
 
2598
      }
 
2599
 
 
2600
      if (!wwunpack(dest, dsize, headsize, min, exe_sections[nsections-1].rva, e_lfanew, wwp, exe_sections[nsections - 1].rsz, nsections-1)) {
 
2601
        
 
2602
        free(wwp);
 
2603
 
 
2604
        if(!(tempfile = cli_gentemp(NULL))) {
 
2605
          free(dest);
 
2606
          free(section_hdr);
 
2607
          free(exe_sections);
 
2608
          return CL_EMEM;
 
2609
        }
 
2610
 
 
2611
        if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
2612
          cli_dbgmsg("WWPack: Can't create file %s\n", tempfile);
 
2613
          free(tempfile);
 
2614
          free(dest);
 
2615
          free(section_hdr);
 
2616
          free(exe_sections);
 
2617
          return CL_EIO;
 
2618
        }
 
2619
 
 
2620
        if((unsigned int) write(ndesc, dest, dsize) != dsize) {
 
2621
          cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize);
 
2622
          close(ndesc);
 
2623
          free(tempfile);
 
2624
          free(dest);
 
2625
          free(section_hdr);
 
2626
          free(exe_sections);
 
2627
          return CL_EIO;
 
2628
        }
 
2629
 
 
2630
        free(dest);
 
2631
        if (cli_leavetemps_flag)
 
2632
          cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
2633
        else
 
2634
          cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n");
 
2635
 
 
2636
        fsync(ndesc);
 
2637
        lseek(ndesc, 0, SEEK_SET);
 
2638
 
 
2639
        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
2640
          free(section_hdr);
 
2641
          free(exe_sections);
 
2642
          close(ndesc);
 
2643
          if(!cli_leavetemps_flag)
 
2644
            unlink(tempfile);
 
2645
          free(tempfile);
 
2646
          return CL_VIRUS;
 
2647
        }
 
2648
 
 
2649
        close(ndesc);
 
2650
        if(!cli_leavetemps_flag)
 
2651
          unlink(tempfile);
 
2652
        free(tempfile);
 
2653
      } else {
 
2654
        free(wwp);
 
2655
        free(dest);
 
2656
        cli_dbgmsg("WWPpack: Decompression failed\n");
 
2657
      }
2208
2658
    }
2209
2659
 
2210
2660
    /* NsPack */
2211
2661
 
2212
2662
    while (DCONF & PE_CONF_NSPACK) {
2213
 
        uint32_t eprva = vep;
2214
 
        uint32_t start_of_stuff, ssize, dsize, rep = ep;
2215
 
        unsigned int nowinldr;
2216
 
        char *nbuff;
2217
 
        char *src=epbuff, *dest;
2218
 
 
2219
 
        if (*epbuff=='\xe9') { /* bitched headers */
2220
 
            eprva = cli_readint32(epbuff+1)+vep+5;
2221
 
            if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break;
2222
 
            if (!(nbuff = fmap_need_off_once(map, rep, 24))) break;
2223
 
            src = nbuff;
2224
 
        }
2225
 
 
2226
 
        if (memcmp(src, "\x9c\x60\xe8\x00\x00\x00\x00\x5d\xb8\x07\x00\x00\x00", 13)) break;
2227
 
 
2228
 
        nowinldr = 0x54-cli_readint32(src+17);
2229
 
        cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr);
2230
 
 
2231
 
        if(!(nbuff = fmap_need_off_once(map, rep-nowinldr, 4))) break;
2232
 
        start_of_stuff=rep+cli_readint32(nbuff);
2233
 
        if(!(nbuff = fmap_need_off_once(map, start_of_stuff, 20))) break;
 
2663
      uint32_t eprva = vep;
 
2664
      uint32_t start_of_stuff, ssize, dsize, rep = ep;
 
2665
      unsigned int nowinldr;
 
2666
      char nbuff[24];
 
2667
      char *src=buff, *dest;
 
2668
      FILE *asd;
 
2669
 
 
2670
      if (*buff=='\xe9') { /* bitched headers */
 
2671
        eprva = cli_readint32(buff+1)+vep+5;
 
2672
        if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize)) && err) break;
 
2673
        if (lseek(desc, rep, SEEK_SET)==-1) break;
 
2674
        if (cli_readn(desc, nbuff, 24)!=24) break;
2234
2675
        src = nbuff;
2235
 
        if (!cli_readint32(nbuff)) {
2236
 
            start_of_stuff+=4; /* FIXME: more to do */
2237
 
            src+=4;
2238
 
        }
2239
 
 
2240
 
        ssize = cli_readint32(src+5)|0xff;
2241
 
        dsize = cli_readint32(src+9);
2242
 
 
2243
 
        CLI_UNPSIZELIMITS("NsPack", MAX(ssize,dsize));
2244
 
 
2245
 
        if (!ssize || !dsize || dsize != exe_sections[0].vsz) break;
2246
 
        if (!(dest=cli_malloc(dsize))) break;
2247
 
        /* memset(dest, 0xfc, dsize); */
2248
 
 
2249
 
        if(!(src = fmap_need_off(map, start_of_stuff, ssize))) {
2250
 
            free(dest);
2251
 
            break;
2252
 
        }
2253
 
        /* memset(src, 0x00, ssize); */
2254
 
 
2255
 
        eprva+=0x27a;
2256
 
        if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) {
2257
 
          free(dest);
2258
 
          break;
2259
 
        }
2260
 
        if(!(nbuff = fmap_need_off_once(map, rep, 5))) {
2261
 
          free(dest);
2262
 
          break;
2263
 
        }
2264
 
        fmap_unneed_off(map, start_of_stuff, ssize);
2265
 
        eprva=eprva+5+cli_readint32(nbuff+1);
2266
 
        cli_dbgmsg("NsPack: OEP = %08x\n", eprva);
2267
 
 
2268
 
        CLI_UNPTEMP("NsPack",(dest,exe_sections,0));
2269
 
        CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(dest,0));
 
2676
      }
 
2677
 
 
2678
      if (memcmp(src, "\x9c\x60\xe8\x00\x00\x00\x00\x5d\xb8\x07\x00\x00\x00", 13)) break;
 
2679
 
 
2680
      nowinldr = 0x54-cli_readint32(src+17);
 
2681
      cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr);
 
2682
 
 
2683
      if (lseek(desc, rep-nowinldr, SEEK_SET)==-1) break;
 
2684
      if (cli_readn(desc, nbuff, 4)!=4) break;
 
2685
      start_of_stuff=rep+cli_readint32(nbuff);
 
2686
      if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
 
2687
      if (cli_readn(desc, nbuff, 20)!=20) break;
 
2688
      src = nbuff;
 
2689
      if (!cli_readint32(nbuff)) {
 
2690
        start_of_stuff+=4; /* FIXME: more to do */
 
2691
        src+=4;
 
2692
      }
 
2693
 
 
2694
      ssize = cli_readint32(src+5)|0xff;
 
2695
      dsize = cli_readint32(src+9);
 
2696
 
 
2697
      if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
 
2698
        cli_dbgmsg("NsPack: Size exceeded\n");
 
2699
        free(section_hdr);
 
2700
        free(exe_sections);
 
2701
        if(BLOCKMAX) {
 
2702
          *ctx->virname = "PE.NsPack.ExceededFileSize";
 
2703
          return CL_VIRUS;
 
2704
        } else {
 
2705
          return CL_CLEAN;
 
2706
        }
 
2707
      }
 
2708
 
 
2709
      if ( !ssize || !dsize || dsize != exe_sections[0].vsz) break;
 
2710
      if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
 
2711
      if (!(dest=cli_malloc(dsize))) break;
 
2712
      /* memset(dest, 0xfc, dsize); */
 
2713
 
 
2714
      if (!(src=cli_malloc(ssize))) {
 
2715
        free(dest);
2270
2716
        break;
 
2717
      }
 
2718
      /* memset(src, 0x00, ssize); */
 
2719
      cli_readn(desc, src, ssize);
 
2720
 
 
2721
      eprva+=0x27a;
 
2722
      if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize)) && err) break;
 
2723
      if (lseek(desc, rep, SEEK_SET)==-1) break;
 
2724
      if (cli_readn(desc, nbuff, 5)!=5) break;
 
2725
      eprva=eprva+5+cli_readint32(nbuff+1);
 
2726
      cli_dbgmsg("NsPack: OEP = %08x\n", eprva);
 
2727
 
 
2728
      if(!(tempfile = cli_gentemp(NULL))) {
 
2729
        free(src);
 
2730
        free(dest);
 
2731
        free(section_hdr);
 
2732
        free(exe_sections);
 
2733
        return CL_EMEM;
 
2734
      }
 
2735
 
 
2736
      if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
 
2737
        cli_dbgmsg("NsPack: Can't create file %s\n", tempfile);
 
2738
        free(tempfile);
 
2739
        free(src);
 
2740
        free(dest);
 
2741
        free(section_hdr);
 
2742
        free(exe_sections);
 
2743
        return CL_EIO;
 
2744
      }
 
2745
 
 
2746
      if (!unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)) {
 
2747
        free(src);
 
2748
        free(dest);
 
2749
        if (cli_leavetemps_flag)
 
2750
          cli_dbgmsg("NsPack: Unpacked and rebuilt executable saved in %s\n", tempfile);
 
2751
        else
 
2752
          cli_dbgmsg("NsPack: Unpacked and rebuilt executable\n");
 
2753
        fsync(ndesc);
 
2754
        lseek(ndesc, 0, SEEK_SET);
 
2755
 
 
2756
        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
 
2757
          free(section_hdr);
 
2758
          free(exe_sections);
 
2759
          close(ndesc);
 
2760
          if(!cli_leavetemps_flag) unlink(tempfile);
 
2761
          free(tempfile);
 
2762
          return CL_VIRUS;
 
2763
        }
 
2764
      } else {
 
2765
        free(src);
 
2766
        free(dest);
 
2767
        cli_dbgmsg("NsPack: Unpacking failed\n");
 
2768
      }
 
2769
      close(ndesc);
 
2770
      if(!cli_leavetemps_flag) unlink(tempfile);
 
2771
      free(tempfile);
 
2772
      break;
2271
2773
    }
2272
2774
 
2273
2775
    /* to be continued ... */
2274
2776
 
2275
 
    /* Bytecode BC_PE_UNPACKER hook */
2276
 
    bc_ctx = cli_bytecode_context_alloc();
2277
 
    if (!bc_ctx) {
2278
 
        cli_errmsg("cli_scanpe: can't allocate memory for bc_ctx\n");
2279
 
        return CL_EMEM;
2280
 
    }
2281
 
    cli_bytecode_context_setpe(bc_ctx, &pedata, exe_sections);
2282
 
    cli_bytecode_context_setctx(bc_ctx, ctx);
2283
 
    ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_UNPACKER, map, ctx->virname);
2284
 
    switch (ret) {
2285
 
        case CL_VIRUS:
2286
 
            free(exe_sections);
2287
 
            cli_bytecode_context_destroy(bc_ctx);
2288
 
            return CL_VIRUS;
2289
 
        case CL_SUCCESS:
2290
 
            ndesc = cli_bytecode_context_getresult_file(bc_ctx, &tempfile);
2291
 
            cli_bytecode_context_destroy(bc_ctx);
2292
 
            if (ndesc != -1 && tempfile) {
2293
 
                CLI_UNPRESULTS("bytecode PE hook", 1, 1, (0));
2294
 
            }
2295
 
            break;
2296
 
        default:
2297
 
            cli_bytecode_context_destroy(bc_ctx);
2298
 
    }
2299
 
 
 
2777
    free(section_hdr);
2300
2778
    free(exe_sections);
2301
2779
    return CL_CLEAN;
2302
2780
}
2303
2781
 
2304
 
int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
 
2782
int cli_peheader(int desc, struct cli_exe_info *peinfo)
2305
2783
{
2306
2784
        uint16_t e_magic; /* DOS signature ("MZ") */
2307
2785
        uint32_t e_lfanew; /* address of new exe header */
2314
2792
            struct pe_image_optional_hdr32 opt32;
2315
2793
        } pe_opt;
2316
2794
        struct pe_image_section_hdr *section_hdr;
 
2795
        struct stat sb;
2317
2796
        int i;
2318
2797
        unsigned int err, pe_plus = 0;
2319
 
        uint32_t valign, falign, hdr_size;
 
2798
        uint32_t valign, falign;
2320
2799
        size_t fsize;
2321
 
        ssize_t at;
2322
 
        struct pe_image_data_dir *dirs;
2323
2800
 
2324
2801
    cli_dbgmsg("in cli_peheader\n");
2325
2802
 
2326
 
    fsize = map->len - peinfo->offset;
2327
 
    if(fmap_readn(map, &e_magic, peinfo->offset, sizeof(e_magic)) != sizeof(e_magic)) {
 
2803
    if(fstat(desc, &sb) == -1) {
 
2804
        cli_dbgmsg("fstat failed\n");
 
2805
        return -1;
 
2806
    }
 
2807
 
 
2808
    fsize = sb.st_size;
 
2809
 
 
2810
    if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
2328
2811
        cli_dbgmsg("Can't read DOS signature\n");
2329
 
        return CL_CLEAN;
 
2812
        return -1;
2330
2813
    }
2331
2814
 
2332
 
    if(EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE && EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE_OLD) {
 
2815
    if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
2333
2816
        cli_dbgmsg("Invalid DOS signature\n");
2334
2817
        return -1;
2335
2818
    }
2336
2819
 
2337
 
    if(fmap_readn(map, &e_lfanew, peinfo->offset + 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
 
2820
    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
 
2821
 
 
2822
    if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
 
2823
        cli_dbgmsg("Can't read new header address\n");
2338
2824
        /* truncated header? */
2339
2825
        return -1;
2340
2826
    }
2345
2831
        return -1;
2346
2832
    }
2347
2833
 
2348
 
    if(fmap_readn(map, &file_hdr, peinfo->offset + e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
 
2834
    if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
 
2835
        /* probably not a PE file */
 
2836
        cli_dbgmsg("Can't lseek to e_lfanew\n");
 
2837
        return -1;
 
2838
    }
 
2839
 
 
2840
    if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
2349
2841
        /* bad information in e_lfanew - probably not a PE file */
2350
2842
        cli_dbgmsg("Can't read file header\n");
2351
2843
        return -1;
2352
2844
    }
2353
2845
 
2354
 
    if(EC32(file_hdr.Magic) != PE_IMAGE_NT_SIGNATURE) {
 
2846
    if(EC32(file_hdr.Magic) != IMAGE_NT_SIGNATURE) {
2355
2847
        cli_dbgmsg("Invalid PE signature (probably NE file)\n");
2356
2848
        return -1;
2357
2849
    }
2358
2850
 
2359
 
    if ( (peinfo->nsections = EC16(file_hdr.NumberOfSections)) < 1 || peinfo->nsections > 96 ) return -1;
 
2851
    peinfo->nsections = EC16(file_hdr.NumberOfSections);
2360
2852
 
2361
2853
    if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) {
2362
2854
        cli_dbgmsg("SizeOfOptionalHeader too small\n");
2363
2855
        return -1;
2364
2856
    }
2365
2857
 
2366
 
    at = peinfo->offset + e_lfanew + sizeof(struct pe_image_file_hdr);
2367
 
    if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
 
2858
    if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
2368
2859
        cli_dbgmsg("Can't read optional file header\n");
2369
2860
        return -1;
2370
2861
    }
2371
 
    at += sizeof(struct pe_image_optional_hdr32);
2372
2862
 
2373
 
    if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) { /* PE+ */
 
2863
    if(EC32(optional_hdr64.Magic)==PE32P_SIGNATURE) {
2374
2864
        if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) {
2375
2865
            cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
2376
2866
            return -1;
2377
2867
        }
2378
 
        if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
2379
 
            cli_dbgmsg("Can't read optional file header\n");
2380
 
            return -1;
2381
 
        }
2382
 
        at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
2383
 
        hdr_size = EC32(optional_hdr64.SizeOfHeaders);
2384
 
        pe_plus=1;
2385
 
    } else { /* PE */
 
2868
        pe_plus = 1;
 
2869
    }
 
2870
 
 
2871
    if(!pe_plus) { /* PE */
 
2872
        cli_dbgmsg("File format: PE\n");
2386
2873
        if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
2387
2874
            /* Seek to the end of the long header */
2388
 
            at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
2389
 
        }
2390
 
        hdr_size = EC32(optional_hdr32.SizeOfHeaders);
 
2875
            lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
 
2876
        }
 
2877
 
 
2878
    } else { /* PE+ */
 
2879
        if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
 
2880
            cli_dbgmsg("Can't read optional file header\n");
 
2881
            return -1;
 
2882
        }
 
2883
 
 
2884
        cli_dbgmsg("File format: PE32+\n");
2391
2885
    }
2392
2886
 
2393
2887
    valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment);
2394
2888
    falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment);
2395
2889
 
2396
 
    peinfo->hdr_size = hdr_size = PESALIGN(hdr_size, valign);
2397
 
 
2398
2890
    peinfo->section = (struct cli_exe_section *) cli_calloc(peinfo->nsections, sizeof(struct cli_exe_section));
2399
2891
 
2400
2892
    if(!peinfo->section) {
2411
2903
        return -1;
2412
2904
    }
2413
2905
 
2414
 
    if(fmap_readn(map, section_hdr, at, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
2415
 
        cli_dbgmsg("Can't read section header\n");
2416
 
        cli_dbgmsg("Possibly broken PE file\n");
2417
 
        free(section_hdr);
2418
 
        free(peinfo->section);
2419
 
        peinfo->section = NULL;
2420
 
        return -1;
2421
 
    }
2422
 
    at += sizeof(struct pe_image_section_hdr)*peinfo->nsections;
2423
 
 
2424
 
    for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) {
2425
 
        /* file alignment fallback mode - blah */
2426
 
        if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) {
2427
 
            falign = 0x200;
2428
 
        }
2429
 
    }
2430
 
 
2431
2906
    for(i = 0; i < peinfo->nsections; i++) {
2432
 
        peinfo->section[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign);
 
2907
 
 
2908
        if(cli_readn(desc, &section_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) {
 
2909
            cli_dbgmsg("Can't read section header\n");
 
2910
            cli_dbgmsg("Possibly broken PE file\n");
 
2911
            free(section_hdr);
 
2912
            free(peinfo->section);
 
2913
            peinfo->section = NULL;
 
2914
            return -1;
 
2915
        }
 
2916
 
 
2917
        peinfo->section[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign);
2433
2918
        peinfo->section[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign);
2434
2919
        peinfo->section[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign);
2435
2920
        peinfo->section[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign);
2436
 
 
2437
 
        if (!peinfo->section[i].vsz && peinfo->section[i].rsz)
2438
 
            peinfo->section[i].vsz=PESALIGN(EC32(section_hdr[i].SizeOfRawData), valign);
2439
 
 
2440
2921
        if (peinfo->section[i].rsz && !CLI_ISCONTAINED(0, (uint32_t) fsize, peinfo->section[i].raw, peinfo->section[i].rsz))
2441
2922
            peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw);
 
2923
 
 
2924
        /* cli_rawaddr now handles the whole process space
 
2925
         * TO BE REMOVED
 
2926
        if(!i) {
 
2927
            min = peinfo->section[i].rva;
 
2928
            max = peinfo->section[i].rva + peinfo->section[i].rsz;
 
2929
        } else {
 
2930
            if(EC32(section_hdr[i].VirtualAddress) < min)
 
2931
                min = EC32(section_hdr[i].VirtualAddress);
 
2932
 
 
2933
            if(EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData) > max)
 
2934
                max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
 
2935
        }
 
2936
        */
2442
2937
    }
2443
2938
 
2444
 
    if(pe_plus) {
 
2939
    if(pe_plus)
2445
2940
        peinfo->ep = EC32(optional_hdr64.AddressOfEntryPoint);
2446
 
        dirs = optional_hdr64.DataDirectory;
2447
 
    } else {
 
2941
    else
2448
2942
        peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint);
2449
 
        dirs = optional_hdr32.DataDirectory;
2450
 
    }
2451
2943
 
2452
 
    if(!(peinfo->ep = cli_rawaddr(peinfo->ep, peinfo->section, peinfo->nsections, &err, fsize, hdr_size)) && err) {
 
2944
    if(!(peinfo->ep = cli_rawaddr(peinfo->ep, peinfo->section, peinfo->nsections, &err, fsize)) && err) {
 
2945
#ifdef ACAB_REGRESSION
 
2946
        peinfo->ep = 0x7fffffff;
 
2947
#else
2453
2948
        cli_dbgmsg("Broken PE file\n");
2454
2949
        free(section_hdr);
2455
2950
        free(peinfo->section);
2456
2951
        peinfo->section = NULL;
2457
2952
        return -1;
 
2953
#endif /* ACAB_REGRESSION */
2458
2954
    }
2459
2955
 
2460
 
    if(EC16(file_hdr.Characteristics) & 0x2000 || !dirs[2].Size)
2461
 
        peinfo->res_addr = 0;
2462
 
    else
2463
 
        peinfo->res_addr = EC32(dirs[2].VirtualAddress);
2464
 
 
2465
 
    while(dirs[2].Size) {
2466
 
        struct vinfo_list vlist;
2467
 
        uint8_t *vptr, *baseptr;
2468
 
        uint32_t rva, res_sz;
2469
 
        unsigned int i;
2470
 
 
2471
 
        memset(&vlist, 0, sizeof(vlist));
2472
 
        findres(0x10, 0xffffffff, EC32(dirs[2].VirtualAddress), map, peinfo->section, peinfo->nsections, hdr_size, versioninfo_cb, &vlist);
2473
 
        if(!vlist.count) break; /* No version_information */
2474
 
        if(cli_hashset_init(&peinfo->vinfo, 32, 80)) {
2475
 
            cli_errmsg("cli_peheader: Unable to init vinfo hashset\n");
2476
 
            free(section_hdr);
2477
 
            free(peinfo->section);
2478
 
            peinfo->section = NULL;
2479
 
            return -1;
2480
 
        }
2481
 
 
2482
 
        err = 0;
2483
 
        for(i=0; i<vlist.count; i++) { /* enum all version_information res - RESUMABLE */
2484
 
            cli_dbgmsg("cli_peheader: parsing version info @ rva %x (%u/%u)\n", vlist.rvas[i], i+1, vlist.count);
2485
 
            rva = cli_rawaddr(vlist.rvas[i], peinfo->section, peinfo->nsections, &err, fsize, hdr_size);
2486
 
            if(err)
2487
 
                continue;
2488
 
 
2489
 
            if(!(vptr = fmap_need_off_once(map, rva, 16)))
2490
 
                continue;
2491
 
 
2492
 
            baseptr = vptr - rva;
2493
 
            /* parse resource */
2494
 
            rva = cli_readint32(vptr); /* ptr to version_info */
2495
 
            res_sz = cli_readint32(vptr+4); /* sizeof(resource) */
2496
 
            rva = cli_rawaddr(rva, peinfo->section, peinfo->nsections, &err, fsize, hdr_size);
2497
 
            if(err)
2498
 
                continue;
2499
 
            if(!(vptr = fmap_need_off_once(map, rva, res_sz)))
2500
 
                continue;
2501
 
            
2502
 
            while(res_sz>4) { /* look for version_info - NOT RESUMABLE (expecting exactly one versioninfo) */
2503
 
                uint32_t vinfo_sz, vinfo_val_sz;
2504
 
 
2505
 
                vinfo_sz = vinfo_val_sz = cli_readint32(vptr);
2506
 
                vinfo_sz &= 0xffff;
2507
 
                if(vinfo_sz > res_sz)
2508
 
                    break; /* the content is larger than the container */
2509
 
 
2510
 
                vinfo_val_sz >>= 16;
2511
 
                if(vinfo_sz <= 6 + 0x20 + 2 + 0x34 ||
2512
 
                   vinfo_val_sz != 0x34 || 
2513
 
                   memcmp(vptr+6, "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0\0", 0x20) ||
2514
 
                   cli_readint32(vptr + 0x28) != 0xfeef04bd) {
2515
 
                    /* - there should be enough room for the header(6), the key "VS_VERSION_INFO"(20), the padding(2) and the value(34)
2516
 
                     * - the value should be sizeof(fixedfileinfo)
2517
 
                     * - the key should match
2518
 
                     * - there should be some proper magic for fixedfileinfo */
2519
 
                    break; /* there's no point in looking further */
2520
 
                }
2521
 
 
2522
 
                /* move to the end of fixedfileinfo where the child elements are located */
2523
 
                vptr += 6 + 0x20 + 2 + 0x34;
2524
 
                vinfo_sz -= 6 + 0x20 + 2 + 0x34;
2525
 
 
2526
 
                while(vinfo_sz > 6) { /* look for stringfileinfo - NOT RESUMABLE (expecting at most one stringfileinfo) */
2527
 
                    uint32_t sfi_sz = cli_readint32(vptr) & 0xffff;
2528
 
 
2529
 
                    if(sfi_sz > vinfo_sz)
2530
 
                        break; /* the content is larger than the container */
2531
 
 
2532
 
                    /* expecting stringfileinfo to always precede varfileinfo */
2533
 
                    if(sfi_sz <= 6 + 0x1e || memcmp(vptr+6, "S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x1e)) {
2534
 
                        /* - there should be enough room for the header(6) and the key "StringFileInfo"(1e)
2535
 
                         * - the key should match */
2536
 
                        break; /* this is an implicit hard fail: parent is not resumable */
2537
 
                    }
2538
 
 
2539
 
                    /* move to the end of stringfileinfo where the child elements are located */
2540
 
                    vptr += 6 + 0x1e;
2541
 
                    sfi_sz -= 6 + 0x1e;
2542
 
 
2543
 
                    while(sfi_sz > 6) { /* enum all stringtables - RESUMABLE */
2544
 
                        uint32_t st_sz = cli_readint32(vptr) & 0xffff;
2545
 
                        uint8_t *next_vptr = vptr + st_sz;
2546
 
                        uint32_t next_sfi_sz = sfi_sz - st_sz;
2547
 
 
2548
 
                        if(st_sz > sfi_sz || st_sz <= 24) {
2549
 
                            /* - the content is larger than the container
2550
 
                               - there's no room for a stringtables (headers(6) + key(16) + padding(2)) */
2551
 
                            break; /* this is an implicit hard fail: parent is not resumable */
2552
 
                        }
2553
 
 
2554
 
                        /* move to the end of stringtable where the child elements are located */
2555
 
                        vptr += 24;
2556
 
                        st_sz -= 24;
2557
 
 
2558
 
                        while(st_sz > 6) {  /* enum all strings - RESUMABLE */
2559
 
                            uint32_t s_sz, s_key_sz, s_val_sz;
2560
 
 
2561
 
                            s_sz = (cli_readint32(vptr) & 0xffff) + 3;
2562
 
                            s_sz &= ~3;
2563
 
                            if(s_sz > st_sz || s_sz <= 6 + 2 + 8) {
2564
 
                                /* - the content is larger than the container
2565
 
                                 * - there's no room for a minimal string
2566
 
                                 * - there's no room for the value */
2567
 
                                st_sz = 0;
2568
 
                                sfi_sz = 0;
2569
 
                                break; /* force a hard fail */
2570
 
                            }
2571
 
 
2572
 
                            /* ~wcstrlen(key) */
2573
 
                            for(s_key_sz = 6; s_key_sz+1 < s_sz; s_key_sz += 2) {
2574
 
                                if(vptr[s_key_sz] || vptr[s_key_sz+1]) continue;
2575
 
                                s_key_sz += 2;
2576
 
                                break;
2577
 
                            }
2578
 
 
2579
 
                            s_key_sz += 3;
2580
 
                            s_key_sz &= ~3;
2581
 
 
2582
 
                            if(s_key_sz >= s_sz) {
2583
 
                                /* key overflow */
2584
 
                                vptr += s_sz;
2585
 
                                st_sz -= s_sz;
2586
 
                                continue;
2587
 
                            }
2588
 
 
2589
 
                            s_val_sz = s_sz - s_key_sz;
2590
 
                            s_key_sz -= 6;
2591
 
 
2592
 
                            if(s_val_sz <= 2) {
2593
 
                                /* skip unset value */
2594
 
                                vptr += s_sz;
2595
 
                                st_sz -= s_sz;
2596
 
                                continue;
2597
 
                            }
2598
 
 
2599
 
                            if(cli_hashset_addkey(&peinfo->vinfo, (uint32_t)(vptr - baseptr + 6))) {
2600
 
                                cli_errmsg("cli_peheader: Unable to add rva to vinfo hashset\n");
2601
 
                                cli_hashset_destroy(&peinfo->vinfo);
2602
 
                                free(section_hdr);
2603
 
                                free(peinfo->section);
2604
 
                                peinfo->section = NULL;
2605
 
                                return -1;
2606
 
                            }
2607
 
 
2608
 
                            if(cli_debug_flag) {
2609
 
                                char *k, *v, *s;
2610
 
 
2611
 
                                /* FIXME: skip too long strings */
2612
 
                                k = cli_utf16toascii((const char*)vptr + 6, s_key_sz);
2613
 
                                if(k) {
2614
 
                                    v = cli_utf16toascii((const char*)vptr + s_key_sz + 6, s_val_sz);
2615
 
                                    if(v) {
2616
 
                                        s = cli_str2hex((const char*)vptr + 6, s_key_sz + s_val_sz - 6);
2617
 
                                        if(s) {
2618
 
                                            cli_dbgmsg("VersionInfo (%x): '%s'='%s' - VI:%s\n", (uint32_t)(vptr - baseptr + 6), k, v, s);
2619
 
                                            free(s);
2620
 
                                        }
2621
 
                                        free(v);
2622
 
                                    }
2623
 
                                    free(k);
2624
 
                                }
2625
 
                            }
2626
 
                            vptr += s_sz;
2627
 
                            st_sz -= s_sz;
2628
 
                        } /* enum all strings - RESUMABLE */
2629
 
                        vptr = next_vptr;
2630
 
                        sfi_sz = next_sfi_sz * (sfi_sz != 0);
2631
 
                    } /* enum all stringtables - RESUMABLE */
2632
 
                    break;
2633
 
                } /* look for stringfileinfo - NOT RESUMABLE */
2634
 
                break;
2635
 
            } /* look for version_info - NOT RESUMABLE */
2636
 
        } /* enum all version_information res - RESUMABLE */
2637
 
        break;
2638
 
    } /* while(dirs[2].Size) */
2639
 
 
2640
2956
    free(section_hdr);
2641
2957
    return 0;
2642
2958
}