    def find_cave(self):
        """This function finds all code caves, allowing the user
        to pick the cave for injecting shellcode."""

        self.flItms['len_allshells'] = ()
        if self.flItms['cave_jumping'] is True:
            for item in self.flItms['allshells']:
                self.flItms['len_allshells'] += (len(item), )
            # TODO: ADD Stub len for zeroing memory here
            self.flItms['len_allshells'] += (len(self.flItms['resumeExe']), )
            SIZE_CAVE_TO_FIND = sorted(self.flItms['len_allshells'])[0]
        else:
            SIZE_CAVE_TO_FIND = self.flItms['shellcode_length']
            self.flItms['len_allshells'] = (self.flItms['shellcode_length'], )

        print "[*] Looking for caves that will fit the minimum "\
              "shellcode length of %s" % SIZE_CAVE_TO_FIND
        print "[*] All caves lengths: ", ', '.join([str(i) for i in self.flItms['len_allshells']])
        Tracking = 0
        count = 1
        #BeginCave=0
        caveTracker = []
        caveSpecs = []
        self.binary.seek(0)

        if self.PATCH_METHOD == 'automatic':
            #  This is so much faster than the other method
            for k, item in enumerate(sorted(self.flItms['len_allshells'])):
                cave_buffer = "\x00" * (item + 8)
                p = re.compile(cave_buffer)
                self.binary.seek(0)
                for m in p.finditer(self.binary.read()):
                    caveSpecs.append(m.start() + 4)
                    caveSpecs.append(m.start() + item + 8)
                    caveTracker.append(caveSpecs)
                    caveSpecs = []
            self.binary.seek(0)

        else:
            # Manual Slow method
            while True:
                # TODO: ADD in Fast Mode
                # Jump to near end of .text section and start parsing there.
                try:
                    s = struct.unpack("<b", self.binary.read(1))[0]
                except:     # Exception as e:
                    break
                if s == 0:
                    if count == 1:
                        BeginCave = Tracking
                    count += 1
                else:
                    if count >= SIZE_CAVE_TO_FIND:
                        #Add a four byte buffer between objects
                        caveSpecs.append(BeginCave + 4)
                        caveSpecs.append(Tracking - 4)
                        caveTracker.append(caveSpecs)
                    count = 1
                    caveSpecs = []

                Tracking += 1

        pickACave = {}
        for i, caves in enumerate(caveTracker):
            i += 1
            for section in self.flItms['Sections']:
                sectionFound = False
                try:
                    if caves[0] >= section[4] and \
                       caves[1] <= (section[3] + section[4]) and \
                       caves[1] - caves[0] >= SIZE_CAVE_TO_FIND:
                        if self.VERBOSE is True:
                            print "Inserting code in this section:", section[0]
                            print '->Begin Cave', hex(caves[0])
                            print '->End of Cave', hex(caves[1])
                            print 'Size of Cave (int)', caves[1] - caves[0]
                            print 'SizeOfRawData', hex(section[3])
                            print 'PointerToRawData', hex(section[4])
                            print 'End of Raw Data:', hex(section[3] + section[4])
                            print '*' * 50
                        JMPtoCodeAddress = (section[2] + caves[0] - section[4] -
                                            5 - self.flItms['PatchLocation'])

                        sectionFound = True
                        pickACave[i] = [section[0], hex(caves[0]), hex(caves[1]),
                                        caves[1] - caves[0], hex(section[4]),
                                        hex(section[3] + section[4]), JMPtoCodeAddress,
                                        section[1], section[2]]
                        break
                except:
                    print "-End of File Found.."
                    break
                if sectionFound is False:
                    if self.VERBOSE is True:
                        print "No section"
                        print '->Begin Cave', hex(caves[0])
                        print '->End of Cave', hex(caves[1])
                        print 'Size of Cave (int)', caves[1] - caves[0]
                        print '*' * 50

                JMPtoCodeAddress = (section[2] + caves[0] - section[4] -
                                    5 - self.flItms['PatchLocation'])
                try:
                    pickACave[i] = [None, hex(caves[0]), hex(caves[1]),
                                    caves[1] - caves[0], None,
                                    None, JMPtoCodeAddress]
                except:
                    print "EOF"

        CavesPicked = {}

        if self.PATCH_METHOD.lower() == 'automatic':
            print "[*] Attempting PE File Automatic Patching"
            availableCaves = {}
            # Take away the rsrc restriction, solved
            for caveNumber, caveValues in pickACave.iteritems():
                # caveValues[0], Begin Cave, [1] End of Cave
                # stay clear of iat_cave_loc, will be zero if never touched
                if self.iat_cave_loc != 0:
                    if caveValues[0] <= self.iat_cave_loc[0] <= caveValues[1]:
                        continue
                # stay clear of iat_cave_loc ending
                    if caveValues[0] <= self.iat_cave_loc[1] <= caveValues[1]:
                        continue
                if caveValues[0] is None:
                    continue
                elif caveValues[3] >= 50:
                    availableCaves[caveNumber] = caveValues[3]

            #serialize caves:

            payloadDict = {}
            for k, item in enumerate(self.flItms['len_allshells']):
                payloadDict[k] = item

            # choose other Caves first.

            while True:
                # for tracking sections to change perms on
                trackSectionName = set()

                # other caves first
                for ref in sorted(payloadDict.items(), key=operator.itemgetter(1), reverse=True):
                    # largest first
                    # now drop the caves that are big enough in a set
                    # and randomly select from it
                    _tempCaves = {}
                    if _tempCaves == {}:
                        # nothing? get out
                        for refnum, caveSize in availableCaves.iteritems():
                            if caveSize >= ref[1]:
                                _tempCaves[refnum] = caveSize
                        if _tempCaves == {}:
                            break
                    selection = choice(_tempCaves.keys())
                    print '[!] Selected:', str(selection) + ":", ("Section Name: {0}; Cave begin: {1} End: {2}; "
                                                                  "Cave Size: {3}; Payload Size: {4}".format(pickACave[selection][0], pickACave[selection][1],
                                                                                          pickACave[selection][2], pickACave[selection][3], ref[1]
                                                                                          ))
                    trackSectionName.add(pickACave[selection][0])
                    #remove the selection from the dict
                    popSet = set()
                    for cave_ref, cave_vals in availableCaves.iteritems():
                        if pickACave[cave_ref][1] <= pickACave[selection][1] <= pickACave[cave_ref][2] or \
                            pickACave[cave_ref][1] <= pickACave[selection][2] <= pickACave[cave_ref][2] or \
                            pickACave[selection][1] <= pickACave[cave_ref][1] <= pickACave[selection][2] or \
                            pickACave[selection][1] <= pickACave[cave_ref][2] <= pickACave[selection][2]:
                            popSet.add(cave_ref)
                    for item in popSet:
                        availableCaves.pop(item)     
                    if selection in availableCaves.keys():
                        availableCaves.pop(selection)
                    CavesPicked[ref[0]] = pickACave[selection]
                break

            if len(CavesPicked) != len(self.flItms['len_allshells']):
                print "[!] Did not find suitable caves - trying next method"
                if self.flItms['cave_jumping'] is True:
                    return 'single'
                else:
                    return 'append'

            if self.CHANGE_ACCESS is True:
                for cave in trackSectionName:
                    self.change_section_flags(cave)

        elif self.PATCH_METHOD.lower() == 'manual':
            print ("############################################################\n"
                   "The following caves can be used to inject code and possibly\n"
                   "continue execution.\n"
                   "**Don't like what you see? Use jump, single, append, or ignore.**\n"
                   "############################################################")

            for k, item in enumerate(self.flItms['len_allshells']):
                print "[*] Cave {0} length as int: {1}".format(k + 1, item)
                print "[*] Available caves: "

                if pickACave == {}:
                    print "[!!!!] No caves available! Use 'j' for cave jumping or"
                    print "[!!!!] 'i' or 'q' for ignore."
                for ref, details in pickACave.iteritems():
                    if details[3] >= item:
                        print str(ref) + ".", ("Section Name: {0}; Section Begin: {4} "
                                               "End: {5}; Cave begin: {1} End: {2}; "
                                               "Cave Size: {3}".format(details[0], details[1], details[2],
                                                                       details[3], details[4], details[5],
                                                                       details[6]))

                while True:
                    try:
                        self.CAVE_MINER_TRACKER
                    except:
                        self.CAVE_MINER_TRACKER = 0

                    print "*" * 50

                    selection = raw_input("[!] Enter your selection: ")
                    try:
                        selection = int(selection)

                        print "[!] Using selection: %s" % selection
                        try:
                            if self.CHANGE_ACCESS is True:
                                if pickACave[selection][0] is not None:
                                    self.change_section_flags(pickACave[selection][0])
                            CavesPicked[k] = pickACave[selection]
                            break
                        except:
                            print "[!!!!] User selection beyond the bounds of available caves."
                            print "[!!!!] Try a number or the following commands:"
                            print "[!!!!] append or a, jump or j, ignore or i, single or s"
                            print "[!!!!] TRY AGAIN."
                            continue
                    except:
                        pass
                    breakOutValues = ['append', 'jump', 'single', 'ignore', 'a', 'j', 's', 'i', 'q']
                    if selection.lower() in breakOutValues:
                        return selection
        else:
            print "[!] Invalid Patching Method"
            return None
        return CavesPicked
This function finds all code caves, allowing the user
to pick the cave for injecting shellcode.
pebin.py