~vcs-imports/clamav/main-old

« back to all changes in this revision

Viewing changes to libclamav/pe.c

  • Committer: nervoso
  • Date: 2006-05-21 15:16:39 UTC
  • Revision ID: Arch-1:clamav@arch.ubuntu.com%clamav--MAIN--0--patch-1959
repository moved to cvs.clamav.net

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (C) 2004 - 2006 Tomasz Kojm <tkojm@clamav.net>
3
 
 *
4
 
 *  With additions from aCaB <acab@clamav.net>
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 
 *  MA 02110-1301, USA.
20
 
 */
21
 
 
22
 
#if HAVE_CONFIG_H
23
 
#include "clamav-config.h"
24
 
#endif
25
 
 
26
 
#include <stdio.h>
27
 
#include <string.h>
28
 
#include <sys/types.h>
29
 
#include <sys/stat.h>
30
 
#include <fcntl.h>
31
 
#include <sys/stat.h>
32
 
#include <unistd.h>
33
 
#include <time.h>
34
 
 
35
 
#include "cltypes.h"
36
 
#include "clamav.h"
37
 
#include "others.h"
38
 
#include "pe.h"
39
 
#include "petite.h"
40
 
#include "fsg.h"
41
 
#include "spin.h"
42
 
#include "upx.h"
43
 
#include "yc.h"
44
 
#include "scanners.h"
45
 
#include "rebuildpe.h"
46
 
#include "str.h"
47
 
#include "execs.h"
48
 
 
49
 
#define IMAGE_DOS_SIGNATURE         0x5a4d          /* MZ */
50
 
#define IMAGE_DOS_SIGNATURE_OLD     0x4d5a          /* ZM */
51
 
#define IMAGE_NT_SIGNATURE          0x00004550
52
 
#define PE32_SIGNATURE              0x010b
53
 
#define PE32P_SIGNATURE             0x020b
54
 
 
55
 
#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"
56
 
#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"
57
 
#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"
58
 
 
59
 
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
60
 
#define EC16(x) le16_to_host(x)
61
 
 
62
 
extern short cli_leavetemps_flag;
63
 
 
64
 
struct offset_list {
65
 
    uint32_t offset;
66
 
    struct offset_list *next;
67
 
};
68
 
 
69
 
static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos, unsigned int *err)
70
 
{
71
 
        int i, found = 0;
72
 
 
73
 
 
74
 
    for(i = 0; i < nos; i++) {
75
 
        if(EC32(shp[i].VirtualAddress) <= rva && EC32(shp[i].VirtualAddress) + EC32(shp[i].SizeOfRawData) > rva) {
76
 
            found = 1;
77
 
            break;
78
 
        }
79
 
    }
80
 
 
81
 
    if(!found) {
82
 
        *err = 1;
83
 
        return 0;
84
 
    }
85
 
 
86
 
    *err = 0;
87
 
    return rva - EC32(shp[i].VirtualAddress) + EC32(shp[i].PointerToRawData);
88
 
}
89
 
 
90
 
/*
91
 
static int cli_ddump(int desc, int offset, int size, const char *file)
92
 
{
93
 
        int pos, ndesc, bread, sum = 0;
94
 
        char buff[FILEBUFF];
95
 
 
96
 
 
97
 
    cli_dbgmsg("in ddump()\n");
98
 
 
99
 
    if((pos = lseek(desc, 0, SEEK_CUR)) == -1) {
100
 
        cli_dbgmsg("Invalid descriptor\n");
101
 
        return -1;
102
 
    }
103
 
 
104
 
    if(lseek(desc, offset, SEEK_SET) == -1) {
105
 
        cli_dbgmsg("lseek() failed\n");
106
 
        lseek(desc, pos, SEEK_SET);
107
 
        return -1;
108
 
    }
109
 
 
110
 
    if((ndesc = open(file, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
111
 
        cli_dbgmsg("Can't create file %s\n", file);
112
 
        lseek(desc, pos, SEEK_SET);
113
 
        return -1;
114
 
    }
115
 
 
116
 
    while((bread = read(desc, buff, FILEBUFF)) > 0) {
117
 
        if(sum + bread >= size) {
118
 
            if(write(ndesc, buff, size - sum) == -1) {
119
 
                cli_dbgmsg("Can't write to file\n");
120
 
                lseek(desc, pos, SEEK_SET);
121
 
                close(ndesc);
122
 
                unlink(file);
123
 
                return -1;
124
 
            }
125
 
            break;
126
 
        } else {
127
 
            if(write(ndesc, buff, bread) == -1) {
128
 
                cli_dbgmsg("Can't write to file\n");
129
 
                lseek(desc, pos, SEEK_SET);
130
 
                close(ndesc);
131
 
                unlink(file);
132
 
                return -1;
133
 
            }
134
 
        }
135
 
        sum += bread;
136
 
    }
137
 
 
138
 
    close(ndesc);
139
 
    lseek(desc, pos, SEEK_SET);
140
 
    return 0;
141
 
}
142
 
*/
143
 
 
144
 
int cli_scanpe(int desc, cli_ctx *ctx)
145
 
