| /* |
| genpeimg - Modify Portable Executable flags and properties. |
| Copyright (C) 2009-2016 mingw-w64 project |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "img.h" |
| |
| unsigned short set_pe_hdr_chara = 0; |
| unsigned short mask_pe_hdr_chara = 0xffff; |
| unsigned short set_pe_opt_hdr_dll_chara = 0; |
| unsigned short mask_pe_opt_hdr_dll_chara = 0xffff; |
| int dump_information = 0; |
| static char *file_name = NULL; |
| |
| static void __attribute__((noreturn)) |
| show_usage (void) |
| { |
| fprintf (stderr, "genpeimg [options] files...\n"); |
| fprintf (stderr, "\nOptions:\n" |
| " -p Takes as addition argument one or more of the following\n" |
| " options:\n" |
| " +<flags> and/or -<flags>\n" |
| " flags are: l, r, n, s, u\n" |
| " l: large-address-aware (only valid for 32-bit)\n" |
| " r: removable-run-from-swap\n" |
| " n: new-run-from-swap\n" |
| " s: system\n" |
| " u: up-system-only\n"); |
| fprintf (stderr, |
| " -d Takes as addition argument one or more of the following\n" |
| " options:\n" |
| " +<flags> and/or -<flags>\n" |
| " flags are: d, f, n, i, s, b, a, w, t\n" |
| " d: dynamic base\n" |
| " f: force integrity\n" |
| " n: nx compatible\n" |
| " i: no-isolation\n" |
| " s: no-SEH\n" |
| " b: no-bind\n" |
| " a: app-container\n" |
| " w: WDM-driver\n" |
| " t: terminal-server-aware\n"); |
| fprintf (stderr, |
| " -h: Show this page.\n" |
| " -x: Dump image information to stdout\n"); |
| exit (0); |
| } |
| |
| static int |
| pass_args (int argc, char **argv) |
| { |
| int has_file = 0; |
| int has_error = 0; |
| while (argc-- > 0) |
| { |
| int is_pos = 1; |
| char *h = *argv++; |
| if (h[0] != '-') |
| { |
| has_file = 1; |
| file_name = h; |
| continue; |
| } |
| switch (h[1]) |
| { |
| case 'p': |
| if (h[2] != 0) |
| goto error_point; |
| if (argc == 0) |
| { |
| fprintf (stderr, "Missing argument for -p\n"); |
| show_usage (); |
| } |
| h = *argv++; argc--; |
| while (*h != 0) |
| { |
| if (*h == '-') is_pos = 0; |
| else if (*h == '+') is_pos = 1; |
| else if (*h == 'l') |
| { |
| if (is_pos) |
| set_pe_hdr_chara |= 0x20; |
| else |
| mask_pe_hdr_chara &= ~0x20; |
| } |
| else if (*h == 'r') |
| { |
| if (is_pos) |
| set_pe_hdr_chara |= 0x400; |
| else |
| mask_pe_hdr_chara &= ~0x400; |
| } |
| else if (*h == 'n') |
| { |
| if (is_pos) |
| set_pe_hdr_chara |= 0x800; |
| else |
| mask_pe_hdr_chara &= ~0x800; |
| } |
| else if (*h == 's') |
| { |
| if (is_pos) |
| set_pe_hdr_chara |= 0x1000; |
| else |
| mask_pe_hdr_chara &= ~0x1000; |
| } |
| else if (*h == 'u') |
| { |
| if (is_pos) |
| set_pe_hdr_chara |= 0x4000; |
| else |
| mask_pe_hdr_chara &= ~0x4000; |
| } |
| else |
| { |
| fprintf (stderr, "Unknown flag-option '%c' for -p\n", *h); |
| has_error = 1; |
| } |
| ++h; |
| } |
| break; |
| case 'd': |
| if (h[2] != 0) |
| goto error_point; |
| if (argc == 0) |
| { |
| fprintf (stderr, "Missing argument for -d\n"); |
| show_usage (); |
| } |
| h = *argv++; argc--; |
| while (*h != 0) |
| { |
| switch (*h) |
| { |
| case '-': is_pos = 0; break; |
| case '+': is_pos = 1; break; |
| case 'd': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x40; |
| else mask_pe_opt_hdr_dll_chara &= ~0x40; |
| break; |
| case 'f': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x80; |
| else mask_pe_opt_hdr_dll_chara &= ~0x80; |
| break; |
| case 'n': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x100; |
| else mask_pe_opt_hdr_dll_chara &= ~0x100; |
| break; |
| case 'i': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x200; |
| else mask_pe_opt_hdr_dll_chara &= ~0x200; |
| break; |
| case 's': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x400; |
| else mask_pe_opt_hdr_dll_chara &= ~0x400; |
| break; |
| case 'b': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x800; |
| else mask_pe_opt_hdr_dll_chara &= ~0x800; |
| break; |
| case 'a': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x1000; |
| else mask_pe_opt_hdr_dll_chara &= ~0x1000; |
| break; |
| case 'w': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x2000; |
| else mask_pe_opt_hdr_dll_chara &= ~0x2000; |
| break; |
| case 't': |
| if (is_pos) set_pe_opt_hdr_dll_chara |= 0x8000; |
| else mask_pe_opt_hdr_dll_chara &= ~0x8000; |
| break; |
| default: |
| fprintf (stderr, "Unknown flag-option '%c' for -d\n", *h); |
| has_error = 1; |
| break; |
| } |
| ++h; |
| } |
| break; |
| case 'x': |
| if (h[2] == 0) |
| { |
| dump_information = 1; |
| break; |
| } |
| goto error_point; |
| case 'h': |
| if (h[2] == 0) |
| show_usage (); |
| /* fallthru */ |
| default: |
| error_point: |
| fprintf (stderr, "Unknown option ,%s'\n", h); |
| has_error = 1; |
| break; |
| } |
| } |
| if (has_error) |
| show_usage (); |
| if (!has_file) |
| { |
| fprintf (stderr, "File argument missing\n"); |
| show_usage (); |
| } |
| return 1; |
| } |
| |
| int main (int argc, char **argv) |
| { |
| pe_image *pe; |
| --argc, ++argv; |
| pass_args (argc, argv); |
| |
| pe = peimg_load (file_name); |
| if (!pe) |
| { |
| fprintf (stderr, "File not found, or no PE-image\n"); |
| return 0; |
| } |
| |
| if (dump_information) |
| peimg_show (pe, stdout); |
| /* First we need to do actions which aren't modifying image's size. */ |
| peimg_set_hdr_characeristics (pe, set_pe_hdr_chara, mask_pe_hdr_chara); |
| peimg_set_hdr_opt_dll_characteristics (pe, set_pe_opt_hdr_dll_chara, mask_pe_opt_hdr_dll_chara); |
| if (pe->pimg->is_modified) |
| pe->pimg->want_save = 1; |
| peimg_free (pe); |
| return 0; |
| } |