├── .gitignore ├── pe-load-con ├── inc │ └── core.h ├── pe-load-con.vcxproj ├── pe-load-con.vcxproj.filters └── src │ └── core.cpp ├── pe-loadder.sln ├── pe-loader ├── inc │ ├── pe_common.h │ └── pe_loader.h ├── pe-loader.vcxproj ├── pe-loader.vcxproj.filters └── src │ └── pe_loader.cpp ├── readme.txt └── testing-dll ├── inc └── core.h ├── src └── core.cpp ├── testing-dll.def ├── testing-dll.vcxproj └── testing-dll.vcxproj.filters /.gitignore: -------------------------------------------------------------------------------- 1 | [Tt]humbs.db 2 | *.*sdf 3 | *.ipch 4 | *.obj 5 | *.exe 6 | *.dll 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *_i.c 12 | *_p.c 13 | *.ncb 14 | *.suo 15 | *.tlb 16 | *.tlh 17 | *.bak 18 | *.cache 19 | *.ilk 20 | *.log 21 | *.sbr 22 | *.scc 23 | pdb/ 24 | [Bb]in 25 | [Db]ebug*/ 26 | obj/ 27 | [Rr]elease*/ 28 | _ReSharper*/ 29 | [Tt]est[Rr]esult* 30 | [Bb]uild[Ll]og.* 31 | *.[Pp]ublish.xml 32 | [Tt]est 33 | libs -------------------------------------------------------------------------------- /pe-load-con/inc/core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "pe_loader.h" 5 | 6 | typedef __declspec(dllimport) BOOL (CALLBACK *beep_func_t)( DWORD msg ); -------------------------------------------------------------------------------- /pe-load-con/pe-load-con.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {AE03790D-C643-4DE6-ACD7-B1B6E5664E26} 15 | Win32Proj 16 | peloadcon 17 | 18 | 19 | 20 | Application 21 | true 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | true 28 | MultiByte 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 53 | inc;$(SolutionDir)pe-loader\inc;%(AdditionalIncludeDirectories) 54 | 55 | 56 | Console 57 | true 58 | 59 | 60 | 61 | 62 | Level3 63 | 64 | 65 | MaxSpeed 66 | true 67 | true 68 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 69 | inc;%(AdditionalIncludeDirectories) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | {f6cafbfb-2ac2-4241-938a-ef2001a19b36} 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /pe-load-con/pe-load-con.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | 23 | 24 | Source Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /pe-load-con/src/core.cpp: -------------------------------------------------------------------------------- 1 | #include "core.h" 2 | 3 | namespace { 4 | pe::loader_t dll; 5 | beep_func_t beep; 6 | }; 7 | 8 | int main( int argc, char *argv[], char *envp[] ){ 9 | 10 | dll.open( "testing-dll.dll" ); 11 | dll.load(); 12 | 13 | beep = (beep_func_t)dll.proc_address( "test_beep" ); 14 | if( beep ){ 15 | beep( MB_HELP ); 16 | }; 17 | 18 | dll.close(); 19 | 20 | return 0; 21 | }; 22 | -------------------------------------------------------------------------------- /pe-loadder.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6A5AE4F3-A7C1-4253-A5A7-786C82D11089}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{E1CDAE82-D33C-42C9-AF4A-D6E397399F20}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pe-loader", "pe-loader\pe-loader.vcxproj", "{F6CAFBFB-2AC2-4241-938A-EF2001A19B36}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pe-load-con", "pe-load-con\pe-load-con.vcxproj", "{AE03790D-C643-4DE6-ACD7-B1B6E5664E26}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testing-dll", "testing-dll\testing-dll.vcxproj", "{02AD654D-14A5-4589-817F-C131D6889CFB}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Win32 = Debug|Win32 17 | Release|Win32 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {F6CAFBFB-2AC2-4241-938A-EF2001A19B36}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {F6CAFBFB-2AC2-4241-938A-EF2001A19B36}.Debug|Win32.Build.0 = Debug|Win32 22 | {F6CAFBFB-2AC2-4241-938A-EF2001A19B36}.Release|Win32.ActiveCfg = Release|Win32 23 | {F6CAFBFB-2AC2-4241-938A-EF2001A19B36}.Release|Win32.Build.0 = Release|Win32 24 | {AE03790D-C643-4DE6-ACD7-B1B6E5664E26}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {AE03790D-C643-4DE6-ACD7-B1B6E5664E26}.Debug|Win32.Build.0 = Debug|Win32 26 | {AE03790D-C643-4DE6-ACD7-B1B6E5664E26}.Release|Win32.ActiveCfg = Release|Win32 27 | {AE03790D-C643-4DE6-ACD7-B1B6E5664E26}.Release|Win32.Build.0 = Release|Win32 28 | {02AD654D-14A5-4589-817F-C131D6889CFB}.Debug|Win32.ActiveCfg = Debug|Win32 29 | {02AD654D-14A5-4589-817F-C131D6889CFB}.Debug|Win32.Build.0 = Debug|Win32 30 | {02AD654D-14A5-4589-817F-C131D6889CFB}.Release|Win32.ActiveCfg = Release|Win32 31 | {02AD654D-14A5-4589-817F-C131D6889CFB}.Release|Win32.Build.0 = Release|Win32 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | GlobalSection(NestedProjects) = preSolution 37 | {AE03790D-C643-4DE6-ACD7-B1B6E5664E26} = {6A5AE4F3-A7C1-4253-A5A7-786C82D11089} 38 | {02AD654D-14A5-4589-817F-C131D6889CFB} = {6A5AE4F3-A7C1-4253-A5A7-786C82D11089} 39 | {F6CAFBFB-2AC2-4241-938A-EF2001A19B36} = {E1CDAE82-D33C-42C9-AF4A-D6E397399F20} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /pe-loader/inc/pe_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | typedef __int8 int8_t; 14 | typedef __int16 int16_t; 15 | typedef __int32 int32_t; 16 | typedef __int64 int64_t; 17 | 18 | typedef unsigned __int8 uint8_t; 19 | typedef unsigned __int16 uint16_t; 20 | typedef unsigned __int32 uint32_t; 21 | typedef unsigned __int64 uint64_t; 22 | 23 | #pragma pack( push, 1 ) 24 | namespace pe { 25 | static const uint16_t g_dos_magic = 0x5A4D; // "MZ" 26 | static const uint32_t g_pe_magic = 0x00004550; // "PE" 27 | static const uint16_t g_opt_exe32 = 0x010B; // Win32 EXE 28 | static const uint16_t g_opt_exe64 = 0x020B; // Win64 EXE 29 | static const uint16_t g_opt_rom = 0x0107; // ROM Image 30 | static const uint32_t g_data_dir_count = 16; 31 | static const uint32_t g_sect_hdr_name_size = 8; 32 | 33 | enum loader_state_t { 34 | ls_error = -1, 35 | ls_none = 0, 36 | ls_ready, 37 | ls_opened, 38 | ls_closed, 39 | ls_loaded, 40 | ls_unloaded, 41 | }; 42 | 43 | enum data_dir_index_t { 44 | ide_export = 0, 45 | ide_import, 46 | ide_resource, 47 | ide_exception, 48 | ide_seqrity, 49 | ide_base_reloc, 50 | ide_debug, 51 | ide_architecture, 52 | ide_global_ptr, 53 | ide_tls, 54 | ide_load_config, 55 | ide_bound_import, 56 | ide_iat, 57 | ide_delay_import, 58 | ide_com_descriptor, 59 | }; 60 | 61 | struct dos_hdr_t { 62 | uint16_t m_magic; 63 | uint16_t m_cblp; 64 | uint16_t m_pages_count; 65 | uint16_t m_relocations; 66 | uint16_t m_cparhdr; 67 | 68 | struct alloc_t { 69 | uint16_t m_min; 70 | uint16_t m_max; 71 | } m_alloc; 72 | 73 | struct registers_t { 74 | uint16_t m_ss; 75 | uint16_t m_sp; 76 | uint16_t m_checksum; 77 | uint16_t m_ip; 78 | uint16_t m_cs; 79 | } m_reg; 80 | 81 | uint16_t m_reloc_offset; 82 | uint16_t m_overlay_num; 83 | uint16_t m_reserved_01[4]; 84 | 85 | struct oem_t { 86 | uint16_t m_id; 87 | uint16_t m_info; 88 | } m_oem; 89 | 90 | uint16_t m_reserved_02[10]; 91 | uint32_t m_offset_next; 92 | 93 | inline const bool is_valid() const { return ( g_dos_magic == m_magic ) && m_offset_next; }; 94 | }; 95 | 96 | struct data_dir_t { 97 | uint32_t m_offset; 98 | uint32_t m_size; 99 | }; 100 | 101 | struct nt_header_t { 102 | uint32_t m_magic; 103 | 104 | struct file_hdr_t { 105 | uint16_t m_machine; 106 | uint16_t m_sections_count; 107 | uint32_t m_timedate_stamp; 108 | uint32_t m_symbols_offset; 109 | uint32_t m_symbols_count; 110 | uint16_t m_opt_hdr_size; 111 | uint16_t m_characteristics; 112 | } m_file_hdr; 113 | 114 | struct optional_hdr_t { 115 | uint16_t m_magic; 116 | 117 | struct linker_version_t { 118 | uint8_t m_major; 119 | uint8_t m_minor; 120 | } m_linker_version; 121 | 122 | struct sizes_t { 123 | uint32_t m_code; 124 | uint32_t m_inited_data; 125 | uint32_t m_uninited_data; 126 | } m_size; 127 | 128 | uint32_t m_entry_point; 129 | 130 | struct bases_t { 131 | uint32_t m_code; 132 | uint32_t m_data; 133 | uint32_t m_image; 134 | } m_base; 135 | 136 | struct alignments_t { 137 | uint32_t m_section; 138 | uint32_t m_file; 139 | } m_alignment; 140 | 141 | struct versions_t { 142 | uint16_t m_os_major; 143 | uint16_t m_os_minor; 144 | uint16_t m_img_major; 145 | uint16_t m_img_minor; 146 | uint16_t m_subsystem_major; 147 | uint16_t m_subsystem_minor; 148 | uint32_t m_win32; 149 | } m_version; 150 | 151 | uint32_t m_image_size; 152 | uint32_t m_headers_size; 153 | uint32_t m_checksum; 154 | uint16_t m_subsystem; 155 | uint16_t m_dll_flags; 156 | 157 | uint32_t m_stack_reserve_size; 158 | uint32_t m_stack_commit_size; 159 | uint32_t m_heap_reserve_size; 160 | uint32_t m_heap_commit_size; 161 | 162 | uint32_t m_loader_flags; 163 | uint32_t m_rva_count; 164 | 165 | data_dir_t m_data_directory[ g_data_dir_count ]; 166 | } m_optional_hdr; 167 | 168 | const bool is_valid() const { return ( g_pe_magic == m_magic ) && ( g_opt_exe32 == m_optional_hdr.m_magic ); }; 169 | }; 170 | 171 | struct entry_t { 172 | void* m_address; 173 | int32_t m_ordinal; 174 | string m_name; 175 | string m_module; 176 | }; 177 | 178 | union sect_hdr_flags_t { 179 | uint32_t m_bits; 180 | struct { 181 | uint32_t m_index_scaled : 1; // [0x00000001] 182 | uint32_t m_r00000002 : 1; // [0x00000002] 183 | uint32_t m_r00000004 : 1; // [0x00000004] 184 | uint32_t m_r00000008 : 1; // [0x00000008] 185 | uint32_t m_r00000010 : 1; // [0x00000010] 186 | uint32_t m_has_code : 1; // [0x00000020] 187 | uint32_t m_has_init_data : 1; // [0x00000040] 188 | uint32_t m_has_uninit_data : 1; // [0x00000080] 189 | 190 | uint32_t m_link_other : 1; // [0x00000100] 191 | uint32_t m_link_info : 1; // [0x00000200] 192 | uint32_t m_type_over : 1; // [0x00000400] 193 | uint32_t m_link_remove : 1; // [0x00000800] 194 | uint32_t m_link_comdat : 1; // [0x00001000] 195 | uint32_t m_r00002000 : 1; // [0x00002000] 196 | uint32_t m_reset_spec_exc : 1; // [0x00004000] 197 | uint32_t m_mem_far_data : 1; // [0x00008000] 198 | 199 | uint32_t m_mem_sys_heap : 1; // [0x00010000] 200 | uint32_t m_mem_16bit : 1; // [0x00020000] 201 | uint32_t m_mem_locked : 1; // [0x00040000] 202 | uint32_t m_mem_preload : 1; // [0x00080000] 203 | uint32_t m_mem_align_1b : 1; // [0x00100000] 204 | uint32_t m_mem_align_2b : 1; // [0x00200000] 205 | uint32_t m_mem_align_8b : 1; // [0x00400000] 206 | uint32_t m_mem_align_128b : 1; // [0x00800000] 207 | 208 | uint32_t m_link_ext_reloc : 1; // [0x01000000] 209 | uint32_t m_mem_discardable : 1; // [0x02000000] 210 | uint32_t m_mem_not_cached : 1; // [0x04000000] 211 | uint32_t m_mem_not_paged : 1; // [0x08000000] 212 | uint32_t m_mem_shared : 1; // [0x10000000] 213 | uint32_t m_mem_execute : 1; // [0x20000000] 214 | uint32_t m_mem_read : 1; // [0x40000000] 215 | uint32_t m_mem_write : 1; // [0x80000000] 216 | }; 217 | 218 | inline const bool mem_align_4b() const { return m_mem_align_1b && m_mem_align_2b; }; 219 | inline const bool mem_align_16b() const { return m_mem_align_1b && m_mem_align_8b; }; 220 | inline const bool mem_align_32b() const { return m_mem_align_2b && m_mem_align_8b; }; 221 | inline const bool mem_align_64b() const { return m_mem_align_1b && m_mem_align_2b && m_mem_align_8b; }; 222 | inline const bool mem_align_256b() const { return m_mem_align_1b && m_mem_align_128b; }; 223 | inline const bool mem_align_512b() const { return m_mem_align_2b && m_mem_align_128b; }; 224 | inline const bool mem_align_1024b() const { return m_mem_align_1b && m_mem_align_2b && m_mem_align_128b; }; 225 | inline const bool mem_align_2048b() const { return m_mem_align_8b && m_mem_align_128b; }; 226 | inline const bool mem_align_4096b() const { return m_mem_align_1b && m_mem_align_8b && m_mem_align_128b; }; 227 | inline const bool mem_align_8192b() const { return m_mem_align_1b && m_mem_align_2b && m_mem_align_8b && m_mem_align_128b; }; 228 | }; 229 | 230 | struct section_header_t { 231 | uint8_t m_name[ g_sect_hdr_name_size ]; 232 | 233 | union { 234 | uint32_t m_phys_address; 235 | uint32_t m_virtual_size; 236 | }; 237 | 238 | uint32_t m_virtual_address; 239 | uint32_t m_raw_data_size; 240 | uint32_t m_raw_data_offset; 241 | uint32_t m_reloc_offset; 242 | uint32_t m_linenum_offset; 243 | uint16_t m_reloc_count; 244 | uint16_t m_linenum_count; 245 | sect_hdr_flags_t m_flags; 246 | }; 247 | 248 | struct reloc_desc_t { 249 | uint32_t m_offset; 250 | uint32_t m_size; 251 | }; 252 | 253 | struct import_desc_t { 254 | uint32_t m_first_thunk_orig; 255 | uint32_t m_timestamp; 256 | uint32_t m_forward_chain; 257 | uint32_t m_name_offset; 258 | uint32_t m_first_thunk; 259 | }; 260 | 261 | struct export_desc_t { 262 | uint32_t m_flags; 263 | uint32_t m_timestamp; 264 | uint16_t m_major_version; 265 | uint16_t m_minor_version; 266 | uint32_t m_name_offset; 267 | uint32_t m_ordinal_base; 268 | uint32_t m_func_count; 269 | uint32_t m_names_count; 270 | uint32_t m_func_offset; 271 | uint32_t m_names_offset; 272 | uint32_t m_ordinals_offset; 273 | }; 274 | 275 | struct import_name_desc_t { 276 | uint16_t m_hint; 277 | uint8_t m_name[1]; 278 | }; 279 | 280 | static const uint32_t g_reloc_desc_size = sizeof( reloc_desc_t ); 281 | 282 | typedef BOOL (WINAPI *dll_main_t)( HINSTANCE dll_inst, DWORD call_reason, LPVOID tag ); 283 | }; 284 | #pragma pack( pop ) -------------------------------------------------------------------------------- /pe-loader/inc/pe_loader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pe_common.h" 4 | 5 | namespace pe { 6 | struct section_desc_t { 7 | section_header_t* m_header; 8 | uint8_t* m_base; 9 | uint32_t m_size; 10 | }; 11 | 12 | struct import_lib_t { 13 | import_desc_t* m_desc; 14 | string m_name; 15 | HMODULE m_handle; 16 | }; 17 | 18 | class loader_t { 19 | private: 20 | typedef vector sections_t; 21 | typedef vector exports_t; 22 | typedef map imports_t; 23 | 24 | loader_state_t m_state; 25 | HMODULE m_inst; 26 | uint8_t* m_image_base; 27 | size_t m_image_size; 28 | uint8_t* m_section_base; 29 | size_t m_section_size; 30 | 31 | HANDLE m_file; 32 | HANDLE m_map; 33 | uint8_t* m_view; 34 | 35 | sections_t m_sections; 36 | exports_t m_exports; 37 | imports_t m_imports; 38 | string m_path; 39 | 40 | const bool alloc_sections(); 41 | const bool relink_sections(); 42 | const bool protect_sections(); 43 | 44 | const bool process_imports(); 45 | const bool import_used( const string& name ); 46 | const bool add_import( const string& name, import_desc_t* desc ); 47 | const bool is_import_ordinal( const uint32_t& func_ptr, HMODULE lib_handle ); 48 | const bool process_exports(); 49 | 50 | const DWORD section_permitions( const sect_hdr_flags_t& sf ); 51 | 52 | void close_view(); 53 | 54 | public: 55 | loader_t(); 56 | ~loader_t(); 57 | 58 | const bool open( const string& path, const bool open_and_load = false ); 59 | const bool load(); 60 | const bool unload(); 61 | const bool close(); 62 | 63 | HMODULE handle() const { return m_inst; }; 64 | HINSTANCE instance() const { return (HINSTANCE&)m_inst; }; 65 | loader_state_t state() const { return m_state; }; 66 | void* proc_address( const string& name ) const; 67 | void* proc_address( const int32_t ordinal ) const; 68 | }; 69 | }; 70 | -------------------------------------------------------------------------------- /pe-loader/pe-loader.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {F6CAFBFB-2AC2-4241-938A-EF2001A19B36} 22 | Win32Proj 23 | peloader 24 | 25 | 26 | 27 | StaticLibrary 28 | true 29 | MultiByte 30 | 31 | 32 | StaticLibrary 33 | false 34 | true 35 | MultiByte 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 55 | inc;%(AdditionalIncludeDirectories) 56 | 57 | 58 | Windows 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 71 | inc;%(AdditionalIncludeDirectories) 72 | 73 | 74 | Windows 75 | true 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /pe-loader/pe-loader.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /pe-loader/src/pe_loader.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_loader.h" 2 | 3 | namespace pe { 4 | uint32_t g_os_page_size = 0; 5 | 6 | loader_t::loader_t() : m_state(ls_none), m_inst(NULL), m_image_base(NULL), m_image_size(0), m_file(INVALID_HANDLE_VALUE), m_map(INVALID_HANDLE_VALUE), m_view(NULL) { 7 | if( !g_os_page_size ){ 8 | SYSTEM_INFO si; 9 | 10 | GetSystemInfo( &si ); 11 | g_os_page_size = si.dwAllocationGranularity; 12 | }; 13 | }; 14 | 15 | loader_t::~loader_t(){ 16 | close(); 17 | m_state = ls_error; 18 | }; 19 | 20 | void* loader_t::proc_address( const string& name ) const { 21 | if( !( ( ls_ready == m_state ) && m_exports.size() ) ){ 22 | return NULL; 23 | }; 24 | 25 | void* result = NULL; 26 | 27 | for( exports_t::const_iterator fd = m_exports.begin(); ( m_exports.end() != fd ) && !result; fd++ ){ 28 | if( name == fd->m_name ){ 29 | result = fd->m_address; 30 | }; 31 | }; 32 | 33 | return result; 34 | }; 35 | 36 | void* loader_t::proc_address( const int32_t ordinal ) const { 37 | if( !( ( ls_ready == m_state ) && m_exports.size() ) ){ 38 | return NULL; 39 | }; 40 | 41 | void* result = NULL; 42 | 43 | for( exports_t::const_iterator fd = m_exports.begin(); ( m_exports.end() != fd ) && !result; fd++ ){ 44 | if( ordinal == fd->m_ordinal ){ 45 | result = fd->m_address; 46 | }; 47 | }; 48 | 49 | return result; 50 | }; 51 | 52 | const bool loader_t::open( const string& path, const bool open_and_load ){ 53 | close(); 54 | 55 | if( ls_closed != m_state ){ 56 | return false; 57 | }; 58 | 59 | m_state = ls_none; 60 | m_path = path; 61 | 62 | m_file = CreateFile( m_path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL ); 63 | if( !m_file || INVALID_HANDLE_VALUE == m_file ){ 64 | m_state = ls_error; 65 | return false; 66 | }; 67 | 68 | m_map = CreateFileMapping( m_file, NULL, PAGE_READONLY, 0, 0, NULL ); 69 | if( !m_map || INVALID_HANDLE_VALUE == m_map ){ 70 | close(); 71 | m_state = ls_error; 72 | return false; 73 | }; 74 | 75 | m_view = (uint8_t*)MapViewOfFile( m_map, SECTION_MAP_READ, 0, 0, 0 ); 76 | if( !m_view ){ 77 | close(); 78 | m_state = ls_error; 79 | return false; 80 | }; 81 | 82 | m_state = ls_opened; 83 | return ( open_and_load )? load() : true; 84 | }; 85 | 86 | const bool loader_t::load(){ 87 | if( ls_opened != m_state ){ 88 | return false; 89 | }; 90 | 91 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_view; 92 | if( !dos_hdr.is_valid() ){ 93 | close(); 94 | m_state = ls_error; 95 | return false; 96 | }; 97 | 98 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_view + dos_hdr.m_offset_next ); 99 | if( !nt_hdr.is_valid() ){ 100 | close(); 101 | m_state = ls_error; 102 | return false; 103 | }; 104 | 105 | m_image_size = nt_hdr.m_optional_hdr.m_image_size; 106 | m_image_base = (uint8_t*)VirtualAlloc( NULL, m_image_size, MEM_RESERVE, PAGE_NOACCESS ); 107 | if( !m_image_base ){ 108 | close(); 109 | m_state = ls_error; 110 | return false; 111 | }; 112 | 113 | m_section_size = nt_hdr.m_optional_hdr.m_headers_size; 114 | m_section_base = (uint8_t*)VirtualAlloc( m_image_base, m_section_size, MEM_COMMIT, PAGE_READWRITE ); 115 | if( !m_section_base ){ 116 | close(); 117 | m_state = ls_error; 118 | return false; 119 | }; 120 | 121 | memcpy( m_section_base, m_view, m_section_size ); 122 | 123 | { 124 | DWORD tmp; 125 | VirtualProtect( m_section_base, m_section_size, PAGE_READONLY, &tmp ); 126 | }; 127 | 128 | if( !alloc_sections() ){ 129 | return false; 130 | }; 131 | 132 | if( !relink_sections() ){ 133 | return false; 134 | }; 135 | 136 | if( !process_imports() ){ 137 | return false; 138 | }; 139 | 140 | if( !protect_sections() ){ 141 | return false; 142 | }; 143 | 144 | m_state = ls_loaded; 145 | 146 | m_inst = (HMODULE&)m_image_base; 147 | if( nt_hdr.m_optional_hdr.m_entry_point ){ 148 | dll_main_t main_func = (dll_main_t)( m_image_base + nt_hdr.m_optional_hdr.m_entry_point ); 149 | if( !main_func( m_inst, DLL_PROCESS_ATTACH, NULL ) ){ 150 | close(); 151 | m_state = ls_error; 152 | return false; 153 | }; 154 | }; 155 | 156 | if( !process_exports() ){ 157 | return false; 158 | }; 159 | 160 | close_view(); 161 | m_state = ls_ready; 162 | return true; 163 | }; 164 | 165 | const bool loader_t::unload(){ 166 | if( !m_image_base ){ 167 | return true; 168 | }; 169 | 170 | if( ls_ready == m_state ){ 171 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_image_base; 172 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_image_base + dos_hdr.m_offset_next ); 173 | 174 | if( nt_hdr.m_optional_hdr.m_entry_point ){ 175 | dll_main_t main_func = (dll_main_t)( m_image_base + nt_hdr.m_optional_hdr.m_entry_point ); 176 | 177 | main_func( m_inst, DLL_PROCESS_DETACH, 0 ); 178 | }; 179 | }; 180 | 181 | for( imports_t::iterator fd = m_imports.begin(); m_imports.end() != fd; fd++ ){ 182 | FreeLibrary( fd->second.m_handle ); 183 | }; 184 | 185 | m_exports.clear(); 186 | m_imports.clear(); 187 | m_sections.clear(); 188 | 189 | VirtualFree( m_image_base, 0, MEM_RELEASE ); 190 | m_image_base = NULL; 191 | m_image_size = 0; 192 | m_section_base = NULL; 193 | m_section_size = 0; 194 | m_inst = NULL; 195 | 196 | m_state = ls_unloaded; 197 | return true; 198 | }; 199 | 200 | const bool loader_t::close(){ 201 | unload(); 202 | close_view(); 203 | 204 | m_state = ls_closed; 205 | return true; 206 | }; 207 | 208 | void loader_t::close_view(){ 209 | if( m_view && m_map && ( INVALID_HANDLE_VALUE != m_map ) ){ 210 | UnmapViewOfFile( m_view ); 211 | }; 212 | 213 | if( m_map && ( INVALID_HANDLE_VALUE != m_map ) ){ 214 | CloseHandle( m_map ); 215 | }; 216 | 217 | if( m_file && ( INVALID_HANDLE_VALUE != m_file ) ){ 218 | CloseHandle( m_file ); 219 | }; 220 | 221 | m_view = NULL; 222 | m_map = INVALID_HANDLE_VALUE; 223 | m_file = INVALID_HANDLE_VALUE; 224 | m_path = ""; 225 | }; 226 | 227 | const bool loader_t::alloc_sections(){ 228 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_image_base; 229 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_image_base + dos_hdr.m_offset_next ); 230 | 231 | section_header_t* section = (section_header_t*)( (uint8_t*)&nt_hdr.m_optional_hdr + nt_hdr.m_file_hdr.m_opt_hdr_size ); 232 | m_sections.resize( nt_hdr.m_file_hdr.m_sections_count ); 233 | for( int32_t sd = 0; nt_hdr.m_file_hdr.m_sections_count > sd; sd++ ){ 234 | section_desc_t& desc = m_sections[ sd ]; 235 | 236 | desc.m_header = section; 237 | desc.m_size = section->m_virtual_size; 238 | desc.m_base = (uint8_t*)VirtualAlloc( m_image_base + section->m_virtual_address, desc.m_size, MEM_COMMIT, PAGE_READWRITE ); 239 | 240 | if( !desc.m_base ){ 241 | close(); 242 | m_state = ls_error; 243 | return false; 244 | }; 245 | 246 | memset( desc.m_base, 0, desc.m_size ); 247 | if( section->m_raw_data_offset && section->m_raw_data_size ){ 248 | memcpy( desc.m_base, m_view + section->m_raw_data_offset, min( desc.m_size, section->m_raw_data_size ) ); 249 | }; 250 | 251 | section++; 252 | }; 253 | 254 | return true; 255 | }; 256 | 257 | const bool loader_t::relink_sections(){ 258 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_image_base; 259 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_image_base + dos_hdr.m_offset_next ); 260 | 261 | if( !nt_hdr.m_optional_hdr.m_data_directory[ ide_base_reloc ].m_offset ){ 262 | return true; 263 | }; 264 | 265 | const uint32_t& reloc_size = nt_hdr.m_optional_hdr.m_data_directory[ ide_base_reloc ].m_size; 266 | const int32_t reloc_offset = (int32_t)( m_image_base - nt_hdr.m_optional_hdr.m_base.m_image ); 267 | reloc_desc_t* reloc_desc = (reloc_desc_t*)( m_image_base + nt_hdr.m_optional_hdr.m_data_directory[ ide_base_reloc ].m_offset ); 268 | const reloc_desc_t* reloc_base = reloc_desc; 269 | 270 | while( reloc_size > (uint32_t)( (uint8_t*)reloc_desc - (uint8_t*)reloc_base ) ){ 271 | uint32_t lnk_count = ( reloc_desc->m_size - g_reloc_desc_size ) / 2; 272 | uint16_t* lnk = (uint16_t*)( (uint8_t*)reloc_desc + g_reloc_desc_size ); 273 | uint8_t* lnk_base = m_image_base + reloc_desc->m_offset; 274 | 275 | while( lnk_count-- ){ 276 | if( 0xF000 & *lnk ){ 277 | *(uint32_t*)( lnk_base + ( 0x0FFF & *lnk ) ) += reloc_offset; 278 | }; 279 | 280 | lnk++; 281 | }; 282 | 283 | reloc_desc = (reloc_desc_t*)lnk; 284 | }; 285 | 286 | return true; 287 | }; 288 | 289 | const DWORD loader_t::section_permitions( const sect_hdr_flags_t& sf ){ 290 | DWORD result = 0; 291 | 292 | if( sf.m_mem_execute ){ 293 | if( sf.m_mem_read ){ 294 | result = ( sf.m_mem_write )? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; 295 | }else{ 296 | result = ( sf.m_mem_write )? PAGE_EXECUTE_WRITECOPY : PAGE_EXECUTE; 297 | }; 298 | }else{ 299 | if( sf.m_mem_read ){ 300 | result = ( sf.m_mem_write )? PAGE_READWRITE : PAGE_READONLY; 301 | }else{ 302 | result = ( sf.m_mem_write )? PAGE_WRITECOPY : PAGE_NOACCESS; 303 | }; 304 | }; 305 | 306 | return result | ( ( sf.m_mem_not_cached )? PAGE_NOCACHE : 0 ); 307 | }; 308 | 309 | const bool loader_t::protect_sections(){ 310 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_image_base; 311 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_image_base + dos_hdr.m_offset_next ); 312 | DWORD tmp = 0; 313 | 314 | for( sections_t::iterator fd = m_sections.begin(); m_sections.end() != fd; fd++ ){ 315 | if( !VirtualProtect( fd->m_base, fd->m_size, section_permitions( fd->m_header->m_flags ), &tmp ) ){ 316 | close(); 317 | m_state = ls_error; 318 | return false; 319 | }; 320 | }; 321 | 322 | return true; 323 | }; 324 | 325 | const bool loader_t::import_used( const string& name ){ 326 | imports_t::iterator fd = m_imports.find( name ); 327 | return m_imports.end() != fd; 328 | }; 329 | 330 | const bool loader_t::add_import( const string& name, import_desc_t* desc ){ 331 | import_lib_t lib; 332 | 333 | lib.m_desc = desc; 334 | lib.m_name = name; 335 | lib.m_handle = LoadLibrary( name.c_str() ); 336 | 337 | if( !lib.m_handle ){ 338 | return false; 339 | }; 340 | 341 | m_imports[ name ] = lib; 342 | 343 | return true; 344 | }; 345 | 346 | const bool loader_t::is_import_ordinal( const uint32_t& func_ptr, HMODULE lib_handle ){ 347 | return 0 != ( 0x80000000U & func_ptr ); 348 | }; 349 | 350 | const bool loader_t::process_imports(){ 351 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_image_base; 352 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_image_base + dos_hdr.m_offset_next ); 353 | 354 | if( !nt_hdr.m_optional_hdr.m_data_directory[ ide_import ].m_offset ){ 355 | return true; 356 | }; 357 | 358 | import_desc_t* imp_desc = (import_desc_t*)( m_image_base + nt_hdr.m_optional_hdr.m_data_directory[ ide_import ].m_offset ); 359 | 360 | while( imp_desc->m_name_offset ){ 361 | const string lib_name = (char*)( m_image_base + imp_desc->m_name_offset ); 362 | 363 | if( !import_used( lib_name ) ){ 364 | if( !add_import( lib_name, imp_desc ) ){ 365 | close(); 366 | m_state = ls_error; 367 | return false; 368 | }; 369 | }; 370 | 371 | const import_lib_t& lib = m_imports[ lib_name ]; 372 | 373 | for( uint32_t* func_ptr = (uint32_t*)( m_image_base + ( ( imp_desc->m_timestamp )? imp_desc->m_first_thunk_orig : imp_desc->m_first_thunk ) ); *func_ptr; func_ptr++ ){ 374 | if( is_import_ordinal( *func_ptr, lib.m_handle ) ){ 375 | *func_ptr = (uint32_t)GetProcAddress( lib.m_handle, (LPCSTR)( 0xFFFFU & *func_ptr ) ); 376 | }else{ 377 | *func_ptr = (uint32_t)GetProcAddress( lib.m_handle, (LPCSTR)( ((import_name_desc_t*)( m_image_base + *func_ptr ))->m_name ) ); 378 | }; 379 | 380 | if( !*func_ptr ){ 381 | close(); 382 | m_state = ls_error; 383 | return false; 384 | }; 385 | }; 386 | 387 | imp_desc++; 388 | }; 389 | 390 | return true; 391 | }; 392 | 393 | const bool loader_t::process_exports(){ 394 | const dos_hdr_t& dos_hdr = *(dos_hdr_t*)m_image_base; 395 | const nt_header_t& nt_hdr = *(nt_header_t*)( m_image_base + dos_hdr.m_offset_next ); 396 | 397 | if( !nt_hdr.m_optional_hdr.m_data_directory[ ide_export ].m_offset ){ 398 | return true; 399 | }; 400 | 401 | const uint32_t& section_size = nt_hdr.m_optional_hdr.m_data_directory[ ide_export ].m_size; 402 | const export_desc_t& exports = *(export_desc_t*)( m_image_base + nt_hdr.m_optional_hdr.m_data_directory[ ide_export ].m_offset ); 403 | const uint32_t* const func_ptrs = (uint32_t*)( m_image_base + exports.m_func_offset ); 404 | const uint32_t* const names = (uint32_t*)( m_image_base + exports.m_names_offset ); 405 | const uint16_t* const ordinals = (uint16_t*)( m_image_base + exports.m_ordinals_offset ); 406 | const char* const module_name = (char*)( m_image_base + exports.m_name_offset ); 407 | 408 | for( uint32_t fd = 0; exports.m_names_count > fd; fd++ ){ 409 | entry_t func; 410 | 411 | func.m_module = module_name; 412 | func.m_name = (char*)( m_image_base + names[ fd ] ); 413 | func.m_ordinal = ordinals[ fd ]; 414 | func.m_address = m_image_base + func_ptrs[ func.m_ordinal ]; 415 | 416 | if( ( func.m_address > &exports ) && ( section_size > ( (uint32_t)func.m_address - (uint32_t)&exports ) ) ){ 417 | func.m_module = func.m_name.substr( 0, func.m_name.find( '.' ) ) + ".dll"; 418 | func.m_name = func.m_name.substr( func.m_module.size() + 1 ); 419 | 420 | if( '#' == func.m_name.front() ){ 421 | func.m_name = func.m_name.substr( 1 ); 422 | }; 423 | 424 | if( !import_used( func.m_module ) ){ 425 | if( !add_import( func.m_module, NULL ) ){ 426 | close(); 427 | m_state = ls_error; 428 | return false; 429 | }; 430 | }; 431 | 432 | const import_lib_t& lib = m_imports[ func.m_module ]; 433 | 434 | func.m_address = GetProcAddress( lib.m_handle, func.m_name.c_str() ); 435 | if( !func.m_address ){ 436 | close(); 437 | m_state = ls_error; 438 | return false; 439 | }; 440 | }; 441 | 442 | m_exports.push_back( func ); 443 | }; 444 | 445 | return true; 446 | }; 447 | }; 448 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | --- RU --- 2 | Эта библиотека может помочь в изучении PE формата (PE - Portable Executable - *.exe;*.dll;...). 3 | Библиотека содержит свой набор структур описания формата, но ни что не мешает, получив одну структуру, привести ее к структуре из заголовка WinNT.h. Это легко делается. 4 | А свои структуры я завел исключительно ради полного изучения всех полей DOS-, PE- и COFF- заголовков. К тому же мне немного легче работать с кроссплатформенными типами данных, хотя этот фактор был менее всего значим. 5 | Первый раз такую библиотеку я писал еще в 2007 году, этот вариант - это уже переработка с учетом некоторых моих текущих знаний. 6 | 7 | Задуматься над такой библиотекой меня сподвигла статья : http://www.rsdn.ru/?article/baseserv/peloader.xml 8 | А источники, которые я изучал для написания, и вспомнить уже не удастся, их было очень много. 9 | 10 | Это уже готовая библиотека, которую вполне можно использовать для работы с небольшим dll-файлом. 11 | Я не проверял работу на загрузке системных или каких либо сложных dll, поэтому не могу ручаться за корректность работы кода полностью для всех случаев. 12 | 13 | --- EN --- 14 | This library can help to understand the PE file format (PE - Portable Executable - *.exe;*.dll;...). 15 | The library is based on it's own data structures. But nothing can stop you from using type cast between my structures and that ones, which described inside WinNT.h. 16 | I use my structures just because i want to clearly understand all the DOS- PE- and COFF- structures data fields. 17 | That is not my first PE-loader library, first one was written at 2007, this is my modern reconstruction of that library. 18 | 19 | This is a final library, which can be used for loading some small DLL file. 20 | I can't guaranty that library will work with all DLL files you want. I never test it with system or some kind of huge DLL files. -------------------------------------------------------------------------------- /testing-dll/inc/core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define EXPORT __declspec(dllexport) 6 | 7 | EXPORT BOOL CALLBACK test_beep( DWORD ); -------------------------------------------------------------------------------- /testing-dll/src/core.cpp: -------------------------------------------------------------------------------- 1 | #include "core.h" 2 | 3 | BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID tag ){ 4 | switch( reason ){ 5 | case DLL_PROCESS_ATTACH: 6 | DisableThreadLibraryCalls( inst ); 7 | MessageBeep( MB_ICONEXCLAMATION ); 8 | break; 9 | case DLL_PROCESS_DETACH: 10 | MessageBeep( MB_ICONEXCLAMATION ); 11 | break; 12 | }; 13 | 14 | return true; 15 | }; 16 | 17 | EXPORT BOOL CALLBACK test_beep( DWORD message ){ 18 | MessageBeep( message ); 19 | return true; 20 | }; -------------------------------------------------------------------------------- /testing-dll/testing-dll.def: -------------------------------------------------------------------------------- 1 | LIBRARY "testing-dll" 2 | 3 | EXPORTS 4 | test_beep @1 -------------------------------------------------------------------------------- /testing-dll/testing-dll.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {02AD654D-14A5-4589-817F-C131D6889CFB} 15 | Win32Proj 16 | testingdll 17 | 18 | 19 | 20 | DynamicLibrary 21 | true 22 | MultiByte 23 | 24 | 25 | DynamicLibrary 26 | false 27 | true 28 | MultiByte 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTINGDLL_EXPORTS;%(PreprocessorDefinitions) 53 | inc;%(AdditionalIncludeDirectories) 54 | 55 | 56 | Windows 57 | true 58 | testing-dll.def 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_WINDOWS;_USRDLL;TESTINGDLL_EXPORTS;%(PreprocessorDefinitions) 70 | inc;%(AdditionalIncludeDirectories) 71 | 72 | 73 | Windows 74 | true 75 | true 76 | true 77 | testing-dll.def 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /testing-dll/testing-dll.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | 28 | 29 | Source Files 30 | 31 | 32 | --------------------------------------------------------------------------------