利用ida python 实现复原函数调用的参数 (仅对数据被简单硬编码有效)



例如我们有一个 c 源程序


/*************************************************************************
	> File Name: ddg.c
	> Author: 
	> Mail: 
	> Created Time: 2017年08月24日 星期四 10时52分31秒
 ************************************************************************/

#include<stdio.h>
#define Version_Num "1.122"
#define Version_num 122
const int v_num = 1222;
const char * ver_num = "1.1.1222";
char *x = "Hello world";



int main(){

    int a = 112;
    a += 12;
    printf("Version is : %s, %d",x,a);

}

void print1 (){
    printf("print1 %s",Version_Num);
}

void print2(){
    printf("print2 %d",Version_num);
}

void print3(){
    printf("print3 %d ",v_num);
}

void print4(){
    printf("print4 %s",ver_num);
}



编译运行(本人使用了交叉编译,生成ARM平台下可执行文件)



然后使用所写脚本即可还原函数调用的参数,不过 脚本的输入是  printf的格式化字符串 例如:“print3 %d”

ida脚本如下:

#!/usr/bin/env python
# coding=utf-8

from idc import *
from idaapi import *
import idautils
class AnayBinFil(object):
    def __init__(self):
        list = []
    # 得到某一条汇编指令所指向的内存的内容 
    def GetXref_String(self,ea,n):
        if (GetOpType(ea,n) == 2):
            ea = GetOperandValue(ea,n)
        if (not SegName(ea) == '.rodata'):
            addrx = idautils.DataRefsFrom(ea)
            for item in addrx:
                return self.GetXref_String(item,n)
            return idc.Dword(ea)
        return GetString(ea)
        
    
    #get the register's content whose number is i from ea forward search
    def get_content_register(self,ea,i):
        #print hex(ea) , idc.GetDisasm(ea), i

        if (GetOpType(ea,0) == 1 and GetOperandValue(ea,0) == i):# wanted register
            if (ua_mnem (ea) == 'LDR'):
                if (GetOpType(ea,1) == 2):#Optype is Memory Reference
                    return self.GetXref_String(ea,1)
                elif (GetOpType(ea,1) == 4):#Base+index+Displacement
                    if(GetOperandValue(ea,1) == 0): # like  : LDR R3,[R3]
                        return self.get_content_register(PrevHead(ea),i)
                    else:
                        return 
                else :
                    print 'unkown Optype:' ,hex(ea),idc.GetDisasm(ea)
            elif (ua_mnem(ea) == 'MOV'):
                if (GetOpType(ea,1) == 5):
                    return GetOperandValue(ea,1)
                elif (GetOpType(ea,1) == 1):
                    return self.get_content_register(PrevHead(ea),GetOperandValue(ea,1))
                else:
                    print 'unkown OpType:',hex(ea),idc.GetDisasm(ea)
        else:
            return self.get_content_register(PrevHead(ea),i)


    #from a call instruction BackForward search parameter
    def BackForward(self,addr,n):
        Reg_content = []
        #addr = PrevHead(addr)
        i = 0 # register number
        for i in range(n):
            Reg_content.append(self.get_content_register(addr,i))

        return Reg_content


    def Anayl_Func_Call(self, func_name, para_num):
         if func_name == "":
             return
         
         #get start address
         segkind = ['.text' , '.init' ,'.plt'] 
         #startaddr = idc.SegByName('.rodata')
         startaddr = MinEA() 
         #fun_addr = idc.LocByName(func_name)
         # search the address of the pattern text
         while True:
            fun_addr = FindText(startaddr,SEARCH_DOWN, 0, 0, func_name)
            if not (SegName(fun_addr)) in segkind:
                break
            startaddr = NextHead(fun_addr)

         print 'find pattern string addr',hex(fun_addr)

         #byte_str = [hex(y) for y in bytearray(func_name)]
         #print byte_str

         #print hex(fun_addr),idc.GetDisasm(fun_addr)
         
         call_addrs = idautils.DataRefsTo(fun_addr)
         dic = {}
         for item in call_addrs:
             if (not isCode(GetFlags(item))):
                 continue
             #print hex(item),idc.GetDisasm(item)
             CALL_ADDR = item
             while ( not ua_mnem(CALL_ADDR) == 'BL' ):
                 CALL_ADDR = NextHead(CALL_ADDR)
             CALL_ADDR = PrevHead(CALL_ADDR)        
             #print 'from addr %s analyses' % (str(hex(CALL_ADDR)))
             para = self.BackForward(CALL_ADDR,para_num)
             xref_funname = GetFunctionName(CALL_ADDR)
             dic[xref_funname] = para
         return dic

        


def print_help():
    info = 'use this as : idal64/idal -S"Anaylise_All.py \'print1 %s\'" '
    print info

def main():
    #test code
    if (len (idc.ARGV) < 2):
        print_help()
        ana_fun_name = '%s  version %s  protocol version %d%s'
    else:
        ana_fun_name = idc.ARGV[1]#要分析的函数名
    
    para_num = 0 #参数数量
    pos = ana_fun_name.find('%')
    while (not pos == -1):
        para_num += 1
        pos += 1
        pos = ana_fun_name.find('%',pos)

    ana = AnayBinFil()
    dic = ana.Anayl_Func_Call(ana_fun_name,para_num+1)
    
    print '在函数中','其调用参数为'
    for item in dic:
        print item , dic[item]
    
    sf = open("out.dat",'w')
    if not sf:
        
        sf.write ('parameter:'+str(idc.ARGV[0])+str(idc.ARGV[1])+'\n')
        idc.Exit(0)
    for item in dic:
        sf.write('In function : '+item+'\n')
        x = (dic[item])
        s = '    '
        for i in range(len(x)):
            if x[i] is None:
                continue
            s += str(x[i])+' , '
        sf.write(s + '\n')
        
    sf.close()
    '''
    # get all names and it's addr
    for x in Names():
        print x
    '''   
    idc.Exit(0)

if __name__ == '__main__':
    main()


运行命令:idal64 -S"../Graph-based_Bug_Search/Analysis_Param_Call.py 'print4 %s'" arm_ddg

-S 表示运行ida python脚本

得到结果

In function : print4
    print4 %s , 1.1.1222 , 




猜你喜欢

转载自blog.csdn.net/qq_21063873/article/details/77678619
今日推荐