{
146
 
        uint16_t e_magic; /* DOS signature ("MZ") */
147
 
        uint16_t nsections;
148
 
        uint32_t e_lfanew; /* address of new exe header */
149
 
        uint32_t ep; /* entry point (raw) */
150
 
        uint8_t polipos = 0;
151
 
        time_t timestamp;
152
 
        struct pe_image_file_hdr file_hdr;
153
 
        struct pe_image_optional_hdr32 optional_hdr32;
154
 
        struct pe_image_optional_hdr64 optional_hdr64;
155
 
        struct pe_image_section_hdr *section_hdr;
156
 
        struct stat sb;
157
 
        char sname[9], buff[4096], *tempfile;
158
 
        unsigned char *ubuff;
159
 
        ssize_t bytes;
160
 
        unsigned int i, found, upx_success = 0, min = 0, max = 0, err, broken = 0;
161
 
        unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
162
 
        int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
163
 
        char *src = NULL, *dest = NULL;
164
 
        int ndesc, ret = CL_CLEAN;
165
 
        size_t fsize;
166
 
 
167
 
 
168
 
    if(read(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
169
 
        cli_dbgmsg("Can't read DOS signature\n");
170
 
        return CL_CLEAN;
171
 
    }
172
 
 
173
 
    if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
174
 
        cli_dbgmsg("Invalid DOS signature\n");
175
 
        return CL_CLEAN;
176
 
    }
177
 
 
178
 
    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
179
 
 
180
 
    if(read(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
181
 
        cli_dbgmsg("Can't read new header address\n");
182
 
        /* truncated header? */
183
 
        if(DETECT_BROKEN) {
184
 
            if(ctx->virname)
185
 
                *ctx->virname = "Broken.Executable";
186
 
            return CL_VIRUS;
187
 
        }
188
 
        return CL_CLEAN;
189
 
    }
190
 
 
191
 
    e_lfanew = EC32(e_lfanew);
192
 
    cli_dbgmsg("e_lfanew == %d\n", e_lfanew);
193
 
    if(!e_lfanew) {
194
 
        cli_dbgmsg("Not a PE file\n");
195
 
        return CL_CLEAN;
196
 
    }
197
 
 
198
 
    if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
199
 
        /* probably not a PE file */
200
 
        cli_dbgmsg("Can't lseek to e_lfanew\n");
201
 
        return CL_CLEAN;
202
 
    }
203
 
 
204
 
    if(read(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
205
 
        /* bad information in e_lfanew - probably not a PE file */
206
 
        cli_dbgmsg("Can't read file header\n");
207
 
        return CL_CLEAN;
208
 
    }
209
 
 
210
 
    if(EC32(file_hdr.Magic) != IMAGE_NT_SIGNATURE) {
211
 
        cli_dbgmsg("Invalid PE signature (probably NE file)\n");
212
 
        return CL_CLEAN;
213
 
    }
214
 
 
215
 
    if(EC16(file_hdr.Characteristics) & 0x2000) {
216
 
        cli_dbgmsg("File type: DLL\n");
217
 
        dll = 1;
218
 
    } else if(EC16(file_hdr.Characteristics) & 0x01) {
219
 
        cli_dbgmsg("File type: Executable\n");
220
 
    }
221
 
 
222
 
    switch(EC16(file_hdr.Machine)) {
223
 
        case 0x0:
224
 
            cli_dbgmsg("Machine type: Unknown\n");
225
 
        case 0x14c:
226
 
            cli_dbgmsg("Machine type: 80386\n");
227
 
            break;
228
 
        case 0x14d:
229
 
            cli_dbgmsg("Machine type: 80486\n");
230
 
            break;
231
 
        case 0x14e:
232
 
            cli_dbgmsg("Machine type: 80586\n");
233
 
            break;
234
 
        case 0x160:
235
 
            cli_dbgmsg("Machine type: R30000 (big-endian)\n");
236
 
            break;
237
 
        case 0x162:
238
 
            cli_dbgmsg("Machine type: R3000\n");
239
 
            break;
240
 
        case 0x166:
241
 
            cli_dbgmsg("Machine type: R4000\n");
242
 
            break;
243
 
        case 0x168:
244
 
            cli_dbgmsg("Machine type: R10000\n");
245
 
            break;
246
 
        case 0x184:
247
 
            cli_dbgmsg("Machine type: DEC Alpha AXP\n");
248
 
            break;
249
 
        case 0x284:
250
 
            cli_dbgmsg("Machine type: DEC Alpha AXP 64bit\n");
251
 
            break;
252
 
        case 0x1f0:
253
 
            cli_dbgmsg("Machine type: PowerPC\n");
254
 
            break;
255
 
        case 0x200:
256
 
            cli_dbgmsg("Machine type: IA64\n");
257
 
            break;
258
 
        case 0x268:
259
 
            cli_dbgmsg("Machine type: M68k\n");
260
 
            break;
261
 
        case 0x266:
262
 
            cli_dbgmsg("Machine type: MIPS16\n");
263
 
            break;
264
 
        case 0x366:
265
 
            cli_dbgmsg("Machine type: MIPS+FPU\n");
266
 
            break;
267
 
        case 0x466:
268
 
            cli_dbgmsg("Machine type: MIPS16+FPU\n");
269
 
            break;
270
 
        case 0x1a2:
271
 
            cli_dbgmsg("Machine type: Hitachi SH3\n");
272
 
            break;
273
 
        case 0x1a3:
274
 
            cli_dbgmsg("Machine type: Hitachi SH3-DSP\n");
275
 
            break;
276
 
        case 0x1a4:
277
 
            cli_dbgmsg("Machine type: Hitachi SH3-E\n");
278
 
            break;
279
 
        case 0x1a6:
280
 
            cli_dbgmsg("Machine type: Hitachi SH4\n");
281
 
            break;
282
 
        case 0x1a8:
283
 
            cli_dbgmsg("Machine type: Hitachi SH5\n");
284
 
            break;
285
 
        case 0x1c0:
286
 
            cli_dbgmsg("Machine type: ARM\n");
287
 
            break;
288
 
        case 0x1c2:
289
 
            cli_dbgmsg("Machine type: THUMB\n");
290
 
            break;
291
 
        case 0x1d3:
292
 
            cli_dbgmsg("Machine type: AM33\n");
293
 
            break;
294
 
        case 0x520:
295
 
            cli_dbgmsg("Machine type: Infineon TriCore\n");
296
 
            break;
297
 
        case 0xcef:
298
 
            cli_dbgmsg("Machine type: CEF\n");
299
 
            break;
300
 
        case 0xebc:
301
 
            cli_dbgmsg("Machine type: EFI Byte Code\n");
302
 
            break;
303
 
        case 0x9041:
304
 
            cli_dbgmsg("Machine type: M32R\n");
305
 
            break;
306
 
        case 0xc0ee:
307
 
            cli_dbgmsg("Machine type: CEE\n");
308
 
            break;
309
 
        case 0x8664:
310
 
            cli_dbgmsg("Machine type: AMD64\n");
311
 
            break;
312
 
        default:
313
 
            cli_warnmsg("Unknown machine type in PE header (0x%x)\n", EC16(file_hdr.Machine));
314
 
    }
315
 
 
316
 
    nsections = EC16(file_hdr.NumberOfSections);
317
 
    if(nsections < 1 || nsections > 99) {
318
 
        if(DETECT_BROKEN) {
319
 
            if(ctx->virname)
320
 
                *ctx->virname = "Broken.Executable";
321
 
            return CL_VIRUS;
322
 
        }
323
 
        if(nsections)
324
 
            cli_warnmsg("PE file contains %d sections\n", nsections);
325
 
        else
326
 
            cli_warnmsg("PE file contains no sections\n");
327
 
        return CL_CLEAN;
328
 
    }
329
 
    cli_dbgmsg("NumberOfSections: %d\n", nsections);
330
 
 
331
 
    timestamp = (time_t) EC32(file_hdr.TimeDateStamp);
332
 
    cli_dbgmsg("TimeDateStamp: %s", ctime(&timestamp));
333
 
 
334
 
    cli_dbgmsg("SizeOfOptionalHeader: %d\n", EC16(file_hdr.SizeOfOptionalHeader));
335
 
 
336
 
    if(EC16(file_hdr.SizeOfOptionalHeader) != sizeof(struct pe_image_optional_hdr32)) {
337
 
        if(EC16(file_hdr.SizeOfOptionalHeader) == sizeof(struct pe_image_optional_hdr64)) {
338
 
            pe_plus = 1;
339
 
        } else {
340
 
            cli_dbgmsg("Incorrect value of SizeOfOptionalHeader\n");
341
 
            if(DETECT_BROKEN) {
342
 
                if(ctx->virname)
343
 
                    *ctx->virname = "Broken.Executable";
344
 
                return CL_VIRUS;
345
 
            }
346
 
            return CL_CLEAN;
347
 
        }
348
 
    }
349
 
 
350
 
    if(!pe_plus) { /* PE */
351
 
 
352
 
        if(read(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
353
 
            cli_dbgmsg("Can't optional file header\n");
354
 
            if(DETECT_BROKEN) {
355
 
                if(ctx->virname)
356
 
                    *ctx->virname = "Broken.Executable";
357
 
                return CL_VIRUS;
358
 
            }
359
 
            return CL_CLEAN;
360
 
        }
361
 
 
362
 
        if(EC16(optional_hdr32.Magic) != PE32_SIGNATURE) {
363
 
            cli_warnmsg("Incorrect magic number in optional header\n");
364
 
            if(DETECT_BROKEN) {
365
 
                if(ctx->virname)
366
 
                    *ctx->virname = "Broken.Executable";
367
 
                return CL_VIRUS;
368
 
            }
369
 
        }
370
 
        cli_dbgmsg("File format: PE\n");
371
 
 
372
 
        cli_dbgmsg("MajorLinkerVersion: %d\n", optional_hdr32.MajorLinkerVersion);
373
 
        cli_dbgmsg("MinorLinkerVersion: %d\n", optional_hdr32.MinorLinkerVersion);
374
 
        cli_dbgmsg("SizeOfCode: %d\n", EC32(optional_hdr32.SizeOfCode));
375
 
        cli_dbgmsg("SizeOfInitializedData: %d\n", EC32(optional_hdr32.SizeOfInitializedData));
376
 
        cli_dbgmsg("SizeOfUninitializedData: %d\n", EC32(optional_hdr32.SizeOfUninitializedData));
377
 
        cli_dbgmsg("AddressOfEntryPoint: 0x%x\n", EC32(optional_hdr32.AddressOfEntryPoint));
378
 
        cli_dbgmsg("BaseOfCode: 0x%x\n", EC32(optional_hdr32.BaseOfCode));
379
 
        cli_dbgmsg("SectionAlignment: %d\n", EC32(optional_hdr32.SectionAlignment));
380
 
        cli_dbgmsg("FileAlignment: %d\n", EC32(optional_hdr32.FileAlignment));
381
 
        cli_dbgmsg("MajorSubsystemVersion: %d\n", EC16(optional_hdr32.MajorSubsystemVersion));
382
 
        cli_dbgmsg("MinorSubsystemVersion: %d\n", EC16(optional_hdr32.MinorSubsystemVersion));
383
 
        cli_dbgmsg("SizeOfImage: %d\n", EC32(optional_hdr32.SizeOfImage));
384
 
        cli_dbgmsg("SizeOfHeaders: %d\n", EC32(optional_hdr32.SizeOfHeaders));
385
 
        cli_dbgmsg("NumberOfRvaAndSizes: %d\n", EC32(optional_hdr32.NumberOfRvaAndSizes));
386
 
 
387
 
    } else { /* PE+ */
388
 
 
389
 
        if(read(desc, &optional_hdr64, sizeof(struct pe_image_optional_hdr64)) != sizeof(struct pe_image_optional_hdr64)) {
390
 
            cli_dbgmsg("Can't optional file header\n");
391
 
            if(DETECT_BROKEN) {
392
 
                if(ctx->virname)
393
 
                    *ctx->virname = "Broken.Executable";
394
 
                return CL_VIRUS;
395
 
            }
396
 
            return CL_CLEAN;
397
 
        }
398
 
 
399
 
        if(EC16(optional_hdr64.Magic) != PE32P_SIGNATURE) {
400
 
            cli_warnmsg("Incorrect magic number in optional header\n");
401
 
            if(DETECT_BROKEN) {
402
 
                if(ctx->virname)
403
 
                    *ctx->virname = "Broken.Executable";
404
 
                return CL_VIRUS;
405
 
            }
406
 
        }
407
 
        cli_dbgmsg("File format: PE32+\n");
408
 
 
409
 
        cli_dbgmsg("MajorLinkerVersion: %d\n", optional_hdr64.MajorLinkerVersion);
410
 
        cli_dbgmsg("MinorLinkerVersion: %d\n", optional_hdr64.MinorLinkerVersion);
411
 
        cli_dbgmsg("SizeOfCode: %d\n", EC32(optional_hdr64.SizeOfCode));
412
 
        cli_dbgmsg("SizeOfInitializedData: %d\n", EC32(optional_hdr64.SizeOfInitializedData));
413
 
        cli_dbgmsg("SizeOfUninitializedData: %d\n", EC32(optional_hdr64.SizeOfUninitializedData));
414
 
        cli_dbgmsg("AddressOfEntryPoint: 0x%x\n", EC32(optional_hdr64.AddressOfEntryPoint));
415
 
        cli_dbgmsg("BaseOfCode: 0x%x\n", EC32(optional_hdr64.BaseOfCode));
416
 
        cli_dbgmsg("SectionAlignment: %d\n", EC32(optional_hdr64.SectionAlignment));
417
 
        cli_dbgmsg("FileAlignment: %d\n", EC32(optional_hdr64.FileAlignment));
418
 
        cli_dbgmsg("MajorSubsystemVersion: %d\n", EC16(optional_hdr64.MajorSubsystemVersion));
419
 
        cli_dbgmsg("MinorSubsystemVersion: %d\n", EC16(optional_hdr64.MinorSubsystemVersion));
420
 
        cli_dbgmsg("SizeOfImage: %d\n", EC32(optional_hdr64.SizeOfImage));
421
 
        cli_dbgmsg("SizeOfHeaders: %d\n", EC32(optional_hdr64.SizeOfHeaders));
422
 
        cli_dbgmsg("NumberOfRvaAndSizes: %d\n", EC32(optional_hdr64.NumberOfRvaAndSizes));
423
 
    }
424
 
 
425
 
    switch(pe_plus ? EC16(optional_hdr64.Subsystem) : EC16(optional_hdr32.Subsystem)) {
426
 
        case 0:
427
 
            cli_dbgmsg("Subsystem: Unknown\n");
428
 
            break;
429
 
        case 1:
430
 
            cli_dbgmsg("Subsystem: Native (a driver ?)\n");
431
 
            break;
432
 
        case 2:
433
 
            cli_dbgmsg("Subsystem: Win32 GUI\n");
434
 
            break;
435
 
        case 3:
436
 
            cli_dbgmsg("Subsystem: Win32 console\n");
437
 
            break;
438
 
        case 5:
439
 
            cli_dbgmsg("Subsystem: OS/2 console\n");
440
 
            break;
441
 
        case 7:
442
 
            cli_dbgmsg("Subsystem: POSIX console\n");
443
 
            break;
444
 
        case 8:
445
 
            cli_dbgmsg("Subsystem: Native Win9x driver\n");
446
 
            break;
447
 
        case 9:
448
 
            cli_dbgmsg("Subsystem: WinCE GUI\n");
449
 
            break;
450
 
        case 10:
451
 
            cli_dbgmsg("Subsystem: EFI application\n");
452
 
            break;
453
 
        case 11:
454
 
            cli_dbgmsg("Subsystem: EFI driver\n");
455
 
            break;
456
 
        case 12:
457
 
            cli_dbgmsg("Subsystem: EFI runtime driver\n");
458
 
            break;
459
 
        default:
460
 
            cli_warnmsg("Unknown subsystem in PE header (0x%x)\n", pe_plus ? EC16(optional_hdr64.Subsystem) : EC16(optional_hdr32.Subsystem));
461
 
    }
462
 
 
463
 
    cli_dbgmsg("------------------------------------\n");
464
 
 
465
 
    if(fstat(desc, &sb) == -1) {
466
 
        cli_dbgmsg("fstat failed\n");
467
 
        return CL_EIO;
468
 
    }
469
 
 
470
 
    fsize = sb.st_size;
471
 
 
472
 
    section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr));
473
 
 
474
 
    if(!section_hdr) {
475
 
        cli_dbgmsg("Can't allocate memory for section headers\n");
476
 
        return CL_EMEM;
477
 
    }
478
 
 
479
 
    for(i = 0; i < nsections; i++) {
480
 
 
481
 
        if(read(desc, &section_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) {
482
 
            cli_dbgmsg("Can't read section header\n");
483
 
            cli_dbgmsg("Possibly broken PE file\n");
484
 
            free(section_hdr);
485
 
            if(DETECT_BROKEN) {
486
 
                if(ctx->virname)
487
 
                    *ctx->virname = "Broken.Executable";
488
 
                return CL_VIRUS;
489
 
            }
490
 
            return CL_CLEAN;
491
 
        }
492
 
 
493
 
        strncpy(sname, section_hdr[i].Name, 8);
494
 
        sname[8] = 0;
495
 
        cli_dbgmsg("Section %d\n", i);
496
 
        cli_dbgmsg("Section name: %s\n", sname);
497
 
        cli_dbgmsg("VirtualSize: %d\n", EC32(section_hdr[i].VirtualSize));
498
 
        cli_dbgmsg("VirtualAddress: 0x%x\n", EC32(section_hdr[i].VirtualAddress));
499
 
        cli_dbgmsg("SizeOfRawData: %d\n", EC32(section_hdr[i].SizeOfRawData));
500
 
        cli_dbgmsg("PointerToRawData: 0x%x (%d)\n", EC32(section_hdr[i].PointerToRawData), EC32(section_hdr[i].PointerToRawData));
501
 
 
502
 
        if(EC32(section_hdr[i].Characteristics) & 0x20) {
503
 
            cli_dbgmsg("Section contains executable code\n");
504
 
 
505
 
            if(EC32(section_hdr[i].VirtualSize) < EC32(section_hdr[i].SizeOfRawData)) {
506
 
                cli_dbgmsg("Section contains free space\n");
507
 
                /*
508
 
                cli_dbgmsg("Dumping %d bytes\n", section_hdr.SizeOfRawData - section_hdr.VirtualSize);
509
 
                ddump(desc, section_hdr.PointerToRawData + section_hdr.VirtualSize, section_hdr.SizeOfRawData - section_hdr.VirtualSize, cli_gentemp(NULL));
510
 
                */
511
 
 
512
 
            }
513
 
        }
514
 
 
515
 
        if(EC32(section_hdr[i].Characteristics) & 0x20000000)
516
 
            cli_dbgmsg("Section's memory is executable\n");
517
 
 
518
 
        if(EC32(section_hdr[i].Characteristics) & 0x80000000)
519
 
            cli_dbgmsg("Section's memory is writeable\n");
520
 
 
521
 
        cli_dbgmsg("------------------------------------\n");
522
 
 
523
 
        if(!CLI_ISCONTAINED2(0, (uint32_t) fsize, EC32(section_hdr[i].PointerToRawData), EC32(section_hdr[i].SizeOfRawData)) || EC32(section_hdr[i].PointerToRawData) > fsize) {
524
 
            cli_dbgmsg("Possibly broken PE file - Section %d out of file (Offset@ %d, Rsize %d, Total filesize %d)\n", i, EC32(section_hdr[i].PointerToRawData), EC32(section_hdr[i].SizeOfRawData), fsize);
525
 
            if(DETECT_BROKEN) {
526
 
                if(ctx->virname)
527
 
                    *ctx->virname = "Broken.Executable";
528
 
                free(section_hdr);
529
 
                return CL_VIRUS;
530
 
            }
531
 
            broken = 1;
532
 
        }
533
 
 
534
 
        if(!i) {
535
 
            min = EC32(section_hdr[i].VirtualAddress);
536
 
            max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
537
 
        } else {
538
 
            if(EC32(section_hdr[i].VirtualAddress) < min)
539
 
                min = EC32(section_hdr[i].VirtualAddress);
540
 
 
541
 
            if(EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData) > max)
542
 
                max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
543
 
        }
544
 
 
545
 
        if(SCAN_ALGO && !strlen(sname)) {
546
 
            if(EC32(section_hdr[i].VirtualSize) > 40000 && EC32(section_hdr[i].VirtualSize) < 70000) {
547
 
                if(EC32(section_hdr[i].Characteristics) == 0xe0000060) {
548
 
                    polipos = i;
549
 
                }
550
 
            }
551
 
        }
552
 
 
553
 
    }
554
 
 
555
 
    if(pe_plus)
556
 
        ep = EC32(optional_hdr64.AddressOfEntryPoint);
557
 
    else
558
 
        ep = EC32(optional_hdr32.AddressOfEntryPoint);
559
 
 
560
 
    if(ep >= min && !(ep = cli_rawaddr(ep, section_hdr, nsections, &err)) && err) {
561
 
        cli_dbgmsg("Possibly broken PE file\n");
562
 
        free(section_hdr);
563
 
        if(DETECT_BROKEN) {
564
 
            if(ctx->virname)
565
 
                *ctx->virname = "Broken.Executable";
566
 
            return CL_VIRUS;
567
 
        }
568
 
        return CL_CLEAN;
569
 
    }
570
 
 
571
 
    cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
572
 
 
573
 
    /* Attempt to detect some popular polymorphic viruses */
574
 
 
575
 
    /* W32.Parite.B */
576
 
    if(SCAN_ALGO && !dll && ep == EC32(section_hdr[nsections - 1].PointerToRawData)) {
577
 
        lseek(desc, ep, SEEK_SET);
578
 
        if(read(desc, buff, 4096) == 4096) {
579
 
                const char *pt = cli_memstr(buff, 4040, "\x47\x65\x74\x50\x72\x6f\x63\x41\x64\x64\x72\x65\x73\x73\x00", 15);
580
 
            if(pt) {
581
 
                    uint32_t dw1, dw2;
582
 
 
583
 
                pt += 15;
584
 
                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) {
585
 
                    *ctx->virname = "W32.Parite.B";
586
 
                    free(section_hdr);
587
 
                    return CL_VIRUS;
588
 
                }
589
 
            }
590
 
        }
591
 
    }
