Inject data into .rdata/.text and replace reusedata_fixup placeholders in code with LEA
(self)
| 279 | |
| 280 | |
| 281 | def inject_and_reference_data(self): |
| 282 | """Inject data into .rdata/.text and replace reusedata_fixup placeholders in code with LEA""" |
| 283 | reusedata_fixups: List[DataReuseEntry] = self.injectable.get_all_reusedata_fixups() |
| 284 | if len(reusedata_fixups) == 0: |
| 285 | # nothing todo |
| 286 | return |
| 287 | |
| 288 | # insert data |
| 289 | logger.info(" Inject Carrier-data into injectable") |
| 290 | for datareuse_fixup in reusedata_fixups: |
| 291 | logger.debug(" Handling DataReuse Fixup: {} (.code: {})".format( |
| 292 | datareuse_fixup.string_ref, datareuse_fixup.in_code)) |
| 293 | |
| 294 | if datareuse_fixup.in_code: # .text |
| 295 | shellcode_offset = self.superpe.pe.get_offset_from_rva(self.payload_rva) |
| 296 | self.superpe.pe.set_bytes_at_offset(shellcode_offset, datareuse_fixup.data) |
| 297 | payload_rva = self.superpe.pe.get_rva_from_offset(shellcode_offset) |
| 298 | if payload_rva == None: |
| 299 | raise Exception("DataReuseFixup: payload_rva is None") |
| 300 | datareuse_fixup.addr = payload_rva + self.injectable.superpe.get_image_base() |
| 301 | logger.debug(" Add to .text at 0x{:X} ({}): {} with size {}".format( |
| 302 | datareuse_fixup.addr, payload_rva, datareuse_fixup.string_ref, len(datareuse_fixup.data))) |
| 303 | |
| 304 | else: # .rdata |
| 305 | # get a hole in the .rdata section to put our data |
| 306 | hole_rva = self.rdata_manager.find_hole(len(datareuse_fixup.data)) |
| 307 | if hole_rva == None: |
| 308 | raise Exception("No suitable hole with size {} found in .rdata section, abort".format( |
| 309 | len(datareuse_fixup.data) |
| 310 | )) |
| 311 | self.rdata_manager.add_range(hole_rva[0], hole_rva[1]+1) # mark it as used |
| 312 | |
| 313 | var_data = datareuse_fixup.data |
| 314 | data_rva = hole_rva[0] |
| 315 | self.superpe.pe.set_bytes_at_rva(data_rva, var_data) |
| 316 | datareuse_fixup.addr = data_rva + self.injectable.superpe.get_image_base() |
| 317 | ## |
| 318 | logger.debug(" Add to .rdata at 0x{:X} ({}): {}: {}".format( |
| 319 | datareuse_fixup.addr, data_rva, datareuse_fixup.string_ref, ui_string_decode(var_data))) |
| 320 | |
| 321 | # replace the placeholder in .text with a LEA instruction to the data we written above |
| 322 | logger.info(" Patch Carrier code to reference the injected data") |
| 323 | code = self.superpe.get_code_section_data() |
| 324 | for datareuse_fixup in reusedata_fixups: |
| 325 | ref: DataReuseReference |
| 326 | for ref in datareuse_fixup.references: |
| 327 | if not ref.placeholder in code: |
| 328 | raise Exception("fix data in injectable: DataReuse: ID {} ({}) not found in code section, abort".format( |
| 329 | ref.placeholder.hex(), datareuse_fixup.string_ref)) |
| 330 | |
| 331 | offset_from_datasection = code.index(ref.placeholder) |
| 332 | instruction_virtual_address = offset_from_datasection + self.superpe.get_image_base() + self.superpe.get_code_section().VirtualAddress |
| 333 | destination_virtual_address = datareuse_fixup.addr |
| 334 | logger.debug(" Replace bytes {} at VA 0x{:X} with: LEA {} .rdata 0x{:X}".format( |
| 335 | ref.placeholder.hex(), instruction_virtual_address, ref.register, destination_virtual_address |
| 336 | )) |
| 337 | lea = assemble_lea( |
| 338 | instruction_virtual_address, destination_virtual_address, ref.register |
no test coverage detected