Skip to content

Commit

Permalink
fix python3.9 bug and Ghidra 10.1.5 key error
Browse files Browse the repository at this point in the history
  • Loading branch information
clearbluejar committed Oct 20, 2023
1 parent a53e4f9 commit fe943f0
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 33 deletions.
36 changes: 26 additions & 10 deletions ghidriff/ghidra_diff_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ def add_ghidra_args_to_parser(parser: argparse.ArgumentParser) -> None:
"""

group = parser.add_argument_group('Ghidra Project Options')
group.add_argument('-p', '--project-location', help='Ghidra Project Path', default='.ghidra_projects')
group.add_argument('-p', '--project-location', help='Ghidra Project Path', default='ghidra_projects')
group.add_argument('-n', '--project-name', help='Ghidra Project Name', default='ghidriff')
group.add_argument('-s', '--symbols-path', help='Ghidra local symbol store directory', default='.symbols')
group.add_argument('-s', '--symbols-path', help='Ghidra local symbol store directory', default='symbols')

group = parser.add_argument_group('Engine Options')
group.add_argument('--threaded', help='Use threading during import, analysis, and diffing. Recommended',
Expand Down Expand Up @@ -195,6 +195,12 @@ def add_ghidra_args_to_parser(parser: argparse.ArgumentParser) -> None:
help='Max number of functions to display per section.', type=int, default=200)
group.add_argument('--md-title', help='Overwrite default title for markdown diff', type=str, default=None)

def get_ghidra_version(self) -> str:

from pyhidra.version import get_ghidra_version

return get_ghidra_version()

def get_default_args(self) -> list:
"""
Return list of default args for engine
Expand Down Expand Up @@ -744,6 +750,10 @@ def analyze_program(self, df_or_prog: Union["ghidra.framework.model.DomainFile",
self.set_analysis_option_bool(
program, 'Shared Return Calls.Assume Contiguous Functions Only', False)

# TODO make this argument optional, or provide custom analyzer config parsing
# This really helps with decompilation, was turned off by default in 10.x
# self.set_analysis_option_bool(program, 'Decompiler Parameter ID', True)

if self.no_symbols:
self.logger.warn(f'Disabling symbols for analysis! --no-symbols flag: {self.no_symbols}')
self.set_analysis_option_bool(program, 'PDB Universal', False)
Expand Down Expand Up @@ -1314,20 +1324,20 @@ def diff_bins(
old_instructions = ematch_1['instructions']
new_instructions = ematch_2['instructions']

instructions_ratio = round(difflib.SequenceMatcher(None, old_instructions, new_instructions).ratio(),2)
instructions_ratio = round(difflib.SequenceMatcher(None, old_instructions, new_instructions).ratio(), 2)

old_mnemonics = ematch_1['mnemonics']
new_mnemonics = ematch_2['mnemonics']

mnemonics_ratio = round(difflib.SequenceMatcher(None, old_mnemonics, new_mnemonics).ratio(),2)
mnemonics_ratio = round(difflib.SequenceMatcher(None, old_mnemonics, new_mnemonics).ratio(), 2)

old_blocks = ematch_1['blocks']
new_blocks = ematch_2['blocks']

blocks_ratio = round(difflib.SequenceMatcher(None, old_blocks, new_blocks).ratio(),2)
blocks_ratio = round(difflib.SequenceMatcher(None, old_blocks, new_blocks).ratio(), 2)

# ignore signature for ratio
ratio = round(difflib.SequenceMatcher(None, old_code_no_sig, new_code_no_sig).ratio(),2)
ratio = round(difflib.SequenceMatcher(None, old_code_no_sig, new_code_no_sig).ratio(), 2)

self.normalize_ghidra_decomp(old_code)
self.normalize_ghidra_decomp(new_code)
Expand Down Expand Up @@ -1425,10 +1435,16 @@ def diff_bins(
pdiff['new_meta'] = self.get_metadata(p2)

# add pe url
if 'visualstudio' in p1.compiler:
pdiff['old_pe_url'] = self.get_pe_download_url(old, pdiff['old_meta']['PE Property[OriginalFilename]'])
if 'visualstudio' in p1.compiler:
pdiff['new_pe_url'] = self.get_pe_download_url(new, pdiff['new_meta']['PE Property[OriginalFilename]'])
if 'visualstudio' in p1.compiler and 'visualstudio' in p2.compiler:

if pdiff['old_meta'].get('OriginalFilename') is not None:
# handle Ghidra pe_key before 10.2
pe_key = 'OriginalFilename'
else:
pe_key = 'PE Property[OriginalFilename]'

pdiff['old_pe_url'] = self.get_pe_download_url(old, pdiff['old_meta'][pe_key])
pdiff['new_pe_url'] = self.get_pe_download_url(new, pdiff['new_meta'][pe_key])

pdiff['md_credits'] = self.gen_credits()
pdiff['html_credits'] = self.gen_credits(html=True)
Expand Down
54 changes: 31 additions & 23 deletions ghidriff/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def gen_esym_table_diff_meta(self, old_name, new_name, modified) -> str:
count = 1
for key in keys:
val = modified[key]
if isinstance(val,list):
if isinstance(val, list):
val = ','.join(val)
table_list.extend([key, val])
count += 1
Expand Down Expand Up @@ -268,23 +268,22 @@ def gen_code_table_diff_html(old_code,
if isinstance(new_code, str):
new_code = new_code.splitlines(True)

match html_type:
case 'inline':
styles = '<style type="text/css">%(styles)s\n</style>' % dict(
styles=difflib.HtmlDiff(tabsize=tabsize)._styles)
table = difflib.HtmlDiff(tabsize=tabsize).make_table(
old_code, new_code, fromdesc=old_name, todesc=new_name)

diff_html = styles + table
diff_html.encode(charset, 'xmlcharrefreplace').decode(charset)
case 'table-only':
diff_html = difflib.HtmlDiff(tabsize=4).make_table(
old_code, new_code, fromdesc=old_name, todesc=new_name)
case 'file':
diff_html = difflib.HtmlDiff(tabsize=tabsize).make_file(
old_code, new_code, fromdesc=old_name, todesc=new_name)
case _:
raise NotImplementedError
if html_type == 'inline':
styles = '<style type="text/css">%(styles)s\n</style>' % dict(
styles=difflib.HtmlDiff(tabsize=tabsize)._styles)
table = difflib.HtmlDiff(tabsize=tabsize).make_table(
old_code, new_code, fromdesc=old_name, todesc=new_name)

diff_html = styles + table
diff_html.encode(charset, 'xmlcharrefreplace').decode(charset)
elif html_type == 'table-only':
diff_html = difflib.HtmlDiff(tabsize=4).make_table(
old_code, new_code, fromdesc=old_name, todesc=new_name)
elif html_type == 'file':
diff_html = difflib.HtmlDiff(tabsize=tabsize).make_file(
old_code, new_code, fromdesc=old_name, todesc=new_name)
else:
raise NotImplementedError

if dedent_table:
diff_html = diff_html.splitlines(True)
Expand Down Expand Up @@ -519,12 +518,21 @@ def _decode_arch(proc, addr_size):
new_url = pdiff['new_pe_url']

# PE Property[OriginalFilename]: localspl.dll
old_filename = pdiff['old_meta']['PE Property[OriginalFilename]'].lower()
new_filename = pdiff['new_meta']['PE Property[OriginalFilename]'].lower()

if pdiff['old_meta'].get('OriginalFilename') is not None:
# handle Ghidra pe_key before 10.2
pe_key = 'OriginalFilename'
ver_key = 'ProductVersion'
else:
pe_key = 'PE Property[OriginalFilename]'
ver_key = 'PE Property[ProductVersion]'

old_filename = pdiff['old_meta'][pe_key].lower()
new_filename = pdiff['new_meta'][pe_key].lower()

# PE Property[ProductVersion]: 10.0.22000.795
old_ver = pdiff['old_meta']['PE Property[ProductVersion]']
new_ver = pdiff['new_meta']['PE Property[ProductVersion]']
old_ver = pdiff['old_meta'][ver_key]
new_ver = pdiff['new_meta'][ver_key]

# Processor: x86
# Address Size: 64
Expand Down Expand Up @@ -595,7 +603,7 @@ def gen_diff_md(
known_cmd, extra_cmd, full_cmd = self.gen_diff_cmd_line(old_name, new_name)
md.new_header(4, 'Captured Command Line', add_table_of_contents='n')
md.new_paragraph(self._wrap_with_code(known_cmd))
md.new_header(4, 'Verbose Args', add_table_of_contents='n')
md.new_header(4, 'Verbose Args', add_table_of_contents='n')
md.new_paragraph(self._wrap_with_details(self._wrap_with_code(full_cmd)))

if pdiff.get('old_pe_url') is not None and pdiff.get('new_pe_url') is not None:
Expand Down

0 comments on commit fe943f0

Please sign in to comment.