Created
January 3, 2011 10:05
-
-
Save ktf/763318 to your computer and use it in GitHub Desktop.
A simple script which dumps all the addresses for call/callq instructions of a given process.
This file contains 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 | |
from optparse import OptionParser | |
from commands import getstatusoutput | |
from sys import exit | |
description="""A simple script which dumps all the addresses for call/callq instructions of a given process. | |
""" | |
if __name__ == "__main__": | |
parser = OptionParser(usage="%prog <pid>", description=description) | |
parser.add_option("--json", "-j", dest="json", help="dump output as JSON dictionary", action="store_true", default=False) | |
opts, args = parser.parse_args() | |
if len(args) != 1: | |
parser.error("PID not specified.") | |
exit(1) | |
# Get the loaded libraries and the address at which they where loaded. | |
addrs = {} | |
vmbases = {} | |
symbols = [] | |
callsites = [] | |
error, output = getstatusoutput('pmap %s | grep -v -e "[[][ ].*[ ][]]" | grep -e "r.x--" | sort -u -k 4' % args[0]) | |
if error: | |
parser.error("Cannot run pmap on PID %s\n%s " % (args[0], output)) | |
exit(1) | |
# Get the load address for all the loaded libraries. | |
for line in output.splitlines(): | |
addr, size, perm, filename = (x for x in line.split(" ") if x) | |
addrs[filename] = int(addr, 16) | |
# Get the vmbase for the executable section of each loaded library. | |
for filename in addrs.keys(): | |
error, output = getstatusoutput("objdump -p %s | grep LOAD | head -1" % filename) | |
if error: | |
print "Error while parsing the VMBASE for %s" % filename | |
# Format: | |
# LOAD off 0x0000000000000000 vaddr 0x00000036d2000000 paddr 0x00000036d2000000 align 2**21 | |
d1, d2, offset, d3, vmbase, d4, paddr, d5, d6 = (x for x in output.split(" ") if x) | |
vmbases[filename] = int(vmbase, 16) | |
# Parse the disassembly and get the symbols and the call / callq addresses. | |
symbols.append("<unknown>") | |
currentSymbolIndex = 0 | |
for filename in addrs.keys(): | |
error, output = getstatusoutput('objdump -D %s | grep "\(call\|>:\)"' % filename) | |
if error: | |
print "Error while disassebling." | |
currentOffset = addrs[filename] | |
currentBase = vmbases[filename] | |
for line in output.splitlines(): | |
if line.startswith(" "): | |
address = int([x for x in line.split(":", 1) if x][0], 16) | |
# This is the code which calculates the actual virtual address. | |
vaddress = address - currentBase + currentOffset | |
callsites.append((vaddress, currentSymbolIndex)) | |
if not opts.json: | |
print "%s, %s" % (vaddress, symbols[currentSymbolIndex]) | |
elif line.endswith(":"): | |
symbol = line.rstrip(">:").split("<")[1] | |
symbols.append(symbol) | |
currentSymbolIndex += 1 | |
if opts.json: | |
print "[" | |
print symbols, "," | |
print dict(callsites) | |
print "]" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment