Skip to content

Commit

Permalink
Direct get symbol data from firmware file in VxHunter Core, Sync edit…
Browse files Browse the repository at this point in the history
… to Radare2.
  • Loading branch information
dark-lbp committed Nov 6, 2019
1 parent a16a49c commit 18480df
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 98 deletions.
111 changes: 63 additions & 48 deletions firmware_tools/vxhunter_r2_py2.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
]

need_create_function = [
0x0500,
0x050000
0x04,
0x05
]


Expand All @@ -69,6 +69,7 @@ def __init__(self, firmware, vx_version=5, big_endian=False, logger=None):
self.symbol_table_end = None
self._string_table = []
self._symbol_table = []
self.symbols = []
self.load_address = None
self._firmware = firmware
self._has_symbol = None
Expand Down Expand Up @@ -234,6 +235,7 @@ def find_symbol_table(self):
if self.symbol_table_start:
for i in range(self.symbol_table_start, len(self._firmware), self._symbol_interval):
check_data = self._firmware[i:i + self._symbol_interval]

if len(check_data) < self._symbol_interval:
self.logger.debug("Check_data length is too small")
break
Expand Down Expand Up @@ -263,6 +265,7 @@ def get_symbol_table(self):
for i in range(self.symbol_table_start, self.symbol_table_end, self._symbol_interval):
symbol_name_addr = self._firmware[i + 4:i + 8]
symbol_dest_addr = self._firmware[i + 8:i + 12]
symbol_flag = ord(self._firmware[i + self._symbol_interval - 2])
if self.big_endian:
unpack_format = '>I'
else:
Expand All @@ -275,6 +278,7 @@ def get_symbol_table(self):
'symbol_name_addr': symbol_name_addr,
'symbol_name_length': None,
'symbol_dest_addr': symbol_dest_addr,
'symbol_flag': symbol_flag,
'offset': i
})
# self.logger.debug("self._symbol_table: %s" % self._symbol_table)
Expand Down Expand Up @@ -620,6 +624,38 @@ def cleanup(self):
self.load_address = None
self._has_symbol = None

def get_string_from_firmware_by_offset(self, string_offset):
symbol_name = ""
while True:
if self._firmware[string_offset] != '\x00':
symbol_name += self._firmware[string_offset]
string_offset += 1

else:
break

return symbol_name

def get_symbols(self):
self.symbols = []
if self.load_address:
for symbol in self._symbol_table:
symbol_name_addr = symbol["symbol_name_addr"]
symbol_dest_addr = symbol["symbol_dest_addr"]
symbol_flag = symbol["symbol_flag"]
symbol_name_firmware_addr = symbol_name_addr - self.load_address
symbol_name = self.get_string_from_firmware_by_offset(symbol_name_firmware_addr)
self.symbols.append({
"symbol_name": symbol_name,
"symbol_name_addr": symbol_name_addr,
"symbol_dest_addr": symbol_dest_addr,
"symbol_flag": symbol_flag
})
return self.symbols

else:
return None


def demangle_function(demangle_string):
function_return = None
Expand Down Expand Up @@ -692,6 +728,23 @@ def manual_vxworks_version():
return None


def add_symbol(symbol_name, symbol_name_address, symbol_address, symbol_type):
# Load symbols
if symbol_name:
if symbol_type in need_create_function:
r2_command = "fs functions; f {} @ 0x{:08X}".format(symbol_name, symbol_address)
r2p.cmd(r2_command)
# TODO: Need find a way to disable warnning "af: Cannot find function at"
r2_command = "af {} 0x{:08X}".format(symbol_name, symbol_address)
r2p.cmd(r2_command)

else:
r2_command = "fs symbols; f {} @ 0x{:08X}".format(symbol_name, symbol_address)
r2p.cmd(r2_command)

return


if __name__ == '__main__':
print("Running with python version: {}".format(sys.version))
r2p = r2pipe.open()
Expand Down Expand Up @@ -764,55 +817,17 @@ def manual_vxworks_version():
if target.big_endian:
r2p.cmd("e cfg.bigendian=True")

