Advertisement
opexxx

recomposer.py

Jul 14th, 2014
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 38.98 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. '''
  4. Recomposer.py
  5. Author Joshua Pitts the.midnite.runr 'at' gmail <d ot > com
  6.  
  7. Copyright (C) 2013, Joshua Pitts
  8.  
  9. License:   GPLv3
  10.  
  11. This program is free software: you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation, either version 3 of the License, or
  14. (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. See <http://www.gnu.org/licenses/> for a copy of the GNU General
  22. Public License
  23.  
  24. Currently supports win32/64 EXEs/DLLs only (intel architecture).
  25. This program is to be used for only legal activities by IT security
  26. professionals and researchers. Author not responsible for malicious
  27. uses.
  28. '''
  29. '''
  30. To do:
  31. Automatic log_recomposer.txt.
  32.    Original_FIle|NewFile
  33.  
  34. '''
  35.  
  36. from optparse import OptionParser
  37. import struct
  38. import operator
  39. import shutil
  40. import os
  41. import string
  42. import random
  43. import sys
  44. import hashlib
  45.  
  46. global flItms
  47. global f
  48. global verbose
  49. verbose = False
  50.  
  51. exit_values = ['quit', 'q', 'done', 'exit']
  52.  
  53. MachineTypes = {'0x0': 'AnyMachineType',
  54.                 '0x1d3': 'Matsushita AM33',
  55.                 '0x8664': 'x64',
  56.                 '0x1c0': 'ARM LE',
  57.                 '0x1c4': 'ARMv7',
  58.                 '0xaa64': 'ARMv8 x64',
  59.                 '0xebc': 'EFIByteCode',
  60.                 '0x14c': 'Intel x86',
  61.                 '0x200': 'Intel Itanium',
  62.                 '0x9041': 'M32R',
  63.                 '0x266': 'MIPS16',
  64.                 '0x366': 'MIPS w/FPU',
  65.                 '0x466': 'MIPS16 w/FPU',
  66.                 '0x1f0': 'PowerPC LE',
  67.                 '0x1f1': 'PowerPC w/FP',
  68.                 '0x166': 'MIPS LE',
  69.                 '0x1a2': 'Hitachi SH3',
  70.                 '0x1a3': 'Hitachi SH3 DSP',
  71.                 '0x1a6': 'Hitachi SH4',
  72.                 '0x1a8': 'Hitachi SH5',
  73.                 '0x1c2': 'ARM or Thumb -interworking',
  74.                 '0x169': 'MIPS little-endian WCE v2'
  75.                 }
  76.  
  77. supported_types = ['Intel x86', 'x64']
  78.  
  79. safe_section_additions = ['FUTURE_USE_1', 'FUTURE_USE_2', 'FUTURE_USE_3',
  80.                           'FUTURE_USE_4', 'FUTURE_USE_5', 'IMAGE_SCN_CNT_CODE',
  81.                           'IMAGE_SCN_CNT_INITIALIZED_DATA', 'IMAGE_SCN_MEM_WRITE',
  82.                           'IMAGE_SCN_MEM_READ', 'IMAGE_SCN_MEM_EXECUTE',
  83.                           'IMAGE_SCN_MEM_SHARED']
  84.  
  85. nops = [0x90, 0x3690, 0x6490, 0x6590, 0x6690, 0x6790]
  86.  
  87.  
  88. section_flags = {"Group1":
  89.                 {"FUTURE_USE_1": 0x00000001,
  90.                  "FUTURE_USE_2": 0x00000002,
  91.                  "FUTURE_USE_3": 0x00000004,
  92.                  "IMAGE_SCN_TYPE_NO_PAD": 0x00000008,
  93.                  },
  94.                  "Group2":
  95.                  {"FUTURE_USE_4":       0x00000010,
  96.                   "IMAGE_SCN_CNT_CODE": 0x00000020,
  97.                   "IMAGE_SCN_CNT_INITIALIZED_DATA": 0x00000040,
  98.                   "IMAGE_SCN_CNT_UNINITIALIZED_DATA": 0x00000080,
  99.                   },
  100.                  "Group3":
  101.                  {"IMAGE_SCN_LNK_OTHER": 0x00000100,
  102.                   "IMAGE_SCN_LNK_INFO": 0x00000200,
  103.                   "FUTURE_USE_5": 0x00000400,
  104.                   "IMAGE_SCN_LNK_REMOVE": 0x00000800,
  105.                   },
  106.                  "Group4":
  107.                  {"IMAGE_SCN_LNK_COMDAT": 0x00001000,
  108.                   "IMAGE_SCN_GPREL": 0x00008000,
  109.                   },
  110.                  "Group5":
  111.                  {"IMAGE_SCN_MEM_PURGEABLE": 0x00020000,
  112.                   "IMAGE_SCN_MEM_LOCKED": 0x00040000,
  113.                   "IMAGE_SCN_MEM_PRELOAD": 0x00080000,
  114.                   },
  115.                  "Group6":
  116.                  {"IMAGE_SCN_ALIGN_1BYTES": 0x00100000,
  117.                   "IMAGE_SCN_ALIGN_2BYTES": 0x00200000,
  118.                   "IMAGE_SCN_ALIGN_4BYTES": 0x00300000,
  119.                   "IMAGE_SCN_ALIGN_8BYTES": 0x00400000,
  120.                   "IMAGE_SCN_ALIGN_16BYTES": 0x00500000,
  121.                   "IMAGE_SCN_ALIGN_32BYTES": 0x00600000,
  122.                   "IMAGE_SCN_ALIGN_64BYTES": 0x00700000,
  123.                   "IMAGE_SCN_ALIGN_128BYTES": 0x00800000,
  124.                   "IMAGE_SCN_ALIGN_256BYTES": 0x00900000,
  125.                   "IMAGE_SCN_ALIGN_512BYTES": 0x00A00000,
  126.                   "IMAGE_SCN_ALIGN_1024BYTES": 0x00B00000,
  127.                   "IMAGE_SCN_ALIGN_2048BYTES": 0x00C00000,
  128.                   "IMAGE_SCN_ALIGN_4096BYTES": 0x00D00000,
  129.                   "IMAGE_SCN_ALIGN_8192BYTES": 0x00E00000,
  130.                   },
  131.                  "Group7":
  132.                  {"IMAGE_SCN_LNK_NRELOC_OVFL": 0x01000000,
  133.                   "IMAGE_SCN_MEM_DISCARDABLE": 0x02000000,
  134.                   "IMAGE_SCN_MEM_NOT_CACHED": 0x04000000,
  135.                   "IMAGE_SCN_MEM_NOT_PAGED": 0x08000000,
  136.                   },
  137.                  "Group8":
  138.                  {"IMAGE_SCN_MEM_SHARED": 0x10000000,
  139.                   "IMAGE_SCN_MEM_EXECUTE": 0x20000000,
  140.                   "IMAGE_SCN_MEM_READ": 0x40000000,
  141.                   "IMAGE_SCN_MEM_WRITE": 0x80000000,
  142.                   }
  143.                  }
  144.  
  145. sectionflag_help= ("""
  146. LEGEND:
  147. Section Flags Example: 0x40000040
  148. Group:  8   7   6   5   4   3   2   1
  149.      0x4   0   0   0   0   0   4   0
  150.  
  151. Group3                  Group2                              Group1:
  152. IMAGE_SCN_LNK_OTHER     FUTURE_USE_4                        FUTURE_USE_1
  153. IMAGE_SCN_LNK_INFO      IMAGE_SCN_CNT_CODE                  FUTURE_USE_2
  154. FUTURE_USE_5            IMAGE_SCN_CNT_INITIALIZED_DATA      FUTURE_USE_3
  155. IMAGE_SCN_LNK_REMOVE    IMAGE_SCN_CNT_UNINITIALIZED_DATA    IMAGE_SCN_TYPE_NO_PAD
  156.    
  157. Group6:                     Group5:                         Group4:
  158. IMAGE_SCN_ALIGN_1BYTES      IMAGE_SCN_MEM_PURGEABLE         IMAGE_SCN_LNK_COMDAT
  159. IMAGE_SCN_ALIGN_2BYTES      IMAGE_SCN_MEM_LOCKED            IMAGE_SCN_GPREL
  160. IMAGE_SCN_ALIGN_4BYTES      IMAGE_SCN_MEM_PRELOAD        
  161. IMAGE_SCN_ALIGN_8BYTES
  162. IMAGE_SCN_ALIGN_16BYTES     Group7:
  163. IMAGE_SCN_ALIGN_32BYTES     IMAGE_SCN_LNK_NRELOC_OVFL
  164. IMAGE_SCN_ALIGN_64BYTES     IMAGE_SCN_MEM_DISCARDABLE
  165. IMAGE_SCN_ALIGN_128BYTES    IMAGE_SCN_MEM_NOT_CACHED
  166. IMAGE_SCN_ALIGN_256BYTES    IMAGE_SCN_MEM_NOT_PAGED
  167. IMAGE_SCN_ALIGN_512BYTES    
  168. IMAGE_SCN_ALIGN_1024BYTES   Group8:
  169. IMAGE_SCN_ALIGN_2048BYTES   IMAGE_SCN_MEM_SHARED
  170. IMAGE_SCN_ALIGN_4096BYTES   IMAGE_SCN_MEM_EXECUTE
  171. IMAGE_SCN_ALIGN_8192BYTES   IMAGE_SCN_MEM_READ
  172.                            IMAGE_SCN_MEM_WRITE
  173.   """)
  174.  
  175.  
  176. def md5_for_file(FILE, block_size=2**20):
  177.     """
  178.    Modded from stackoverflow:
  179.    http://stackoverflow.com/questions/1131220/get-md5-hash-of-big-files-in-python
  180.    """
  181.     md5 = hashlib.md5()
  182.     filehandle = open(FILE, 'r+b')
  183.     while True:
  184.         data = filehandle.read(block_size)
  185.         if not data:
  186.             break
  187.         md5.update(data)
  188.     filehandle.close()
  189.     return md5.hexdigest()
  190.  
  191.  
  192. def random_name_return(len):
  193.     '''
  194.    Returns a random name of alphanumeric chars
  195.    based on input length
  196.    '''
  197.     chars = string.digits + string.ascii_uppercase + string.ascii_lowercase
  198.     name = ''
  199.     for i in range(0, len):
  200.         name += random.choice(chars)
  201.     return name
  202.  
  203.  
  204. def return_filename(outputfile):
  205.     os_name = os.name
  206.     if not os.path.exists("updatedfile"):
  207.         os.makedirs("updatedfile")
  208.     if os_name == 'nt':
  209.         updatedfile = "updatedfile\\" + outputfile
  210.     else:
  211.         updatedfile = "updatedfile/" + outputfile
  212.    
  213.     return updatedfile
  214.  
  215.  
  216. def randomly_change_file(FILE, DISK_OFFSET):
  217.     global flItms
  218.     global f
  219.     flItms = {}
  220.     print "Old file name:", FILE
  221.     flItms['filename'] = FILE
  222.     #make random file name 4-13 char in len
  223.     new_file_name = random_name_return(random.randrange(4,14)) + ".exe"
  224.     print "New file name:", new_file_name
  225.     new_file_name = return_filename(new_file_name)
  226.     flItms['outputfile'] = new_file_name
  227.     #print flItms['outputfile']
  228.     shutil.copy2(flItms['filename'], flItms['outputfile'])
  229.     flItms = support_check(flItms['outputfile'], DISK_OFFSET)
  230.     flItms['outputfile'] = new_file_name
  231.     f = open(flItms['outputfile'], "r+b")
  232.     for i, section in enumerate(flItms['Sections']):
  233.         print i+1, "Section:", section[0], "| SectionFlags:", hex(section[9])
  234.     get_section_attributes(flItms)
  235.     find_cave(flItms, 20)
  236.        
  237.     for i, section in enumerate(flItms['Sections']):
  238.         if random.random() > .49999999999:
  239.             addflags = True
  240.             #Enumerate Sections
  241.             defaultattrib = []
  242.             for attrib in flItms['FlagAttributes'][flItms['Sections'][i][0]]:
  243.                 defaultattrib.append(attrib)
  244.             section_overlap = []
  245.             for item in defaultattrib:
  246.                 for item1 in safe_section_additions:
  247.                     if item1 in item:
  248.                         section_overlap.append(item1)
  249.             temp_sections = safe_section_additions[:]
  250.             for k, item in enumerate(section_overlap):
  251.                 temp_sections.remove(item)
  252.             attributeStore = set()
  253.             for k in range(random.randrange(1, len(temp_sections))):
  254.                 attributeStore.add(random.choice(temp_sections))
  255.             new_value = change_section_flags(flItms, flItms['Sections'][i], attributeStore)  
  256.             flItms['Sections'][i][9] = new_value
  257.         else:
  258.             addflags = False
  259.         newSectionName = random_name_return(random.randrange(2, 8))
  260.         newSectionName = newSectionName + ((7 - len(newSectionName)) * "\x00")
  261.         change_section_name(flItms, flItms['Sections'][i][0], newSectionName)
  262.        
  263.    
  264.    
  265.     f.close()
  266.     print "Updated Binary:"
  267.     print "\t" + flItms['outputfile']
  268.     f = open(flItms['outputfile'], "r+b")
  269.     flItms = support_check(flItms['outputfile'], DISK_OFFSET)
  270.     for i, section in enumerate(flItms['Sections']):
  271.         print i+1, "Section:", section[0], "| SectionFlags:", hex(section[9])
  272.     f.close()
  273.     print "Writing to log_recomposer.txt"
  274.     g = open("log_recomposer.txt",'a')
  275.     g.write(FILE + '|' + md5_for_file(FILE) + '|')
  276.     g.write(new_file_name + '|' + md5_for_file(new_file_name) + '\n')
  277.     g.close()
  278.  
  279.  
  280. def change_binary_workflow(FILE, OUTPUT, DISK_OFFSET):
  281.     """
  282.    Workflow to change the sections:
  283.  
  284.        What sections would you like to change?
  285.        print sections
  286.        Current flags
  287.        What flags would you like to use:
  288.        print all flags
  289.    """
  290.     global flItms
  291.     flItms = {}
  292.     flItms['filename'] = FILE
  293.     if OUTPUT == "":
  294.         outputfile = return_filename("change." + os.path.basename(FILE))
  295.     else:
  296.         outputfile = return_filename(os.path.basename(OUTPUT))
  297.  
  298.     shutil.copy2(flItms['filename'], outputfile)
  299.     flItms = support_check(outputfile, DISK_OFFSET)
  300.     global f
  301.     Error = ''
  302.     while True:
  303.         os.system('cls' if os.name=='nt' else 'clear')
  304.         if Error != '':
  305.             print Error
  306.             Error = ''
  307.  
  308.         flItms = support_check(outputfile, DISK_OFFSET)
  309.         flItms['outputfile'] = outputfile
  310.         f = open(flItms['outputfile'], "r+b")
  311.         print "[?] What sections would you like to change:"
  312.         get_section_attributes(flItms)
  313.         for i, section in enumerate(flItms['Sections']):
  314.             print i+1, "Section:", section[0], "| SectionFlags:", hex(section[9])
  315.         number = raw_input("Section number:")
  316.         if number in exit_values:
  317.             print "exiting"
  318.             f.close()
  319.             break
  320.         try:
  321.             number = int(number)
  322.         except:
  323.             Error = "Whoops, try again..."
  324.             continue
  325.         print "[-] You picked the", flItms['Sections'][number-1][0], "section."
  326.         selection = raw_input("[?] Would you like to (A) change the section name or (B) the section flags? ")
  327.         print "[-] You picked:", selection
  328.         if selection.lower() == 'a':
  329.             while True:
  330.                 newSectionName=raw_input("[?] Enter a new section name (less than 7 chars): ")
  331.                 if len(newSectionName) <= 7:
  332.                     newSectionName = newSectionName + ((7 - len(newSectionName)) * "\x00")
  333.                     break
  334.             change_section_name(flItms, flItms['Sections'][number-1][0], newSectionName)
  335.         if selection.lower() == 'b':
  336.             attributeStore=set()
  337.             Error_call = False
  338.             error_msg = ''
  339.             while True:
  340.                 os.system('cls' if os.name=='nt' else 'clear')
  341.                 if Error_call is True:
  342.                     print error_msg
  343.                     Error_call = False
  344.                 get_section_attributes(flItms)
  345.                 if attributeStore != set([]):
  346.                     print "[!] Attributes to write:"
  347.                     for attrib in attributeStore:
  348.                         print "[*]", attrib
  349.                 print "=" * 25
  350.                 print "[*] Current attributes:"
  351.                 try:
  352.                     print flItms['Sections'][number-1][0], "|" , hex(flItms['Sections'][number-1][9])
  353.                     for attrib in flItms['FlagAttributes'][flItms['Sections'][number-1][0]]:
  354.                         print "[-]", attrib
  355.                 except:
  356.                     print "[!] No attributes assigned."
  357.                 print "=" * 25
  358.                 print "[*] Commands 'zero' out the flags, 'help', 'write', or ('exit', 'quit', 'q', 'done')"
  359.                 print "[*] Use 'write' to commit your changes or 'clear' to start over."
  360.                 attrib_select = raw_input("[?] Enter an attribute to add or type 'help' or 'exit': ")
  361.                 if attrib_select.lower() == 'help':
  362.                     Error_call = True
  363.                     error_msg = sectionflag_help
  364.                 elif attrib_select.lower() in exit_values:
  365.                     break
  366.                 elif attrib_select.lower() == 'clear':
  367.                     attributeStore = set()
  368.                 elif attrib_select.lower() == 'write':
  369.                     new_value = change_section_flags(flItms, flItms['Sections'][number-1], attributeStore)
  370.                     flItms['Sections'][number-1][9] = new_value
  371.                     attributeStore=set()
  372.                 elif attrib_select.lower() == 'zero':
  373.                     print "This will zero out your selection. You can't go back.."
  374.                     ans = raw_input("Continue? (y/n)")
  375.                     if ans.lower()  != 'y':
  376.                         break
  377.                     new_value = change_section_flags(flItms, flItms['Sections'][number-1], set(['zero'],))
  378.                     flItms['Sections'][number-1][9] = new_value
  379.                 else:
  380.                     for each_attribute in [x.strip() for x in attrib_select.split(',')]:
  381.                         #add to attribute store, check 1st if they exist:
  382.                         found = False
  383.                         try:
  384.                             print each_attribute.upper(), flItms['FlagAttributes'][flItms['Sections'][number-1][0]]
  385.                             for list_item in flItms['FlagAttributes'][flItms['Sections'][number-1][0]]:
  386.                                 if each_attribute in [x.strip() for x in list_item.split(',')]:
  387.                                     error_msg = "[!] " + each_attribute + " already assigned, continuting.."
  388.                                     Error_call = True
  389.                                     found = True
  390.                                     continue
  391.                         except:
  392.                             pass
  393.                         for key, value in section_flags.iteritems():
  394.                             if found is True:
  395.                                 break
  396.                             for key1, value1 in value.iteritems():
  397.                                 if each_attribute.upper() == key1:
  398.                                     attributeStore.add(each_attribute)
  399.                                     print each_attribute, "added for writing"
  400.                                     found = True
  401.                         if found is False:
  402.                             Error_call = True
  403.                             error_msg = "[!] Attribute not found please try again."
  404.         f.close()
  405.  
  406.     print "Writing to log_recomposer.txt"
  407.     g = open("log_recomposer.txt",'a')
  408.     g.write(FILE + '|' + md5_for_file(FILE) + '|')
  409.     g.write(outputfile + '|' + md5_for_file(outputfile) + '\n')
  410.     g.close()
  411.  
  412. def change_section_name(flItms, section, name="none"):
  413.     print "[*] Changing Section " + section + " Name"
  414.     f.seek(flItms['BeginSections'], 0)
  415.     for _ in range(flItms['NumberOfSections']):
  416.         currentPos = f.tell()
  417.         sec_name = f.read(8)
  418.         if section in sec_name:
  419.             f.seek(currentPos)
  420.             #must be less than 7
  421.             f.write("." + name)
  422.             return True
  423.         else:
  424.             f.seek(32, 1)
  425.     return False
  426.  
  427.  
  428. def find_cave(flItms, shellcode_length):
  429.     """This function finds all code caves, allowing the user
  430.    to pick the cave for injecting shellcode."""
  431.  
  432.     len_allshells = (shellcode_length, )
  433.     SIZE_CAVE_TO_FIND = shellcode_length
  434.     Tracking = 0
  435.     count = 1
  436.     caveTracker = []
  437.     caveSpecs = []
  438.  
  439.     f.seek(0)
  440.  
  441.     while True:
  442.         try:
  443.             s = struct.unpack("<b", f.read(1))[0]
  444.         except:
  445.             break
  446.         if s == 0:
  447.             if count == 1:
  448.                 BeginCave = Tracking
  449.             count += 1
  450.         else:
  451.             if count >= SIZE_CAVE_TO_FIND:
  452.                 caveSpecs.append(BeginCave)
  453.                 caveSpecs.append(Tracking)
  454.                 caveTracker.append(caveSpecs)
  455.             count = 1
  456.             caveSpecs = []
  457.  
  458.         Tracking += 1
  459.  
  460.     pickACave = {}
  461.    
  462.     section_injected = {}
  463.     for section in flItms['Sections']:
  464.         section_injected[section[0]] = False
  465.     for i, caves in enumerate(caveTracker):
  466.         i += 1
  467.         countOfSections = 0
  468.         for section in flItms['Sections']:
  469.             sectionFound = False
  470.             try:
  471.                 if caves[0] >= section[4] and \
  472.                    caves[1] <= (section[3] + section[4]) and \
  473.                    caves[1] - caves[0] >= SIZE_CAVE_TO_FIND:
  474.                     if verbose is True:
  475.                         print "Inserting code in this section:", section[0]
  476.                         print '->Begin Cave', hex(caves[0])
  477.                         print '->End of Cave', hex(caves[1])
  478.                         print 'Size of Cave (int)', caves[1] - caves[0]
  479.                         print 'SizeOfRawData', hex(section[3])
  480.                         print 'PointerToRawData', hex(section[4])
  481.                         print 'End of Raw Data:', hex(section[3] + section[4])
  482.                         print '*' * 50
  483.                     JMPtoCodeAddress = (section[2] + caves[0] - section[4] -
  484.                                         5 - flItms['AddressOfEntryPoint'])
  485.                     section_injected[section[0]] = True
  486.                     sectionFound = True
  487.                     pickACave[i] = [section[0], hex(caves[0]), hex(caves[1]),
  488.                                     caves[1] - caves[0], hex(section[4]),
  489.                                     hex(section[3] + section[4]), JMPtoCodeAddress]
  490.                     break
  491.             except:
  492.                 print "-End of File Found.."
  493.                 break
  494.        
  495.             JMPtoCodeAddress = (section[2] + caves[0] - section[4] -
  496.                                 5 - flItms['AddressOfEntryPoint'])
  497.             try:
  498.                 pickACave[i] = ["None", hex(caves[0]), hex(caves[1]),
  499.                                 caves[1] - caves[0], "None",
  500.                                 "None", JMPtoCodeAddress]
  501.             except:
  502.                 print "EOF"
  503.  
  504.         if sectionFound is False:
  505.             if verbose is True:
  506.                 print "No section"
  507.                 print '->Begin Cave', hex(caves[0])
  508.                 print '->End of Cave', hex(caves[1])
  509.                 print 'Size of Cave (int)', caves[1] - caves[0]
  510.                 print '*' * 50
  511.  
  512.    
  513.     for key, value in section_injected.iteritems():
  514.         if value is False:
  515.             print '\033[93m' + "[!] Warning,", key, "section hash is not changed!"
  516.             print "[!] No caves available for nop injection." + '\033[0m'
  517.  
  518.     CavesPicked = {}
  519.  
  520.     for k, item in enumerate(len_allshells):
  521.        
  522.         for ref, details in pickACave.iteritems():
  523.            
  524.             if int(details[1], 16) < flItms['Sections'][0][2]:
  525.                 continue
  526.             # write to code cave
  527.             payload_size = details[3] / 8
  528.             if payload_size < 2:
  529.                 payload_size = 5
  530.             payload_size = random.randrange(1, payload_size)
  531.             f.seek(0)
  532.             write_point = int(details[1], 16) + ( ( details[3] - payload_size) / 2 )
  533.             f.seek(write_point, 0)
  534.             thenop =random.choice(nops)
  535.             if thenop > 144:
  536.                 f.write(struct.pack('!H', thenop) * (payload_size / 2))
  537.             else:
  538.                 f.write(struct.pack('!B', thenop) * (payload_size))
  539.  
  540.        
  541. def change_section_flags(flItms, section, flagvalues):
  542.     """
  543.    Changes the user selected section to RWE for successful execution
  544.    """
  545.     print "[*] Changing Section " + section[0] + " Flags"
  546.     sectionName = section[0]
  547.     newSectionFlags = section[9]
  548.     for item in flagvalues:
  549.         if item == 'zero'.lower():
  550.             newSectionFlags = 0x00000000
  551.         found = False
  552.         for key, value in section_flags.iteritems():
  553.             if found is True:
  554.                 break
  555.             for key1, value1 in value.iteritems():
  556.                 if item == key1:
  557.                     if 'Group6' == key:
  558.                         print key
  559.                         newSectionFlags = value1
  560.                     else:    
  561.                         newSectionFlags += value1
  562.                     found = True
  563.                     break
  564.  
  565.         f.seek(flItms['BeginSections'], 0)
  566.         for _ in range(flItms['NumberOfSections']):
  567.             sec_name = f.read(8)
  568.             if sectionName in sec_name:
  569.                 #print "found it"
  570.                 f.seek(28, 1)
  571.                 if newSectionFlags == 0:
  572.                     f.write("\x00\x00\x00\x00")
  573.                 else:
  574.                     f.write(struct.pack('<I', newSectionFlags))
  575.             else:
  576.                 f.seek(32, 1)
  577.     return newSectionFlags
  578.  
  579.  
  580. def print_section_attr():
  581.     """
  582.    Prints the section attributes by calculating each type of section.
  583.    """
  584.     eachtypeofsection={}
  585.     sectionAttrib = []
  586.        
  587.     for keyA, valueA in section_flags.iteritems():
  588.         print keyA, valueA
  589.         for keyA, valueB in valueA.iteritems():
  590.             print keyA, valueB  
  591.  
  592.  
  593. def support_check(filename, LocOfEntryinCode_Offset):
  594.     """
  595.    This function is for checking if the current exe/dll is
  596.    supported by this program. Returns false if not supported,
  597.    returns flItms if it is.
  598.    """
  599.     print "[*] Checking if binary is supported"
  600.     flItms = {}
  601.     flItms['supported'] = False
  602.     global f
  603.     f = open(filename, "rb")
  604.     flItms['LocOfEntryinCode_Offset'] = LocOfEntryinCode_Offset
  605.     if f.read(2) != "\x4d\x5a":
  606.         print "%s not a PE File" % filename
  607.         return False
  608.     flItms = gather_file_info_win(flItms, filename, flItms['LocOfEntryinCode_Offset'])
  609.     if flItms is False:
  610.         return False
  611.     if MachineTypes[hex(flItms['MachineType'])] not in supported_types:
  612.         for item in flItms:
  613.             print item + ':', flItms[item]
  614.         print ("This program does not support this format: %s"
  615.                % MachineTypes[hex(flItms['MachineType'])])
  616.     else:
  617.         flItms['supported'] = True
  618.    
  619.     f.close()
  620.  
  621.     if verbose is True:
  622.         print_flItms(flItms)
  623.  
  624.     if flItms['supported'] is False:
  625.         return False
  626.     else:
  627.         return flItms
  628.  
  629.  
  630. def gather_file_info_win(flItms, filename, LocOfEntryinCode_Offset):
  631.     """
  632.    Gathers necessary PE header information to backdoor
  633.    a file and returns a dict of file information called flItms
  634.    """
  635.     s = f.seek(int('3C', 16))
  636.     print "[*] Gathering file info"
  637.     flItms['filename'] = filename
  638.     flItms['buffer'] = 0
  639.     flItms['JMPtoCodeAddress'] = 0
  640.     flItms['LocOfEntryinCode_Offset'] = LocOfEntryinCode_Offset
  641.     flItms['dis_frm_pehdrs_sectble'] = 248
  642.     flItms['pe_header_location'] = struct.unpack('<i', f.read(4))[0]
  643.     # Start of COFF
  644.     flItms['COFF_Start'] = flItms['pe_header_location'] + 4
  645.     f.seek(flItms['COFF_Start'])
  646.     flItms['MachineType'] = struct.unpack('<H', f.read(2))[0]
  647.     for mactype, name in MachineTypes.iteritems():
  648.         if int(mactype, 16) == flItms['MachineType']:
  649.             if verbose is True:
  650.                 print 'MachineType is:', name
  651.     #f.seek(flItms['ImportTableLocation'])
  652.     #flItms['IATLocInCode'] = struct.unpack('<I', f.read(4))[0]
  653.     f.seek(flItms['COFF_Start'] + 2, 0)
  654.     flItms['NumberOfSections'] = struct.unpack('<H', f.read(2))[0]
  655.     flItms['TimeDateStamp'] = struct.unpack('<I', f.read(4))[0]
  656.     f.seek(flItms['COFF_Start'] + 16, 0)
  657.     flItms['SizeOfOptionalHeader'] = struct.unpack('<H', f.read(2))[0]
  658.     flItms['Characteristics'] = struct.unpack('<H', f.read(2))[0]
  659.     #End of COFF
  660.     flItms['OptionalHeader_start'] = flItms['COFF_Start'] + 20
  661.     if flItms['SizeOfOptionalHeader']:
  662.         #Begin Standard Fields section of Optional Header
  663.         f.seek(flItms['OptionalHeader_start'])
  664.         flItms['Magic'] = struct.unpack('<H', f.read(2))[0]
  665.         flItms['MajorLinkerVersion'] = struct.unpack("!B", f.read(1))[0]
  666.         flItms['MinorLinkerVersion'] = struct.unpack("!B", f.read(1))[0]
  667.         flItms['SizeOfCode'] = struct.unpack("<I", f.read(4))[0]
  668.         flItms['SizeOfInitializedData'] = struct.unpack("<I", f.read(4))[0]
  669.         flItms['SizeOfUninitializedData'] = struct.unpack("<i",
  670.                                                           f.read(4))[0]
  671.         flItms['AddressOfEntryPoint'] = struct.unpack('<I', f.read(4))[0]
  672.         flItms['BaseOfCode'] = struct.unpack('<i', f.read(4))[0]
  673.         #print 'Magic', flItms['Magic']
  674.         if flItms['Magic'] != int('20B', 16):
  675.             #print 'Not 0x20B!'
  676.             flItms['BaseOfData'] = struct.unpack('<i', f.read(4))[0]
  677.         # End Standard Fields section of Optional Header
  678.         # Begin Windows-Specific Fields of Optional Header
  679.         if flItms['Magic'] == int('20B', 16):
  680.             #print 'x64!'
  681.             flItms['ImageBase'] = struct.unpack('<Q', f.read(8))[0]
  682.         else:
  683.             flItms['ImageBase'] = struct.unpack('<I', f.read(4))[0]
  684.         #print 'flItms[ImageBase]', hex(flItms['ImageBase'])
  685.         flItms['SectionAlignment'] = struct.unpack('<I', f.read(4))[0]
  686.         flItms['FileAlignment'] = struct.unpack('<I', f.read(4))[0]
  687.         flItms['MajorOperatingSystemVersion'] = struct.unpack('<H',
  688.                                                               f.read(2))[0]
  689.         flItms['MinorOperatingSystemVersion'] = struct.unpack('<H',
  690.                                                               f.read(2))[0]
  691.         flItms['MajorImageVersion'] = struct.unpack('<H', f.read(2))[0]
  692.         flItms['MinorImageVersion'] = struct.unpack('<H', f.read(2))[0]
  693.         flItms['MajorSubsystemVersion'] = struct.unpack('<H', f.read(2))[0]
  694.         flItms['MinorSubsystemVersion'] = struct.unpack('<H', f.read(2))[0]
  695.         flItms['Win32VersionValue'] = struct.unpack('<I', f.read(4))[0]
  696.         flItms['SizeOfImageLoc'] = f.tell()
  697.         flItms['SizeOfImage'] = struct.unpack('<I', f.read(4))[0]
  698.         #print "size of img", flItms['SizeOfImage']
  699.         flItms['SizeOfHeaders'] = struct.unpack('<I', f.read(4))[0]
  700.         flItms['CheckSum'] = struct.unpack('<I', f.read(4))[0]
  701.         flItms['Subsystem'] = struct.unpack('<H', f.read(2))[0]
  702.         flItms['DllCharacteristics'] = struct.unpack('<H', f.read(2))[0]
  703.         if flItms['Magic'] == int('20B', 16):
  704.             flItms['SizeOfStackReserve'] = struct.unpack('<Q', f.read(8))[0]
  705.             flItms['SizeOfStackCommit'] = struct.unpack('<Q', f.read(8))[0]
  706.             flItms['SizeOfHeapReserve'] = struct.unpack('<Q', f.read(8))[0]
  707.             flItms['SizeOfHeapCommit'] = struct.unpack('<Q', f.read(8))[0]
  708.  
  709.         else:
  710.             flItms['SizeOfStackReserve'] = struct.unpack('<I', f.read(4))[0]
  711.             flItms['SizeOfStackCommit'] = struct.unpack('<I', f.read(4))[0]
  712.             flItms['SizeOfHeapReserve'] = struct.unpack('<I', f.read(4))[0]
  713.             flItms['SizeOfHeapCommit'] = struct.unpack('<I', f.read(4))[0]
  714.         flItms['LoaderFlags'] = struct.unpack('<I', f.read(4))[0]  # zero
  715.         flItms['NumberofRvaAndSizes'] = struct.unpack('<I', f.read(4))[0]
  716.         # End Windows-Specific Fields of Optional Header
  717.         # Begin Data Directories of Optional Header
  718.         flItms['ExportTable'] = struct.unpack('<Q', f.read(8))[0]
  719.         flItms['ImportTable'] = struct.unpack('<Q', f.read(8))[0]
  720.         flItms['ResourceTable'] = struct.unpack('<Q', f.read(8))[0]
  721.         flItms['ExceptionTable'] = struct.unpack('<Q', f.read(8))[0]
  722.         flItms['CertificateTable'] = struct.unpack('<Q', f.read(8))[0]
  723.         flItms['BaseReLocationTable'] = struct.unpack('<Q', f.read(8))[0]
  724.         flItms['Debug'] = struct.unpack('<Q', f.read(8))[0]
  725.         flItms['Architecutre'] = struct.unpack('<Q', f.read(8))[0]  # zero
  726.         flItms['GlobalPrt'] = struct.unpack('<Q', f.read(8))[0]
  727.         flItms['TLS Table'] = struct.unpack('<Q', f.read(8))[0]
  728.         flItms['LoadConfigTable'] = struct.unpack('<Q', f.read(8))[0]
  729.         flItms['ImportTableLocation'] = f.tell()
  730.         #print 'ImportTableLocation', hex(flItms['ImportTableLocation'])
  731.         flItms['BoundImport'] = struct.unpack('<Q', f.read(8))[0]
  732.         f.seek(flItms['ImportTableLocation'])
  733.         flItms['IATLocInCode'] = struct.unpack('<I', f.read(4))[0]
  734.         #print 'first IATLOCIN CODE', hex(flItms['IATLocInCode'])
  735.         flItms['IATSize'] = struct.unpack('<I', f.read(4))[0]
  736.         #print 'IATSize', hex(flItms['IATSize'])
  737.         flItms['IAT'] = struct.unpack('<Q', f.read(8))[0]
  738.         flItms['DelayImportDesc'] = struct.unpack('<Q', f.read(8))[0]
  739.         flItms['CLRRuntimeHeader'] = struct.unpack('<Q', f.read(8))[0]
  740.         flItms['Reserved'] = struct.unpack('<Q', f.read(8))[0]  # zero
  741.         flItms['BeginSections'] = f.tell()
  742.  
  743.     flItms['Sections'] = []
  744.     for section in range(flItms['NumberOfSections']):
  745.         sectionValues = []
  746.         sectionValues.append(f.read(8))
  747.         # VirtualSize
  748.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  749.         # VirtualAddress
  750.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  751.         # SizeOfRawData
  752.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  753.         # PointerToRawData
  754.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  755.         # PointerToRelocations
  756.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  757.         # PointerToLinenumbers
  758.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  759.         # NumberOfRelocations
  760.         sectionValues.append(struct.unpack('<H', f.read(2))[0])
  761.         # NumberOfLinenumbers
  762.         sectionValues.append(struct.unpack('<H', f.read(2))[0])
  763.         # SectionFlags
  764.         sectionValues.append(struct.unpack('<I', f.read(4))[0])
  765.         flItms['Sections'].append(sectionValues)
  766.  
  767.     flItms['VirtualAddress'] = flItms['SizeOfImage']
  768.  
  769.     flItms['VrtStrtngPnt'] = (flItms['AddressOfEntryPoint'] +
  770.                               flItms['ImageBase'])
  771.     f.seek(flItms['IATLocInCode'])
  772.     flItms['ImportTableALL'] = f.read(flItms['IATSize'])
  773.     flItms['NewIATLoc'] = flItms['IATLocInCode'] + 40
  774.     return flItms
  775.  
  776.  
  777. def print_flItms(flItms):
  778.  
  779.     keys = flItms.keys()
  780.     keys.sort()
  781.     for item in keys:
  782.         if type(flItms[item]) == int:
  783.             print item + ':', hex(flItms[item])
  784.         elif item == 'Sections':
  785.             print "-" * 50
  786.             for section in flItms['Sections']:
  787.                 print "Section Name", section[0]
  788.                 print "Virutal Size", hex(section[1])
  789.                 print "Virtual Address", hex(section[2])
  790.                 print "SizeOfRawData", hex(section[3])
  791.                 print "PointerToRawData", hex(section[4])
  792.                 print "PointerToRelocations", hex(section[5])
  793.                 print "PointerToLinenumbers", hex(section[6])
  794.                 print "NumberOfRelocations", hex(section[7])
  795.                 print "NumberOfLinenumbers", hex(section[8])
  796.                 print "SectionFlags", hex(section[9])
  797.                 print "-" * 50
  798.         else:
  799.             print item + ':', flItms[item]
  800.     print "*" * 50, "END flItms"
  801.  
  802.  
  803. def get_section_attributes(flItms):
  804.     flItms['FlagAttributes'] = {}
  805.     #print flItms['Sections']
  806.     for section in flItms['Sections']:
  807.         sectionTracker = []
  808.         if len(hex(section[9])) != 10:
  809.             section_value = '0x' + '0' * (8 - len(hex(section[9]).split('0x')[1])) + hex(section[9]).split('0x')[1]
  810.         else:
  811.             section_value = hex(section[9])
  812.         for i, j in enumerate(section_value.split('0x')[1]):
  813.             if j == '0':
  814.                 continue
  815.             elif i == 0:
  816.                 groupValue = "Group8"
  817.                 #values = section_flags[groupValue].values()
  818.                 #results = get_values(combinations(values))
  819.                 #parse_attribs(groupValue, results, i, j)
  820.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  821.                 #print results
  822.             elif i == 1:
  823.                 groupValue = "Group7"
  824.                 #values = section_flags[groupValue].values()
  825.                 #results = get_values(combinations(values))
  826.                 #parse_attribs(groupValue, results, i, j)
  827.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  828.                 #print results
  829.             elif i == 2:
  830.                 groupValue = "Group6"
  831.                 #values = section_flags[groupValue].values()
  832.                 #results = get_values(combinations(values))
  833.                 #parse_attribs(groupValue, results, i, j)
  834.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  835.                 #print results
  836.             elif i == 3:
  837.                 groupValue = "Group5"
  838.                 #values = section_flags[groupValue].values()
  839.                 #results = get_values(combinations(values))
  840.                 #parse_attribs(groupValue, results, i, j)
  841.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  842.                
  843.             elif i == 4:
  844.                 groupValue = "Group4"
  845.                 #values = section_flags[groupValue].values()
  846.                 #results = get_values(combinations(values))
  847.                 #parse_attribs(groupValue, results, i, j)
  848.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  849.                 #print results
  850.             elif i == 5:
  851.                 groupValue = "Group3"
  852.                 #values = section_flags[groupValue].values()
  853.                 #results = get_values(combinations(values))
  854.                 #parse_attribs(groupValue, results, i, j)
  855.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  856.                 #print results
  857.             elif i == 6:
  858.                 groupValue = "Group2"
  859.                 #values = section_flags[groupValue].values()
  860.                 #print "values", values
  861.                
  862.                 #results = get_values(combinations(values))
  863.                 #parse_attribs(groupValue, results, i, j)
  864.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  865.                 #print results
  866.             elif i == 7:
  867.                 groupValue = "Group1"
  868.                 #print 6
  869.                 #values = section_flags[groupValue].values()
  870.                 #results = get_values(combinations(values))
  871.                 sectionTracker.append(parse_attribs(groupValue, i, j))
  872.                 #parse_attribs(groupValue, results, i, j)
  873.                 #print results
  874.             flItms["FlagAttributes"][section[0]]=sectionTracker
  875.  
  876.  
  877. def parse_attribs(groupValue, position, value):
  878.     #print section_flags[groupValue], results, position, value
  879.     #print groupValue
  880.     MyValue = int('0x' + '0' * (position) + str(value) + '0' * (7 - position), 16)
  881.     #print MyValue
  882.     #continue here list attribs
  883.     tempValue = 0
  884.     FlagAttributes = []
  885.     for key, value in sorted(section_flags[groupValue].iteritems(), key=operator.itemgetter(1), reverse=True):
  886.         if value > MyValue:
  887.             continue  
  888.         if tempValue != 0 and value > tempValue:
  889.             #print "Value Greater than MyValue"
  890.             continue
  891.  
  892.         if tempValue > 0:
  893.             if tempValue % value == 0:
  894.                 #print "tempValue, found value"
  895.                 #print "Flag", key
  896.                 FlagAttributes.append(key)
  897.                 break
  898.         #print key, '\t', value
  899.         tempValue = MyValue % value
  900.         if tempValue == 0:
  901.             #print "found value"
  902.             #print "Flag", key
  903.             FlagAttributes.append(key)
  904.             break
  905.         else:
  906.             #print "Flag", key
  907.             FlagAttributes.append(key)
  908.             #print 'tempValue', tempValue
  909.  
  910.     return ", ".join(FlagAttributes)
  911.  
  912.  
  913. if __name__ == "__main__":
  914.  
  915.     parser = OptionParser()
  916.     parser.add_option("-f", "--file", dest="FILE", action="store",
  917.                       type="string",
  918.                       help="File to backdoor")
  919.     parser.add_option("-o", "--output-file", default="", dest="OUTPUT",
  920.                       action="store", type="string",
  921.                       help="The backdoor output file")
  922.    
  923.     parser.add_option("-O", "--disk_offset", default=0,
  924.                       dest="DISK_OFFSET", type="int", action="store",
  925.                       help="Starting point on disk offset, in bytes. "
  926.                       "Some authors want to obfuscate their on disk offset "
  927.                       "to avoid reverse engineering, if you find one of those "
  928.                       "files use this flag, after you find the offset.")
  929.  
  930.     parser.add_option("-v", "--verbose", default=False, dest="VERBOSE",
  931.                       action="store_true",
  932.                       help="For debug information output.")
  933.     parser.add_option("-m", "--manual", default=False, dest="MANUAL",
  934.                       action="store_true",
  935.                       help="To change section headers names and flags")
  936.     parser.add_option("-a", "--auto", default=False, dest="AUTO",
  937.                       action="store_true",
  938.                       help="Randomly change section header names and flags")
  939.  
  940.     (options, args) = parser.parse_args()
  941.     verbose = options.VERBOSE
  942.  
  943.     if not options.FILE:
  944.         parser.print_help()
  945.         sys.exit(1)
  946.  
  947.     if options.MANUAL is True:
  948.         change_binary_workflow(options.FILE, options.OUTPUT, options.DISK_OFFSET)
  949.         sys.exit(0)
  950.     if options.AUTO is True:
  951.         randomly_change_file(options.FILE, options.DISK_OFFSET)
  952.         sys.exit(0)
  953.     parser.print_help()
  954.     sys.exit(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement