Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. from idaapi import Form
  2. from idaapi import GraphViewer
  3. from idaapi import plugin_t
  4. import re
  5.  
  6. def getText(ea):
  7.     t=GetFunctionName(ea)
  8.     if t=='':
  9.         t='%s:%x: %s'%(SegName(ea),ea,GetDisasm(ea))
  10.     return t
  11.  
  12. class Xrefs:
  13.     def __init__(self,ea,max_depth=1,regexp=None):
  14.         self.xrefs_to={}
  15.         self.xrefs_from={}
  16.         self.ea=ea
  17.         self.max_depth=max_depth
  18.         self.regexp=regexp            
  19.  
  20.     def _recGetXrefsTo(self,ea,depth=1):
  21.         found=False
  22.         self.xrefs_to[ea]=[]
  23.         for xref in XrefsTo(ea,idaapi.XREF_FAR):
  24.             if not xref.iscode:
  25.                 continue
  26.             x=xref.frm
  27.             f=idaapi.get_func(x)
  28.             if f:
  29.                 x=f.startEA
  30.             if x in self.xrefs_to[ea]:
  31.                 continue
  32.             t=getText(x)
  33.             if self.regexp!=None:
  34.                 if re.search(self.regexp,t)!=None:
  35.                     self.xrefs_to[ea].append(x)
  36.                     found=True
  37.                     continue
  38.                 if f and depth<self.max_depth \
  39.                     and x not in self.xrefs_to \
  40.                     and self._recGetXrefsTo(x,depth+1)==True:
  41.                     self.xrefs_to[ea].append(x)
  42.                     found=True
  43.                 elif x in self.xrefs_to and len(self.xrefs_to[x])>0:
  44.                     self.xrefs_to[ea].append(x)
  45.                     found=True
  46.             else:
  47.                 self.xrefs_to[ea].append(x)
  48.                 if f and depth<self.max_depth and x not in self.xrefs_to:
  49.                     self._recGetXrefsTo(x,depth+1)
  50.         return found
  51.  
  52.     def getXrefsTo(self):
  53.         self.xrefs_to={}
  54.         f=idaapi.get_func(self.ea)
  55.         if f:
  56.             self._recGetXrefsTo(f.startEA)
  57.         return self.xrefs_to
  58.  
  59.     def _recGetXrefsFrom(self,ea,depth=1):
  60.         found=False
  61.         self.xrefs_from[ea]=[]
  62.         for x in [x for x in FuncItems(ea) if idaapi.is_call_insn(x)]:
  63.             for xref in XrefsFrom(x,idaapi.XREF_FAR):
  64.                 if not xref.iscode:
  65.                     continue
  66.                 if xref.to in self.xrefs_from[ea]:
  67.                     continue
  68.                 t=getText(xref.to)
  69.                 if self.regexp!=None:
  70.                     if re.search(self.regexp,t)!=None:
  71.                         self.xrefs_from[ea].append(xref.to)
  72.                         found=True
  73.                         continue
  74.                     if depth<self.max_depth and xref.to not in self.xrefs_from \
  75.                         and self._recGetXrefsFrom(xref.to,depth+1)==True:
  76.                         self.xrefs_from[ea].append(xref.to)
  77.                         found=True
  78.                     elif xref.to in self.xrefs_from and \
  79.                         len(self.xrefs_from[xref.to])>0:
  80.                         self.xrefs_from[ea].append(xref.to)
  81.                         found=True
  82.                 else:
  83.                     self.xrefs_from[ea].append(xref.to)
  84.                     if depth<self.max_depth and xref.to not in self.xrefs_from:
  85.                         self._recGetXrefsFrom(xref.to,depth+1)
  86.         return found
  87.  
  88.     def getXrefsFrom(self):
  89.         self.xrefs_from={}
  90.         f=idaapi.get_func(self.ea)
  91.         if f:
  92.             self._recGetXrefsFrom(f.startEA)
  93.         return self.xrefs_from
  94.        
  95. class XrefsGraph(GraphViewer):
  96.     def __init__(self,title,ea,xrefs_to,xrefs_from):
  97.         GraphViewer.__init__(self,title)
  98.         self.xrefs_to=xrefs_to
  99.         self.xrefs_from=xrefs_from
  100.  
  101.     def OnRefresh(self):
  102.         self.Clear()
  103.         nodes={}
  104.         for ea in self.xrefs_to:
  105.             if len(self.xrefs_to[ea])==0:
  106.                 continue
  107.             if ea not in nodes:
  108.                 nodes[ea]=self.AddNode(ea)
  109.             for x in self.xrefs_to[ea]:
  110.                 if x not in nodes:
  111.                     nodes[x]=self.AddNode(x)
  112.                 self.AddEdge(nodes[x],nodes[ea])
  113.         for ea in self.xrefs_from:
  114.             if len(self.xrefs_from[ea])==0:
  115.                 continue
  116.             if ea not in nodes:
  117.                 nodes[ea]=self.AddNode(ea)
  118.             for x in self.xrefs_from[ea]:
  119.                 if x not in nodes:
  120.                     nodes[x]=self.AddNode(x)
  121.                 self.AddEdge(nodes[ea],nodes[x])
  122.         return True
  123.  
  124.     def OnGetText(self,node_id):
  125.         return getText(self[node_id])
  126.  
  127.     def OnDblClick(self,node_id):
  128.         ea=self[node_id]
  129.         idc.Jump(ea)
  130.         return True
  131.  
  132. class XrefsForm(Form):
  133.     def __init__(self):
  134.         Form.__init__(self,r"""STARTITEM {id:iAddr}
  135. BUTTON YES* Ok
  136. BUTTON CANCEL Cancel
  137. Xrefs Graph
  138.  
  139. {FormChangeCb}
  140. <#Address must be within a function#Enter an address:{iAddr}>
  141.  
  142. Directions:
  143. <Cross references from:{rFrom}>
  144. <Cross references to:{rTo}>{cGroupDirections}>
  145.  
  146. Options:
  147. <Recursion:{rRecursion}>
  148. <Include data references (NOT USED YET):{rDrefs}>
  149. <Apply regular expression filter:{rRegexp}>
  150. <Display recursion dots (NOT USED YET):{rDots}>
  151. <Display comments (NOT USED YET):{rComments}>{cGroupOptions}>
  152.  
  153. <##Recursion depth:{iDepth}>
  154. <##Regular expression:{iRegexp}>
  155. """, {
  156.     'iAddr': Form.NumericInput(tp=Form.FT_ADDR),
  157.     'cGroupDirections': Form.ChkGroupControl(('rFrom','rTo')),
  158.     'cGroupOptions': Form.ChkGroupControl(('rRecursion',
  159.                                            'rDrefs',
  160.                                            'rRegexp',
  161.                                            'rDots',
  162.                                            'rComments')),
  163.     'iDepth': Form.NumericInput(tp=Form.FT_UINT64),
  164.     'iRegexp': Form.StringInput(),
  165.     'FormChangeCb': Form.FormChangeCb(self.OnFormChange)
  166.     })
  167.  
  168.     def OnFormChange(self,fid):
  169.         print('>>fid=%d'%(fid))
  170.         return 1
  171.  
  172. class XrefsGraphPlugin_t(plugin_t):
  173.     flags=idaapi.PLUGIN_UNL
  174.     comment="Xrefs Graph plugin for IDA"
  175.     help=""
  176.     wanted_name="Xrefs Graph"
  177.     wanted_hotkey="Alt-F8"
  178.  
  179.     def init(self):
  180.         return idaapi.PLUGIN_OK
  181.  
  182.     def run(self,arg=0):
  183.         f=XrefsForm()
  184.         f.Compile()
  185.         f.iAddr.value=ScreenEA()
  186.         f.iDepth.value=16
  187.         f.cGroupDirections.value=3
  188.         f.cGroupOptions.value=5
  189.         f.iRegexp.value='^xxx'
  190.         ok=f.Execute()
  191.         #print('>>ok=%d'%(ok))
  192.         if ok==1:
  193.             #print('f.cGroupDirections.value=%x'%(f.cGroupDirections.value))
  194.             #print('f.cGroupOptions.value=%x'%(f.cGroupOptions.value))
  195.             ea=f.iAddr.value
  196.             max_depth=f.iDepth.value
  197.             if f.cGroupOptions.value&1==0:
  198.                 max_depth=1            
  199.             regexp=None
  200.             if f.cGroupOptions.value&4!=0:
  201.                 regexp=f.iRegexp.value
  202.             x=Xrefs(ea,max_depth,regexp)
  203.             xrefs_to={}
  204.             xrefs_from={}
  205.             if f.cGroupDirections.value&2!=0:
  206.                 xrefs_to.update(x.getXrefsTo())
  207.             if f.cGroupDirections.value&1!=0:
  208.                 xrefs_from.update(x.getXrefsFrom())
  209.             title='XrefsGraph for %s (depth=%d,regexp=%s)'%(getText(ea),
  210.                                                             max_depth,regexp)
  211.             g=XrefsGraph(title,ea,xrefs_to,xrefs_from)
  212.             g.Show()
  213.         f.Free()
  214.         return
  215.  
  216.     def term(self):
  217.         return
  218.  
  219. def PLUGIN_ENTRY():
  220.     return XrefsGraphPlugin_t()