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();