symbol_table_start_address += image_load_address
symbol_table_end_address += image_load_address
print("symbol_table_start_address: 0x{:08X}".format(symbol_table_start_address))
print("symbol_table_end_address: 0x{:08X}".format(symbol_table_end_address))
symbol_interval = 16
if vx_version == 6:
symbol_interval = 20
ea = symbol_table_start_address
while ea < symbol_table_end_address:
symbol_name_string = None
offset = 4
r2_command = "pv4j @0x{:08X}".format(ea + symbol_interval - 4)
symbol_flag = r2p.cmdj(r2_command)[0]['value']
r2_command = "pv4j @0x{:08X}".format(ea + offset)
symbol_name_address = r2p.cmdj(r2_command)[0]['value']
r2_command = "pv4j @0x{:08X}".format(ea + offset + 4)
symbol_dest_address = r2p.cmdj(r2_command)[0]['value']
# print("symbol_flag: 0x{:08X}".format(symbol_flag))
# print("symbol_name_address: 0x{:08X}".format(symbol_name_address))
# print("symbol_dest_address: 0x{:08X}".format(symbol_dest_address))
if not symbol_dest_address:
ea += symbol_interval
continue

# Get symbol name
symbols = target.get_symbols()
for symbol in symbols:
try:
r2_command = "pszj @0x{:08X}".format(symbol_name_address)
symbol_name_string = r2p.cmdj(r2_command)['string']
symbol_name = symbol["symbol_name"]
symbol_name_addr = symbol["symbol_name_addr"]
symbol_dest_addr = symbol["symbol_dest_addr"]
symbol_type = symbol["symbol_flag"]
add_symbol(symbol_name, symbol_name_addr, symbol_dest_addr, symbol_type)

except Exception as err:
print("Exception: {}".format(err))
pass

# create functions
if symbol_name_string:
if symbol_flag in need_create_function:
r2_command = "fs functions; f {} @ 0x{:08X}".format(symbol_name_string, symbol_dest_address)
r2p.cmd(r2_command)
# TODO: Need find a way to disable warnning "af: Cannot find function at"
r2_command = "af {} 0x{:08X}".format(symbol_name_string, symbol_dest_address)
r2p.cmd(r2_command)

else:
r2_command = "fs symbols; f {} @ 0x{:08X}".format(symbol_name_string, symbol_dest_address)
r2p.cmd(r2_command)

# TODO: set other symbol labels
# Need find how to do it.
ea += symbol_interval
continue

flags = r2p.cmdj("fsj")
function_count = 0
Expand Down
116 changes: 66 additions & 50 deletions firmware_tools/vxhunter_r2_py3.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
]

need_create_function = [
0x0500,
0x050000
0x04,
0x05
]


Expand All @@ -69,6 +69,7 @@ def __init__(self, firmware, vx_version=5, big_endian=False, logger=None):
self.symbol_table_end = None
self._string_table = []
self._symbol_table = []
self.symbols = []
self.load_address = None
self._firmware = firmware
self._has_symbol = None
Expand Down Expand Up @@ -235,6 +236,7 @@ def find_symbol_table(self):
if self.symbol_table_start:
for i in range(self.symbol_table_start, len(self._firmware), self._symbol_interval):
check_data = self._firmware[i:i + self._symbol_interval]

if len(check_data) < self._symbol_interval:
self.logger.debug("Check_data length is too small")
break
Expand Down Expand Up @@ -264,6 +266,7 @@ def get_symbol_table(self):
for i in range(self.symbol_table_start, self.symbol_table_end, self._symbol_interval):
symbol_name_addr = self._firmware[i + 4:i + 8]
symbol_dest_addr = self._firmware[i + 8:i + 12]
symbol_flag = self._firmware[i + self._symbol_interval - 2]
if self.big_endian:
unpack_format = '>I'
else:
Expand All @@ -276,6 +279,7 @@ def get_symbol_table(self):
'symbol_name_addr': symbol_name_addr,
'symbol_name_length': None,
'symbol_dest_addr': symbol_dest_addr,
'symbol_flag': symbol_flag,
'offset': i
})
# self.logger.debug("self._symbol_table: %s" % self._symbol_table)
Expand Down Expand Up @@ -624,6 +628,38 @@ def cleanup(self):
self.load_address = None
self._has_symbol = None

def get_string_from_firmware_by_offset(self, string_offset):
symbol_name = ""
while True:
if self._firmware[string_offset] != 0x00:
symbol_name += chr(self._firmware[string_offset])
string_offset += 1

else:
break

return symbol_name

def get_symbols(self):
self.symbols = []
if self.load_address:
for symbol in self._symbol_table:
symbol_name_addr = symbol["symbol_name_addr"]
symbol_dest_addr = symbol["symbol_dest_addr"]
symbol_flag = symbol["symbol_flag"]
symbol_name_firmware_addr = symbol_name_addr - self.load_address
symbol_name = self.get_string_from_firmware_by_offset(symbol_name_firmware_addr)
self.symbols.append({
"symbol_name": symbol_name,
"symbol_name_addr": symbol_name_addr,
"symbol_dest_addr": symbol_dest_addr,
"symbol_flag": symbol_flag
})
return self.symbols

