Full Code of abhisek/Pe-Loader-Sample for AI

master 9aed4b3f6cd3 cached
9 files
25.6 KB
8.4k tokens
13 symbols
1 requests
Download .txt
Repository: abhisek/Pe-Loader-Sample
Branch: master
Commit: 9aed4b3f6cd3
Files: 9
Total size: 25.6 KB

Directory structure:
gitextract_cjiu6xeh/

├── .gitattributes
├── .gitignore
├── Pe-Loader-Sample.vcproj
├── README.md
└── src/
    ├── Debug.h
    ├── Main.cpp
    ├── PEB.h
    ├── PeLdr.cpp
    └── PeLdr.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs     diff=csharp
*.sln    merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

# Standard to msysgit
*.doc	 diff=astextplain
*.DOC	 diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot  diff=astextplain
*.DOT  diff=astextplain
*.pdf  diff=astextplain
*.PDF	 diff=astextplain
*.rtf	 diff=astextplain
*.RTF	 diff=astextplain


================================================
FILE: .gitignore
================================================

#################
## Eclipse
#################

*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath


#################
## Visual Studio
#################

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.sln.docstates

# Build results
**/[Dd]ebug/
**/[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
**/*.dotCover

## TODO: If you have NuGet Package Restore enabled, uncomment this
#**/packages/ 

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf

# Visual Studio profiler
*.psess
*.vsp

# ReSharper is a .NET coding add-in
_ReSharper*

# Installshield output folder 
[Ee]xpress

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish

# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects

# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML



############
## Windows
############

# Windows image file caches
Thumbs.db 

# Folder config file
Desktop.ini


#############
## Python
#############

*.py[co]

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox

#Translations
*.mo

#Mr Developer
.mr.developer.cfg

# Mac crap
.DS_Store

Debug


================================================
FILE: Pe-Loader-Sample.vcproj
================================================
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
	ProjectType="Visual C++"
	Version="9.00"
	Name="Pe-Loader-Sample"
	ProjectGUID="{8DED49F0-69AF-4815-B5DE-522CEEEFD56C}"
	RootNamespace="PeLoaderSample"
	Keyword="Win32Proj"
	TargetFrameworkVersion="196613"
	>
	<Platforms>
		<Platform
			Name="Win32"
		/>
	</Platforms>
	<ToolFiles>
	</ToolFiles>
	<Configurations>
		<Configuration
			Name="Debug|Win32"
			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
			IntermediateDirectory="$(ConfigurationName)"
			ConfigurationType="1"
			CharacterSet="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
				MinimalRebuild="true"
				BasicRuntimeChecks="3"
				RuntimeLibrary="3"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="4"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				LinkIncremental="2"
				GenerateDebugInformation="true"
				SubSystem="1"
				FixedBaseAddress="1"
				TargetMachine="1"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
			/>
		</Configuration>
		<Configuration
			Name="Release|Win32"
			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
			IntermediateDirectory="$(ConfigurationName)"
			ConfigurationType="1"
			CharacterSet="1"
			WholeProgramOptimization="1"
			>
			<Tool
				Name="VCPreBuildEventTool"
			/>
			<Tool
				Name="VCCustomBuildTool"
			/>
			<Tool
				Name="VCXMLDataGeneratorTool"
			/>
			<Tool
				Name="VCWebServiceProxyGeneratorTool"
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="2"
				EnableIntrinsicFunctions="true"
				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
				RuntimeLibrary="2"
				EnableFunctionLevelLinking="true"
				UsePrecompiledHeader="0"
				WarningLevel="3"
				DebugInformationFormat="3"
			/>
			<Tool
				Name="VCManagedResourceCompilerTool"
			/>
			<Tool
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				LinkIncremental="1"
				GenerateDebugInformation="true"
				SubSystem="1"
				OptimizeReferences="2"
				EnableCOMDATFolding="2"
				FixedBaseAddress="1"
				TargetMachine="1"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
			/>
			<Tool
				Name="VCXDCMakeTool"
			/>
			<Tool
				Name="VCBscMakeTool"
			/>
			<Tool
				Name="VCFxCopTool"
			/>
			<Tool
				Name="VCAppVerifierTool"
			/>
			<Tool
				Name="VCPostBuildEventTool"
			/>
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
			>
			<File
				RelativePath=".\src\Main.cpp"
				>
			</File>
			<File
				RelativePath=".\src\PeLdr.cpp"
				>
			</File>
		</Filter>
		<Filter
			Name="Header Files"
			Filter="h;hpp;hxx;hm;inl;inc;xsd"
			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
			>
			<File
				RelativePath=".\src\Debug.h"
				>
			</File>
			<File
				RelativePath=".\src\PEB.h"
				>
			</File>
			<File
				RelativePath=".\src\PeLdr.h"
				>
			</File>
		</Filter>
		<Filter
			Name="Resource Files"
			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
			>
		</Filter>
	</Files>
	<Globals>
	</Globals>
</VisualStudioProject>


================================================
FILE: README.md
================================================
PE Loader Sample
=================

In memory execution of PE executables:

 * Self Relocation
 * Memory Mapping
 * IAT Processing
 * Relocation
 * Control Transfer
	
This project aims to implement a complete PE Loader capable of loading all PE and PE+ executables. The current version should be considered as a PoC only as it does not handle all practical cases.

TODO:

 * Handle Import Forwarding
 * Bound Imports
 * Is it possible to relocate a PE if relocation table is not included? Hack++?
 * Most Important: Documentation of PE Loading Process
	
Thanks
-------

* Special thanks to Stephen Fewer of Harmony Security for Reflective DLL Injection paper and implementation. The IAT processing and Relocation code in this project is taken from ReflectiveDLL Loader implementation.

* sincoder for ideas on Self Relocation.

================================================
FILE: src/Debug.h
================================================
#ifndef _DEBUG_H
#define _DEBUG_H

#include <stdio.h>

#define __DEBUG

#ifdef __DEBUG
#include <strsafe.h>
#define DMSG(x, ...)	fprintf(stderr, "[+] " x "\n", __VA_ARGS__)
#define EMSG(x, ...)	fprintf(stderr, "[-] " x "\n", __VA_ARGS__)
#else
#define DMSG(x, ...)	do { } while(0)
#define EMSG(x, ...)	do { } while(0)
#endif

#endif

================================================
FILE: src/Main.cpp
================================================
#include "PeLdr.h"
#include "Debug.h"

static
INT ShowUsage()
{
	printf("-- PE Loader Sample --\n\n");
	printf("PeLdr [PE-File]\n");
	printf("\n");

	return 0;
}

int wmain(int argc, wchar_t *argv[])
{
	PE_LDR_PARAM peLdr;

	if(argc < 2)
		return ShowUsage();

	PeLdrInit(&peLdr);
	PeLdrSetExecutablePath(&peLdr, argv[1]);
	PeLdrStart(&peLdr);

	return 0;
}

================================================
FILE: src/PEB.h
================================================
#ifndef _PEB_H
#define _PEB_H

// https://github.com/stephenfewer/ReflectiveDLLInjection
//===============================================================================================//
typedef struct _UNICODE_STR
{
  USHORT Length;
  USHORT MaximumLength;
  PWSTR pBuffer;
} UNICODE_STR, *PUNICODE_STR;

// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
//__declspec( align(8) ) 
typedef struct _LDR_DATA_TABLE_ENTRY
{
	//LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	PVOID DllBase;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STR FullDllName;
	UNICODE_STR BaseDllName;
	ULONG Flags;
	SHORT LoadCount;
	SHORT TlsIndex;
	LIST_ENTRY HashTableEntry;
	ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

// WinDbg> dt -v ntdll!_PEB_LDR_DATA
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
{
   DWORD dwLength;
   DWORD dwInitialized;
   LPVOID lpSsHandle;
   LIST_ENTRY InLoadOrderModuleList;
   LIST_ENTRY InMemoryOrderModuleList;
   LIST_ENTRY InInitializationOrderModuleList;
   LPVOID lpEntryInProgress;
} PEB_LDR_DATA, * PPEB_LDR_DATA;

// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
{
   struct _PEB_FREE_BLOCK * pNext;
   DWORD dwSize;
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;

// struct _PEB is defined in Winternl.h but it is incomplete
// WinDbg> dt -v ntdll!_PEB
typedef struct __PEB // 65 elements, 0x210 bytes
{
   BYTE bInheritedAddressSpace;
   BYTE bReadImageFileExecOptions;
   BYTE bBeingDebugged;
   BYTE bSpareBool;
   LPVOID lpMutant;
   LPVOID lpImageBaseAddress;
   PPEB_LDR_DATA pLdr;
   LPVOID lpProcessParameters;
   LPVOID lpSubSystemData;
   LPVOID lpProcessHeap;
   PRTL_CRITICAL_SECTION pFastPebLock;
   LPVOID lpFastPebLockRoutine;
   LPVOID lpFastPebUnlockRoutine;
   DWORD dwEnvironmentUpdateCount;
   LPVOID lpKernelCallbackTable;
   DWORD dwSystemReserved;
   DWORD dwAtlThunkSListPtr32;
   PPEB_FREE_BLOCK pFreeList;
   DWORD dwTlsExpansionCounter;
   LPVOID lpTlsBitmap;
   DWORD dwTlsBitmapBits[2];
   LPVOID lpReadOnlySharedMemoryBase;
   LPVOID lpReadOnlySharedMemoryHeap;
   LPVOID lpReadOnlyStaticServerData;
   LPVOID lpAnsiCodePageData;
   LPVOID lpOemCodePageData;
   LPVOID lpUnicodeCaseTableData;
   DWORD dwNumberOfProcessors;
   DWORD dwNtGlobalFlag;
   LARGE_INTEGER liCriticalSectionTimeout;
   DWORD dwHeapSegmentReserve;
   DWORD dwHeapSegmentCommit;
   DWORD dwHeapDeCommitTotalFreeThreshold;
   DWORD dwHeapDeCommitFreeBlockThreshold;
   DWORD dwNumberOfHeaps;
   DWORD dwMaximumNumberOfHeaps;
   LPVOID lpProcessHeaps;
   LPVOID lpGdiSharedHandleTable;
   LPVOID lpProcessStarterHelper;
   DWORD dwGdiDCAttributeList;
   LPVOID lpLoaderLock;
   DWORD dwOSMajorVersion;
   DWORD dwOSMinorVersion;
   WORD wOSBuildNumber;
   WORD wOSCSDVersion;
   DWORD dwOSPlatformId;
   DWORD dwImageSubsystem;
   DWORD dwImageSubsystemMajorVersion;
   DWORD dwImageSubsystemMinorVersion;
   DWORD dwImageProcessAffinityMask;
   DWORD dwGdiHandleBuffer[34];
   LPVOID lpPostProcessInitRoutine;
   LPVOID lpTlsExpansionBitmap;
   DWORD dwTlsExpansionBitmapBits[32];
   DWORD dwSessionId;
   ULARGE_INTEGER liAppCompatFlags;
   ULARGE_INTEGER liAppCompatFlagsUser;
   LPVOID lppShimData;
   LPVOID lpAppCompatInfo;
   UNICODE_STR usCSDVersion;
   LPVOID lpActivationContextData;
   LPVOID lpProcessAssemblyStorageMap;
   LPVOID lpSystemDefaultActivationContextData;
   LPVOID lpSystemAssemblyStorageMap;
   DWORD dwMinimumStackCommit;
} _PEB, * _PPEB;

typedef struct
{
	WORD	offset:12;
	WORD	type:4;
} IMAGE_RELOC, *PIMAGE_RELOC;

#endif


================================================
FILE: src/PeLdr.cpp
================================================
#include "PeLdr.h"
#include "Debug.h"
#include "PEB.h"

#include <strsafe.h>

#ifndef NTSTATUS
#define NTSTATUS	LONG
#endif

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
#endif

#pragma warning(disable: 4995)

static
BOOL PeLdrApplyImageRelocations(DWORD dwImageBase, UINT_PTR iRelocOffset)
{
	PIMAGE_DOS_HEADER			pDosHeader;
	PIMAGE_NT_HEADERS			pNtHeaders;
	DWORD						x;
	DWORD						dwTmp;
	PIMAGE_BASE_RELOCATION		pBaseReloc;
	PIMAGE_RELOC				pReloc;

	DMSG("Applying Image Relocation (Base: 0x%08x RelocOffset: 0x%08x)",
		dwImageBase, iRelocOffset);

	pDosHeader = (PIMAGE_DOS_HEADER) dwImageBase;
	pNtHeaders = (PIMAGE_NT_HEADERS) (dwImageBase + pDosHeader->e_lfanew);

	pBaseReloc = (PIMAGE_BASE_RELOCATION) 
		(dwImageBase + 
		pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

	while(pBaseReloc->SizeOfBlock) {
		x = dwImageBase + pBaseReloc->VirtualAddress;
		dwTmp = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);
		pReloc = (PIMAGE_RELOC) (((DWORD) pBaseReloc) + sizeof(IMAGE_BASE_RELOCATION));

		while(dwTmp--) {
			switch(pReloc->type) {
				case IMAGE_REL_BASED_DIR64:
					*((UINT_PTR*)(x + pReloc->offset)) += iRelocOffset;
					break;	
				case IMAGE_REL_BASED_HIGHLOW:
					*((DWORD*)(x + pReloc->offset)) += (DWORD) iRelocOffset;
					break;

				case IMAGE_REL_BASED_HIGH:
					*((WORD*)(x + pReloc->offset)) += HIWORD(iRelocOffset);
					break;

				case IMAGE_REL_BASED_LOW:
					*((WORD*)(x + pReloc->offset)) += LOWORD(iRelocOffset);
					break;

				case IMAGE_REL_BASED_ABSOLUTE:
					break;

				default:
					DMSG("Unknown relocation type: 0x%08x", pReloc->type);
					break;
			}

			pReloc += 1;
		}

		pBaseReloc = (PIMAGE_BASE_RELOCATION)(((DWORD) pBaseReloc) + pBaseReloc->SizeOfBlock);
	}

	return TRUE;
}

static
BOOL PeLdrProcessIAT(DWORD dwImageBase)
{
	BOOL						ret = FALSE;
	PIMAGE_DOS_HEADER			pDosHeader;
	PIMAGE_NT_HEADERS			pNtHeaders;
	PIMAGE_IMPORT_DESCRIPTOR	pImportDesc;
	PIMAGE_THUNK_DATA			pThunkData;
	PIMAGE_THUNK_DATA			pThunkDataOrig;
	PIMAGE_IMPORT_BY_NAME		pImportByName;
	PIMAGE_EXPORT_DIRECTORY		pExportDir;
	DWORD						flError = 0;
	DWORD						dwTmp;
	BYTE						*pLibName;
	HMODULE						hMod;

	DMSG("Processing IAT (Image Base: 0x%08x)", dwImageBase);

	pDosHeader = (PIMAGE_DOS_HEADER) dwImageBase;
	pNtHeaders = (PIMAGE_NT_HEADERS) (dwImageBase + pDosHeader->e_lfanew);

	do {
		pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(dwImageBase +
			pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

		if(!pImportDesc) {
			DMSG("IAT not found");
			break;
		}

		while((pImportDesc->Name != 0) && (!flError)) {
			pLibName = (BYTE*) (dwImageBase + pImportDesc->Name);
			DMSG("Loading Library and processing Imports: %s", (CHAR*) pLibName);

			if(pImportDesc->ForwarderChain != -1) {
				DMSG("FIXME: Cannot handle Import Forwarding");
				//flError = 1;
				//break;
			}

			hMod = LoadLibraryA((CHAR*) pLibName);
			if(!hMod) {
				DMSG("Failed to load library: %s", pLibName);
				flError = 1;
				break;
			}

			pThunkData = (PIMAGE_THUNK_DATA)(dwImageBase + pImportDesc->FirstThunk);
			if(pImportDesc->Characteristics == 0)
				/* Borland compilers doesn't produce Hint Table */
				pThunkDataOrig = pThunkData;
			else
				/* Hint Table */
				pThunkDataOrig = (PIMAGE_THUNK_DATA)(dwImageBase + pImportDesc->Characteristics);

			while(pThunkDataOrig->u1.AddressOfData != 0) {
				if(pThunkDataOrig->u1.Ordinal & IMAGE_ORDINAL_FLAG) {
					/* Import via. Export Ordinal */
					PIMAGE_DOS_HEADER		_dos;
					PIMAGE_NT_HEADERS		_nt;

					_dos = (PIMAGE_DOS_HEADER) hMod;
					_nt = (PIMAGE_NT_HEADERS) (((DWORD) hMod) + _dos->e_lfanew);

					pExportDir = (PIMAGE_EXPORT_DIRECTORY) 
						(((DWORD) hMod) + _nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
					dwTmp = (((DWORD) hMod) + pExportDir->AddressOfFunctions) + (((IMAGE_ORDINAL(pThunkDataOrig->u1.Ordinal) - pExportDir->Base)) * sizeof(DWORD));
					dwTmp = ((DWORD) hMod) + *((DWORD*) dwTmp);

					pThunkData->u1.Function = dwTmp;
				}
				else {
					pImportByName = (PIMAGE_IMPORT_BY_NAME)
						(dwImageBase + pThunkDataOrig->u1.AddressOfData);
					pThunkData->u1.Function = (DWORD) GetProcAddress(hMod, (LPCSTR) pImportByName->Name);

					if(!pThunkData->u1.Function) {
						DMSG("Failed to resolve API: %s!%s", 
							(CHAR*)pLibName, (CHAR*)pImportByName->Name);
						flError = 1;
						break;
					}
				}

				pThunkDataOrig++;
				pThunkData++;
			}

			pImportDesc++;
		}

		if(!flError)
			ret = TRUE;

	} while(0);
	return ret;
}

static
BOOL PeLdrNeedSelfRelocation(PE_LDR_PARAM *pe)
{
	DWORD				dwMyBase;
	PIMAGE_DOS_HEADER	pMyDosHeader;
	PIMAGE_NT_HEADERS	pMyNtHeaders;

	DMSG("Checking for self relocation");

	dwMyBase = (DWORD) GetModuleHandle(NULL);
	if(!dwMyBase) {
		EMSG("Failed to get our loaded address");
		return FALSE;
	}
	
	pMyDosHeader = (PIMAGE_DOS_HEADER) dwMyBase;
	pMyNtHeaders = (PIMAGE_NT_HEADERS) (dwMyBase + pMyDosHeader->e_lfanew);

	if(pMyNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
		EMSG("Failed to find our own headers");
		return FALSE;
	}

	DMSG("MyBase: 0x%08x MySize: %d", dwMyBase, pMyNtHeaders->OptionalHeader.SizeOfImage);

	if((pe->pNtHeaders->OptionalHeader.ImageBase >= dwMyBase) &&
		(pe->pNtHeaders->OptionalHeader.ImageBase < (dwMyBase + pMyNtHeaders->OptionalHeader.SizeOfImage)))
	{
		DMSG("Self relocation required");
		return TRUE;
	}

	return FALSE;
}

static
BOOL PeLdrRelocateAndContinue(PE_LDR_PARAM *pe, VOID *pContFunc, VOID *pParam)
{
	PIMAGE_DOS_HEADER	pMyDosHeader;
	PIMAGE_NT_HEADERS	pMyNtHeaders;
	DWORD				dwNewBase;
	DWORD				dwMyBase;
	DWORD				dwAddr;
	UINT_PTR			iRelocOffset;

	DMSG("Relocating loader image (Continue Function: 0x%08x)", (DWORD) pContFunc);

	dwMyBase = (DWORD) GetModuleHandle(NULL);
	if(!dwMyBase) {
		EMSG("Failed to get our loaded address");
		return FALSE;
	}
	
	pMyDosHeader = (PIMAGE_DOS_HEADER) dwMyBase;
	pMyNtHeaders = (PIMAGE_NT_HEADERS) (dwMyBase + pMyDosHeader->e_lfanew);

	dwNewBase = (DWORD) VirtualAlloc(NULL, pMyNtHeaders->OptionalHeader.SizeOfImage + 1,
		MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if(!dwNewBase) {
		EMSG("Failed to allocate memory for self relocation");
		return FALSE;
	}

	DMSG("New Loader Base: 0x%08x", dwNewBase);
	pe->dwLoaderRelocatedBase = dwNewBase;

	CopyMemory((VOID*) dwNewBase, (VOID*) dwMyBase,
		pMyNtHeaders->OptionalHeader.SizeOfImage);

	if(!PeLdrProcessIAT(dwNewBase)) {
		EMSG("Failed to process IAT for relocated image");
		return FALSE;
	}

	iRelocOffset = dwNewBase - dwMyBase;
	if(!PeLdrApplyImageRelocations(dwNewBase, iRelocOffset)) {
		EMSG("Failed to apply relocations on relocated image");
		return FALSE;
	}

	pe->dwLoaderBase = dwNewBase;

	dwAddr = ((DWORD) pContFunc) - dwMyBase;
	dwAddr += dwNewBase;

	DMSG("Jumping to relocated image (Relocated Continue Function: 0x%08x)", dwAddr);
	__asm {
		mov eax, pParam
		push eax
		mov eax, dwAddr
		call eax
	}

	return TRUE;
}

static
BOOL PeLdrExecuteEP(PE_LDR_PARAM *pe)
{
	DWORD	dwOld;
	DWORD	dwEP;
	_PPEB	peb;

	// TODO: Fix permission as per section flags
	if(!VirtualProtect((LPVOID) pe->dwMapBase, pe->pNtHeaders->OptionalHeader.SizeOfImage,
		PAGE_EXECUTE_READWRITE, &dwOld)) {
		DMSG("Failed to change mapping protection");
		return FALSE;
	}

	
	DMSG("Fixing Image Base address in PEB");
	peb = (_PPEB)__readfsdword(0x30);
	peb->lpImageBaseAddress = (LPVOID) pe->dwMapBase;

	dwEP = pe->dwMapBase + pe->pNtHeaders->OptionalHeader.AddressOfEntryPoint;
	DMSG("Executing Entry Point: 0x%08x", dwEP);

	__asm {
		mov eax, dwEP
		call eax
		int 3
	}

	return TRUE;
}

static
BOOL PeLdrApplyRelocations(PE_LDR_PARAM *pe)
{
	UINT_PTR	iRelocOffset;

	if(pe->dwMapBase == pe->pNtHeaders->OptionalHeader.ImageBase) {
		DMSG("Relocation not required");
		return TRUE;
	}

	if(!pe->pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) {
		DMSG("PE required relocation but no relocatiom information found");
		return FALSE;
	}

	iRelocOffset = pe->dwMapBase - pe->pNtHeaders->OptionalHeader.ImageBase;
	return PeLdrApplyImageRelocations(pe->dwMapBase, iRelocOffset);
}

static
BOOL PeLdrMapImage(PE_LDR_PARAM *pe)
{
	DWORD						i;
	MEMORY_BASIC_INFORMATION	mi;
	PIMAGE_SECTION_HEADER		pSectionHeader;
	BOOL						ret = FALSE;

	NTSTATUS	(NTAPI *NtUnmapViewOfSection)
					(HANDLE, LPVOID) = NULL;
	if(!pe)
		return ret;

	DMSG("Mapping Target PE File");
	DMSG("Loader Base Orig: 0x%08x New: 0x%08x", 
		pe->dwLoaderBase, pe->dwLoaderRelocatedBase);

	NtUnmapViewOfSection = 
		(NTSTATUS (NTAPI *)(HANDLE, LPVOID))
			GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "ZwUnmapViewOfSection");
	if(!NtUnmapViewOfSection)
		DMSG("Failed to resolve address of NtUnmapViewOfSection");

	do {
		DMSG("Target PE Load Base: 0x%08x Image Size: 0x%08x",
			pe->pNtHeaders->OptionalHeader.ImageBase,
			pe->pNtHeaders->OptionalHeader.SizeOfImage);

		// Find the size of our mapping
		i = pe->dwLoaderBase;
		while(VirtualQuery((LPVOID) i, &mi, sizeof(mi))) {
			if(mi.State == MEM_FREE)
				break;

			i += mi.RegionSize;
		}

		if((pe->pNtHeaders->OptionalHeader.ImageBase >= pe->dwLoaderBase) && 
			(pe->pNtHeaders->OptionalHeader.ImageBase < i)) {
			if(NtUnmapViewOfSection) {
				DMSG("Unmapping original loader mapping");
				if(NtUnmapViewOfSection(GetCurrentProcess(), (VOID*) pe->dwLoaderBase) == STATUS_SUCCESS) {
					pe->dwMapBase = (DWORD) VirtualAlloc((LPVOID) pe->pNtHeaders->OptionalHeader.ImageBase,
										pe->pNtHeaders->OptionalHeader.SizeOfImage + 1,
										MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
				}
				else {
					EMSG("Failed to unmap original loader mapping");
				}
			}
		}
		
		pe->dwMapBase = (DWORD) VirtualAlloc((LPVOID) pe->pNtHeaders->OptionalHeader.ImageBase,
			pe->pNtHeaders->OptionalHeader.SizeOfImage + 1,
			MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

		if(!pe->dwMapBase)
			EMSG("Failed to allocate PE ImageBase: 0x%08x", 
				pe->pNtHeaders->OptionalHeader.ImageBase);

		if(!pe->dwMapBase) {
			DMSG("Attempting to allocate new memory");

			if(!pe->pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) {
				EMSG("Failed to map required memory address, need relocation to continue");
				EMSG("[WARNING] Forcing re-use of mapped memory");
				
				pe->dwMapBase = (DWORD) pe->pNtHeaders->OptionalHeader.ImageBase;
			}
			else {
				pe->dwMapBase = (DWORD) VirtualAlloc(NULL, 
					pe->pNtHeaders->OptionalHeader.SizeOfImage + 1,
					MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
			}
		}

		if(!pe->dwMapBase) {
			EMSG("Failed to map memory for Target PE");
			break;
		}

		DMSG("Allocated memory for Target PE: 0x%08x", pe->dwMapBase);
		
		DMSG("Copying Headers");
		CopyMemory((LPVOID) pe->dwMapBase, (LPVOID) pe->dwImage,
			pe->pNtHeaders->OptionalHeader.SizeOfHeaders);

		DMSG("Copying Sections");
		pSectionHeader = IMAGE_FIRST_SECTION(pe->pNtHeaders);
		for(i = 0; i < pe->pNtHeaders->FileHeader.NumberOfSections; i++) {
			DMSG("  Copying Section: %s", (CHAR*) pSectionHeader[i].Name);

			CopyMemory(
				(LPVOID)(pe->dwMapBase + pSectionHeader[i].VirtualAddress),
				(LPVOID)(pe->dwImage + pSectionHeader[i].PointerToRawData),
				pSectionHeader[i].SizeOfRawData
			);
		}

		ret = TRUE;
	} while(0);

	return ret;
}

static 
BOOL PeLdrLoadImage(PE_LDR_PARAM *pe)
{
	HANDLE	hFile	= NULL;
	HANDLE	hMap	= NULL;
	BOOL	ret = FALSE;
	_PPEB	peb;

	if(!pe)
		goto out;

	DMSG("Mapping PE File");

	if(!pe->bLoadFromBuffer) {
		DMSG("Creating Map View of File");

		hFile = CreateFile(pe->pTargetPath, GENERIC_READ, 
			FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
		if(hFile == INVALID_HANDLE_VALUE) {
			DMSG("Failed to open PE File");
			goto out;
		}

		pe->dwImageSizeOnDisk = GetFileSize(hFile, NULL);
		hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
		if(hMap == NULL) {
			DMSG("Failed to create file mapping for PE File");
			goto out;
		}

		pe->dwImage = (DWORD) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
		if(!pe->dwImage) {
			DMSG("Failed to obtain a map view of PE File");
			goto out;
		}
	}

	DMSG("Map View of File created");

	pe->pDosHeader = (PIMAGE_DOS_HEADER) pe->dwImage;
	if(pe->pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
		DMSG("DOS Signature invalid");
		goto out;
	}

	pe->pNtHeaders = (PIMAGE_NT_HEADERS)(((DWORD) pe->dwImage) + pe->pDosHeader->e_lfanew);
	if(pe->pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
		DMSG("NT Signature mismatch");
		goto out;
	}

	peb = (_PPEB)__readfsdword(0x30);
	pe->dwLoaderBase = (DWORD) peb->lpImageBaseAddress;

	ret = TRUE;

out:
	if(hMap)
		CloseHandle(hMap);
	if(hFile)
		CloseHandle(hFile);

	return ret;
}

static
BOOL PeLdrRunImage(PE_LDR_PARAM *pe)
{
	if(!PeLdrMapImage(pe))
		return FALSE;
	if(!PeLdrProcessIAT(pe->dwMapBase))
		return FALSE;
	if(!PeLdrApplyRelocations(pe))
		return FALSE;
	if(!PeLdrExecuteEP(pe))
		return FALSE;

	return TRUE;
}

BOOL PeLdrStart(PE_LDR_PARAM *pe)
{
	if(!PeLdrLoadImage(pe))
		return FALSE;

	if(PeLdrNeedSelfRelocation(pe))
		return PeLdrRelocateAndContinue(pe, (VOID*) PeLdrRunImage, (VOID*) pe);
	else
		return PeLdrRunImage(pe);
}

BOOL PeLdrSetExecutableBuffer(PE_LDR_PARAM *pe, PVOID pExecutable, DWORD dwLen)
{
	if(!pe)
		return FALSE;

	pe->dwImageSizeOnDisk = dwLen;
	pe->dwImage = (DWORD) pExecutable;
	pe->bLoadFromBuffer = TRUE;

	return TRUE;
}

BOOL PeLdrSetExecutablePath(PE_LDR_PARAM *pe, TCHAR *pExecutable)
{
	if(!pe)
		return FALSE;

	pe->pTargetPath = (TCHAR*) HeapAlloc(GetProcessHeap(), 
		HEAP_ZERO_MEMORY, (lstrlen(pExecutable) + 1) * sizeof(TCHAR));
	if(!pe->pTargetPath) {
		DMSG("Failed to allocate memory for pTargetPath");
		return FALSE;
	}

	lstrcpy(pe->pTargetPath, pExecutable);
	return TRUE;
}

VOID PeLdrInit(PE_LDR_PARAM *pe)
{
	ZeroMemory(pe, sizeof(PE_LDR_PARAM));
}

================================================
FILE: src/PeLdr.h
================================================
#ifndef _PE_LDR_H
#define _PE_LDR_H

#include <windows.h>
#include <tchar.h>
#include <winnt.h>

typedef struct {
	TCHAR					*pTargetPath;
	PIMAGE_DOS_HEADER		pDosHeader;
	PIMAGE_NT_HEADERS		pNtHeaders;

	BOOLEAN					bLoadFromBuffer;
	DWORD					dwImage;
	DWORD					dwImageSizeOnDisk;

	DWORD					dwLoaderBase;
	DWORD					dwLoaderRelocatedBase;

	DWORD					dwMapBase;

} PE_LDR_PARAM;

VOID PeLdrInit(PE_LDR_PARAM *pe);
BOOL PeLdrSetExecutablePath(PE_LDR_PARAM *pe, TCHAR *pExecutable);
BOOL PeLdrSetExecutableBuffer(PE_LDR_PARAM *pe, PVOID pExecutable, DWORD dwLen);
BOOL PeLdrStart(PE_LDR_PARAM *pe);

#endif
Download .txt
gitextract_cjiu6xeh/

├── .gitattributes
├── .gitignore
├── Pe-Loader-Sample.vcproj
├── README.md
└── src/
    ├── Debug.h
    ├── Main.cpp
    ├── PEB.h
    ├── PeLdr.cpp
    └── PeLdr.h
Download .txt
SYMBOL INDEX (13 symbols across 4 files)

FILE: src/Main.cpp
  function INT (line 4) | static
  function wmain (line 14) | int wmain(int argc, wchar_t *argv[])

FILE: src/PEB.h
  type UNICODE_STR (line 6) | typedef struct _UNICODE_STR
  type LDR_DATA_TABLE_ENTRY (line 15) | typedef struct _LDR_DATA_TABLE_ENTRY
  type PEB_LDR_DATA (line 33) | typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
  type PEB_FREE_BLOCK (line 45) | typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
  type _PEB (line 53) | typedef struct __PEB // 65 elements, 0x210 bytes
  type IMAGE_RELOC (line 122) | typedef struct

FILE: src/PeLdr.cpp
  function BOOL (line 17) | static
  function BOOL (line 76) | static
  function BOOL (line 174) | static
  function BOOL (line 209) | static

FILE: src/PeLdr.h
  type PE_LDR_PARAM (line 8) | typedef struct {
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (30K chars).
[
  {
    "path": ".gitattributes",
    "chars": 483,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n*.sln"
  },
  {
    "path": ".gitignore",
    "chars": 2006,
    "preview": "\n#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/**\ntmp/**\ntmp/**/*\n*.tmp\n*.bak\n*."
  },
  {
    "path": "Pe-Loader-Sample.vcproj",
    "chars": 4053,
    "preview": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"9.00\"\n\tName=\"Pe-L"
  },
  {
    "path": "README.md",
    "chars": 826,
    "preview": "PE Loader Sample\n=================\n\nIn memory execution of PE executables:\n\n * Self Relocation\n * Memory Mapping\n * IAT "
  },
  {
    "path": "src/Debug.h",
    "chars": 332,
    "preview": "#ifndef _DEBUG_H\n#define _DEBUG_H\n\n#include <stdio.h>\n\n#define __DEBUG\n\n#ifdef __DEBUG\n#include <strsafe.h>\n#define DMSG"
  },
  {
    "path": "src/Main.cpp",
    "chars": 357,
    "preview": "#include \"PeLdr.h\"\n#include \"Debug.h\"\n\nstatic\nINT ShowUsage()\n{\n\tprintf(\"-- PE Loader Sample --\\n\\n\");\n\tprintf(\"PeLdr [P"
  },
  {
    "path": "src/PEB.h",
    "chars": 3701,
    "preview": "#ifndef _PEB_H\n#define _PEB_H\n\n// https://github.com/stephenfewer/ReflectiveDLLInjection\n//============================="
  },
  {
    "path": "src/PeLdr.cpp",
    "chars": 13873,
    "preview": "#include \"PeLdr.h\"\n#include \"Debug.h\"\n#include \"PEB.h\"\n\n#include <strsafe.h>\n\n#ifndef NTSTATUS\n#define NTSTATUS\tLONG\n#en"
  },
  {
    "path": "src/PeLdr.h",
    "chars": 609,
    "preview": "#ifndef _PE_LDR_H\n#define _PE_LDR_H\n\n#include <windows.h>\n#include <tchar.h>\n#include <winnt.h>\n\ntypedef struct {\n\tTCHAR"
  }
]

About this extraction

This page contains the full source code of the abhisek/Pe-Loader-Sample GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (25.6 KB), approximately 8.4k tokens, and a symbol index with 13 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!