def laf_open_disk(comm): # Open whole disk in read/write mode open_cmd = lglaf.make_request(b'OPEN', body=b'\0') open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) comm.call(close_cmd)
def laf_open_disk(comm): # Open whole disk in read/write mode open_cmd = lglaf.make_request(b'OPEN', body=b'\0') open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) comm.call(close_cmd)
def laf_open_ro(comm, filename): filename = filename.encode('utf8') + b'\0' # Open a single file in readonly mode open_cmd = lglaf.make_request(b'OPEN', body=filename) open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) comm.call(close_cmd)
def laf_open_ro(comm, filename): filename = filename.encode('utf8') + b'\0' # Open a single file in readonly mode open_cmd = lglaf.make_request(b'OPEN', body=filename) open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) comm.call(close_cmd)
def laf_open_disk(comm): # Open whole disk in read/write mode open_cmd = lglaf.make_request(b'OPEN', body=b'\0') #open_cmd = lglaf.make_request(b'OPEN', body=b'\x2f\x64\x65\x76\x2f\x62\x6c\x6f\x63\x6b\x2f\x73\x64\x65\x00\x06\xfb\x0f\x00\x00\x30\xb0\x9d\x06\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x30\xb0\x9d\x06\x00\x00\x00\x00\xdd\x60\x1a\x10\x48\x52\x9f\x06\xd8\x4f\x9d\x06\x06\x00\x00\x00\x00\x00\x00\x00\x58\x52\x9f\x06\x00\x00\x00\x00\x0c\x00\x06\x00\x04\x00\x00\x00\x60\xea\xff\x03\xeb\x27\x00\x10\xdc\xea\xff\x03\x30\xb0\x9d\x06\x64\xea\xff\x03\x41\x76\x1a\x10\x00\x00\x61\x06\x00\x00\x00\x00\x30\xb0\x9d\x06\xc0\xea\xff\x03\xbe\xe4\x09\x10\x30\xb0\x9d\x06\xb6\xd9\xee\xd8\x48\x00\x00\x00\xbc\x52\xa7\x06\xdb\xe4\x09\x10\x30\xb0\x9d\x06\x30\xc0\x9d\x06\x30\xc0\x9d\x06\x00\x00\x00\x00\xdc\xea\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\xb6\xd9\xee\xd8\xfc\xea\xff\x03\xf0\x9a\x1d\x10\x48\x00\x00\x00\x10\x00\x00\x00\x08\xeb\xff\x03\x7b\x8c\x03\x10\x10\x00\x00\x00\x8a\x8c\x03\x10\x7e\xd8\xee\xd8\xba\x8c\x03\x10\x00\x6f\x6f\x74\x00\xd9\xee\xd8\xa0\xe8\xff\x03\x9c\xec\xff\x03\x02\x00\x02\x00\xb6\x81\x00\x00\x00\x00\xb6\x01\x00\x00\x00\x00\x00\x00\x00\x00\0') if comm.protocol_version >= 0x1000004 or comm.CR_NEEDED == 1: lglaf.challenge_response(comm, 2) open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) if comm.protocol_version >= 0x1000004 or comm.CR_NEEDED == 1: lglaf.challenge_response(comm, 4) comm.call(close_cmd)
def laf_open_ro(comm, filename): filename = filename.encode('utf8') + b'\0' # Open a single file in readonly mode open_cmd = lglaf.make_request(b'OPEN', body=filename) if comm.protocol_version >= 0x1000004 or comm.CR_NEEDED == 1: lglaf.challenge_response(comm, 2) open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) if comm.protocol_version >= 0x1000004 or comm.CR_NEEDED == 1: lglaf.challenge_response(comm, 4) comm.call(close_cmd)
def laf_erase(comm, fd_num, sector_start, sector_count): """TRIM some sectors.""" erase_cmd = lglaf.make_request(b'ERSE', args=[fd_num, sector_start, sector_count]) header, response = comm.call(erase_cmd) # Ensure that response fd, start and count are sane (match the request) assert erase_cmd[4:4+12] == header[4:4+12], "Unexpected erase response"
def laf_erase(comm, fd_num, sector_start, sector_count): """TRIM some sectors.""" erase_cmd = lglaf.make_request(b'ERSE', args=[fd_num, sector_start, sector_count]) header, response = comm.call(erase_cmd) # Ensure that response fd, start and count are sane (match the request) assert erase_cmd[4:4+12] == header[4:4+12], "Unexpected erase response"
def laf_open_disk(comm): # Open whole disk in read/write mode open_cmd = lglaf.make_request(b'OPEN', body=b'\0') cr_needed = lglaf.chk_mode(comm.protocol_version, comm.CR_NEEDED, comm.CR_MODE) if cr_needed == 1: lglaf.challenge_response(comm, 2) open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) if cr_needed == 1: lglaf.challenge_response(comm, 4) comm.call(close_cmd)
def laf_misc_write(comm, size, data): """This is for writting to the misc partition.""" """You can specify an offset, but that is currently not implemented""" misc_offset = 0 write_cmd = lglaf.make_request(b'MISC', args=[b'WRTE', misc_offset, size], body=data) #header = comm.call(write_cmd)[0] comm.call(write_cmd)
def laf_open_disk(comm): # On a UFS device, if you don't pass anything for the body, /dev/block/sda is opened. open_cmd = lglaf.make_request(b'OPEN', body=b'\0') # This opens /dev/block/sde. Obviously you can't have both uncommented. # Need to put this in a switch so that --block sde or --block sdf etc can be passed #open_cmd = lglaf.make_request(b'OPEN', body=b'\x2f\x64\x65\x76\x2f\x62\x6c\x6f\x63\x6b\x2f\x73\x64\x65\x00\x06\xfb\x0f\x00\x00\x30\xb0\x9d\x06\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x30\xb0\x9d\x06\x00\x00\x00\x00\xdd\x60\x1a\x10\x48\x52\x9f\x06\xd8\x4f\x9d\x06\x06\x00\x00\x00\x00\x00\x00\x00\x58\x52\x9f\x06\x00\x00\x00\x00\x0c\x00\x06\x00\x04\x00\x00\x00\x60\xea\xff\x03\xeb\x27\x00\x10\xdc\xea\xff\x03\x30\xb0\x9d\x06\x64\xea\xff\x03\x41\x76\x1a\x10\x00\x00\x61\x06\x00\x00\x00\x00\x30\xb0\x9d\x06\xc0\xea\xff\x03\xbe\xe4\x09\x10\x30\xb0\x9d\x06\xb6\xd9\xee\xd8\x48\x00\x00\x00\xbc\x52\xa7\x06\xdb\xe4\x09\x10\x30\xb0\x9d\x06\x30\xc0\x9d\x06\x30\xc0\x9d\x06\x00\x00\x00\x00\xdc\xea\xff\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\xb6\xd9\xee\xd8\xfc\xea\xff\x03\xf0\x9a\x1d\x10\x48\x00\x00\x00\x10\x00\x00\x00\x08\xeb\xff\x03\x7b\x8c\x03\x10\x10\x00\x00\x00\x8a\x8c\x03\x10\x7e\xd8\xee\xd8\xba\x8c\x03\x10\x00\x6f\x6f\x74\x00\xd9\xee\xd8\xa0\xe8\xff\x03\x9c\xec\xff\x03\x02\x00\x02\x00\xb6\x81\x00\x00\x00\x00\xb6\x01\x00\x00\x00\x00\x00\x00\x00\x00\0') if comm.protocol_version >= 0x1000004 or comm.CR_NEEDED == 1: lglaf.challenge_response(comm, 2) open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) try: yield fd_num finally: close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) if comm.protocol_version >= 0x1000004 or comm.CR_NEEDED == 1: lglaf.challenge_response(comm, 4) comm.call(close_cmd)
def laf_read(comm, fd_num, offset, size): """Read size bytes at the given block offset.""" read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size]) header, response = comm.call(read_cmd) # Ensure that response fd, offset and length are sane (match the request) assert read_cmd[4:4+12] == header[4:4+12], "Unexpected read response" assert len(response) == size return response
def laf_read(comm, fd_num, offset, size): """Read size bytes at the given block offset.""" read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size]) header, response = comm.call(read_cmd) # Ensure that response fd, offset and length are sane (match the request) assert read_cmd[4:4+12] == header[4:4+12], "Unexpected read response" assert len(response) == size return response
def make_exec_request(shell_command): argv = b'sh -c eval\t"$*"\t -- ' argv += shell_command.encode('ascii') if isinstance(shell_command, str) else shell_command if len(argv) > 255: raise RuntimeError("Command length %d is larger than 255" % len(argv)) return lglaf.make_request(b'EXEC', body=argv + b'\0')
def get_file_size(comm, path): shell_command = b'stat -t ' + path.encode('utf8') + b'\0' output = comm.call(lglaf.make_request(b'EXEC', body=shell_command))[1] output = output.decode('utf8') if not output.startswith(path + ' '): _logger.debug("Output: %r", output) raise RuntimeError("Cannot get filesize for %s" % path) size_bytes = output.lstrip(path + ' ').split()[0] return int(size_bytes)
def make_exec_request(shell_command): argv = b'sh -c eval\t"$*"\t -- ' argv += shell_command.encode('ascii') if isinstance(shell_command, str) else shell_command if len(argv) > 255: raise RuntimeError("Command length %d is larger than 255" % len(argv)) return lglaf.make_request(b'EXEC', body=argv + b'\0')
def get_file_size(comm, path): shell_command = b'stat -t ' + path.encode('utf8') + b'\0' output = comm.call(lglaf.make_request(b'EXEC', body=shell_command))[1] output = output.decode('utf8') if not output.startswith(path + ' '): _logger.debug("Output: %r", output) raise RuntimeError("Cannot get filesize for %s" % path) size_bytes = output.lstrip(path + ' ').split()[0] return int(size_bytes)
def laf_read(comm, fd_num, offset, size): """Read size bytes at the given block offset.""" read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size]) for attempt in range(3): try: header, response = comm.call(read_cmd) break except usb.core.USBError as e: if e.strerror == 'Overflow': _logger.debug("Overflow on READ %d %d %d", fd_num, offset, size) for attempt in range(3): try: comm.reset() comm._read(-1) # clear line break except usb.core.USBError: pass continue elif e.strerror == 'Operation timed out': _logger.debug("Timeout on READ %d %d %d", fd_num, offset, size) comm.close() time.sleep(3) comm.__init__() try: lglaf.try_hello(comm) except usb.core.USBError: pass close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) comm.call(close_cmd) open_cmd = lglaf.make_request(b'OPEN', body=b'\0') open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size]) continue else: raise # rethrow # Ensure that response fd, offset and length are sane (match the request) assert read_cmd[4:4 + 12] == header[4:4 + 12], "Unexpected read response" assert len(response) == size return response, fd_num
def do_challenge_response(comm): request_kilo = lglaf.make_request( b'KILO', args=[b'CENT', b'\0\0\0\0', b'\0\0\0\0', b'\0\0\0\0']) kilo_header, kilo_response = comm.call(request_kilo) kilo_challenge = kilo_header[8:12] chalstring = ":".join("{:02x}".format(ord(k)) for k in kilo_challenge) _logger.debug("Challenge: %s" % chalstring) print("Challenge: %s" % chalstring) key2 = b'qndiakxxuiemdklseqid~a~niq,zjuxl' # if this doesnt work try 'lgowvqnltpvtgogwswqn~n~mtjjjqxro' kilo_response = do_aes_encrypt( key_xoring(key_transform(key2), kilo_challenge)) respstring = ":".join("{:02x}".format(ord(m)) for m in kilo_response) #_logger.debug("Response: %s" %respstring) print("Response: %s" % respstring) request_kilo_metr = lglaf.make_request( b'KILO', args=[b'METR', b'\0\0\0\0', b'\x02\0\0\0', b'\0\0\0\0'], body=bytes(kilo_response)) metr_header, metr_response = comm.call(request_kilo_metr)
def laf_write(comm, fd_num, offset, data): """Write size bytes at the given block offset.""" #_logger.debug("WRTE(0x%05x, #%d)", offset, len(data)); return write_cmd = lglaf.make_request(b'WRTE', args=[fd_num, offset], body=data) header = comm.call(write_cmd)[0] # Response offset (in bytes) must match calculated offset calc_offset = (offset * 512) & 0xffffffff resp_offset = read_uint32(header, 8) assert write_cmd[4:4 + 4] == header[4:4 + 4], "Unexpected write response" assert calc_offset == resp_offset, \ "Unexpected write response: %#x != %#x" % (calc_offset, resp_offset)
def laf_write(comm, fd_num, offset, data): """Write size bytes at the given block offset.""" #_logger.debug("WRTE(0x%05x, #%d)", offset, len(data)); return write_cmd = lglaf.make_request(b'WRTE', args=[fd_num, offset], body=data) header = comm.call(write_cmd)[0] # Response offset (in bytes) must match calculated offset calc_offset = (offset * 512) & 0xffffffff resp_offset = read_uint32(header, 8) assert write_cmd[4:4+4] == header[4:4+4], "Unexpected write response" assert calc_offset == resp_offset, \ "Unexpected write response: %#x != %#x" % (calc_offset, resp_offset)
def laf_read(comm, fd_num, offset, size): """Read size bytes at the given block offset.""" read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size]) for attempt in range(3): try: header, response = comm.call(read_cmd) break except usb.core.USBError as e: if e.strerror == 'Overflow': _logger.debug("Overflow on READ %d %d %d", fd_num, offset, size) for attempt in range(3): try: comm.reset() comm._read(-1) # clear line break except usb.core.USBError: pass continue elif e.strerror == 'Operation timed out': _logger.debug("Timeout on READ %d %d %d", fd_num, offset, size) comm.close() time.sleep(3) comm.__init__() try: lglaf.try_hello(comm) except usb.core.USBError: pass close_cmd = lglaf.make_request(b'CLSE', args=[fd_num]) comm.call(close_cmd) open_cmd = lglaf.make_request(b'OPEN', body=b'\0') open_header = comm.call(open_cmd)[0] fd_num = read_uint32(open_header, 4) read_cmd = lglaf.make_request(b'READ', args=[fd_num, offset, size]) continue else: raise # rethrow # Ensure that response fd, offset and length are sane (match the request) assert read_cmd[4:4+12] == header[4:4+12], "Unexpected read response" assert len(response) == size return response, fd_num
def get_file_size(comm, path): shell_command = b'ls -ld ' + path.encode('utf8') + b'\0' output = comm.call(lglaf.make_request(b'EXEC', body=shell_command))[1] output = output.decode('utf8') if not len(output): raise RuntimeError("Cannot find file %s" % path) # Example output: "-rwxr-x--- root root 496888 1970-01-01 00:00 lafd" # Accommodate for varying ls output fields = output.split() if len(fields) >= 7: for field in fields[3:]: if field.isdigit(): return int(field) _logger.debug("ls output: %s", output) raise RuntimeError("Cannot find filesize for path %s" % path)
def cat_file(comm, path): shell_command = b'cat ' + path.encode('ascii') + b'\0' return comm.call(lglaf.make_request(b'EXEC', body=shell_command))[1]
def laf_ioct(comm, fd_num, param): """This manipulates ioctl for a given file descriptor""" """The only known IOCT param is 0x1261 which enables write""" ioct_cmd = lglaf.make_request(b'IOCT', args=[fd_num, param]) comm.call(ioct_cmd)
def laf_copy(comm, fd_num, src_offset, size, dst_offset): """This will copy blocks from one location to another on the same block device""" copy_cmd = lglaf.make_request(b'COPY', args=[fd_num, src_offset, size, dst_offset]) comm.call(copy_cmd)
def cat_file(comm, path): shell_command = b'cat ' + path.encode('ascii') + b'\0' return comm.call(lglaf.make_request(b'EXEC', body=shell_command))[1]