0x00 Preface
---
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#.
0x01 Introduction
---
This article will cover the following:
- Implementation Principles
- Casey Smith's open-source PELoader.cs
- Methods to extend PELoader.cs
- Implementation details of SharpPELoaderGenerater
- Exploitation methods
0x02 Implementation Principles of Loading PE Files into Memory
---
The implementation principles are as follows:
- Read the PE file and parse it according to the PE format
- Allocate memory, using ImageBase as the memory base address and SizeOfImage as the length
- Copy the PE file header into memory
- Parse the Section addresses and copy the Sections into memory
- Modify memory based on the relocation table
- Parse the import table and load the required DLLs
- Jump to the entry point AddressOfEntryPoint and execute the PE file
0x03 Casey Smith's open-source PELoader.cs
---
Currently available reference address:
https://github.com/re4lity/subTee-gits-backups/blob/master/PELoader.cs
This code can be compiled using csc.exe under .NET 4.0 or higher
The compilation command is as follows:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /unsafe PELoader.cs |
The code implements loading 64-bit mimikatz.exe in memory
PELoader.cs stores the encoded mimikatz.exe in the string KatzCompressed
If you want to perform a replacement, you can refer to my code at the following address:
An open-source project
After execution, the file base64.txt is generated. Use its content to replace the string KatzCompressed
0x04 Extending the methods of PELoader.cs
---
1. Adding support for compilation environments
PELoader.cs uses .Add() which makes it incompatible with .Net 3.5. This can be replaced to support .Net 3.5
2. Supporting 32-bit program loading
It is necessary to distinguish between the PE structures of 32-bit and 64-bit programs and recalculate the offsets
The extended PELoader.cs code has been uploaded to GitHub at the following address:
An open-source project
An open-source project
Corresponding to the code for loading 32-bit and 64-bit mimikatz in memory, respectively
Supports .Net 3.5 and newer versions
The compilation command for SharpMimikatz_x86.cs is as follows:
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe /unsafe /platform:x86 SharpMimikatz_x86.cs |
The compilation command for SharpMimikatz_x64.cs is as follows:
C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe /unsafe /platform:x64 SharpMimikatz_x64.cs |
0x05 Implementation Details of SharpPELoaderGenerater
---
Using Casey Smith's open-source PELoader.cs as a template, attempt to implement automatic generation of PE file loading templates in C#
Here, taking SharpMimikatz_x64.cs as an example, the code can be divided into the following three parts:
- Front-end calling code
- Compressed string of the exe file
- Back-end calling code
The code generation method is as follows:
1. First half calling code
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).
The first half code can be compressed using the following C# code:
using System; |
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
The compressed string of the 2.exe file
Can be generated using the following code:
byte[] AsBytes = File.ReadAllBytes(@"mimikatz.exe"); |
3. Call code for the latter part
Escape characters need to be used here
Can be defined using the following code:
string source3_x86 = "\\";\r\n }\r\n } "; |
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:
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
The complete code has been uploaded to GitHub, address as follows:
An open-source project
Usage example:
SharpPELoaderGenerater.exe test.exe |
If test.exe is a 32-bit program, the file SharpPELoader_x86.cs will be generated
Compilation method:
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe /unsafe /platform:x86 SharpPELoader_x86.cs |
If test.exe is a 64-bit program, it will generate the file SharpPELoader_x64.cs
Compilation method:
C:\Windows\Microsoft.NET\Framework64\v3.5\csc.exe /unsafe /platform:x64 SharpPELoader_x64.cs |
Additional note:
When writing test.exe in C++, it is necessary to manually add the DLLs that need to be called
Example code is as follows:
#include "stdafx.h" |
0x06 Summary
---
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.