592
 
 
593
 
    /* W32.Magistr.A/B */
594
 
    if(SCAN_ALGO && !dll && (EC32(section_hdr[nsections - 1].Characteristics) & 0x80000000)) {
595
 
            uint32_t rsize, vsize;
596
 
 
597
 
        rsize = EC32(section_hdr[nsections - 1].SizeOfRawData);
598
 
        vsize = EC32(section_hdr[nsections - 1].VirtualSize);
599
 
 
600
 
        if(rsize >= 0x612c && vsize >= 0x612c && ((vsize & 0xff) == 0xec)) {
601
 
                int bw = rsize < 0x7000 ? rsize : 0x7000;
602
 
 
603
 
            lseek(desc, EC32(section_hdr[nsections - 1].PointerToRawData) + rsize - bw, SEEK_SET);
604
 
            if(read(desc, buff, 4096) == 4096) {
605
 
                if(cli_memstr(buff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
606
 
                    *ctx->virname = "W32.Magistr.A";
607
 
                    free(section_hdr);
608
 
                    return CL_VIRUS;
609
 
                } 
610
 
            }
611
 
 
612
 
        } else if(rsize >= 0x7000 && vsize >= 0x7000 && ((vsize & 0xff) == 0xed)) {
613
 
                int bw = rsize < 0x8000 ? rsize : 0x8000;
614
 
 
615
 
            lseek(desc, EC32(section_hdr[nsections - 1].PointerToRawData) + rsize - bw, SEEK_SET);
616
 
            if(read(desc, buff, 4096) == 4096) {
617
 
                if(cli_memstr(buff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
618
 
                    *ctx->virname = "W32.Magistr.B";
619
 
                    free(section_hdr);
620
 
                    return CL_VIRUS;
621
 
                } 
622
 
            }
623
 
        }
624
 
    }
625
 
 
626
 
    /* W32.Polipos.A */
627
 
   if(polipos && !dll && !pe_plus && 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) {
628
 
                uint32_t remaining = EC32(section_hdr[0].SizeOfRawData);
629
 
                uint32_t chunk = sizeof(buff);
630
 
                uint32_t val, shift, raddr, curroff, total = 0;
631
 
                const char *jpt;
632
 
                struct offset_list *offlist = NULL, *offnode;
633
 
 
634
 
 
635
 
        cli_dbgmsg("Detected W32.Polipos.A characteristics\n");
636
 
 
637
 
        if(remaining < chunk)
638
 
            chunk = remaining;
639
 
 
640
 
        lseek(desc, EC32(section_hdr[0].PointerToRawData), SEEK_SET);
641
 
        while((bytes = cli_readn(desc, buff, chunk)) > 0) {
642
 
            shift = 0;
643
 
            while(bytes - 5 > shift) {
644
 
                jpt = buff + shift;
645
 
                if(*jpt!='\xe9' && *jpt!='\xe8') {
646
 
                    shift++;
647
 
                    continue;
648
 
                }
649
 
                val = cli_readint32(jpt + 1);
650
 
                val += 5 + EC32(section_hdr[0].VirtualAddress) + total + shift;
651
 
                raddr = cli_rawaddr(val, section_hdr, nsections, &err);
652
 
 
653
 
                if(!err && (raddr >= EC32(section_hdr[polipos].PointerToRawData) && raddr < EC32(section_hdr[polipos].PointerToRawData) + EC32(section_hdr[polipos].SizeOfRawData)) && (!offlist || (raddr != offlist->offset))) {
654
 
                    offnode = (struct offset_list *) cli_malloc(sizeof(struct offset_list));
655
 
                    if(!offnode) {
656
 
                        free(section_hdr);
657
 
                        while(offlist) {
658
 
                            offnode = offlist;
659
 
                            offlist = offlist->next;
660
 
                            free(offnode);
661
 
                        }
662
 
                        return CL_EMEM;
663
 
                    }
664
 
                    offnode->offset = raddr;
665
 
                    offnode->next = offlist;
666
 
                    offlist = offnode;
667
 
                }
668
 
 
669
 
                shift++;
670
 
            }
671
 
 
672
 
            if(remaining < chunk) {
673
 
                chunk = remaining;
674
 
            } else {
675
 
                remaining -= bytes;
676
 
                if(remaining < chunk) {
677
 
                    chunk = remaining;
678
 
                }
679
 
            }
680
 
 
681
 
            if(!remaining)
682
 
                break;
683
 
 
684
 
            total += bytes;
685
 
        }
686
 
 
687
 
        offnode = offlist;
688
 
        while(offnode) {
689
 
            cli_dbgmsg("Polipos: Checking offset 0x%x (%u)", offnode->offset, offnode->offset);
690
 
            lseek(desc, offnode->offset, SEEK_SET);
691
 
            if(cli_readn(desc, buff, 9) == 9) {
692
 
                ubuff = (unsigned char *) buff;
693
 
                if(ubuff[0] == 0x55 && ubuff[1] == 0x8b && ubuff[2] == 0xec &&
694
 
                   ((ubuff[3] == 0x83 && ubuff[4] == 0xec && ubuff[6] == 0x60) ||  ubuff[3] == 0x60 ||
695
 
                     (ubuff[3] == 0x81 && ubuff[4] == 0xec && ubuff[7] == 0x00 && ubuff[8] == 0x00))) {
696
 
                    ret = CL_VIRUS;
697
 
                    *ctx->virname = "W32.Polipos.A";
698
 
                    break;
699
 
                }
700
 
            }
701
 
 
702
 
            offnode = offnode->next;
703
 
        }
704
 
 
705
 
        while(offlist) {
706
 
            offnode = offlist;
707
 
            offlist = offlist->next;
708
 
            free(offnode);
709
 
        }
710
 
 
711
 
        if(ret == CL_VIRUS) {
712
 
            free(section_hdr);
713
 
            return CL_VIRUS;
714
 
        }
715
 
    }
716
 
 
717
 
 
718
 
    if(broken) {
719
 
        free(section_hdr);
720
 
        return CL_CLEAN;
721
 
    }
722
 
 
723
 
    if(pe_plus) { /* Do not continue for PE32+ files */
724
 
        free(section_hdr);
725
 
        return CL_CLEAN;
726
 
    }
727
 
 
728
 
 
729
 
    /* UPX & FSG support */
730
 
 
731
 
    /* try to find the first section with physical size == 0 */
732
 
    found = 0;
733
 
    for(i = 0; i < (unsigned int) nsections - 1; i++) {
734
 
        if(!section_hdr[i].SizeOfRawData && section_hdr[i].VirtualSize && section_hdr[i + 1].SizeOfRawData && section_hdr[i + 1].VirtualSize) {
735
 
            found = 1;
736
 
            cli_dbgmsg("UPX/FSG: empty section found - assuming compression\n");
737
 
            break;
738
 
        }
739
 
    }
740
 
 
741
 
    if(found) {
742
 
 
743
 
        /* Check EP for UPX vs. FSG */
744
 
        if(lseek(desc, ep, SEEK_SET) == -1) {
745
 
            cli_dbgmsg("UPX/FSG: lseek() failed\n");
746
 
            free(section_hdr);
747
 
            return CL_EIO;
748
 
        }
749
 
 
750
 
        if(read(desc, buff, 168) != 168) {
751
 
            cli_dbgmsg("UPX/FSG: Can't read 168 bytes at 0x%x (%d)\n", ep, ep);
752
 
            cli_dbgmsg("UPX/FSG: Broken or not UPX/FSG compressed file\n");
753
 
            free(section_hdr);
754
 
            return CL_CLEAN;
755
 
        }
756
 
 
757
 
        if(buff[0] == '\x87' && buff[1] == '\x25') {
758
 
 
759
 
            /* FSG v2.0 support - thanks to aCaB ! */
760
 
 
761
 
            ssize = EC32(section_hdr[i + 1].SizeOfRawData);
762
 
            dsize = EC32(section_hdr[i].VirtualSize);
763
 
 
764
 
            while(found) {
765
 
                    uint32_t newesi, newedi, newebx, newedx;
766
 
 
767
 
                if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
768
 
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
769
 
                    free(section_hdr);
770
 
                    if(BLOCKMAX) {
771
 
                        *ctx->virname = "PE.FSG.ExceededFileSize";
772
 
                        return CL_VIRUS;
773
 
                    } else {
774
 
                        return CL_CLEAN;
775
 
                    }
776
 
                }
777
 
 
778
 
                if(ssize <= 0x19 || dsize <= ssize) {
779
 
                    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
780
 
                    free(section_hdr);
781
 
                    return CL_CLEAN;
782
 
                }
783
 
 
784
 
                if((newedx = cli_readint32(buff + 2) - EC32(optional_hdr32.ImageBase)) < EC32(section_hdr[i + 1].VirtualAddress) || newedx >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 4) {
785
 
                    cli_dbgmsg("FSG: xchg out of bounds (%x), giving up\n", newedx);
786
 
                    break;
787
 
                }
788
 
 
789
 
                if((src = (char *) cli_malloc(ssize)) == NULL) {
790
 
                    free(section_hdr);
791
 
                    return CL_EMEM;
792
 
                }
793
 
 
794
 
                lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET);
795
 
                if((unsigned int) read(desc, src, ssize) != ssize) {
796
 
                    cli_dbgmsg("Can't read raw data of section %d\n", i);
797
 
                    free(section_hdr);
798
 
                    free(src);
799
 
                    return CL_EIO;
800
 
                }
801
 
 
802
 
                if(newedx < EC32(section_hdr[i + 1].VirtualAddress) || ((dest = src + newedx - EC32(section_hdr[i + 1].VirtualAddress)) < src && dest >= src + EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 4)) {
803
 
                    cli_dbgmsg("FSG: New ESP out of bounds\n");
804
 
                    free(src);
805
 
                    break;
806
 
                }
807
 
 
808
 
                if((newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase)) <= EC32(section_hdr[i + 1].VirtualAddress) || newedx >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 4) {
809
 
                    cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx);
810
 
                    free(src);
811
 
                    break;
812
 
                }
813
 
 
814
 
                if((dest = src + newedx - EC32(section_hdr[i + 1].VirtualAddress)) < src || dest >= src + EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 32) {
815
 
                    cli_dbgmsg("FSG: New stack out of bounds\n");
816
 
                    free(src);
817
 
                    break;
818
 
                }
819
 
 
820
 
                newedi = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
821
 
                newesi = cli_readint32(dest + 4) - EC32(optional_hdr32.ImageBase);
822
 
                newebx = cli_readint32(dest + 16) - EC32(optional_hdr32.ImageBase);
823
 
                newedx = cli_readint32(dest + 20);
824
 
 
825
 
                if(newedi != EC32(section_hdr[i].VirtualAddress)) {
826
 
                    cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, EC32(section_hdr[i].VirtualAddress));
827
 
                    free(src);
828
 
                    break;
829
 
                }
