[go: up one dir, main page]

Menu

[r76]: / procdump.py  Maximize  Restore  History

Download this file

100 lines (83 with data), 3.8 kB

 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
#!/usr/bin/env python
from struct import unpack
from pefile import PE
from memutil import virt2phys, PagedOutException, offsets, read_range
from hexutil import hd
def read_section(memdump,pdba,sect,img_base):
"""Read the contents of a PE section from memory. This must be done
a page at a time, as adjacent virtual memory addresses may reference
completely different areas of physical memory.
Arguments:
memdump - file pointer to the memory dump image
pdba - address of the page directory
sect - a Section object from pefile
img_base - the executable's base address (necessary to calculate
section offsets)
Returns: a string containing the contents of the section
"""
accum = ''
# DUBIOUS DECISION: should we read SizeOfRawData bytes or Misc_VirtualSize?
section_start = img_base + sect.VirtualAddress
section_end = img_base + sect.VirtualAddress + sect.SizeOfRawData
return read_range(memdump,pdba,section_start,section_end)
def reconstruct_PE(memdump,pe,pdba):
"""Rebuild an on-disk PE file from an image in memory.
Arguments:
memdump - a file pointer to the memory dump
pe - a PE object from pefile
pdba - the address of the page directory for this process
Returns: a string representing the executable
"""
img_base = pe.OPTIONAL_HEADER.ImageBase
rebuilt_exe = ''
# Add the pe header:
# Dubious decision: the PE header is in the first page at ImageBase
img_base_real = virt2phys(memdump,pdba,img_base)
memdump.seek(img_base_real)
rebuilt_exe += memdump.read(4096)
for sect in pe.sections:
print "DEBUG: Starting section %s" % sect.Name
section_data = read_section(memdump,pdba,sect,img_base)
# If there is a gap, fill it with zeroes
if sect.PointerToRawData > len(rebuilt_exe):
rebuilt_exe += '\0' * (sect.PointerToRawData - len(rebuilt_exe))
# If there is overlap, later section takes precedence, ie, truncate
elif sect.PointerToRawData < len(rebuilt_exe):
rebuilt_exe = rebuilt_exe[:sect.PointerToRawData]
rebuilt_exe += section_data
return rebuilt_exe
def unpack_le(str):
"""Silly helper function to convert 4 characters to a little-endian unsigned int"""
return unpack("<L", str)[0]
if __name__ == "__main__":
from general import parser
parser.add_option("-e", "--executable", dest="exename",
help="write reconstructed executable out to FILE [default: [EPROCESS].exe]",
metavar='FILE')
(options, args) = parser.parse_args()
if len(args) != 2:
import sys
parser.print_help()
sys.exit(1)
memdump = open(args[0], 'rb')
eproc_offset = int(args[1], 0)
offs = offsets[options.osname]
if options.exename:
output_file = open(options.exename, 'wb')
else:
output_file = open(str(eproc_offset) + '.exe', 'wb')
memdump.seek(eproc_offset)
eproc_struct = memdump.read(offs["EPROC_SIZE"])
pdba = unpack_le(eproc_struct[offs["PDBA_OFFSET"]:offs["PDBA_OFFSET"]+4])
peb_addr_virt = unpack_le(eproc_struct[offs["PEB_OFFSET"]:offs["PEB_OFFSET"]+4])
peb_addr_real = virt2phys(memdump, pdba, peb_addr_virt)
print "DEBUG: PEB found at %x (%x)" % (peb_addr_virt,peb_addr_real)
memdump.seek(peb_addr_real + offs["PEB_IMG_BASE"])
img_base_virt = unpack_le(memdump.read(4))
img_base_real = virt2phys(memdump, pdba, img_base_virt)
memdump.seek(img_base_real)
pe_page = memdump.read(4096)
pe = PE(data=pe_page, fast_load=True)
output_file.write(reconstruct_PE(memdump, pe, pdba))
output_file.close()
memdump.close()