def __str__(self): return '\n' \ '\tChunk: {0}\n' \ '\tOffset: {1:#x} ({1})\n' \ '\tPatch: {2}\n' \ '\tOffset: {3:#x} ({3})\n' \ .format(util.bytes2hexstr(self.chunk), self.chunkoffset, util.bytes2hexstr(self.patch), self.patchoffset)
def patch(device, address, chunks): ''' Writes back to the device at address, using the patches in the signature chunks ''' success = True backup = device.read(address, cfg.PAGESIZE) for c in chunks: if len(cfg.patchfile) > 0: patch = cfg.patchfile else: patch = c['patch'] if not patch: continue ioffset = c['internaloffset'] poffset = c['patchoffset'] if not poffset: poffset = 0 realaddress = address + ioffset + poffset device.write(realaddress, patch) read = device.read(realaddress, len(patch)) if cfg.verbose: term.info('Data read back: ' + util.bytes2hexstr(read)) #TODO: Change to .format() if read != patch: success = False # Only patch once from file if len(cfg.patchfile) > 0: break return success, backup
def dump(start, end, path): # Make sure that the right mode is set settings.memdump = True # Initialize and lower DMA shield if not settings.filemode: fw = FireWire() starttime = time.time() device_index = fw.select_device() # Print selection msg('*', 'Selected device: {0}'.format(fw.vendors[device_index])) # Lower DMA shield or use a file as input device = None if settings.filemode: device = MemoryFile(settings.filename, settings.PAGESIZE) else: elapsed = int(time.time() - starttime) device = fw.getdevice(device_index, elapsed) requestsize = settings.max_request_size size = end - start #filename = 'memdump_{0}-{1}.bin'.format(hex(start), hex(end)) #path added for Pac4Mac filename = path file = open(filename, 'wb') msg('*', 'Dumping from {0:#x} to {1:#x}, a total of {2} MiB'.format(start, end, size/settings.MiB)) try: for i in range(start, end, requestsize): # Avoid accessing upper memory area if we are using FireWire if needtoavoid(i): data = b'\x00' * requestsize else: data = device.read(i, requestsize) file.write(data) # Print status dumped = (i - start) // settings.MiB sys.stdout.write('[*] Dumping memory, {0:>4d} MiB so far'.format(dumped)) if settings.verbose: sys.stdout.write('. Sample data read: {0}'.format(bytes2hexstr(data)[0:24])) sys.stdout.write('\r') sys.stdout.flush() file.close() print() # Filler msg('*', 'Dumped memory to file {0}'.format(filename)) device.close() except KeyboardInterrupt: file.close() print() msg('*', 'Dumped memory to file {0}'.format(filename)) raise KeyboardInterrupt
def patch(device, address, chunks): ''' Writes back to the device at address, using the patches in the signature chunks ''' success = True for c in chunks: patch = c['patch'] if not patch: continue ioffset = c['internaloffset'] poffset = c['patchoffset'] if not poffset: poffset = 0 realaddress = address + ioffset + poffset if patch: device.write(realaddress, patch) read = device.read(realaddress, len(patch)) if settings.verbose: msg('*', 'Data written: 0x' + bytes2hexstr(patch)) msg('*', 'Data read: 0x' + bytes2hexstr(read)) if read != patch: success = False return success
def searchanddestroy(device, target, memsize): ''' Main search loop ''' pageaddress = settings.startaddress signatures = target['signatures'] # Add signature lengths in bytes to the dictionary, and replace integer # representations of the signatures and patches with bytes for signature in signatures: signature['length'] = siglen(signature['chunks']) offsets = signature['offsets'] # Offsets within pages for chunk in signature['chunks']: chunk['chunk'] = int2binhex(chunk['chunk']) try: chunk['patch'] = int2binhex(chunk['patch']) except KeyError: chunk['patch'] = None try: # Build a batch of read requests of the form: [(addr1, len1), ...] and # a corresponding match vector: [(chunks1, patchoffset1), ...] j = 0 count = 0 cand = b'\x00' r = [] p = [] while pageaddress < memsize: sig_len = len(signatures) for i in range(sig_len): # Iterate over signatures offsets = signatures[i]['offsets'] # Offsets within pages if isinstance(offsets, int): offsets = [offsets] # Create a list if single offset chunks = signatures[i]['chunks'] # The chunks that is the sig length = signatures[i]['length'] # Sig length in bytes offset_len = len(offsets) for n in range(offset_len): # Iterate over offsets address = pageaddress + offsets[n] + settings.PAGESIZE * j r.append((address, length)) p.append(chunks) count += 1 # If we have built a full vector, read from memory and # compare to the corresponding signatures if count == settings.vectorsize: # Read data from device m = 0 for caddr, cand in device.readv(r): if match(cand, p[m]): print() return (caddr, p[m]) m += 1 # Jump to next pages (we're finished with these) mask = ~(settings.PAGESIZE - 0x01) pageaddress = address & mask if sig_len == i and offset_len == n: pageaddress = pageaddress + settings.PAGESIZE # Zero out counters and vectors j = 0 count = 0 r = [] p = [] # Print status mibaddr = pageaddress // settings.MiB sys.stdout.write('[*] Searching, {0:>4d} MiB so far'.format(mibaddr)) if settings.verbose: sys.stdout.write('. Sample data read: {0}'.format(bytes2hexstr(cand)[0:24])) sys.stdout.write('\r') sys.stdout.flush() j += 1 # Increase read request count except IOError: print() fail('I/O Error, make sure FireWire interfaces are properly connected') except KeyboardInterrupt: print() fail('Aborted') raise KeyboardInterrupt # If we get here, we haven't found anything :-/ print() return (None, None)
def test_bytes2hexstr(self): test1 = b'ABCD' test1_res = '0x41424344' self.assertEqual(bytes2hexstr(test1), test1_res) test2 = '41424344' self.assertRaises(BytesWarning, bytes2hexstr, test2)
def searchanddestroy(device, target, memsize): ''' Main search loop ''' pageaddress = settings.startaddress signatures = target['signatures'] # Add signature lengths in bytes to the dictionary, and replace integer # representations of the signatures and patches with bytes for signature in signatures: signature['length'] = siglen(signature['chunks']) offsets = signature['offsets'] # Offsets within pages for chunk in signature['chunks']: chunk['chunk'] = int2binhex(chunk['chunk']) try: chunk['patch'] = int2binhex(chunk['patch']) except KeyError: chunk['patch'] = None try: # Build a batch of read requests of the form: [(addr1, len1), ...] and # a corresponding match vector: [(chunks1, patchoffset1), ...] j = 0 count = 0 cand = b'\x00' r = [] p = [] while pageaddress < memsize: sig_len = len(signatures) for i in range(sig_len): # Iterate over signatures offsets = signatures[i]['offsets'] # Offsets within pages if isinstance(offsets, int): offsets = [offsets] # Create a list if single offset chunks = signatures[i]['chunks'] # The chunks that is the sig length = signatures[i]['length'] # Sig length in bytes offset_len = len(offsets) for n in range(offset_len): # Iterate over offsets address = pageaddress + offsets[n] + settings.PAGESIZE * j r.append((address, length)) p.append(chunks) count += 1 # If we have built a full vector, read from memory and # compare to the corresponding signatures if count == settings.vectorsize: # Read data from device m = 0 for caddr, cand in device.readv(r): if match(cand, p[m]): print() return (caddr, p[m]) m += 1 # Jump to next pages (we're finished with these) mask = ~(settings.PAGESIZE - 0x01) pageaddress = address & mask if sig_len == i and offset_len == n: pageaddress = pageaddress + settings.PAGESIZE # Zero out counters and vectors j = 0 count = 0 r = [] p = [] # Print status mibaddr = pageaddress // settings.MiB sys.stdout.write( '[*] Searching, {0:>4d} MiB so far'.format( mibaddr)) if settings.verbose: sys.stdout.write('. Sample data read: {0}'.format( bytes2hexstr(cand)[0:24])) sys.stdout.write('\r') sys.stdout.flush() j += 1 # Increase read request count except IOError: print() fail('I/O Error, make sure FireWire interfaces are properly connected') except KeyboardInterrupt: print() fail('Aborted') raise KeyboardInterrupt # If we get here, we haven't found anything :-/ print() return (None, None)