830
 
 
831
 
                if(newesi < EC32(section_hdr[i + 1].VirtualAddress) || newesi >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData)) {
832
 
                    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
833
 
                    free(src);
834
 
                    break;
835
 
                }
836
 
 
837
 
                if(newebx < EC32(section_hdr[i + 1].VirtualAddress) || newebx >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData) - 16) {
838
 
                    cli_dbgmsg("FSG: Array of functions out of bounds\n");
839
 
                    free(src);
840
 
                    break;
841
 
                }
842
 
 
843
 
                newedx=cli_readint32(newebx + 12 - EC32(section_hdr[i + 1].VirtualAddress) + src) - EC32(optional_hdr32.ImageBase);
844
 
                cli_dbgmsg("FSG: found old EP @%x\n",newedx);
845
 
 
846
 
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
847
 
                    free(section_hdr);
848
 
                    free(src);
849
 
                    return CL_EMEM;
850
 
                }
851
 
 
852
 
                if(!(tempfile = cli_gentemp(NULL)))
853
 
                    return CL_EMEM;
854
 
 
855
 
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
856
 
                    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
857
 
                    free(tempfile);
858
 
                    free(section_hdr);
859
 
                    free(src);
860
 
                    free(dest);
861
 
                    return CL_EIO;
862
 
                }
863
 
                
864
 
                switch (unfsg_200(newesi - EC32(section_hdr[i + 1].VirtualAddress) + src, dest, ssize + EC32(section_hdr[i + 1].VirtualAddress) - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)) {
865
 
                    case 1: /* Everything OK */
866
 
                        cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
867
 
                        free(src);
868
 
                        free(dest);
869
 
                        fsync(ndesc);
870
 
                        lseek(ndesc, 0, SEEK_SET);
871
 
 
872
 
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
873
 
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
874
 
                            free(section_hdr);
875
 
                            close(ndesc);
876
 
                            if(!cli_leavetemps_flag)
877
 
                                unlink(tempfile);
878
 
                            free(tempfile);
879
 
                            return CL_VIRUS;
880
 
                        }
881
 
 
882
 
                        close(ndesc);
883
 
                        if(!cli_leavetemps_flag)
884
 
                            unlink(tempfile);
885
 
                        free(tempfile);
886
 
                        free(section_hdr);
887
 
                        return CL_CLEAN;
888
 
 
889
 
                    case 0: /* We've got an unpacked buffer, no exe though */
890
 
                        cli_dbgmsg("FSG: FSG: Successfully decompressed\n");
891
 
                        close(ndesc);
892
 
                        unlink(tempfile);
893
 
                        free(tempfile);
894
 
                        found = 0;
895
 
                        upx_success = 1;
896
 
                        break; /* Go and scan the buffer! */
897
 
 
898
 
                    default: /* Everything gone wrong */
899
 
                        cli_dbgmsg("FSG: Unpacking failed\n");
900
 
                        close(ndesc);
901
 
                        unlink(tempfile); // It's empty anyway
902
 
                        free(tempfile);
903
 
                        free(src);
904
 
                        free(dest);
905
 
                        break;
906
 
                }
907
 
 
908
 
                break; /* were done with 2 */
909
 
            }
910
 
        }
911
 
 
912
 
        if(found && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) < min) {
913
 
 
914
 
            /* FSG support - v. 1.33 (thx trog for the many samples) */
915
 
 
916
 
            ssize = EC32(section_hdr[i + 1].SizeOfRawData);
917
 
            dsize = EC32(section_hdr[i].VirtualSize);
918
 
 
919
 
            while(found) {
920
 
                    int gp, t, sectcnt = 0;
921
 
                    char *support;
922
 
                    uint32_t newesi, newedi, newebx, oldep;
923
 
                    struct SECTION *sections;
924
 
 
925
 
 
926
 
                if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
927
 
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, ctx->limits->maxfilesize);
928
 
                    free(section_hdr);
929
 
                    if(BLOCKMAX) {
930
 
                        *ctx->virname = "PE.FSG.ExceededFileSize";
931
 
                        return CL_VIRUS;
932
 
                    } else {
933
 
                        return CL_CLEAN;
934
 
                    }
935
 
                }
936
 
 
937
 
                if(ssize <= 0x19 || dsize <= ssize) {
938
 
                    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
939
 
                    free(section_hdr);
940
 
                    return CL_CLEAN;
941
 
                }
