162 lines
4.9 KiB
Python
Executable File
162 lines
4.9 KiB
Python
Executable File
## @ loadthis.py
|
|
#
|
|
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
#
|
|
##
|
|
|
|
import os
|
|
import gdb
|
|
from functools import reduce
|
|
|
|
|
|
def bytes_to_value(bytes):
|
|
return reduce(lambda x, y: (x << 8) | y, bytes[::-1])
|
|
|
|
|
|
def value_to_bytes(value, length):
|
|
return [(value >> (i * 8) & 0xff) for i in range(length)]
|
|
|
|
|
|
class LoadThis(gdb.Command):
|
|
def __init__(self):
|
|
super(LoadThis, self).__init__("loadthis", gdb.COMMAND_DATA)
|
|
self.gdb_inf = gdb.inferiors()[0]
|
|
|
|
def ord(self, addr, width):
|
|
val = self.gdb_inf.read_memory(addr, width)
|
|
return bytes_to_value(val.tobytes())
|
|
|
|
def ord2(self, addr):
|
|
return self.ord(addr, 2)
|
|
|
|
def ord4(self, addr):
|
|
return self.ord(addr, 4)
|
|
|
|
def ord8(self, addr):
|
|
return self.ord(addr, 8)
|
|
|
|
def gets(self, addr):
|
|
result = []
|
|
loop = True
|
|
while loop:
|
|
v = self.ord8(addr)
|
|
t = 0
|
|
while v > 0:
|
|
l = v & 0x7F
|
|
if l == 0:
|
|
break
|
|
result.append("%c" % l)
|
|
v >>= 8
|
|
t = t + 1
|
|
if t != 8:
|
|
loop = False
|
|
addr = addr + 8
|
|
return ''.join(result)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
arch = gdb.selected_frame().architecture().name()
|
|
eip_str = "$eip"
|
|
if "x86-64" in arch:
|
|
eip_str = "$rip"
|
|
eip = int(gdb.parse_and_eval(eip_str))
|
|
if eip < 0x10000:
|
|
eip += 0xffff0000
|
|
|
|
curr = eip & 0xfffffffc
|
|
back = curr - 0x40000
|
|
step = 4
|
|
found = False
|
|
while curr > back:
|
|
val = self.ord4(curr)
|
|
if val == 0x00005a4d: # PE image
|
|
pe_image_base = curr
|
|
pe00_base = pe_image_base + self.ord4(curr + 0x3c)
|
|
pe_sig = self.ord4(pe00_base)
|
|
if pe_sig == 0x4550:
|
|
found = True
|
|
elif val == 0x014C5A56: # TE image
|
|
found = True
|
|
|
|
if found == True: break
|
|
curr -= step
|
|
if not found:
|
|
print("ERROR: could not locate PE/TE header !")
|
|
return
|
|
|
|
if val == 0x00005a4d:
|
|
pe_coff_hdr = pe00_base + 4
|
|
pe_num_sections = self.ord2(pe_coff_hdr + 2)
|
|
pe_opt_hdr_base = pe_coff_hdr + 0x14
|
|
pe_opt_hdr_size = self.ord2(pe_coff_hdr + 0x10)
|
|
|
|
if pe_opt_hdr_size == 0:
|
|
print("ERROR: optional header size is zero.")
|
|
return
|
|
|
|
pe_sig = self.ord2(pe_opt_hdr_base)
|
|
if (pe_sig != 0x010B) and (pe_sig != 0x020B):
|
|
print("ERROR: bad magic number")
|
|
return
|
|
|
|
code_off = self.ord4(pe_opt_hdr_base + 0x14)
|
|
pe_num_rva_offs = 0
|
|
pe_data_dir_offs = 0
|
|
if pe_sig == 0x010b:
|
|
# PE32 executable
|
|
pe_num_rva_offs = 0x5c
|
|
pe_data_dir_offs = 0x60
|
|
else:
|
|
# PE32+ executable
|
|
pe_num_rva_offs = 0x6c
|
|
pe_data_dir_offs = 0x70
|
|
|
|
num_rva = self.ord4(pe_opt_hdr_base + pe_num_rva_offs)
|
|
if self.ord4(pe_opt_hdr_base + pe_num_rva_offs) < 7:
|
|
print("ERROR: number of RVA < 7")
|
|
return
|
|
|
|
pe_debug_dir_entry_offs = self.ord4(pe_opt_hdr_base +
|
|
pe_data_dir_offs + 6 * 8)
|
|
|
|
else:
|
|
|
|
te_header = curr
|
|
print('TE image base at 0x%08X' % te_header)
|
|
te_header_size = 0xa * 0x4
|
|
stripped_size = self.ord2(te_header + 6)
|
|
code_off = self.ord4(te_header + 0xc)
|
|
pe_start_of_file = te_header + te_header_size - stripped_size
|
|
pe_image_base = pe_start_of_file
|
|
pe_debug_dir_entry_offs = self.ord4(te_header + (0x8 * 0x4))
|
|
|
|
if self.ord2(pe_image_base + pe_debug_dir_entry_offs + 0xc) != 0x2:
|
|
print('ERROR: no debug info !')
|
|
return
|
|
|
|
val = self.ord4(pe_image_base + pe_debug_dir_entry_offs + 0x14)
|
|
if val:
|
|
baseptr = pe_image_base + val
|
|
else:
|
|
baseptr = pe_image_base + self.ord4(pe_image_base +
|
|
pe_debug_dir_entry_offs + 0x18)
|
|
sig = self.ord4(baseptr)
|
|
if sig == 0x3031424e:
|
|
baseptr += 0x10
|
|
print("NB10 signature at 0x%X" % baseptr)
|
|
elif sig == 0x53445352:
|
|
baseptr += 0x18
|
|
print("RSDS signature at 0x%X" % baseptr)
|
|
else:
|
|
print("Unknown debug signature")
|
|
return
|
|
|
|
text_base = pe_image_base + code_off
|
|
dbgpath = self.gets(baseptr)[0:-3] + 'debug'
|
|
print("Loading symbol %s at 0x%x" % (dbgpath, pe_image_base))
|
|
gdb.execute("symbol-file")
|
|
gdb.execute("add-symbol-file %s 0x%08x" % (dbgpath, text_base))
|
|
|
|
|
|
LoadThis()
|