-
-
Notifications
You must be signed in to change notification settings - Fork 362
/
VmmExample.java
267 lines (226 loc) · 11.2 KB
/
VmmExample.java
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
import vmm.*;
import vmm.entry.*;
import leechcore.*;
import leechcore.entry.LeechCoreBar;
import leechcore.entry.LeechCoreBarRequest;
import java.util.*;
/**
* MemProcFS example code how use the Java wrapper API for the native library.
* More functionality exists, please check the interfaces for more information.
* @see https://github.com/ufrisk/MemProcFS
* @author Ulf Frisk - pcileech@frizk.net
*/
public class VmmExample {
public static String strPathToNativeBinaries = "C:\\Github\\MemProcFS-dev\\files";
public static String[] argvMemProcFS = {"-device", "c:\\dumps\\WIN7-X64-SP1-1.pmem", "-printf", "-v"};
public static void main(String[] args) {
// Initialize VMM.DLL
// Arguments are as they are given on the command line.
// Also required is to specify the path to the native MemProcFS files.
// Important! remember to close the vmm object after use to free up native resources!
IVmm vmm = IVmm.initializeVmm(strPathToNativeBinaries, argvMemProcFS);
// Get/Set option
vmm.setConfig(IVmm.OPT_CORE_PRINTF_ENABLE, 1);
long build = vmm.getConfig(IVmm.OPT_WIN_VERSION_BUILD);
// VFS init / list / read / write
List<Vmm_VfsListEntry> vfs_directory_listing = vmm.vfsList("\\sys\\");
byte[] vfs_build_bytes = vmm.vfsRead("\\sys\\version-build.txt", 0, 10);
String vfs_build_string = vmm.vfsReadString("\\sys\\version-build.txt", 0, 10);
//vmm.vfsWrite("\\memory.pmem", vfs_build_bytes, 0);
// physical memory prefetch/read/write
long[] physmem_prefetch = {0x1000, 0x10000, 0x20000};
vmm.memPrefetchPages(physmem_prefetch);
byte[] physmem_read = vmm.memRead(0x1000, 0x100);
byte[] physmem_read_withflags = vmm.memRead(0x1000, 0x100, IVmm.FLAG_NOCACHE | IVmm.FLAG_ZEROPAD_ON_FAIL);
//vmm.memWrite(0x400, physmem_read);
// physical memory scatter efficient read/write
IVmmMemScatterMemory physMemScatter = vmm.memScatterInitialize(IVmm.FLAG_ZEROPAD_ON_FAIL);
physMemScatter.prepare(0x1000, 0x100);
physMemScatter.prepare(0x2000, 8);
physMemScatter.execute();
byte[] physmem_readscatter1 = physMemScatter.read(0x1000, 0x100);
byte[] physmem_readscatter2 = physMemScatter.read(0x2004, 4);
byte[] physmem_readscatter3 = physMemScatter.read(0x2000, 8);
physMemScatter.close();
// get core maps
List<VmmMap_MemMapEntry> maps_physmemmap = vmm.mapPhysicalMemory();
List<VmmMap_NetEntry> maps_net = vmm.mapNet();
List<VmmMap_UserEntry> maps_users = vmm.mapUser();
List<VmmMap_ServiceEntry> maps_services = vmm.mapService();
VmmMap_PoolMap maps_pool = vmm.mapPool(true); // retrieve big pool entries only (faster).
// get kernel info
IVmmProcess processKernel1 = vmm.kernelProcess();
IVmmPdb kernelPdb = vmm.kernelPdb();
int kernelBuildNumber = vmm.kernelBuildNumber();
// get processes
IVmmProcess processKernel2 = vmm.processGet(4);
IVmmProcess processExplorer = vmm.processGet("explorer.exe");
List<IVmmProcess> processAll = vmm.processGetAll();
// get process maps
VmmMap_HeapMap procmaps_heap = processExplorer.mapHeap();
List<VmmMap_HeapAllocEntry> procmaps_heapalloc = processExplorer.mapHeapAlloc(0);
List<VmmMap_HandleEntry> procmaps_handle = processExplorer.mapHandle();
List<VmmMap_PteEntry> procmaps_PTEs = processExplorer.mapPte();
List<VmmMap_ThreadEntry> procmaps_threads = processExplorer.mapThread();
List<VmmMap_UnloadedModuleEntry> procmaps_unloadedmodules = processExplorer.mapUnloadedModule();
List<VmmMap_VadEntry> procmaps_VADs = processExplorer.mapVad();
List<VmmMap_VadExEntry> procmaps_VADex = processExplorer.mapVadEx(0, 0x100);
// get module
List<IVmmModule> moduleExplorerAll = processExplorer.moduleGetAll(false); // retrieve without extended debug/version info.
IVmmModule moduleExplorerKernel32 = processExplorer.moduleGet("kernel32.dll", true); // retrieve with extended debug/version info.
// get some module info (additional info exists - check interface for more!)
String strModuleKernel32Full = moduleExplorerKernel32.getNameFull();
// get debug info and version info of kernel32.
// This requires that the module have been initialized with isExtendedInfo = true,
// but the call may still fail and return null if required memory is unreadable.
Vmm_ModuleExDebugInfo moduleExplorerKernel32_DebugInfo = moduleExplorerKernel32.getExDebugInfo();
Vmm_ModuleExVersionInfo moduleExplorerKernel32_VersionInfo = moduleExplorerKernel32.getExVersionInfo();
// get module maps for kernel32:
List<VmmMap_ModuleDataDirectory> moduleKernel32_DataDirectory = moduleExplorerKernel32.mapDataDirectory();
List<VmmMap_ModuleExport> moduleKernel32_Export = moduleExplorerKernel32.mapExport();
List<VmmMap_ModuleImport> moduleKernel32_Import = moduleExplorerKernel32.mapImport();
List<VmmMap_ModuleSection> moduleKernel32_Section = moduleExplorerKernel32.mapSection();
// pdb debug symbols for kernel and kernel32
IVmmPdb pdbKernel = vmm.kernelPdb();
IVmmPdb pdbKernel32 = moduleExplorerKernel32.getPdb();
long vaGetProcAddress = pdbKernel32.getSymbolAddress("GetProcAddress");
int cbEprocess = pdbKernel.getTypeSize("_EPROCESS");
int oEprocessToken = pdbKernel.getTypeChildOffset("_EPROCESS", "Token");
// registry
List<IVmmRegHive> reghives = vmm.regHive();
IVmmRegHive reghive = reghives.get(0);
IVmmRegKey regkey1 = reghive.getKeyRoot();
IVmmRegKey regkey2 = vmm.regKey("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
IVmmRegKey regkey3 = regkey2.getKeyParent();
Map<String, IVmmRegValue> regvalues = regkey2.getValues();
IVmmRegValue regvalue = vmm.regValue("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\VBoxTray");
// LeechCore is the underlying low-level memory acquisition library focusing
// on physical memory reads. It's possible to initialize LeechCore using
// arguments and/or retrieve the LeechCore from an existing Vmm instance.
// The LeechCore object should always be closed after completed usage.
{
// Example: LeechCore
// LeechCore is the underlying low-level memory acquisition library focusing
// on physical memory reads. It's possible to create it as stand-alone or as
// here retrieve it from an active Vmm instance.
ILeechCore lc = ILeechCore.initializeLeechCore(vmm);
// Example: LeechCore memory read:
byte[] lc_physmem_read = lc.memRead(0x1000, 0x100);
// Example: LeechCore get/set option:
// Use constants LC_OPT_* for these functions.
long lc_option_verbose_extra_pre = lc.getOption(ILeechCore.LC_OPT_CORE_VERBOSE_EXTRA);
lc.setOption(ILeechCore.LC_OPT_CORE_PRINTF_ENABLE, 1);
lc.setOption(ILeechCore.LC_OPT_CORE_VERBOSE_EXTRA, 1);
long lc_option_verbose_extra_post = lc.getOption(ILeechCore.LC_OPT_CORE_PRINTF_ENABLE);
// Example: LeechCore get/set memory map in use by LeechCore:
String lcMemoryMap = lc.getMemMap();
lc.setMemMap(lcMemoryMap);
// Example: LeechCore close and free up native resources.
lc.close();
}
vmm.close();
// Try FPGA devices examples (if possible).
lcExampleTestPCIeFPGA();
}
// The below examples showcase how LeechCore may be used if the underlying
// device is a PCIe FPGA board to send/receive PCIe TLPs and respond to
// PCIe BAR requests.
public static void lcExampleTestPCIeFPGA() {
ILeechCore lc = ILeechCore.initializeLeechCore(strPathToNativeBinaries, "fpga://");
// Example: retrieve information about the 6 PCIe BARs.
LeechCoreBar[] lcBarInfo = lc.getBarInfo();
// Example: register a PCIe BAR callback function. The callback will be
// called when the host system accesses a Base Address Register (BAR)
// of the PCIe FPGA device. The function should respond with a reply to
// each read request, whilst writes require no response.
BarCallback userBarCB = new BarCallback();
ILeechCoreBarContext ctxBar = lc.setPCIeBarCallback(userBarCB);
// Example: register a PCIe TLP callback function. The callback will be
// called for each PCIe TLP packet received.
// The context created must be kept alive or the callback will close.
// At most one callback per native LeechCore instance is possible.
// First instantiate our callback class. This instantiated object may
// also contain various user-defined states, such as tlpCallCount.
TlpCallback userTlpCB = new TlpCallback();
ILeechCoreTlpContext ctxTlp = lc.setPCIeTlpCallback(userTlpCB);
// Example: retrieve FPGA PCIe ID (bus:dev.fn)
// For getOption/setOption use option ids ILeechCore.LC_OPT_*.
long lcBusDevId = lc.getOption(ILeechCore.LC_OPT_FPGA_DEVICE_ID);
// Example: send a TLP. In this case the TLP is a memory read TLP that
// will read a page (0x1000 bytes) from physical address 0x1000. This
// will also be seen in the TLP callback function previously activated.
// The below TLP is not yet prepared with the device id in the form of
// bus:dev.fn (shown as 0x33, 0x33 below).
byte[] tlp = {0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x01, (byte)0xff, 0x00, 0x00, 0x10, 0x00};
tlp[4] = (byte)((lcBusDevId >> 8) & 0xff);
tlp[5] = (byte)(lcBusDevId & 0xff);
lc.writePCIeTLP(tlp);
// Sleep 10 seconds.
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {}
// Example: close the BAR callback
ctxBar.close();
// Example: close the TLP callback
ctxTlp.close();
// Example: close the LeechCore instance.
lc.close();
}
}
// User-defined callback class to receive TLP callbacks.
class TlpCallback implements ILeechCoreTlpCallback {
// The callback instance may contain state.
long tlpCallCount = 0;
// The callback function will be called for each received TLP.
@Override
public void LeechCoreTlpCallback(ILeechCore lc, byte[] tlpData, String tlpInfo) {
tlpCallCount++;
String str = "";
str += "------------------------------------------\n";
str += "PCIe TLP callback received:\n";
str += " callcount: " + tlpCallCount + "\n";
str += tlpInfo;
System.out.println(str);
}
}
//User-defined callback class to receive BAR callbacks.
class BarCallback implements ILeechCoreBarCallback {
// The callback instance may contain state.
long barCallCount = 0;
private static String toHex(byte[] data) {
StringBuilder hexString = new StringBuilder();
for(byte b : data) {
hexString.append(String.format("%02x ", b));
}
return hexString.toString();
}
// The callback function will be called for each BAR access.
// The below implements a small dummy BAR which responds with
// bytes depending on which address is read.
@Override
public void LeechCoreBarCallback(LeechCoreBarRequest req) {
barCallCount++;
String str = "";
str += "------------------------------------------\n";
str += "PCIe BAR request received:\n";
str += " callcount: " + barCallCount + "\n";
str += " type: " + (req.isRead ? "read" : "write") + "\n";
str += " bar: " + req.bar.iBar + "\n";
str += " offset: " + req.oData + "\n";
str += " length: " + req.cbData + "\n";
if(req.isWrite) {
str += " data_received: [" + toHex(req.pbDataWrite) + "]\n";
}
if(req.isRead) {
byte[] dataReply = new byte[req.cbData];
for(int i = 0; i < req.cbData; i++) {
dataReply[i] = (byte)(req.oData + i);
}
str += " data_reply: [" + toHex(dataReply) + "]\n";
// reply to a PCIe BAR request this way.
// length of dataReply must exactly match req.cbData.
req.reply.reply(dataReply);
}
System.out.println(str);
}
}