942
 
 
943
 
                if((gp = cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase)) >= (int) EC32(section_hdr[i + 1].PointerToRawData) || gp < 0) {
944
 
                    cli_dbgmsg("FSG: Support data out of padding area (vaddr: %d)\n", EC32(section_hdr[i].VirtualAddress));
945
 
                    break;
946
 
                }
947
 
 
948
 
                lseek(desc, gp, SEEK_SET);
949
 
                gp = EC32(section_hdr[i + 1].PointerToRawData) - gp;
950
 
 
951
 
                if(ctx->limits && ctx->limits->maxfilesize && (unsigned int) gp > ctx->limits->maxfilesize) {
952
 
                    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, ctx->limits->maxfilesize);
953
 
                    free(section_hdr);
954
 
                    if(BLOCKMAX) {
955
 
                        *ctx->virname = "PE.FSG.ExceededFileSize";
956
 
                        return CL_VIRUS;
957
 
                    } else {
958
 
                        return CL_CLEAN;
959
 
                    }
960
 
                }
961
 
 
962
 
                if((support = (char *) cli_malloc(gp)) == NULL) {
963
 
                    free(section_hdr);
964
 
                    return CL_EMEM;
965
 
                }
966
 
 
967
 
                if(read(desc, support, gp) != gp) {
968
 
                    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
969
 
                    free(section_hdr);
970
 
                    free(support);
971
 
                    return CL_EIO;
972
 
                }
973
 
 
974
 
                newebx = cli_readint32(support) - EC32(optional_hdr32.ImageBase); /* Unused */
975
 
                newedi = cli_readint32(support + 4) - EC32(optional_hdr32.ImageBase); /* 1st dest */
976
 
                newesi = cli_readint32(support + 8) - EC32(optional_hdr32.ImageBase); /* Source */
977
 
 
978
 
                if(newesi < EC32(section_hdr[i + 1].VirtualAddress) || newesi >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData)) {
979
 
                    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
980
 
                    free(support);
981
 
                    break;
982
 
                }
983
 
 
984
 
                if(newedi != EC32(section_hdr[i].VirtualAddress)) {
985
 
                    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, EC32(section_hdr[i].VirtualAddress));
986
 
                    free(support);
987
 
                    break;
988
 
                }
989
 
 
990
 
                /* Counting original sections */
991
 
                for(t = 12; t < gp - 4; t += 4) {
992
 
                        uint32_t rva = cli_readint32(support+t);
993
 
 
994
 
                    if(!rva)
995
 
                        break;
996
 
 
997
 
                    rva -= EC32(optional_hdr32.ImageBase)+1;
998
 
                    sectcnt++;
999
 
 
1000
 
                    if(rva % 0x1000)
1001
 
                        /* FIXME: really need to bother? */
1002
 
                        cli_dbgmsg("FSG: Original section %d is misaligned\n", sectcnt);
1003
 
 
1004
 
                    if(rva < EC32(section_hdr[i].VirtualAddress) || rva >= EC32(section_hdr[i].VirtualAddress)+EC32(section_hdr[i].VirtualSize)) {
1005
 
                        cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
1006
 
                        break;
1007
 
                    }
1008
 
                }
1009
 
 
1010
 
                if(t >= gp - 4 || cli_readint32(support + t)) {
1011
 
                    free(support);
1012
 
                    break;
1013
 
                }
1014
 
 
1015
 
                if((sections = (struct SECTION *) cli_malloc((sectcnt + 1) * sizeof(struct SECTION))) == NULL) {
1016
 
                    free(section_hdr);
1017
 
                    free(support);
1018
 
                    return CL_EMEM;
1019
 
                }
1020
 
 
1021
 
                sections[0].rva = newedi;
1022
 
                for(t = 1; t <= sectcnt; t++)
1023
 
                    sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 -EC32(optional_hdr32.ImageBase);
1024
 
 
1025
 
                free(support);
1026
 
 
1027
 
                if((src = (char *) cli_malloc(ssize)) == NULL) {
1028
 
                    free(section_hdr);
1029
 
                    free(sections);
1030
 
                    return CL_EMEM;
1031
 
                }
1032
 
 
1033
 
                lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET);
1034
 
                if((unsigned int) read(desc, src, ssize) != ssize) {
1035
 
                    cli_dbgmsg("Can't read raw data of section %d\n", i);
1036
 
                    free(section_hdr);
1037
 
                    free(sections);
1038
 
                    free(src);
1039
 
                    return CL_EIO;
1040
 
                }
1041
 
 
1042
 
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1043
 
                    free(section_hdr);
1044
 
                    free(src);
1045
 
                    free(sections);
1046
 
                    return CL_EMEM;
1047
 
                }
1048
 
 
1049
 
                oldep = EC32(optional_hdr32.AddressOfEntryPoint) + 161 + 6 + cli_readint32(buff+163);
1050
 
                cli_dbgmsg("FSG: found old EP @%x\n", oldep);
1051
 
 
1052
 
                if(!(tempfile = cli_gentemp(NULL)))
1053
 
                    return CL_EMEM;
1054
 
 
1055
 
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1056
 
                    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
1057
 
                    free(tempfile);
1058
 
                    free(section_hdr);
1059
 
                    free(src);
1060
 
                    free(dest);
1061
 
                    free(sections);
1062
 
                    return CL_EIO;
1063
 
                }
1064
 
 
1065
 
                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)) {
1066
 
                    case 1: /* Everything OK */
1067
 
                        cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
1068
 
                        free(src);
1069
 
                        free(dest);
1070
 
                        free(sections);
1071
 
                        fsync(ndesc);
1072
 
                        lseek(ndesc, 0, SEEK_SET);
1073
 
 
1074
 
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
1075
 
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
1076
 
                            free(section_hdr);
1077
 
                            close(ndesc);
1078
 
                            if(!cli_leavetemps_flag)
1079
 
                                unlink(tempfile);
1080
 
                            free(tempfile);
1081
 
                            return CL_VIRUS;
1082
 
                        }
1083
 
 
1084
 
                        close(ndesc);
1085
 
                        if(!cli_leavetemps_flag)
1086
 
                            unlink(tempfile);
1087
 
                        free(tempfile);
1088
 
                        free(section_hdr);
1089
 
                        return CL_CLEAN;
1090
 
 
1091
 
                    case 0: /* We've got an unpacked buffer, no exe though */
1092
 
                        cli_dbgmsg("FSG: FSG: Successfully decompressed\n");
1093
 
                        close(ndesc);
1094
 
                        unlink(tempfile);
1095
 
                        free(tempfile);
1096
 
                        free(sections);
1097
 
                        found = 0;
1098
 
                        upx_success = 1;
1099
 
                        break; /* Go and scan the buffer! */
1100
 
 
1101
 
                    default: /* Everything gone wrong */
1102
 
                        cli_dbgmsg("FSG: Unpacking failed\n");
1103
 
                        close(ndesc);
1104
 
                        unlink(tempfile); // It's empty anyway
1105
 
                        free(tempfile);
1106
 
                        free(src);
1107
 
                        free(dest);
1108
 
                        free(sections);
1109
 
                        break;
1110
 
                }
1111
 
 
1112
 
                break; /* were done with 1.33 */
1113
 
            }
1114
 
        }
1115
 
 
1116
 
        /* FIXME: easy 2 hack */
1117
 
        if(found && buff[0] == '\xbb' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) < min && buff[5] == '\xbf' && buff[10] == '\xbe') {
1118
 
 
1119
 
            /* FSG support - v. 1.31 */
1120
 
 
1121
 
            ssize = EC32(section_hdr[i + 1].SizeOfRawData);
1122
 
            dsize = EC32(section_hdr[i].VirtualSize);
1123
 
 
1124
 
            while(found) {
1125
 
                    int gp = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase), t, sectcnt = 0;
1126
 
                    char *support;
1127
 
                    uint32_t newesi = cli_readint32(buff+11) - EC32(optional_hdr32.ImageBase);
1128
 
                    uint32_t newedi = cli_readint32(buff+6) - EC32(optional_hdr32.ImageBase);
1129
 
                    uint32_t oldep = EC32(optional_hdr32.AddressOfEntryPoint);
1130
 
                    struct SECTION *sections;
1131
 
 
1132
 
                if (oldep <= EC32(section_hdr[i + 1].VirtualAddress) || oldep > EC32(section_hdr[i + 1].VirtualAddress)+EC32(section_hdr[i + 1].SizeOfRawData) - 0xe0) {
1133
 
                  cli_dbgmsg("FSG: EP not in section %d\n", i+1);
1134
 
                  break;
1135
 
                }
1136
 
                oldep -= EC32(section_hdr[i + 1].VirtualAddress);
1137
 
 
1138
 
                if(newesi < EC32(section_hdr[i + 1].VirtualAddress) || newesi >= EC32(section_hdr[i + 1].VirtualAddress) + EC32(section_hdr[i + 1].SizeOfRawData)) {
1139
 
                    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
1140
 
                    break;
1141
 
                }
1142
 
 
1143
 
                if(newedi != EC32(section_hdr[i].VirtualAddress)) {
1144
 
                    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, EC32(section_hdr[i].VirtualAddress));
1145
 
                    break;
1146
 
                }
1147
 
 
1148
 
                if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
1149
 
                    cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, ctx->limits->maxfilesize);
1150
 
                    free(section_hdr);
1151
 
                    if(BLOCKMAX) {
1152
 
                        *ctx->virname = "PE.FSG.ExceededFileSize";
1153
 
                        return CL_VIRUS;
1154
 
                    } else {
1155
 
                        return CL_CLEAN;
1156
 
                    }
1157
 
                }
1158
 
 
1159
 
                if(ssize <= 0x19 || dsize <= ssize) {
1160
 
                    cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
1161
 
                    free(section_hdr);
1162
 
                    return CL_CLEAN;
1163
 
                }
1164
 
 
1165
 
                if(gp >= (int) EC32(section_hdr[i + 1].PointerToRawData) || gp < 0) {
1166
 
                    cli_dbgmsg("FSG: Support data out of padding area (newedi: %d, vaddr: %d)\n", newedi, EC32(section_hdr[i].VirtualAddress));
1167
 
                    break;
1168
 
                }
1169
 
 
1170
 
                lseek(desc, gp, SEEK_SET);
1171
 
                gp = EC32(section_hdr[i + 1].PointerToRawData) - gp;
1172
 
 
1173
 
                if(ctx->limits && ctx->limits->maxfilesize && (unsigned int) gp > ctx->limits->maxfilesize) {
1174
 
                    cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, ctx->limits->maxfilesize);
1175
 
                    free(section_hdr);
1176
 
                    if(BLOCKMAX) {
1177
 
                        *ctx->virname = "PE.FSG.ExceededFileSize";
1178
 
                        return CL_VIRUS;
1179
 
                    } else {
1180
 
                        return CL_CLEAN;
1181
 
                    }
1182
 
                }
