Created
February 24, 2015 15:57
-
-
Save riyadparvez/45b7f457a303408867ad to your computer and use it in GitHub Desktop.
Run addr2line on all instructions in the binary. You need pybfd package.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# Import the disassembly library (libopcodes) | |
from pybfd.opcodes import Opcodes, OpcodesException | |
from pybfd.bfd import Bfd, BfdException | |
from sys import argv, exit | |
from subprocess import Popen, PIPE | |
def print_file_line_callback(address, size, branch_delay_insn, | |
insn_type, target, target2, disassembly): | |
""" | |
Callack on each disassembled instruction to print its information. | |
""" | |
#print("0x%X SZ=%d BD=%d IT=%d\t%s" % \ | |
# (address, size, branch_delay_insn, insn_type, disassembly)) | |
proc = Popen(["/usr/bin/addr2line", "-e", argv[1], "-C", "-f", "-p", "-a", address], stdout=PIPE, stderr=PIPE); | |
stdout, stderr = proc.communicate() | |
print(stdout) | |
return PYBFD_DISASM_CONTINUE | |
if len(argv) == 1: | |
print("Usage : %s <filename>" % argv[0]) | |
exit(0) | |
bfd = None | |
path = None | |
try: | |
# | |
# Initialize BFD instance. | |
# We can either pass a filename or a file descriptor and they will be used | |
# in the same way. | |
# | |
print("[+] Creating BFD instance...") | |
path = argv[1] | |
bfd = Bfd(path) | |
# Print the file format and in case that its an archive then just show | |
# its files and leave. | |
print("[+] File format : %s" % bfd.file_format_name) | |
if bfd.is_archive: | |
print("[-] List of internal files:") | |
#for inner_filename in bfd.archive_filenames: | |
# print "\t%s" % inner_filename | |
for inner_bfd in bfd.archive_files: | |
print("\t%-40s - sections : %d - symbols : %s" % \ | |
(inner_bfd.filename, | |
len(inner_bfd.sections), | |
len(inner_bfd.symbols))) | |
# The bfd.close() is executed below in the finally clause. | |
exit(0) | |
# | |
# Display some information about the currently open file. | |
# | |
print("[+] Architecture : %s (%d)" % \ | |
(bfd.architecture_name, bfd.architecture)) | |
print("[+] BFD target name : %s" % bfd.target) | |
print("[+] Entry point : 0x%X" % bfd.start_address) | |
print("[+] Sections : %d" % len(bfd.sections)) | |
#print "\n".join([str(s) for s in bfd.sections]) | |
# | |
# Get the .text section for further usage. | |
# | |
section_name = ".text" | |
section = bfd.sections.get(section_name) | |
if not section: | |
print("[-] No section \'%s\' available." % section_name) | |
exit(0) | |
# | |
# Display its name (we get it from the section instance) and its index | |
# inside the binary file. | |
# | |
print("[+] Selected section information:") | |
print("\tName : %s" % section.name) | |
print("\tIndex : %d" % section.index) | |
# Dump the section content to a buffer | |
content = section.content | |
# Display approximate section length. | |
length = len(content) / 1024 | |
if length == 0: | |
length = len(content) % 1024 | |
length_unit = "Bytes" | |
else: | |
length_unit = "Kbytes" | |
print("\tLength : %(length)d %(length_unit)s" % vars()) | |
# | |
# At this point we'll disassemble the entire section content. We'll obtain | |
# instruction address, size, type and disassembly (in text format). | |
# | |
try: | |
# Create opcodes instance to start code section disassembly. | |
opcodes = Opcodes(bfd) | |
# Set the code area we'll move through. | |
opcodes.initialize_smart_disassemble(content, section.vma) | |
# Set an internal -ready to use- callback function to print disassembly | |
# information from the current section content. | |
#opcodes.start_smart_disassemble(0, opcodes.print_single_instruction_callback) | |
#opcodes.start_smart_disassemble(0, print_file_line_callback) | |
except OpcodesException, err: | |
print("[-] Opcodes exception : %s" % err) | |
for vma, size, disasm in opcodes.disassemble(content, bfd.start_address): | |
print("0x%X (%d)\t %s" % (vma, size, disasm)) | |
proc = Popen(["/usr/bin/addr2line", "-e", path, "-C", "-f", "-p", "-a", str(vma)], stdout=PIPE, stderr=PIPE) | |
stdout, stderr = proc.communicate() | |
print(stdout) | |
#print(disasm, opcodes.build_instruction(vma, size, disasm)) | |
pass | |
except BfdException, err: | |
#print_exc() | |
print("Error : %s" % err) | |
finally: | |
if bfd: | |
# Check is we're working with an archive and close archived files | |
# before closing the container. | |
try: | |
# Release inner BFD files in case we're an archive BFD. | |
if bfd.is_archive: | |
[inner_bfd.close() for inner_bfd in bfd.archive_files] | |
except TypeError, err: | |
pass | |
# Release the current BFD and leave. | |
bfd.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment