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  import os 
 27   
 28  from rekall.plugins.windows import common 
 29  from rekall.plugins import core 
 30  from rekall import plugin 
 31  from rekall_lib import utils 
 32   
 33   
 34 -class PEDump(common.WindowsCommandPlugin): 
  35      """Dump a PE binary from memory.""" 
 36   
 37      __name = "pedump" 
 38   
 39      __args = [ 
 40          dict(name="image_base", type="SymbolAddress", required=False, 
 41               positional=True, 
 42               help="The address of the image base (dos header)."), 
 43   
 44          dict(name="out_file", 
 45               help="The file name to write."), 
 46   
 47          dict(name="address_space", type="AddressSpace", 
 48               help="The address space to use."), 
 49   
 50          dict(name="out_fd", 
 51               help="A file like object to write the output.") 
 52      ] 
 53   
 57   
 58 -    def WritePEFile(self, fd=None, address_space=None, image_base=None): 
  59          """Dumps the PE file found into the filelike object. 
 60   
 61          Note that this function can be used for any PE file (e.g. executable, 
 62          dll, driver etc). Only a base address need be specified. This makes this 
 63          plugin useful as a routine in other plugins. 
 64   
 65          Args: 
 66            fd: A writable filelike object which must support seeking. 
 67            address_space: The address_space to read from. 
 68            image_base: The offset of the dos file header. 
 69          """ 
 70          dos_header = self.pe_profile._IMAGE_DOS_HEADER( 
 71              offset=image_base, vm=address_space) 
 72   
 73          image_base = dos_header.obj_offset 
 74          nt_header = dos_header.NTHeader 
 75   
 76           
 77          data = dos_header.obj_vm.read( 
 78              image_base, min(1000000, nt_header.OptionalHeader.SizeOfHeaders)) 
 79   
 80          if not data: 
 81              return 
 82   
 83          fd.seek(0) 
 84          fd.write(data) 
 85   
 86          for section in nt_header.Sections: 
 87               
 88              size_of_section = min(10000000, section.SizeOfRawData) 
 89              physical_offset = min(100000000, int(section.PointerToRawData)) 
 90   
 91              data = section.obj_vm.read( 
 92                  section.VirtualAddress + image_base, size_of_section) 
 93   
 94              fd.seek(physical_offset, 0) 
 95              fd.write(data) 
  96   
 119   
120   
121 -class ProcExeDump(core.DirectoryDumperMixin, common.WinProcessFilter): 
 122      """Dump a process to an executable file sample""" 
123   
124      __name = "procdump" 
125   
126      dump_dir_optional = True 
127   
128      __args = [ 
129          dict(name="out_fd", 
130               help="A file like object to write the output.") 
131      ] 
132   
133      table_header = [ 
134          dict(name="_EPROCESS", width=50), 
135          dict(name="Filename"), 
136      ] 
137   
139          """Dump a process from memory into an executable. 
140   
141          In windows PE files are mapped into memory in sections. Each section is 
142          mapped into a region within the process virtual memory from a region in 
143          the executable file: 
144   
145      File on Disk                 Memory Image 
146  0-> ------------    image base-> ------------ 
147       Header                      Header 
148      ------------                 ------------ 
149       Section 1 
150      ------------                 ------------ 
151       Section 2                    Section 1 
152      ------------                 ------------ 
153   
154                                   ------------ 
155                                    Section 2 
156                                   ------------ 
157   
158          This plugin simply copies the sections from memory back into the file on 
159          disk. Its likely that some of the pages in memory are not actually 
160          memory resident, so we might get invalid page reads. In this case the 
161          region on disk is null padded. If that happens it will not be possible 
162          to run the executable, but the executable can still be disassembled and 
163          analysed statically. 
164   
165          References: 
166          http://code.google.com/p/corkami/downloads/detail?name=pe-20110117.pdf 
167   
168          NOTE: Malware can mess with the headers after loading. The remap option 
169          allows to remap the sections on the disk file so they do not collide. 
170   
171          Args: 
172            remap: If set, allows to remap the sections on disk so they do not 
173              overlap. 
174   
175            out_fd: Alternatively, a filelike object can be provided directly. 
176          """ 
177          super(ProcExeDump, self).__init__(*args, **kwargs) 
178          self.pedump = PEDump(session=self.session) 
179          if self.dump_dir is None and not self.plugin_args.out_fd: 
180              raise plugin.PluginError("Dump dir must be specified.") 
 181   
183          """Renders the tasks to disk images, outputting progress as they go""" 
184          for task in self.filter_processes(): 
185              pid = task.UniqueProcessId 
186   
187              task_address_space = task.get_process_address_space() 
188              if not task_address_space: 
189                  self.session.logging.info( 
190                      "Can not get task address space - skipping.") 
191                  continue 
192   
193              if self.plugin_args.out_fd: 
194                  self.pedump.WritePEFile( 
195                      self.plugin_args.out_fd, 
196                      task_address_space, task.Peb.ImageBaseAddress) 
197                  yield task, "User FD" 
198   
199               
200              else: 
201                  filename = u"executable.%s_%s.exe" % ( 
202                      utils.EscapeForFilesystem(task.name), pid) 
203   
204                  yield task, filename 
205   
206                  with self.session.GetRenderer().open( 
207                          directory=self.dump_dir, 
208                          filename=filename, 
209                          mode="wb") as fd: 
210                       
211                      self.pedump.WritePEFile( 
212                          fd, task_address_space, task.Peb.ImageBaseAddress) 
  213   
214   
216      """Dump DLLs from a process address space""" 
217   
218      __name = "dlldump" 
219   
220      __args = [ 
221          dict(name="regex", default=".", type="RegEx", 
222              help="A Regular expression for selecting the dlls to dump.") 
223      ] 
224   
225      table_header = [ 
226          dict(name="_EPROCESS"), 
227          dict(name="base", style="address"), 
228          dict(name="module", width=20), 
229          dict(name="filename") 
230      ] 
231   
233          for task in self.filter_processes(): 
234              task_as = task.get_process_address_space() 
235   
236               
237              for module in task.get_load_modules(): 
238                  process_offset = task_as.vtop(task.obj_offset) 
239                  if process_offset: 
240   
241                       
242                      if not self.plugin_args.regex.search( 
243                              utils.SmartUnicode(module.BaseDllName)): 
244                          continue 
245   
246                      base_name = os.path.basename( 
247                          utils.SmartUnicode(module.BaseDllName)) 
248   
249                      dump_file = "module.{0}.{1:x}.{2:x}.{3}".format( 
250                          task.UniqueProcessId, process_offset, module.DllBase, 
251                          utils.EscapeForFilesystem(base_name)) 
252   
253                      yield dict(_EPROCESS=task, 
254                                 base=module.DllBase, 
255                                 module=module.BaseDllName, 
256                                 filename=dump_file) 
257   
258                       
259                      with self.session.GetRenderer().open( 
260                              filename=dump_file, 
261                              directory=self.dump_dir, 
262                              mode="wb") as fd: 
263                          self.pedump.WritePEFile(fd, task_as, module.DllBase) 
264   
265                  else: 
266                      self.session.logging.error( 
267                          "Cannot dump %s@%s at %#x\n", 
268                          task.ImageFileName, module.BaseDllName, 
269                          int(module.DllBase)) 
  270   
271   
315