1183
 
 
1184
 
                if((support = (char *) cli_malloc(gp)) == NULL) {
1185
 
                    free(section_hdr);
1186
 
                    return CL_EMEM;
1187
 
                }
1188
 
 
1189
 
                if(read(desc, support, gp) != gp) {
1190
 
                    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
1191
 
                    free(section_hdr);
1192
 
                    free(support);
1193
 
                    return CL_EIO;
1194
 
                }
1195
 
 
1196
 
                /* Counting original sections */
1197
 
                for(t = 0; t < gp - 2; t += 2) {
1198
 
                  uint32_t rva = support[t]+256*support[t+1];
1199
 
                  
1200
 
                  if (rva == 2 || rva == 1)
1201
 
                    break;
1202
 
 
1203
 
                  rva = ((rva-2)<<12) - EC32(optional_hdr32.ImageBase);
1204
 
                  sectcnt++;
1205
 
 
1206
 
                  if(rva < EC32(section_hdr[i].VirtualAddress) || rva >= EC32(section_hdr[i].VirtualAddress)+EC32(section_hdr[i].VirtualSize)) {
1207
 
                    cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt);
1208
 
                    break;
1209
 
                  }
1210
 
                }
1211
 
 
1212
 
                if(t >= gp-10 || cli_readint32(support + t + 6) != 2) {
1213
 
                    free(support);
1214
 
                    break;
1215
 
                }
1216
 
 
1217
 
                if((sections = (struct SECTION *) cli_malloc((sectcnt + 1) * sizeof(struct SECTION))) == NULL) {
1218
 
                    free(section_hdr);
1219
 
                    free(support);
1220
 
                    return CL_EMEM;
1221
 
                }
1222
 
 
1223
 
                sections[0].rva = newedi;
1224
 
                for(t = 0; t <= sectcnt - 1; t++) {
1225
 
                  sections[t+1].rva = (((support[t*2]+256*support[t*2+1])-2)<<12)-EC32(optional_hdr32.ImageBase);
1226
 
                }
1227
 
 
1228
 
                free(support);
1229
 
 
1230
 
                if((src = (char *) cli_malloc(ssize)) == NULL) {
1231
 
                    free(section_hdr);
1232
 
                    free(sections);
1233
 
                    return CL_EMEM;
1234
 
                }
1235
 
 
1236
 
                lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET);
1237
 
                if((unsigned int) read(desc, src, ssize) != ssize) {
1238
 
                    cli_dbgmsg("Can't read raw data of section %d\n", i);
1239
 
                    free(section_hdr);
1240
 
                    free(sections);
1241
 
                    free(src);
1242
 
                    return CL_EIO;
1243
 
                }
1244
 
 
1245
 
                if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1246
 
                    free(section_hdr);
1247
 
                    free(src);
1248
 
                    free(sections);
1249
 
                    return CL_EMEM;
1250
 
                }
1251
 
 
1252
 
                /* Better not increasing buff size any further, let's go the hard way */
1253
 
                gp = 0xda + 6*(buff[16]=='\xe8');
1254
 
                oldep = EC32(optional_hdr32.AddressOfEntryPoint) + gp + 6 + cli_readint32(src+gp+2+oldep);
1255
 
                cli_dbgmsg("FSG: found old EP @%x\n", oldep);
1256
 
 
1257
 
                if(!(tempfile = cli_gentemp(NULL)))
1258
 
                    return CL_EMEM;
1259
 
 
1260
 
                if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1261
 
                    cli_dbgmsg("FSG: Can't create file %s\n", tempfile);
1262
 
                    free(tempfile);
1263
 
                    free(section_hdr);
1264
 
                    free(src);
1265
 
                    free(dest);
1266
 
                    free(sections);
1267
 
                    return CL_EIO;
1268
 
                }
1269
 
 
1270
 
                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)) {
1271
 
                    case 1: /* Everything OK */
1272
 
                        cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile);
1273
 
                        free(src);
1274
 
                        free(dest);
1275
 
                        free(sections);
1276
 
                        fsync(ndesc);
1277
 
                        lseek(ndesc, 0, SEEK_SET);
1278
 
 
1279
 
                        cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
1280
 
                        if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
1281
 
                            free(section_hdr);
1282
 
                            close(ndesc);
1283
 
                            if(!cli_leavetemps_flag)
1284
 
                                unlink(tempfile);
1285
 
                            free(tempfile);
1286
 
                            return CL_VIRUS;
1287
 
                        }
1288
 
 
1289
 
                        close(ndesc);
1290
 
                        if(!cli_leavetemps_flag)
1291
 
                            unlink(tempfile);
1292
 
                        free(tempfile);
1293
 
                        free(section_hdr);
1294
 
                        return CL_CLEAN;
1295
 
 
1296
 
                    case 0: /* We've got an unpacked buffer, no exe though */
1297
 
                        cli_dbgmsg("FSG: FSG: Successfully decompressed\n");
1298
 
                        close(ndesc);
1299
 
                        unlink(tempfile);
1300
 
                        free(tempfile);
1301
 
                        free(sections);
1302
 
                        found = 0;
1303
 
                        upx_success = 1;
1304
 
                        break; /* Go and scan the buffer! */
1305
 
 
1306
 
                    default: /* Everything gone wrong */
1307
 
                        cli_dbgmsg("FSG: Unpacking failed\n");
1308
 
                        close(ndesc);
1309
 
                        unlink(tempfile); // It's empty anyway
1310
 
                        free(tempfile);
1311
 
                        free(src);
1312
 
                        free(dest);
1313
 
                        free(sections);
1314
 
                        break;
1315
 
                }
1316
 
 
1317
 
                break; /* were done with 1.31 */
1318
 
            }
1319
 
        }
1320
 
 
1321
 
 
1322
 
        if(found) {
1323
 
 
1324
 
            /* UPX support */
1325
 
 
1326
 
            strncpy(sname, section_hdr[i].Name, 8);
1327
 
            sname[8] = 0;
1328
 
            cli_dbgmsg("UPX: Section %d name: %s\n", i, sname);
1329
 
            strncpy(sname, section_hdr[i + 1].Name, 8);
1330
 
            sname[8] = 0;
1331
 
            cli_dbgmsg("UPX: Section %d name: %s\n", i + 1, sname);
1332
 
 
1333
 
            if(strncmp(section_hdr[i].Name, "UPX0", 4) || strncmp(section_hdr[i + 1].Name, "UPX1", 4))
1334
 
                cli_dbgmsg("UPX: Possibly hacked UPX section headers\n");
1335
 
 
1336
 
            /* we assume (i + 1) is UPX1 */
1337
 
            ssize = EC32(section_hdr[i + 1].SizeOfRawData);
1338
 
            dsize = EC32(section_hdr[i].VirtualSize) + EC32(section_hdr[i + 1].VirtualSize);
1339
 
 
1340
 
            if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) {
1341
 
                cli_dbgmsg("UPX: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize);
1342
 
                free(section_hdr);
1343
 
                if(BLOCKMAX) {
1344
 
                    *ctx->virname = "PE.UPX.ExceededFileSize";
1345
 
                    return CL_VIRUS;
1346
 
                } else {
1347
 
                    return CL_CLEAN;
1348
 
                }
1349
 
            }
1350
 
 
1351
 
            if(ssize <= 0x19 || dsize <= ssize) { /* FIXME: What are reasonable values? */
1352
 
                cli_dbgmsg("UPX: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
1353
 
                free(section_hdr);
1354
 
                return CL_CLEAN;
1355
 
            }
1356
 
 
1357
 
            /* FIXME: use file operations in case of big files */
1358
 
            if((src = (char *) cli_malloc(ssize)) == NULL) {
1359
 
                free(section_hdr);
1360
 
                return CL_EMEM;
1361
 
            }
1362
 
 
1363
 
            if(dsize > CLI_MAX_ALLOCATION) {
1364
 
                cli_errmsg("UPX: Too big value of dsize\n");
1365
 
                free(section_hdr);
1366
 
                free(src);
1367
 
                return CL_EMEM;
1368
 
            }
1369
 
 
1370
 
            if((dest = (char *) cli_calloc(dsize + 1024 + nsections * 40, sizeof(char))) == NULL) {
1371
 
                free(section_hdr);
1372
 
                free(src);
1373
 
                return CL_EMEM;
1374
 
            }
1375
 
 
1376
 
            lseek(desc, EC32(section_hdr[i + 1].PointerToRawData), SEEK_SET);
1377
 
            if((unsigned int) read(desc, src, ssize) != ssize) {
1378
 
                cli_dbgmsg("Can't read raw data of section %d\n", i);
1379
 
                free(section_hdr);
1380
 
                free(src);
1381
 
                free(dest);
1382
 
                return CL_EIO;
1383
 
            }
1384
 
 
1385
 
            /* try to detect UPX code */
1386
 
 
1387
 
            if(lseek(desc, ep, SEEK_SET) == -1) {
1388
 
                cli_dbgmsg("lseek() failed\n");
1389
 
                free(section_hdr);
1390
 
                free(src);
1391
 
                free(dest);
1392
 
                return CL_EIO;
1393
 
            }
1394
 
 
1395
 
            if(read(desc, buff, 126) != 126) { /* i.e. 0x69 + 13 + 8 */
1396
 
                cli_dbgmsg("UPX: Can't read 126 bytes at 0x%x (%d)\n", ep, ep);
1397
 
                cli_dbgmsg("UPX/FSG: Broken or not UPX/FSG compressed file\n");
1398
 
                free(section_hdr);
1399
 
                free(src);
1400
 
                free(dest);
1401
 
                return CL_CLEAN;
1402
 
            } else {
1403
 
                if(cli_memstr(UPX_NRV2B, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, buff + 0x69 + 8, 13)) {
1404
 
                    cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
1405
 
                    upxfn = upx_inflate2b;
1406
 
                } else if(cli_memstr(UPX_NRV2D, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2D, 24, buff + 0x69 + 8, 13)) {
1407
 
                    cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n");
1408
 
                    upxfn = upx_inflate2d;
1409
 
                } else if(cli_memstr(UPX_NRV2E, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2E, 24, buff + 0x69 + 8, 13)) {
1410
 
                    cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n");
1411
 
                    upxfn = upx_inflate2e;
1412
 
                }
1413
 
            }
1414
 
 
1415
 
            if(upxfn) {
1416
 
                    int skew = cli_readint32(buff + 2) - EC32(optional_hdr32.ImageBase) - EC32(section_hdr[i + 1].VirtualAddress);
1417
 
 
1418
 
                if(buff[1] != '\xbe' || skew <= 0 || skew > 0xfff) { /* FIXME: legit skews?? */
1419
 
                    skew = 0; 
1420
 
                    if(upxfn(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint)) >= 0)
1421
 
                        upx_success = 1;
1422
 
 
1423
 
                } else {
1424
 
                    cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew);
1425
 
                    if(upxfn(src + skew, ssize - skew, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint)-skew) >= 0 || upxfn(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint)) >= 0)
