SHOW:
|
|
- or go back to the newest paste.
1 | Imports System.IO | |
2 | Imports System.ComponentModel | |
3 | Imports System.Runtime.InteropServices | |
4 | ||
5 | '------------------ | |
6 | 'Creator: aeonhack | |
7 | 'Site: nimoru.com | |
8 | 'Created: 05/06/2014 | |
9 | 'Changed: 05/06/2014 | |
10 | 'Version: 1.0.0.0 | |
11 | '------------------ | |
12 | ||
13 | Public NotInheritable Class ExecutableReader | |
14 | Implements IDisposable | |
15 | ||
16 | #Region " Properties " | |
17 | ||
18 | Private _Is32Bit As Boolean | |
19 | ReadOnly Property Is32Bit() As Boolean | |
20 | Get | |
21 | Return _Is32Bit | |
22 | End Get | |
23 | End Property | |
24 | ||
25 | Private _DosHeader As Win32.IMAGE_DOS_HEADER | |
26 | ReadOnly Property DosHeader As Win32.IMAGE_DOS_HEADER | |
27 | Get | |
28 | Return _DosHeader | |
29 | End Get | |
30 | End Property | |
31 | ||
32 | Private _Signature As UInteger | |
33 | ReadOnly Property Signature As UInteger | |
34 | Get | |
35 | Return _Signature | |
36 | End Get | |
37 | End Property | |
38 | ||
39 | Private _FileHeader As Win32.IMAGE_FILE_HEADER | |
40 | ReadOnly Property FileHeader As Win32.IMAGE_FILE_HEADER | |
41 | Get | |
42 | Return _FileHeader | |
43 | End Get | |
44 | End Property | |
45 | ||
46 | Private _OptionalHeader32 As Win32.IMAGE_OPTIONAL_HEADER32 | |
47 | ReadOnly Property OptionalHeader32 As Win32.IMAGE_OPTIONAL_HEADER32 | |
48 | Get | |
49 | Return _OptionalHeader32 | |
50 | End Get | |
51 | End Property | |
52 | ||
53 | Private _OptionalHeader64 As Win32.IMAGE_OPTIONAL_HEADER64 | |
54 | ReadOnly Property OptionalHeader64 As Win32.IMAGE_OPTIONAL_HEADER64 | |
55 | Get | |
56 | Return _OptionalHeader64 | |
57 | End Get | |
58 | End Property | |
59 | ||
60 | Private _DataDirectory As Win32.IMAGE_DATA_DIRECTORY() | |
61 | ReadOnly Property DataDirectory As Win32.IMAGE_DATA_DIRECTORY() | |
62 | Get | |
63 | Return _DataDirectory | |
64 | End Get | |
65 | End Property | |
66 | ||
67 | Private _SectionHeaders As Win32.IMAGE_SECTION_HEADER() | |
68 | ReadOnly Property SectionHeaders() As Win32.IMAGE_SECTION_HEADER() | |
69 | Get | |
70 | Return _SectionHeaders | |
71 | End Get | |
72 | End Property | |
73 | ||
74 | Private _IsDisposed As Boolean | |
75 | ReadOnly Property IsDisposed As Boolean | |
76 | Get | |
77 | Return _IsDisposed | |
78 | End Get | |
79 | End Property | |
80 | ||
81 | Private _IsLoaded As Boolean | |
82 | ReadOnly Property IsLoaded As Boolean | |
83 | Get | |
84 | Return _IsLoaded | |
85 | End Get | |
86 | End Property | |
87 | ||
88 | #End Region | |
89 | ||
90 | ||
91 | #Region " Constants " | |
92 | ||
93 | Private Const PROCESS_VM_OPERATION As Integer = 8 | |
94 | Private Const PROCESS_VM_READ As Integer = 16 | |
95 | ||
96 | Private Const PAGE_NOACCESS As Integer = 1 | |
97 | Private Const PAGE_EXECUTE_READWRITE As Integer = 64 | |
98 | ||
99 | #End Region | |
100 | ||
101 | ||
102 | #Region " Members " | |
103 | ||
104 | Private _IsRuntime As Boolean | |
105 | ||
106 | Private _ProcessHandle As IntPtr | |
107 | Private _FileStream As FileStream | |
108 | ||
109 | Private _Address As IntPtr | |
110 | Private _BaseAddress As IntPtr | |
111 | ||
112 | #End Region | |
113 | ||
114 | ||
115 | #Region " Initialization " | |
116 | ||
117 | Public Sub LoadFromProcess(process As Process) | |
118 | ThrowOnDisposed() | |
119 | ThrowOnLoaded() | |
120 | ||
121 | _IsLoaded = True | |
122 | _IsRuntime = True | |
123 | ||
124 | _BaseAddress = process.MainModule.BaseAddress | |
125 | _Address = _BaseAddress | |
126 | ||
127 | _ProcessHandle = Win32.OpenProcess(PROCESS_VM_READ Or PROCESS_VM_OPERATION, False, process.Id) | |
128 | ||
129 | If _ProcessHandle = IntPtr.Zero Then | |
130 | Throw New Win32Exception(Marshal.GetLastWin32Error()) | |
131 | End If | |
132 | ||
133 | ProcessExecutable() | |
134 | End Sub | |
135 | ||
136 | Public Sub LoadFromFile(fileName As String) | |
137 | ThrowOnDisposed() | |
138 | ThrowOnLoaded() | |
139 | ||
140 | _IsLoaded = True | |
141 | _FileStream = File.OpenRead(fileName) | |
142 | ||
143 | ProcessExecutable() | |
144 | End Sub | |
145 | ||
146 | #End Region | |
147 | ||
148 | ||
149 | #Region " Processing " | |
150 | ||
151 | Private Sub ProcessExecutable() | |
152 | _DosHeader = Read(Of Win32.IMAGE_DOS_HEADER)() | |
153 | Seek(_DosHeader.e_lfanew) | |
154 | ||
155 | _Signature = Read(Of UInteger)() | |
156 | _FileHeader = Read(Of Win32.IMAGE_FILE_HEADER)() | |
157 | _Is32Bit = (_FileHeader.Machine = 332) | |
158 | ||
159 | If _Is32Bit Then | |
160 | _OptionalHeader32 = Read(Of Win32.IMAGE_OPTIONAL_HEADER32)() | |
161 | Else | |
162 | _OptionalHeader64 = Read(Of Win32.IMAGE_OPTIONAL_HEADER64)() | |
163 | End If | |
164 | ||
165 | _DataDirectory = New Win32.IMAGE_DATA_DIRECTORY(16 - 1) {} | |
166 | For I As Integer = 0 To _DataDirectory.Length - 1 | |
167 | _DataDirectory(I) = Read(Of Win32.IMAGE_DATA_DIRECTORY)() | |
168 | Next | |
169 | ||
170 | SeekToSectionHeaders() | |
171 | ||
172 | _SectionHeaders = New Win32.IMAGE_SECTION_HEADER(_FileHeader.NumberOfSections - 1) {} | |
173 | For I As Integer = 0 To _FileHeader.NumberOfSections - 1 | |
174 | _SectionHeaders(I) = Read(Of Win32.IMAGE_SECTION_HEADER)() | |
175 | Next | |
176 | End Sub | |
177 | ||
178 | Private Function Read(Of T As Structure)() As T | |
179 | Dim Data As Byte() = Read(Marshal.SizeOf(GetType(T))) | |
180 | ||
181 | Dim Item As New T() | |
182 | Dim Handle As IntPtr = Marshal.AllocCoTaskMem(Data.Length) | |
183 | ||
184 | Marshal.Copy(Data, 0, Handle, Data.Length) | |
185 | Item = DirectCast(Marshal.PtrToStructure(Handle, GetType(T)), T) | |
186 | Marshal.FreeCoTaskMem(Handle) | |
187 | ||
188 | Return Item | |
189 | End Function | |
190 | ||
191 | Private Function Read(length As Integer) As Byte() | |
192 | Dim Data(length - 1) As Byte | |
193 | ||
194 | If _IsRuntime Then | |
195 | Dim BytesRead As Integer | |
196 | ||
197 | If Not Win32.ReadProcessMemory(_ProcessHandle, _Address, Data, Data.Length, BytesRead) Then | |
198 | Throw New Win32Exception(Marshal.GetLastWin32Error()) | |
199 | End If | |
200 | ||
201 | _Address = New IntPtr(_Address.ToInt64() + Data.Length) | |
202 | Else | |
203 | _FileStream.Read(Data, 0, Data.Length) | |
204 | End If | |
205 | ||
206 | Return Data | |
207 | End Function | |
208 | ||
209 | Private Sub Seek(offset As Integer) | |
210 | If _IsRuntime Then | |
211 | _Address = New IntPtr(_BaseAddress.ToInt64() + offset) | |
212 | Else | |
213 | _FileStream.Seek(offset, SeekOrigin.Begin) | |
214 | End If | |
215 | End Sub | |
216 | ||
217 | Private Sub SeekToSectionHeaders() | |
218 | Dim Offset As Integer = _DosHeader.e_lfanew | |
219 | ||
220 | Offset += Marshal.SizeOf(_Signature) | |
221 | Offset += Marshal.SizeOf(_FileHeader) | |
222 | Offset += _FileHeader.SizeOfOptionalHeader | |
223 | ||
224 | Seek(Offset) | |
225 | End Sub | |
226 | ||
227 | #End Region | |
228 | ||
229 | ||
230 | #Region " Extraction " | |
231 | ||
232 | Public Function DumpSection(sectionHeader As Win32.IMAGE_SECTION_HEADER) As Byte() | |
233 | ThrowOnDisposed() | |
234 | ThrowOnNotLoaded() | |
235 | ||
236 | If _IsRuntime Then | |
237 | Seek(sectionHeader.VirtualAddress) | |
238 | Else | |
239 | Seek(sectionHeader.PointerToRawData) | |
240 | End If | |
241 | ||
242 | Return GetDump(sectionHeader.VirtualSize) | |
243 | End Function | |
244 | ||
245 | Public Function DumpDataDirectory(dataDirectory As Win32.IMAGE_DATA_DIRECTORY) As Byte() | |
246 | ThrowOnDisposed() | |
247 | ThrowOnNotLoaded() | |
248 | ||
249 | If dataDirectory.VirtualAddress = 0 Then | |
250 | Return New Byte() {} | |
251 | End If | |
252 | ||
253 | If _IsRuntime Then | |
254 | Seek(dataDirectory.VirtualAddress) | |
255 | Else | |
256 | Seek(GetPointerToRawData(dataDirectory.VirtualAddress)) | |
257 | End If | |
258 | ||
259 | Return GetDump(dataDirectory.Size) | |
260 | End Function | |
261 | ||
262 | Public Function DumpUnmappedData() As Byte() | |
263 | ThrowOnDisposed() | |
264 | ThrowOnNotLoaded() | |
265 | ||
266 | If _IsRuntime Then | |
267 | Return New Byte() {} | |
268 | Else | |
269 | Dim HighestOffset As Integer | |
270 | ||
271 | For Each Section As Win32.IMAGE_SECTION_HEADER In _SectionHeaders | |
272 | If Section.PointerToRawData + Section.SizeOfRawData > HighestOffset Then | |
273 | HighestOffset = Section.PointerToRawData + Section.SizeOfRawData | |
274 | End If | |
275 | Next | |
276 | ||
277 | For Each Directory As Win32.IMAGE_DATA_DIRECTORY In _DataDirectory | |
278 | Dim PointerToRawData As Integer = GetPointerToRawData(Directory.VirtualAddress) | |
279 | ||
280 | If PointerToRawData + Directory.Size > HighestOffset Then | |
281 | HighestOffset = PointerToRawData + Directory.Size | |
282 | End If | |
283 | Next | |
284 | ||
285 | Seek(HighestOffset) | |
286 | ||
287 | Return Read(CInt(_FileStream.Length) - HighestOffset) | |
288 | End If | |
289 | End Function | |
290 | ||
291 | Private Function GetPointerToRawData(virtualAddress As Integer) As Integer | |
292 | For Each Section As Win32.IMAGE_SECTION_HEADER In _SectionHeaders | |
293 | If (virtualAddress < Section.VirtualAddress) OrElse (virtualAddress > (Section.VirtualAddress + Section.SizeOfRawData)) Then | |
294 | Continue For | |
295 | End If | |
296 | ||
297 | Return Section.PointerToRawData + (virtualAddress - Section.VirtualAddress) | |
298 | Next | |
299 | ||
300 | Return -1 | |
301 | End Function | |
302 | ||
303 | Private Function GetDump(size As Integer) As Byte() | |
304 | If size = 0 Then | |
305 | Return New Byte() {} | |
306 | End If | |
307 | ||
308 | Dim Address As IntPtr = _Address | |
309 | Dim Protection As Integer = SetMemProtection(Address, size, PAGE_EXECUTE_READWRITE) | |
310 | ||
311 | If Protection = -1 Then | |
312 | Return New Byte() {} | |
313 | End If | |
314 | ||
315 | Dim Data As Byte() = Read(size) | |
316 | SetMemProtection(Address, size, Protection) | |
317 | ||
318 | Return Data | |
319 | End Function | |
320 | ||
321 | Private Function SetMemProtection(address As IntPtr, size As Integer, protection As Integer) As Integer | |
322 | If Not _IsRuntime Then Return 0 | |
323 | ||
324 | Dim OldProtection As Integer | |
325 | ||
326 | If Win32.VirtualProtectEx(_ProcessHandle, address, size, protection, OldProtection) = 0 Then | |
327 | If OldProtection = PAGE_NOACCESS Then | |
328 | Return -1 | |
329 | Else | |
330 | Throw New Win32Exception(Marshal.GetLastWin32Error()) | |
331 | End If | |
332 | End If | |
333 | ||
334 | Return OldProtection | |
335 | End Function | |
336 | ||
337 | #End Region | |
338 | ||
339 | ||
340 | #Region " State Handling " | |
341 | ||
342 | Private Sub ThrowOnDisposed() | |
343 | If _IsDisposed Then | |
344 | Throw New ObjectDisposedException([GetType]().FullName) | |
345 | End If | |
346 | End Sub | |
347 | ||
348 | Private Sub ThrowOnLoaded() | |
349 | If _IsLoaded Then | |
350 | Throw New Exception("An executable has already been loaded.") | |
351 | End If | |
352 | End Sub | |
353 | ||
354 | Private Sub ThrowOnNotLoaded() | |
355 | If Not _IsLoaded Then | |
356 | Throw New Exception("No executable has been loaded.") | |
357 | End If | |
358 | End Sub | |
359 | ||
360 | #End Region | |
361 | ||
362 | ||
363 | #Region " IDisposable " | |
364 | ||
365 | Protected Sub Dispose(disposing As Boolean) | |
366 | If Not _IsDisposed Then | |
367 | If disposing Then | |
368 | ||
369 | If _FileStream IsNot Nothing Then | |
370 | _FileStream.Close() | |
371 | End If | |
372 | ||
373 | End If | |
374 | ||
375 | Win32.CloseHandle(_ProcessHandle) | |
376 | End If | |
377 | ||
378 | _IsDisposed = True | |
379 | End Sub | |
380 | ||
381 | Protected Overrides Sub Finalize() | |
382 | Dispose(False) | |
383 | MyBase.Finalize() | |
384 | End Sub | |
385 | ||
386 | Public Sub Dispose() Implements IDisposable.Dispose | |
387 | Dispose(True) | |
388 | GC.SuppressFinalize(Me) | |
389 | End Sub | |
390 | ||
391 | Public Sub Close() | |
392 | Dispose() | |
393 | End Sub | |
394 | ||
395 | #End Region | |
396 | ||
397 | End Class | |
398 | ||
399 | Public NotInheritable Class Win32 | |
400 | ||
401 | #Region " Methods " | |
402 | ||
403 | <DllImport("kernel32.dll", EntryPoint:="OpenProcess", SetLastError:=True)> _ | |
404 | Public Shared Function OpenProcess( _ | |
405 | ByVal access As Integer, _ | |
406 | ByVal inherit As Boolean, _ | |
407 | ByVal processId As Integer) As IntPtr | |
408 | End Function | |
409 | ||
410 | <DllImport("kernel32.dll", EntryPoint:="VirtualProtectEx", SetLastError:=True)> _ | |
411 | Public Shared Function VirtualProtectEx( _ | |
412 | ByVal handle As IntPtr, _ | |
413 | ByVal address As IntPtr, _ | |
414 | ByVal size As Integer, _ | |
415 | ByVal newProtection As Integer, _ | |
416 | ByRef oldProtection As Integer) As Integer | |
417 | End Function | |
418 | ||
419 | <DllImport("kernel32.dll", EntryPoint:="ReadProcessMemory", SetLastError:=True)> _ | |
420 | Public Shared Function ReadProcessMemory( _ | |
421 | ByVal handle As IntPtr, _ | |
422 | ByVal address As IntPtr, _ | |
423 | ByVal data As Byte(), _ | |
424 | ByVal dataLength As Integer, _ | |
425 | ByRef length As Integer) As Boolean | |
426 | End Function | |
427 | ||
428 | <DllImport("kernel32.dll", EntryPoint:="CloseHandle")> _ | |
429 | Public Shared Function CloseHandle( _ | |
430 | ByVal handle As IntPtr) As Boolean | |
431 | End Function | |
432 | ||
433 | #End Region | |
434 | ||
435 | #Region " Structures " | |
436 | ||
437 | <StructLayout(LayoutKind.Sequential, Pack:=1)> _ | |
438 | Public Structure IMAGE_DOS_HEADER | |
439 | Public e_magic As UShort | |
440 | Public e_cblp As UShort | |
441 | Public e_cp As UShort | |
442 | Public e_crlc As UShort | |
443 | Public e_cparhdr As UShort | |
444 | Public e_minalloc As UShort | |
445 | Public e_maxalloc As UShort | |
446 | Public e_ss As UShort | |
447 | Public e_sp As UShort | |
448 | Public e_csum As UShort | |
449 | Public e_ip As UShort | |
450 | Public e_cs As UShort | |
451 | Public e_lfarlc As UShort | |
452 | Public e_ovno As UShort | |
453 | <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ | |
454 | Public e_res As UShort() | |
455 | Public e_oemid As UShort | |
456 | Public e_oeminfo As UShort | |
457 | <MarshalAs(UnmanagedType.ByValArray, SizeConst:=10)> _ | |
458 | Public e_res2 As UShort() | |
459 | Public e_lfanew As Integer 'NOTE: Should be unsigned | |
460 | End Structure | |
461 | ||
462 | <StructLayout(LayoutKind.Sequential, Pack:=1)> _ | |
463 | Public Structure IMAGE_FILE_HEADER | |
464 | Public Machine As UShort | |
465 | Public NumberOfSections As UShort | |
466 | Public TimeDateStamp As Integer | |
467 | Public PointerToSymbolTable As Integer | |
468 | Public NumberOfSymbols As Integer | |
469 | Public SizeOfOptionalHeader As UShort | |
470 | Public Characteristics As UShort | |
471 | End Structure | |
472 | ||
473 | <StructLayout(LayoutKind.Sequential, Pack:=1)> _ | |
474 | Public Structure IMAGE_OPTIONAL_HEADER32 | |
475 | Public Magic As UShort | |
476 | Public MajorLinkerVersion As Byte | |
477 | Public MinorLinkerVersion As Byte | |
478 | Public SizeOfCode As Integer | |
479 | Public SizeOfInitializedData As Integer | |
480 | Public SizeOfUninitializedData As Integer | |
481 | Public AddressOfEntryPoint As Integer | |
482 | Public BaseOfCode As Integer | |
483 | Public BaseOfData As Integer | |
484 | Public ImageBase As Integer | |
485 | Public SectionAlignment As Integer | |
486 | Public FileAlignment As Integer | |
487 | Public MajorOperatingSystemVersion As UShort | |
488 | Public MinorOperatingSystemVersion As UShort | |
489 | Public MajorImageVersion As UShort | |
490 | Public MinorImageVersion As UShort | |
491 | Public MajorSubsystemVersion As UShort | |
492 | Public MinorSubsystemVersion As UShort | |
493 | Public Win32VersionValue As Integer | |
494 | Public SizeOfImage As Integer | |
495 | Public SizeOfHeaders As Integer | |
496 | Public CheckSum As Integer | |
497 | Public Subsystem As UShort | |
498 | Public DllCharacteristics As UShort | |
499 | Public SizeOfStackReserve As Integer | |
500 | Public SizeOfStackCommit As Integer | |
501 | Public SizeOfHeapReserve As Integer | |
502 | Public SizeOfHeapCommit As Integer | |
503 | Public LoaderFlags As Integer | |
504 | Public NumberOfRvaAndSizes As Integer | |
505 | End Structure | |
506 | ||
507 | <StructLayout(LayoutKind.Sequential, Pack:=1)> _ | |
508 | Public Structure IMAGE_OPTIONAL_HEADER64 | |
509 | Public Magic As UShort | |
510 | Public MajorLinkerVersion As Byte | |
511 | Public MinorLinkerVersion As Byte | |
512 | Public SizeOfCode As Integer | |
513 | Public SizeOfInitializedData As Integer | |
514 | Public SizeOfUninitializedData As Integer | |
515 | Public AddressOfEntryPoint As Integer | |
516 | Public BaseOfCode As Integer | |
517 | Public ImageBase As Long | |
518 | Public SectionAlignment As Integer | |
519 | Public FileAlignment As Integer | |
520 | Public MajorOperatingSystemVersion As UShort | |
521 | Public MinorOperatingSystemVersion As UShort | |
522 | Public MajorImageVersion As UShort | |
523 | Public MinorImageVersion As UShort | |
524 | Public MajorSubsystemVersion As UShort | |
525 | Public MinorSubsystemVersion As UShort | |
526 | Public Win32VersionValue As Integer | |
527 | Public SizeOfImage As Integer | |
528 | Public SizeOfHeaders As Integer | |
529 | Public CheckSum As Integer | |
530 | Public Subsystem As UShort | |
531 | Public DllCharacteristics As UShort | |
532 | Public SizeOfStackReserve As Long | |
533 | Public SizeOfStackCommit As Long | |
534 | Public SizeOfHeapReserve As Long | |
535 | Public SizeOfHeapCommit As Long | |
536 | Public LoaderFlags As Integer | |
537 | Public NumberOfRvaAndSizes As Integer | |
538 | End Structure | |
539 | ||
540 | <StructLayout(LayoutKind.Sequential, Pack:=1)> _ | |
541 | Public Structure IMAGE_DATA_DIRECTORY | |
542 | Public VirtualAddress As Integer | |
543 | Public Size As Integer | |
544 | End Structure | |
545 | ||
546 | <StructLayout(LayoutKind.Sequential, Pack:=1)> _ | |
547 | Public Structure IMAGE_SECTION_HEADER | |
548 | <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)> _ | |
549 | Public Name As String | |
550 | Public VirtualSize As Integer 'NOTE: Alias of Misc | |
551 | Public VirtualAddress As Integer | |
552 | Public SizeOfRawData As Integer | |
553 | Public PointerToRawData As Integer | |
554 | Public PointerToRelocations As Integer | |
555 | Public PointerToLineNumbers As Integer | |
556 | Public NumberOfRelocations As UShort | |
557 | Public NumberOfLineNumbers As UShort | |
558 | Public Characteristics As Integer | |
559 | End Structure | |
560 | ||
561 | #End Region | |
562 | ||
563 | ||
564 | End Class |