blob: 3aee264beb99b1d128b984982b941a322d66baa8 [file] [log] [blame] [raw]
/* PE header item edit tool
toolbox
Copyright 2007-2015 PC GO Ld.
Copyright 2015 libdll.so
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 2 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.
*/
#include "pe-struct.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#define PE_ITEM_RW(ITEM) \
do { \
if(readonly) { \
*out = pe->ITEM; \
return 0; \
} \
pe->ITEM = in; \
if(save_file(file, (const char *)&pe->ITEM, \
offset + ((char *)&pe->ITEM - (char *)pe), sizeof pe->ITEM)) { \
return 0; \
} \
return 6; \
} while(0)
static int save_file(const char *filename, const char *buffer, off_t offset, size_t len) {
int fd = open(filename, O_WRONLY);
if(fd == -1) {
perror(filename);
return 0;
}
//if(!len) len = BUF_SIZE;
if(offset) lseek(fd, offset, SEEK_SET);
return write(fd, buffer, len) != -1;
}
static int pe_file_rw(struct portable_executable *pe, const char *item, char readonly, ...) {
va_list ap;
uint32_t *out;
uint32_t in;
const char *file;
off_t offset;
va_start(ap, readonly);
if(readonly) {
out = va_arg(ap, uint32_t *);
} else {
in = va_arg(ap, uint32_t);
file = va_arg(ap, const char *);
offset = va_arg(ap, off_t);
}
va_end(ap);
if(strcmp(item, "machine") == 0) PE_ITEM_RW(machine);
else if(strcmp(item, "major_linker_version") == 0) PE_ITEM_RW(major_linker_version);
else if(strcmp(item, "minor_linker_version") == 0) PE_ITEM_RW(minor_linker_version);
else if(strcmp(item, "code_size") == 0) PE_ITEM_RW(code_size);
else if(strcmp(item, "initialized_data_size") == 0) PE_ITEM_RW(initialized_data_size);
else if(strcmp(item, "uninitialized_data_size") == 0) PE_ITEM_RW(uninitialized_data_size);
else if(strcmp(item, "entry_point_address") == 0) PE_ITEM_RW(entry_point_address);
else if(strcmp(item, "code_base") == 0) PE_ITEM_RW(code_base);
else if(strcmp(item, "data_base") == 0) PE_ITEM_RW(data_base);
else if(strcmp(item, "image_base") == 0) PE_ITEM_RW(image_base);
else if(strcmp(item, "major_os_version") == 0) PE_ITEM_RW(major_os_version);
else if(strcmp(item, "minor_os_version") == 0) PE_ITEM_RW(minor_os_version);
else if(strcmp(item, "major_image_version") == 0) PE_ITEM_RW(major_image_version);
else if(strcmp(item, "minor_image_version") == 0) PE_ITEM_RW(minor_image_version);
else if(strcmp(item, "major_subsystem_version") == 0) PE_ITEM_RW(major_subsystem_version);
else if(strcmp(item, "minor_subsystem_version") == 0) PE_ITEM_RW(minor_subsystem_version);
else if(strcmp(item, "subsystem") == 0) PE_ITEM_RW(subsystem);
else if(strcmp(item, "dll_characteristics") == 0) PE_ITEM_RW(dll_characteristics);
else if(strcmp(item, "stack_reserve_size") == 0) PE_ITEM_RW(stack_reserve_size);
else if(strcmp(item, "stack_commit_size") == 0) PE_ITEM_RW(stack_commit_size);
else if(strcmp(item, "heap_reserve_size") == 0) PE_ITEM_RW(heap_reserve_size);
else if(strcmp(item, "heap_commit_size") == 0) PE_ITEM_RW(heap_commit_size);
else if(strcmp(item, "loader_flags") == 0) PE_ITEM_RW(loader_flags);
return 1;
}
int modexe_main(int argc, char **argv) {
if(argc < 3) {
fprintf(stderr, "Usage: %s <file> <item> [<new value>]\n", argv[0]);
return -1;
}
int fd = open(argv[1], O_RDONLY);
if(fd == -1) {
perror(argv[1]);
return 2;
}
lseek(fd, 0x3c, SEEK_SET);
unsigned char pe_offset;
if(read(fd, &pe_offset, 1) < 1) {
perror(argv[1]);
return 5;
}
if(!pe_offset) {
fprintf(stderr, "Unexpected PE offset, %s may not a valid PE file\n", argv[1]);
return 4;
}
lseek(fd, pe_offset, SEEK_SET);
int s = 0;
struct portable_executable pe;
do {
int r = read(fd, ((char *)&pe) + s, 1);
if(r < 1) break;
s += r;
} while(s < sizeof pe);
close(fd);
if(pe.pe_signature != 0x4550) {
fprintf(stderr, "The PE signature not found, %s may not a valid PE file\n", argv[1]);
return 3;
}
int r;
uint32_t value;
if(argc == 3) {
r = pe_file_rw(&pe, argv[2], 1, &value);
if(r == 0) {
printf("%s = %u\n", argv[2], value);
return 0;
}
} else {
r = pe_file_rw(&pe, argv[2], 0, atoi(argv[3]), argv[1], pe_offset);
}
if(r == 1) fprintf(stderr, "Item %s unknown or unsupported\n", argv[2]);
else if(r > 5) perror(argv[1]);
return r;
}