1426
 
                        upx_success = 1;
1427
 
                }
1428
 
 
1429
 
                if(upx_success)
1430
 
                    cli_dbgmsg("UPX: Successfully decompressed\n");
1431
 
                else
1432
 
                    cli_dbgmsg("UPX: Prefered decompressor failed\n");
1433
 
            }
1434
 
 
1435
 
            if(!upx_success && upxfn != upx_inflate2b) {
1436
 
                if(upx_inflate2b(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint)) == -1 && upx_inflate2b(src + 0x15, ssize - 0x15, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint) - 0x15) == -1) {
1437
 
 
1438
 
                    cli_dbgmsg("UPX: NRV2B decompressor failed\n");
1439
 
                } else {
1440
 
                    upx_success = 1;
1441
 
                    cli_dbgmsg("UPX: Successfully decompressed with NRV2B\n");
1442
 
                }
1443
 
            }
1444
 
 
1445
 
            if(!upx_success && upxfn != upx_inflate2d) {
1446
 
                if(upx_inflate2d(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint)) == -1 && upx_inflate2d(src + 0x15, ssize - 0x15, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint) - 0x15) == -1) {
1447
 
 
1448
 
                    cli_dbgmsg("UPX: NRV2D decompressor failed\n");
1449
 
                } else {
1450
 
                    upx_success = 1;
1451
 
                    cli_dbgmsg("UPX: Successfully decompressed with NRV2D\n");
1452
 
                }
1453
 
            }
1454
 
 
1455
 
            if(!upx_success && upxfn != upx_inflate2e) {
1456
 
                if(upx_inflate2e(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint)) == -1 && upx_inflate2e(src + 0x15, ssize - 0x15, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr32.AddressOfEntryPoint) - 0x15) == -1) {
1457
 
                    cli_dbgmsg("UPX: NRV2E decompressor failed\n");
1458
 
                } else {
1459
 
                    upx_success = 1;
1460
 
                    cli_dbgmsg("UPX: Successfully decompressed with NRV2E\n");
1461
 
                }
1462
 
            }
1463
 
 
1464
 
            if(!upx_success) {
1465
 
                cli_dbgmsg("UPX: All decompressors failed\n");
1466
 
                free(src);
1467
 
                free(dest);
1468
 
            }
1469
 
        }
1470
 
 
1471
 
        if(upx_success) {
1472
 
            free(src);
1473
 
            free(section_hdr);
1474
 
 
1475
 
            if(!(tempfile = cli_gentemp(NULL)))
1476
 
                return CL_EMEM;
1477
 
 
1478
 
            if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1479
 
                cli_dbgmsg("UPX/FSG: Can't create file %s\n", tempfile);
1480
 
                free(tempfile);
1481
 
                free(dest);
1482
 
                return CL_EIO;
1483
 
            }
1484
 
 
1485
 
            if((unsigned int) write(ndesc, dest, dsize) != dsize) {
1486
 
                cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize);
1487
 
                free(tempfile);
1488
 
                free(dest);
1489
 
                close(ndesc);
1490
 
                return CL_EIO;
1491
 
            }
1492
 
 
1493
 
            free(dest);
1494
 
            fsync(ndesc);
1495
 
            lseek(ndesc, 0, SEEK_SET);
1496
 
 
1497
 
            if(cli_leavetemps_flag)
1498
 
                cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile);
1499
 
 
1500
 
            cli_dbgmsg("***** Scanning decompressed file *****\n");
1501
 
            if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS) {
1502
 
                close(ndesc);
1503
 
                if(!cli_leavetemps_flag)
1504
 
                    unlink(tempfile);
1505
 
                free(tempfile);
1506
 
                return CL_VIRUS;
1507
 
            }
1508
 
 
1509
 
            close(ndesc);
1510
 
            if(!cli_leavetemps_flag)
1511
 
                unlink(tempfile);
1512
 
            free(tempfile);
1513
 
            return ret;
1514
 
        }
1515
 
    }
1516
 
 
1517
 
    /* Petite */
1518
 
 
1519
 
    found = 2;
1520
 
 
1521
 
    lseek(desc, ep, SEEK_SET);
1522
 
    if(read(desc, buff, 200) != 200) {
1523
 
        cli_dbgmsg("Can't read 200 bytes\n");
1524
 
        free(section_hdr);
1525
 
        return CL_EIO;
1526
 
    }
1527
 
 
1528
 
    if(buff[0] != '\xb8' || (uint32_t) cli_readint32(buff + 1) != EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(optional_hdr32.ImageBase)) {
1529
 
        if(nsections < 2 || buff[0] != '\xb8' || (uint32_t) cli_readint32(buff + 1) != EC32(section_hdr[nsections - 2].VirtualAddress) + EC32(optional_hdr32.ImageBase))
1530
 
            found = 0;
1531
 
        else
1532
 
            found = 1;
1533
 
    }
1534
 
 
1535
 
    if(found) {
1536
 
        cli_dbgmsg("Petite: v2.%d compression detected\n", found);
1537
 
 
1538
 
        if(cli_readint32(buff + 0x80) == 0x163c988d) {
1539
 
            cli_dbgmsg("Petite: level zero compression is not supported yet\n");
1540
 
        } else {
1541
 
            dsize = max - min;
1542
 
 
1543
 
            if(ctx->limits && ctx->limits->maxfilesize && dsize > ctx->limits->maxfilesize) {
1544
 
                cli_dbgmsg("Petite: Size exceeded (dsize: %u, max: %lu)\n", dsize, ctx->limits->maxfilesize);
1545
 
                free(section_hdr);
1546
 
                if(BLOCKMAX) {
1547
 
                    *ctx->virname = "PE.Petite.ExceededFileSize";
1548
 
                    return CL_VIRUS;
1549
 
                } else {
1550
 
                    return CL_CLEAN;
1551
 
                }
1552
 
            }
1553
 
 
1554
 
            if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
1555
 
                cli_dbgmsg("Petite: Can't allocate %d bytes\n", dsize);
1556
 
                free(section_hdr);
1557
 
                return CL_EMEM;
1558
 
            }
1559
 
 
1560
 
            for(i = 0 ; i < nsections; i++) {
1561
 
                if(section_hdr[i].SizeOfRawData) {
1562
 
                        uint32_t offset = cli_rawaddr(EC32(section_hdr[i].VirtualAddress), section_hdr, nsections, &err);
1563
 
 
1564
 
                    if(err || lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) read(desc, dest + EC32(section_hdr[i].VirtualAddress) - min, EC32(section_hdr[i].SizeOfRawData)) != EC32(section_hdr[i].SizeOfRawData)) {
1565
 
                        free(section_hdr);
1566
 
                        free(dest);
1567
 
                        return CL_EIO;
1568
 
                    }
1569
 
                }
1570
 
            }
1571
 
 
1572
 
            if(!(tempfile = cli_gentemp(NULL)))
1573
 
                return CL_EMEM;
1574
 
 
1575
 
            if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1576
 
                cli_dbgmsg("Petite: Can't create file %s\n", tempfile);
1577
 
                free(tempfile);
1578
 
                free(section_hdr);
1579
 
                free(dest);
1580
 
                return CL_EIO;
1581
 
            }
1582
 
 
1583
 
            /* aCaB: Fixed to allow petite v2.1 unpacking (last section is a ghost) */
1584
 
            switch(petite_inflate2x_1to9(dest, min, max - min, section_hdr,
1585
 
                    nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase),
1586
 
                    EC32(optional_hdr32.AddressOfEntryPoint), ndesc,
1587
 
                    found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress),
1588
 
                    EC32(optional_hdr32.DataDirectory[2].Size))) {
1589
 
                case 1:
1590
 
                    cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile);
1591
 
                    cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
1592
 
                    break;
1593
 
 
1594
 
                case 0:
1595
 
                    cli_dbgmsg("Petite: Unpacked data saved in %s\n", tempfile);
1596
 
                    break;
1597
 
 
1598
 
                default:
1599
 
                    cli_dbgmsg("Petite: Unpacking failed\n");
1600
 
            }
1601
 
 
1602
 
            free(dest);
1603
 
            fsync(ndesc);
1604
 
            lseek(ndesc, 0, SEEK_SET);
1605
 
 
1606
 
            if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
1607
 
                free(section_hdr);
1608
 
                close(ndesc);
1609
 
                if(!cli_leavetemps_flag) {
1610
 
                    unlink(tempfile);
1611
 
                    free(tempfile);
1612
 
                } else {
1613
 
                    free(tempfile);
1614
 
                }
1615
 
                return CL_VIRUS;
1616
 
            }
1617
 
 
1618
 
            close(ndesc);
1619
 
 
1620
 
            if(!cli_leavetemps_flag) {
1621
 
                unlink(tempfile);
1622
 
                free(tempfile);
1623
 
            } else {
1624
 
                free(tempfile);
1625
 
            }
1626
 
        }
1627
 
    }
1628
 
 
1629
 
    /* PESpin 1.1 */
1630
 
 
1631
 
    if(nsections > 1 &&
1632
 
       EC32(optional_hdr32.AddressOfEntryPoint) >= EC32(section_hdr[nsections - 1].VirtualAddress) &&
1633
 
       EC32(optional_hdr32.AddressOfEntryPoint) < EC32(section_hdr[nsections - 1].VirtualAddress) + EC32(section_hdr[nsections - 1].SizeOfRawData) - 0x3217 - 4 &&
1634
 
       memcmp(buff+4, "\xe8\x00\x00\x00\x00\x8b\x1c\x24\x83\xc3", 10) == 0)  {
1635
 
 
1636
 
            char *spinned;
1637
 
 
1638
 
        if((spinned = (char *) cli_malloc(fsize)) == NULL) {
1639
 
            free(section_hdr);
1640
 
            return CL_EMEM;
1641
 
        }
1642
 
 
1643
 
        lseek(desc, 0, SEEK_SET);
1644
 
        if(read(desc, spinned, fsize) != fsize) {
1645
 
            cli_dbgmsg("PESpin: Can't read %d bytes\n", fsize);
1646
 
            free(spinned);
1647
 
            free(section_hdr);
1648
 
            return CL_EIO;
1649
 
        }
1650
 
 
1651
 
        if(!(tempfile = cli_gentemp(NULL)))
1652
 
            return CL_EMEM;
1653
 
 
1654
 
        if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1655
 
            cli_dbgmsg("PESpin: Can't create file %s\n", tempfile);
1656
 
            free(tempfile);
1657
 
            free(spinned);
1658
 
            free(section_hdr);
1659
 
            return CL_EIO;
1660
 
        }
