1
1
import os
2
+ from struct import pack
2
3
from volatility import debug , utils
3
4
from volatility .plugins .linux .auto_dtblist import linux_auto_dtblist
4
5
@@ -14,10 +15,10 @@ def __init__(self, config, *args, **kwargs):
14
15
help = "Starting virtual address to dump" )
15
16
self ._config .add_option ('VA-END' , short_option = 'e' , type = 'int' , default = None ,
16
17
help = "Ending virtual address to dump" )
17
- self ._config .add_option ('OUTPUTFILE ' , short_option = 'O' , default = None ,
18
+ self ._config .add_option ('DUMP-FILE ' , short_option = 'O' , default = None ,
18
19
help = "Output file to write a dump of virtual address space to" )
19
20
self ._config .add_option ('DUMP-DIR' , short_option = 'D' , default = None ,
20
- help = "Directory to write the output files to" )
21
+ help = "Directory to write the dump files to" )
21
22
22
23
def _parse_address (self , addr ):
23
24
if addr [:2 ].lower () == '0x' : # hexadecimal
@@ -28,6 +29,27 @@ def _parse_address(self, addr):
28
29
radix = 10
29
30
return int (addr , radix )
30
31
32
+ def _process_name (self , dtb ):
33
+ """Returns the name of a process associated with the given dtb."""
34
+ return "DTB_{0:#010x}" .format (dtb )
35
+
36
+ def _process_dump_filepath (self , dtb ):
37
+ dump_dir = self ._config .DUMP_DIR
38
+ if not dump_dir :
39
+ debug .error ("Dump directory is not specified." )
40
+ process_name = self ._process_name (dtb )
41
+ dump_filepath = os .path .join (dump_dir , '{0}.bin' .format (process_name ))
42
+ if not os .path .exists (dump_filepath ):
43
+ return dump_filepath
44
+ # The dump file path is already exist. It means that there are more
45
+ # than one process named 'process_name'.
46
+ name_id = 0
47
+ while True :
48
+ dump_filepath = os .path .join (dump_dir , '{0}_{1}.bin' .format (process_name , name_id ))
49
+ if not os .path .exists (dump_filepath ):
50
+ return dump_filepath
51
+ name_id += 1
52
+
31
53
def calculate (self ):
32
54
if self ._config .PROC_DTB :
33
55
process_dtblist = []
@@ -61,10 +83,10 @@ def calculate(self):
61
83
yield process_dtb , vaddr , page
62
84
63
85
def render_text (self , outfd , data ):
64
- output_file = self ._config .OUTPUTFILE
86
+ dump_file = self ._config .DUMP_FILE
65
87
dump_dir = self ._config .DUMP_DIR
66
- if not output_file and not dump_dir :
67
- debug .error ("Please specify an output file (use option --outputfile )"
88
+ if not dump_file and not dump_dir :
89
+ debug .error ("Please specify an output file (use option --dump-file )"
68
90
" or a dump directory (use option --dump-dir)." )
69
91
if dump_dir and not os .path .isdir (dump_dir ):
70
92
debug .error ("'{0}' is not a directory." .format (self ._config .DUMP_DIR ))
@@ -74,13 +96,15 @@ def render_text(self, outfd, data):
74
96
vaddr_start = None
75
97
vaddr_end = None
76
98
cur_process_dtb = None
77
- # Dump all processes to a single file (OUTPUTFILE) if DUMP_DIR is not specified.
78
- dump_fd = open (output_file , 'wb' ) if not dump_dir else None
99
+ # Dump all processes to a single file (DUMP_FILE) if DUMP_DIR is not specified.
100
+ dump_fd = open (dump_file , 'wb' ) if not dump_dir else None
101
+ index_fd = IndexFile ('{0}.index' .format (dump_file )) if not dump_dir else None
79
102
for process_dtb , vaddr , page in data :
80
103
if process_dtb != cur_process_dtb :
81
- # Print the last range of virtual addresses of the previous process
104
+ # Write the last range of virtual addresses of the previous process
82
105
if vaddr_start is not None :
83
106
self .table_row (outfd , cur_process_dtb , vaddr_start , vaddr_end )
107
+ index_fd .write_range (vaddr_start , vaddr_end )
84
108
vaddr_start = None
85
109
vaddr_end = None
86
110
cur_process_dtb = process_dtb
@@ -89,18 +113,46 @@ def render_text(self, outfd, data):
89
113
# next process.
90
114
if dump_fd :
91
115
dump_fd .close ()
92
- output_file = os .path .join (dump_dir , "{0:#010x}" .format (process_dtb ))
93
- dump_fd = open (output_file , 'wb' )
116
+ index_fd .close ()
117
+ dump_file = os .path .join (self ._process_dump_filepath (process_dtb ))
118
+ index_file = '{0}.index' .format (dump_file )
119
+ dump_fd = open (dump_file , 'wb' )
120
+ index_fd = IndexFile (index_file )
94
121
if vaddr == vaddr_end :
95
122
vaddr_end += len (page )
96
123
else :
97
124
if vaddr_start is not None :
98
125
self .table_row (outfd , process_dtb , vaddr_start , vaddr_end )
126
+ index_fd .write_range (vaddr_start , vaddr_end )
99
127
vaddr_start = vaddr
100
128
vaddr_end = vaddr + len (page )
101
129
dump_fd .write (page )
102
- # Print the last range of virtual addresses
130
+ # Write the last range of virtual addresses
103
131
if vaddr_start is not None :
104
132
self .table_row (outfd , process_dtb , vaddr_start , vaddr_end )
133
+ index_fd .write_range (vaddr_start , vaddr_end )
105
134
if dump_fd :
106
- dump_fd .close ()
135
+ dump_fd .close ()
136
+ index_fd .close ()
137
+
138
+
139
+ class IndexFile (object ):
140
+ """Used to describe virtual address ranges that are stored in a dump file."""
141
+ def __init__ (self , filepath ):
142
+ self .fd = open (filepath , 'wb' )
143
+ self .offset = 0
144
+
145
+ def write_range (self , vaddr_start , vaddr_end ):
146
+ """Appends index record.
147
+
148
+ A record is a packed structure (12 bytes):
149
+ 0x0: virtual address start
150
+ 0x4: virtual address end
151
+ 0x8: offset of the range within a dump file
152
+
153
+ """
154
+ self .fd .write (pack ('III' , vaddr_start , vaddr_end , self .offset ))
155
+ self .offset += vaddr_end - vaddr_start
156
+
157
+ def close (self ):
158
+ self .fd .close ()
0 commit comments