<commit_before>import sys
import vivisect
import vivisect.impemu.monitor as viv_monitor

from vivisect import LOC_STRING, LOC_UNI, REF_DATA

MAX_INIT_OPCODES = 30

def reprPointer(vw, va):
    """
    Do your best to create a humon readable name for the
    value of this pointer.
    """
    if va == 0:
        return "NULL"

    loc = vw.getLocation(va)
    if loc != None:
        locva, locsz, lt, ltinfo = loc
        if lt in (LOC_STRING, LOC_UNI):
            return vw.reprVa(locva)

    mbase,msize,mperm,mfile = vw.memobj.getMemoryMap(va)
    ret = mfile
    sym = vw.getName(va)
    if sym != None:
        ret = sym
    return ret

class AnalysisMonitor(viv_monitor.AnalysisMonitor):

    def __init__(self, vw, fva):
        viv_monitor.AnalysisMonitor.__init__(self, vw, fva)
        self.reg = vw.getFunctionMeta(fva, 'PIE_reg')
        self.tracker = {}

    def prehook(self, emu, op, starteip):
        viv_monitor.AnalysisMonitor.prehook(self, emu, op, starteip)

    def posthook(self, emu, op, starteip):
        viv_monitor.AnalysisMonitor.posthook(self, emu, op, starteip)
        if len(op.opers) > 1:
            # TODO: future: make this getRegister() for the registers... look for .GOT
            oper = op.opers[1]
            if (hasattr(oper, 'reg') and oper.reg == self.reg) \
                    or (hasattr(oper, 'base_reg') and oper.base_reg == self.reg):
                # second operand has the register we're interested in for this function
                tgt = op.getOperValue(0, emu)
                if tgt == None:
                    print "0x%x: %s   tgt == None!" % (op.va, op)
                    return

                self.tracker[op.va] = tgt
                #print("%x  %s" % (op.va, self.vw.reprVa(tgt)))


def analyzeFunction(vw, fva, prepend=False):
    '''
    this analysis module will identify thunk_reg functions, which place the .GOT pointer
    into some register which is then accessed later.  
    doing so allows for position-independent code.

    store funcva in "thunk_reg" VaSet in case we identify multiples (not likely) or misidentify 
    something.

    then store the module base in metadata as "PIE_GOT", accessible by other analysis modules.
    then store the register used in this function in function metadata as "PIE_reg"
    '''
    got = None
    for segva, segsz, segnm, segimg in vw.getSegments():
        if segnm == '.got':
            got = segva
            break

    # if we don't have a segment named ".got" we fail.
    if got == None: 
        return

    # roll through the first few opcodes looking for one to load a register with .got's address
    success = 0
    tva = fva
    emu = vw.getEmulator()

    for x in range(MAX_INIT_OPCODES):
        op = vw.parseOpcode(tva)
        emu.executeOpcode(op)
        if not len(op.opers):
            continue

        operval = op.getOperValue(0, emu)
        if operval == got:
            success = True

            reg = op.opers[0].reg
            vw.setVaSetRow('thunk_reg', (fva, reg))

            if vw.getFunctionMeta(fva, 'PIE_reg') == None:
                vw.setFunctionMeta(fva, 'PIE_reg', reg)
                vw.setComment(op.va, 'Position Indendent Code Register Set: %s' % \
                        vw.arch._arch_reg.getRegisterName(reg))

            if vw.getMeta('PIE_GOT') == None:
                vw.setMeta('PIE_GOT', got)
            break

        tva += len(op)

    if not success: <commit_msg>update for reg-thunks: don't emulate past function-end!<commit_after>import sys
import envi
import vivisect
import vivisect.impemu.monitor as viv_monitor

from vivisect import LOC_STRING, LOC_UNI, REF_DATA

MAX_INIT_OPCODES = 30

def reprPointer(vw, va):
    """
    Do your best to create a humon readable name for the
    value of this pointer.
    """
    if va == 0:
        return "NULL"

    loc = vw.getLocation(va)
    if loc != None:
        locva, locsz, lt, ltinfo = loc
        if lt in (LOC_STRING, LOC_UNI):
            return vw.reprVa(locva)

    mbase,msize,mperm,mfile = vw.memobj.getMemoryMap(va)
    ret = mfile
    sym = vw.getName(va)
    if sym != None:
        ret = sym
    return ret

class AnalysisMonitor(viv_monitor.AnalysisMonitor):

    def __init__(self, vw, fva):
        viv_monitor.AnalysisMonitor.__init__(self, vw, fva)
        self.reg = vw.getFunctionMeta(fva, 'PIE_reg')
        self.tracker = {}

    def prehook(self, emu, op, starteip):
        viv_monitor.AnalysisMonitor.prehook(self, emu, op, starteip)

    def posthook(self, emu, op, starteip):
        viv_monitor.AnalysisMonitor.posthook(self, emu, op, starteip)
        if len(op.opers) > 1:
            # TODO: future: make this getRegister() for the registers... look for .GOT
            oper = op.opers[1]
            if (hasattr(oper, 'reg') and oper.reg == self.reg) \
                    or (hasattr(oper, 'base_reg') and oper.base_reg == self.reg):
                # second operand has the register we're interested in for this function
                tgt = op.getOperValue(0, emu)
                if tgt == None:
                    print "0x%x: %s   tgt == None!" % (op.va, op)
                    return

                self.tracker[op.va] = tgt
                #print("%x  %s" % (op.va, self.vw.reprVa(tgt)))


def analyzeFunction(vw, fva, prepend=False):
    '''
    this analysis module will identify thunk_reg functions, which place the .GOT pointer
    into some register which is then accessed later.  
    doing so allows for position-independent code.

    store funcva in "thunk_reg" VaSet in case we identify multiples (not likely) or misidentify 
    something.

    then store the module base in metadata as "PIE_GOT", accessible by other analysis modules.
    then store the register used in this function in function metadata as "PIE_reg"
    '''
    got = None
    for segva, segsz, segnm, segimg in vw.getSegments():
        if segnm == '.got':
            got = segva
            break

    # if we don't have a segment named ".got" we fail.
    if got == None: 
        return

    # roll through the first few opcodes looking for one to load a register with .got's address
    success = 0
    tva = fva
    emu = vw.getEmulator()

    for x in range(MAX_INIT_OPCODES):
        op = vw.parseOpcode(tva)
        emu.executeOpcode(op)

        if op.iflags & envi.IF_NOFALL:
            break

        if not len(op.opers):
            continue

        operval = op.getOperValue(0, emu)
        if operval == got:
            success = True

            reg = op.opers[0].reg
            vw.setVaSetRow('thunk_reg', (fva, reg))

            if vw.getFunctionMeta(fva, 'PIE_reg') == None:
                vw.setFunctionMeta(fva, 'PIE_reg', reg)
                vw.setComment(op.va, 'Position Indendent Code Register Set: %s' % \
                        vw.arch._arch_reg.getRegisterName(reg))

            if vw.getMeta('PIE_GOT') == None:
                vw.setMeta('PIE_GOT', got)
            break

        tva += len(op)

    if not success: 
{'fraction_non_alphanumeric': 0.09987214092910925, 'fraction_numerical': 0.0028413126864611452, 'mean_word_length': 2.076923076923077, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6065852', 'n_tokens_mistral': 2346, 'n_tokens_neox': 2249, 'n_words': 676}