1661
 
 
1662
 
        if(!unspin(spinned, fsize, section_hdr, nsections - 1, EC32(optional_hdr32.AddressOfEntryPoint), ndesc)) {
1663
 
            free(spinned);
1664
 
            cli_dbgmsg("PESpin: Unpacked and rebuilt executable saved in %s\n", tempfile);
1665
 
            fsync(ndesc);
1666
 
            lseek(ndesc, 0, SEEK_SET);
1667
 
 
1668
 
            if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
1669
 
                free(section_hdr);
1670
 
                close(ndesc);
1671
 
                if(!cli_leavetemps_flag) {
1672
 
                    unlink(tempfile);
1673
 
                    free(tempfile);
1674
 
                } else {
1675
 
                    free(tempfile);
1676
 
                }
1677
 
                return CL_VIRUS;
1678
 
            }
1679
 
 
1680
 
        } else {
1681
 
            free(spinned);
1682
 
            cli_dbgmsg("PESpin: Rebuilding failed\n");
1683
 
        }
1684
 
 
1685
 
        close(ndesc);
1686
 
        if(!cli_leavetemps_flag) {
1687
 
            unlink(tempfile);
1688
 
            free(tempfile);
1689
 
        } else {
1690
 
            free(tempfile);
1691
 
        }
1692
 
    }
1693
 
 
1694
 
 
1695
 
    /* yC 1.3 */
1696
 
 
1697
 
    if(nsections > 1 &&
1698
 
       EC32(optional_hdr32.AddressOfEntryPoint) == EC32(section_hdr[nsections - 1].VirtualAddress) + 0x60 &&
1699
 
       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)  {
1700
 
 
1701
 
            char *spinned;
1702
 
 
1703
 
        if ( fsize >= EC32(section_hdr[nsections - 1].PointerToRawData) + 0xC6 + 0xb97 ) { /* size check on yC sect */
1704
 
          if((spinned = (char *) cli_malloc(fsize)) == NULL) {
1705
 
            free(section_hdr);
1706
 
            return CL_EMEM;
1707
 
          }
1708
 
 
1709
 
          lseek(desc, 0, SEEK_SET);
1710
 
          if(read(desc, spinned, fsize) != fsize) {
1711
 
            cli_dbgmsg("yC: Can't read %d bytes\n", fsize);
1712
 
            free(spinned);
1713
 
            free(section_hdr);
1714
 
            return CL_EIO;
1715
 
          }
1716
 
 
1717
 
          if(!(tempfile = cli_gentemp(NULL)))
1718
 
              return CL_EMEM;
1719
 
 
1720
 
          if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) {
1721
 
            cli_dbgmsg("yC: Can't create file %s\n", tempfile);
1722
 
            free(tempfile);
1723
 
            free(spinned);
1724
 
            free(section_hdr);
1725
 
            return CL_EIO;
1726
 
          }
1727
 
 
1728
 
          if(!yc_decrypt(spinned, fsize, section_hdr, nsections-1, e_lfanew, ndesc)) {
1729
 
            free(spinned);
1730
 
            cli_dbgmsg("yC: Unpacked and rebuilt executable saved in %s\n", tempfile);
1731
 
            fsync(ndesc);
1732
 
            lseek(ndesc, 0, SEEK_SET);
1733
 
            
1734
 
            if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) {
1735
 
              free(section_hdr);
1736
 
              close(ndesc);
1737
 
              if(!cli_leavetemps_flag) {
1738
 
                unlink(tempfile);
1739
 
                free(tempfile);
1740
 
              } else {
1741
 
                free(tempfile);
1742
 
              }
1743
 
              return CL_VIRUS;
1744
 
            }
1745
 
            
1746
 
          } else {
1747
 
            free(spinned);
1748
 
            cli_dbgmsg("yC: Rebuilding failed\n");
1749
 
          }
1750
 
          
1751
 
          close(ndesc);
1752
 
          if(!cli_leavetemps_flag) {
1753
 
            unlink(tempfile);
1754
 
            free(tempfile);
1755
 
          } else {
1756
 
            free(tempfile);
1757
 
          }
1758
 
 
1759
 
        }
1760
 
    }
1761
 
 
1762
 
    /* to be continued ... */
1763
 
 
1764
 
    free(section_hdr);
1765
 
    return CL_CLEAN;
1766
 
}
1767
 
 
1768
 
int cli_peheader(int desc, struct cli_exe_info *peinfo)
1769
 
{
1770
 
        uint16_t e_magic; /* DOS signature ("MZ") */
1771
 
        uint32_t e_lfanew; /* address of new exe header */
1772
 
        uint32_t min, max;
1773
 
        struct pe_image_file_hdr file_hdr;
1774
 
        struct pe_image_optional_hdr32 optional_hdr32;
1775
 
        struct pe_image_optional_hdr64 optional_hdr64;
1776
 
        struct pe_image_section_hdr *section_hdr;
1777
 
        struct stat sb;
1778
 
        int i;
1779
 
        unsigned int err, pe_plus = 0;
1780
 
 
1781
 
 
1782
 
    cli_dbgmsg("in cli_peheader\n");
1783
 
 
1784
 
    if(read(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
1785
 
        cli_dbgmsg("Can't read DOS signature\n");
1786
 
        return -1;
1787
 
    }
1788
 
 
1789
 
    if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
1790
 
        cli_dbgmsg("Invalid DOS signature\n");
1791
 
        return -1;
1792
 
    }
1793
 
 
1794
 
    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
1795
 
 
1796
 
    if(read(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
1797
 
        cli_dbgmsg("Can't read new header address\n");
1798
 
        /* truncated header? */
1799
 
        return -1;
1800
 
    }
1801
 
 
1802
 
    e_lfanew = EC32(e_lfanew);
1803
 
    if(!e_lfanew) {
1804
 
        cli_dbgmsg("Not a PE file\n");
1805
 
        return -1;
1806
 
    }
1807
 
 
1808
 
    if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
1809
 
        /* probably not a PE file */
1810
 
        cli_dbgmsg("Can't lseek to e_lfanew\n");
1811
 
        return -1;
1812
 
    }
1813
 
 
1814
 
    if(read(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
1815
 
        /* bad information in e_lfanew - probably not a PE file */
1816
 
        cli_dbgmsg("Can't read file header\n");
1817
 
        return -1;
1818
 
    }
1819
 
 
1820
 
    if(EC32(file_hdr.Magic) != IMAGE_NT_SIGNATURE) {
1821
 
        cli_dbgmsg("Invalid PE signature (probably NE file)\n");
1822
 
        return -1;
1823
 
    }
1824
 
 
1825
 
    peinfo->nsections = EC16(file_hdr.NumberOfSections);
1826
 
 
1827
 
    if(EC16(file_hdr.SizeOfOptionalHeader) != sizeof(struct pe_image_optional_hdr32)) {
1828
 
        if(EC16(file_hdr.SizeOfOptionalHeader) == sizeof(struct pe_image_optional_hdr64)) {
1829
 
            pe_plus = 1;
1830
 
        } else {
1831
 
            cli_dbgmsg("Incorrect value of SizeOfOptionalHeader\n");
1832
 
            return -1;
1833
 
        }
1834
 
    }
1835
 
 
1836
 
    if(!pe_plus) { /* PE */
1837
 
 
1838
 
        if(read(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
1839
 
            cli_dbgmsg("Can't optional file header\n");
1840
 
            return -1;
1841
 
        }
1842
 
 
1843
 
    } else { /* PE+ */
1844
 
 
1845
 
        if(read(desc, &optional_hdr64, sizeof(struct pe_image_optional_hdr64)) != sizeof(struct pe_image_optional_hdr64)) {
1846
 
            cli_dbgmsg("Can't optional file header\n");
1847
 
            return -1;
1848
 
        }
1849
 
    }
1850
 
 
1851
 
    peinfo->section = (struct cli_exe_section *) cli_calloc(peinfo->nsections, sizeof(struct cli_exe_section));
1852
 
 
1853
 
    if(!peinfo->section) {
1854
 
        cli_dbgmsg("Can't allocate memory for section headers\n");
1855
 
        return -1;
1856
 
    }
1857
 
 
1858
 
    if(fstat(desc, &sb) == -1) {
1859
 
        cli_dbgmsg("fstat failed\n");
1860
 
        free(peinfo->section);
1861
 
        return -1;
1862
 
    }
1863
 
 
1864
 
    section_hdr = (struct pe_image_section_hdr *) cli_calloc(peinfo->nsections, sizeof(struct pe_image_section_hdr));
1865
 
 
1866
 
    if(!section_hdr) {
1867
 
        cli_dbgmsg("Can't allocate memory for section headers\n");
1868
 
        free(peinfo->section);
1869
 
        return -1;
1870
 
    }
1871
 
 
1872
 
    for(i = 0; i < peinfo->nsections; i++) {
1873
 
 
1874
 
        if(read(desc, &section_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) {
1875
 
            cli_dbgmsg("Can't read section header\n");
1876
 
            cli_dbgmsg("Possibly broken PE file\n");
1877
 
            free(section_hdr);
1878
 
            free(peinfo->section);
1879
 
            return -1;
1880
 
        }
1881
 
 
1882
 
        peinfo->section[i].rva = EC32(section_hdr[i].VirtualAddress);
1883
 
        peinfo->section[i].vsz = EC32(section_hdr[i].VirtualSize);
1884
 
        peinfo->section[i].raw = EC32(section_hdr[i].PointerToRawData);
1885
 
        peinfo->section[i].rsz = EC32(section_hdr[i].SizeOfRawData);
1886
 
 
1887
 
        if(!i) {
1888
 
            min = EC32(section_hdr[i].VirtualAddress);
1889
 
            max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
1890
 
        } else {
1891
 
            if(EC32(section_hdr[i].VirtualAddress) < min)
1892
 
                min = EC32(section_hdr[i].VirtualAddress);
1893
 
 
1894
 
            if(EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData) > max)
1895
 
                max = EC32(section_hdr[i].VirtualAddress) + EC32(section_hdr[i].SizeOfRawData);
1896
 
        }
1897
 
    }
1898
 
 
1899
 
    if(pe_plus)
1900
 
        peinfo->ep = EC32(optional_hdr64.AddressOfEntryPoint);
1901
 
    else
1902
 
        peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint);
1903
 
 
1904
 
    if(peinfo->ep >= min && !(peinfo->ep = cli_rawaddr(peinfo->ep, section_hdr, peinfo->nsections, &err)) && err) {
1905
 
        cli_dbgmsg("Possibly broken PE file\n");
1906
 
        free(section_hdr);
1907
 
        free(peinfo->section);
1908
 
        return -1;
1909
 
    }
1910
 
 
1911
 
    free(section_hdr);
1912
 
    return 0;
1913
 
}