else:
return None


def demangle_function(demangle_string):
function_return = None
Expand Down Expand Up @@ -667,7 +703,7 @@ def demangle_function(demangle_string):
def autodetect_vxworks_version(r2p):
''' Naive way to autodetect VxWorks version '''
vx_version = None
# TODO: replace with cmdj and izzzj later, currently izzzj is not stable.
# TODO: replace with cmdj and izzj later, currently izzj is not stable.
vx_version_r2p = r2p.cmd("izz~VxWorks")
if 'VxWorks5' in vx_version_r2p:
vx_version = 5
Expand Down Expand Up @@ -696,6 +732,23 @@ def manual_vxworks_version():
return None


def add_symbol(symbol_name, symbol_name_address, symbol_address, symbol_type):
# Load symbols
if symbol_name:
if symbol_type in need_create_function:
r2_command = "fs functions; f {} @ 0x{:08X}".format(symbol_name, symbol_address)
r2p.cmd(r2_command)
# TODO: Need find a way to disable warnning "af: Cannot find function at"
r2_command = "af {} 0x{:08X}".format(symbol_name, symbol_address)
r2p.cmd(r2_command)

else:
r2_command = "fs symbols; f {} @ 0x{:08X}".format(symbol_name, symbol_address)
r2p.cmd(r2_command)

return


if __name__ == '__main__':
print("Running with python version: {}".format(sys.version))
r2p = r2pipe.open()
Expand Down Expand Up @@ -761,62 +814,25 @@ def manual_vxworks_version():
r2p.cmd(r2_command)

####################
# Create Functions #
# Load symbols #
####################

# Check endian
print("\n###### Start analyzing functions######")
if target.big_endian:
r2p.cmd("e cfg.bigendian=True")

symbol_table_start_address += image_load_address
symbol_table_end_address += image_load_address
print("symbol_table_start_address: 0x{:08X}".format(symbol_table_start_address))
print("symbol_table_end_address: 0x{:08X}".format(symbol_table_end_address))
symbol_interval = 16
if vx_version == 6:
symbol_interval = 20
ea = symbol_table_start_address
while ea < symbol_table_end_address:
symbol_name_string = None
offset = 4
r2_command = "pv4j @0x{:08X}".format(ea + symbol_interval - 4)
symbol_flag = r2p.cmdj(r2_command)[0]['value']
r2_command = "pv4j @0x{:08X}".format(ea + offset)
symbol_name_address = r2p.cmdj(r2_command)[0]['value']
r2_command = "pv4j @0x{:08X}".format(ea + offset + 4)
symbol_dest_address = r2p.cmdj(r2_command)[0]['value']
# print("symbol_flag: 0x{:08X}".format(symbol_flag))
# print("symbol_name_address: 0x{:08X}".format(symbol_name_address))
# print("symbol_dest_address: 0x{:08X}".format(symbol_dest_address))
if not symbol_dest_address:
ea += symbol_interval
continue

# Get symbol name
symbols = target.get_symbols()
for symbol in symbols:
try:
r2_command = "pszj @0x{:08X}".format(symbol_name_address)
symbol_name_string = r2p.cmdj(r2_command)['string']
symbol_name = symbol["symbol_name"]
symbol_name_addr = symbol["symbol_name_addr"]
symbol_dest_addr = symbol["symbol_dest_addr"]
symbol_type = symbol["symbol_flag"]
add_symbol(symbol_name, symbol_name_addr, symbol_dest_addr, symbol_type)

except Exception as err:
print("Exception: {}".format(err))
pass

# create functions
if symbol_name_string:
if symbol_flag in need_create_function:
r2_command = "fs functions; f {} @ 0x{:08X}".format(symbol_name_string, symbol_dest_address)
r2p.cmd(r2_command)
# TODO: Need find a way to disable warnning "af: Cannot find function at"
r2_command = "af {} 0x{:08X}".format(symbol_name_string, symbol_dest_address)
r2p.cmd(r2_command)

else:
r2_command = "fs symbols; f {} @ 0x{:08X}".format(symbol_name_string, symbol_dest_address)
r2p.cmd(r2_command)

# TODO: set other symbol labels
# Need find how to do it.
ea += symbol_interval
continue

flags = r2p.cmdj("fsj")
function_count = 0
Expand Down

0 comments on commit 18480df

Please sign in to comment.