IMF-hook.py

2018-04-18  本文已影响0人  Dosi_X

定义了三个类和一个函数
这个.py作用在于生成hook的文件

class Hooker:

def __init__(self):
    调用basic.load_apis(),返回值赋给self.apis

def gen_hook(self, fn_hook):
    const.HEADER赋值给code
    const.HOOK_TABLE_TEMPLATE赋值给table
    const.HOOK_ENTRY_TEMPLATE赋值给entry
    tmp = ''
    name, api遍历self.apis:
        调用ApiHook(api)赋给h
        code += h.log()
        temp += entry%h.hook_entry()
    code += table%tmp
    以可写方式打开文件fn_hook,把code写入

class ApiHook(basic.Api):

def __init__(self, api):
    self.__dict__ = api.__dict__.copy()
    self.arghooks = []存放要hook的所有args
    遍历self.args:
        self.arghooks.append(ArgHook(arg))

def list_args(self, show_type):
    ret = ''
    遍历self.arghooks:
        如果show_type为真:
            ret追加上arghook的type和name
        否则ret追加上name
    返回ret

def log(self):
    body = self.log_intro()
    body += self.log_input()
    body += self.call_ori()
    body += self.log_output()
    args = self.list_args(True)True即要返回type
    返回self.rtype,self.name,args,body

def log_intro(self):
    intro = '\tFILE *fp = fopen(log_path,"a");\n'
    intro +='\tflock(fileno(fp),LOCK_EX);\n'
    return intro

def log_input(self):
    ret = ''
    遍历self.arghooks:
        如果arghook.is_input()为真:
            ret += arghook.log()
    ret = '''\tfprintf(fp,"IN ['%s',");\n'''%(self.name) +ret
    return ret +'''\tfprintf(fp,"]\\n");\n'''

def call_ori(self):
    args = self.list_args(False)
    if self.is_void()为真:
        return  '\t%s(%s);\n'%(self.name, args)
    return '\t%s ret = %s(%s);\n'%(self.rtype,self.name, args)  
    
def log_output(self):
    ret = ArgHook(self.rval).log()
    遍历self.arghooks:
        如果arg是output:
            ret += arghook.log()
    ret = '''\tfprintf(fp,"OUT ['%s',");\n'''%(self.name) +ret
    ret += '''\tfprintf(fp,"]\\n");\n'''
    ret += '\tfclose(fp);\n'
    如果返回值不为空:
        ret += '\treturn ret;\n'
    返回ret

def hook_entry(self):
    return ('fake_%s'%self.name, self.name)

class ArgHook(basic.Arg):

def __init__(self, arg):
    self.__dict__ = arg.__dict__.copy()

def log(self):
    如果self.name == const.RVAL并且self.type=='void':
        返回''
    ret, add, add_arg = '', '', ''
    如果self.is_input()为真且self.name不为const.RVAL且self.type在const.CHECK_ORIGINAL里:
        ret += '''\tchar name_buf[0x100];\n'''
        ret += '''\tIORegistryEntryGetName(%s,name_buf);\n'''%self.name 
        add += "'ori':'IOServiceGetMatchingService(0,IOServiceMatching(\\\"%s\\\"))',"
        add_arg+= ',name_buf'
    log_name = self.get_log_name()
    fmt = self.get_fmt()
    ret += '\tif(%s) '%(self.valid_ptr())
    ret += '''fprintf(fp,"{'name':'%s','''%self.name
    ret += ''''value': %s,'''%fmt
    ret += ''''size' : 0x%%lx,'cnt':0x%%x,%s '''%add
    ret += ''''data':[",%s, sizeof(%s),'''%(log_name, self.type)
    ret += '''%s%s);\n '''%(self.get_opt('cnt'), add_arg)
    ret += '''\telse fprintf(fp,"{'name':'%s','''%self.name
    ret += ''''value': %s, '''%fmt
    ret += ''''size' : 0x%%lx,'cnt':'undefined',%s '''%add
    ret += ''''data':[",%s,sizeof(%s)%s);\n'''%(log_name, self.type, add_arg)
    如果参数是指针:
        ret += self.log_ptr()
    如果self.is_input()为真且self.name不为const.RVAL且self.type在const.CHECK_CF里:
        ret += '''\tfprintf(fp,"],'ori':");\n'''
        ret += '''\tlog_CFTypeRef(fp,%s);\n'''%self.name
        ret += '''\tfprintf(fp,"},");\n'''
    否则 :
        ret += '''\tfprintf(fp,"]},");\n '''
    返回ret

def log_ptr(self):如果是指针
    template = '''\tif(%s){\n\t\tfor(int i=0; i<%s;i++){\n%s\t\t}\n\t}\n'''
    name = self.name
    如果类型为void *:
        name = '((uint8_t *) %s)'%name
    body = '''\t\t\tfprintf(fp,"%s,",%s[i]);\n'''%(self.get_fmt(True), name)
    return template%(self.valid_ptr(self.name), self.get_opt('cnt'), body)

def get_log_name(self):
    name = self.name
    如果类型为'CFStringRef':
        返回 'CFStringGetCStringPtr(%s,kCFStringEncodingMacRoman)'%name
    返回name

def get_fmt(self, for_ptr = False):
    把self.type里的const替换为'',赋给ty
    如果ty在const.TYPE_FMT里:
        返回const.TYPE_FMT[ty]
    如果for_ptr为假且参数为指针:
        返回'%p'
    返回const.SIZE_FMT[self.get_opt('size')]

def valid_ptr(self, init='1'):
    ret = init
    cnt = str(self.get_opt('cnt'))
    遍历cnt:
        如果出现了*就break
        ret = '%s && '%cnt[idx+1:]+ret
    返回ret
上一篇下一篇

猜你喜欢

热点阅读