def genStub(self, userCmd): """ Generate a valid deobfuscation stub and wrap an obfuscated command in it. :param userCmd: command that need to be wrapped in a deobfuscation stub :type userCmd: str """ if self.escapeQuotes: userCmd = userCmd.replace("'", "'\"'\"'") genStub = self.stub for var in re.findall(r"VAR\d+", genStub): genStub = genStub.replace(var, self.randGen.randGenVar()) genStub = self.mangler.getMangledLine(genStub) if "CMD" not in genStub: printError(f"Stub '{self.name}' is improperly formatted: no 'CMD' string found") else: genStub = genStub.replace("CMD", userCmd) return genStub
def choosePrefStub(self, stubs, sizePref, timePref, binaryPref, filePref, userStub=None): """ Choose a stub which is of the desired sizeRating, timeRating, and uses desired binaries. If the userStub parameter is passed, the specific stub defined by userStub is searched for and is checked to make sure it aligns with the users preferences for used binaries. :param stubs: list of Stubs to choose from :param sizePref: payload size user preference :type sizePref: int :param timePref: execution time user preference :type timePref: int :param binaryPref: list of binaries that the chosen Mutator should or should not use :type binaryPref: tuple containing a list of strs, and a bool :param userStub: the specific Stub the user chose to use :type userStub: lowercase str :returns: a :class:`bashfuscator.common.objects.Stub` object """ selStub = None if binaryPref is not None: binList = binaryPref[0] includeBinary = binaryPref[1] # attempt to find the specific stub the user wants if userStub is not None: for stub in stubs: if stub.longName == userStub: if binaryPref is not None: for binary in stub.binariesUsed: if (binary in binList) != includeBinary: printWarning( f"'{userStub}' stub contains an unwanted binary" ) if filePref is False and stub.fileWrite != filePref: printWarning(f"'{userStub}' stub preforms file writes") selStub = stub if selStub is None: printError(f"'{userStub}' stub not found") else: selStub = self.randGen.randSelect(stubs) return selStub
def getMutator(self, userMutator=None, userStub=None, sizePref=None, timePref=None, binaryPref=None, filePref=None): selMutator = None if userMutator: mutatorType = userMutator.split("/")[0] if mutatorType == "command": selMutator = self.choosePrefMutator(self.cmdObfuscators, sizePref, timePref, binaryPref, filePref, self.prevCmdOb, userMutator, userStub) self.prevCmdOb = selMutator elif mutatorType == "string": selMutator = self.choosePrefMutator(self.strObfuscators, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) elif mutatorType == "token": selMutator = self.choosePrefMutator(self.tokObfuscators, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) elif mutatorType == "encode": selMutator = self.choosePrefMutator(self.encoders, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) elif mutatorType == "compress": selMutator = self.choosePrefMutator(self.compressors, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) else: printError(f"{mutatorType} isn't a valid mutator type") else: # TODO: handle case when no mutators of chosen type are compatible with user's preferences obChoice = self.randGen.randChoice(3) if obChoice == 0: selMutator = self.choosePrefMutator(self.cmdObfuscators, sizePref, timePref, binaryPref, filePref, self.prevCmdOb) self.prevCmdOb = selMutator elif obChoice == 1: selMutator = self.choosePrefMutator(self.strObfuscators, sizePref, timePref, binaryPref, filePref) else: selMutator = self.choosePrefMutator(self.tokObfuscators, sizePref, timePref) selMutator.sizePref = sizePref selMutator.timePref = timePref return selMutator
def choosePrefMutator(self, mutators, sizePref=None, timePref=None, binaryPref=None, filePref=None, prevCmdOb=None, userMutator=None, userStub=None): """ Chooses a Mutator from a list of mutators which is of the desired preferences, with a stub that uses desired binaries if appropriate. If called with the userMutator or userStub parameters, the Mutator and/or Stub specified by userMutator and/or userStub will be chosen. If those parameters are not used, a Mutator and Stub (if appropriate) will be chosen automatically based off of the values of the other parameters. :param mutators: list of Mutators to choose a Mutator from :param sizePref: payload size user preference :type sizePref: int :param timePref: execution time user preference :type timePref: int :param binaryPref: list of binaries that the chosen Mutator should or should not use :type binaryPref: tuple containing a list of strs, and a bool :param filePref: file write user preference :type filePref: bool :param prevCmdOb: the previous CommandObfuscator used. Should only be passed if a CommandObfuscator was used to generate the most recent obfuscation layer :type prevCmdOb: :class:`bashfuscator.lib.command_mutators.CommandObfuscator` :param userMutator: the specific Mutator the user chose to use :type userMutator: lowercase str :param userStub: the specific Stub the user chose to use :type userStub: lowercase str :returns: a :class:`bashfuscator.common.objects.Mutator` object """ selMutator = None if userMutator: if binaryPref: binList = binaryPref[0] includeBinary = binaryPref[1] for mutator in mutators: if mutator.longName == userMutator: if filePref is False and mutator.mutatorType != "command" and mutator.fileWrite != filePref: printWarning( f"'{userMutator}' mutator preforms file writes") elif binaryPref and mutator.mutatorType != "command": for binary in mutator.binariesUsed: if (binary in binList) != includeBinary: printWarning( f"'{userMutator}' mutator contains an unwanted binary" ) selMutator = mutator if selMutator.mutatorType == "command": selMutator.prefStubs = self.getPrefStubs( selMutator.stubs, sizePref, timePref, binaryPref, filePref) break if selMutator is None: printError(f"Selected mutator '{userMutator}' not found") else: prefMutators = self.getPrefMutators(mutators, sizePref, timePref, binaryPref, filePref, prevCmdOb) selMutator = self.randGen.randSelect(prefMutators) if selMutator is not None and selMutator.mutatorType == "command": selMutator.deobStub = self.choosePrefStub(selMutator.prefStubs, sizePref, timePref, binaryPref, filePref, userStub) if selMutator.deobStub: selMutator.deobStub.mangler = selMutator.mangler selMutator.deobStub.randGen = selMutator.mangler.randGen else: printError( f"All of '{selMutator.longName}'s Stubs do not fulfil your requirements" ) return selMutator
def genObfuscationLayer(self, payload, userMutator=None, userStub=None, sizePref=None, timePref=None, binaryPref=None, filePref=None, enableMangling=None, mangleBinaries=None, binaryManglePercent=None, randWhitespace=None, randWhitespaceRange=None, insertChars=None, insertCharsRange=None, misleadingCmds=None, misleadingCmdsRange=None, writeDir=None, debug=None): """ Generate one layer of obfuscation. If called with the userMutator or userStub parameters, the Mutator and/or Stub specified by userMutator and/or userStub will be used to mutate the payload. If those parameters are not used, a Mutator and Stub (if appropriate) will be chosen automatically. .. note:: If not set, the sizePref, timePref, binaryPref, filePref, and writeDir parameters will be set to the coresponding attributes of the ObfuscationHandler object being called from. :param payload: input command(s) to obfuscate :type payload: str :param userMutator: the `longName` attribute of a :class:`bashfuscator.common.objects.Mutator` :type userMutator: lowercase str :param userStub: the `longName` attribute of a :class:`bashfuscator.common.objects.Stub` :type userStub: lowercase str :param sizePref: payload size user preference :type sizePref: int :param timePref: execution time user preference :type timePref: int :param binaryPref: list of binaries that the chosen Mutator should or should not use :type binaryPref: tuple containing a list of strs, and a bool :param filePref: file write user preference :type filePref: bool :returns: a str containing the 'payload' argument obfuscated by a single Mutator """ if sizePref is None: sizePref = self.sizePref if timePref is None: timePref = self.timePref if binaryPref is None: binaryPref = self.binaryPref if filePref is None: filePref = self.filePref if enableMangling is None: enableMangling = self.enableMangling if mangleBinaries is None: mangleBinaries = self.mangleBinaries if binaryManglePercent is None: binaryManglePercent = self.binaryManglePercent if randWhitespace is None: randWhitespace = self.randWhitespace if randWhitespaceRange is None: randWhitespaceRange = self.randWhitespaceRange if insertChars is None: insertChars = self.insertChars if insertCharsRange is None: insertCharsRange = self.insertCharsRange if misleadingCmds is None: misleadingCmds = self.misleadingCmds if misleadingCmdsRange is None: misleadingCmdsRange = self.misleadingCmdsRange if debug is None: debug = self.debug if writeDir is None: writeDir = self.writeDir selMutator = None if userMutator: mutatorType = userMutator.split("/")[0] if mutatorType == "command": selMutator = self.choosePrefMutator(self.cmdObfuscators, sizePref, timePref, binaryPref, filePref, self.prevCmdOb, userMutator, userStub) self.prevCmdOb = selMutator elif mutatorType == "string": selMutator = self.choosePrefMutator(self.strObfuscators, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) elif mutatorType == "token": selMutator = self.choosePrefMutator(self.tokObfuscators, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) elif mutatorType == "encode": selMutator = self.choosePrefMutator(self.encoders, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) elif mutatorType == "compress": selMutator = self.choosePrefMutator(self.compressors, binaryPref=binaryPref, filePref=filePref, userMutator=userMutator) else: printError(f"ERROR: {mutatorType} isn't a valid mutator type") else: # TODO: handle case when no mutators of chosen type are compatible with user's preferences obChoice = self.randGen.randChoice(3) if obChoice == 0: selMutator = self.choosePrefMutator(self.cmdObfuscators, sizePref, timePref, binaryPref, filePref, self.prevCmdOb) self.prevCmdOb = selMutator elif obChoice == 1: selMutator = self.choosePrefMutator(self.strObfuscators, sizePref, timePref, binaryPref, filePref) else: selMutator = self.choosePrefMutator(self.tokObfuscators, sizePref, timePref) selMutator.sizePref = sizePref selMutator.timePref = timePref selMutator.writeDir = writeDir selMutator._originalCmd = payload selMutator.mangler.initialize(sizePref, enableMangling, mangleBinaries, binaryManglePercent, randWhitespace, randWhitespaceRange, insertChars, insertCharsRange, misleadingCmds, misleadingCmdsRange, debug) payload = selMutator.mutate(payload) selMutator._obfuscatedCmd = payload self.randGen.forgetUniqueStrs() payload = self.evalWrap(payload, selMutator) return payload