summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile.in14
-rw-r--r--config.lzy28
-rwxr-xr-xconfigure114
-rw-r--r--include/pemagine/bits/nt32/pe_inline_asm__gcc.h89
-rw-r--r--include/pemagine/bits/nt32/pe_inline_asm__msvc.h67
-rw-r--r--include/pemagine/bits/nt64/pe_inline_asm__gcc.h87
-rw-r--r--include/pemagine/bits/nt64/pe_inline_asm__msvc.h58
-rw-r--r--include/pemagine/pe_api.h36
-rw-r--r--include/pemagine/pe_consts.h371
-rw-r--r--include/pemagine/pe_inline_asm.h20
-rw-r--r--include/pemagine/pe_structs.h635
-rw-r--r--include/pemagine/pemagine.h196
-rw-r--r--pemagine.lzy128
-rw-r--r--src/exports/pe_enum_image_exports.c61
-rw-r--r--src/exports/pe_get_export_symbol_info.c142
-rw-r--r--src/exports/pe_get_procedure_address.c18
-rw-r--r--src/headers/pe_get_image_coff_hdr_addr.c30
-rw-r--r--src/headers/pe_get_image_data_dirs_addr.c33
-rw-r--r--src/headers/pe_get_image_dos_hdr_addr.c24
-rw-r--r--src/headers/pe_get_image_entry_point_addr.c39
-rw-r--r--src/headers/pe_get_image_opt_hdr_addr.c20
-rw-r--r--src/headers/pe_get_image_special_hdr_addr.c49
-rw-r--r--src/imports/pe_enum_image_import_hdrs.c35
-rw-r--r--src/internal/pe_impl.c51
-rw-r--r--src/internal/pe_impl.h17
-rw-r--r--src/internal/pe_lib_entry_point.c6
-rw-r--r--src/meta/pe_get_image_stack_heap_info.c43
-rw-r--r--src/meta/pe_get_symbol_module_info.c56
-rw-r--r--src/meta/pe_get_symbol_name.c209
-rw-r--r--src/modules/pe_enum_modules.c102
-rw-r--r--src/modules/pe_get_kernel32_module_handle.c73
-rw-r--r--src/modules/pe_get_module_handle.c80
-rw-r--r--src/modules/pe_get_ntdll_module_handle.c27
33 files changed, 2958 insertions, 0 deletions
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..b370cb0
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,14 @@
+all:
+ ./lazy -x build
+
+install:
+ ./lazy -x build -e install
+
+clean:
+ rm -rf src
+ rm -rf lib
+ rm -f lazy
+ rm -f lazy.config.tag
+ rm -f lz_stack
+ rm -f *.objs
+ rm -rf *.lst
diff --git a/config.lzy b/config.lzy
new file mode 100644
index 0000000..9f71770
--- /dev/null
+++ b/config.lzy
@@ -0,0 +1,28 @@
+# package
+lz_package=pemagine
+
+
+# toolchain
+lz_default_target=x86_64-nt64-midipix
+lz_default_arch=x86_64
+lz_default_compiler=gcc
+
+
+# lazy
+lz_cflags_cmdline=
+lz_cxxflags_cmdline=
+lz_ldflags_cmdline=
+
+lz_cflags_debug=
+lz_cflags_release=
+
+lz_cflags_include_first=
+lz_cflags_include_last=
+lz_cflags_include_cmdline=
+lz_cxxflags_include_cmdline=
+
+lz_exec_prefix=
+lz_bindir=
+lz_libdir=
+lz_includedir=
+lz_syslibdir=
diff --git a/configure b/configure
new file mode 100755
index 0000000..1e02d8f
--- /dev/null
+++ b/configure
@@ -0,0 +1,114 @@
+#!/bin/sh
+
+# a simple configure-make wrapper for use in conjunction with the 'lazy' build script.
+# 'lazy' is deviant, occasionally useful, and permissively licensed; get_lazy() below,
+# then look for configure.template in the root directory.
+
+init_vars()
+{
+ lz_config_dir=`readlink -f $(dirname $0)`
+ lz_pwd=`pwd`
+
+ if [ x"$lz_config" = x ]; then
+ . $lz_config_dir/config.lzy || exit 2
+ else
+ . "$lz_config" || exit 2
+ fi
+}
+
+
+error_msg()
+{
+ echo $@ >&2
+}
+
+
+require_out_of_tree()
+{
+ if [ x"$lz_config_dir" = x"$lz_pwd" ]; then
+ error_msg "$lz_package: out-of-tree builds are required."
+ error_msg "please invoke configure again from a clean build directory."
+ exit 2
+ fi
+
+ return 0
+}
+
+
+get_lazy()
+{
+ which lazy && lazy=`which lazy` && return 0
+
+ if ! [ -d slazy ]; then
+ git clone git://midipix.org/lazy slazy || exit 2
+ fi
+
+ lazy=$lz_pwd/slazy/lazy
+}
+
+
+lazy_approach()
+{
+ if [ x"$lz_prefix" = x ]; then
+ error_msg "prefix is required."
+ exit 2
+ fi
+
+ if [ x"$lz_arch" = x ]; then lz_arch=$lz_default_arch; fi
+ if [ x"$lz_target" = x ]; then lz_target=$lz_default_target; fi
+ if [ x"$lz_compiler" = x ]; then lz_compiler=$lz_default_compiler; fi
+ if [ x"$lz_compiler" = x ]; then lz_compiler=gcc; fi
+
+ $lazy -x config $lz_debug \
+ -t $lz_target \
+ -c $lz_compiler \
+ -n $lz_package \
+ -p $lz_config_dir \
+ -f $lz_prefix \
+ || exit 2
+
+}
+
+
+lazy_copy()
+{
+ cp "$lz_config_dir/Makefile.in" "$lz_pwd/Makefile"
+}
+
+
+for arg ; do
+ case "$arg" in
+ --help) usage
+ ;;
+
+ --prefix=*)
+ lz_prefix=${arg#*=}
+ ;;
+ --host=*)
+ lz_target=${arg#*=}
+ ;;
+ --target=*)
+ lz_target=${arg#*=}
+ ;;
+ --compiler=*)
+ lz_compiler=${arg#*=}
+ ;;
+ --config=*)
+ lz_config=${arg#*=}
+ ;;
+ --debug)
+ lz_debug='-d'
+ ;;
+ *)
+ error_msg ${arg#}: "unsupported config argument."
+ exit 2
+ ;;
+ esac
+done
+
+
+init_vars
+require_out_of_tree
+get_lazy
+lazy_approach
+lazy_copy
diff --git a/include/pemagine/bits/nt32/pe_inline_asm__gcc.h b/include/pemagine/bits/nt32/pe_inline_asm__gcc.h
new file mode 100644
index 0000000..10473b4
--- /dev/null
+++ b/include/pemagine/bits/nt32/pe_inline_asm__gcc.h
@@ -0,0 +1,89 @@
+static __inline__ void * pe_get_teb_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x18, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x18, %0\n\t"
+ "mov %%ds:0x30(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_address_alt(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x30, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x18, %0\n\t"
+ "mov %%ds:0x30(%0), %0\n\t"
+ "mov %%ds:0x0C(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address_alt(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x30, %0\n\t"
+ "mov %%ds:0x0C(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+static __inline__ uint32_t pe_get_current_process_id(void)
+{
+ uint32_t ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x20, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+static __inline__ uint32_t pe_get_current_thread_id(void)
+{
+ uint32_t ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x24, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+static __inline__ uint32_t pe_get_current_session_id(void)
+{
+ uint32_t ptrRet;
+ __asm__ __volatile__ (
+ "mov %%fs:0x18, %0\n\t"
+ "mov %%ds:0x30(%0), %0\n\t"
+ "mov %%ds:0x1d4(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
diff --git a/include/pemagine/bits/nt32/pe_inline_asm__msvc.h b/include/pemagine/bits/nt32/pe_inline_asm__msvc.h
new file mode 100644
index 0000000..161a846
--- /dev/null
+++ b/include/pemagine/bits/nt32/pe_inline_asm__msvc.h
@@ -0,0 +1,67 @@
+/* optimize: use __readfsdword rather than explicit eax */
+
+static __inline__ void * pe_get_teb_address(void)
+{
+ __asm {
+ mov eax, fs:0x18
+ };
+}
+
+
+static __inline__ void * pe_get_peb_address(void)
+{
+ __asm {
+ mov eax, fs:0x18
+ mov eax, ds:[eax+0x30]
+ };
+}
+
+
+static __inline__ void * pe_get_peb_address_alt(void)
+{
+ __asm {
+ mov eax, fs:0x30
+ };
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address(void)
+{
+ __asm {
+ mov eax, fs:0x18
+ mov eax, ds:[eax+0x30]
+ mov eax, ds:[eax+0x0C]
+ };
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address_alt(void)
+{
+ __asm {
+ mov eax, fs:0x30
+ mov eax, ds:[eax+0x0C]
+ };
+}
+
+static __inline__ uint32_t pe_get_current_process_id(void)
+{
+ __asm {
+ mov eax, fs:0x20
+ };
+}
+
+static __inline__ uint32_t pe_get_current_thread_id(void)
+{
+ __asm {
+ mov eax, fs:0x24
+ };
+}
+
+static __inline__ uint32_t pe_get_current_session_id(void)
+{
+ __asm {
+ mov eax, fs:0x18
+ mov eax, ds:[eax+0x30]
+ mov eax, ds:[eax+0x1d4]
+ };
+}
diff --git a/include/pemagine/bits/nt64/pe_inline_asm__gcc.h b/include/pemagine/bits/nt64/pe_inline_asm__gcc.h
new file mode 100644
index 0000000..94d4e34
--- /dev/null
+++ b/include/pemagine/bits/nt64/pe_inline_asm__gcc.h
@@ -0,0 +1,87 @@
+static __inline__ void * pe_get_teb_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x30, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x60, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_address_alt(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x60, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x60, %0\n\t"
+ "mov %%ds:0x18(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address_alt(void)
+{
+ void * ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x60, %0\n\t"
+ "mov %%ds:0x18(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+
+static __inline__ uint32_t pe_get_current_process_id(void)
+{
+ uint32_t ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x40, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+static __inline__ uint32_t pe_get_current_thread_id(void)
+{
+ uint32_t ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x48, %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
+
+static __inline__ uint32_t pe_get_current_session_id(void)
+{
+ uint32_t ptrRet;
+ __asm__ __volatile__ (
+ "mov %%gs:0x60, %0\n\t"
+ "mov %%ds:0x2c0(%0), %0\n\t"
+ : "=r" (ptrRet) : :
+ );
+ return ptrRet;
+}
diff --git a/include/pemagine/bits/nt64/pe_inline_asm__msvc.h b/include/pemagine/bits/nt64/pe_inline_asm__msvc.h
new file mode 100644
index 0000000..e83d587
--- /dev/null
+++ b/include/pemagine/bits/nt64/pe_inline_asm__msvc.h
@@ -0,0 +1,58 @@
+#include <psxtypes/psxtypes.h>
+
+unsigned __int64 __readgsqword(unsigned long);
+
+static __inline__ void * pe_get_teb_address(void)
+{
+ return (void *)__readgsqword(0x30);
+}
+
+
+static __inline__ void * pe_get_peb_address(void)
+{
+ return (void *)__readgsqword(0x60);
+}
+
+
+static __inline__ void * pe_get_peb_address_alt(void)
+{
+ return (void *)__readgsqword(0x60);
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address(void)
+{
+ char * rsi;
+
+ rsi = (char *)__readgsqword(0x60);
+ rsi += 0x18;
+
+ return *(void **)rsi;
+}
+
+
+static __inline__ void * pe_get_peb_ldr_data_address_alt(void)
+{
+ return pe_get_peb_ldr_data_address();
+}
+
+
+static __inline__ uint32_t pe_get_current_process_id(void)
+{
+ return (uint32_t)__readgsqword(0x40);
+}
+
+static __inline__ uint32_t pe_get_current_thread_id(void)
+{
+ return (uint32_t)__readgsqword(0x48);
+}
+
+static __inline__ uint32_t pe_get_current_session_id(void)
+{
+ char * rsi;
+
+ rsi = (char *)__readgsqword(0x60);
+ rsi += 0x2c0;
+
+ return *(uint32_t *)rsi;
+}
diff --git a/include/pemagine/pe_api.h b/include/pemagine/pe_api.h
new file mode 100644
index 0000000..923daa9
--- /dev/null
+++ b/include/pemagine/pe_api.h
@@ -0,0 +1,36 @@
+#ifndef PE_API_H
+#define PE_API_H
+
+/* portable integer types */
+#if defined (MIDIPIX_FREESTANDING)
+#include <psxtypes/psxtypes.h>
+#else
+#include <stdint.h>
+#endif
+
+/* pe_export */
+#if defined(__attr_export__)
+#define pe_export __attr_export__
+#else
+#define pe_export
+#endif
+
+/* pe_import */
+#if defined(__attr_import__)
+#define pe_import __attr_import__
+#else
+#define pe_import
+#endif
+
+/* pe_api */
+#if defined (PE_BUILD)
+#define pe_api pe_export
+#elif defined (PE_SHARED)
+#define pe_api pe_import
+#elif defined (PE_STATIC)
+#define pe_api
+#else
+#define pe_api
+#endif
+
+#endif /* _PE_API_H_ */
diff --git a/include/pemagine/pe_consts.h b/include/pemagine/pe_consts.h
new file mode 100644
index 0000000..e7bd657
--- /dev/null
+++ b/include/pemagine/pe_consts.h
@@ -0,0 +1,371 @@
+#ifndef PE_CONSTS_H
+#define PE_CONSTS_H
+
+#ifndef PE_BITWISE
+#define PE_BITWISE(x) x
+#endif
+
+#ifndef PE_ARBITRARY
+#define PE_ARBITRARY(x) x
+#endif
+
+#define PE_IMAGE_REL_BASED_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_BASED_HIGH PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_BASED_LOW PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_BASED_HIGHLOW PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_BASED_HIGHADJ PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_BASED_MIPS_JMPADDR PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_BASED_ARM_MOV32A PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_BASED_RESERVED PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_BASED_ARM_MOV32T PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_BASED_MIPS_JMPADDR16 PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_BASED_DIR64 PE_ARBITRARY (0x0000000a)
+#define PE_WIN_CERT_REVISION_1_0 PE_ARBITRARY (0x00000100)
+#define PE_WIN_CERT_REVISION_2_0 PE_ARBITRARY (0x00000200)
+#define PE_WIN_CERT_TYPE_X509 PE_ARBITRARY (0x00000001)
+#define PE_WIN_CERT_TYPE_PKCS_SIGNED_DATA PE_ARBITRARY (0x00000002)
+#define PE_WIN_CERT_TYPE_RESERVED_1 PE_ARBITRARY (0x00000003)
+#define PE_WIN_CERT_TYPE_TS_STACK_SIGNED PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_ARM_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_ARM_ADDR32 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_ARM_ADDR32NB PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_ARM_BRANCH24 PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_ARM_BRANCH11 PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_ARM_TOKEN PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_ARM_BLX24 PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_REL_ARM_BLX11 PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_ARM_SECTION PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_REL_ARM_SECREL PE_ARBITRARY (0x0000000f)
+#define PE_IMAGE_REL_ARM_MOV32A PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_REL_ARM_MOV32T PE_ARBITRARY (0x00000011)
+#define PE_IMAGE_REL_ARM_BRANCH20T PE_ARBITRARY (0x00000012)
+#define PE_IMAGE_REL_ARM_BRANCH24T PE_ARBITRARY (0x00000014)
+#define PE_IMAGE_REL_ARM_BLX23T PE_ARBITRARY (0x00000015)
+#define PE_IMAGE_REL_SH3_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_SH3_DIRECT16 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_SH3_DIRECT32 PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_SH3_DIRECT8 PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_SH3_DIRECT8_WORD PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_SH3_DIRECT8_LONG PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_SH3_DIRECT4 PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_SH3_DIRECT4_WORD PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_SH3_DIRECT4_LONG PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_REL_SH3_PCREL8_WORD PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_SH3_PCREL8_LONG PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_SH3_PCREL12_WORD PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_SH3_STARTOF_SECTION PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_SH3_SIZEOF_SECTION PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_REL_SH3_SECTION PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_REL_SH3_SECREL PE_ARBITRARY (0x0000000f)
+#define PE_IMAGE_REL_SH3_DIRECT32_NB PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_REL_SH3_GPREL4_LONG PE_ARBITRARY (0x00000011)
+#define PE_IMAGE_REL_SH3_TOKEN PE_ARBITRARY (0x00000012)
+#define PE_IMAGE_REL_SHM_PCRELPT PE_ARBITRARY (0x00000013)
+#define PE_IMAGE_REL_SHM_REFLO PE_ARBITRARY (0x00000014)
+#define PE_IMAGE_REL_SHM_REFHALF PE_ARBITRARY (0x00000015)
+#define PE_IMAGE_REL_SHM_RELLO PE_ARBITRARY (0x00000016)
+#define PE_IMAGE_REL_SHM_RELHALF PE_ARBITRARY (0x00000017)
+#define PE_IMAGE_REL_SHM_PAIR PE_ARBITRARY (0x00000018)
+#define PE_IMAGE_REL_SHM_NOMODE PE_ARBITRARY (0x00008000)
+#define PE_IMAGE_REL_I386_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_I386_DIR16 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_I386_REL16 PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_I386_DIR32 PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_I386_DIR32NB PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_I386_SEG12 PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_I386_SECTION PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_I386_SECREL PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_I386_TOKEN PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_I386_SECREL7 PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_REL_I386_REL32 PE_ARBITRARY (0x00000014)
+#define PE_IMAGE_REL_IA64_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_IA64_IMM14 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_IA64_IMM22 PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_IA64_IMM64 PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_IA64_DIR32 PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_IA64_DIR64 PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_IA64_PCREL21B PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_IA64_PCREL21M PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_IA64_PCREL21F PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_REL_IA64_GPREL22 PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_IA64_LTOFF22 PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_IA64_SECTION PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_IA64_SECREL22 PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_IA64_SECREL64I PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_REL_IA64_SECREL32 PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_REL_IA64_DIR32NB PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_REL_IA64_SREL14 PE_ARBITRARY (0x00000011)
+#define PE_IMAGE_REL_IA64_SREL22 PE_ARBITRARY (0x00000012)
+#define PE_IMAGE_REL_IA64_SREL32 PE_ARBITRARY (0x00000013)
+#define PE_IMAGE_REL_IA64_UREL32 PE_ARBITRARY (0x00000014)
+#define PE_IMAGE_REL_IA64_PCREL60X PE_ARBITRARY (0x00000015)
+#define PE_IMAGE_REL_IA64_PCREL60B PE_ARBITRARY (0x00000016)
+#define PE_IMAGE_REL_IA64_PCREL60F PE_ARBITRARY (0x00000017)
+#define PE_IMAGE_REL_IA64_PCREL60I PE_ARBITRARY (0x00000018)
+#define PE_IMAGE_REL_IA64_PCREL60M PE_ARBITRARY (0x00000019)
+#define PE_IMAGE_REL_IA64_IMMGPREL64 PE_ARBITRARY (0x0000001a)
+#define PE_IMAGE_REL_IA64_TOKEN PE_ARBITRARY (0x0000001b)
+#define PE_IMAGE_REL_IA64_GPREL32 PE_ARBITRARY (0x0000001c)
+#define PE_IMAGE_REL_IA64_ADDEND PE_ARBITRARY (0x0000001f)
+#define PE_IMAGE_REL_PPC_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_PPC_ADDR64 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_PPC_ADDR32 PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_PPC_ADDR24 PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_PPC_ADDR16 PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_PPC_ADDR14 PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_PPC_REL24 PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_PPC_REL14 PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_PPC_ADDR32NB PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_PPC_SECREL PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_PPC_SECTION PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_PPC_SECREL16 PE_ARBITRARY (0x0000000f)
+#define PE_IMAGE_REL_PPC_REFHI PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_REL_PPC_REFLO PE_ARBITRARY (0x00000011)
+#define PE_IMAGE_REL_PPC_PAIR PE_ARBITRARY (0x00000012)
+#define PE_IMAGE_REL_PPC_SECRELLO PE_ARBITRARY (0x00000013)
+#define PE_IMAGE_REL_PPC_GPREL PE_ARBITRARY (0x00000015)
+#define PE_IMAGE_REL_PPC_TOKEN PE_ARBITRARY (0x00000016)
+#define PE_IMAGE_REL_MIPS_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_MIPS_REFHALF PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_MIPS_REFWORD PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_MIPS_JMPADDR PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_MIPS_REFHI PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_MIPS_REFLO PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_MIPS_GPREL PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_MIPS_LITERAL PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_MIPS_SECTION PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_MIPS_SECREL PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_MIPS_SECRELLO PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_MIPS_SECRELHI PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_REL_MIPS_JMPADDR16 PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_REL_MIPS_REFWORDNB PE_ARBITRARY (0x00000022)
+#define PE_IMAGE_REL_MIPS_PAIR PE_ARBITRARY (0x00000025)
+#define PE_IMAGE_REL_M32R_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_M32R_ADDR32 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_M32R_ADDR32NB PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_M32R_ADDR24 PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_M32R_GPREL16 PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_M32R_PCREL24 PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_M32R_PCREL16 PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_M32R_PCREL8 PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_M32R_REFHALF PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_REL_M32R_REFHI PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_M32R_REFLO PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_M32R_PAIR PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_M32R_SECTION PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_M32R_SECREL PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_REL_M32R_TOKEN PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_REL_AMD64_ABSOLUTE PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_REL_AMD64_ADDR64 PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_REL_AMD64_ADDR32 PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_REL_AMD64_ADDR32NB PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_REL_AMD64_REL32 PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_REL_AMD64_REL32_1 PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_REL_AMD64_REL32_2 PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_REL_AMD64_REL32_3 PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_REL_AMD64_REL32_4 PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_REL_AMD64_REL32_5 PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_REL_AMD64_SECTION PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_REL_AMD64_SECREL PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_REL_AMD64_SECREL7 PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_REL_AMD64_TOKEN PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_REL_AMD64_SREL32 PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_REL_AMD64_PAIR PE_ARBITRARY (0x0000000f)
+#define PE_IMAGE_REL_AMD64_SSPAN32 PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_COMDAT_SELECT_NODUPLICATES PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_COMDAT_SELECT_ANY PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_COMDAT_SELECT_SAME_SIZE PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_COMDAT_SELECT_EXACT_MATCH PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_COMDAT_SELECT_ASSOCIATIVE PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_COMDAT_SELECT_LARGEST PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_DLL_RESERVED_X0001 PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_RESERVED_X0002 PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_RESERVED_X0004 PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_RESERVED_X0008 PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_NX_COMPAT PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_NO_SEH PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_NO_BIND PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_RESERVED_X1000 PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER PE_BITWISE (0x00000000)
+#define PE_IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_RELOCS_STRIPPED PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_EXECUTABLE_IMAGE PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_LINE_NUMS_STRIPPED PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_LOCAL_SYMS_STRIPPED PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_AGGRESSIVE_WS_TRIM PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_LARGE_ADDRESS_AWARE PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_RESERVED_CHARACTERISTIC PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_BYTES_REVERSED_LO PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_32BIT_MACHINE PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_DEBUG_STRIPPED PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_NET_RUN_FROM_SWAP PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_SYSTEM PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_DLL PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_UP_SYSTEM_ONLY PE_BITWISE (0x00000000)
+#define PE_IMAGE_FILE_BYTES_REVERSED_HI PE_BITWISE (0x00000000)
+#define PE_IMAGE_DEBUG_TYPE_UNKNOWN PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_DEBUG_TYPE_COFF PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_DEBUG_TYPE_CODEVIEW PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_DEBUG_TYPE_FPO PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_DEBUG_TYPE_MISC PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_DEBUG_TYPE_EXCEPTION PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_DEBUG_TYPE_FIXUP PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_DEBUG_TYPE_OMAP_TO_SRC PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_DEBUG_TYPE_OMAP_FROM_SRC PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_DEBUG_TYPE_BORLAND PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_DEBUG_TYPE_RESERVED10 PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_DEBUG_TYPE_CLSID PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_SUBSYSTEM_UNKNOWN PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_SUBSYSTEM_NATIVE PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_SUBSYSTEM_WINDOWS_GUI PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_SUBSYSTEM_WINDOWS_CUI PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_SUBSYSTEM_POSIX_CUI PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_SUBSYSTEM_WINDOWS_CE_GUI PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_SUBSYSTEM_EFI_APPLICATION PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_SUBSYSTEM_EFI_ROM PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_SUBSYSTEM_XBOX PE_ARBITRARY (0x0000000e)
+#define PE_IMPORT_ORDINAL PE_ARBITRARY (0x00000000)
+#define PE_IMPORT_NAME PE_ARBITRARY (0x00000001)
+#define PE_IMPORT_NAME_NOPREFIX PE_ARBITRARY (0x00000002)
+#define PE_IMPORT_NAME_UNDECORATE PE_ARBITRARY (0x00000003)
+#define PE_IMPORT_CODE PE_ARBITRARY (0x00000000)
+#define PE_IMPORT_DATA PE_ARBITRARY (0x00000001)
+#define PE_IMPORT_CONST PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_FILE_MACHINE_UNKNOWN PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_FILE_MACHINE_I386 PE_ARBITRARY (0x0000014c)
+#define PE_IMAGE_FILE_MACHINE_R4000 PE_ARBITRARY (0x00000166)
+#define PE_IMAGE_FILE_MACHINE_WCEMIPSV2 PE_ARBITRARY (0x00000169)
+#define PE_IMAGE_FILE_MACHINE_SH3 PE_ARBITRARY (0x000001a2)
+#define PE_IMAGE_FILE_MACHINE_SH3DSP PE_ARBITRARY (0x000001a3)
+#define PE_IMAGE_FILE_MACHINE_SH4 PE_ARBITRARY (0x000001a6)
+#define PE_IMAGE_FILE_MACHINE_SH5 PE_ARBITRARY (0x000001a8)
+#define PE_IMAGE_FILE_MACHINE_ARM PE_ARBITRARY (0x000001c0)
+#define PE_IMAGE_FILE_MACHINE_THUMB PE_ARBITRARY (0x000001c2)
+#define PE_IMAGE_FILE_MACHINE_ARMV7 PE_ARBITRARY (0x000001c4)
+#define PE_IMAGE_FILE_MACHINE_AM33 PE_ARBITRARY (0x000001d3)
+#define PE_IMAGE_FILE_MACHINE_POWERPC PE_ARBITRARY (0x000001f0)
+#define PE_IMAGE_FILE_MACHINE_POWERPCFP PE_ARBITRARY (0x000001f1)
+#define PE_IMAGE_FILE_MACHINE_IA64 PE_ARBITRARY (0x00000200)
+#define PE_IMAGE_FILE_MACHINE_MIPS16 PE_ARBITRARY (0x00000266)
+#define PE_IMAGE_FILE_MACHINE_MIPSFPU PE_ARBITRARY (0x00000366)
+#define PE_IMAGE_FILE_MACHINE_MIPSFPU16 PE_ARBITRARY (0x00000466)
+#define PE_IMAGE_FILE_MACHINE_EBC PE_ARBITRARY (0x00000ebc)
+#define PE_IMAGE_FILE_MACHINE_AMD64 PE_ARBITRARY (0x00008664)
+#define PE_IMAGE_FILE_MACHINE_M32R PE_ARBITRARY (0x00009041)
+#define PE_MAGIC_ROM_IMAGE PE_ARBITRARY (0x00000107)
+#define PE_MAGIC_PE32 PE_ARBITRARY (0x0000010b)
+#define PE_MAGIC_PE32_PLUS PE_ARBITRARY (0x0000020b)
+#define PE_IMAGE_SCN_RESERVED_X00000001 PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_RESERVED_X00000002 PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_RESERVED_X00000004 PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_TYPE_NO_PAD PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_RESERVED_X00000010 PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_CNT_CODE PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_CNT_INITIALIZED_DATA PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_CNT_UNINITIALIZED_DATA PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_LNK_OTHER PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_LNK_INFO PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_RESERVED_X00000400 PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_LNK_REMOVE PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_LNK_COMDAT PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_GPREL PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_PURGEABLE PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_16BIT PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_LOCKED PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_PRELOAD PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_1BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_2BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_4BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_8BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_16BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_32BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_64BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_128BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_256BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_512BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_1024BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_2048BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_4096BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_ALIGN_8192BYTES PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_LNK_NRELOC_OVFL PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_DISCARDABLE PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_NOT_CACHED PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_NOT_PAGED PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_SHARED PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_EXECUTE PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_READ PE_BITWISE (0x00000000)
+#define PE_IMAGE_SCN_MEM_WRITE PE_BITWISE (0x00000000)
+#define PE_IMAGE_SYM_DEBUG PE_ARBITRARY ( -2)
+#define PE_IMAGE_SYM_ABSOLUTE PE_ARBITRARY ( -1)
+#define PE_IMAGE_SYM_UNDEFINED PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_SYM_CLASS_NULL PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_SYM_CLASS_AUTOMATIC PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_SYM_CLASS_EXTERNAL PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_SYM_CLASS_STATIC PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_SYM_CLASS_REGISTER PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_SYM_CLASS_EXTERNAL_DEF PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_SYM_CLASS_LABEL PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_SYM_CLASS_UNDEFINED_LABEL PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_SYM_CLASS_ARGUMENT PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_SYM_CLASS_STRUCT_TAG PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_SYM_CLASS_MEMBER_OF_UNION PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_SYM_CLASS_UNION_TAG PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_SYM_CLASS_TYPE_DEFINITION PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_SYM_CLASS_UNDEFINED_STATIC PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_SYM_CLASS_ENUM_TAG PE_ARBITRARY (0x0000000f)
+#define PE_IMAGE_SYM_CLASS_MEMBER_OF_ENUM PE_ARBITRARY (0x00000010)
+#define PE_IMAGE_SYM_CLASS_REGISTER_PARAM PE_ARBITRARY (0x00000011)
+#define PE_IMAGE_SYM_CLASS_BIT_FIELD PE_ARBITRARY (0x00000012)
+#define PE_IMAGE_SYM_CLASS_BLOCK PE_ARBITRARY (0x00000064)
+#define PE_IMAGE_SYM_CLASS_FUNCTION PE_ARBITRARY (0x00000065)
+#define PE_IMAGE_SYM_CLASS_END_OF_STRUCT PE_ARBITRARY (0x00000066)
+#define PE_IMAGE_SYM_CLASS_FILE PE_ARBITRARY (0x00000067)
+#define PE_IMAGE_SYM_CLASS_SECTION PE_ARBITRARY (0x00000068)
+#define PE_IMAGE_SYM_CLASS_WEAK_EXTERN PE_ARBITRARY (0x00000069)
+#define PE_IMAGE_SYM_CLASS_CLR_TOKEN PE_ARBITRARY (0x0000006b)
+#define PE_IMAGE_SYM_CLASS_END_OF_FUNC PE_ARBITRARY (0x000000ff)
+#define PE_IMAGE_SYM_TYPE_NULL PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_SYM_TYPE_VOID PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_SYM_TYPE_CHAR PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_SYM_TYPE_SHORT PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_SYM_TYPE_INT PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_SYM_TYPE_LONG PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_SYM_TYPE_FLOAT PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_SYM_TYPE_DOUBLE PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_SYM_TYPE_STRUCT PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_SYM_TYPE_UNION PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_SYM_TYPE_ENUM PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_SYM_TYPE_MOE PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_SYM_TYPE_BYTE PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_SYM_TYPE_WORD PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_SYM_TYPE_UINT PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_SYM_TYPE_DWORD PE_ARBITRARY (0x0000000f)
+#define PE_IMAGE_SYM_DTYPE_NULL PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_SYM_DTYPE_POINTER PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_SYM_DTYPE_FUNCTION PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_SYM_DTYPE_ARRAY PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_DATA_DIR_ORDINAL_EXPORT PE_ARBITRARY (0x00000000)
+#define PE_IMAGE_DATA_DIR_ORDINAL_IMPORT PE_ARBITRARY (0x00000001)
+#define PE_IMAGE_DATA_DIR_ORDINAL_RESOURCE PE_ARBITRARY (0x00000002)
+#define PE_IMAGE_DATA_DIR_ORDINAL_EXCEPTION PE_ARBITRARY (0x00000003)
+#define PE_IMAGE_DATA_DIR_ORDINAL_CERTIFICATE PE_ARBITRARY (0x00000004)
+#define PE_IMAGE_DATA_DIR_ORDINAL_BASE_RELOCATION PE_ARBITRARY (0x00000005)
+#define PE_IMAGE_DATA_DIR_ORDINAL_DEBUG PE_ARBITRARY (0x00000006)
+#define PE_IMAGE_DATA_DIR_ORDINAL_ARCHITECTURE PE_ARBITRARY (0x00000007)
+#define PE_IMAGE_DATA_DIR_ORDINAL_GLOBAL_PTR PE_ARBITRARY (0x00000008)
+#define PE_IMAGE_DATA_DIR_ORDINAL_TLS PE_ARBITRARY (0x00000009)
+#define PE_IMAGE_DATA_DIR_ORDINAL_LOAD_CONFIG PE_ARBITRARY (0x0000000a)
+#define PE_IMAGE_DATA_DIR_ORDINAL_BOUND_IMPORT PE_ARBITRARY (0x0000000b)
+#define PE_IMAGE_DATA_DIR_ORDINAL_IAT PE_ARBITRARY (0x0000000c)
+#define PE_IMAGE_DATA_DIR_ORDINAL_DELAY_IMPORT_DESCRIPTOR PE_ARBITRARY (0x0000000d)
+#define PE_IMAGE_DATA_DIR_ORDINAL_CLR_RUNTIME_HEADER PE_ARBITRARY (0x0000000e)
+#define PE_IMAGE_DATA_DIR_ORDINAL_RESERVED PE_ARBITRARY (0x0000000f)
+
+#endif
diff --git a/include/pemagine/pe_inline_asm.h b/include/pemagine/pe_inline_asm.h
new file mode 100644
index 0000000..65e1376
--- /dev/null
+++ b/include/pemagine/pe_inline_asm.h
@@ -0,0 +1,20 @@
+#if defined(__NT32)
+#if (__COMPILER__ == __GCC__)
+#include "bits/nt32/pe_inline_asm__gcc.h"
+#elif (__COMPILER__ == __MSVC__)
+#include "bits/nt32/pe_inline_asm__msvc.h"
+#endif
+
+#elif defined(__NT64)
+#if (__COMPILER__ == __GCC__)
+#include "bits/nt64/pe_inline_asm__gcc.h"
+#elif (__COMPILER__ == __MSVC__)
+#include "bits/nt64/pe_inline_asm__msvc.h"
+#endif
+#endif
+
+/* trivial */
+static __inline__ void * pe_va_from_rva(const void * base, intptr_t offset)
+{
+ return (void *)((intptr_t)base + offset);
+}
diff --git a/include/pemagine/pe_structs.h b/include/pemagine/pe_structs.h
new file mode 100644
index 0000000..4a7017d
--- /dev/null
+++ b/include/pemagine/pe_structs.h
@@ -0,0 +1,635 @@
+#ifndef PE_STRUCTS_H
+#define PE_STRUCTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* pe_image_dos_header... */
+#define PE_DOS_MAGIC_BS 0x02
+#define PE_DOS_CBLP_BS 0x02
+#define PE_DOS_CP_BS 0x02
+#define PE_DOS_CRLC_BS 0x02
+#define PE_DOS_CPARHDR_BS 0x02
+#define PE_DOS_MINALLOC_BS 0x02
+#define PE_DOS_MAXALLOC_BS 0x02
+#define PE_DOS_SS_BS 0x02
+#define PE_DOS_SP_BS 0x02
+#define PE_DOS_CSUM_BS 0x02
+#define PE_DOS_IP_BS 0x02
+#define PE_DOS_CS_BS 0x02
+#define PE_DOS_LFARLC_BS 0x02
+#define PE_DOS_OVNO_BS 0x02
+#define PE_DOS_RES_BS 0x08
+#define PE_DOS_OEMID_BS 0x02
+#define PE_DOS_OEMINFO_BS 0x02
+#define PE_DOS_RES2_BS 0x14
+#define PE_DOS_LFANEW_BS 0x04
+
+struct pe_image_dos_hdr {
+ unsigned char dos_magic [PE_DOS_MAGIC_BS]; /* 0x00 */
+ unsigned char dos_cblp [PE_DOS_CBLP_BS]; /* 0x02 */
+ unsigned char dos_cp [PE_DOS_CP_BS]; /* 0x04 */
+ unsigned char dos_crlc [PE_DOS_CRLC_BS]; /* 0x06 */
+ unsigned char dos_cparhdr [PE_DOS_CPARHDR_BS]; /* 0x08 */
+ unsigned char dos_minalloc [PE_DOS_MINALLOC_BS]; /* 0x0a */
+ unsigned char dos_maxalloc [PE_DOS_MAXALLOC_BS]; /* 0x0c */
+ unsigned char dos_ss [PE_DOS_SS_BS]; /* 0x0e */
+ unsigned char dos_sp [PE_DOS_SP_BS]; /* 0x10 */
+ unsigned char dos_csum [PE_DOS_CSUM_BS]; /* 0x12 */
+ unsigned char dos_ip [PE_DOS_IP_BS]; /* 0x14 */
+ unsigned char dos_cs [PE_DOS_CS_BS]; /* 0x16 */
+ unsigned char dos_lfarlc [PE_DOS_LFARLC_BS]; /* 0x18 */
+ unsigned char dos_ovno [PE_DOS_OVNO_BS]; /* 0x1a */
+ unsigned char dos_res [PE_DOS_RES_BS]; /* 0x1c */
+ unsigned char dos_oemid [PE_DOS_OEMID_BS]; /* 0x24 */
+ unsigned char dos_oeminfo [PE_DOS_OEMINFO_BS]; /* 0x26 */
+ unsigned char dos_res2 [PE_DOS_RES2_BS]; /* 0x28 */
+ unsigned char dos_lfanew [PE_DOS_LFANEW_BS]; /* 0x3c */
+};
+
+#undef PE_DOS_MAGIC_BS
+#undef PE_DOS_CBLP_BS
+#undef PE_DOS_CP_BS
+#undef PE_DOS_CRLC_BS
+#undef PE_DOS_CPARHDR_BS
+#undef PE_DOS_MINALLOC_BS
+#undef PE_DOS_MAXALLOC_BS
+#undef PE_DOS_SS_BS
+#undef PE_DOS_SP_BS
+#undef PE_DOS_CSUM_BS
+#undef PE_DOS_IP_BS
+#undef PE_DOS_CS_BS
+#undef PE_DOS_LFARLC_BS
+#undef PE_DOS_OVNO_BS
+#undef PE_DOS_RES_BS
+#undef PE_DOS_OEMID_BS
+#undef PE_DOS_OEMINFO_BS
+#undef PE_DOS_RES2_BS
+#undef PE_DOS_LFANEW_BS
+
+
+/* pe_coff_file_header... */
+#define PE_SIGNATURE_BS 0x04
+#define PE_MACHINE_BS 0x02
+#define PE_NUMBER_OF_SECTIONS_BS 0x02
+#define PE_TIME_DATE_STAMP_BS 0x04
+#define PE_POINTER_TO_SYMBOL_TABLE_BS 0x04
+#define PE_NUMBER_OF_SYMBOLS_BS 0x04
+#define PE_SIZE_OF_OPTIONAL_HEADER_BS 0x02
+#define PE_CHARACTERISTICS_BS 0x02
+
+struct pe_coff_file_hdr {
+ unsigned char signature [PE_SIGNATURE_BS]; /* 0x00 */
+ unsigned char machine [PE_MACHINE_BS]; /* 0x04 */
+ unsigned char num_of_sections [PE_NUMBER_OF_SECTIONS_BS]; /* 0x06 */
+ unsigned char time_date_stamp [PE_TIME_DATE_STAMP_BS]; /* 0x08 */
+ unsigned char ptr_to_sym_tbl [PE_POINTER_TO_SYMBOL_TABLE_BS]; /* 0x0c */
+ unsigned char num_of_syms [PE_NUMBER_OF_SYMBOLS_BS]; /* 0x10 */
+ unsigned char size_of_opt_hdr [PE_SIZE_OF_OPTIONAL_HEADER_BS]; /* 0x14 */
+ unsigned char characteristics [PE_CHARACTERISTICS_BS]; /* 0x16 */
+};
+
+#undef PE_SIGNATURE_BS
+#undef PE_MACHINE_BS
+#undef PE_NUMBER_OF_SECTIONS_BS
+#undef PE_TIME_DATE_STAMP_BS
+#undef PE_POINTER_TO_SYMBOL_TABLE_BS
+#undef PE_NUMBER_OF_SYMBOLS_BS
+#undef PE_SIZE_OF_OPTIONAL_HEADER_BS
+#undef PE_CHARACTERISTICS_BS
+
+
+/* pe32_optional_header... */
+#define PE_MAGIC_BS 0x02
+#define PE_MAJOR_LINKER_VERSION_BS 0x01
+#define PE_MINOR_LINKER_VERSION_BS 0x01
+#define PE_SIZE_OF_CODE_BS 0x04
+#define PE_SIZE_OF_INITIALIZED_DATA_BS 0x04
+#define PE_SIZE_OF_UNINITIALIZED_DATA_BS 0x04
+#define PE_ADDRESS_OF_ENTRY_POINT_BS 0x04
+#define PE_BASE_OF_CODE_BS 0x04
+#define PE_BASE_OF_DATA_BS 0x04
+#define PE_IMAGE_BASE_BS 0x04
+#define PE_SECTION_ALIGNMENT_BS 0x04
+#define PE_FILE_ALIGNMENT_BS 0x04
+#define PE_MAJOR_OPERATING_SYSTEM_VERSION_BS 0x02
+#define PE_MINOR_OPERATING_SYSTEM_VERSION_BS 0x02
+#define PE_MAJOR_IMAGE_VERSION_BS 0x02
+#define PE_MINOR_IMAGE_VERSION_BS 0x02
+#define PE_MAJOR_SUBSYSTEM_VERSION_BS 0x02
+#define PE_MINOR_SUBSYSTEM_VERSION_BS 0x02
+#define PE_WIN32_VERSION_VALUE_BS 0x04
+#define PE_SIZE_OF_IMAGE_BS 0x04
+#define PE_SIZE_OF_HEADERS_BS 0x04
+#define PE_CHECK_SUM_BS 0x04
+#define PE_SUBSYSTEM_BS 0x02
+#define PE_DLL_CHARACTERISTICS_BS 0x02
+#define PE_SIZE_OF_STACK_RESERVE_BS 0x04
+#define PE_SIZE_OF_STACK_COMMIT_BS 0x04
+#define PE_SIZE_OF_HEAP_RESERVE_BS 0x04
+#define PE_SIZE_OF_HEAP_COMMIT_BS 0x04
+#define PE_LOADER_FLAGS_BS 0x04
+#define PE_NUMBER_OF_RVA_AND_SIZES_BS 0x04
+#define PE_EXPORT_TABLE_BS 0x08
+#define PE_IMPORT_TABLE_BS 0x08
+#define PE_RESOURCE_TABLE_BS 0x08
+#define PE_EXCEPTION_TABLE_BS 0x08
+#define PE_CERTIFICATE_TABLE_BS 0x08
+#define PE_BASE_RELOCATION_TABLE_BS 0x08
+#define PE_DEBUG_BS 0x08
+#define PE_ARCHITECTURE_BS 0x08
+#define PE_GLOBAL_PTR_BS 0x08
+#define PE_TLS_TABLE_BS 0x08
+#define PE_LOAD_CONFIG_TABLE_BS 0x08
+#define PE_BOUND_IMPORT_BS 0x08
+#define PE_IAT_BS 0x08
+#define PE_DELAY_IMPORT_DESCRIPTOR_BS 0x08
+#define PE_CLR_RUNTIME_HEADER_BS 0x08
+#define PE_RESERVED__MUST_BE_ZERO_BS 0x08
+
+struct pe_opt_hdr_std {
+ unsigned char magic [PE_MAGIC_BS]; /* 0x00 */
+ unsigned char major_linker_ver [PE_MAJOR_LINKER_VERSION_BS]; /* 0x02 */
+ unsigned char minor_linker_ver [PE_MINOR_LINKER_VERSION_BS]; /* 0x03 */
+ unsigned char size_of_code [PE_SIZE_OF_CODE_BS]; /* 0x04 */
+ unsigned char size_of_initialized_data [PE_SIZE_OF_INITIALIZED_DATA_BS]; /* 0x08 */
+ unsigned char size_of_uninitialized_data [PE_SIZE_OF_UNINITIALIZED_DATA_BS]; /* 0x0c */
+ unsigned char entry_point [PE_ADDRESS_OF_ENTRY_POINT_BS]; /* 0x10 */
+ unsigned char base_of_code [PE_BASE_OF_CODE_BS]; /* 0x14 */
+};
+
+struct pe_opt_hdr_align {
+ unsigned char section_align [PE_SECTION_ALIGNMENT_BS]; /* 0x20 */
+ unsigned char file_align [PE_FILE_ALIGNMENT_BS]; /* 0x24 */
+};
+
+struct pe_opt_hdr_vers {
+ unsigned char major_os_ver [PE_MAJOR_OPERATING_SYSTEM_VERSION_BS]; /* 0x28 */
+ unsigned char minor_os_ver [PE_MINOR_OPERATING_SYSTEM_VERSION_BS]; /* 0x2a */
+ unsigned char major_image_ver [PE_MAJOR_IMAGE_VERSION_BS]; /* 0x2c */
+ unsigned char minor_image_ver [PE_MINOR_IMAGE_VERSION_BS]; /* 0x2e */
+ unsigned char major_subsys_ver [PE_MAJOR_SUBSYSTEM_VERSION_BS]; /* 0x30 */
+ unsigned char minor_subsys_ver [PE_MINOR_SUBSYSTEM_VERSION_BS]; /* 0x32 */
+ unsigned char win32_ver [PE_WIN32_VERSION_VALUE_BS]; /* 0x34 */
+};
+
+struct pe_opt_hdr_img {
+ unsigned char size_of_image [PE_SIZE_OF_IMAGE_BS]; /* 0x38 */
+ unsigned char size_of_headers [PE_SIZE_OF_HEADERS_BS]; /* 0x3c */
+ unsigned char checksum [PE_CHECK_SUM_BS]; /* 0x40 */
+ unsigned char subsystem [PE_SUBSYSTEM_BS]; /* 0x44 */
+ unsigned char dll_characteristics [PE_DLL_CHARACTERISTICS_BS]; /* 0x46 */
+};
+
+struct pe_opt_hdr_ldr {
+ unsigned char loader_flags [PE_LOADER_FLAGS_BS];
+ unsigned char rva_and_sizes [PE_NUMBER_OF_RVA_AND_SIZES_BS];
+};
+
+struct pe_opt_hdr_dirs {
+ unsigned char export_tbl [PE_EXPORT_TABLE_BS];
+ unsigned char import_tbl [PE_IMPORT_TABLE_BS];
+ unsigned char resource_tbl [PE_RESOURCE_TABLE_BS];
+ unsigned char exception_tbl [PE_EXCEPTION_TABLE_BS];
+ unsigned char certificate_tbl [PE_CERTIFICATE_TABLE_BS];
+ unsigned char base_reloc_tbl [PE_BASE_RELOCATION_TABLE_BS];
+ unsigned char debug [PE_DEBUG_BS];
+ unsigned char arch [PE_ARCHITECTURE_BS];
+ unsigned char global_ptr [PE_GLOBAL_PTR_BS];
+ unsigned char tls_tbl [PE_TLS_TABLE_BS];
+ unsigned char load_config_tbl [PE_LOAD_CONFIG_TABLE_BS];
+ unsigned char bound_import [PE_BOUND_IMPORT_BS];
+ unsigned char iat [PE_IAT_BS];
+ unsigned char delay_import_descriptor [PE_DELAY_IMPORT_DESCRIPTOR_BS];
+ unsigned char clr_runtime_hdr [PE_CLR_RUNTIME_HEADER_BS];
+ unsigned char reserved [PE_RESERVED__MUST_BE_ZERO_BS];
+};
+
+struct pe_data_dirs {
+ unsigned char rva_and_sizes [PE_NUMBER_OF_RVA_AND_SIZES_BS];
+ unsigned char export_tbl [PE_EXPORT_TABLE_BS];
+ unsigned char import_tbl [PE_IMPORT_TABLE_BS];
+ unsigned char resource_tbl [PE_RESOURCE_TABLE_BS];
+ unsigned char exception_tbl [PE_EXCEPTION_TABLE_BS];
+ unsigned char certificate_tbl [PE_CERTIFICATE_TABLE_BS];
+ unsigned char base_reloc_tbl [PE_BASE_RELOCATION_TABLE_BS];
+ unsigned char debug [PE_DEBUG_BS];
+ unsigned char arch [PE_ARCHITECTURE_BS];
+ unsigned char global_ptr [PE_GLOBAL_PTR_BS];
+ unsigned char tls_tbl [PE_TLS_TABLE_BS];
+ unsigned char load_config_tbl [PE_LOAD_CONFIG_TABLE_BS];
+ unsigned char bound_import [PE_BOUND_IMPORT_BS];
+ unsigned char iat [PE_IAT_BS];
+ unsigned char delay_import_descriptor [PE_DELAY_IMPORT_DESCRIPTOR_BS];
+ unsigned char clr_runtime_hdr [PE_CLR_RUNTIME_HEADER_BS];
+ unsigned char reserved [PE_RESERVED__MUST_BE_ZERO_BS];
+};
+
+struct pe_opt_hdr_32 {
+ unsigned char magic [PE_MAGIC_BS]; /* 0x00 */
+ unsigned char major_linker_ver [PE_MAJOR_LINKER_VERSION_BS]; /* 0x02 */
+ unsigned char minor_linker_ver [PE_MINOR_LINKER_VERSION_BS]; /* 0x03 */
+ unsigned char size_of_code [PE_SIZE_OF_CODE_BS]; /* 0x04 */
+ unsigned char size_of_initialized_data [PE_SIZE_OF_INITIALIZED_DATA_BS]; /* 0x08 */
+ unsigned char size_of_uninitialized_data [PE_SIZE_OF_UNINITIALIZED_DATA_BS]; /* 0x0c */
+ unsigned char entry_point [PE_ADDRESS_OF_ENTRY_POINT_BS]; /* 0x10 */
+ unsigned char base_of_code [PE_BASE_OF_CODE_BS]; /* 0x14 */
+ unsigned char base_of_data [PE_BASE_OF_DATA_BS]; /* 0x18 */
+ unsigned char image_base [PE_IMAGE_BASE_BS]; /* 0x1c */
+ unsigned char section_align [PE_SECTION_ALIGNMENT_BS]; /* 0x20 */
+ unsigned char file_align [PE_FILE_ALIGNMENT_BS]; /* 0x24 */
+ unsigned char major_os_ver [PE_MAJOR_OPERATING_SYSTEM_VERSION_BS]; /* 0x28 */
+ unsigned char minor_or_ver [PE_MINOR_OPERATING_SYSTEM_VERSION_BS]; /* 0x2a */
+ unsigned char major_image_ver [PE_MAJOR_IMAGE_VERSION_BS]; /* 0x2c */
+ unsigned char minor_image_ver [PE_MINOR_IMAGE_VERSION_BS]; /* 0x2e */
+ unsigned char major_subsys_ver [PE_MAJOR_SUBSYSTEM_VERSION_BS]; /* 0x30 */
+ unsigned char minor_subsys_ver [PE_MINOR_SUBSYSTEM_VERSION_BS]; /* 0x32 */
+ unsigned char win32_ver [PE_WIN32_VERSION_VALUE_BS]; /* 0x34 */
+ unsigned char size_of_image [PE_SIZE_OF_IMAGE_BS]; /* 0x38 */
+ unsigned char size_of_headers [PE_SIZE_OF_HEADERS_BS]; /* 0x3c */
+ unsigned char checksum [PE_CHECK_SUM_BS]; /* 0x40 */
+ unsigned char subsystem [PE_SUBSYSTEM_BS]; /* 0x44 */
+ unsigned char dll_characteristics [PE_DLL_CHARACTERISTICS_BS]; /* 0x46 */
+ unsigned char size_of_stack_reserve [PE_SIZE_OF_STACK_RESERVE_BS]; /* 0x48 */
+ unsigned char size_of_stack_commit [PE_SIZE_OF_STACK_COMMIT_BS]; /* 0x4c */
+ unsigned char size_of_heap_reserve [PE_SIZE_OF_HEAP_RESERVE_BS]; /* 0x50 */
+ unsigned char size_of_heap_commit [PE_SIZE_OF_HEAP_COMMIT_BS]; /* 0x54 */
+ unsigned char loader_flags [PE_LOADER_FLAGS_BS]; /* 0x58 */
+ unsigned char rva_and_sizes [PE_NUMBER_OF_RVA_AND_SIZES_BS]; /* 0x5c */
+ unsigned char export_tbl [PE_EXPORT_TABLE_BS]; /* 0x60 */
+ unsigned char import_tbl [PE_IMPORT_TABLE_BS]; /* 0x68 */
+ unsigned char resource_tbl [PE_RESOURCE_TABLE_BS]; /* 0x70 */
+ unsigned char exception_tbl [PE_EXCEPTION_TABLE_BS]; /* 0x78 */
+ unsigned char certificate_tbl [PE_CERTIFICATE_TABLE_BS]; /* 0x80 */
+ unsigned char base_reloc_tbl [PE_BASE_RELOCATION_TABLE_BS]; /* 0x88 */
+ unsigned char debug [PE_DEBUG_BS]; /* 0x90 */
+ unsigned char arch [PE_ARCHITECTURE_BS]; /* 0x98 */
+ unsigned char global_ptr [PE_GLOBAL_PTR_BS]; /* 0xa0 */
+ unsigned char tls_tbl [PE_TLS_TABLE_BS]; /* 0xa8 */
+ unsigned char load_config_tbl [PE_LOAD_CONFIG_TABLE_BS]; /* 0xb0 */
+ unsigned char bound_import [PE_BOUND_IMPORT_BS]; /* 0xb8 */
+ unsigned char iat [PE_IAT_BS]; /* 0xc0 */
+ unsigned char delay_import_descriptor [PE_DELAY_IMPORT_DESCRIPTOR_BS]; /* 0xc8 */
+ unsigned char clr_runtime_hdr [PE_CLR_RUNTIME_HEADER_BS]; /* 0xd0 */
+ unsigned char reserved [PE_RESERVED__MUST_BE_ZERO_BS]; /* 0xd8 */
+};
+
+#undef PE_MAGIC_BS
+#undef PE_MAJOR_LINKER_VERSION_BS
+#undef PE_MINOR_LINKER_VERSION_BS
+#undef PE_SIZE_OF_CODE_BS
+#undef PE_SIZE_OF_INITIALIZED_DATA_BS
+#undef PE_SIZE_OF_UNINITIALIZED_DATA_BS
+#undef PE_ADDRESS_OF_ENTRY_POINT_BS
+#undef PE_BASE_OF_CODE_BS
+#undef PE_BASE_OF_DATA_BS
+#undef PE_IMAGE_BASE_BS
+#undef PE_SECTION_ALIGNMENT_BS
+#undef PE_FILE_ALIGNMENT_BS
+#undef PE_MAJOR_OPERATING_SYSTEM_VERSION_BS
+#undef PE_MINOR_OPERATING_SYSTEM_VERSION_BS
+#undef PE_MAJOR_IMAGE_VERSION_BS
+#undef PE_MINOR_IMAGE_VERSION_BS
+#undef PE_MAJOR_SUBSYSTEM_VERSION_BS
+#undef PE_MINOR_SUBSYSTEM_VERSION_BS
+#undef PE_WIN32_VERSION_VALUE_BS
+#undef PE_SIZE_OF_IMAGE_BS
+#undef PE_SIZE_OF_HEADERS_BS
+#undef PE_CHECK_SUM_BS
+#undef PE_SUBSYSTEM_BS
+#undef PE_DLL_CHARACTERISTICS_BS
+#undef PE_SIZE_OF_STACK_RESERVE_BS
+#undef PE_SIZE_OF_STACK_COMMIT_BS
+#undef PE_SIZE_OF_HEAP_RESERVE_BS
+#undef PE_SIZE_OF_HEAP_COMMIT_BS
+#undef PE_LOADER_FLAGS_BS
+#undef PE_NUMBER_OF_RVA_AND_SIZES_BS
+#undef PE_EXPORT_TABLE_BS
+#undef PE_IMPORT_TABLE_BS
+#undef PE_RESOURCE_TABLE_BS
+#undef PE_EXCEPTION_TABLE_BS
+#undef PE_CERTIFICATE_TABLE_BS
+#undef PE_BASE_RELOCATION_TABLE_BS
+#undef PE_DEBUG_BS
+#undef PE_ARCHITECTURE_BS
+#undef PE_GLOBAL_PTR_BS
+#undef PE_TLS_TABLE_BS
+#undef PE_LOAD_CONFIG_TABLE_BS
+#undef PE_BOUND_IMPORT_BS
+#undef PE_IAT_BS
+#undef PE_DELAY_IMPORT_DESCRIPTOR_BS
+#undef PE_CLR_RUNTIME_HEADER_BS
+#undef PE_RESERVED__MUST_BE_ZERO_BS
+
+
+/* pe64_optional_header... */
+#define PE_MAGIC_BS 0x02
+#define PE_MAJOR_LINKER_VERSION_BS 0x01
+#define PE_MINOR_LINKER_VERSION_BS 0x01
+#define PE_SIZE_OF_CODE_BS 0x04
+#define PE_SIZE_OF_INITIALIZED_DATA_BS 0x04
+#define PE_SIZE_OF_UNINITIALIZED_DATA_BS 0x04
+#define PE_ADDRESS_OF_ENTRY_POINT_BS 0x04
+#define PE_BASE_OF_CODE_BS 0x04
+#define PE_IMAGE_BASE_BS 0x08
+#define PE_SECTION_ALIGNMENT_BS 0x04
+#define PE_FILE_ALIGNMENT_BS 0x04
+#define PE_MAJOR_OPERATING_SYSTEM_VERSION_BS 0x02
+#define PE_MINOR_OPERATING_SYSTEM_VERSION_BS 0x02
+#define PE_MAJOR_IMAGE_VERSION_BS 0x02
+#define PE_MINOR_IMAGE_VERSION_BS 0x02
+#define PE_MAJOR_SUBSYSTEM_VERSION_BS 0x02
+#define PE_MINOR_SUBSYSTEM_VERSION_BS 0x02
+#define PE_WIN32_VERSION_VALUE_BS 0x04
+#define PE_SIZE_OF_IMAGE_BS 0x04
+#define PE_SIZE_OF_HEADERS_BS 0x04
+#define PE_CHECK_SUM_BS 0x04
+#define PE_SUBSYSTEM_BS 0x02
+#define PE_DLL_CHARACTERISTICS_BS 0x02
+#define PE_SIZE_OF_STACK_RESERVE_BS 0x08
+#define PE_SIZE_OF_STACK_COMMIT_BS 0x08
+#define PE_SIZE_OF_HEAP_RESERVE_BS 0x08
+#define PE_SIZE_OF_HEAP_COMMIT_BS 0x08
+#define PE_LOADER_FLAGS_BS 0x04
+#define PE_NUMBER_OF_RVA_AND_SIZES_BS 0x04
+#define PE_EXPORT_TABLE_BS 0x08
+#define PE_IMPORT_TABLE_BS 0x08
+#define PE_RESOURCE_TABLE_BS 0x08
+#define PE_EXCEPTION_TABLE_BS 0x08
+#define PE_CERTIFICATE_TABLE_BS 0x08
+#define PE_BASE_RELOCATION_TABLE_BS 0x08
+#define PE_DEBUG_BS 0x08
+#define PE_ARCHITECTURE_BS 0x08
+#define PE_GLOBAL_PTR_BS 0x08
+#define PE_TLS_TABLE_BS 0x08
+#define PE_LOAD_CONFIG_TABLE_BS 0x08
+#define PE_BOUND_IMPORT_BS 0x08
+#define PE_IAT_BS 0x08
+#define PE_DELAY_IMPORT_DESCRIPTOR_BS 0x08
+#define PE_CLR_RUNTIME_HEADER_BS 0x08
+#define PE_RESERVED__MUST_BE_ZERO_BS 0x08
+
+struct pe_opt_hdr_64 {
+ unsigned char magic [PE_MAGIC_BS]; /* 0x00 */
+ unsigned char major_linker_ver [PE_MAJOR_LINKER_VERSION_BS]; /* 0x02 */
+ unsigned char minor_linker_ver [PE_MINOR_LINKER_VERSION_BS]; /* 0x03 */
+ unsigned char size_of_code [PE_SIZE_OF_CODE_BS]; /* 0x04 */
+ unsigned char size_of_initialized_data [PE_SIZE_OF_INITIALIZED_DATA_BS]; /* 0x08 */
+ unsigned char size_of_uninitialized_data [PE_SIZE_OF_UNINITIALIZED_DATA_BS]; /* 0x0c */
+ unsigned char entry_point [PE_ADDRESS_OF_ENTRY_POINT_BS]; /* 0x10 */
+ unsigned char base_of_code [PE_BASE_OF_CODE_BS]; /* 0x14 */
+ unsigned char image_base [PE_IMAGE_BASE_BS]; /* 0x18 */
+ unsigned char section_align [PE_SECTION_ALIGNMENT_BS]; /* 0x20 */
+ unsigned char file_align [PE_FILE_ALIGNMENT_BS]; /* 0x24 */
+ unsigned char major_os_ver [PE_MAJOR_OPERATING_SYSTEM_VERSION_BS]; /* 0x28 */
+ unsigned char minor_or_ver [PE_MINOR_OPERATING_SYSTEM_VERSION_BS]; /* 0x2a */
+ unsigned char major_image_ver [PE_MAJOR_IMAGE_VERSION_BS]; /* 0x2c */
+ unsigned char minor_image_ver [PE_MINOR_IMAGE_VERSION_BS]; /* 0x2e */
+ unsigned char major_subsys_ver [PE_MAJOR_SUBSYSTEM_VERSION_BS]; /* 0x30 */
+ unsigned char minor_subsys_ver [PE_MINOR_SUBSYSTEM_VERSION_BS]; /* 0x32 */
+ unsigned char win32_ver [PE_WIN32_VERSION_VALUE_BS]; /* 0x34 */
+ unsigned char size_of_image [PE_SIZE_OF_IMAGE_BS]; /* 0x38 */
+ unsigned char size_of_headers [PE_SIZE_OF_HEADERS_BS]; /* 0x3c */
+ unsigned char checksum [PE_CHECK_SUM_BS]; /* 0x40 */
+ unsigned char subsystem [PE_SUBSYSTEM_BS]; /* 0x44 */
+ unsigned char dll_characteristics [PE_DLL_CHARACTERISTICS_BS]; /* 0x46 */
+ unsigned char size_of_stack_reserve [PE_SIZE_OF_STACK_RESERVE_BS]; /* 0x48 */
+ unsigned char size_of_stack_commit [PE_SIZE_OF_STACK_COMMIT_BS]; /* 0x50 */
+ unsigned char size_of_heap_reserve [PE_SIZE_OF_HEAP_RESERVE_BS]; /* 0x58 */
+ unsigned char size_of_heap_commit [PE_SIZE_OF_HEAP_COMMIT_BS]; /* 0x60 */
+ unsigned char loader_flags [PE_LOADER_FLAGS_BS]; /* 0x68 */
+ unsigned char rva_and_sizes [PE_NUMBER_OF_RVA_AND_SIZES_BS]; /* 0x6c */
+ unsigned char export_tbl [PE_EXPORT_TABLE_BS]; /* 0x70 */
+ unsigned char import_tbl [PE_IMPORT_TABLE_BS]; /* 0x78 */
+ unsigned char resource_tbl [PE_RESOURCE_TABLE_BS]; /* 0x80 */
+ unsigned char exception_tbl [PE_EXCEPTION_TABLE_BS]; /* 0x88 */
+ unsigned char certificate_tbl [PE_CERTIFICATE_TABLE_BS]; /* 0x90 */
+ unsigned char base_reloc_tbl [PE_BASE_RELOCATION_TABLE_BS]; /* 0x98 */
+ unsigned char debug [PE_DEBUG_BS]; /* 0xa0 */
+ unsigned char arch [PE_ARCHITECTURE_BS]; /* 0xa8 */
+ unsigned char global_ptr [PE_GLOBAL_PTR_BS]; /* 0xb0 */
+ unsigned char tls_tbl [PE_TLS_TABLE_BS]; /* 0xb8 */
+ unsigned char load_config_tbl [PE_LOAD_CONFIG_TABLE_BS]; /* 0xc0 */
+ unsigned char bound_import [PE_BOUND_IMPORT_BS]; /* 0xc8 */
+ unsigned char iat [PE_IAT_BS]; /* 0xd0 */
+ unsigned char delay_import_descriptor [PE_DELAY_IMPORT_DESCRIPTOR_BS]; /* 0xd8 */
+ unsigned char clr_runtime_hdr [PE_CLR_RUNTIME_HEADER_BS]; /* 0xe0 */
+ unsigned char reserved [PE_RESERVED__MUST_BE_ZERO_BS]; /* 0xe8 */
+};
+
+#undef PE_MAGIC_BS
+#undef PE_MAJOR_LINKER_VERSION_BS
+#undef PE_MINOR_LINKER_VERSION_BS
+#undef PE_SIZE_OF_CODE_BS
+#undef PE_SIZE_OF_INITIALIZED_DATA_BS
+#undef PE_SIZE_OF_UNINITIALIZED_DATA_BS
+#undef PE_ADDRESS_OF_ENTRY_POINT_BS
+#undef PE_BASE_OF_CODE_BS
+#undef PE_IMAGE_BASE_BS
+#undef PE_SECTION_ALIGNMENT_BS
+#undef PE_FILE_ALIGNMENT_BS
+#undef PE_MAJOR_OPERATING_SYSTEM_VERSION_BS
+#undef PE_MINOR_OPERATING_SYSTEM_VERSION_BS
+#undef PE_MAJOR_IMAGE_VERSION_BS
+#undef PE_MINOR_IMAGE_VERSION_BS
+#undef PE_MAJOR_SUBSYSTEM_VERSION_BS
+#undef PE_MINOR_SUBSYSTEM_VERSION_BS
+#undef PE_WIN32_VERSION_VALUE_BS
+#undef PE_SIZE_OF_IMAGE_BS
+#undef PE_SIZE_OF_HEADERS_BS
+#undef PE_CHECK_SUM_BS
+#undef PE_SUBSYSTEM_BS
+#undef PE_DLL_CHARACTERISTICS_BS
+#undef PE_SIZE_OF_STACK_RESERVE_BS
+#undef PE_SIZE_OF_STACK_COMMIT_BS
+#undef PE_SIZE_OF_HEAP_RESERVE_BS
+#undef PE_SIZE_OF_HEAP_COMMIT_BS
+#undef PE_LOADER_FLAGS_BS
+#undef PE_NUMBER_OF_RVA_AND_SIZES_BS
+#undef PE_EXPORT_TABLE_BS
+#undef PE_IMPORT_TABLE_BS
+#undef PE_RESOURCE_TABLE_BS
+#undef PE_EXCEPTION_TABLE_BS
+#undef PE_CERTIFICATE_TABLE_BS
+#undef PE_BASE_RELOCATION_TABLE_BS
+#undef PE_DEBUG_BS
+#undef PE_ARCHITECTURE_BS
+#undef PE_GLOBAL_PTR_BS
+#undef PE_TLS_TABLE_BS
+#undef PE_LOAD_CONFIG_TABLE_BS
+#undef PE_BOUND_IMPORT_BS
+#undef PE_IAT_BS
+#undef PE_DELAY_IMPORT_DESCRIPTOR_BS
+#undef PE_CLR_RUNTIME_HEADER_BS
+#undef PE_RESERVED__MUST_BE_ZERO_BS
+
+union pe_opt_hdr {
+ struct pe_opt_hdr_32 opt_hdr_32;
+ struct pe_opt_hdr_64 opt_hdr_64;
+};
+
+
+/* pe_image_data_directory... */
+#define PE_VIRTUAL_ADDRESS_BS 0x04
+#define PE_SIZE_BS 0x04
+
+struct pe_image_data_dir {
+ unsigned char rva [PE_VIRTUAL_ADDRESS_BS]; /* 0x00 */
+ unsigned char size [PE_SIZE_BS]; /* 0x04 */
+};
+
+#undef PE_VIRTUAL_ADDRESS_BS
+#undef PE_SIZE_BS
+
+
+/* pe_section_table... */
+#define PE_NAME_BS 0x08
+#define PE_VIRTUAL_SIZE_BS 0x04
+#define PE_VIRTUAL_ADDRESS_BS 0x04
+#define PE_SIZE_OF_RAW_DATA_BS 0x04
+#define PE_POINTER_TO_RAW_DATA_BS 0x04
+#define PE_POINTER_TO_RELOCATIONS_BS 0x04
+#define PE_POINTER_TO_LINENUMBERS_BS 0x04
+#define PE_NUMBER_OF_RELOCATIONS_BS 0x02
+#define PE_NUMBER_OF_LINENUMBERS_BS 0x02
+#define PE_CHARACTERISTICS_BS 0x04
+
+struct pe_sec_hdr {
+ unsigned char name [PE_NAME_BS]; /* 0x00 */
+ unsigned char virtual_size [PE_VIRTUAL_SIZE_BS]; /* 0x08 */
+ unsigned char virtual_addr [PE_VIRTUAL_ADDRESS_BS]; /* 0x0c */
+ unsigned char size_of_raw_data [PE_SIZE_OF_RAW_DATA_BS]; /* 0x10 */
+ unsigned char ptr_to_raw_data [PE_POINTER_TO_RAW_DATA_BS]; /* 0x14 */
+ unsigned char ptr_to_relocs [PE_POINTER_TO_RELOCATIONS_BS]; /* 0x18 */
+ unsigned char ptr_to_line_nums [PE_POINTER_TO_LINENUMBERS_BS]; /* 0x1c */
+ unsigned char num_of_relocs [PE_NUMBER_OF_RELOCATIONS_BS]; /* 0x20 */
+ unsigned char num_of_line_nums [PE_NUMBER_OF_LINENUMBERS_BS]; /* 0x22 */
+ unsigned char characteristics [PE_CHARACTERISTICS_BS]; /* 0x24 */
+};
+
+#undef PE_NAME_BS
+#undef PE_VIRTUAL_SIZE_BS
+#undef PE_VIRTUAL_ADDRESS_BS
+#undef PE_SIZE_OF_RAW_DATA_BS
+#undef PE_POINTER_TO_RAW_DATA_BS
+#undef PE_POINTER_TO_RELOCATIONS_BS
+#undef PE_POINTER_TO_LINENUMBERS_BS
+#undef PE_NUMBER_OF_RELOCATIONS_BS
+#undef PE_NUMBER_OF_LINENUMBERS_BS
+#undef PE_CHARACTERISTICS_BS
+
+
+/* pe_export_directory_table... */
+#define PE_EXPORT_FLAGS_BS 0x04
+#define PE_TIME_DATE_STAMP_BS 0x04
+#define PE_MAJOR_VERSION_BS 0x02
+#define PE_MINOR_VERSION_BS 0x02
+#define PE_NAME_RVA_BS 0x04
+#define PE_ORDINAL_BASE_BS 0x04
+#define PE_ADDRESS_TABLE_ENTRIES_BS 0x04
+#define PE_NUMBER_OF_NAME_POINTERS_BS 0x04
+#define PE_EXPORT_ADDRESS_TABLE_RVA_BS 0x04
+#define PE_NAME_POINTER_RVA_BS 0x04
+#define PE_ORDINAL_TABLE_RVA_BS 0x04
+
+struct pe_export_hdr {
+ unsigned char export_flags [PE_EXPORT_FLAGS_BS]; /* 0x00 */
+ unsigned char time_date_stamp [PE_TIME_DATE_STAMP_BS]; /* 0x04 */
+ unsigned char major_ver [PE_MAJOR_VERSION_BS]; /* 0x08 */
+ unsigned char minor_ver [PE_MINOR_VERSION_BS]; /* 0x0a */
+ unsigned char name_rva [PE_NAME_RVA_BS]; /* 0x0c */
+ unsigned char ordinal_base [PE_ORDINAL_BASE_BS]; /* 0x10 */
+ unsigned char addr_tbl_entries [PE_ADDRESS_TABLE_ENTRIES_BS]; /* 0x14 */
+ unsigned char num_of_name_ptrs [PE_NUMBER_OF_NAME_POINTERS_BS]; /* 0x18 */
+ unsigned char export_addr_tbl_rva [PE_EXPORT_ADDRESS_TABLE_RVA_BS]; /* 0x1c */
+ unsigned char name_ptr_rva [PE_NAME_POINTER_RVA_BS]; /* 0x20 */
+ unsigned char ordinal_tbl_rva [PE_ORDINAL_TABLE_RVA_BS]; /* 0x24 */
+};
+
+#undef PE_EXPORT_FLAGS_BS
+#undef PE_TIME_DATE_STAMP_BS
+#undef PE_MAJOR_VERSION_BS
+#undef PE_MINOR_VERSION_BS
+#undef PE_NAME_RVA_BS
+#undef PE_ORDINAL_BASE_BS
+#undef PE_ADDRESS_TABLE_ENTRIES_BS
+#undef PE_NUMBER_OF_NAME_POINTERS_BS
+#undef PE_EXPORT_ADDRESS_TABLE_RVA_BS
+#undef PE_NAME_POINTER_RVA_BS
+#undef PE_ORDINAL_TABLE_RVA_BS
+
+
+/* pe_export_address_table... */
+#define PE_EXPORT_RVA_BS 0x04
+#define PE_FORWARDER_RVA_BS 0x04
+
+union pe_export_addr_tbl {
+ unsigned char export_rva [PE_EXPORT_RVA_BS]; /* 0x00 */
+ unsigned char forwarder_rva [PE_FORWARDER_RVA_BS]; /* 0x00 */
+};
+
+#undef PE_EXPORT_RVA_BS
+#undef PE_FORWARDER_RVA_BS
+
+
+/* image: pe_import_table_entry_lookup_item... */
+#define PE_IMPORT_LOOKUP_ENTRY_PE64_BS 0x08
+#define PE_IMPORT_LOOKUP_ENTRY_PE32_BS 0x04
+#define PE_HINT_NAME_TABLE_RVA_BS 0x04
+#define PE_ORDINAL_NUMBER_BS 0x02
+
+struct pe_import_lookup_item {
+ union {
+ unsigned char import_lookup_entry_64 [PE_IMPORT_LOOKUP_ENTRY_PE64_BS]; /* 0x00 */
+ unsigned char import_lookup_entry_32 [PE_IMPORT_LOOKUP_ENTRY_PE32_BS]; /* 0x00 */
+ unsigned char hint_name_tbl_rva [PE_HINT_NAME_TABLE_RVA_BS]; /* 0x00 */
+ unsigned char ordinal_number [PE_ORDINAL_NUMBER_BS]; /* 0x00 */
+ } u;
+};
+
+#undef PE_IMPORT_LOOKUP_ENTRY_PE64_BS
+#undef PE_IMPORT_LOOKUP_ENTRY_PE32_BS
+#undef PE_HINT_NAME_TABLE_RVA_BS
+#undef PE_ORDINAL_NUMBER_BS
+
+
+/* image: pe_import_directory_table_entry... */
+#define PE_IMPORT_LOOKUP_TABLE_RVA_BS 0x04
+#define PE_TIME_DATE_STAMP_BS 0x04
+#define PE_FORWARDER_CHAIN_BS 0x04
+#define PE_NAME_RVA_BS 0x04
+#define PE_IMPORT_ADDRESS_TABLE_RVA_BS 0x04
+
+struct pe_import_hdr {
+ unsigned char import_lookup_tbl_rva [PE_IMPORT_LOOKUP_TABLE_RVA_BS]; /* 0x00 */
+ unsigned char time_date_stamp [PE_TIME_DATE_STAMP_BS]; /* 0x04 */
+ unsigned char forwarder_chain [PE_FORWARDER_CHAIN_BS]; /* 0x08 */
+ unsigned char name_rva [PE_NAME_RVA_BS]; /* 0x0c */
+ unsigned char import_addr_tbl_rva [PE_IMPORT_ADDRESS_TABLE_RVA_BS]; /* 0x10 */
+};
+
+#undef PE_IMPORT_LOOKUP_TABLE_RVA_BS
+#undef PE_TIME_DATE_STAMP_BS
+#undef PE_FORWARDER_CHAIN_BS
+#undef PE_NAME_RVA_BS
+#undef PE_IMPORT_ADDRESS_TABLE_RVA_BS
+
+
+/* pe_hint_name_table_padded... */
+#define PE_HINT_BS 0x02
+#define PE_NAME_BS 0x02
+
+struct pe_hint_name_entry {
+ unsigned char hint [PE_HINT_BS]; /* 0x00 */
+ unsigned char name [PE_NAME_BS]; /* 0x02 */
+};
+
+#undef PE_HINT_BS
+#undef PE_NAME_BS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/pemagine/pemagine.h b/include/pemagine/pemagine.h
new file mode 100644
index 0000000..8beb5e4
--- /dev/null
+++ b/include/pemagine/pemagine.h
@@ -0,0 +1,196 @@
+#ifndef PEMAGINE_H
+#define PEMAGINE_H
+
+#include "pe_api.h"
+#include "pe_consts.h"
+#include "pe_structs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum pe_callback_reason {
+ PE_CALLBACK_REASON_INIT = 0x00,
+ PE_CALLBACK_REASON_ITEM = 0x01,
+ PE_CALLBACK_REASON_INFO = 0x02,
+ PE_CALLBACK_REASON_QUERY = 0x04,
+ PE_CALLBACK_REASON_DONE = 0x1000,
+ PE_CALLBACK_REASON_ERROR = (-1)
+};
+
+
+/* library specific structures */
+struct pe_export_sym {
+ uint32_t * ordinal_base;
+ uint16_t * ordinal;
+ void * addr;
+ void * forwarder_rva;
+ char * name;
+ long status;
+};
+
+
+struct pe_unicode_str {
+ uint16_t strlen;
+ uint16_t maxlen;
+ uint16_t * buffer;
+};
+
+
+struct pe_list_entry {
+ struct pe_list_entry * flink;
+ struct pe_list_entry * blink;
+};
+
+
+struct pe_client_id {
+ uint32_t process_id;
+ uint32_t thread_id;
+};
+
+
+struct pe_stack_heap_info {
+ size_t size_of_stack_reserve;
+ size_t size_of_stack_commit;
+ size_t size_of_heap_reserve;
+ size_t size_of_heap_commit;
+};
+
+
+struct pe_peb_ldr_data {
+ uint32_t length;
+ uint32_t initialized;
+ void * ss_handle;
+ struct pe_list_entry in_load_order_module_list;
+ struct pe_list_entry in_memory_order_module_list;
+ struct pe_list_entry in_init_order_module_list;
+};
+
+
+struct pe_ldr_tbl_entry {
+ struct pe_list_entry in_load_order_links;
+ struct pe_list_entry in_memory_order_links;
+ struct pe_list_entry in_init_order_links;
+ void * dll_base;
+ void * entry_point;
+
+ union {
+ uint32_t size_of_image;
+ unsigned char size_of_image_padding[sizeof(uintptr_t)];
+ };
+
+ struct pe_unicode_str full_dll_name;
+ struct pe_unicode_str base_dll_name;
+ uint32_t flags;
+ uint16_t load_count;
+ uint16_t tls_index;
+
+ union {
+ struct pe_list_entry hash_links;
+ struct {
+ void * section_pointer;
+ uint32_t check_sum;
+ };
+ };
+
+ union {
+ void * loaded_imports;
+ uint32_t time_date_stamp;
+ };
+
+ void * entry_point_activation_context;
+ void * patch_information;
+ struct pe_list_entry forwarder_links;
+ struct pe_list_entry service_tag_links;
+ struct pe_list_entry static_links;
+ void * context_information;
+ uintptr_t original_base;
+ int64_t load_time;
+};
+
+
+
+/* static inlined functions */
+static __inline__ void * pe_get_teb_address(void);
+static __inline__ void * pe_get_peb_address(void);
+static __inline__ void * pe_get_peb_address_alt(void);
+static __inline__ void * pe_get_peb_ldr_data_address(void);
+static __inline__ void * pe_get_peb_ldr_data_address_alt(void);
+static __inline__ uint32_t pe_get_current_process_id(void);
+static __inline__ uint32_t pe_get_current_thread_id(void);
+static __inline__ uint32_t pe_get_current_session_id(void);
+static __inline__ void * pe_va_from_rva(const void * base, intptr_t offset);
+
+#include "pe_inline_asm.h"
+
+
+/**
+ * user callback function responses
+ *
+ * positive: continue enumeration.
+ * zero: exit enumeration (ok).
+ * negative: exit enumeration (error).
+**/
+
+/* callback signatures */
+typedef int pe_enum_modules_callback(
+ struct pe_ldr_tbl_entry * image_ldr_tbl_entry,
+ enum pe_callback_reason reason,
+ void * context);
+
+typedef int pe_enum_image_exports_callback(
+ const void * base,
+ struct pe_export_hdr * exp_hdr,
+ struct pe_export_sym * sym,
+ enum pe_callback_reason reason,
+ void * context);
+
+typedef int pe_enum_image_import_hdrs_callback(
+ const void * base,
+ struct pe_import_hdr * imp_hdr,
+ enum pe_callback_reason reason,
+ void * context);
+
+/* library functions */
+pe_api struct pe_image_dos_hdr *pe_get_image_dos_hdr_addr (const void * base);
+pe_api struct pe_coff_file_hdr *pe_get_image_coff_hdr_addr (const void * base);
+pe_api union pe_opt_hdr * pe_get_image_opt_hdr_addr (const void * base);
+pe_api struct pe_data_dirs * pe_get_image_data_dirs_addr (const void * base);
+pe_api struct pe_export_hdr * pe_get_image_export_hdr_addr (const void * base, uint32_t * sec_size);
+pe_api struct pe_import_hdr * pe_get_image_import_dir_addr (const void * base, uint32_t * sec_size);
+pe_api void * pe_get_image_special_hdr_addr (const void * base, uint32_t ordinal, uint32_t * sec_size);
+pe_api void * pe_get_image_entry_point_addr (const void * base);
+pe_api int pe_get_image_stack_heap_info (const void * base, struct pe_stack_heap_info *);
+
+pe_api void * pe_get_procedure_address (const void * base, const char * name);
+pe_api int pe_get_export_symbol_info (const void * base, const char * name, struct pe_export_sym *);
+pe_api int pe_enum_image_exports (const void * base,
+ pe_enum_image_exports_callback *,
+ struct pe_export_sym *,
+ void * ctx);
+
+pe_api int pe_enum_image_import_hdrs (const void * base,
+ pe_enum_image_import_hdrs_callback *,
+ void * ctx);
+
+pe_api char * pe_get_symbol_name (const void * base, const void * sym_addr);
+pe_api struct pe_ldr_tbl_entry *pe_get_symbol_module_info (const void * sym_addr);
+pe_api char * pe_get_import_symbol_info (const void * sym_addr,
+ void ** sym_image_addr,
+ char ** sym_name,
+ struct pe_ldr_tbl_entry ** ldr_tbl_entry);
+
+pe_api int pe_enum_modules_in_load_order (pe_enum_modules_callback *, void * ctx);
+pe_api int pe_enum_modules_in_memory_order (pe_enum_modules_callback *, void * ctx);
+pe_api int pe_enum_modules_in_init_order (pe_enum_modules_callback *, void * ctx);
+pe_api void * pe_get_module_handle (const wchar16_t * name);
+pe_api void * pe_get_first_module_handle (void);
+pe_api void * pe_get_ntdll_module_handle (void);
+pe_api void * pe_get_kernel32_module_handle (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/pemagine.lzy b/pemagine.lzy
new file mode 100644
index 0000000..ed1df9c
--- /dev/null
+++ b/pemagine.lzy
@@ -0,0 +1,128 @@
+lz_project_rules()
+{
+ lz_rules="all install xstatic install_xstatic"
+}
+
+lz_project_definitions()
+{
+ pemagine_lib_name=libpemagine
+ pemagine_so_name="$lz_build_dir/lib/$pemagine_lib_name$lz_dylib_ext"
+ pemagine_a_name="$lz_build_dir/lib/$pemagine_lib_name$lz_stlib_ext"
+ pemagine_so_def_name="$lz_build_dir/lib/$pemagine_lib_name$lz_libdef_ext"
+ pemagine_implib_name="$lz_build_dir/lib/$pemagine_lib_name$lz_implib_ext"
+
+ lz_cflags_common="-DMIDIPIX_FREESTANDING
+ -D__NT$lz_arch_bits \
+ -UWIN32 -U_WIN32 -U__WIN32 -U__WIN32__ \
+ -UWIN64 -U_WIN64 -U__WIN64 -U__WIN64__ \
+ -Werror=all -fno-builtin -ffreestanding"
+
+
+ # lz_cflags_extra="-Os -fno-stack-protector -fomit-frame-pointer -fno-unwind-tables -fno-asynchronous-unwind-tables"
+
+ pemagine_so_ldflags="-shared --image-base=0x560000 \
+ --entry "$lz_default_underscore"pe_lib_entry_point@12 \
+ --exclude-all-symbols \
+ --output-def $pemagine_so_def_name \
+ --out-implib $pemagine_implib_name \
+ --subsystem=windows"
+
+ lz_cflags_include_common="-I$lz_project_dir/src/internal -I$lz_project_dir/include"
+
+ if [ "$MIDIPIX_ROOT"x != x ]; then
+ lz_cflags_include_common="$lz_cflags_include_common -I$MIDIPIX_ROOT/include"
+ fi
+
+ pemagine_so_obj_list=pemagine.so.objs
+ pemagine_so_src_list=pemagine.so.src.lst
+
+ pemagine_a_obj_list=pemagine.a.objs
+ pemagine_a_src_list=pemagine.a.src.lst
+}
+
+pemagine_shared()
+{
+ lz_src_dirs="src"
+ lz_cflags_step="-DPE_BUILD"
+
+ if ! [ "$lz_pecoff_winnt"x = yesx ]; then
+ lz_cflags_step="$lz_cflags_step -fpic"
+ fi
+
+ lz_compile "$pemagine_so_obj_list" "$pemagine_so_src_list" "$lz_dyobj_ext"
+ lz_link "$pemagine_so_obj_list" "$pemagine_so_src_list" "$pemagine_so_name" \
+ "$pemagine_so_ldflags" \
+ ''
+}
+
+
+pemagine_static()
+{
+ lz_src_dirs="src"
+
+ lz_compile "$pemagine_a_obj_list" "$pemagine_a_src_list" "$lz_stobj_ext"
+ lz_archive "$pemagine_a_obj_list" "$pemagine_a_src_list" "$pemagine_a_name"
+}
+
+
+pemagine_xstatic()
+{
+ lz_src_dirs="src"
+ lz_cflags_step="-DPE_BUILD"
+
+ lz_compile "$pemagine_a_obj_list" "$pemagine_a_src_list" "$lz_stobj_ext"
+ lz_archive "$pemagine_a_obj_list" "$pemagine_a_src_list" "$pemagine_a_name"
+}
+
+
+pemagine_install_headers()
+{
+ lz_pushd $lz_project_dir
+
+ cp -r -t $lz_prefix/include include/$lz_project_name
+
+ lz_popd
+}
+
+
+pemagine_install_shared()
+{
+ lz_pushd $lz_build_dir/lib
+
+ cp -t $lz_prefix/lib $pemagine_lib_name$lz_dylib_ext
+ cp -t $lz_prefix/lib $pemagine_lib_name$lz_implib_ext
+
+ lz_popd
+}
+
+
+pemagine_install_static()
+{
+ lz_pushd $lz_build_dir/lib
+
+ cp -t $lz_prefix/lib $pemagine_lib_name$lz_stlib_ext
+
+ lz_popd
+}
+
+
+pemagine_install_xstatic()
+{
+ lz_step pemagine_xstatic
+ lz_step pemagine_install_static
+}
+
+pemagine_all()
+{
+ lz_step pemagine_shared
+ lz_step pemagine_static
+}
+
+
+pemagine_install()
+{
+ lz_step pemagine_all
+ lz_step pemagine_install_shared
+ lz_step pemagine_install_static
+ lz_step pemagine_install_headers
+}
diff --git a/src/exports/pe_enum_image_exports.c b/src/exports/pe_enum_image_exports.c
new file mode 100644
index 0000000..85e92cf
--- /dev/null
+++ b/src/exports/pe_enum_image_exports.c
@@ -0,0 +1,61 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+int pe_enum_image_exports(
+ const void * base,
+ pe_enum_image_exports_callback * callback,
+ struct pe_export_sym * sym,
+ void * ctx)
+{
+ struct pe_export_hdr * exp_hdr;
+ uint32_t * count;
+ uint32_t * fn_addr;
+ uint32_t * fn_names;
+ uint16_t * fn_ordinals;
+ uint32_t * offset;
+ uint32_t idx;
+ int ret;
+
+ if (!(exp_hdr = pe_get_image_export_hdr_addr(base,0))) {
+ callback(base,0,0,PE_CALLBACK_REASON_ERROR,ctx);
+ return -1;
+ }
+
+ offset = (uint32_t *)(exp_hdr->export_addr_tbl_rva);
+ fn_addr = (uint32_t *)pe_va_from_rva(base,*offset);
+
+ offset = (uint32_t *)(exp_hdr->name_ptr_rva);
+ fn_names = (uint32_t *)pe_va_from_rva(base,*offset);
+
+ offset = (uint32_t *)(exp_hdr->ordinal_tbl_rva);
+ fn_ordinals = (uint16_t *)pe_va_from_rva(base,*offset);
+
+ if ((ret = callback(base,exp_hdr,0,PE_CALLBACK_REASON_INIT,ctx)) <= 0)
+ return ret;
+
+ count = (uint32_t *)exp_hdr->num_of_name_ptrs;
+ sym->ordinal_base = (uint32_t *)exp_hdr->ordinal_base;
+
+ for (idx=0; idx<*count; idx++) {
+ offset = (uint32_t *)pe_va_from_rva(fn_names,idx*sizeof(uint32_t));
+ sym->name = (char *)pe_va_from_rva(base,*offset);
+ sym->ordinal = (uint16_t *)pe_va_from_rva(fn_ordinals,idx*sizeof(uint16_t));
+
+ offset = (uint32_t *)pe_va_from_rva(fn_addr,(*sym->ordinal)*sizeof(uint32_t));
+ sym->addr = pe_va_from_rva(base,*offset);
+
+ if ((ret = callback(base,exp_hdr,sym,PE_CALLBACK_REASON_ITEM,ctx)) <= 0)
+ return ret;
+ }
+
+ return callback(base,exp_hdr,sym,PE_CALLBACK_REASON_DONE,ctx);
+}
diff --git a/src/exports/pe_get_export_symbol_info.c b/src/exports/pe_get_export_symbol_info.c
new file mode 100644
index 0000000..9f00634
--- /dev/null
+++ b/src/exports/pe_get_export_symbol_info.c
@@ -0,0 +1,142 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+static __inline__ int pe_addr_within_bounds(void * addr, void * bottom, void * top)
+{
+ return (((uintptr_t)addr >= (uintptr_t)bottom) && ((uintptr_t)addr < (uintptr_t)top));
+}
+
+pe_api
+int pe_get_export_symbol_info(
+ const void * base,
+ const char * name,
+ struct pe_export_sym * sym)
+{
+ struct pe_export_hdr * exp_hdr;
+
+ size_t len;
+ uint32_t * rva_offset;
+ uintptr_t * addr_offset;
+
+ uint32_t sec_size;
+ void * sec_addr_cap;
+
+ uint32_t * fn_addr;
+ uint32_t * fn_names;
+ uint16_t * fn_ordinals;
+ uint32_t * addr_entries;
+ uint32_t * name_entries;
+
+ char * exp_name;
+ const char * src;
+ const char * dst;
+ size_t match;
+
+ uint32_t lower;
+ uint32_t upper;
+ uint32_t idx;
+
+ /* initialize pe_exp_item */
+ sym->ordinal_base = (uint32_t *)0;
+ sym->ordinal = (uint16_t *)0;
+ sym->addr = (void *)0;
+ sym->forwarder_rva = (void *)0;
+ sym->name = (char *)0;
+ sym->status = 0;
+
+ if (!(exp_hdr = pe_get_image_export_hdr_addr(base,&sec_size)))
+ return -1;
+
+ sec_addr_cap = pe_va_from_rva(exp_hdr,sec_size);
+ rva_offset = (uint32_t *)(exp_hdr->export_addr_tbl_rva);
+ fn_addr = (uint32_t *)pe_va_from_rva(base,*rva_offset);
+
+ rva_offset = (uint32_t *)(exp_hdr->name_ptr_rva);
+ fn_names = (uint32_t *)pe_va_from_rva(base,*rva_offset);
+
+ rva_offset = (uint32_t *)(exp_hdr->ordinal_tbl_rva);
+ fn_ordinals = (uint16_t *)pe_va_from_rva(base,*rva_offset);
+
+ addr_entries = (uint32_t *)exp_hdr->addr_tbl_entries;
+ name_entries = (uint32_t *)exp_hdr->num_of_name_ptrs;
+
+ /* by ordinal? */
+ if ((intptr_t)name < 0x10000) {
+ sym->ordinal_base = (uint32_t *)exp_hdr->ordinal_base;
+
+ /* the array is zero-based, but ordinals are normally one-based... */
+ if (((intptr_t)name - *sym->ordinal_base + 1) > *addr_entries)
+ return -1;
+
+ rva_offset = (uint32_t *)pe_va_from_rva(fn_addr,((uintptr_t)name-*sym->ordinal_base)*sizeof(uint32_t));
+ addr_offset = (uintptr_t *)pe_va_from_rva(base,*rva_offset);
+
+ if (pe_addr_within_bounds(addr_offset,exp_hdr,sec_addr_cap)) {
+ sym->forwarder_rva = 0;
+ sym->addr = addr_offset;
+ } else
+ /* todo: resolve forwarder address */
+ sym->addr = addr_offset;
+
+ return 0;
+ }
+
+ if ((len = pe_impl_strlen_ansi(name)) < 0)
+ return -1;
+
+ len++;
+ lower = 0;
+ upper = *name_entries;
+
+ while (lower < upper) {
+ idx = (lower + upper) / 2;
+ rva_offset = (uint32_t *)pe_va_from_rva(fn_names,idx*sizeof(uint32_t));
+ exp_name = (char *)pe_va_from_rva(base,*rva_offset);
+
+ src = name;
+ dst = exp_name;
+
+ for (match=0; (match<len) && (*src==*dst); match++) {
+ src++;
+ dst++;
+ }
+
+ if (match == len) {
+ sym->ordinal_base = (uint32_t *)exp_hdr->ordinal_base;
+ sym->ordinal = (uint16_t *)pe_va_from_rva(fn_ordinals,idx*sizeof(uint16_t));
+
+ rva_offset = (uint32_t *)pe_va_from_rva(fn_addr,(*sym->ordinal)*sizeof(uint32_t));
+ addr_offset = (uintptr_t *)pe_va_from_rva(base,*rva_offset);
+
+ if (pe_addr_within_bounds(addr_offset,exp_hdr,sec_addr_cap)) {
+ /* todo: resolve forwarder address */
+ sym->forwarder_rva = 0;
+ sym->addr = 0;
+ } else {
+ sym->forwarder_rva = 0;
+ sym->addr = addr_offset;
+ }
+
+ return 0;
+ }
+
+ else {
+ if (*src > *dst)
+ lower = idx + 1;
+ else
+ upper = idx;
+ }
+ }
+
+ /* export name not found */
+ return -1;
+}
diff --git a/src/exports/pe_get_procedure_address.c b/src/exports/pe_get_procedure_address.c
new file mode 100644
index 0000000..958f205
--- /dev/null
+++ b/src/exports/pe_get_procedure_address.c
@@ -0,0 +1,18 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <pemagine/pemagine.h>
+
+pe_api
+void * pe_get_procedure_address(const void * base, const char * name)
+{
+ struct pe_export_sym sym;
+
+ return pe_get_export_symbol_info(base,name,&sym)
+ ? 0
+ : sym.addr;
+
+}
diff --git a/src/headers/pe_get_image_coff_hdr_addr.c b/src/headers/pe_get_image_coff_hdr_addr.c
new file mode 100644
index 0000000..d2ff03a
--- /dev/null
+++ b/src/headers/pe_get_image_coff_hdr_addr.c
@@ -0,0 +1,30 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+struct pe_coff_file_hdr * pe_get_image_coff_hdr_addr(const void * base)
+{
+ struct pe_image_dos_hdr * dos;
+ struct pe_coff_file_hdr * coff;
+ uint32_t * offset;
+
+ if (!(dos = pe_get_image_dos_hdr_addr(base)))
+ return 0;
+
+ offset = (uint32_t *)(dos->dos_lfanew);
+ coff = (struct pe_coff_file_hdr *)pe_va_from_rva(base,*offset);
+
+ if ((coff->signature[0] == 'P') && (coff->signature[1] == 'E')
+ && (coff->signature[2] == '\0') && (coff->signature[3] == '\0'))
+ return coff;
+ else
+ return 0;
+}
diff --git a/src/headers/pe_get_image_data_dirs_addr.c b/src/headers/pe_get_image_data_dirs_addr.c
new file mode 100644
index 0000000..d0167c0
--- /dev/null
+++ b/src/headers/pe_get_image_data_dirs_addr.c
@@ -0,0 +1,33 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+struct pe_data_dirs * pe_get_image_data_dirs_addr(const void * base)
+{
+ uint16_t * magic;
+ union pe_opt_hdr * hdr;
+
+ if (!(hdr = pe_get_image_opt_hdr_addr(base)))
+ return 0;
+
+ magic = (uint16_t *)hdr;
+
+ switch (*magic) {
+ case PE_MAGIC_PE32:
+ return (struct pe_data_dirs *)hdr->opt_hdr_32.rva_and_sizes;
+
+ case PE_MAGIC_PE32_PLUS:
+ return (struct pe_data_dirs *)hdr->opt_hdr_64.rva_and_sizes;
+
+ default:
+ return 0;
+ }
+}
diff --git a/src/headers/pe_get_image_dos_hdr_addr.c b/src/headers/pe_get_image_dos_hdr_addr.c
new file mode 100644
index 0000000..279d04e
--- /dev/null
+++ b/src/headers/pe_get_image_dos_hdr_addr.c
@@ -0,0 +1,24 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+struct pe_image_dos_hdr * pe_get_image_dos_hdr_addr(const void * base)
+{
+ struct pe_image_dos_hdr * dos;
+
+ dos = (struct pe_image_dos_hdr *)base;
+
+ if ((dos->dos_magic[0] == 'M') && (dos->dos_magic[1] == 'Z'))
+ return dos;
+ else
+ return 0;
+}
diff --git a/src/headers/pe_get_image_entry_point_addr.c b/src/headers/pe_get_image_entry_point_addr.c
new file mode 100644
index 0000000..5869633
--- /dev/null
+++ b/src/headers/pe_get_image_entry_point_addr.c
@@ -0,0 +1,39 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pemagine.h>
+
+
+pe_api
+void * pe_get_image_entry_point_addr(const void * base)
+{
+ uint16_t * magic;
+ union pe_opt_hdr * hdr;
+ uint32_t * rva;
+
+ if (!(hdr = pe_get_image_opt_hdr_addr(base)))
+ return 0;
+
+ magic = (uint16_t *)hdr;
+
+ switch (*magic) {
+ case PE_MAGIC_PE32:
+ rva = (uint32_t *)hdr->opt_hdr_32.entry_point;
+ break;
+
+ case PE_MAGIC_PE32_PLUS:
+ rva = (uint32_t *)hdr->opt_hdr_64.entry_point;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return pe_va_from_rva(base,*rva);
+}
diff --git a/src/headers/pe_get_image_opt_hdr_addr.c b/src/headers/pe_get_image_opt_hdr_addr.c
new file mode 100644
index 0000000..dcb8c48
--- /dev/null
+++ b/src/headers/pe_get_image_opt_hdr_addr.c
@@ -0,0 +1,20 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+union pe_opt_hdr * pe_get_image_opt_hdr_addr(const void * base)
+{
+ struct pe_coff_file_hdr * coff;
+
+ if (!(coff = pe_get_image_coff_hdr_addr(base)))
+ return 0;
+ else
+ return (union pe_opt_hdr *)pe_va_from_rva(coff, sizeof(*coff));
+}
diff --git a/src/headers/pe_get_image_special_hdr_addr.c b/src/headers/pe_get_image_special_hdr_addr.c
new file mode 100644
index 0000000..276ec9f
--- /dev/null
+++ b/src/headers/pe_get_image_special_hdr_addr.c
@@ -0,0 +1,49 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+pe_api
+void * pe_get_image_special_hdr_addr(const void * base, uint32_t ordinal, uint32_t * sec_size)
+{
+ struct pe_data_dirs * dirs;
+ struct pe_block * dir;
+ uint32_t * count;
+
+ if (!(dirs = pe_get_image_data_dirs_addr(base)))
+ return 0;
+
+ count = (uint32_t *)dirs->rva_and_sizes;
+
+ if (*count < (ordinal+1))
+ return 0;
+
+ dir = (struct pe_block *)dirs->export_tbl;
+ dir += ordinal;
+
+ if (sec_size)
+ *sec_size = dir->size;
+
+ return dir->rva
+ ? pe_va_from_rva(base,dir->rva)
+ : 0;
+}
+
+pe_api
+struct pe_export_hdr * pe_get_image_export_hdr_addr(const void * base, uint32_t * sec_size)
+{
+ return (struct pe_export_hdr *)pe_get_image_special_hdr_addr(base,PE_IMAGE_DATA_DIR_ORDINAL_EXPORT,sec_size);
+}
+
+pe_api
+struct pe_import_hdr * pe_get_image_import_dir_addr(const void * base, uint32_t * sec_size)
+{
+ return (struct pe_import_hdr *)pe_get_image_special_hdr_addr(base,PE_IMAGE_DATA_DIR_ORDINAL_IMPORT,sec_size);
+}
diff --git a/src/imports/pe_enum_image_import_hdrs.c b/src/imports/pe_enum_image_import_hdrs.c
new file mode 100644
index 0000000..0a1a10e
--- /dev/null
+++ b/src/imports/pe_enum_image_import_hdrs.c
@@ -0,0 +1,35 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+int pe_enum_image_import_hdrs(
+ const void * base,
+ pe_enum_image_import_hdrs_callback * callback,
+ void * ctx)
+{
+ struct pe_import_hdr * imp_hdr;
+ int ret;
+
+ if (!(imp_hdr = pe_get_image_import_dir_addr(base,0))) {
+ callback(base,0,PE_CALLBACK_REASON_ERROR,ctx);
+ return -1;
+ }
+
+ if ((ret = callback(base,0,PE_CALLBACK_REASON_INIT,ctx)) <= 0)
+ return ret;
+
+ while (imp_hdr->name_rva[0]) {
+ if ((ret = callback(base,imp_hdr,PE_CALLBACK_REASON_ITEM,ctx)) <= 0)
+ return ret;
+ imp_hdr++;
+ };
+
+ return callback(base,imp_hdr,PE_CALLBACK_REASON_DONE,ctx);
+}
diff --git a/src/internal/pe_impl.c b/src/internal/pe_impl.c
new file mode 100644
index 0000000..46069e8
--- /dev/null
+++ b/src/internal/pe_impl.c
@@ -0,0 +1,51 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+size_t pe_impl_strlen_ansi(const char * str)
+{
+ char * ch;
+ char * upper_bound;
+
+ /* sanity check */
+ upper_bound = (char *)str + PE_STR_MAX_SYMBOL_LEN_ALLOWED;
+
+ for (ch = (char *)str; (ch < upper_bound) && (*ch); ch++);
+
+ if (ch < upper_bound)
+ return (size_t)((intptr_t)ch - (intptr_t)str);
+ else
+ return -1;
+}
+
+
+size_t pe_impl_strlen_utf16(const wchar16_t * str)
+{
+ wchar16_t * wch;
+ wchar16_t * upper_bound;
+
+ /* sanity check */
+ upper_bound = (wchar16_t *)str + PE_STR_MAX_SYMBOL_LEN_ALLOWED;
+
+ for (wch = (wchar16_t *)str; (wch < upper_bound) && (*wch); wch++);
+
+ if (wch < upper_bound)
+ return (size_t)((intptr_t)wch - (intptr_t)str);
+ else
+ return -1;
+}
+
+
+wchar16_t pe_impl_utf16_char_to_lower(const wchar16_t c)
+{
+ if ((c >= 'A') && (c <= 'Z'))
+ return c + 'a' - 'A';
+ else
+ return c;
+}
diff --git a/src/internal/pe_impl.h b/src/internal/pe_impl.h
new file mode 100644
index 0000000..09e81c9
--- /dev/null
+++ b/src/internal/pe_impl.h
@@ -0,0 +1,17 @@
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+
+#define PE_STR_MAX_SYMBOL_LEN_ALLOWED (uint32_t)0x10000
+
+#define IN_LOAD_ORDER_MODULE_LIST_OFFSET (intptr_t)0x00
+#define IN_MEMORY_ORDER_MODULE_LIST_OFFSET (intptr_t)0x01 * sizeof(struct pe_list_entry)
+#define IN_INITIALIZATION_ORDER_MODULE_LIST_OFFSET (intptr_t)0x02 * sizeof(struct pe_list_entry)
+
+struct pe_block {
+ uint32_t rva;
+ uint32_t size;
+};
+
+size_t pe_impl_strlen_ansi(const char * str);
+size_t pe_impl_strlen_utf16(const wchar16_t * str);
+wchar16_t pe_impl_utf16_char_to_lower(const wchar16_t c);
diff --git a/src/internal/pe_lib_entry_point.c b/src/internal/pe_lib_entry_point.c
new file mode 100644
index 0000000..efdaa26
--- /dev/null
+++ b/src/internal/pe_lib_entry_point.c
@@ -0,0 +1,6 @@
+#include <psxtypes/psxtypes.h>
+
+int __stdcall pe_lib_entry_point(void * hinstance, uint32_t reason, void * reserved)
+{
+ return 1;
+}
diff --git a/src/meta/pe_get_image_stack_heap_info.c b/src/meta/pe_get_image_stack_heap_info.c
new file mode 100644
index 0000000..ec1aba9
--- /dev/null
+++ b/src/meta/pe_get_image_stack_heap_info.c
@@ -0,0 +1,43 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+
+pe_api
+int pe_get_image_stack_heap_info(const void * base, struct pe_stack_heap_info * stack_heap_info)
+{
+ uint16_t * magic;
+ union pe_opt_hdr * hdr;
+
+ if (!(hdr = pe_get_image_opt_hdr_addr(base)))
+ return 0;
+
+ magic = (uint16_t *)hdr;
+
+ switch (*magic) {
+ case PE_MAGIC_PE32:
+ stack_heap_info->size_of_stack_reserve = *(uint32_t *)hdr->opt_hdr_32.size_of_stack_reserve;
+ stack_heap_info->size_of_stack_commit = *(uint32_t *)hdr->opt_hdr_32.size_of_stack_commit;
+ stack_heap_info->size_of_heap_reserve = *(uint32_t *)hdr->opt_hdr_32.size_of_heap_reserve;
+ stack_heap_info->size_of_heap_commit = *(uint32_t *)hdr->opt_hdr_32.size_of_heap_commit;
+ break;
+
+ case PE_MAGIC_PE32_PLUS:
+ stack_heap_info->size_of_stack_reserve = *(size_t *)hdr->opt_hdr_64.size_of_stack_reserve;
+ stack_heap_info->size_of_stack_commit = *(size_t *)hdr->opt_hdr_64.size_of_stack_commit;
+ stack_heap_info->size_of_heap_reserve = *(size_t *)hdr->opt_hdr_64.size_of_heap_reserve;
+ stack_heap_info->size_of_heap_commit = *(size_t *)hdr->opt_hdr_64.size_of_heap_commit;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/meta/pe_get_symbol_module_info.c b/src/meta/pe_get_symbol_module_info.c
new file mode 100644
index 0000000..7dd8a5a
--- /dev/null
+++ b/src/meta/pe_get_symbol_module_info.c
@@ -0,0 +1,56 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+
+
+struct pe_module_info_ctx {
+ uintptr_t sym_addr;
+ struct pe_ldr_tbl_entry * image_ldr_tbl_entry;
+};
+
+
+
+static int pe_get_symbol_module_info_callback(
+ struct pe_ldr_tbl_entry * ldr_tbl_entry,
+ enum pe_callback_reason reason,
+ void * context)
+{
+ uintptr_t image_base;
+ uintptr_t image_size;
+ struct pe_module_info_ctx * ctx;
+
+ if (reason != PE_CALLBACK_REASON_ITEM)
+ return 1;
+
+ ctx = (struct pe_module_info_ctx *)context;
+ image_base = (uintptr_t)(ldr_tbl_entry->dll_base);
+ image_size = (uintptr_t)(ldr_tbl_entry->size_of_image);
+
+ if ((ctx->sym_addr > image_base) && (ctx->sym_addr < image_base + image_size)) {
+ /* within bounds */
+ ctx->image_ldr_tbl_entry = ldr_tbl_entry;
+ return 0;
+ } else
+ return 1;
+}
+
+
+pe_api
+struct pe_ldr_tbl_entry * pe_get_symbol_module_info(const void * sym_addr)
+{
+ struct pe_module_info_ctx ctx;
+
+ ctx.sym_addr = (uintptr_t)sym_addr;
+ ctx.image_ldr_tbl_entry = 0;
+
+ pe_enum_modules_in_load_order(
+ pe_get_symbol_module_info_callback,
+ &ctx);
+
+ return ctx.image_ldr_tbl_entry;
+}
diff --git a/src/meta/pe_get_symbol_name.c b/src/meta/pe_get_symbol_name.c
new file mode 100644
index 0000000..f9001ef
--- /dev/null
+++ b/src/meta/pe_get_symbol_name.c
@@ -0,0 +1,209 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+
+/* private args structure */
+struct pe_symbol_name_ctx {
+ const void * addr;
+ char * name;
+};
+
+/* private forward declarations */
+static int pe_enum_exports_callback(
+ const void * base,
+ struct pe_export_hdr * exp_hdr,
+ struct pe_export_sym * sym,
+ enum pe_callback_reason reason,
+ void * context);
+
+#if defined (__NT32)
+static char * pe_get_imported_symbol_info_32(
+ const void * sym_addr,
+ void ** sym_image_addr,
+ char ** sym_name,
+ struct pe_ldr_tbl_entry ** ldr_tbl_entry);
+#endif
+
+#if defined (__NT64)
+static char * pe_get_imported_symbol_info_64(
+ const void * sym_addr,
+ void ** sym_image_addr,
+ char ** sym_name,
+ struct pe_ldr_tbl_entry ** ldr_tbl_entry);
+;
+#endif
+
+pe_api
+char * pe_get_symbol_name(const void * base, const void * sym_addr)
+{
+ struct pe_export_sym exp_item;
+ struct pe_symbol_name_ctx ctx;
+
+ ctx.name = 0;
+ ctx.addr = sym_addr;
+
+ pe_enum_image_exports(
+ base,
+ pe_enum_exports_callback,
+ &exp_item,
+ &ctx);
+
+ return ctx.name;
+}
+
+
+pe_api
+char * pe_get_import_symbol_info(
+ const void * sym_addr,
+ void ** sym_image_addr,
+ char ** sym_name,
+ struct pe_ldr_tbl_entry ** ldr_tbl_entry)
+{
+ #if defined(__NT32)
+ return pe_get_imported_symbol_info_32(
+ sym_addr,
+ sym_image_addr,
+ sym_name,
+ ldr_tbl_entry);
+ #elif defined (__NT64)
+ return pe_get_imported_symbol_info_64(
+ sym_addr,
+ sym_image_addr,
+ sym_name,
+ ldr_tbl_entry);
+ #endif
+}
+
+static int pe_enum_exports_callback(
+ const void * base,
+ struct pe_export_hdr * exp_hdr,
+ struct pe_export_sym * sym,
+ enum pe_callback_reason reason,
+ void * context)
+{
+ struct pe_symbol_name_ctx * ctx;
+
+ if (reason != PE_CALLBACK_REASON_ITEM)
+ return 1;
+
+ ctx = (struct pe_symbol_name_ctx *)context;
+
+ if (sym->addr == ctx->addr) {
+ ctx->name = sym->name;
+ return 0;
+ } else
+ return 1;
+}
+
+
+#ifdef __NT32
+static char * pe_get_imported_symbol_info_32(
+ const void * sym_addr,
+ void ** sym_image_addr,
+ char ** sym_name,
+ struct pe_ldr_tbl_entry ** ldr_tbl_entry)
+{
+ struct symbol {
+ unsigned char call;
+ unsigned char ds;
+ unsigned char sym_addr[4];
+ unsigned char padding[2];
+ };
+
+ char * fn_name;
+ struct pe_ldr_tbl_entry * mod_info;
+ void * mod_base;
+ uint32_t *** sym_redirected_addr;
+ struct symbol * sym;
+
+ fn_name = 0;
+ mod_info = 0;
+ sym = (struct symbol *)sym_addr;
+
+ if ((sym->call == 0xff) && (sym->ds == 0x25)) {
+ sym_redirected_addr = (uint32_t ***)sym->sym_addr;
+
+ if (sym_redirected_addr)
+ mod_info = pe_get_symbol_module_info(**sym_redirected_addr);
+
+ if (mod_info)
+ mod_base = mod_info->dll_base;
+ else
+ mod_base = (void *)0;
+
+ if (mod_base)
+ fn_name = pe_get_symbol_name(
+ mod_base,
+ **sym_redirected_addr);
+ }
+
+ if (fn_name && ldr_tbl_entry)
+ *ldr_tbl_entry = mod_info;
+
+ return fn_name;
+}
+#endif
+
+
+#ifdef __NT64
+static char * pe_get_imported_symbol_info_64(
+ const void * sym_addr,
+ void ** sym_image_addr,
+ char ** sym_name,
+ struct pe_ldr_tbl_entry ** ldr_tbl_entry)
+{
+ struct symbol {
+ unsigned char call;
+ unsigned char ds;
+ unsigned char sym_addr[4];
+ unsigned char padding[2];
+ };
+
+ char * fn_name;
+ struct pe_ldr_tbl_entry * mod_info;
+ void * mod_base;
+ uint32_t * sym_offset;
+ uint32_t offset;
+ struct symbol * sym;
+
+ fn_name = 0;
+ mod_info = 0;
+ sym = (struct symbol *)sym_addr;
+
+ if ((sym->call == 0xff) && (sym->ds == 0x25)) {
+ sym_offset = (uint32_t *)sym->sym_addr;
+
+ if (sym_offset) {
+ offset = *sym_offset;
+ sym_addr = *(void **)(offset + (uintptr_t)(++sym_offset));
+ mod_info = pe_get_symbol_module_info(sym_addr);
+ }
+
+ if (mod_info)
+ mod_base = mod_info->dll_base;
+ else
+ mod_base = (void *)0;
+
+ if (mod_base)
+ fn_name = pe_get_symbol_name(mod_base,sym_addr);
+ }
+
+ if (fn_name) {
+ if (ldr_tbl_entry)
+ *ldr_tbl_entry = mod_info;
+
+ if (sym_image_addr)
+ *sym_image_addr = (void *)sym_addr;
+
+ if (sym_name)
+ *sym_name = fn_name;
+ }
+
+ return fn_name;
+}
+#endif
diff --git a/src/modules/pe_enum_modules.c b/src/modules/pe_enum_modules.c
new file mode 100644
index 0000000..c36b076
--- /dev/null
+++ b/src/modules/pe_enum_modules.c
@@ -0,0 +1,102 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+static int pe_enum_modules(
+ pe_enum_modules_callback * callback,
+ const uintptr_t in_order_member_offset,
+ void * context)
+{
+ int ret;
+ uintptr_t peb_tbl_addr;
+ struct pe_peb_ldr_data * peb_ldr_data;
+ struct pe_ldr_tbl_entry * ldr_tbl_entry;
+ struct pe_list_entry * plist_head;
+ struct pe_list_entry * plist_current;
+
+ peb_ldr_data = (struct pe_peb_ldr_data *)pe_get_peb_ldr_data_address();
+ plist_head = (struct pe_list_entry *)0;
+
+ if ((intptr_t)peb_ldr_data == 0) {
+ callback(
+ 0,
+ PE_CALLBACK_REASON_ERROR,
+ context);
+ return -1;
+ }
+
+ ret = callback(
+ 0,
+ PE_CALLBACK_REASON_INIT,
+ context);
+
+ if (ret <= 0)
+ return ret;
+
+ switch (in_order_member_offset) {
+ case IN_LOAD_ORDER_MODULE_LIST_OFFSET:
+ plist_head = peb_ldr_data->in_load_order_module_list.flink;
+ break;
+
+ case IN_MEMORY_ORDER_MODULE_LIST_OFFSET:
+ plist_head = peb_ldr_data->in_memory_order_module_list.flink;
+ break;
+
+ case IN_INITIALIZATION_ORDER_MODULE_LIST_OFFSET:
+ plist_head = peb_ldr_data->in_init_order_module_list.flink;
+ break;
+ }
+
+ plist_current = plist_head;
+
+ do
+ {
+ peb_tbl_addr = (uintptr_t)plist_current - in_order_member_offset;
+ ldr_tbl_entry = (struct pe_ldr_tbl_entry *)peb_tbl_addr;
+
+ ret = callback(
+ ldr_tbl_entry,
+ PE_CALLBACK_REASON_ITEM,
+ context);
+
+ if (ret <= 0)
+ return ret;
+ else
+ plist_current = plist_current->flink;
+
+ } while (plist_current != plist_head);
+
+ ret = callback(
+ ldr_tbl_entry,
+ PE_CALLBACK_REASON_DONE,
+ context);
+
+ return ret;
+}
+
+
+pe_api
+int pe_enum_modules_in_load_order(pe_enum_modules_callback * fn, void * ctx)
+{
+ return pe_enum_modules(fn,IN_LOAD_ORDER_MODULE_LIST_OFFSET,ctx);
+}
+
+pe_api
+int pe_enum_modules_in_memory_order(pe_enum_modules_callback * fn, void * ctx)
+{
+ return pe_enum_modules(fn,IN_MEMORY_ORDER_MODULE_LIST_OFFSET,ctx);
+}
+
+pe_api
+int pe_enum_modules_in_init_order(pe_enum_modules_callback * fn, void * ctx)
+{
+ return pe_enum_modules(fn,IN_INITIALIZATION_ORDER_MODULE_LIST_OFFSET,ctx);
+}
diff --git a/src/modules/pe_get_kernel32_module_handle.c b/src/modules/pe_get_kernel32_module_handle.c
new file mode 100644
index 0000000..9cd0c18
--- /dev/null
+++ b/src/modules/pe_get_kernel32_module_handle.c
@@ -0,0 +1,73 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+static int pe_get_kernel32_handle_callback(
+ struct pe_ldr_tbl_entry * ldr_tbl_entry,
+ enum pe_callback_reason reason,
+ void * context)
+{
+ #define KERNEL32_UTF16_STRLEN 24
+
+ int32_t kernel32_base_name_le[4];
+ char * kernel32_base_name_ansi;
+
+ intptr_t * addr;
+ char * ch;
+ size_t match;
+
+ /* avoid scan-based false positives */
+ kernel32_base_name_le[0] = 0x6E72656B; /* 'kern' */
+ kernel32_base_name_le[1] = 0x32336C65; /* 'el32' */
+ kernel32_base_name_le[2] = 0x6C6C642E; /* '.dll' */
+ kernel32_base_name_le[3] = 0;
+
+ kernel32_base_name_ansi = (char *)&kernel32_base_name_le;
+
+ match = 0;
+ addr = (intptr_t *)context;
+
+ if (reason == PE_CALLBACK_REASON_ITEM)
+ if (ldr_tbl_entry->base_dll_name.strlen == KERNEL32_UTF16_STRLEN) {
+ ch = (char *)ldr_tbl_entry->base_dll_name.buffer;
+ match = 0;
+
+ while ((match < sizeof(kernel32_base_name_ansi))
+ && ((*ch == kernel32_base_name_ansi[match])
+ || (*ch == (kernel32_base_name_ansi[match] + 'A' - 'a')))
+ && (*(ch + 1) == 0)) {
+ ch+=sizeof(uint16_t);
+ match++;
+ }
+ }
+
+ if (match == sizeof(kernel32_base_name_ansi)) {
+ *addr = (intptr_t)ldr_tbl_entry->dll_base;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+
+pe_api
+void * pe_get_kernel32_module_handle(void)
+{
+
+ intptr_t kernel32_base_addr = 0;
+ void * ptr_to_callback = &kernel32_base_addr;
+
+ pe_enum_modules_in_init_order(
+ &pe_get_kernel32_handle_callback,
+ ptr_to_callback);
+
+ return (void *)kernel32_base_addr;
+}
diff --git a/src/modules/pe_get_module_handle.c b/src/modules/pe_get_module_handle.c
new file mode 100644
index 0000000..7677ba0
--- /dev/null
+++ b/src/modules/pe_get_module_handle.c
@@ -0,0 +1,80 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+pe_api
+void * pe_get_first_module_handle(void)
+{
+ struct pe_peb_ldr_data * peb_ldr_data;
+ struct pe_list_entry * peb_list_entry;
+ intptr_t peb_tbl_addr;
+ struct pe_ldr_tbl_entry * peb_ldr_tbl_entry;
+
+ peb_ldr_data = (struct pe_peb_ldr_data *)pe_get_peb_ldr_data_address();
+ peb_list_entry = (struct pe_list_entry *)peb_ldr_data->in_load_order_module_list.flink;
+ peb_tbl_addr = (intptr_t)peb_list_entry - IN_LOAD_ORDER_MODULE_LIST_OFFSET;
+ peb_ldr_tbl_entry = (struct pe_ldr_tbl_entry *)peb_tbl_addr;
+
+ return peb_ldr_tbl_entry->dll_base;
+}
+
+pe_api
+void * pe_get_module_handle(const wchar16_t * name)
+{
+ wchar16_t * src;
+ wchar16_t * dst;
+
+ size_t match;
+ size_t len;
+
+ struct pe_peb_ldr_data * peb_ldr_data;
+ struct pe_list_entry * plist_head;
+
+ struct pe_list_entry * plist_current;
+ struct pe_ldr_tbl_entry * ldr_tbl_entry = 0;
+
+ peb_ldr_data = (struct pe_peb_ldr_data *)pe_get_peb_ldr_data_address();
+ plist_head = (struct pe_list_entry *)peb_ldr_data->in_load_order_module_list.flink;
+ plist_current = plist_head;
+
+ len = pe_impl_strlen_utf16(name);
+
+ do {
+ ldr_tbl_entry = (struct pe_ldr_tbl_entry *)plist_current - IN_LOAD_ORDER_MODULE_LIST_OFFSET;
+
+ if (ldr_tbl_entry->base_dll_name.strlen == len)
+ dst = (wchar16_t *)ldr_tbl_entry->base_dll_name.buffer;
+ else if (ldr_tbl_entry->full_dll_name.strlen == len)
+ dst = (wchar16_t *)ldr_tbl_entry->full_dll_name.buffer;
+ else
+ dst = (wchar16_t *)0;
+
+ if ((intptr_t)(dst)) {
+ src = (wchar16_t *)name;
+ match = 0;
+
+ while ((match < len)
+ && ((pe_impl_utf16_char_to_lower(*src)) == (pe_impl_utf16_char_to_lower(*dst)))) {
+ src = (wchar16_t *)pe_va_from_rva(src,sizeof(wchar16_t));
+ dst = (wchar16_t *)pe_va_from_rva(dst,sizeof(wchar16_t));
+ match+=sizeof(wchar16_t);
+ }
+
+ if (match == len)
+ return ldr_tbl_entry->dll_base;
+ }
+
+ plist_current = plist_current->flink;
+ } while (plist_current != plist_head);
+
+ /* address not found */
+ return 0;
+}
diff --git a/src/modules/pe_get_ntdll_module_handle.c b/src/modules/pe_get_ntdll_module_handle.c
new file mode 100644
index 0000000..72f81ec
--- /dev/null
+++ b/src/modules/pe_get_ntdll_module_handle.c
@@ -0,0 +1,27 @@
+/*****************************************************************************/
+/* pemagination: a (virtual) tour into portable bits and executable bytes */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.PEMAGINE. */
+/*****************************************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pe_consts.h>
+#include <pemagine/pe_structs.h>
+#include <pemagine/pemagine.h>
+#include "pe_impl.h"
+
+pe_api
+void * pe_get_ntdll_module_handle(void)
+{
+ struct pe_peb_ldr_data * peb_ldr_data;
+ struct pe_list_entry * peb_list_entry;
+ intptr_t peb_tbl_addr;
+ struct pe_ldr_tbl_entry * peb_ldr_tbl_entry;
+
+ peb_ldr_data = (struct pe_peb_ldr_data *)pe_get_peb_ldr_data_address();
+ peb_list_entry = peb_ldr_data->in_init_order_module_list.flink;
+ peb_tbl_addr = (intptr_t)peb_list_entry - IN_INITIALIZATION_ORDER_MODULE_LIST_OFFSET;
+ peb_ldr_tbl_entry = (struct pe_ldr_tbl_entry *)peb_tbl_addr;
+
+ return peb_ldr_tbl_entry->dll_base;
+}