Advertisement
Guest User

Untitled

a guest
Sep 6th, 2018
139
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. """@package unlinker
  2. Documentation for this module.
  3. This is a IDA script file built to output Section, Symbol, and Xref information
  4.  
  5.  
  6. If run as script in IDA should create csv files called Xref, Symbols, and Sections
  7. """
  8. import json
  9. from idautils import *
  10. from idc import *
  11. from idaapi import *
  12. import sqlite3
  13. import sys
  14.  
  15. #Python Quicksort from interactivepython.org/courselib/static/pythonds/SortSearch/TheQuickSort.html
  16. def quickSort(alist, blist):
  17.     """Documentation for a function.
  18.    @param alist list to be sorted
  19.    @param blist an additional list that is to be sorted not by its order but by lista's order
  20.    @brief Simple function that sorts both lists in the order of lowest to highest based on the first list
  21.    """
  22.     quickSortHelper(alist,0,len(alist)-1, blist)
  23.  
  24. def quickSortHelper(alist,first,last, blist):
  25.     """Documentation for a function.
  26.    @param alist list to be sorted
  27.    @param first is the index of first value in quicksort
  28.    @param last is the index of last value in quicksort
  29.    @param blist an additional list that is to be sorted not by its order but by lista's order
  30.    @brief Helper Function that can be called recursively
  31.    """
  32.     if first<last:
  33.  
  34.         splitpoint = partition(alist,first,last, blist)
  35.  
  36.         quickSortHelper(alist,first,splitpoint-1, blist)
  37.         quickSortHelper(alist,splitpoint+1,last, blist)
  38.  
  39.  
  40. def partition(alist,first,last, blist):
  41.     """Documentation for a function.
  42.    @param alist list to be sorted
  43.    @param first is the index of first value in quicksort
  44.    @param last is the index of last value in quicksort
  45.    @param blist an additional list that is to be sorted not by its order but by lista's order
  46.    @brief Partitions and sorts per quicksort rules. Pivotvalue just chosen as first right now
  47.    """
  48.     pivotvalue = alist[first]
  49.  
  50.     leftmark = first+1
  51.     rightmark = last
  52.  
  53.     done = False
  54.     while not done:
  55.  
  56.         while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
  57.             leftmark = leftmark + 1
  58.  
  59.         while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
  60.             rightmark = rightmark -1
  61.  
  62.         if rightmark < leftmark:
  63.             done = True
  64.         else:
  65.             temp = alist[leftmark]
  66.             alist[leftmark] = alist[rightmark]
  67.             alist[rightmark] = temp
  68.             temp = blist[leftmark]
  69.             blist[leftmark] = blist[rightmark]
  70.             blist[rightmark] = temp
  71.  
  72.     temp = alist[first]
  73.     alist[first] = alist[rightmark]
  74.     alist[rightmark] = temp
  75.     temp = blist[first]
  76.     blist[first] = blist[rightmark]
  77.     blist[rightmark] = temp
  78.  
  79.     return rightmark
  80.  
  81. def write_all(cur):
  82.     """Documentation for a function.
  83.    @param cur Cursor to the sqlite database to write to
  84.    @brief Discovers xrefs and symbols and gets information to print them. Calls print sections
  85.    """
  86.     #Random Declarations
  87.     funcs = Functions()
  88.     #Record all xref.to's to symbol list and their type to corresponding index in symbolListType
  89.     symbolList = []
  90.     symbolListType = []
  91.     ptrList = []
  92.  
  93.     #Prints the section
  94.     add_sections_to_db(cur)
  95.  
  96.     #Make sure all functions are added to symbol list. Must be prior so funcs don't get identified as objects
  97.     for x in funcs:
  98.         func = get_func(x)
  99.         if not func is None:
  100.             symbolList.append(func.startEA)
  101.             symbolListType.append(17)
  102.     funcs = Functions()
  103.     #This main loop goes through all functions discovering all xrefs
  104.     for x in funcs:
  105.         func = get_func(x)
  106.         if not func is None:
  107.             fname = Name(func.startEA)
  108.             items = FuncItems(func.startEA)
  109.             #Every item is a line of assembly
  110.             for i in items:
  111.                 #There can be multiple xrefs in a line of assembly if two pointers are referenced
  112.                 for xref in XrefsFrom(i, 0):
  113.                     add_xref_info_to_db(cur, i, xref, 0)
  114.                     #Detecting if this is a symbol and has not been added to symbol table yet
  115.                     if xref.to not in symbolList and int(xref.type) != 21:
  116.                         symbolList.append(xref.to)
  117.                         symbolListType.append(int(xref.type))
  118.  
  119.                 #Both the next two if statements are for detecting pointer's intial values
  120.                 if(get_operand_type(i, 0) == 2):
  121.                     #we don't need to store its intial value more than once so created a list
  122.                     if int(GetOperandValue(i, 0)) not in ptrList:
  123.                         ptrList.append(int(GetOperandValue(i,0)))
  124.                         for xrefHidden in XrefsFrom(GetOperandValue(i, 0), 0):
  125.                             #add the new xref to xref file
  126.                             add_xref_info_to_db(cur, GetOperandValue(i, 0), xrefHidden, 1)
  127.                             #add the xref.to to the symbol file
  128.                             if xrefHidden.to not in symbolList and int(xrefHidden.type) != 21:
  129.                                 symbolList.append(xrefHidden.to)
  130.                                 symbolListType.append(int(xrefHidden.type))
  131.                 #Same as above but with second operand
  132.                 if(get_operand_type(i, 1) == 2):
  133.                     if int(GetOperandValue(i, 1)) not in ptrList:
  134.                         ptrList.append(int(GetOperandValue(i, 1)))
  135.                         for xrefHidden in XrefsFrom(GetOperandValue(i, 1), 0):
  136.                             add_xref_info_to_db(cur, GetOperandValue(i, 1), xrefHidden, 1)
  137.                             if xrefHidden.to not in symbolList and int(xrefHidden.type) != 21:
  138.                                 symbolList.append(xrefHidden.to)
  139.                                 symbolListType.append(int(xrefHidden.type))
  140.  
  141.  
  142.     #Use xrefs to calculate size of symbols if they are data
  143.     quickSort(symbolList, symbolListType)
  144.     i = 0
  145.     #Calculates the size of each symbol by subtraction
  146.     while i < len(symbolList):
  147.         #Either subtracts next Xref or Seg End, whichever comes first
  148.         segEnd = get_segm_end(symbolList[i])
  149.         #Last xref has to be linked against segment because no xref after it
  150.         if i != len(symbolList)-1:
  151.             nextXref = symbolList[i + 1]
  152.         else:
  153.             nextXref = segEnd
  154.         if(nextXref < segEnd):
  155.             diff = nextXref - symbolList[i]
  156.         else:
  157.             diff = segEnd - symbolList[i]
  158.         add_symbol_to_db(cur, symbolList[i], symbolListType[i], diff)
  159.         i += 1
  160.  
  161. #    fileX.close()
  162. #    fileS.close()
  163.     return;
  164.  
  165. def create_tables(cur):
  166.     """Documentation for a function.
  167.    @param cur Cursor to the sqlite database to write to
  168.    @brief Clears any existing database information and sets up new tables
  169.    """
  170.     #Purge any old data.
  171.     #SQLite will not create new tables if there are existing tables with the same name.
  172.     cur.execute("DROP TABLE IF EXISTS XREF")
  173.     cur.execute("DROP TABLE IF EXISTS SYMBOLS")
  174.     cur.execute("DROP TABLE IF EXISTS SECTIONS")
  175.     cur.execute("CREATE TABLE XREF(ADDRESS INTEGER, SIZE INTEGER, TARGET_ADDRESS INTEGER, TYPE STRING)")
  176.     cur.execute("CREATE TABLE SYMBOLS(ADDRESS INTEGER, SIZE INTEGER, TYPE STRING, NAME STRING)")
  177.     cur.execute("CREATE TABLE SECTIONS(NAME STRING, PERM INTEGER, VADDR INTEGER, VSIZE INTEGER)")
  178.  
  179. #Replacement for write_sections_csv
  180. def add_sections_to_db(cur):
  181.     """Documentation for a function.
  182.    @param cur Cursor to the sqlite database to write to
  183.    @brief Ouput section information to section.csv
  184.    """
  185.     for s in Segments():
  186.         seg_name = get_segm_name(getseg(s))
  187.         if(seg_name != 'LOAD'):
  188.             sqlString = "INSERT INTO SECTIONS VALUES('{}',{}, {}, {})"
  189.             sqlString = sqlString.format(seg_name, get_segm_attr(s, SEGATTR_PERM), get_segm_start(s), get_segm_end(s) - get_segm_start(s))
  190.             cur.execute(sqlString)
  191.  
  192. #Replacement for addSymbol
  193. def add_symbol_to_db(cur, address, xrefType, size):
  194.     """Documentation for a function.
  195.    @param cur Cursor to the sqlite database to write to
  196.    @param address Is the address of the symbol to be added
  197.    @param xrefType Is an integer representing the type of xref the symbol was
  198.    @param size Is the size of the symbol
  199.    @brief should output symbol at address information to a symbols.txt file
  200.    """
  201.     if(xrefType != 21):
  202.         funcInside = get_func(address)
  203.         if(funcInside is None or int(funcInside.startEA) == int(address)):
  204.             if(xrefType == 17 and funcInside is not None):
  205.                 size = funcInside.endEA - funcInside.startEA;
  206.             if(xrefType == 1 or xrefType == 2 or xrefType == 3):
  207.                 typeChanged = "object"
  208.             else:
  209.                 typeChanged = "func"
  210.             sqlString = "INSERT INTO SYMBOLS VALUES({}, {}, '{}', '{}')"
  211.             sqlString = sqlString.format(address, size, typeChanged, str(idc.get_name(address, 0)))
  212.             cur.execute(sqlString)
  213.  
  214. #Replacement for printXrefInfo
  215. def add_xref_info_to_db(cur, address, xref, ptr):
  216.     """Documentation for a function.
  217.    @param cur Cursor to the sqlite database to write to
  218.    @param address the address of the xref
  219.    @param xref the xref object from idapython
  220.    @param ptr Is 1 if ptr is 0 if not
  221.    @brief It will then output to the xref file (Xref.csv) all the information about that xref.
  222.    """
  223.     #xref type 21 is some sort of dataFlow xref that is not legit
  224.     if(xref.type != 21):
  225.         size = 4
  226.         typeChanged = ""
  227.         if (int(xref.to) == int(GetOperandValue(address, 0))):
  228.             size = len(str(hex(GetOperandValue(address, 0)))) - 1
  229.             if(get_operand_type(address, 0) == 2):
  230.                 typeChanged = "disp"
  231.             elif(get_operand_type(address, 0) == 5):
  232.                 if(get_operand_type(address, 1) == 2):
  233.                     typeChanged = "imm"
  234.                 else:
  235.                     typeChanged = "imm_alone"
  236.         if(int(xref.to) == int(GetOperandValue(address, 1))):
  237.             size = len(str(hex(GetOperandValue(address, 1)))) - 1
  238.             if(get_operand_type(address, 1) == 2):
  239.                 typeChanged = "disp"
  240.             elif(get_operand_type(address, 1) == 5):
  241.                 if(get_operand_type(address, 0) == 2):
  242.                     typeChanged = "imm"
  243.                 else:
  244.                     typeChanged = "imm_alone"
  245.         if(xref.type == 17):
  246.             typeChanged = "call"
  247.         elif(xref.type == 19):
  248.             typeChanged = "jmp"
  249.         #Passed in whether this is a pointer
  250.         if(ptr == 1):
  251.             typeChanged = "ptr"
  252.         sqlString = "INSERT INTO XREF VALUES({}, {}, {}, '{}')"
  253.         sqlString = sqlString.format(address, size, xref.to, typeChanged)
  254.         cur.execute(sqlString)
  255.  
  256.  
  257.  
  258. #Technically this is the main function:
  259. print("\n\n\n\nBegin script call")
  260. #fileName = "database.sqlite"+sys.argv[1]
  261. #fileName = "database.sqlite"
  262. targetNum = get_root_filename()[-1]
  263. fileName = "unlinker"+str(targetNum)+".db"
  264. conn = sqlite3.connect(fileName)
  265. cur = conn.cursor()
  266. create_tables(cur)
  267. write_all(cur)
  268. conn.commit()
  269. conn.close()
  270. qexit(0)
  271. print("Database has been generated.")
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement