📄 peloader.c
字号:
/****************************************************************************** SciTech MGL Graphics Library** ========================================================================** The contents of this file are subject to the SciTech MGL Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.scitechsoft.com/mgl-license.txt** Software distributed under the License is distributed on an* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.** The Initial Developer of the Original Code is SciTech Software, Inc.* All Rights Reserved.** ========================================================================** Language: ANSI C* Environment: Any** Description: Module to implement a simple Portable Binary DLL loader* library. This library can be used to load PE DLL's under* any Intel based OS, provided the DLL's do not have any* imports in the import table.** NOTE: This loader module expects the DLL's to be built with* Watcom C++ and may produce unexpected results with* DLL's linked by another compiler.*****************************************************************************/#include "drvlib/peloader.h"#include "pmapi.h"#include "drvlib/os/os.h"#include "drvlib/libc/init.h"#if (defined(__WINDOWS32__) || defined(__DRIVER__)) && defined(CHECKED)#define WIN32_LEAN_AND_MEAN#define STRICT#include <windows.h>#endif#include "drvlib/pe.h"/*--------------------------- Global variables ----------------------------*/static int result = PE_ok;/*------------------------- Implementation --------------------------------*//****************************************************************************PARAMETERS:f - Handle to open file to read driver fromstartOffset - Offset to the start of the driver within the fileRETURNS:Handle to loaded PE DLL, or NULL on failure.REMARKS:This function loads a Portable Binary DLL library from disk, relocatesthe code and returns a handle to the loaded library. This function is thesame as the regular PE_loadLibrary except that it take a handle to anopen file and an offset within that file for the DLL to load.****************************************************************************/static int PE_readHeader( FILE *f, long startOffset, FILE_HDR *filehdr, OPTIONAL_HDR *opthdr){ EXE_HDR exehdr; ulong offset,signature; /* Read the EXE header and check for valid header signature */ result = PE_invalidDLLImage; fseek(f, startOffset, SEEK_SET); if (fread(&exehdr, 1, sizeof(exehdr), f) != sizeof(exehdr)) return false; if (exehdr.signature != 0x5A4D) return false; /* Now seek to the start of the PE header defined at offset 0x3C * in the MS-DOS EXE header, and read the signature and check it. */ fseek(f, startOffset+0x3C, SEEK_SET); if (fread(&offset, 1, sizeof(offset), f) != sizeof(offset)) return false; fseek(f, startOffset+offset, SEEK_SET); if (fread(&signature, 1, sizeof(signature), f) != sizeof(signature)) return false; if (signature != 0x00004550) return false; /* Now read the PE file header and check that it is correct */ if (fread(filehdr, 1, sizeof(*filehdr), f) != sizeof(*filehdr)) return false; if (filehdr->Machine != IMAGE_FILE_MACHINE_I386) return false; if (!(filehdr->Characteristics & IMAGE_FILE_32BIT_MACHINE)) return false; if (!(filehdr->Characteristics & IMAGE_FILE_DLL)) return false; if (fread(opthdr, 1, sizeof(*opthdr), f) != sizeof(*opthdr)) return false; if (opthdr->Magic != 0x10B) return false; /* Success, so return true! */ return true;}/****************************************************************************PARAMETERS:f - Handle to open file to read driver fromstartOffset - Offset to the start of the driver within the fileRETURNS:Size of the DLL file on disk, or -1 on errorREMARKS:This function scans the headers for a Portable Binary DLL to determine thelength of the DLL file on disk.{secret}****************************************************************************/ulong PEAPI PE_getFileSize( FILE *f, ulong startOffset){ FILE_HDR filehdr; OPTIONAL_HDR opthdr; SECTION_HDR secthdr; ulong size; int i; /* Read the PE file headers from disk */ if (!PE_readHeader(f,startOffset,&filehdr,&opthdr)) return 0xFFFFFFFF; /* Scan all the section headers summing up the total size */ size = opthdr.SizeOfHeaders; for (i = 0; i < filehdr.NumberOfSections; i++) { if (fread(§hdr, 1, sizeof(secthdr), f) != sizeof(secthdr)) return 0xFFFFFFFF; size += secthdr.SizeOfRawData; } return size;}/****************************************************************************DESCRIPTION:Loads a Portable Binary DLL into memory from an open fileHEADER:peloader.hPARAMETERS:f - Handle to open file to read driver fromstartOffset - Offset to the start of the driver within the filesize - Place to store the size of the driver loadedshared - True to load module into shared memoryRETURNS:Handle to loaded PE DLL, or NULL on failure.REMARKS:This function loads a Portable Binary DLL library from disk, relocatesthe code and returns a handle to the loaded library. This function is thesame as the regular PE_loadLibrary except that it take a handle to anopen file and an offset within that file for the DLL to load.SEE ALSO:PE_loadLibrary, PE_getProcAddress, PE_freeLibrary****************************************************************************/PE_MODULE * PEAPI PE_loadLibraryExt( FILE *f, ulong startOffset, ulong *size, ibool shared){ FILE_HDR filehdr; OPTIONAL_HDR opthdr; SECTION_HDR secthdr; ulong offset,pageOffset; ulong text_off,text_addr,text_size; ulong data_off,data_addr,data_size,data_end; ulong export_off,export_addr,export_size,export_end; ulong reloc_off,reloc_size; ulong image_size; int i,delta,numFixups; ushort relocType,*fixup; PE_MODULE *hMod = NULL; void *reloc = NULL; BASE_RELOCATION *baseReloc; InitLibC_t InitLibC; /* Read the PE file headers from disk */ if (!PE_readHeader(f,startOffset,&filehdr,&opthdr)) return NULL; /* Scan all the section headers and find the necessary sections */ text_off = data_off = reloc_off = export_off = 0; text_addr = text_size = 0; data_addr = data_size = data_end = 0; export_addr = export_size = export_end = 0; reloc_size = 0; for (i = 0; i < filehdr.NumberOfSections; i++) { if (fread(§hdr, 1, sizeof(secthdr), f) != sizeof(secthdr)) goto Error; if (strcmp(secthdr.Name, ".edata") == 0 || strcmp(secthdr.Name, ".rdata") == 0) { /* Exports section */ export_off = secthdr.PointerToRawData; export_addr = secthdr.VirtualAddress; export_size = secthdr.SizeOfRawData; export_end = export_addr + export_size; } else if (strcmp(secthdr.Name, ".idata") == 0) { /* Imports section, ignore */ } else if (strcmp(secthdr.Name, ".reloc") == 0) { /* Relocations section */ reloc_off = secthdr.PointerToRawData; reloc_size = secthdr.SizeOfRawData; } else if (!text_off && secthdr.Characteristics & IMAGE_SCN_CNT_CODE) { /* Code section */ text_off = secthdr.PointerToRawData; text_addr = secthdr.VirtualAddress; text_size = secthdr.SizeOfRawData; } else if (!data_off && secthdr.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { /* Data section */ data_off = secthdr.PointerToRawData; data_addr = secthdr.VirtualAddress; data_size = secthdr.SizeOfRawData; data_end = data_addr + data_size; } } /* Check to make sure that we have all the sections we need */ if (!text_off || !data_off || !export_off || !reloc_off) { result = PE_invalidDLLImage; goto Error; } /* Find the size of the image to load allocate memory for it */ image_size = MAX(export_end,data_end) - text_addr; *size = sizeof(PE_MODULE) + image_size + 4096; if (shared) hMod = PM_mallocShared(*size); else hMod = PM_malloc(*size); reloc = PM_malloc(reloc_size); if (!hMod || !reloc) { result = PE_outOfMemory; goto Error; } hMod->text = (uchar*)ROUND_4K((ulong)hMod + sizeof(PE_MODULE)); hMod->data = (uchar*)((ulong)hMod->text + (data_addr - text_addr)); hMod->export = (uchar*)((ulong)hMod->text + (export_addr - text_addr)); hMod->textBase = text_addr; hMod->dataBase = data_addr; hMod->exportBase = export_addr; hMod->exportDir = opthdr.DataDirectory[0].RelVirtualAddress - export_addr; hMod->shared = shared; /* Now read the section images from disk */ result = PE_invalidDLLImage; fseek(f, startOffset+text_off, SEEK_SET); if (fread(hMod->text, 1, text_size, f) != text_size) goto Error; fseek(f, startOffset+data_off, SEEK_SET); if (fread(hMod->data, 1, data_size, f) != data_size) goto Error; fseek(f, startOffset+export_off, SEEK_SET); if (fread(hMod->export, 1, export_size, f) != export_size) goto Error; fseek(f, startOffset+reloc_off, SEEK_SET); if (fread(reloc, 1, reloc_size, f) != reloc_size) goto Error; /* Now perform relocations on all sections in the image */ delta = (ulong)hMod->text - opthdr.ImageBase - text_addr; baseReloc = (BASE_RELOCATION*)reloc; for (;;) { /* Check for termination condition */ if (!baseReloc->PageRVA || !baseReloc->BlockSize) break; /* Do fixups */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -