From 4fe4339e81e9ba908d0ae69e76bc3e47fac9e387 Mon Sep 17 00:00:00 2001 From: Ophelia Beatrice de Sica Date: Fri, 12 May 2023 19:36:13 +0200 Subject: [PATCH] Add premake and prepare main executable --- .github/workflows/win-artifact-build.yml | 39 ++ Makefile | 95 +++-- completion/bash/readpe | 13 +- include/common.h | 6 +- include/peldd.h | 40 ++ include/peres.h | 48 +++ include/pesec.h | 55 +++ include/pestr.h | 46 +++ include/readpe.h | 55 +++ lib/libpe/Makefile | 324 ++++++++------- lib/libudis86/libudis86/Makefile | 159 ++++++++ premake5.lua | 71 ++++ src/Makefile | 394 ++++++++++-------- src/main.c | 492 +++++++++++++++++++++++ src/main.h | 51 +++ src/ofs2rva.c | 5 +- src/pedis.c | 7 +- src/pehash.c | 3 +- src/peldd.c | 8 +- src/pepack.c | 3 +- src/peres.c | 14 +- src/pescan.c | 5 +- src/pesec.c | 96 +++-- src/pestr.c | 78 ++-- src/readpe.c | 74 ++-- src/rva2ofs.c | 3 +- 26 files changed, 1686 insertions(+), 498 deletions(-) create mode 100644 .github/workflows/win-artifact-build.yml create mode 100644 include/peldd.h create mode 100644 include/peres.h create mode 100644 include/pesec.h create mode 100644 include/pestr.h create mode 100644 include/readpe.h create mode 100644 lib/libudis86/libudis86/Makefile create mode 100644 premake5.lua create mode 100644 src/main.c create mode 100644 src/main.h diff --git a/.github/workflows/win-artifact-build.yml b/.github/workflows/win-artifact-build.yml new file mode 100644 index 00000000..f6238f50 --- /dev/null +++ b/.github/workflows/win-artifact-build.yml @@ -0,0 +1,39 @@ +name: win-artifact-build + +on: + push: + branches: [ build ] + +jobs: + build-win64: + + runs-on: windows-latest + + steps: + + - name: Install Cygwin + # You may pin to the exact commit or the version. + # uses: egor-tensin/setup-cygwin@4f96f9fecb8c952fa32ff791b0a77d93d5191bb4 + uses: egor-tensin/setup-cygwin@v3 + with: + platform: x64 # optional, default is x64 + install-dir: c:\tools\cygwin # optional, default is C:\tools\cygwin + packages: gcc-core binutils make zip libssl-devel # optional + + - name: Checkout with submodules + uses: actions/checkout@v3 + with: + submodules: 'true' + + - name: Compile + run: make + + - name: Compile Windows-only tools and create a ZIP package + run: make zip + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: win-build + path: ./*.zip + retention-days: 1 diff --git a/Makefile b/Makefile index 51637e9b..40e9c077 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,68 @@ -LIBPE_DIR = lib/libpe -PEV_DIR = src -VERSION = 0.82 -ZIPDIR = pev-$(VERSION)-win -ZIPFILE = $(ZIPDIR).zip - -all: -%: - cd $(LIBPE_DIR) && $(MAKE) $@ - cd $(PEV_DIR) && $(MAKE) $@ - -# Cygwin only -zip: - cd $(PEV_DIR)/windows && $(MAKE) - mkdir -p $(ZIPDIR)/plugins - cp src/build/plugins/*.dll $(ZIPDIR)/plugins/ - echo -ne "plugins_dir=plugins\r\n" > $(ZIPDIR)/pev.conf - cp $(PEV_DIR)/userdb.txt $(ZIPDIR) - cp lib/libpe/libpe.dll $(ZIPDIR)/ - cp /usr/bin/cygwin1.dll $(ZIPDIR)/ - cp /usr/bin/cygcrypto-1*.dll $(ZIPDIR)/ - cp /usr/bin/cygz.dll $(ZIPDIR)/ - cp README.md $(ZIPDIR)/ - cp $(PEV_DIR)/build/*.exe $(ZIPDIR)/ - cp $(PEV_DIR)/windows/run.bat $(ZIPDIR)/ - zip -r $(ZIPFILE) $(ZIPDIR)/* - rm -rf $(ZIPDIR) +# Alternative GNU Make workspace makefile autogenerated by Premake + +ifndef config + config=debug +endif + +ifndef verbose + SILENT = @ +endif + +ifeq ($(config),debug) + pe_config = debug + udis86_config = debug + readpe_config = debug + +else ifeq ($(config),release) + pe_config = release + udis86_config = release + readpe_config = release + +else + $(error "invalid configuration $(config)") +endif + +PROJECTS := pe udis86 readpe + +.PHONY: all clean help $(PROJECTS) + +all: $(PROJECTS) + +pe: +ifneq (,$(pe_config)) + @echo "==== Building pe ($(pe_config)) ====" + @${MAKE} --no-print-directory -C lib/libpe -f Makefile config=$(pe_config) +endif + +udis86: +ifneq (,$(udis86_config)) + @echo "==== Building udis86 ($(udis86_config)) ====" + @${MAKE} --no-print-directory -C lib/libudis86/libudis86 -f Makefile config=$(udis86_config) +endif + +readpe: pe udis86 +ifneq (,$(readpe_config)) + @echo "==== Building readpe ($(readpe_config)) ====" + @${MAKE} --no-print-directory -C src -f Makefile config=$(readpe_config) +endif + +clean: + @${MAKE} --no-print-directory -C lib/libpe -f Makefile clean + @${MAKE} --no-print-directory -C lib/libudis86/libudis86 -f Makefile clean + @${MAKE} --no-print-directory -C src -f Makefile clean + +help: + @echo "Usage: make [config=name] [target]" + @echo "" + @echo "CONFIGURATIONS:" + @echo " debug" + @echo " release" + @echo "" + @echo "TARGETS:" + @echo " all (default)" + @echo " clean" + @echo " pe" + @echo " udis86" + @echo " readpe" + @echo "" + @echo "For more information, see https://github.com/premake/premake-core/wiki" \ No newline at end of file diff --git a/completion/bash/readpe b/completion/bash/readpe index d36e4b43..9eb88074 100644 --- a/completion/bash/readpe +++ b/completion/bash/readpe @@ -1,5 +1,15 @@ #!/usr/bin/env bash -complete -F _longopt readpe + +function _complete_readpe () { + echo $COMP_LINE + # local _comp=$COMP_LINE + # local _comp=$("${COMP_LINE[@]::${#COMP_LINE[@]}-1} --complete") + local _comp=$($COMP_LINE "--complete") + # printf "headers directories exports" + COMPREPLY=($_comp) +} + +complete -F _complete_readpe readpe complete -F _longopt pedis complete -F _longopt pehash complete -F _longopt peldd @@ -9,3 +19,4 @@ complete -F _longopt pescan complete -F _longopt pesec complete -F _longopt pestr + diff --git a/include/common.h b/include/common.h index 2ba551bf..d50d83c2 100644 --- a/include/common.h +++ b/include/common.h @@ -59,7 +59,11 @@ #define MAX_MSG 81 #define MAX_PATH 256 -#define VERSION "0.82" + +#ifndef VERSION +#define VERSION "1.0" +#endif + #define TOOLKIT "from pev " VERSION " toolkit" #define COPY \ "License GPLv2+: GNU GPL version 2 or later .\n" \ diff --git a/include/peldd.h b/include/peldd.h new file mode 100644 index 00000000..2d55f964 --- /dev/null +++ b/include/peldd.h @@ -0,0 +1,40 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +#pragma once + +#include + +void print_dependencies(pe_ctx_t *ctx); + diff --git a/include/peres.h b/include/peres.h new file mode 100644 index 00000000..b8b46e7e --- /dev/null +++ b/include/peres.h @@ -0,0 +1,48 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +#pragma once + +#include +#include +#include +#include +#include + +void peres_show_nodes(pe_ctx_t *ctx, const pe_resource_node_t *node); +void peres_show_stats(const pe_resource_node_t *node); +void peres_show_list(pe_ctx_t *ctx, const pe_resource_node_t *node); +void peres_save_all_resources(pe_ctx_t *ctx, const pe_resource_node_t *node, bool namedExtract); +void peres_show_version(pe_ctx_t *ctx, const pe_resource_node_t *node); + diff --git a/include/pesec.h b/include/pesec.h new file mode 100644 index 00000000..4431d0b1 --- /dev/null +++ b/include/pesec.h @@ -0,0 +1,55 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +#pragma once + +#include "common.h" +#include +#include + +typedef enum { + CERT_FORMAT_TEXT = 1, + CERT_FORMAT_PEM = 2, + CERT_FORMAT_DER = 3 +} cert_format_e; + +typedef struct { + cert_format_e certoutform; + BIO *certout; +} certificate_settings; + +bool stack_cookies(pe_ctx_t *ctx); +void print_securities(pe_ctx_t *ctx); +void parse_certificates(const certificate_settings *options, pe_ctx_t *ctx); + diff --git a/include/pestr.h b/include/pestr.h new file mode 100644 index 00000000..e91d168c --- /dev/null +++ b/include/pestr.h @@ -0,0 +1,46 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +#pragma once + +#include + +typedef struct { + unsigned short strsize; + bool offset; + bool section; +} string_settings; + +void print_strings( pe_ctx_t *ctx, const string_settings *options); + diff --git a/include/readpe.h b/include/readpe.h new file mode 100644 index 00000000..8babb96e --- /dev/null +++ b/include/readpe.h @@ -0,0 +1,55 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + readpe.h + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +#pragma once + +#include +#include +// #include "common.h" +// #include "output.h" + +void print_dos_header(pe_ctx_t *ctx); +void print_coff_header(pe_ctx_t *ctx); +void print_optional_header(pe_ctx_t *ctx); + +void print_directories(pe_ctx_t *ctx); +void print_imports(pe_ctx_t *ctx); +void print_exports(pe_ctx_t *ctx); + +void print_sections(pe_ctx_t *ctx); + +IMAGE_DATA_DIRECTORY **get_pe_directories(pe_ctx_t *ctx); + diff --git a/lib/libpe/Makefile b/lib/libpe/Makefile index 85547454..d218c1f9 100644 --- a/lib/libpe/Makefile +++ b/lib/libpe/Makefile @@ -1,169 +1,183 @@ -####### Platform specifics - -# cut is necessary for Cygwin -PLATFORM_OS := $(shell uname | cut -d_ -f1) - -####### Makefile Conventions - Directory variables - -srcdir = . -prefix = /usr/local -exec_prefix = $(prefix) -sysconfdir = $(prefix)/etc -includedir = $(prefix)/include -datarootdir = $(prefix)/share -localstatedir = $(prefix)/var -bindir = $(exec_prefix)/bin -libdir = $(exec_prefix)/lib -libexecdir = $(exec_prefix)/libexec -sbindir = $(exec_prefix)/sbin -datadir = $(datarootdir) -docdir = $(datarootdir)/doc/pev -infodir = $(datarootdir)/info -localedir = $(datarootdir)/locale - -mandir = $(datarootdir)/man -manext = .1 -man1dir = $(mandir)/man1 -man1ext = .1 - -####### Makefile Conventions - Utilities - -CC ?= gcc -LINK = $(CC) -CHK_DIR_EXISTS = test -d -CHK_FILE_EXISTS = test -f -INSTALL = install -INSTALL_DATA = ${INSTALL} -m 644 -INSTALL_PROGRAM = $(INSTALL) -SYMLINK = ln -sf -MKDIR = mkdir -p -RM = rm -f -RM_DIR = rm -rf - -ifeq ($(PLATFORM_OS), Darwin) - STRIP = strip -x -else - STRIP = strip --strip-unneeded -endif - -####### Compiler options - -override CFLAGS += \ - -O2 -ffast-math \ - -I"./include" \ - -fPIC \ - -W -Wall -Wextra -pedantic -std=c99 -c -override CPPFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -#override LDFLAGS += -lssl -lcrypto -LIBS = -lssl -lcrypto -lm - -# --- FIX: -fPIC is necessary to ALL shared objects! Changed above. -#ifneq ($(PLATFORM_OS), CYGWIN) -# override CFLAGS += -fPIC -#endif - -VERSION = 0.82 -LIBNAME = libpe +# Alternative GNU Make project makefile autogenerated by Premake -SRC_DIRS = $(srcdir) $(srcdir)/libfuzzy - -libpe_BUILDDIR = $(CURDIR)/build -libpe_SRCS_FILTER = $(sort $(wildcard ${dir}/*.c)) -libpe_SRCS = $(foreach dir, ${SRC_DIRS}, ${libpe_SRCS_FILTER}) -libpe_OBJS = $(addprefix ${libpe_BUILDDIR}/, $(addsuffix .o, $(basename ${libpe_SRCS}))) +ifndef config + config=debug +endif -####### Build rules +ifndef verbose + SILENT = @ +endif -.PHONY : libpe install strip-binaries install-strip uninstall clean +.PHONY: clean prebuild -all: libpe +SHELLTYPE := posix +ifeq (.exe,$(findstring .exe,$(ComSpec))) + SHELLTYPE := msdos +endif -# FIX: WARNING.. ld expects -l option at the END of the command line or after the object files. -# From gcc's documentation: -# -# It makes a difference where in the command you write this option; the linker searches and processes -# libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library -# ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions -# may not be loaded. -# +# Configurations +# ############################################# + +RESCOMP = windres +DEFINES += -D_GNU_SOURCE +INCLUDES += -Iinclude +FORCE_INCLUDE += +ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) +ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) +LIBS += -lcrypto -lm +LDDEPS += +define PREBUILDCMDS +endef +define PRELINKCMDS +endef +define POSTBUILDCMDS +endef + +ifeq ($(config),debug) +TARGETDIR = ../../build/Debug +TARGET = $(TARGETDIR)/libpe.a +OBJDIR = obj/Debug +ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) +ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) +ALL_LDFLAGS += $(LDFLAGS) -s +LINKCMD = $(AR) -rcs "$@" $(OBJECTS) + +else ifeq ($(config),release) +TARGETDIR = ../../build/Release +TARGET = $(TARGETDIR)/libpe.so +OBJDIR = obj/Release +ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -fPIC +ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -fPIC +ALL_LDFLAGS += $(LDFLAGS) -shared -Wl,-soname=libpe.so -s +LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS) -libpe: CPPFLAGS += -D_GNU_SOURCE -ifeq ($(PLATFORM_OS), CYGWIN) -libpe: CPPFLAGS += -D_XOPEN_SOURCE=600 endif -libpe: $(libpe_OBJS) -ifeq ($(PLATFORM_OS), Linux) - $(LINK) -shared -Wl,-soname,$(LIBNAME).so.1 $(LDFLAGS) -o $(LIBNAME).so $^ $(LIBS) -else ifeq ($(PLATFORM_OS), NetBSD) - $(LINK) -shared -Wl,-soname,$(LIBNAME).so.1 $(LDFLAGS) -o $(LIBNAME).so $^ $(LIBS) -else ifeq ($(PLATFORM_OS), FreeBSD) - $(LINK) -shared -Wl,-soname,$(LIBNAME).so.1 $(LDFLAGS) -o $(LIBNAME).so $^ $(LIBS) -else ifeq ($(PLATFORM_OS), OpenBSD) - $(LINK) -shared -Wl,-soname,$(LIBNAME).so.1 $(LDFLAGS) -o $(LIBNAME).so $^ $(LIBS) -else ifeq ($(PLATFORM_OS), GNU) - $(LINK) -shared -Wl,-soname,$(LIBNAME).so.1 $(LDFLAGS) -o $(LIBNAME).so $^ $(LIBS) -else ifeq ($(PLATFORM_OS), GNU/kFreeBSD) - $(LINK) -shared -Wl,-soname,$(LIBNAME).so.1 $(LDFLAGS) -o $(LIBNAME).so $^ $(LIBS) -else ifeq ($(PLATFORM_OS), Darwin) - $(LINK) -headerpad_max_install_names -dynamiclib \ - -flat_namespace -install_name $(LIBNAME).$(VERSION).dylib \ - -current_version $(VERSION) -compatibility_version $(VERSION) \ - $(LDFLAGS) -o $(LIBNAME).dylib $^ $(LIBS) -else ifeq ($(PLATFORM_OS), CYGWIN) - $(LINK) -shared -o $(LIBNAME).dll $^ $(LDFLAGS) $(LIBS) + +# Per File Configurations +# ############################################# + + +# File sets +# ############################################# + +GENERATED := +OBJECTS := + +GENERATED += $(OBJDIR)/edit_dist.o +GENERATED += $(OBJDIR)/error.o +GENERATED += $(OBJDIR)/exports.o +GENERATED += $(OBJDIR)/fuzzy.o +GENERATED += $(OBJDIR)/hashes.o +GENERATED += $(OBJDIR)/imports.o +GENERATED += $(OBJDIR)/misc.o +GENERATED += $(OBJDIR)/pe.o +GENERATED += $(OBJDIR)/resources.o +GENERATED += $(OBJDIR)/utils.o +OBJECTS += $(OBJDIR)/edit_dist.o +OBJECTS += $(OBJDIR)/error.o +OBJECTS += $(OBJDIR)/exports.o +OBJECTS += $(OBJDIR)/fuzzy.o +OBJECTS += $(OBJDIR)/hashes.o +OBJECTS += $(OBJDIR)/imports.o +OBJECTS += $(OBJDIR)/misc.o +OBJECTS += $(OBJDIR)/pe.o +OBJECTS += $(OBJDIR)/resources.o +OBJECTS += $(OBJDIR)/utils.o + +# Rules +# ############################################# + +all: $(TARGET) + @: + +$(TARGET): $(GENERATED) $(OBJECTS) $(LDDEPS) | $(TARGETDIR) + $(PRELINKCMDS) + @echo Linking pe + $(SILENT) $(LINKCMD) + $(POSTBUILDCMDS) + +$(TARGETDIR): + @echo Creating $(TARGETDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(TARGETDIR) +else + $(SILENT) mkdir $(subst /,\\,$(TARGETDIR)) endif -$(libpe_BUILDDIR)/%.o: %.c - @$(CHK_DIR_EXISTS) $(dir $@) || $(MKDIR) $(dir $@) - $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< - -install: installdirs -ifeq ($(PLATFORM_OS), Linux) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).so $(DESTDIR)$(libdir)/$(LIBNAME).so.$(VERSION) - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so.1 -else ifeq ($(PLATFORM_OS), NetBSD) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).so $(DESTDIR)$(libdir)/$(LIBNAME).so.$(VERSION) - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so.1 -else ifeq ($(PLATFORM_OS), FreeBSD) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).so $(DESTDIR)$(libdir)/$(LIBNAME).so.$(VERSION) - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so.1 -else ifeq ($(PLATFORM_OS), OpenBSD) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).so $(DESTDIR)$(libdir)/$(LIBNAME).so.$(VERSION) - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so.1 -else ifeq ($(PLATFORM_OS), GNU) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).so $(DESTDIR)$(libdir)/$(LIBNAME).so.$(VERSION) - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so.1 -else ifeq ($(PLATFORM_OS), GNU/kFreeBSD) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).so $(DESTDIR)$(libdir)/$(LIBNAME).so.$(VERSION) - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).so.$(VERSION) $(LIBNAME).so.1 -else ifeq ($(PLATFORM_OS), Darwin) - $(INSTALL_DATA) $(INSTALL_FLAGS) $(LIBNAME).dylib $(DESTDIR)$(libdir)/$(LIBNAME).$(VERSION).dylib - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).$(VERSION).dylib $(LIBNAME).dylib - cd $(DESTDIR)$(libdir); $(SYMLINK) $(LIBNAME).$(VERSION).dylib $(LIBNAME).1.dylib -else ifeq ($(PLATFORM_OS), CYGWIN) - # TODO +$(OBJDIR): + @echo Creating $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(OBJDIR) +else + $(SILENT) mkdir $(subst /,\\,$(OBJDIR)) endif -installdirs: - @$(CHK_DIR_EXISTS) $(DESTDIR) || $(MKDIR) $(DESTDIR) - @$(CHK_DIR_EXISTS) $(DESTDIR)$(libdir) || $(MKDIR) $(DESTDIR)$(libdir) +clean: + @echo Cleaning pe +ifeq (posix,$(SHELLTYPE)) + $(SILENT) rm -f $(TARGET) + $(SILENT) rm -rf $(GENERATED) + $(SILENT) rm -rf $(OBJDIR) +else + $(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET)) + $(SILENT) if exist $(subst /,\\,$(GENERATED)) del /s /q $(subst /,\\,$(GENERATED)) + $(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR)) +endif -install-strip: INSTALL_FLAGS += -s -install-strip: install +prebuild: | $(OBJDIR) + $(PREBUILDCMDS) + +ifneq (,$(PCH)) +$(OBJECTS): $(GCH) | $(PCH_PLACEHOLDER) +$(GCH): $(PCH) | prebuild + @echo $(notdir $<) + $(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<" +$(PCH_PLACEHOLDER): $(GCH) | $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) touch "$@" +else + $(SILENT) echo $null >> "$@" +endif +else +$(OBJECTS): | prebuild +endif -uninstall: - $(RM) $(DESTDIR)$(libdir)/$(LIBNAME).so* \ - $(DESTDIR)$(libdir)/$(LIBNAME)*.dylib -clean: - $(RM_DIR) $(libpe_BUILDDIR) - $(RM) $(LIBNAME)*.o \ - $(LIBNAME)*.so \ - $(LIBNAME)*.dylib \ - $(LIBNAME)*.dll +# File Rules +# ############################################# + +$(OBJDIR)/error.o: error.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/exports.o: exports.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/hashes.o: hashes.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/imports.o: imports.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/edit_dist.o: libfuzzy/edit_dist.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/fuzzy.o: libfuzzy/fuzzy.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/misc.o: misc.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pe.o: pe.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/resources.o: resources.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/utils.o: utils.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" + +-include $(OBJECTS:%.o=%.d) +ifneq (,$(PCH)) + -include $(PCH_PLACEHOLDER).d +endif \ No newline at end of file diff --git a/lib/libudis86/libudis86/Makefile b/lib/libudis86/libudis86/Makefile new file mode 100644 index 00000000..d341b19e --- /dev/null +++ b/lib/libudis86/libudis86/Makefile @@ -0,0 +1,159 @@ +# Alternative GNU Make project makefile autogenerated by Premake + +ifndef config + config=debug +endif + +ifndef verbose + SILENT = @ +endif + +.PHONY: clean prebuild + +SHELLTYPE := posix +ifeq (.exe,$(findstring .exe,$(ComSpec))) + SHELLTYPE := msdos +endif + +# Configurations +# ############################################# + +RESCOMP = windres +DEFINES += -DHAVE_STRING_H=1 +INCLUDES += +FORCE_INCLUDE += +ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) +ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) +ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) +ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) +LIBS += +LDDEPS += +ALL_LDFLAGS += $(LDFLAGS) -s +LINKCMD = $(AR) -rcs "$@" $(OBJECTS) +define PREBUILDCMDS +endef +define PRELINKCMDS +endef +define POSTBUILDCMDS +endef + +ifeq ($(config),debug) +TARGETDIR = ../../../build/Debug +TARGET = $(TARGETDIR)/libudis86.a +OBJDIR = obj/Debug + +else ifeq ($(config),release) +TARGETDIR = ../../../build/Release +TARGET = $(TARGETDIR)/libudis86.a +OBJDIR = obj/Release + +endif + +# Per File Configurations +# ############################################# + + +# File sets +# ############################################# + +GENERATED := +OBJECTS := + +GENERATED += $(OBJDIR)/decode.o +GENERATED += $(OBJDIR)/itab.o +GENERATED += $(OBJDIR)/syn-att.o +GENERATED += $(OBJDIR)/syn-intel.o +GENERATED += $(OBJDIR)/syn.o +GENERATED += $(OBJDIR)/udis86.o +OBJECTS += $(OBJDIR)/decode.o +OBJECTS += $(OBJDIR)/itab.o +OBJECTS += $(OBJDIR)/syn-att.o +OBJECTS += $(OBJDIR)/syn-intel.o +OBJECTS += $(OBJDIR)/syn.o +OBJECTS += $(OBJDIR)/udis86.o + +# Rules +# ############################################# + +all: $(TARGET) + @: + +$(TARGET): $(GENERATED) $(OBJECTS) $(LDDEPS) | $(TARGETDIR) + $(PRELINKCMDS) + @echo Linking udis86 + $(SILENT) $(LINKCMD) + $(POSTBUILDCMDS) + +$(TARGETDIR): + @echo Creating $(TARGETDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(TARGETDIR) +else + $(SILENT) mkdir $(subst /,\\,$(TARGETDIR)) +endif + +$(OBJDIR): + @echo Creating $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(OBJDIR) +else + $(SILENT) mkdir $(subst /,\\,$(OBJDIR)) +endif + +clean: + @echo Cleaning udis86 +ifeq (posix,$(SHELLTYPE)) + $(SILENT) rm -f $(TARGET) + $(SILENT) rm -rf $(GENERATED) + $(SILENT) rm -rf $(OBJDIR) +else + $(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET)) + $(SILENT) if exist $(subst /,\\,$(GENERATED)) del /s /q $(subst /,\\,$(GENERATED)) + $(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR)) +endif + +prebuild: | $(OBJDIR) + $(PREBUILDCMDS) + +ifneq (,$(PCH)) +$(OBJECTS): $(GCH) | $(PCH_PLACEHOLDER) +$(GCH): $(PCH) | prebuild + @echo $(notdir $<) + $(SILENT) $(CXX) -x c++-header $(ALL_CXXFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<" +$(PCH_PLACEHOLDER): $(GCH) | $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) touch "$@" +else + $(SILENT) echo $null >> "$@" +endif +else +$(OBJECTS): | prebuild +endif + + +# File Rules +# ############################################# + +$(OBJDIR)/decode.o: decode.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/itab.o: itab.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/syn-att.o: syn-att.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/syn-intel.o: syn-intel.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/syn.o: syn.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/udis86.o: udis86.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" + +-include $(OBJECTS:%.o=%.d) +ifneq (,$(PCH)) + -include $(PCH_PLACEHOLDER).d +endif \ No newline at end of file diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 00000000..3e02701d --- /dev/null +++ b/premake5.lua @@ -0,0 +1,71 @@ +workspace "readpe" + configurations { "Debug", "Release" } + +project "pe" + language "C" + location "lib/libpe" + includedirs { "lib/libpe/include" } + targetdir "build/%{cfg.buildcfg}" + files { "lib/libpe/**.h", "lib/libpe/**.c" } + defines { + "_GNU_SOURCE", + } + links { "crypto" } + + filter { "system:linux" } + links { "m" } + + filter "Debug" + kind "StaticLib" + + filter "Release" + kind "SharedLib" + +project "udis86" + kind "StaticLib" + location "lib/libudis86/libudis86" + targetdir "build/%{cfg.buildcfg}" + files { "lib/libudis86/libudis86/*.h", "lib/libudis86/libudis86/*.c" } + defines { "HAVE_STRING_H=1" } + +-- TODO: ZIP Packing +project "readpe" + kind "ConsoleApp" + language "C" + location "src" + includedirs { "include", "lib/libpe/include", "lib" } + targetdir "build/%{cfg.buildcfg}" + + files { "src/*.h", "src/*.c", "src/compat/*.c" } + -- removefiles { "src/ofs2rva.c", "src/pedis.c", "src/pehash.c", "src/pepack.c", "src/peres.c", "src/pescan.c", "src/pesec.c", "src/readpe.c", "src/rva2ofs.c" } + + defines { + "_GNU_SOURCE", + "SHAREDIR=\"\"", + "PLUGINSDIR=\"pev/plugins\"" + } + + links { "pe", "udis86", "crypto" } + + warnings "Extra" + flags { "LinkTimeOptimization" } + + filter { "system:linux" } + links { "m" } + + filter "configurations:Debug" + defines { "DEBUG" } + enablewarnings { + "pedantic", + "shadow", + "undef", + "double-promotion", + "format=2", + "format-security", + "conversion" + } + symbols "On" + + filter "configurations:Release" + defines { "NDEBUG" } + optimize "Full" diff --git a/src/Makefile b/src/Makefile index b22251a3..4e62995b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,187 +1,235 @@ -####### Platform specifics - -# cut is necessary for Cygwin -export PLATFORM_OS := $(shell uname | cut -d_ -f1) - -####### Makefile Conventions - Directory variables - -srcdir = . -prefix = /usr/local - -exec_prefix = $(prefix) -sysconfdir = $(prefix)/etc -includedir = $(prefix)/include -datarootdir = $(prefix)/share -localstatedir = $(prefix)/var - -bindir = $(exec_prefix)/bin -libdir = $(exec_prefix)/lib -libexecdir = $(exec_prefix)/libexec -sbindir = $(exec_prefix)/sbin - -datadir = $(datarootdir) -docdir = $(datarootdir)/doc/pev -infodir = $(datarootdir)/info -localedir = $(datarootdir)/locale - -mandir = $(datarootdir)/man -manext = .1 -man1dir = $(mandir)/man1 -man1ext = .1 - -export pluginsdir = $(libdir)/pev/plugins - -####### Makefile Conventions - Utilities - -export CC ?= gcc -export LINK = $(CC) -export CHK_DIR_EXISTS = test -d -export CHK_FILE_EXISTS = test -f -export INSTALL = install -export INSTALL_DATA = ${INSTALL} -m 644 -export INSTALL_PROGRAM = ${INSTALL} -export SYMLINK = ln -sf -export MKDIR = mkdir -p -export RM = rm -f -export RM_DIR = rm -rf -ifeq ($(PLATFORM_OS), Darwin) - export STRIP = strip -x -else - export STRIP = strip --strip-unneeded -endif - -####### Compiler options - -override LDFLAGS += -L$(LIBPE) -lpe -lcrypto -lssl -ldl -lm -override CFLAGS += -O2 -ffast-math -I$(LIBPE)/include -I"../include" -W -Wall -Wextra -Wno-implicit-fallthrough -std=c99 -pedantic - -# To compile for production define the symbol NDEBUG before invoking this makefile. -override CPPFLAGS += \ - -D_GNU_SOURCE \ - -DSHAREDIR="\"$(SHAREDIR)"\" \ - -DPLUGINSDIR="\"$(pluginsdir)"\" +# Alternative GNU Make project makefile autogenerated by Premake -# Some gcc/clang builds (depends on the distro) already define _FORTIFY_SOURCE internally, so we -# only define it if it has not been already. This avoids redefinition warnings and weakening -# those distros' hardening settings. -ifneq ($(findstring _FORTIFY_SOURCE, $(CPPFLAGS)), _FORTIFY_SOURCE) - override CPPFLAGS += -D_FORTIFY_SOURCE=1 +ifndef config + config=debug endif -ifeq ($(PLATFORM_OS), Darwin) - # We disable warnings for deprecated declarations since Apple deprecated OpenSSL in Mac OS X 10.7 - override CFLAGS += -Wno-deprecated-declarations +ifndef verbose + SILENT = @ endif -ifeq ($(PLATFORM_OS), CYGWIN) - override CPPFLAGS += -D_XOPEN_SOURCE=600 -endif - -SRC_DIRS = $(srcdir) $(srcdir)/compat - -PROGS = readpe rva2ofs ofs2rva pehash pesec pescan pepack pestr pedis peres peldd -PLUGINS_DIR = $(srcdir)/plugins -SHAREDIR = $(datadir)/pev -export LIBPE = $(realpath $(srcdir)/../lib/libpe) -LIBUDIS86 = $(srcdir)/../lib/libudis86 -MANDIR = $(srcdir)/../doc/manpages - -export pev_BUILDDIR = ./build -pev_SRCS_FILTER = $(sort $(wildcard ${dir}/*.c)) -pev_SRCS = $(foreach dir, ${SRC_DIRS}, ${pev_SRCS_FILTER}) -pev_OBJS = $(addprefix ${pev_BUILDDIR}/, $(addsuffix .o, $(basename ${pev_SRCS}))) - -pev_COMMON_DEPS = \ - $(pev_BUILDDIR)/compat/strlcat.o \ - $(pev_BUILDDIR)/config.o \ - $(pev_BUILDDIR)/dylib.o \ - $(pev_BUILDDIR)/malloc_s.o \ - $(pev_BUILDDIR)/plugins.o \ - $(pev_BUILDDIR)/output_plugin.o \ - $(pev_BUILDDIR)/output.o \ - $(pev_BUILDDIR)/pev_api.o - -####### Build rules - -.PHONY: plugins install installdirs uninstall clean - -all: $(PROGS) plugins - -plugins: - cd $(PLUGINS_DIR) && $(MAKE) $@ - -ofs2rva: $(pev_BUILDDIR)/ofs2rva.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) - -pedis: CPPFLAGS += -DHAVE_STRING_H -pedis: CFLAGS += -I$(LIBUDIS86) -pedis: $(pev_BUILDDIR)/pedis.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) $(sort $(LIBUDIS86)/libudis86/*.c) - -pehash: $(pev_BUILDDIR)/pehash.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -pepack: $(pev_BUILDDIR)/pepack.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -peres: $(pev_BUILDDIR)/peres.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) +.PHONY: clean prebuild -pescan: LDFLAGS += -lm -pescan: $(pev_BUILDDIR)/pescan.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -pesec: LDFLAGS += -lcrypto -pesec: $(pev_BUILDDIR)/pesec.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -pestr: $(pev_BUILDDIR)/pestr.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -readpe: $(pev_BUILDDIR)/readpe.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -rva2ofs: $(pev_BUILDDIR)/rva2ofs.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) - -peldd: $(pev_BUILDDIR)/peldd.o $(pev_OBJS) - $(CC) $< -o $(pev_BUILDDIR)/$@ $(pev_COMMON_DEPS) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) +SHELLTYPE := posix +ifeq (.exe,$(findstring .exe,$(ComSpec))) + SHELLTYPE := msdos +endif -# Generic rule matching sources +# Configurations +# ############################################# + +RESCOMP = windres +INCLUDES += -I../include -I../lib/libpe/include -I../lib +FORCE_INCLUDE += +ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) +ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) +LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS) +define PREBUILDCMDS +endef +define PRELINKCMDS +endef +define POSTBUILDCMDS +endef + +ifeq ($(config),debug) +TARGETDIR = ../build/Debug +TARGET = $(TARGETDIR)/readpe +OBJDIR = obj/Debug +DEFINES += -D_GNU_SOURCE -DSHAREDIR=\"\" -DPLUGINSDIR=\"pev/plugins\" -DDEBUG +ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -flto -g -Wall -Wextra -Wpedantic -Wshadow -Wundef -Wdouble-promotion -Wformat=2 -Wformat-security -Wconversion +ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -flto -g -Wall -Wextra -Wpedantic -Wshadow -Wundef -Wdouble-promotion -Wformat=2 -Wformat-security -Wconversion +LIBS += ../build/Debug/libpe.a ../build/Debug/libudis86.a -lcrypto -lm +LDDEPS += ../build/Debug/libpe.a ../build/Debug/libudis86.a +ALL_LDFLAGS += $(LDFLAGS) -flto + +else ifeq ($(config),release) +TARGETDIR = ../build/Release +TARGET = $(TARGETDIR)/readpe +OBJDIR = obj/Release +DEFINES += -D_GNU_SOURCE -DSHAREDIR=\"\" -DPLUGINSDIR=\"pev/plugins\" -DNDEBUG +ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -flto -O3 -Wall -Wextra +ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -flto -O3 -Wall -Wextra +LIBS += ../build/Release/libpe.so ../build/Release/libudis86.a -lcrypto -lm +LDDEPS += ../build/Release/libpe.so ../build/Release/libudis86.a +ALL_LDFLAGS += $(LDFLAGS) -Wl,-rpath,'$$ORIGIN' -flto -s -$(pev_BUILDDIR)/%.o: %.c - @$(CHK_DIR_EXISTS) $(dir $@) || $(MKDIR) $(dir $@) - $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) $(INCPATH) +endif -install: installdirs - for prog in $(PROGS); do \ - $(INSTALL_PROGRAM) $(INSTALL_FLAGS) $(pev_BUILDDIR)/$$prog $(DESTDIR)$(bindir); \ - $(CHK_FILE_EXISTS) $(MANDIR)/$$prog$(man1ext) && \ - gzip -c -9 $(MANDIR)/$$prog$(man1ext) > $(DESTDIR)$(man1dir)/$$prog$(man1ext).gz || \ - echo -n; \ - done +# Per File Configurations +# ############################################# + + +# File sets +# ############################################# + +GENERATED := +OBJECTS := + +GENERATED += $(OBJDIR)/config.o +GENERATED += $(OBJDIR)/dylib.o +GENERATED += $(OBJDIR)/main.o +GENERATED += $(OBJDIR)/malloc_s.o +GENERATED += $(OBJDIR)/ofs2rva.o +GENERATED += $(OBJDIR)/output.o +GENERATED += $(OBJDIR)/output_plugin.o +GENERATED += $(OBJDIR)/pedis.o +GENERATED += $(OBJDIR)/pehash.o +GENERATED += $(OBJDIR)/peldd.o +GENERATED += $(OBJDIR)/pepack.o +GENERATED += $(OBJDIR)/peres.o +GENERATED += $(OBJDIR)/pescan.o +GENERATED += $(OBJDIR)/pesec.o +GENERATED += $(OBJDIR)/pestr.o +GENERATED += $(OBJDIR)/pev_api.o +GENERATED += $(OBJDIR)/plugins.o +GENERATED += $(OBJDIR)/readpe.o +GENERATED += $(OBJDIR)/rva2ofs.o +GENERATED += $(OBJDIR)/strlcat.o +OBJECTS += $(OBJDIR)/config.o +OBJECTS += $(OBJDIR)/dylib.o +OBJECTS += $(OBJDIR)/main.o +OBJECTS += $(OBJDIR)/malloc_s.o +OBJECTS += $(OBJDIR)/ofs2rva.o +OBJECTS += $(OBJDIR)/output.o +OBJECTS += $(OBJDIR)/output_plugin.o +OBJECTS += $(OBJDIR)/pedis.o +OBJECTS += $(OBJDIR)/pehash.o +OBJECTS += $(OBJDIR)/peldd.o +OBJECTS += $(OBJDIR)/pepack.o +OBJECTS += $(OBJDIR)/peres.o +OBJECTS += $(OBJDIR)/pescan.o +OBJECTS += $(OBJDIR)/pesec.o +OBJECTS += $(OBJDIR)/pestr.o +OBJECTS += $(OBJDIR)/pev_api.o +OBJECTS += $(OBJDIR)/plugins.o +OBJECTS += $(OBJDIR)/readpe.o +OBJECTS += $(OBJDIR)/rva2ofs.o +OBJECTS += $(OBJDIR)/strlcat.o + +# Rules +# ############################################# + +all: $(TARGET) + @: + +$(TARGET): $(GENERATED) $(OBJECTS) $(LDDEPS) | $(TARGETDIR) + $(PRELINKCMDS) + @echo Linking readpe + $(SILENT) $(LINKCMD) + $(POSTBUILDCMDS) + +$(TARGETDIR): + @echo Creating $(TARGETDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(TARGETDIR) +else + $(SILENT) mkdir $(subst /,\\,$(TARGETDIR)) +endif - $(INSTALL_DATA) $(srcdir)/userdb.txt $(DESTDIR)$(SHAREDIR) - cd $(PLUGINS_DIR) && $(MAKE) $@ +$(OBJDIR): + @echo Creating $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(OBJDIR) +else + $(SILENT) mkdir $(subst /,\\,$(OBJDIR)) +endif -install-strip: INSTALL_FLAGS += -s -install-strip: install +clean: + @echo Cleaning readpe +ifeq (posix,$(SHELLTYPE)) + $(SILENT) rm -f $(TARGET) + $(SILENT) rm -rf $(GENERATED) + $(SILENT) rm -rf $(OBJDIR) +else + $(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET)) + $(SILENT) if exist $(subst /,\\,$(GENERATED)) del /s /q $(subst /,\\,$(GENERATED)) + $(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR)) +endif -installdirs: - @$(CHK_DIR_EXISTS) $(DESTDIR) || $(MKDIR) $(DESTDIR) - @$(CHK_DIR_EXISTS) $(DESTDIR)$(bindir) || $(MKDIR) $(DESTDIR)$(bindir) - @$(CHK_DIR_EXISTS) $(DESTDIR)$(man1dir) || $(MKDIR) $(DESTDIR)$(man1dir) - @$(CHK_DIR_EXISTS) $(DESTDIR)$(SHAREDIR) || $(MKDIR) $(DESTDIR)$(SHAREDIR) +prebuild: | $(OBJDIR) + $(PREBUILDCMDS) + +ifneq (,$(PCH)) +$(OBJECTS): $(GCH) | $(PCH_PLACEHOLDER) +$(GCH): $(PCH) | prebuild + @echo $(notdir $<) + $(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<" +$(PCH_PLACEHOLDER): $(GCH) | $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) touch "$@" +else + $(SILENT) echo $null >> "$@" +endif +else +$(OBJECTS): | prebuild +endif -uninstall: - for prog in $(PROGS); do \ - $(RM) $(DESTDIR)$(bindir)/$$prog; \ - $(RM) $(DESTDIR)$(man1dir)/$$prog$(man1ext).gz; \ - done - $(RM_DIR) $(DESTDIR)$(SHAREDIR) - cd $(PLUGINS_DIR) && $(MAKE) $@ -clean: - $(RM_DIR) $(pev_BUILDDIR) - $(RM) $(PROGS) - cd $(PLUGINS_DIR) && $(MAKE) $@ +# File Rules +# ############################################# + +$(OBJDIR)/strlcat.o: compat/strlcat.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/config.o: config.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/dylib.o: dylib.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/main.o: main.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/malloc_s.o: malloc_s.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/ofs2rva.o: ofs2rva.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/output.o: output.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/output_plugin.o: output_plugin.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pedis.o: pedis.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pehash.o: pehash.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/peldd.o: peldd.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pepack.o: pepack.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/peres.o: peres.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pescan.o: pescan.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pesec.o: pesec.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pestr.o: pestr.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/pev_api.o: pev_api.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/plugins.o: plugins.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/readpe.o: readpe.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/rva2ofs.o: rva2ofs.c + @echo "$(notdir $<)" + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" + +-include $(OBJECTS:%.o=%.d) +ifneq (,$(PCH)) + -include $(PCH_PLACEHOLDER).d +endif \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 00000000..a8f6b73d --- /dev/null +++ b/src/main.c @@ -0,0 +1,492 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + main.c - main executable entry + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +#include "main.h" +#include "common.h" +#include "output.h" +#include "peldd.h" +#include "peres.h" +#include "pesec.h" +#include "pestr.h" +#include "readpe.h" +#include +#include +#include +#include +#include +#include + +enum ARGUMENTS { + ARG_NONE = 0, + + ARG_HELP = 1, + ARG_COMPLETE = 2, + ARG_VERSION = 'V', + + MODE_START = 1000, + MODE_HEADER = 1000, + MODE_HEADER_DOS, + MODE_HEADER_COFF, + MODE_HEADER_OPTIONAL, + MODE_DIRECTORY = 1100, + MODE_EXPORTS, + MODE_IMPORTS, + MODE_RESOURCES, // -- peres + // MODE_EXCEPTIONS, + MODE_CERTIFICATES, // not part of image / -- pesec + // MODE_BASE_RELOCATIONS, + // MODE_DEBUG, + // MODE_ARCHITECTURE, + // MODE_GLOBAL_PTR, + // MODE_TLS, + // MODE_LOAD_CONFIGS, + // MODE_BOUND_IMPORT, + // MODE_IAT, + // MODE_DELAY_IMPORT_DESCRIPTOR, + // MODE_CLR_RUNTIME_HEADER, + MODE_SECURITY, // TODO: Duplicate of MODE_CERTIFICATES, + MODE_SECTION = 1200, + MODE_LIBRARY = 1300, // -- peldd + MODE_STRINGS = 1400, // -- pestr + // MODE_STRINGS_ASCII, + // MODE_STRINGS_UNICODE, + MODE_END, + + COMMAND_SCAN = 2000, // -- pescan + COMMAND_HASH = 2100, // -- pehash + // COMMAND_HASH_MD5, + // COMMAND_HASH_SHA1, + // COMMAND_HASH_SHA256, + // COMMAND_HASH_SSDEEP, + // COMMAND_HASH_IMPHASH, + + COMMAND_DISASSAMBLE = 100000, // -- pedis + COMMAND_PACK, // -- pepack + COMMAND_TRANSFORM = 101000, + // COMMAND_ADDRESSING_RELATIVE, // -- ofs2rva + // COMMAND_ADDRESSING_OFFSET, // -- rva2ofs +}; + +enum HASH_ALGO { + HASH_MD5, + HASH_SHA1, + HASH_SHA256, + HASH_SSDEEP, + HASH_IMPHASH, + HASH_ALL +}; + +static struct argument_options_t { + unsigned int list : 1; + unsigned int all : 1; +} argument_options; + +typedef struct { + const char *const name; + const void *const sub; + const int has_arg; + const int *const flag; + const int val; +} mode_option; + +int getopt_mode(int argc, char *const argv[], const mode_option **mode_options, + int *restrict select, int *restrict index) { + if (*index >= argc) return -1; + char *const arg = argv[*index]; + *index += 1; + + int val = 0; + + for (int i = 0; (*mode_options)[i].name != NULL; ++i) { + mode_option opt = (*mode_options)[i]; + // printf("%s %s\n", arg, opt.name); + if (strcmp(arg, opt.name) == 0) { + val = opt.val; + if (opt.sub != NULL) { + *mode_options = opt.sub; + } + if (val >= MODE_START) { + *select = val; + } + break; + } + } + + return val; +} + +// GNU compliant version output +void version(void) { + printf("readpe %s\n" + "Copyright (C) 2023 readpe authors\n" + "License GPLv2+: GNU GPL version 2 or later " + ".\n" + "This is free software: " + "you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n", + VERSION); + exit(EXIT_SUCCESS); +} + +// GNU compliant help output +void help(void) { + printf("Usage: readpe [] [] [] []\n"); + + printf("\nReport bugs to: https://github.com/mentebinaria/readpe/issues\n"); + exit(EXIT_SUCCESS); +} + +void complete(const mode_option *opts) { + size_t i = 0; + const mode_option *c; + while ((c = &opts[i])) { + if (c->name == NULL) break; + printf("%s ", c->name); + ++i; + } + printf("\n"); + exit(EXIT_SUCCESS); +} + +void usage(void) {} + +int main(int argc, char *argv[]) { + const char *tmp_name = strrchr(argv[0], '/'); + // If no '/' in caller (called from env) we set it to the original caller + const char *bin_name = tmp_name ? tmp_name + 1 : argv[0]; + + // Legacy executables + if (strstr(bin_name, "pedis") == bin_name) exit(pedis(argc, argv)); + if (strstr(bin_name, "peldd") == bin_name) exit(peldd(argc, argv)); + if (strstr(bin_name, "peres") == bin_name) exit(peres(argc, argv)); + if (strstr(bin_name, "pesec") == bin_name) exit(pesec(argc, argv)); + if (strstr(bin_name, "pestr") == bin_name) exit(pestr(argc, argv)); + if (strstr(bin_name, "pehash") == bin_name) exit(pehash(argc, argv)); + if (strstr(bin_name, "pepack") == bin_name) exit(pepack(argc, argv)); + if (strstr(bin_name, "pescan") == bin_name) exit(pescan(argc, argv)); + if (strstr(bin_name, "ofs2rva") == bin_name) exit(ofs2rva(argc, argv)); + if (strstr(bin_name, "rva2ofs") == bin_name) exit(rva2ofs(argc, argv)); + + static const mode_option header_mode[] = { + {"dos", NULL, 0, NULL, MODE_HEADER_DOS }, + {"coff", NULL, 0, NULL, MODE_HEADER_COFF }, + {"optional", NULL, 0, NULL, MODE_HEADER_OPTIONAL}, + {"--list", NULL, 0, NULL, 'l' }, + {"--help", NULL, 0, NULL, 1 }, + {NULL, NULL, 0, NULL, 0 } + }; + + static const mode_option resource_mode[] = { + {"--info", NULL, 0, NULL, 'i'}, + {"--statistics", NULL, 0, NULL, 's'}, + {"--extract", NULL, 0, NULL, 'e'}, + {"--name-extract", NULL, 0, NULL, 'n'}, + {"--file-version", NULL, 0, NULL, 'v'}, + {"--list", NULL, 0, NULL, 'l'}, + {"--help", NULL, 0, NULL, 1 }, + {NULL, NULL, 0, NULL, 0 } + }; + + static const mode_option directory_mode[] = { + {"--list", NULL, 0, NULL, 'l'}, + {"--help", NULL, 0, NULL, 1 }, + {NULL, NULL, 0, NULL, 0 } + }; + + static const mode_option section_mode[] = { + {"--list", NULL, 0, NULL, 'l'}, + {"--help", NULL, 0, NULL, 1 }, + {NULL, NULL, 0, NULL, 0 } + }; + + // static const mode_option hash_mode[] = { + // {"md5", NULL, 0, NULL, COMMAND_HASH_MD5 }, + // {"sha1", NULL, 0, NULL, COMMAND_HASH_SHA1 }, + // {"sha256", NULL, 0, NULL, COMMAND_HASH_SHA256 }, + // {"ssdeep", NULL, 0, NULL, COMMAND_HASH_SSDEEP }, + // {"impash", NULL, 0, NULL, COMMAND_HASH_IMPHASH}, + // {"--list", NULL, 0, NULL, 'l' }, + // {"--help", NULL, 0, NULL, 1 }, + // {NULL, NULL, 0, NULL, 0 }, + // }; + + static const mode_option base_mode[] = { + {"headers", header_mode, 0, NULL, MODE_HEADER }, + {"directories", directory_mode, 0, NULL, MODE_DIRECTORY }, + {"exports", NULL, 0, NULL, MODE_EXPORTS }, + {"imports", NULL, 0, NULL, MODE_IMPORTS }, + {"resources", NULL, 0, NULL, MODE_RESOURCES }, + {"certificates", NULL, 0, NULL, MODE_CERTIFICATES}, + {"sections", section_mode, 0, NULL, MODE_SECTION }, + {"libraries", NULL, 0, NULL, MODE_LIBRARY }, + {"strings", NULL, 0, NULL, MODE_STRINGS }, + {"security", NULL, 0, NULL, MODE_SECURITY }, + {"hash", NULL, optional_argument, NULL, COMMAND_HASH }, + {"scan", NULL, 0, NULL, COMMAND_SCAN }, + {"--format", NULL, 0, NULL, 'f' }, + {"--version", NULL, 0, NULL, 'V' }, + {"--complete", NULL, 0, NULL, 2 }, + {"--help", NULL, 0, NULL, 1 }, + {NULL, NULL, 0, NULL, 0 } + }; + + //------------------------------------------------------------------------// + /* + static const struct option common_options[] = { + {"format", required_argument, NULL, 'f'}, + {"version", no_argument, NULL, 'V'}, + {"help", no_argument, NULL, 1 }, + {NULL, 0, NULL, 0 } + }; + + static const struct option legacy_options[] = { + {"all", no_argument, NULL, 'A'}, + {"all-headers", no_argument, NULL, 'H'}, + {"all-sections", no_argument, NULL, 'S'}, + {"header", required_argument, NULL, 'h'}, + {"imports", no_argument, NULL, 'i'}, + {"exports", no_argument, NULL, 'e'}, + {"dirs", no_argument, NULL, 'd'}, + {NULL, 0, NULL, 0 } + }; + */ + + if (argc < 2) help(); + + const mode_option *mode = base_mode; + int c, f_arg = 0, select = 0, index = 1; + + if (access(argv[index], F_OK) == 0) { + f_arg = index; + ++index; + } + + while ((c = getopt_mode(argc, argv, &mode, &select, &index))) { + if (c < 0) break; + // printf("%i\n", c); + + switch (c) { + case 1: + help(); + break; + case 2: + complete(mode); + break; + case 'V': + version(); + break; + case 'a': + argument_options.all = true; + break; + case 'l': + argument_options.list = true; + break; + + default: + break; + // exit(EXIT_FAILURE); + } + } + + if ((f_arg == 0) && (access(argv[argc - 1], F_OK) == 0)) { + f_arg = argc - 1; + } + if (f_arg == 0) help(); + + // printf("%i\n", file); + + pe_ctx_t ctx; + pe_err_e err = pe_load_file(&ctx, argv[f_arg]); + if (err != LIBPE_E_OK) { + pe_error_print(stderr, err); + return EXIT_FAILURE; + } + + err = pe_parse(&ctx); + if (err != LIBPE_E_OK) { + pe_error_print(stderr, err); + return EXIT_FAILURE; + } + + if (!pe_is_pe(&ctx)) EXIT_ERROR("not a valid PE file"); + + pev_config_t config; + PEV_INITIALIZE(&config); + + output_open_document(); + + switch (select) { + case MODE_HEADER: + // TODO: --list, --all + printf("* dos\n* coff\n* optional\n"); + break; + + case MODE_HEADER_DOS: + print_dos_header(&ctx); + break; + case MODE_HEADER_COFF: + print_coff_header(&ctx); + break; + case MODE_HEADER_OPTIONAL: + print_optional_header(&ctx); + break; + + case MODE_DIRECTORY: { + IMAGE_DATA_DIRECTORY **directories = get_pe_directories(&ctx); + if (directories != NULL) print_directories(&ctx); + break; + } + + case MODE_EXPORTS: { + IMAGE_DATA_DIRECTORY **directories = get_pe_directories(&ctx); + if (directories != NULL) print_exports(&ctx); + break; + } + + case MODE_IMPORTS: { + IMAGE_DATA_DIRECTORY **directories = get_pe_directories(&ctx); + if (directories != NULL) print_imports(&ctx); + break; + } + + case MODE_RESOURCES: { + pe_resources_t *resources = pe_resources(&ctx); + if (resources == NULL || resources->err != LIBPE_E_OK) { + LIBPE_WARNING("This file has no resources"); + return EXIT_SUCCESS; + } + + pe_resource_node_t *root_node = resources->root_node; + + peres_show_nodes(&ctx, root_node); + peres_show_stats(root_node); + peres_show_list(&ctx, root_node); + // peres_save_all_resources(&ctx, root_node, options->namedExtract); + peres_show_version(&ctx, root_node); + break; + } + + // case MODE_EXCEPTIONS: + + case MODE_SECURITY: + print_securities(&ctx); + // fall through + case MODE_CERTIFICATES: { + // TODO: settings + certificate_settings set = {1, NULL}; + parse_certificates(&set, &ctx); + break; + } + + // case MODE_BASE_RELOCATIONS: + // case MODE_DEBUG: + // case MODE_ARCHITECTURE: + // case MODE_GLOBAL_PTR: + // case MODE_TLS: + // case MODE_LOAD_CONFIGS: + // case MODE_BOUND_IMPORT: + // case MODE_IAT: + // case MODE_DELAY_IMPORT_DESCRIPTOR: + // case MODE_CLR_RUNTIME_HEADER: + + case MODE_SECTION: { + if (pe_sections(&ctx) != NULL) + print_sections(&ctx); + else { + LIBPE_WARNING("unable to read sections"); + } + break; + } + + case MODE_LIBRARY: { + IMAGE_DATA_DIRECTORY **directories = pe_directories(&ctx); + if (directories == NULL) { + LIBPE_WARNING("directories not found"); + } else { + print_dependencies(&ctx); + } + + break; + } + + case MODE_STRINGS: { + string_settings set; + print_strings(&ctx, &set); + break; + } + + case COMMAND_HASH: + // case COMMAND_HASH_MD5: + // case COMMAND_HASH_SHA1: + // case COMMAND_HASH_SHA256: + // case COMMAND_HASH_SSDEEP: + // case COMMAND_HASH_IMPHASH: + // TODO + printf("Not Implemented\n"); + break; + + case COMMAND_SCAN: { + // TODO + printf("Not Implemented\n"); + break; + } + + case COMMAND_DISASSAMBLE: + case COMMAND_PACK: + case COMMAND_TRANSFORM: + // case COMMAND_ADDRESSING_RELATIVE: + // case COMMAND_ADDRESSING_OFFSET: + printf("Not Implemented\n"); + break; + default: + // printf("Unknown Argument: %d\n", select); + break; + } + + output_close_document(); + + // free + err = pe_unload(&ctx); + if (err != LIBPE_E_OK) { + pe_error_print(stderr, err); + return EXIT_FAILURE; + } + + PEV_FINALIZE(&config); + + return EXIT_SUCCESS; +} + diff --git a/src/main.h b/src/main.h new file mode 100644 index 00000000..7afd3022 --- /dev/null +++ b/src/main.h @@ -0,0 +1,51 @@ +/* vim: set ts=4 sw=4 noet: */ +/* + readpe - the PE file analyzer toolkit + + main.h - main executable entry + + Copyright (C) 2023 readpe authors + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. +*/ + +int pedis(int argc, char *argv[]); +int pehash(int argc, char *argv[]); +int peldd(int argc, char *argv[]); +int pepack(int argc, char *argv[]); +int peres(int argc, char *argv[]); +int pescan(int argc, char *argv[]); +int pesec(int argc, char *argv[]); +int pestr(int argc, char *argv[]); + +int ofs2rva(int argc, char *argv[]); +int rva2ofs(int argc, char *argv[]); + +int _main(int argc, char *argv[]); + + diff --git a/src/ofs2rva.c b/src/ofs2rva.c index be06cddf..1729ebb3 100644 --- a/src/ofs2rva.c +++ b/src/ofs2rva.c @@ -34,9 +34,10 @@ files in the program, then also delete it here. */ +#include "main.h" +#include "common.h" // FIX: Needed if strtoull() is used and to test overflow. #include -#include "common.h" #define PROGRAM "ofs2rva" @@ -84,7 +85,7 @@ static void parse_options(int argc, char *argv[]) } } -int main(int argc, char *argv[]) +int ofs2rva(int argc, char *argv[]) { //PEV_INITIALIZE(); diff --git a/src/pedis.c b/src/pedis.c index b3e89db2..a8f5267f 100644 --- a/src/pedis.c +++ b/src/pedis.c @@ -34,11 +34,12 @@ files in the program, then also delete it here. */ +#include "main.h" #include "common.h" -#include "../lib/libudis86/udis86.h" +#include "plugins.h" #include #include -#include "plugins.h" +#include #define PROGRAM "pedis" @@ -316,7 +317,7 @@ static void disassemble_offset(pe_ctx_t *ctx, const options_t *options, ud_t *ud } } -int main(int argc, char *argv[]) +int pedis(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); diff --git a/src/pehash.c b/src/pehash.c index f2a33f43..7f51b5a6 100644 --- a/src/pehash.c +++ b/src/pehash.c @@ -34,6 +34,7 @@ files in the program, then also delete it here. */ +#include "main.h" #include "common.h" #include "plugins.h" @@ -189,7 +190,7 @@ static void print_basic_hash(const unsigned char *data, size_t data_size) free(hash_value); } -int main(int argc, char *argv[]) +int pehash(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); diff --git a/src/peldd.c b/src/peldd.c index 18bcc1f5..bc1fa741 100644 --- a/src/peldd.c +++ b/src/peldd.c @@ -34,9 +34,11 @@ files in the program, then also delete it here. */ +#include "peldd.h" +#include "main.h" #include "common.h" -#include #include "output.h" +#include #define PROGRAM "peldd" @@ -92,7 +94,7 @@ static void parse_options(int argc, char *argv[]) } } -static void print_dependencies(pe_ctx_t *ctx) +void print_dependencies(pe_ctx_t *ctx) { output_open_scope("Dependencies", OUTPUT_SCOPE_TYPE_ARRAY); const pe_imports_t *imports = pe_imports(ctx); @@ -103,7 +105,7 @@ static void print_dependencies(pe_ctx_t *ctx) output_close_scope(); } -int main(int argc, char *argv[]) +int peldd(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); diff --git a/src/pepack.c b/src/pepack.c index cacf5478..b7f9794c 100644 --- a/src/pepack.c +++ b/src/pepack.c @@ -34,6 +34,7 @@ files in the program, then also delete it here. */ +#include "main.h" #include "common.h" #include "plugins.h" @@ -241,7 +242,7 @@ static bool compare_signature(const unsigned char *data, uint64_t ep_offset, FIL return false; } -int main(int argc, char *argv[]) +int pepack(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); diff --git a/src/peres.c b/src/peres.c index b766835d..2f8c375b 100644 --- a/src/peres.c +++ b/src/peres.c @@ -34,6 +34,8 @@ files in the program, then also delete it here. */ +#include "peres.h" +#include "main.h" #include "common.h" #include #include @@ -256,7 +258,7 @@ static void peres_show_node(pe_ctx_t *ctx, const pe_resource_node_t *node) } } -static void peres_show_nodes(pe_ctx_t *ctx, const pe_resource_node_t *node) +void peres_show_nodes(pe_ctx_t *ctx, const pe_resource_node_t *node) { if (node == NULL) return; @@ -303,7 +305,7 @@ static void peres_show_list_node(pe_ctx_t *ctx, const pe_resource_node_t *node) printf("%s (%d bytes)\n", node_info, node->raw.dataEntry->Size); } -static void peres_show_list(pe_ctx_t *ctx, const pe_resource_node_t *node) +void peres_show_list(pe_ctx_t *ctx, const pe_resource_node_t *node) { if (node == NULL) return; @@ -527,7 +529,7 @@ static void peres_save_resource(pe_ctx_t *ctx, const pe_resource_node_t *node, b free( relativeFileName ); } -static void peres_save_all_resources(pe_ctx_t *ctx, const pe_resource_node_t *node, bool namedExtract) +void peres_save_all_resources(pe_ctx_t *ctx, const pe_resource_node_t *node, bool namedExtract) { if (node == NULL) return; @@ -548,7 +550,7 @@ bool peres_contains_version_node(const pe_resource_node_t *node) { return node->raw.directoryEntry->u0.data.NameOffset == RT_VERSION; } -static void peres_show_version(pe_ctx_t *ctx, const pe_resource_node_t *node) +void peres_show_version(pe_ctx_t *ctx, const pe_resource_node_t *node) { if (node == NULL) return; @@ -628,7 +630,7 @@ static void peres_generate_stats(peres_stats_t *stats, const pe_resource_node_t } } -static void peres_show_stats(const pe_resource_node_t *node) +void peres_show_stats(const pe_resource_node_t *node) { peres_stats_t stats = {0}; peres_generate_stats(&stats, node); @@ -651,7 +653,7 @@ static void peres_show_stats(const pe_resource_node_t *node) output("Total Data Entry", value); } -int main(int argc, char **argv) +int peres(int argc, char **argv) { pev_config_t config; PEV_INITIALIZE(&config); diff --git a/src/pescan.c b/src/pescan.c index c8e9d19b..7d0578b7 100644 --- a/src/pescan.c +++ b/src/pescan.c @@ -34,11 +34,12 @@ files in the program, then also delete it here. */ +#include "main.h" #include "common.h" +#include "plugins.h" #include #include #include -#include "plugins.h" #define PROGRAM "pescan" @@ -453,7 +454,7 @@ static int8_t cpl_analysis(pe_ctx_t *ctx) return 0; } -int main(int argc, char *argv[]) +int pescan(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); diff --git a/src/pesec.c b/src/pesec.c index 8d400a0c..842d0a6a 100644 --- a/src/pesec.c +++ b/src/pesec.c @@ -34,26 +34,22 @@ files in the program, then also delete it here. */ +#include "pesec.h" +#include "libpe/context.h" +#include "libpe/pe.h" +#include "main.h" #include "common.h" +#include "compat/strlcat.h" +#include "plugins.h" #include #include #include #include -#include "compat/strlcat.h" -#include "plugins.h" #define PROGRAM "pesec" -typedef enum { - CERT_FORMAT_TEXT = 1, - CERT_FORMAT_PEM = 2, - CERT_FORMAT_DER = 3 -} cert_format_e; - -typedef struct { - cert_format_e certoutform; - BIO *certout; -} options_t; +// FIXME +typedef certificate_settings options_t; static void usage(void) { @@ -175,7 +171,7 @@ find stack cookies, a.k.a canary, buffer security check option in MVS 2010 */ // FIXME: What about other versions? -static bool stack_cookies(pe_ctx_t *ctx) +bool stack_cookies(pe_ctx_t *ctx) { static const unsigned char mvs2010[] = { 0x55, 0x8b, 0xec, 0x83, @@ -203,6 +199,40 @@ static bool stack_cookies(pe_ctx_t *ctx) return found == sizeof(mvs2010); } +void print_securities(pe_ctx_t *ctx) +{ + IMAGE_OPTIONAL_HEADER *optional = pe_optional(ctx); + if (optional == NULL) exit(EXIT_FAILURE); // FIXME: exit + + uint16_t dllchar = 0; + switch (optional->type) { + default: + exit(EXIT_FAILURE); // FIXME: exit + case MAGIC_PE32: + dllchar = optional->_32->DllCharacteristics; + break; + case MAGIC_PE64: + dllchar = optional->_64->DllCharacteristics; + break; + } + static char field[MAX_MSG]; + // aslr + snprintf(field, MAX_MSG, "ASLR"); + output(field, (dllchar & 0x40) ? "yes" : "no"); + + // dep/nx + snprintf(field, MAX_MSG, "DEP/NX"); + output(field, (dllchar & 0x100) ? "yes" : "no"); + + // seh + snprintf(field, MAX_MSG, "SEH"); + output(field, (dllchar & 0x400) ? "no" : "yes"); + + // stack cookies + snprintf(field, MAX_MSG, "Stack cookies (EXPERIMENTAL)"); + output(field, stack_cookies(ctx) ? "yes" : "no"); +} + static void print_certificate(BIO *out, cert_format_e format, X509 *cert) { if (out == NULL) @@ -329,7 +359,7 @@ static int parse_pkcs7_data(const options_t *options, const CRYPT_DATA_BLOB *blo return result; } -static void parse_certificates(const options_t *options, pe_ctx_t *ctx) +void parse_certificates(const options_t *options, pe_ctx_t *ctx) { const IMAGE_DATA_DIRECTORY * const directory = pe_directory_by_entry(ctx, IMAGE_DIRECTORY_ENTRY_SECURITY); if (directory == NULL) @@ -432,7 +462,7 @@ static void parse_certificates(const options_t *options, pe_ctx_t *ctx) output_close_scope(); // certificates } -int main(int argc, char *argv[]) +int pesec(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); @@ -464,41 +494,7 @@ int main(int argc, char *argv[]) if (!pe_is_pe(&ctx)) EXIT_ERROR("not a valid PE file"); - IMAGE_OPTIONAL_HEADER *optional = pe_optional(&ctx); - if (optional == NULL) - return EXIT_FAILURE; - - uint16_t dllchar = 0; - switch (optional->type) { - default: - return EXIT_FAILURE; - case MAGIC_PE32: - dllchar = optional->_32->DllCharacteristics; - break; - case MAGIC_PE64: - dllchar = optional->_64->DllCharacteristics; - break; - } - - output_open_document(); - - static char field[MAX_MSG]; - - // aslr - snprintf(field, MAX_MSG, "ASLR"); - output(field, (dllchar & 0x40) ? "yes" : "no"); - - // dep/nx - snprintf(field, MAX_MSG, "DEP/NX"); - output(field, (dllchar & 0x100) ? "yes" : "no"); - - // seh - snprintf(field, MAX_MSG, "SEH"); - output(field, (dllchar & 0x400) ? "no" : "yes"); - - // stack cookies - snprintf(field, MAX_MSG, "Stack cookies (EXPERIMENTAL)"); - output(field, stack_cookies(&ctx) ? "yes" : "no"); + print_securities(&ctx); // certificados parse_certificates(options, &ctx); diff --git a/src/pestr.c b/src/pestr.c index 62efbfaf..26b6119c 100644 --- a/src/pestr.c +++ b/src/pestr.c @@ -34,6 +34,8 @@ files in the program, then also delete it here. */ +#include "pestr.h" +#include "main.h" #include "common.h" #include #include @@ -44,11 +46,8 @@ #define BUFSIZE 4 #define LINE_BUFFER 32768 -typedef struct { - unsigned short strsize; - bool offset; - bool section; -} options_t; +// FIXME +typedef string_settings options_t; static void usage(void) { @@ -181,35 +180,9 @@ static void printb( pe_ctx_t *ctx, putchar('\n'); } -int main(int argc, char *argv[]) -{ - if (argc < 2) { - usage(); - exit(EXIT_FAILURE); - } - - options_t *options = parse_options(argc, argv); // opcoes - - const char *path = argv[argc-1]; - pe_ctx_t ctx; - - pe_err_e err = pe_load_file(&ctx, path); - if (err != LIBPE_E_OK) { - pe_error_print(stderr, err); - return EXIT_FAILURE; - } - - err = pe_parse(&ctx); - if (err != LIBPE_E_OK) { - pe_error_print(stderr, err); - return EXIT_FAILURE; - } - - if (!pe_is_pe(&ctx)) - EXIT_ERROR("not a valid PE file"); - - const uint64_t pe_size = pe_filesize(&ctx); - const uint8_t *pe_raw_data = ctx.map_addr; +void print_strings( pe_ctx_t *ctx, const options_t *options) { + const uint64_t pe_size = pe_filesize(ctx); + const uint8_t *pe_raw_data = ctx->map_addr; uint16_t chunk; size_t buff_start = 0; @@ -232,7 +205,7 @@ int main(int argc, char *argv[]) } else { if ( buff_start != 0 ) { if ((pe_raw_offset - buff_start) >= (options->strsize ? options->strsize : 4)) - printb(&ctx, options, pe_raw_data, buff_start, pe_raw_offset, false); + printb(ctx, options, pe_raw_data, buff_start, pe_raw_offset, false); buff_start = 0; } } @@ -251,18 +224,49 @@ int main(int argc, char *argv[]) if( pe_raw_offset & 0x1 ) { if ( odd_wbuff_start != 0 ) { if ((pe_raw_offset - odd_wbuff_start)/2 >= (options->strsize ? options->strsize : 4)) - printb(&ctx, options, pe_raw_data, odd_wbuff_start, pe_raw_offset, true); + printb(ctx, options, pe_raw_data, odd_wbuff_start, pe_raw_offset, true); odd_wbuff_start = 0; } } else { if ( even_wbuff_start != 0 ) { if ((pe_raw_offset - even_wbuff_start)/2 >= (options->strsize ? options->strsize : 4)) - printb(&ctx, options, pe_raw_data, even_wbuff_start, pe_raw_offset, true); + printb(ctx, options, pe_raw_data, even_wbuff_start, pe_raw_offset, true); even_wbuff_start = 0; } } } } +} + +int pestr(int argc, char *argv[]) +{ + if (argc < 2) { + usage(); + exit(EXIT_FAILURE); + } + + options_t *options = parse_options(argc, argv); // opcoes + + const char *path = argv[argc-1]; + pe_ctx_t ctx; + + pe_err_e err = pe_load_file(&ctx, path); + if (err != LIBPE_E_OK) { + pe_error_print(stderr, err); + return EXIT_FAILURE; + } + + err = pe_parse(&ctx); + if (err != LIBPE_E_OK) { + pe_error_print(stderr, err); + return EXIT_FAILURE; + } + + if (!pe_is_pe(&ctx)) + EXIT_ERROR("not a valid PE file"); + + print_strings(&ctx, options); + // libera a memoria free_options(options); diff --git a/src/readpe.c b/src/readpe.c index 74ca94f9..6d8cbf7e 100644 --- a/src/readpe.c +++ b/src/readpe.c @@ -34,10 +34,14 @@ files in the program, then also delete it here. */ +#include "readpe.h" +#include "libpe/context.h" +#include "libpe/directories.h" +#include "main.h" #include "common.h" +#include "output.h" #include #include -#include "output.h" #define PROGRAM "readpe" @@ -74,6 +78,15 @@ static void usage(void) PROGRAM, PROGRAM, formats); } +IMAGE_DATA_DIRECTORY **get_pe_directories(pe_ctx_t *ctx) +{ + IMAGE_DATA_DIRECTORY **directories = pe_directories(ctx); + if (directories == NULL) + LIBPE_WARNING("directories not found"); + + return directories; +} + static void parse_headers(options_t *options, const char *optarg) { if (!strcmp(optarg, "dos")) @@ -173,7 +186,7 @@ static options_t *parse_options(int argc, char *argv[]) return options; } -static void print_sections(pe_ctx_t *ctx) +void print_sections(pe_ctx_t *ctx) { #ifdef LIBPE_ENABLE_OUTPUT_COMPAT_WITH_V06 static const char * const flags_name[] = { @@ -276,7 +289,7 @@ static void print_sections(pe_ctx_t *ctx) output_close_scope(); // Sections } -static void print_directories(pe_ctx_t *ctx) +void print_directories(pe_ctx_t *ctx) { #ifdef LIBPE_ENABLE_OUTPUT_COMPAT_WITH_V06 typedef struct { @@ -333,8 +346,12 @@ static void print_directories(pe_ctx_t *ctx) output_close_scope(); // Data directories } -static void print_optional_header(IMAGE_OPTIONAL_HEADER *header) +void print_optional_header(pe_ctx_t *ctx) { + IMAGE_OPTIONAL_HEADER *header = pe_optional(ctx); + if (!header) + LIBPE_WARNING("unable to read Optional (Image) file header"); + #ifdef LIBPE_ENABLE_OUTPUT_COMPAT_WITH_V06 typedef struct { WindowsSubsystem subsystem; @@ -599,8 +616,12 @@ static void print_optional_header(IMAGE_OPTIONAL_HEADER *header) output_close_scope(); // Optional/Image heade } -static void print_coff_header(IMAGE_COFF_HEADER *header) +void print_coff_header(pe_ctx_t *ctx) { + IMAGE_COFF_HEADER *header = pe_coff(ctx); + if (!header) + LIBPE_WARNING("unable to read COFF file header"); + #ifdef LIBPE_ENABLE_OUTPUT_COMPAT_WITH_V06 typedef struct { ImageCharacteristics characteristic; @@ -721,8 +742,13 @@ static void print_coff_header(IMAGE_COFF_HEADER *header) output_close_scope(); // COFF/File header } -static void print_dos_header(IMAGE_DOS_HEADER *header) +void print_dos_header(pe_ctx_t *ctx) { + + IMAGE_DOS_HEADER *header = pe_dos(ctx); + if (!header) + LIBPE_WARNING("unable to read DOS header"); + char s[MAX_MSG]; output_open_scope("DOS Header", OUTPUT_SCOPE_TYPE_OBJECT); @@ -778,7 +804,7 @@ static void print_dos_header(IMAGE_DOS_HEADER *header) output_close_scope(); // DOS Header } -static void print_exports(pe_ctx_t *ctx) +void print_exports(pe_ctx_t *ctx) { output_open_scope("Exported functions", OUTPUT_SCOPE_TYPE_ARRAY); @@ -824,7 +850,7 @@ static void print_exports(pe_ctx_t *ctx) output_close_scope(); // Exported functions } -static void print_imports(pe_ctx_t *ctx) +void print_imports(pe_ctx_t *ctx) { output_open_scope("Imported functions", OUTPUT_SCOPE_TYPE_ARRAY); @@ -860,7 +886,7 @@ static void print_imports(pe_ctx_t *ctx) output_close_scope(); // Imported functions } -int main(int argc, char *argv[]) +int _main(int argc, char *argv[]) { pev_config_t config; PEV_INITIALIZE(&config); @@ -895,59 +921,37 @@ int main(int argc, char *argv[]) // dos header if (options->dos || options->all_headers || options->all) { - IMAGE_DOS_HEADER *header_ptr = pe_dos(&ctx); - if (header_ptr) - print_dos_header(header_ptr); - else { LIBPE_WARNING("unable to read DOS header"); } + print_dos_header(&ctx); } // coff/file header if (options->coff || options->all_headers || options->all) { - IMAGE_COFF_HEADER *header_ptr = pe_coff(&ctx); - if (header_ptr) - print_coff_header(header_ptr); - else { LIBPE_WARNING("unable to read COFF file header"); } + print_coff_header(&ctx); } // optional header if (options->opt || options->all_headers || options->all) { - IMAGE_OPTIONAL_HEADER *header_ptr = pe_optional(&ctx); - if (header_ptr) - print_optional_header(header_ptr); - else { LIBPE_WARNING("unable to read Optional (Image) file header"); } + print_optional_header(&ctx); } - IMAGE_DATA_DIRECTORY **directories = pe_directories(&ctx); - bool directories_warned = false; + IMAGE_DATA_DIRECTORY **directories = get_pe_directories(&ctx); // directories if (options->dirs || options->all) { if (directories != NULL) print_directories(&ctx); - else if (!directories_warned) { - LIBPE_WARNING("directories not found"); - directories_warned = true; - } } // imports if (options->imports || options->all) { if (directories != NULL) print_imports(&ctx); - else if (!directories_warned) { - LIBPE_WARNING("directories not found"); - directories_warned = true; - } } // exports if (options->exports || options->all) { if (directories != NULL) print_exports(&ctx); - else if (!directories_warned) { - LIBPE_WARNING("directories not found"); - directories_warned = true; - } } // sections diff --git a/src/rva2ofs.c b/src/rva2ofs.c index 5374d07c..8d73f8fb 100644 --- a/src/rva2ofs.c +++ b/src/rva2ofs.c @@ -34,6 +34,7 @@ files in the program, then also delete it here. */ +#include "main.h" #include "common.h" #define PROGRAM "rva2ofs" @@ -82,7 +83,7 @@ static void parse_options(int argc, char *argv[]) } } -int main(int argc, char *argv[]) +int rva2ofs(int argc, char *argv[]) { //PEV_INITIALIZE();