[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fgfOSctmiXzXItk65dXam21zJd52o-lEF5hWB2ARGYxI":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":33,"aiModel":30,"aiConfidence":30,"updatedAt":49,"createdAt":49,"_status":48},750,"What are the main steps to load a PE file into memory from a .NET application?","The process involves reading and parsing the PE file according to its format, allocating memory using `ImageBase` as the base address and `SizeOfImage` as length, then copying the PE header and sections into memory. The relocation table is processed to adjust addresses, the import table is parsed to load required DLLs, and finally execution jumps to the `AddressOfEntryPoint`. This technique builds on earlier methods for [loading .NET assemblies from memory](\u002Fnews\u002Fanalysis-of-exploitation-techniques-for-loading-net-assemblies-from-memory-assembly-load), but extends them to native PE files. More details can be found in the full article [Loading PE files into memory via .NET](\u002Fnews\u002Floading-pe-files-into-memory-via-net).","\u003Cp>The process involves reading and parsing the PE file according to its format, allocating memory using `ImageBase` as the base address and `SizeOfImage` as length, then copying the PE header and sections into memory. The relocation table is processed to adjust addresses, the import table is parsed to load required DLLs, and finally execution jumps to the `AddressOfEntryPoint`. This technique builds on earlier methods for [loading .NET assemblies from memory](\u002Fnews\u002Fanalysis-of-exploitation-techniques-for-loading-net-assemblies-from-memory-assembly-load), but extends them to native PE files. More details can be found in the full article [Loading PE files into memory via .NET](\u002Fnews\u002Floading-pe-files-into-memory-via-net).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Floading-pe-files-into-memory-via-net\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","what-are-the-main-steps-to-load-a-pe-file-into-memory-from-a-net-application-1777482156642","PE file, memory loading, .NET, import table, relocation table, AddressOfEntryPoint",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":27,"cover":30,"author":31,"views":19,"readingTime":32,"status":33,"publishedAt":34,"seo":35,"tags":39,"qaPairs":40,"meta":45,"updatedAt":46,"createdAt":47,"_status":48},185,"Loading PE files into memory via .NET","loading-pe-files-into-memory-via-net","Learn to load PE files into memory using C# with SharpPELoader. Exploit techniques, 32\u002F64-bit support, and Casey Smith's PELoader extension.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In previous articles 'Exploitation Analysis of Loading .NET Assemblies from Memory (execute-assembly)' and 'Exploitation Analysis of Loading .NET Assemblies from Memory (Assembly.Load)', methods for loading .NET assemblies from memory using C# were introduced. This time, we will go a step further to introduce methods for loading PE files from memory using C#.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Implementation Principles\u003C\u002Fli>\u003Cli>Casey Smith's open-source PELoader.cs\u003C\u002Fli>\u003Cli>Methods to extend PELoader.cs\u003C\u002Fli>\u003Cli>Implementation details of SharpPELoaderGenerater\u003C\u002Fli>\u003Cli>Exploitation methods\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Implementation Principles of Loading PE Files into Memory\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The implementation principles are as follows:\u003C\u002Fp>\u003Col>\u003Cli>Read the PE file and parse it according to the PE format\u003C\u002Fli>\u003Cli>Allocate memory, using ImageBase as the memory base address and SizeOfImage as the length\u003C\u002Fli>\u003Cli>Copy the PE file header into memory\u003C\u002Fli>\u003Cli>Parse the Section addresses and copy the Sections into memory\u003C\u002Fli>\u003Cli>Modify memory based on the relocation table\u003C\u002Fli>\u003Cli>Parse the import table and load the required DLLs\u003C\u002Fli>\u003Cli>Jump to the entry point AddressOfEntryPoint and execute the PE file\u003C\u002Fli>\u003C\u002Fol>\u003Ch2>0x03 Casey Smith's open-source PELoader.cs\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Currently available reference address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fre4lity\u002FsubTee-gits-backups\u002Fblob\u002Fmaster\u002FPELoader.cs\u003C\u002Fp>\u003Cp>This code can be compiled using csc.exe under .NET 4.0 or higher\u003C\u002Fp>\u003Cp>The compilation command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe \u002Funsafe PELoader.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The code implements loading 64-bit mimikatz.exe in memory\u003C\u002Fp>\u003Cp>PELoader.cs stores the encoded mimikatz.exe in the string KatzCompressed\u003C\u002Fp>\u003Cp>If you want to perform a replacement, you can refer to my code at the following address:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>After execution, the file base64.txt is generated. Use its content to replace the string KatzCompressed\u003C\u002Fp>\u003Ch2>0x04 Extending the methods of PELoader.cs\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>1. Adding support for compilation environments\u003C\u002Fp>\u003Cp>PELoader.cs uses .Add() which makes it incompatible with .Net 3.5. This can be replaced to support .Net 3.5\u003C\u002Fp>\u003Cp>2. Supporting 32-bit program loading\u003C\u002Fp>\u003Cp>It is necessary to distinguish between the PE structures of 32-bit and 64-bit programs and recalculate the offsets\u003C\u002Fp>\u003Cp>The extended PELoader.cs code has been uploaded to GitHub at the following address:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Corresponding to the code for loading 32-bit and 64-bit mimikatz in memory, respectively\u003C\u002Fp>\u003Cp>Supports .Net 3.5 and newer versions\u003C\u002Fp>\u003Cp>The compilation command for SharpMimikatz_x86.cs is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework\\v3.5\\csc.exe \u002Funsafe \u002Fplatform:x86 SharpMimikatz_x86.cs\u003Cbr>or\u003Cbr>C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe \u002Funsafe \u002Fplatform:x86 SharpMimikatz_x86.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The compilation command for SharpMimikatz_x64.cs is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework64\\v3.5\\csc.exe \u002Funsafe \u002Fplatform:x64 SharpMimikatz_x64.cs\u003Cbr>or\u003Cbr>C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe \u002Funsafe \u002Fplatform:x64 SharpMimikatz_x64.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x05 Implementation Details of SharpPELoaderGenerater\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Using Casey Smith's open-source PELoader.cs as a template, attempt to implement automatic generation of PE file loading templates in C#\u003C\u002Fp>\u003Cp>Here, taking SharpMimikatz_x64.cs as an example, the code can be divided into the following three parts:\u003C\u002Fp>\u003Col>\u003Cli>Front-end calling code\u003C\u002Fli>\u003Cli>Compressed string of the exe file\u003C\u002Fli>\u003Cli>Back-end calling code\u003C\u002Fli>\u003C\u002Fol>\u003Cp>The code generation method is as follows:\u003C\u002Fp>\u003Ch3>1. First half calling code\u003C\u002Fh3>\u003Cp>Since the first half calling code contains multiple escape characters, storing it directly in a string array is cumbersome. The approach here is to compress and encode the first half code before storing it in the string array, which also significantly reduces code length (from 31kb to 6kb).\u003C\u002Fp>\u003Cp>The first half code can be compressed using the following C# code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>using System.IO;\u003Cbr>using System.IO.Compression;\u003Cbr>\u003Cbr>namespace GenerateCode\u003Cbr>{\u003Cbr>    class Program\u003Cbr>    {\u003Cbr>        static byte[] Compress(byte[] raw)\u003Cbr>        {\u003Cbr>            using (MemoryStream memory = new MemoryStream())\u003Cbr>            {\u003Cbr>                using (GZipStream gzip = new GZipStream(memory,\u003Cbr>                CompressionMode.Compress, true))\u003Cbr>                {\u003Cbr>                    gzip.Write(raw, 0, raw.Length);\u003Cbr>                }\u003Cbr>                return memory.ToArray();\u003Cbr>            }\u003Cbr>        }\u003Cbr>        static void Main(string[] args)\u003Cbr>        {\u003Cbr>            byte[] AsBytes = File.ReadAllBytes(@\"SharpMimikatz_x86_part.cs\");\u003Cbr>            byte[] compress = Compress(AsBytes);\u003Cbr>            String AsBase64String = Convert.ToBase64String(compress);\u003Cbr>\u003Cbr>            StreamWriter sw = new StreamWriter(@\"SharpMimikatz_x86_part.txt\");\u003Cbr>            sw.Write(AsBase64String);\u003Cbr>            sw.Close();\u003Cbr>\u003Cbr>            byte[] AsBytes2 = File.ReadAllBytes(@\"SharpMimikatz_x64_part.cs\");\u003Cbr>            byte[] compress2 = Compress(AsBytes2);\u003Cbr>            String AsBase64String2 = Convert.ToBase64String(compress2);\u003Cbr>\u003Cbr>            StreamWriter sw2 = new StreamWriter(@\"SharpMimikatz_x64_part.txt\");\u003Cbr>            sw2.Write(AsBase64String2);\u003Cbr>            sw2.Close();\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After execution, files SharpMimikatz_x86_part.txt and SharpMimikatz_x64_part.txt are generated, containing the compressed and encoded first half of the calling code\u003C\u002Fp>\u003Ch3>The compressed string of the 2.exe file\u003C\u002Fh3>\u003Cp>Can be generated using the following code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>byte[] AsBytes = File.ReadAllBytes(@\"mimikatz.exe\");\u003Cbr>byte[] compress = Compress(AsBytes);\u003Cbr>string source = Convert.ToBase64String(compress);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>3. Call code for the latter part\u003C\u002Fh3>\u003Cp>Escape characters need to be used here\u003C\u002Fp>\u003Cp>Can be defined using the following code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>string source3_x86 = \"\\\\\";\\r\\n    }\\r\\n } \";\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>As a code generation template, it is also necessary to distinguish whether the exe is 32-bit or 64-bit. The judgment method is as follows:\u003C\u002Fp>\u003Cp>Through the Characteristics field in the IMAGE_FILE_HEADER structure, if the attribute IMAGE_FILE_32BIT_MACHINE exists, then the exe file is 32-bit\u003C\u002Fp>\u003Cp>The complete code has been uploaded to GitHub, address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Usage example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>SharpPELoaderGenerater.exe test.exe\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>If test.exe is a 32-bit program, the file SharpPELoader_x86.cs will be generated\u003C\u002Fp>\u003Cp>Compilation method:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework\\v3.5\\csc.exe \u002Funsafe \u002Fplatform:x86 SharpPELoader_x86.cs\u003Cbr>or\u003Cbr>C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe \u002Funsafe \u002Fplatform:x86 SharpPELoader_x86.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>If test.exe is a 64-bit program, it will generate the file SharpPELoader_x64.cs\u003C\u002Fp>\u003Cp>Compilation method:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework64\\v3.5\\csc.exe \u002Funsafe \u002Fplatform:x64 SharpPELoader_x64.cs\u003Cbr>or\u003Cbr>C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe \u002Funsafe \u002Fplatform:x64 SharpPELoader_x64.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Additional note:\u003C\u002Fp>\u003Cp>When writing test.exe in C++, it is necessary to manually add the DLLs that need to be called\u003C\u002Fp>\u003Cp>Example code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \"stdafx.h\"\u003Cbr>#include \u003Cwindows.h>\u003Cbr>#pragma comment(lib,\"User32.lib\")\u003Cbr>int main(int argc, char *argv[])\u003Cbr>{\u003Cbr>\tLoadLibrary(L\"User32.dll\");\u003Cbr>\tMessageBox(NULL, NULL, NULL, MB_OK);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Fwindows.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x06 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces methods for implementing in-memory PE file loading via .NET. Using Casey Smith's open-source PELoader.cs as a template, we developed the code generation tool SharpPELoaderGenerate and share key details to note during code development.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr",null,"Onedaysec",4,"published","2026-02-02T07:38:21.201Z",{"title":36,"description":14,"keywords":37,"ogImage":30,"canonicalUrl":30,"noIndex":38},"Load PE Files in Memory with C#: SharpPELoader & Exploitation","PE file loading, C# memory execution, .NET assembly, SharpPELoader, Casey Smith PELoader, exploit techniques, mimikatz, 32-bit 64-bit support",false,[],{"docs":41,"hasNextPage":38},[42,43,44,4],753,752,751,{"title":30,"description":30,"image":30},"2026-07-24T02:07:19.557Z","2026-07-23T16:02:03.129Z","draft","2026-07-23T16:14:31.370Z"]