Files
James Gross 3f8c3141fb Relocatable ELF Support (#531)
* wip

* still some cleanup I wanna do but it's mostly there

* back out a few things and make dynamics win more

* fixup elf tests

* cleanup

* moar data

* test data
2022-07-22 00:30:12 -04:00

113 lines
3.8 KiB
Python

"""
generic workspace analysis module to seek through the undiscovered
country looking for pointers to interesting things.
in a previous life, this analysis code lived inside VivWorkspace.analyze()
"""
import logging
import envi.exc as e_exc
import visgraph.exc as g_exc
import visgraph.graphcore as g_core
from vivisect.const import RTYPE_BASEPTR, LOC_POINTER
logger = logging.getLogger(__name__)
def analyze(vw):
logger.info('...analyzing pointers.')
done = {}
# Let's analyze Relocations we know are pointers
for rva, rtype in vw.reloc_by_va.items():
if rtype != RTYPE_BASEPTR:
continue
for xfr, xto, xtype, xinfo in vw.getXrefsFrom(rva):
logger.debug('pointer(xref): 0x%x -> 0x%x', xfr, xto)
try:
vw.analyzePointer(xto)
except e_exc.SegmentationViolation:
continue
done[xfr] = xto
# Now, we'll analyze the pointers placed by the file wrapper (ELF, PE, MACHO, etc...)
for pva, tva, fname, pname in vw.getVaSetRows('PointersFromFile'):
if vw.getLocation(pva) is None:
if tva is None:
logger.debug('making pointer(fromFile) 0x%x (%r)', pva, pname)
else:
logger.debug('making pointer(fromFile) 0x%x -> 0x%x (%r)', pva, tva, pname)
vw.makePointer(pva, tva, follow=True)
done[pva] = tva
for lva, lsz, lt, li in vw.getLocations(LOC_POINTER):
tva = vw.readMemoryPtr(lva)
if not vw.isValidPointer(tva):
continue
if vw.getLocation(tva) is not None:
# event if it's a pointer, we may not have made a name for it
if vw.getName(lva) is None:
done[lva] = tva
continue
logger.debug('following previously discovered pointer 0x%x -> 0x%x', lva, tva)
try:
logger.debug('pointer: 0x%x -> 0x%x', lva, tva)
vw.followPointer(tva)
done[lva] = tva
except Exception as e:
logger.error('followPointer() failed for 0x%.8x (pval: 0x%.8x) (err: %s)', lva, tva, e)
# Now, lets find likely free-hanging pointers
for addr, pval in vw.findPointers():
if vw.isDeadData(pval):
continue
try:
logger.debug('make pointer(found): 0x%x -> 0x%x', addr, pval)
vw.makePointer(addr, follow=True)
done[addr] = pval
except Exception as e:
logger.error('makePointer() failed for 0x%.8x (pval: 0x%.8x) (err: %s)', addr, pval, e)
# link the possible pointers up
pgraph = g_core.Graph()
while done:
ptr, tgt = done.popitem()
try:
pgraph.addNode(ptr)
except g_exc.DuplicateNode:
pass
try:
pgraph.addNode(tgt)
except g_exc.DuplicateNode:
pass
pgraph.addEdgeByNids(ptr, tgt)
leafs = [node for node in pgraph.getNodes() if pgraph.isLeafNode(node)]
for leaf in leafs:
va, props = leaf
name = vw.getName(va)
# if there's not a name at the bottom, not work making ptr names
if not name:
continue
links = [(ptr, tgt) for edge, ptr, tgt, props in pgraph.getRefsToByNid(va)]
while links:
ptr, tgt = links.pop(0)
pname = vw.getName(ptr)
if pname:
continue
if not vw.isLocType(ptr, LOC_POINTER):
continue
tgtname = vw.getName(tgt)
if tgtname:
name = vw._addNamePrefix(tgtname, tgt, 'ptr', '_') + '_%.8x' % ptr
logger.debug('0x%x: adding name prefix: %r (%r)', tgt, tgtname, name)
vw.makeName(ptr, name)
for edge, n1, n2, props in pgraph.getRefsToByNid(ptr):
links.append((n1, n2))