def dump_Descriptor_Table(self, cpu_thread_id, code, num_entries=None): (limit, base, pa) = self.helper.get_descriptor_table(cpu_thread_id, code) dt = self.helper.read_physical_mem(pa, limit + 1) total_num = len(dt) / 16 if (total_num < num_entries) or (num_entries is None): num_entries = total_num logger().log("[cpu%d] Physical Address: 0x%016X" % (cpu_thread_id, pa)) logger().log("[cpu%d] # of entries : %d" % (cpu_thread_id, total_num)) logger().log("[cpu%d] Contents (%d entries):" % (cpu_thread_id, num_entries)) print_buffer(buffer(dt, 0, 16 * num_entries)) logger().log("--------------------------------------") logger().log("# segment:offset attributes") logger().log("--------------------------------------") for i in range(0, num_entries): offset = ( (ord(dt[i * 16 + 11]) << 56) | (ord(dt[i * 16 + 10]) << 48) | (ord(dt[i * 16 + 9]) << 40) | (ord(dt[i * 16 + 8]) << 32) | (ord(dt[i * 16 + 7]) << 24) | (ord(dt[i * 16 + 6]) << 16) | (ord(dt[i * 16 + 1]) << 8) | ord(dt[i * 16 + 0]) ) segsel = (ord(dt[i * 16 + 3]) << 8) | ord(dt[i * 16 + 2]) attr = (ord(dt[i * 16 + 5]) << 8) | ord(dt[i * 16 + 4]) logger().log("%03d %04X:%016X 0x%04X" % (i, segsel, offset, attr)) return (pa, dt)
def _ioctl( self, ioctl_code, in_buf, out_length ): out_buf = (c_char * out_length)() self.get_driver_handle() #ret = kernel32.DeviceIoControl( self.driver_handle, ioctl_code, in_buf, len(in_buf), byref(out_buf), out_length, byref(out_size), None ) if logger().VERBOSE: print_buffer( in_buf ) try: out_buf = win32file.DeviceIoControl( self.driver_handle, ioctl_code, in_buf, out_length, None ) except pywintypes.error, msg: logger().error( 'DeviceIoControl returned error: %s' % str(msg) ) return None
def _ioctl( self, ioctl_code, in_buf, out_length ): out_buf = (c_char * out_length)() self.get_driver_handle() #ret = kernel32.DeviceIoControl( self.driver_handle, ioctl_code, in_buf, len(in_buf), byref(out_buf), out_length, byref(out_size), None ) if logger().VERBOSE: print_buffer( in_buf ) try: out_buf = win32file.DeviceIoControl( self.driver_handle, ioctl_code, in_buf, out_length, None ) except pywintypes.error, _err: err_status = _err[0] + 0x100000000 if STATUS_PRIVILEGED_INSTRUCTION == err_status: err_msg = "HW Access Violation: DeviceIoControl returned STATUS_PRIVILEGED_INSTRUCTION (0x%X)" % err_status logger().error( err_msg ) raise HWAccessViolationError( err_msg, err_status ) else: err_msg = "HW Access Error: DeviceIoControl returned status 0x%X (%s)" % (err_status,_err[2]) logger().error( err_msg ) raise OsHelperError( err_msg, err_status )
def _ioctl( self, ioctl_code, in_buf, out_length ): if not self.driver_loaded: _handle_error("chipsec kernel driver is not loaded (in native API mode?)") out_buf = (c_char * out_length)() self.get_driver_handle() if logger().DEBUG: print_buffer( in_buf ) try: out_buf = win32file.DeviceIoControl( self.driver_handle, ioctl_code, in_buf, out_length, None ) except pywintypes.error, _err: err_status = _err[0] + 0x100000000 if STATUS_PRIVILEGED_INSTRUCTION == err_status: err_msg = "HW Access Violation: DeviceIoControl returned STATUS_PRIVILEGED_INSTRUCTION (0x%X)" % err_status if logger().DEBUG: logger().error( err_msg ) raise HWAccessViolationError( err_msg, err_status ) else: _handle_error( "HW Access Error: DeviceIoControl returned status 0x%X (%s)" % (err_status,_err[2]), err_status )
def write_virtual_mem( self, virt_address, length, buf ): if logger().HAL: logger().log( '[mem] buffer len = 0x%X to VA = 0x%016X' % (length, virt_address) ) print_buffer( buf ) phys_address = self.va2pa(virt_address) return self.helper.write_physical_mem( phys_address, length, buf )
def run(self): size = 0x100 if len(self.argv) < 3: print MemCommand.__doc__ return op = self.argv[2] t = time.time() if 'allocate' == op and 4 == len(self.argv): size = int(self.argv[3],16) (va, pa) = self.cs.mem.alloc_physical_mem( size ) self.logger.log( '[CHIPSEC] Allocated %X bytes of physical memory: VA = 0x%016X, PA = 0x%016X' % (size, va, pa) ) elif 'pagedump' == op and len(self.argv) > 3: start = long(self.argv[3],16) length = long(self.argv[4],16) if len(self.argv) > 4 else chipsec.defines.BOUNDARY_4KB end = start + length dump_region_to_path( chipsec.file.get_main_dir(), start, end ) elif 'read' == op: phys_address = int(self.argv[3],16) size = int(self.argv[4],16) if len(self.argv) > 4 else 0x100 self.logger.log( '[CHIPSEC] reading buffer from memory: PA = 0x%016X, len = 0x%X..' % (phys_address, size) ) buffer = self.cs.mem.read_physical_mem( phys_address, size ) if len(self.argv) > 5: buf_file = self.argv[5] chipsec.file.write_file( buf_file, buffer ) self.logger.log( "[CHIPSEC] written 0x%X bytes to '%s'" % (len(buffer), buf_file) ) else: print_buffer( buffer ) elif 'readval' == op: phys_address = int(self.argv[3],16) width = 0x4 if len(self.argv) > 4: width = chipsec_util.get_option_width(self.argv[4]) if chipsec_util.is_option_valid_width(self.argv[4]) else int(self.argv[4],16) self.logger.log( '[CHIPSEC] reading %X-byte value from PA 0x%016X..' % (width, phys_address) ) if 0x1 == width: value = self.cs.mem.read_physical_mem_byte ( phys_address ) elif 0x2 == width: value = self.cs.mem.read_physical_mem_word ( phys_address ) elif 0x4 == width: value = self.cs.mem.read_physical_mem_dword( phys_address ) self.logger.log( '[CHIPSEC] value = 0x%X' % value ) elif 'write' == op: phys_address = int(self.argv[3],16) if len(self.argv) > 4: size = int(self.argv[4],16) else: self.logger.error( "must specify <length> argument in 'mem write'" ) return if len(self.argv) > 5: buf_file = self.argv[5] if not os.path.exists( buf_file ): #buffer = buf_file.decode('hex') try: buffer = bytearray.fromhex(buf_file) except ValueError, e: self.logger.error( "incorrect <value> specified: '%s'" % buf_file ) self.logger.error( str(e) ) return self.logger.log( "[CHIPSEC] read 0x%X hex bytes from command-line: %s'" % (len(buffer), buf_file) ) else: buffer = chipsec.file.read_file( buf_file ) self.logger.log( "[CHIPSEC] read 0x%X bytes from file '%s'" % (len(buffer), buf_file) ) if len(buffer) < size: self.logger.error( "number of bytes read (0x%X) is less than the specified <length> (0x%X)" % (len(buffer),size) ) return self.logger.log( '[CHIPSEC] writing buffer to memory: PA = 0x%016X, len = 0x%X..' % (phys_address, size) ) self.cs.mem.write_physical_mem( phys_address, size, buffer ) else: self.logger.error( "must specify <buffer>|<file> argument in 'mem write'" ) return
def gfx_aperture_dma_read_write(self, address, size=0x4, value=None, pte_num=0): r = 0 pages = 0 gmadr = self.get_GMADR() off = address%0x1000 h = 0x1000 - off igd_addr = gmadr + pte_num*0x1000 pte_orig = self.read_GGTT_PTE( pte_num ) if self.logger.HAL: self.logger.log( '[igd] reading 0x%X bytes at PA 0x%016X through IGD aperture (DMA) using PTE%d' % (size,address,pte_num) ) self.logger.log( '[igd] GFx aperture (GMADR): 0x%016X' % gmadr ) self.logger.log( '[igd] GFx GTT base : 0x%016X' % self.get_GGTT_base() ) self.logger.log( '[igd] original GTT PTE%03d: 0x%08X' % (pte_num,pte_orig) ) if (h > 0) and (size > h): r = (size - h)%0x1000 pages = 2 + (size - h)//0x1000 else: r = size%0x1000 pages = 1 + size//0x1000 N = pages if self.logger.HAL: self.logger.log( '[igd] pages = 0x%X, r = 0x%x, N = %d' % (pages,r,N) ) if self.logger.VERBOSE: self.logger.log( '[igd] original data at address 0x%016X:' % address ) print_buffer(self.cs.mem.read_physical_mem(address, size)) buffer = '' pa = address for p in range(N): pte = self.get_GGTT_PTE_from_PA(pa) if self.logger.HAL: self.logger.log( '[igd] GFx PTE for address 0x%016X: 0x%08X' % (address,pte) ) self.write_GGTT_PTE(pte_num, pte) if (p == 0): pa_off = off size = h if (pa_off > 0) else 0x1000 else: pa_off = 0 if (p == N-1): size = r if (r > 0) else 0x1000 if value is None: if self.logger.HAL: self.logger.log( '[igd] reading 0x%X bytes at 0x%016X through GFx aperture 0x%016X ..' % (size,pa,igd_addr + pa_off) ) page = self.cs.mem.read_physical_mem(igd_addr + pa_off, size) buffer += page if self.logger.HAL: print_buffer(page[:size]) else: if self.logger.HAL: self.logger.log( '[igd] writing 0x%X bytes to 0x%016X through GFx aperture 0x%016X ..' % (size,pa,igd_addr + pa_off) ) page = value[p*0x1000:p*0x1000+size] self.cs.mem.write_physical_mem(igd_addr + pa_off, size, page) if self.logger.HAL: print_buffer(page) pa += size # restore original PTE if self.logger.HAL: self.logger.log( '[igd] restoring GFx PTE%d 0x%X..' % (pte_num,pte_orig) ) self.write_GGTT_PTE(pte_num, pte_orig) return buffer
def find_EFI_Table(self, table_sig): (smram_base, smram_limit, smram_size) = self.cs.cpu.get_SMRAM() CHUNK_SZ = 1024 * 1024 # 1MB if logger().HAL: logger().log( "[uefi] searching memory for EFI table with signature '{}' ..". format(table_sig)) table_pa, table_header, table, table_buf = None, None, None, None pa = smram_base - CHUNK_SZ isFound = False while pa > CHUNK_SZ: if logger().HAL: logger().log('[uefi] reading 0x{:016X}..'.format(pa)) try: membuf = self.cs.mem.read_physical_mem(pa, CHUNK_SZ) except OsHelperError as err: if logger().HAL: logger().log( "[uefi] Unable to read memory at pa: {:016X} Error: {}" .format(pa, err)) pa -= CHUNK_SZ continue pos = bytestostring(membuf).find(table_sig) if -1 != pos: table_pa = pa + pos if logger().HAL: logger().log( "[uefi] found signature '{}' at 0x{:016X}..".format( table_sig, table_pa)) if pos < (CHUNK_SZ - EFI_TABLE_HEADER_SIZE): hdr = membuf[pos:pos + EFI_TABLE_HEADER_SIZE] else: hdr = self.cs.mem.read_physical_mem( table_pa, EFI_TABLE_HEADER_SIZE) table_header = EFI_TABLE_HEADER( *struct.unpack_from(EFI_TABLE_HEADER_FMT, hdr)) # do some sanity checks on the header if 0 != table_header.Reserved or \ 0 == table_header.CRC32 or \ table_header.Revision not in EFI_REVISIONS or \ table_header.HeaderSize > MAX_EFI_TABLE_SIZE: if logger().HAL: logger().log( "[uefi] found '{}' at 0x{:016X} but doesn't look like an actual table. keep searching.." .format(table_sig, table_pa)) logger().log(table_header) else: isFound = True if logger().HAL: logger().log( "[uefi] found EFI table at 0x{:016X} with signature '{}'.." .format(table_pa, table_sig)) table_size = struct.calcsize(EFI_TABLES[table_sig]['fmt']) if pos < (CHUNK_SZ - EFI_TABLE_HEADER_SIZE - table_size): table_buf = membuf[pos:pos + EFI_TABLE_HEADER_SIZE + table_size] else: table_buf = self.cs.mem.read_physical_mem( table_pa, EFI_TABLE_HEADER_SIZE + table_size) table = EFI_TABLES[table_sig]['struct']( *struct.unpack_from(EFI_TABLES[table_sig]['fmt'], table_buf[EFI_TABLE_HEADER_SIZE:])) if logger().HAL: print_buffer(bytestostring(table_buf)) logger().log('[uefi] {}:'.format( EFI_TABLES[table_sig]['name'])) logger().log(table_header) logger().log(table) break pa -= CHUNK_SZ if (not isFound) and logger().HAL: logger().log( "[uefi] could not find EFI table with signature '{}'".format( table_sig)) return (isFound, table_pa, table_header, table, table_buf)
def find_s3_bootscript(self): found = False BootScript_addresses = [] efivars = self.list_EFI_variables() if efivars is None: logger().error('Could not enumerate UEFI variables at runtime') return (found, BootScript_addresses) if logger().HAL: logger().log("[uefi] searching for EFI variable(s): " + str(S3_BOOTSCRIPT_VARIABLES)) for efivar_name in efivars: (off, buf, hdr, data, guid, attrs) = efivars[efivar_name][0] if efivar_name in S3_BOOTSCRIPT_VARIABLES: if logger().HAL: logger().log("[uefi] found: {} {{{}}} {} variable".format( efivar_name, guid, get_attr_string(attrs))) if logger().HAL: logger().log( '[uefi] {} variable data:'.format(efivar_name)) print_buffer(bytestostring(data)) varsz = len(data) if 4 == varsz: AcpiGlobalAddr_fmt = '<L' elif 8 == varsz: AcpiGlobalAddr_fmt = '<Q' else: logger().error( "Unrecognized format of '{}' UEFI variable (data size = 0x{:X})" .format(efivar_name, varsz)) break AcpiGlobalAddr = struct.unpack_from(AcpiGlobalAddr_fmt, data)[0] if 0 == AcpiGlobalAddr: logger().error( "Pointer to ACPI Global Data structure in {} variable is 0" .format(efivar_name)) break if logger().HAL: logger().log( "[uefi] Pointer to ACPI Global Data structure: 0x{:016X}" .format(AcpiGlobalAddr)) if logger().HAL: logger().log( "[uefi] Decoding ACPI Global Data structure..") AcpiVariableSet = self.helper.read_physical_mem( AcpiGlobalAddr, ACPI_VARIABLE_SET_STRUCT_SIZE) if logger().HAL: logger().log('[uefi] AcpiVariableSet structure:') print_buffer(bytestostring(AcpiVariableSet)) AcpiVariableSet_fmt = '<6Q' #if len(AcpiVariableSet) < struct.calcsize(AcpiVariableSet_fmt): # logger().error( 'Unrecognized format of AcpiVariableSet structure' ) # return (False,0) AcpiReservedMemoryBase, AcpiReservedMemorySize, S3ReservedLowMemoryBase, AcpiBootScriptTable, RuntimeScriptTableBase, AcpiFacsTable = struct.unpack_from( AcpiVariableSet_fmt, AcpiVariableSet) if logger().HAL: logger().log( '[uefi] ACPI Boot-Script table base = 0x{:016X}'. format(AcpiBootScriptTable)) found = True BootScript_addresses.append(AcpiBootScriptTable) #break return (found, BootScript_addresses)