def main(): if sys.version_info[0] != 3: print(ERROR_COLOUR + "[-] Intensio-Obfuscator only support Python 3.x") sys.exit(0) if sys.platform != "win32" and sys.platform != "linux": print(ERROR_COLOUR + "[-] This tool support [windows - Linux] only !") sys.exit(0) args = Args() utils = Utils() if len(sys.argv) > 1 and len(sys.argv) <= 13: pass else: print(ERROR_COLOUR + "[-] Incorrect number of arguments\n") args.GetArgHelp() sys.exit(ERROR_BAD_ARGUMENTS) if args.GetArgsValue().input: if args.GetArgsValue().output: if args.GetArgsValue().mixerlevel: if re.match(r"^lower$|^medium$|^high$", args.GetArgsValue().mixerlevel): if not args.GetArgsValue().paddingscript and not args.GetArgsValue().replacetostr \ and not args.GetArgsValue().replacefilename and not args.GetArgsValue().replacetohex: print( ERROR_COLOUR + "\n[-] Need at least one argument [-rts] - [-ps] - [-rfn] - [-rth]" ) sys.exit(ERROR_BAD_ARGUMENTS) else: print( ERROR_COLOUR + "[-] Incorrect level of mixerlevel, [lower - medium - high] only supported\n" ) sys.exit(ERROR_INVALID_PARAMETER) else: print(ERROR_COLOUR + "[-] Mixerlevel [-m, --mixerlevel] argument missing\n") sys.exit(ERROR_BAD_ARGUMENTS) else: print(ERROR_COLOUR + "[-] Output [-o, --output] argument missing\n") sys.exit(ERROR_BAD_ARGUMENTS) else: print(ERROR_COLOUR + "[-] Input [-i, --input] argument missing\n") sys.exit(ERROR_BAD_ARGUMENTS) for line in INTENSIO_BANNER.split("\n"): time.sleep(0.05) print(BANNER_COLOUR + line) # -- Analysis and set up of the work environment -- # print( SECTION_COLOUR + "\n\n*********************** [ Analyze and setup environment ] ************************\n" ) analyzeData = Analyze() analyseDataInEnv = analyzeData.InputAvailable( inputArg=args.GetArgsValue().input, verboseArg=args.GetArgsValue().verbose) if analyseDataInEnv == EXIT_SUCCESS: print("\n[+] Analyze input argument '{0}' -> ".format( args.GetArgsValue().input) + SUCESS_COLOUR + "Successful") else: print("[-] Analyze input '{0}' -> ".format(args.GetArgsValue().input) + FAILED_COLOUR + "failed\n") sys.exit(ERROR_INVALID_FUNCTION) analyseDataOutEnv = analyzeData.OutputAvailable( inputArg=args.GetArgsValue().input, outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if analyseDataOutEnv == EXIT_SUCCESS: print("\n[+] Analyze and setup output argument environment '{0}' -> " \ .format(args.GetArgsValue().output) + SUCESS_COLOUR + "Successful") else: print( "[-] Analyze output '{0}' -> ".format(args.GetArgsValue().output) + FAILED_COLOUR + "failed\n") sys.exit(ERROR_INVALID_FUNCTION) # -- Obfuscation process -- # print( SECTION_COLOUR + "\n\n************************ [ Obfuscation remove comment ] *************************\n" ) removeData = Remove() removeCommentsData = removeData.Comments( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if removeCommentsData == EXIT_SUCCESS: print("[+] Obfuscation remove comments -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation remove comments -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") print( SECTION_COLOUR + "\n\n*********************** [ Obfuscation remove line space ] ***********************\n" ) if removeData: pass else: removeData = Remove() removeLinesSpacesData = removeData.LinesSpaces( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if removeLinesSpacesData == EXIT_SUCCESS: print("[+] Obfuscation remove lines spaces -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation remove lines spaces -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- If empty class (avert to generate an error) -- # print( SECTION_COLOUR + "\n\n*********************** [ Correction padding empty class ] **********************\n" ) paddingData = Padding() paddingDataEmptyClass = paddingData.EmptyClasses( outputArg=args.GetArgsValue().output, mixerLevelArg=args.GetArgsValue().mixerlevel, verboseArg=args.GetArgsValue().verbose) if paddingDataEmptyClass == EXIT_SUCCESS: pass else: print("\n[-] Padding empty class -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- If empty functions (avert to generate an error) -- # print( SECTION_COLOUR + "\n\n********************** [ Correction padding empty function ] ********************\n" ) if paddingData: pass else: paddingData = Padding() paddingDataEmptyFunc = paddingData.EmptyFunctions( outputArg=args.GetArgsValue().output, mixerLevelArg=args.GetArgsValue().mixerlevel, verboseArg=args.GetArgsValue().verbose) if paddingDataEmptyFunc == EXIT_SUCCESS: pass else: print("\n[-] Padding empty function -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") print( SECTION_COLOUR + "\n\n**************** [ Obfuscation replace string to string mixed ] *****************\n" ) if args.GetArgsValue().replacetostr: replaceData = Replace() replaceDataStrStr = replaceData.StringToString( outputArg=args.GetArgsValue().output, mixerLevelArg=args.GetArgsValue().mixerlevel, verboseArg=args.GetArgsValue().verbose) if replaceDataStrStr == EXIT_SUCCESS: print("[+] Obfuscation replace string to string mixed -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation replace string to string mixed -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace string to string ] mixed no asked !") print( SECTION_COLOUR + "\n\n********************* [ Obfuscation adding padding script ] *********************\n" ) if args.GetArgsValue().paddingscript: if paddingData: pass else: paddingData = Padding() paddingDataGarbage = paddingData.AddRandomScripts( outputArg=args.GetArgsValue().output, mixerLevelArg=args.GetArgsValue().mixerlevel, verboseArg=args.GetArgsValue().verbose) if paddingDataGarbage == EXIT_SUCCESS: print("[+] Obfuscation padding script -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation padding script -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ padding script ] no asked !") print( SECTION_COLOUR + "\n\n********************** [ Obfuscation replace file name ] ************************\n" ) if args.GetArgsValue().replacefilename: if args.GetArgsValue().replacetostr: pass else: replaceData = Replace() replaceDataStrFname = replaceData.FilesName( outputArg=args.GetArgsValue().output, mixerLevelArg=args.GetArgsValue().mixerlevel, verboseArg=args.GetArgsValue().verbose) if replaceDataStrFname == EXIT_SUCCESS: print("\n[+] Obfuscation replace file name -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation replace file name -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace file name ] feature no asked !") print( SECTION_COLOUR + "\n\n******************** [ Obfuscation replace string to hex ] **********************\n" ) if args.GetArgsValue().replacetohex: if args.GetArgsValue().replacetostr or args.GetArgsValue( ).replacefilename: pass else: replaceData = Replace() replaceDataStrHex = replaceData.StringsToHex( outputArg=args.GetArgsValue().output, mixerLevelArg=args.GetArgsValue().mixerlevel, verboseArg=args.GetArgsValue().verbose) if replaceDataStrHex == EXIT_SUCCESS: print("\n[+] Obfuscation replace string to hex -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation replace string to hex -> " + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace string to hex ] feature no asked !") # -- Remove if python pyc file in output directory -- # print( SECTION_COLOUR + "\n\n*********************** [ Correction remove .pyc file ] *************************\n" ) if removeData: pass else: removeData = Remove() removePycData = removeData.TrashFiles( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose, ) if removePycData == EXIT_SUCCESS: pass else: print("\n[-] Remove .pyc file in {0} directory -> ".format( args.GetArgsValue().output) + FAILED_COLOUR + "Failed") if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" )
class Remove: def __init__(self): self.utils = Utils() def Backslashes(self, codeArg, outputArg): checkLine = 0 numberFiles = 0 numberGoodFile = 0 if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFiles), recursive=True) ] # -- Delete line breaks -- # for file in recursFiles: if blockDir in file: continue else: with fileinput.FileInput(file, inplace=True) as inputFile: for line in inputFile: if line.strip(): print(line.rstrip()) # -- Check if all line breaks are deleted -- # for file in recursFiles: checkLine = 0 # Initialize check vars for the next file if blockDir in file: continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if eachLine == "\n": checkLine += 1 if checkLine == 0: numberGoodFile += 1 numberFiles += 1 else: numberGoodFile += 0 numberFiles += 1 if numberGoodFile == numberFiles: return EXIT_SUCCESS else: return EXIT_FAILURE def Commentaries(self, codeArg, outputArg): countLineOutput = 0 countLineInput = 0 noCommentary = 0 isCommentary = 0 countRecursFiles = 0 if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" commentariesBeginLine = r"^\#.*" # Begin '#' quoteOfCommentariesMultipleLines = r"^\s*[\"|\']{3}$" # """ and ''' without before variables and if commentaries is over multiple lines quoteInRegex = r"\={1}\s*r[\"|\']{1}" # If quote in regex quoteOfEndCommentariesMultipleLines = r"^\s*[\"|\']{3}\)?\.?" # """ and ''' without before variables, if commentaries is over multiple lines and he finish by .format() funtion quoteOfCommentariesOneLine = r"[\"|\']{3}.*[\"|\']{3}$" # """ and ''' without before variables and if commentary is over one line, (""" commentaries """) quoteIntoVariable = r".*\={1}\s*\w*\.?\w*[\(|\.]{1}[\"|\']{3}|.*\={1}\s*[\"|\']{3}" # """ and ''' with before variables commentariesAfterLine = r"\s*\#[^\"|^\'|^\.|^\?|^\*|^\!|^\]|^\[|^\\|^\)|^\(|^\{|^\}].*" # '#' after line of code recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFiles), recursive=True) ] # -- Remove commentaries and Count commentaries will be removed -- # for number in recursFiles: countRecursFiles += 1 print("\n[+] Running remove commentaries in {0} file(s)...\n".format( countRecursFiles)) with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: pbar.update(1) if blockDir in file: continue else: # -- Remove commentaries -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: searchCommentariesAfterLine = re.search( commentariesAfterLine, eachLine) searchCommentariesBeginLine = re.search( commentariesBeginLine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: print(eachLine) continue if re.match(quoteInRegex, eachLine): continue elif re.match(quoteIntoVariable, eachLine): noCommentary += 1 elif re.match( quoteOfCommentariesMultipleLines, eachLine ) or re.match( quoteOfEndCommentariesMultipleLines, eachLine): isCommentary += 1 else: pass if re.match(quoteOfCommentariesOneLine, eachLine): countLineInput += 1 isCommentary = 0 continue elif isCommentary == 1 and noCommentary == 0: countLineInput += 1 continue elif isCommentary == 0 and noCommentary == 1: print(eachLine) continue elif isCommentary == 2: countLineInput += 1 isCommentary = 0 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 print(eachLine) continue else: pass if searchCommentariesBeginLine is not None: countLineInput += 1 eachLine = eachLine.replace( searchCommentariesBeginLine.group(0), "") print(eachLine) elif searchCommentariesAfterLine is not None: eachLine = eachLine.replace( searchCommentariesAfterLine.group(0), "") countLineInput += 1 print(eachLine) else: print(eachLine) # -- Initialize vars -- # isCommentary = 0 noCommentary = 0 # -- Check if all commentaries are removed -- # for file in recursFiles: countLineOutput = 0 if blockDir in file: continue else: with open(file, "r") as readFile: countLineOutput = 0 readF = readFile.readlines() for eachLine in readF: searchCommentariesAfterLine = re.search( commentariesAfterLine, eachLine) searchCommentariesBeginLine = re.search( commentariesBeginLine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: continue if re.match(quoteInRegex, eachLine): continue elif re.match(quoteIntoVariable, eachLine): noCommentary += 1 elif re.match( quoteOfCommentariesMultipleLines, eachLine) or re.match( quoteOfEndCommentariesMultipleLines, eachLine): isCommentary += 1 else: pass if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineOutput += 1 continue elif isCommentary == 1 and noCommentary == 0: countLineOutput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineOutput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if searchCommentariesBeginLine is not None: countLineOutput += 1 elif searchCommentariesAfterLine is not None: countLineOutput += 1 else: pass if (Remove.Backslashes(self, codeArg, outputArg) == 0): if countLineOutput == 0: print("\n-> {0} lines of commentaries removed\n".format( countLineInput)) return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE def PrintFunctions(self, codeArg, outputArg): countPrintLine = 0 countCheckPrintLine = 0 countRecursFiles = 0 checkPrintPy3MultipleLines = 0 checkPrintPy2MultipleLines = 0 if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" detectPrint = r"\s*print" detectPythonPrint2 = r"\s*print\s*[\"|\']{1}" detectPythonPrint3 = r"\s*print\s*\({1}" detectPythonPrintMultipleLines = r"^\s+[\"\']{1}\s*\w+|^[\"\']{1}\s*\w+" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFiles), recursive=True) ] for number in recursFiles: countRecursFiles += 1 print("\n[+] Running remove print function in {0} file(s)...\n".format( countRecursFiles)) with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: pbar.update(1) if blockDir in file: continue else: # -- Remove all print functions -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if re.match(detectPrint, eachLine): countPrintLine += 1 # -- If print() python 3 is multiple lines -- # if re.match(detectPythonPrint3, eachLine): if "(" in eachLine and not ")" in eachLine: checkPrintPy3MultipleLines += 1 continue else: continue # -- If print python 2 is multiple lines -- # elif re.match(detectPythonPrint2, eachLine): checkPrintPy2MultipleLines += 1 continue else: if checkPrintPy3MultipleLines == 1: if ")" in eachLine and not "(" in eachLine: checkPrintPy3MultipleLines = 0 continue else: continue elif checkPrintPy2MultipleLines > 0: if re.match(detectPythonPrintMultipleLines, eachLine): checkPrintPy2MultipleLines += 1 continue else: checkPrintPy2MultipleLines = 0 print(eachLine) continue else: print(eachLine) # -- Check if all print functions are removed -- # for file in recursFiles: if blockDir in file: continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if re.match(detectPrint, eachLine): countCheckPrintLine += 1 if (Remove.Backslashes(self, codeArg, outputArg) == 0): if countCheckPrintLine == 0: print("\n-> {0} print functions removed\n".format( countPrintLine)) return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE def TrashFiles(self, codeArg, outputArg): removeFiles = 0 if codeArg == "python": detectFiles = "pyc" blockDir = "__pycache__" detectFilesPycFile = r"\w+\.{1}pyc" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFiles), recursive=True) ] try: # -- Remove pyc file(s) for file in recursFiles: os.remove(file) removeFiles += removeFiles + 1 # -- Check if pyc file(s) are removed for file in recursFiles: if re.match(detectFilesPycFile, file): return EXIT_FAILURE return removeFiles except Exception as e: print(ERROR_COLOUR + "[-] {0}".format(e)) return EXIT_FAILURE
class Remove: def __init__(self): self.utils = Utils() def LineBreaks(self, oneFileArg, codeArg, outputArg): checkLine = 0 numberFiles = 0 numberFileGood = 0 ######################################### One file only ######################################### if oneFileArg: # -- Delete line breaks -- # with fileinput.FileInput(outputArg, inplace=True) as inputFile: for line in inputFile: if line.strip(): print(line.rstrip()) # -- Check if all line breaks are deleted -- # with open(outputArg, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if eachLine == "\n": checkLine += 1 if checkLine == 0: return EXIT_SUCCESS else: return EXIT_FAILURE ######################################### Multiple files ######################################### else: if codeArg == "python": inputExt = "py" blockdirs = r"__pycache__" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, self.utils.Platform(), inputExt), recursive=True)] # -- Delete line breaks -- # for output in recursFiles: if re.match(blockdirs, output): continue else: with fileinput.FileInput(output, inplace=True) as inputFile: for line in inputFile: if line.strip(): print(line.rstrip()) # -- Check if all line breaks are deleted -- # for output in recursFiles: checkLine = 0 # Initialize check vars for the next file if re.match(blockdirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if eachLine == "\n": checkLine += 1 if checkLine == 0: numberFileGood += 1 numberFiles += 1 else: numberFileGood += 0 numberFiles += 1 if numberFileGood == numberFiles: return EXIT_SUCCESS else: return EXIT_FAILURE def Commentaries(self, oneFileArg, codeArg, outputArg): countLineOutput = 0 countLineInput = 0 noCommentary = 0 isCommentary = 0 if codeArg == "python": classicCommentariesDefine = r"\#+.*" # begin '#' and begin code then '#' quoteOfCommentariesMultipleLine = r"^[\"\']+" # """ and ''' without before variables and if commentaries is over multiple lines quoteOfCommentariesOneLine = r"[\"\']{3}.*[\"\']{3}" # """ and ''' without before variables and if commentary is over one line, (""" commentaries """) noQuoteOfCommentaries = r"\w+\s*\={1}\s*[\"\']{3}" # """ and ''' with before variables print("############### [ Commentaries ] ###############\n") print("\n[+] Running commentaries remove...\n") ######################################### One file only ######################################### if oneFileArg: # -- Count commentaries will be removed -- # with open(outputArg, "r") as readFile: readF = readFile.readlines() for eachLine in readF: search = re.search(classicCommentariesDefine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if isCommentary == 1 and noCommentary == 0: if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineInput += 1 continue countLineInput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineInput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if search is not None: countLineInput += 1 # -- Remove commentaries -- # with fileinput.input(outputArg, inplace=True) as inputFile: for eachLine in inputFile: search = re.search(classicCommentariesDefine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: print(eachLine) continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if isCommentary == 1 and noCommentary == 0: if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 continue continue elif isCommentary == 0 and noCommentary == 1: print(eachLine) continue elif isCommentary == 2: isCommentary = 0 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 print(eachLine) continue else: pass if search is not None: eachLine = eachLine.replace(search.group(0), "") print(eachLine) else: print(eachLine) # -- Check if all commentaries are removed -- # with open(outputArg, "r") as readFile: countLineOutput = 0 readF = readFile.readlines() for eachLine in readF: search = re.search(classicCommentariesDefine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if isCommentary == 1 and noCommentary == 0: if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineOutput += 1 continue countLineOutput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineOutput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if search is not None: countLineOutput += 1 if countLineOutput == 0: print("-> {0} lines of commentaries removed\n".format(countLineInput)) if (Remove.LineBreaks(self, oneFileArg, codeArg, outputArg) == 0): return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE ######################################### Multiple files ######################################### else: if codeArg == "python": inputExt = "py" blockdirs = r"__pycache__" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, self.utils.Platform(), inputExt), recursive=True)] # -- Count commentaries will be removed -- # for output in recursFiles: if re.match(blockdirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: search = re.search(classicCommentariesDefine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if isCommentary == 1 and noCommentary == 0: if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineInput += 1 continue countLineInput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineInput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if search is not None: countLineInput += 1 # -- Remove commentaries -- # for output in recursFiles: if re.match(blockdirs, output): continue else: # -- Remove commentaries -- # with fileinput.input(output, inplace=True) as inputFile: for eachLine in inputFile: search = re.search(classicCommentariesDefine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: print(eachLine.rstrip()) continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if isCommentary == 1 and noCommentary == 0: if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 continue continue elif isCommentary == 0 and noCommentary == 1: print(eachLine) continue elif isCommentary == 2: isCommentary = 0 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 print(eachLine) continue else: pass if search is not None: eachLine = eachLine.replace(search.group(0), "") # Util if line containt code and then '#'. (currently commentary) print(eachLine) else: print(eachLine) # -- Check if all commentaries are removed -- # for output in recursFiles: countLineOutput = 0 if re.match(blockdirs, output): continue else: with open(output, "r") as readFile: countLineOutput = 0 readF = readFile.readlines() for eachLine in readF: search = re.search(classicCommentariesDefine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if isCommentary == 1 and noCommentary == 0: if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineOutput += 1 continue countLineOutput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineOutput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if search is not None: countLineOutput += 1 if countLineOutput == 0: print("-> {0} lines of commentaries removed\n".format(countLineInput)) if (Remove.LineBreaks(self, oneFileArg, codeArg, outputArg) == 0): return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() self.pythonExcludeDefaultString = "exclude/string_to_string_mixed/exclude_word_do_not_modify.txt" self.pythonExcludeUserString = "exclude/string_to_string_mixed/exclude_word_by_user.txt"
def main(): if sys.version_info[0] != 3: print(Colors.ERROR + "[-] Intensio-Obfuscator only support Python 3.x" + Colors.DISABLE) sys.exit(1) if sys.platform != "win32" and sys.platform != "linux": print(Colors.ERROR + "[-] This tool support [windows - Linux] only !" + Colors.DISABLE) sys.exit(1) args = Args() utils = Utils() if len(sys.argv) > 1 and len(sys.argv) <= 13: pass else: print(Colors.ERROR + "[-] Incorrect number of arguments\n" + Colors.DISABLE) args.GetArgHelp() sys.exit(1) if args.GetArgsValue().input: if args.GetArgsValue().output: if re.match(r"^lower$|^medium$|^high$", args.GetArgsValue().mixerlength): if not args.GetArgsValue().paddingscript and not args.GetArgsValue().replacetostr \ and not args.GetArgsValue().replacefilename and not args.GetArgsValue().replacetohex: print( Colors.ERROR + "\n[-] Need at least one argument [-rts] - [-ps] - [-rfn] - [-rth]" + Colors.DISABLE) sys.exit(1) else: print( Colors.ERROR + "[-] -mlen, --mixerlength argument [lower-medium-high] only supported\n" + Colors.DISABLE) sys.exit(1) else: print(Colors.ERROR + "[-] Output [-o, --output] argument missing\n" + Colors.DISABLE) sys.exit(1) else: print(Colors.ERROR + "[-] Input [-i, --input] argument missing\n" + Colors.DISABLE) sys.exit(1) for line in INTENSIO_BANNER.split("\n"): time.sleep(0.05) print(line) # -- Analysis and set up of the work environment -- # print(Colors.SECTION + "\n\n********************* [ Analyze and setup environment ] **********************\n" \ + Colors.DISABLE) analyzeData = Analyze() analyseDataInEnv = analyzeData.InputAvailable( inputArg=args.GetArgsValue().input, verboseArg=args.GetArgsValue().verbose) if analyseDataInEnv == 0: print("\n[+] Analyze input argument '{}' -> ".format(args.GetArgsValue().input) + Colors.SUCCESS + \ "Successful" + Colors.DISABLE) else: print("[-] Analyze input '{}' -> ".format(args.GetArgsValue().input) + Colors.ERROR + "failed\n" + Colors.DISABLE) sys.exit(1) analyseDataOutEnv = analyzeData.OutputAvailable( inputArg=args.GetArgsValue().input, outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if analyseDataOutEnv == 0: print("\n[+] Analyze and setup output argument environment '{}' -> " \ .format(args.GetArgsValue().output) + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print( "[-] Analyze output '{}' -> ".format(args.GetArgsValue().output) + Colors.ERROR + "failed\n" + Colors.DISABLE) sys.exit(1) # -- Obfuscation process -- # print( Colors.SECTION + "\n\n********************** [ Obfuscation delete comments ] ***********************\n" + Colors.DISABLE) deleteData = Delete() deleteCommentsData = deleteData.Comments( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if deleteCommentsData == 0: print("[+] Obfuscation delete comments -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation delete comments -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") print( Colors.SECTION + "\n\n******************** [ Obfuscation delete line space(s) ] ********************\n" + Colors.DISABLE) if deleteData: pass else: deleteData = Delete() deleteLinesSpacesData = deleteData.LinesSpaces( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if deleteLinesSpacesData == 0: print("[+] Obfuscation delete lines spaces -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation delete lines spaces -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- If empty class (avert to generate an error) -- # print( Colors.SECTION + "\n\n******************* [ Correction padding empty class(es) ] *******************\n" + Colors.DISABLE) paddingData = Padding() paddingDataEmptyClass = paddingData.EmptyClasses( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if paddingDataEmptyClass == 0: pass else: print("\n[-] Padding empty class -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- If empty functions (avert to generate an error) -- # print( Colors.SECTION + "\n\n****************** [ Correction padding empty function(s) ] ******************\n" + Colors.DISABLE) if paddingData: pass else: paddingData = Padding() paddingDataEmptyFunc = paddingData.EmptyFunctions( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if paddingDataEmptyFunc == 0: pass else: print("\n[-] Padding empty function -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") print( Colors.SECTION + "\n\n************ [ Obfuscation replace string(s) to string(s) mixed ] ************\n" + Colors.DISABLE) if args.GetArgsValue().replacetostr: replaceData = Replace() replaceDataStrStr = replaceData.StringToString( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if replaceDataStrStr == 0: print("[+] Obfuscation replace string to string mixed -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation replace string to string mixed -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace string to string ] mixed no asked !") print( Colors.SECTION + "\n\n****************** [ Obfuscation adding padding script(s) ] ******************\n" + Colors.DISABLE) if args.GetArgsValue().paddingscript: if paddingData: pass else: paddingData = Padding() paddingDataGarbage = paddingData.AddRandomScripts( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if paddingDataGarbage == 0: print("[+] Obfuscation padding script -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation padding script -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ padding script ] no asked !") print( Colors.SECTION + "\n\n******************** [ Obfuscation replace file(s) name ] ********************\n" + Colors.DISABLE) if args.GetArgsValue().replacefilename: if args.GetArgsValue().replacetostr: pass else: replaceData = Replace() replaceDataStrFname = replaceData.FilesName( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if replaceDataStrFname == 0: print("\n[+] Obfuscation replace file name -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation replace file name -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace file name ] feature no asked !") print( Colors.SECTION + "\n\n****************** [ Obfuscation replace string(s) to hex ] ******************\n" + Colors.DISABLE) if args.GetArgsValue().replacetohex: if args.GetArgsValue().replacetostr or args.GetArgsValue( ).replacefilename: pass else: replaceData = Replace() replaceDataStrHex = replaceData.StringsToHex( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if replaceDataStrHex == 0: print("\n[+] Obfuscation replace string to hex -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation replace string to hex -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace string to hex ] feature no asked !") # -- Delete line spaces of padding scripts -- # if args.GetArgsValue().paddingscript: print( Colors.SECTION + "\n\n******************** [ Obfuscation delete line space(s) ] ********************\n" + Colors.DISABLE) if deleteData: pass else: deleteData = Delete() deleteLinesSpacesData = deleteData.LinesSpaces( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if deleteLinesSpacesData == 0: print("[+] Obfuscation delete lines spaces of padding scripts-> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print( "\n[-] Obfuscation delete lines spaces of padding scripts -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- Delete if python pyc file in output directory -- # print( Colors.SECTION + "\n\n********************* [ Correction delete .pyc file(s) ] *********************\n" + Colors.DISABLE) if deleteData: pass else: deleteData = Delete() deletePycData = deleteData.TrashFiles( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose, ) if deletePycData == 0: pass else: print("\n[-] Delete .pyc file from {} directory -> ".format(args.GetArgsValue().output) + Colors.ERROR + \ "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" )
class Replace: def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() self.pythonExcludeWords = "exclude_python_words.txt" self.pythonIncludeWords = "include_python_words.txt" def EachLine(self, codeArg, eachLine, Dict): getIndexLineList = [] returnLine = [] charValue = [] checkCharAfterWord = 1 wordSetter = 0 checkGetKey = "" checkGetWord = "" getLine = "" breakLine = "" if codeArg == "python": regReplace = r"(\.)|(:)|(\))|(\()|(=)|(\[)|(\])|({)|(})|(,)|(\+)|(\s)|(\*)|(\+)|(\-)" # -- Get list of all letters in line -- # for indexLine, letterLine in enumerate(eachLine): getIndexLineList.append(letterLine) # -- Loop in each letter of line -- # for indexLine, letterLine in enumerate(eachLine): # -- Add in final line list all chars mixed -- # if charValue != []: for obfIndex, obfValue in enumerate(charValue): if obfIndex == 0: # First letter in string mixed are already add in the final line continue returnLine.append(obfValue) charValue = [] # -- If the variable is only a letter, check if the next character is specific so as not to replace it -- # if re.match(regReplace, letterLine): returnLine.append(letterLine) # -- Count indexes of word to move after it --# countDeleteIndex = 0 for i in getWord: countDeleteIndex += 1 wordSetter = countDeleteIndex - 2 # -2 Is to letter already append and the letter in progress else: # -- The index numbers of variable is decremented to add the mixed letters that be replaced -- # if wordSetter > 0: wordSetter -= 1 continue else: try: # -- Loop in the dictionary with already mixed values-- # for key, value in Dict: for indexKey, letterKey in enumerate(key): for letterValue in value: # -- Check if letter of word is equal to letter of key -- # if letterKey == letterLine: # -- Begin process to check -- # if indexKey == 0: # -- Place index position after the word -- # indexExplore = indexLine + len(key) # -- If indexError return to next loop -- # try: getIndexLineList[indexExplore] except IndexError: continue # -- Check the char after the word -- # if re.match(regReplace, getIndexLineList[indexExplore]): # -- Check word finded is not into the other word -- # indexExplore = indexLine - 1 if not re.match(r"(\w)", getIndexLineList[indexExplore]): if codeArg == "python": # -- Check if it's 'from' and 'import' word key in line to avoid replace name of file if variable is identic name to file -- # getLine = "".join(getIndexLineList) if "import" in getLine: if "from" in getLine: # -- Cut the line from the current index and check if it is not there is the keyword "import" in the line -- # breakLine = getIndexLineList[:indexLine] breakLine = "".join(breakLine) if not "import" in breakLine: # -- It's file because only 'from'key word -- # checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 0 else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 else: checkCharAfterWord = 1 if checkCharAfterWord == 0: # -- Initialize vars -- # getCharAllInKey = [] getWord = [] indexExploreStart = indexLine indexExploreEnd = indexLine + len(key) - 1 # Remove -1, first letter is already increment # -- List contain all letters of key -- # for getLetterKey in key: getCharAllInKey.append(getLetterKey) # -- Check if all letters of key is equal to all letters of word -- # for indexCheckLetter, checkLetter in enumerate(getIndexLineList): if indexCheckLetter >= indexExploreStart and indexCheckLetter <= indexExploreEnd: getWord.append(checkLetter) # -- Check if number of chars in key equal number of chars in word -- # if list(set(getCharAllInKey) - set(getWord)) == []: checkGetWord = "".join(getWord) checkGetKey = "".join(getCharAllInKey) # -- Check if key == word -- # if checkGetWord == checkGetKey: for obfChar in value: charValue.append(obfChar) letterLine = letterValue raise BreakLoop else: continue else: continue else: continue else: continue else: continue raise BreakLoop except BreakLoop: returnLine.append(letterLine) # -- Rewrite the line -- # returnLine = "".join(returnLine) return returnLine[:] def VarsDefinedByUser(self, oneFileArg, codeArg, outputArg, mixerLevelArg): variablesDict = {} checkVarsMixed = [] wordsExcluded = [] wordsExcludedFound = [] wordsInclude = [] checkCountVarsMixed = 0 checkCountVarsValue = 0 checkPassing = 0 numberReplaced = 0 isCommentary = 0 noCommentary = 0 if codeArg == "python": variablesDefined = r"(^\w+|\w+)([\s|^\s]*=[\s|\w|\"|\'])" # Classic variables variablesErrorDefined = r"except(\s+\w+\sas\s)(\w)" # Error variables variablesLoopDefined = r"for\s([\w\s?\,?]{1,})(\sin)" # Loop variables functionsDefined = r"def\s(\w+)" # Functions classDefined = r"class\s(\w+)" # Classes quoteOfCommentariesOneLine = r"[\"\']{3}.*[\"\']{3}" # """ and ''' without before variables and if commentary is over one line, (""" commentaries """) noQuoteOfCommentaries = r"\s*\w+\s*\={1}\s*[\"\']{3}" # """ and ''' with before variables print("######## [ Variables-Classes-Functions ] ########\n") ######################################### One file only ######################################### if oneFileArg: # -- Find variables - classes - functions and mixed it -- # with open(outputArg, "r") as readFile: readF = readFile.readlines() for eachLine in readF: # -- Classic variables -- # search = re.search(variablesDefined, eachLine) if search != None: # -- Detect mixer -- # mixer = self.mixer.GetStringMixer(mixerLevelArg) # -- Add the mixer value of variables -- # if search.group(1) not in variablesDict: variablesDict[search.group(1)] = mixer # -- Error variables -- # search = re.search(variablesErrorDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(2) not in variablesDict: variablesDict[search.group(2)] = mixer # -- Loop variables -- # search = re.search(variablesLoopDefined, eachLine) if search != None: if "," in search.group(1): varsInFor = [] modifySearch = search.group(1).replace(",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[search.group(1)] = mixer # -- Functions -- # search = re.search(functionsDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in variablesDict: if codeArg == "python": if not re.match(r"(^__init__$)", search.group(1)): variablesDict[search.group(1)] = mixer # -- Classes -- # search = re.search(classDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in variablesDict: variablesDict[search.group(1)] = mixer # -- Delete excluded variables - classes - functions from excluded_python_varaibles.txt in dict -- # if os.path.exists(self.pythonExcludeWords) == True: with open(self.pythonExcludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcluded.append(word) else: print("[-] File '{0}' not found\n".format(self.pythonExcludeWords)) for word in wordsExcluded: if word in variablesDict.keys(): wordsExcludedFound.append(word) del variablesDict[word] # -- Include variables - classes - functions defined from include_python_words.txt in dict -- # if os.path.exists(self.pythonIncludeWords) == True: with open(self.pythonIncludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsInclude.append(word) else: print("[-] File '{0}' not found\n".format(self.pythonIncludeWords)) for word in wordsInclude: if word not in variablesDict.keys(): mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[word] = mixer print("\n[+] Variables - Classes - Functions found :\n") for key, value in variablesDict.items(): print("-> {0} : {1}".format(key, value)) for word in wordsExcludedFound: print("-> {0} : excluded".format(word)) print("\n[+] Running replacement of Variables - Classes - Functions...\n") # -- Change variables - classes - functions to mixed values -- # with fileinput.input(outputArg, inplace=True) as inputFile: for eachLine in inputFile: if not eachLine: continue else: if codeArg == "python": # -- Check code in """ or ''' -- # if "\"\"\"" in eachLine or "\'\'\'" in eachLine: if re.match(quoteOfCommentariesOneLine, eachLine): print(eachLine) continue elif re.match(noQuoteOfCommentaries, eachLine): eachLine = Replace.EachLine(self, codeArg, eachLine, variablesDict.items()) print(eachLine) checkPassing += 1 continue else: checkPassing += 1 if checkPassing == 1: print(eachLine) continue else: checkPassing = 0 eachLine = Replace.EachLine(self, codeArg, eachLine, variablesDict.items()) print(eachLine) # -- Check if variables - classes - functions have been mixed -- # with open(outputArg, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for value in variablesDict.values(): if value in eachLine: checkVarsMixed.append(value) # -- Remove duplicated key -- # checkListVarsMixed = list(dict.fromkeys(checkVarsMixed)) for i in checkListVarsMixed: checkCountVarsMixed += 1 for i in variablesDict.values(): checkCountVarsValue += 1 if checkCountVarsMixed == checkCountVarsValue: print("-> {0} variables - classes - functions replaced\n".format(checkCountVarsValue)) if (self.remove.LineBreaks(oneFileArg, codeArg, outputArg) == 0): return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE ######################################### Multiple files ######################################### else: if codeArg == "python": inputExt = "py" blockdirs = r"__pycache__" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, self.utils.Platform(), inputExt), recursive=True)] # -- Find variables - classes - functions and mixed it -- # for output in recursFiles: if re.match(blockdirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: # -- Classic variables -- # search = re.search(variablesDefined, eachLine) if search != None: # -- Detect mixer -- # mixer = self.mixer.GetStringMixer(mixerLevelArg) # -- Add the mixer value of variables -- # if search.group(1) not in variablesDict: variablesDict[search.group(1)] = mixer # -- Error variables -- # search = re.search(variablesErrorDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(2) not in variablesDict: variablesDict[search.group(2)] = mixer # -- Loop variables -- # search = re.search(variablesLoopDefined, eachLine) if search != None: if "," in search.group(1): varsInFor = [] modifySearch = search.group(1).replace(",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[search.group(1)] = mixer # -- Functions -- # search = re.search(functionsDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in variablesDict: if codeArg == "python": if not re.match(r"(^__init__$)", search.group(1)): variablesDict[search.group(1)] = mixer # -- Classes -- # search = re.search(classDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in variablesDict: variablesDict[search.group(1)] = mixer # -- Remove excluded variables - classes - functions defined from excluded_python_words.txt in dict -- # if os.path.exists(self.pythonExcludeWords) == True: with open(self.pythonExcludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcluded.append(word) else: print("[-] File '{0}' not found\n".format(self.pythonExcludeWords)) for word in wordsExcluded: if word in variablesDict.keys(): wordsExcludedFound.append(word) del variablesDict[word] # -- Include variables - classes - functions defined from include_python_words.txt in dict -- # if os.path.exists(self.pythonIncludeWords) == True: with open(self.pythonIncludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsInclude.append(word) else: print("[-] File '{0}' not found\n".format(self.pythonIncludeWords)) for word in wordsInclude: if word not in variablesDict.keys(): mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[word] = mixer print("\n[+] Variables - Classes - Functions found :\n") for key, value in variablesDict.items(): print("-> {0} : {1}".format(key, value)) for word in wordsExcludedFound: print("-> {0} : excluded".format(word)) print("\n[+] Running replacement of Variables - Classes - Functions...\n") # -- Change variables - classes - functions to mixed values -- # for output in recursFiles: if re.match(blockdirs, output): continue else: with fileinput.input(output, inplace=True) as inputFile: for eachLine in inputFile: if not eachLine: continue else: if codeArg == "python": # -- Check code in """ or ''' -- # if "\"\"\"" in eachLine or "\'\'\'" in eachLine: if re.match(quoteOfCommentariesOneLine, eachLine): print(eachLine) continue elif re.match(noQuoteOfCommentaries, eachLine): eachLine = Replace.EachLine(self, codeArg, eachLine, variablesDict.items()) print(eachLine) checkPassing += 1 continue else: checkPassing += 1 if checkPassing == 1: print(eachLine) continue else: checkPassing = 0 eachLine = Replace.EachLine(self, codeArg, eachLine, variablesDict.items()) print(eachLine) # -- Check if variables - classes - functions have been mixed -- # for output in recursFiles: if re.match(blockdirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for value in variablesDict.values(): if value in eachLine: checkVarsMixed.append(value) # -- Remove duplicated key -- # checkListVarsMixed = list(dict.fromkeys(checkVarsMixed)) for i in checkListVarsMixed: checkCountVarsMixed += 1 for i in variablesDict.values(): checkCountVarsValue += 1 if checkCountVarsMixed == checkCountVarsValue: print("-> {0} variables - classes - functions replaced\n".format(checkCountVarsValue)) if (self.remove.LineBreaks(oneFileArg, codeArg, outputArg) == 0): return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
class Replace: def __init__(self): self.mixer = Mixer() self.utils = Utils() self.pythonExcludeDefaultString = "exclude/string_to_string_mixed/exclude_word_do_not_modify.txt" self.pythonExcludeUserString = "exclude/string_to_string_mixed/exclude_word_by_user.txt" self.pythonExcludeUserFileName = "exclude/file_name/exclude_file_name_by_user.txt" def EachLine(self, line, dictionary, fileNameImport, listModuleImport): getIndexLineList = [] returnLine = [] charValue = [] checkCharAfterWord = 1 wordSetter = 0 checkGetKey = "" checkGetWord = "" getLine = "" breakLine = "" if listModuleImport == True: detectSpecialChars = Reg.detectSpecialChars else: detectSpecialChars = Reg.detectSpecialCharsWihtoutQuotes # -- Get list of all letters in line -- # for indexLine, letterLine in enumerate(line): getIndexLineList.append(letterLine) # -- Loop in each letter of line -- # for indexLine, letterLine in enumerate(line): # -- Add in final line list all chars mixed -- # if charValue != []: for obfIndex, obfValue in enumerate(charValue): if obfIndex == 0: # First letter in string mixed are already added in the final line continue returnLine.append(obfValue) charValue = [] # -- If the variable is only a letter, check if the next character is specific so as not to replace it -- # if re.match(detectSpecialChars, letterLine): returnLine.append(letterLine) # -- Count indexes of word to move after it --# countDeleteIndex = 0 for i in getWord: countDeleteIndex += 1 wordSetter = countDeleteIndex - 2 # -2 Is to letter already append and the letter in progress else: # -- The index numbers of variable is decremented to add the mixed letters that be replaced -- # if wordSetter > 0: wordSetter -= 1 continue else: try: # -- Loop in the dictionary with already mixed values-- # for key, value in dictionary: for indexKey, letterKey in enumerate(key): for letterValue in value: # -- Check if letter of word is equal to letter of key -- # if letterKey == letterLine: # -- Begin process to check -- # if indexKey == 0: # if equal to the first letter of word on <key> variable indexExplore = indexLine + len( key ) # Place index position after the word # -- If indexError return to next loop -- # try: getIndexLineList[indexExplore] except IndexError: continue # -- Check the char after and before the word -- # if re.match( detectSpecialChars, getIndexLineList[ indexExplore]): # Index check if word found is not into the other word indexExploreBefore = indexLine - 1 # Index check if char after the end of string is found with 'detectSpecialChars' regex indexExploreAfter = indexExplore try: if not re.match( r"\w|\\|\%", getIndexLineList[ indexExploreBefore] ): # -- Check if it's 'from' and 'import' file in line to avoid replace \ # name of file if variable is identical name to file -- # getLine = "".join( getIndexLineList) if fileNameImport == False: if "import" in getLine: if "from" in getLine: # -- Cut the line from the current index and check if it is \ # not there is the keyword "import" in the line -- # breakLine = getIndexLineList[: indexLine] breakLine = "".join( breakLine ) if not "import" in breakLine: # -- It's a file because only 'from'key word -- # checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 # -- Check if after char of the word found by 'detectSpecialChars' is \ # not ' or " -- # elif re.match( r"\"|\'", getIndexLineList[ indexExploreAfter] ): if re.match( r"\[|\(|\{", getIndexLineList[ indexExploreAfter - 1] ): checkCharAfterWord = 0 else: checkCharAfterWord = 1 else: checkCharAfterWord = 0 # -- Only for [-rfn, --replacefilsname] feature -- # else: # -- check if file name is imported - # breakLine = getIndexLineList[: indexLine] breakLine = "".join( breakLine) # -- If file name is imported after 'import', the file name is not \ # replaced -- # if "import" in breakLine: checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 except IndexError: checkCharAfterWord = 0 pass else: checkCharAfterWord = 1 if checkCharAfterWord == 0: # -- Initialize vars -- # getCharAllInKey = [] getWord = [] indexExploreStart = indexLine # -- Delete -1, first letter is already increment -- # indexExploreEnd = indexLine + len( key) - 1 # -- List contain all letters of key -- # for getLetterKey in key: getCharAllInKey.append( getLetterKey) # -- Check if all letters of key is equal to all letters of word -- # for indexCheckLetter, checkLetter in enumerate( getIndexLineList): if indexCheckLetter >= indexExploreStart and \ indexCheckLetter <= indexExploreEnd: getWord.append( checkLetter) # -- Check if number of chars in key equal number of chars in word -- # if list( set(getCharAllInKey) - set(getWord)) == []: checkGetWord = "".join( getWord) checkGetKey = "".join( getCharAllInKey) # -- Check if key == word -- # if checkGetWord == checkGetKey: # -- Check if word is not in strings quotes and if a variable # is in format() in end of multiple line -- # if self.utils.DetectIntoSimpleQuotes(getLine, indexLine) == False \ or self.utils.DetectMultipleLinesQuotes(getLine) == True: for obfChar in value: charValue.append( obfChar) letterLine = letterValue raise BreakLoop else: break else: break else: break else: break else: break else: break raise BreakLoop except BreakLoop: returnLine.append(letterLine) # -- Rewrite the line -- # returnLine = "".join(returnLine) return returnLine[:] def StringToString(self, outputArg, mixerLengthArg, verboseArg): variablesDict = {} classesDict = {} functionsDict = {} allDict = {} classFuncDict = {} checkWordsMixed = [] wordsExcludedUser = [] wordsExcludedUserFound = [] wordsExcludedDefault = [] wordsExcludedDefaultFound = [] checkAllWords = [] checkWordsError = [] checkKeyWordsMixed = [] checkCountWordsMixed = 0 checkCountWordsValue = 0 countRecursFiles = 0 multipleLinesQuotes = 0 recursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False) for file in recursFiles: countRecursFiles += 1 print("\n[+] Running replacement of variables/classes/functions in " + str(countRecursFiles) + \ " file(s), he can be long... you have time to make a coffee :)\n") # -- Replace variables/classes/functions to random strings with length defined -- # with Bar("Setting up ", fill="=", max=100, suffix="%(percent)d%%") as bar: for file in recursFiles: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: # -- Variables -- # search = re.search(Reg.detectSimpleVars, eachLine) if search: if "," in search.group(1): modifySearch = search.group(1).replace( ",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg ) i = i.strip() variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) modifySearch = search.group(1).strip() variablesDict[modifySearch] = mixer # -- Error variables -- # search = re.search(Reg.detectErrorVars, eachLine) if search: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) if search.group(2) not in variablesDict: variablesDict[search.group(2)] = mixer # -- Loop variables -- # search = re.search(Reg.detectLoopVars, eachLine) if search: if "," in search.group(1): modifySearch = search.group(1).replace( ",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg ) variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) variablesDict[search.group(1)] = mixer # -- Function(s) -- # search = re.search(Reg.detectFunctions, eachLine) if search: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) if search.group(1) not in functionsDict: if not "__init__" in search.group(1): functionsDict[search.group(1)] = mixer # -- Class(es) -- # search = re.search(Reg.detectClasses, eachLine) if search: mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) if search.group(1) not in classesDict: classesDict[search.group(1)] = mixer bar.next(40) # -- Delete excluded variables/classes/functions defined from \ # 'exclude/string_to_string_mixed/exclude_word_do_not_modify.txt' -- # if os.path.exists(self.pythonExcludeDefaultString) == True: with open(self.pythonExcludeDefaultString, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcludedDefault.append(word) else: print(Colors.ERROR + "[-] '{}' file not found".format(self.pythonExcludeDefaultString) + Colors.DISABLE \ + "\n") bar.next(10) # -- Delete excluded variables/classes/functions defined from \ # 'exclude/string_to_string_mixed/exclude_word_by_user.txt' -- # if os.path.exists(self.pythonExcludeUserString) == True: with open(self.pythonExcludeUserString, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcludedUser.append(word) else: print(Colors.ERROR + "[-] '{}' file not found".format(self.pythonExcludeUserString) + Colors.DISABLE \ + "\n") bar.next(10) for word in wordsExcludedUser: if word in variablesDict.keys(): wordsExcludedUserFound.append(word) if word in classesDict.keys(): wordsExcludedUserFound.append(word) if word in functionsDict.keys(): wordsExcludedUserFound.append(word) bar.next(20) for word in wordsExcludedDefault: if word in variablesDict.keys(): wordsExcludedDefaultFound.append(word) if word in classesDict.keys(): wordsExcludedDefaultFound.append(word) if word in functionsDict.keys(): wordsExcludedDefaultFound.append(word) for word in wordsExcludedUserFound: if word in variablesDict.keys(): del variablesDict[word] if word in classesDict.keys(): del classesDict[word] if word in functionsDict.keys(): del functionsDict[word] for word in wordsExcludedDefaultFound: if word in variablesDict.keys(): del variablesDict[word] if word in classesDict.keys(): del classesDict[word] if word in functionsDict.keys(): del functionsDict[word] bar.next(20) bar.finish() # -- Display variables/classes/functions found -- # if verboseArg: print("\n[+] Variable(s) found :\n") if variablesDict == {}: print("-> No result") else: for key, value in variablesDict.items(): print("-> {} : {}".format(key, value)) print("\n[+] Class(es) found :\n") if classesDict == {}: print("-> No result") else: for key, value in classesDict.items(): print("-> {} : {}".format(key, value)) print("\n[+] Function(s) found :\n") if functionsDict == {}: print("-> No result") else: for key, value in functionsDict.items(): print("-> {} : {}".format(key, value)) print( "\n[+] String excluded found in '{}' that have been matched from '{}' :\n" .format(self.pythonExcludeUserString, outputArg)) if wordsExcludedUserFound == []: print("-> No result") else: for word in wordsExcludedUserFound: print("-> {} : excluded by user".format(word)) print( "\n[+] String excluded found in '{}' that have been matched from '{}' :\n" .format(self.pythonExcludeDefaultString, outputArg)) if wordsExcludedDefaultFound == []: print("-> No result") else: for word in wordsExcludedDefaultFound: print("-> {} : excluded by default".format(word)) print("") # -- Merge all dicts -- # allDict = self.utils.DictMerge(dict1=allDict, dict2=variablesDict) allDict = self.utils.DictMerge(dict1=allDict, dict2=functionsDict) allDict = self.utils.DictMerge(dict1=allDict, dict2=classesDict) classFuncDict = self.utils.DictMerge(dict1=classFuncDict, dict2=classesDict) classFuncDict = self.utils.DictMerge(dict1=classFuncDict, dict2=functionsDict) # -- Change variables/classes/functions to mixed values -- # with Bar("Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Replace variable(s) only -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if not eachLine: continue else: if multipleLinesQuotes == 1: if re.match( Reg.checkIfEndVarStdoutMultipleQuotes, eachLine): if self.utils.DetectMultipleLinesQuotes( eachLine) == True: eachLine = Replace.EachLine( self, line=eachLine, dictionary=allDict.items(), fileNameImport=False, listModuleImport=False) sys.stdout.write(eachLine) multipleLinesQuotes = 0 else: sys.stdout.write(eachLine) else: sys.stdout.write(eachLine) elif re.match(Reg.checkIfVarMultipleQuotes, eachLine) \ or re.match(Reg.checkIfStdoutMultipleQuotes, eachLine): if self.utils.DetectMultipleLinesQuotes( eachLine) == False: pass else: multipleLinesQuotes = 1 eachLine = Replace.EachLine( self, line=eachLine, dictionary=allDict.items(), fileNameImport=False, listModuleImport=False) sys.stdout.write(eachLine) continue else: eachLine = Replace.EachLine( self, line=eachLine, dictionary=allDict.items(), fileNameImport=False, listModuleImport=False) sys.stdout.write(eachLine) bar.next(1) bar.finish() with Bar("Check ", fill="=", max=100, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Check if variables/classes/functions have been mixed -- # with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for key, value in allDict.items(): if value in eachLine: if re.match(r"\w+" + re.escape(value) + r"\w+", eachLine): pass else: checkWordsMixed.append(value) checkKeyWordsMixed.append(key) bar.next(70) # -- Delete duplicated words -- # checkListWordsMixed = list(dict.fromkeys(checkWordsMixed)) checkKeyWordsMixed = list(dict.fromkeys(checkKeyWordsMixed)) bar.next(15) for i in checkListWordsMixed: checkCountWordsMixed += 1 for i in allDict.values(): checkCountWordsValue += 1 bar.next(15) bar.finish() if checkCountWordsMixed == checkCountWordsValue: print( "\n-> {} variable(s)/class(es)/function(s) replaced in {} file(s)\n" .format(checkCountWordsValue, countRecursFiles)) return 1 else: if verboseArg: for key in allDict.keys(): checkAllWords.append(key) checkWordsError = list( set(checkAllWords) - set(checkKeyWordsMixed)) print("\n[!] Word(s) that not been replaced, check if an error will appear when will launch your " + \ "obfuscated code... :\n") if checkWordsError != []: for wordNoReplaced in checkWordsError: print("-> Word : {}".format(wordNoReplaced)) return 0 def StringsToHex(self, outputArg, mixerLengthArg, verboseArg): checkHexError = {} splitLetter = [] getLetterLineList = [] countRecursFiles = 0 checkPrint = 0 numberLine = 0 checkError = False hexLine = "" recursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False) for number in recursFiles: countRecursFiles += 1 print( "\n[+] Running replace all strings to their hexadecimal value in {} file(s)...\n" .format(countRecursFiles)) # -- Replace all strings to their hexadecimal value -- # with Bar("Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Add a new first random line and move the old first line to the second line to avoid replacing it -- # checkPrint = 0 # initialize check print() func at the begining of each file with open(file, "r") as inputFile: stringRandomMixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) firstLine = "{}\n".format(stringRandomMixer) line = inputFile.readlines() line.insert(0, firstLine) with open(file, "w") as inputFile: inputFile.writelines(line) # -- Replace all lines-- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if checkPrint == 0: varMixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) sys.stdout.write(varMixer + "=\"\"\"") checkPrint = 1 else: getLetterLineList = [] for letterLine in eachLine: if len(letterLine.encode("utf-8").hex()) > 2: splitLetter = [] for i in letterLine.encode("utf-8").hex(): splitLetter.append(i) if len(splitLetter) == 2: letterLine = "".join(splitLetter) letterToHex = "\\x" + str( letterLine) getLetterLineList.append( letterToHex) splitLetter = [] else: continue else: letterToHex = "\\x" + str( letterLine.encode("utf-8").hex()) getLetterLineList.append( letterToHex ) # Get list of all letters in line hexLine = "".join(getLetterLineList) sys.stdout.write(hexLine) # -- Add exec funtions to interpret hex code in strings -- # with open(file, "a") as inputFile: inputFile.write("\"\"\"") inputFile.write("\nexec({})".format(varMixer)) bar.next(1) bar.finish() with Bar("Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLine = 0 # -- Check if all lines are replaced of hexadecimal value -- # with open(file, "r") as inputFile: for eachLine in inputFile: numberLine += 1 if not eachLine: continue else: if not "\\x" in eachLine: if re.match(Reg.detectExecFunction, eachLine): continue else: checkHexError[numberLine] = file checkError = True else: continue bar.next(1) bar.finish() if checkError == False: return 1 else: if verboseArg: print( "\n[!] Line(s) that have not been replaced by their hexadecimal values... :\n" ) for key, value in checkHexError.items(): print("\n-> File : {}".format(value)) print("-> Line : {}".format(key)) else: print("\n" + Colors.ERROR + "[!] Launch Intensio-Obfuscator with verbose mode because line(s) have not been " + \ "replaced by their hexadecimal values" + Colors.DISABLE + "\n") return 0 def FilesName(self, outputArg, mixerLengthArg, verboseArg): checkFilesFoundCompare = {} filesNameDict = {} filesNameDictNoExt = {} filesNameFound = [] filesNameFoundNoExt = [] filesNameMixed = [] fileNameExcluded = [] fileNameExcludedFound = [] fileNameExcludedByUser = [] importNoCompliantFound = [] badNameDir = [] numberLine = 0 countRecursFiles = 0 checkCountRecursFiles = 0 currentPosition = os.getcwd() recursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile="__init__", dirOnly=False) recursFilesWithInit = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False) recursDirs = self.utils.CheckFileDir(output=outputArg, detectFiles="", blockDir="__pycache__", blockFile=False, dirOnly=True) for file in recursFiles: countRecursFiles += 1 print("\n[+] Running replace files name in {} file(s)...\n".format( countRecursFiles)) with Bar("Setting up ", fill="=", max=100, suffix="%(percent)d%%") as bar: for file in recursFiles: parseFilePath = file.split( self.utils.Platform(getOS=False, getPathType=True)) mixer = self.mixer.GetStringMixer( mixerLengthArgDefined=mixerLengthArg) filesNameDict[parseFilePath[-1]] = mixer + ".py" filesNameDictNoExt[parseFilePath[-1].replace(".py", "")] = mixer deleteExt = parseFilePath[-1].replace(".py", "") filesNameFound.append(parseFilePath[-1]) filesNameFoundNoExt.append(deleteExt) filesNameMixed.append(mixer + ".py") bar.next(30) # -- Check if directory have the same name for directory in recursDirs: for fileName in filesNameFoundNoExt: if re.match(r".*" + re.escape(self.utils.Platform(getOS=False, getPathType=True)) + r"{1}" + \ re.escape(fileName) + re.escape(self.utils.Platform(getOS=False, getPathType=True)) + \ r"{1}.*", directory): fileNameExcluded.append(fileName) badNameDir.append(fileName) bar.next(20) # -- Delete if file name excluded by user from exclude/file_name/exclude_file_name_by_user.txt' -- # if os.path.exists(self.pythonExcludeUserFileName) == True: with open(self.pythonExcludeUserFileName) as readFile: for fileName in readFile: if "#" in fileName or fileName == "\n" or re.match( r"yourFileName[0-9]{1}", fileName): continue else: fileName = fileName.rstrip() fileNameExcluded.append(fileName) fileNameExcludedByUser.append(fileName) else: print(Colors.ERROR + "[-] '{}' file not found".format( self.pythonExcludeUserFileName) + Colors.DISABLE + "\n") bar.next(10) # -- Delete file name excluded in dictionnary -- # for word in fileNameExcluded: for fileNameNoExt in filesNameFoundNoExt: if fileNameNoExt == word: fileNameExcludedFound.append(word) filesNameFoundNoExt.remove(word) for fileName in filesNameFound: if fileName == word: filesNameFound.remove(word) if word in filesNameDictNoExt.keys(): del filesNameDictNoExt[word] word = word + ".py" if word in filesNameDict.keys(): del filesNameDict[word] bar.next(10) # -- Check if file name in code is after 'import' native python function --# for file in recursFiles: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if re.match(Reg.detectPythonImport, eachLine): searchFileName = re.search(r"(import\s+)(.*)", eachLine) if searchFileName.group(2): searchFileName = searchFileName.group( 2).replace(",", "") searchFileName = searchFileName.split() for i in searchFileName: i = i.strip() for fileNameNoExt in filesNameFoundNoExt: if fileNameNoExt == i: importNoCompliantFound.append(i) filesNameFoundNoExt.remove(i) for fileName in filesNameFound: fileName = fileName.replace(".py", "") if fileName == i: i = i + ".py" filesNameFound.remove(i) if i in filesNameDictNoExt.keys(): del filesNameDictNoExt[i] if i in filesNameDict.keys(): del filesNameDict[i] bar.next(30) bar.finish() # -- Diplay all file name(s) found with their mixed values if verbose arg is actived -- # if verboseArg: print("\n[+] File name(s) found with their mixed values :\n") if filesNameDict == {}: print("-> No result") else: for key, value in filesNameDict.items(): print("-> {} : {}".format(key, value)) print( "\n[+] File name(s) excluded found in '{}' that have been matched from '{}' :\n" .format(self.pythonExcludeUserFileName, outputArg)) if fileNameExcludedByUser == []: print("-> No result") else: for i in fileNameExcludedByUser: print("-> {} : excluded by user".format(i)) print( "\n[+] File name(s) no compliant for 'replace file name' feature :\n" ) if importNoCompliantFound == []: print("-> No result") else: for i in importNoCompliantFound: print( "-> {} : no compliant ( file name excluded automatically )" .format(i)) print("\n[+] Directory that have same name of python file(s) :\n") if badNameDir == []: print("-> No result") else: for i in badNameDir: print( "-> {} : no compliant ( file name excluded automatically )" .format(i)) i = i.rstrip() print("") # -- Replace all file names to random strings with length and obfuscation level defined -- # with Bar("Obfuscation ", fill="=", max=100, suffix="%(percent)d%%") as bar: for fileInCode in recursFilesWithInit: # -- Rename all files in python code -- # with fileinput.input(fileInCode, inplace=True) as inputFile: for eachLine in inputFile: if re.match(Reg.detectPythonImport, eachLine): eachLine = Replace.EachLine( self, line=eachLine, dictionary=filesNameDictNoExt.items(), fileNameImport=True, listModuleImport=False) sys.stdout.write(eachLine) continue else: sys.stdout.write(eachLine) bar.next(50) for file in recursFiles: parseFilePath = file.split( self.utils.Platform(getOS=False, getPathType=True)) # -- Rename all files in their directories -- # for key, value in filesNameDict.items(): if key == parseFilePath[-1]: parseFilePath.remove(parseFilePath[-1]) parseFilePathToMove = self.utils.Platform( getOS=False, getPathType=True).join(parseFilePath) os.chdir(parseFilePathToMove ) # Move in directory to rename python file os.rename(key, value) else: continue os.chdir(currentPosition) bar.next(50) bar.finish() checkRecursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile="__init__", dirOnly=False) for file in checkRecursFiles: checkCountRecursFiles += 1 # -- Check if all files name are been replaced to random strings -- # with Bar("Check ", fill="=", max=checkCountRecursFiles, suffix="%(percent)d%%") as bar: for file in checkRecursFiles: numberLine = 0 # -- Check for file name in directory -- # for key, value in filesNameDict.items(): if key in file: checkFilesFoundCompare[key] = value bar.next(1) bar.finish() if checkFilesFoundCompare != {}: if verboseArg: if checkFilesFoundCompare != {}: print( "\n[!] File name that have not been replaced by their random string value... :\n" ) for key, value in checkFilesFoundCompare.items(): print("\n-> File : {}".format(key)) print("-> Value mixed : {}".format(value)) else: print("\n" + Colors.ERROR + "[-] Launch intensio-obfuscatior with verbose mode [-v, --verbose] because " + \ "file name(s) have not been replaced by their random string value" + Colors.DISABLE) return 0 else: return 1
class Padding: def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() def ScriptsGenerator(self, codeArg, mixerLevelArg): if mixerLevelArg == "lower": varRandom1 = self.mixer.GetStringMixer("lower") varRandom2 = self.mixer.GetStringMixer("lower") varRandom3 = self.mixer.GetStringMixer("lower") varRandom4 = self.mixer.GetStringMixer("lower") varRandom5 = self.mixer.GetStringMixer("lower") varRandom6 = self.mixer.GetStringMixer("lower") varRandom7 = self.mixer.GetStringMixer("lower") varRandom8 = self.mixer.GetStringMixer("lower") varRandom9 = self.mixer.GetStringMixer("lower") varRandom10 = self.mixer.GetStringMixer("lower") varRandom11 = self.mixer.GetStringMixer("lower") varRandom12 = self.mixer.GetStringMixer("lower") elif mixerLevelArg == "medium": varRandom1 = self.mixer.GetStringMixer("medium") varRandom2 = self.mixer.GetStringMixer("medium") varRandom3 = self.mixer.GetStringMixer("medium") varRandom4 = self.mixer.GetStringMixer("medium") varRandom5 = self.mixer.GetStringMixer("medium") varRandom6 = self.mixer.GetStringMixer("medium") varRandom7 = self.mixer.GetStringMixer("medium") varRandom8 = self.mixer.GetStringMixer("medium") varRandom9 = self.mixer.GetStringMixer("medium") varRandom10 = self.mixer.GetStringMixer("medium") varRandom11 = self.mixer.GetStringMixer("medium") varRandom12 = self.mixer.GetStringMixer("medium") elif mixerLevelArg == "high": varRandom1 = self.mixer.GetStringMixer("high") varRandom2 = self.mixer.GetStringMixer("high") varRandom3 = self.mixer.GetStringMixer("high") varRandom4 = self.mixer.GetStringMixer("high") varRandom5 = self.mixer.GetStringMixer("high") varRandom6 = self.mixer.GetStringMixer("high") varRandom7 = self.mixer.GetStringMixer("high") varRandom8 = self.mixer.GetStringMixer("high") varRandom9 = self.mixer.GetStringMixer("high") varRandom10 = self.mixer.GetStringMixer("high") varRandom11 = self.mixer.GetStringMixer("high") varRandom12 = self.mixer.GetStringMixer("high") # ---------- Python random scripts ---------- # if codeArg == "python": rand = random.randint(1, 5) # -- script 1 -- # if rand == 1: scriptAssPadding1 = textwrap.dedent(""" {0} = '{5}' {1} = '{6}' {2} = '{7}' {3} = '{8}' {4} = '{9}' if {0} in {1}: {0} = {4} if {1} in {2}: {1} = {3} elif {1} in {0}: {2} = {1} if {2} in {1}: {1} = {4} """).format(varRandom1, varRandom2, varRandom3, varRandom4, varRandom5, \ varRandom6, varRandom7, varRandom8, varRandom9, varRandom10) return scriptAssPadding1 # -- script 2 -- # elif rand == 2: scriptAssPadding2 = textwrap.dedent(""" {0} = '{4}' {1} = '{5}' if {0} != {1}: {2} = '{6}' {3} = '{7}' {3} = {2} """).format(varRandom1, varRandom2, varRandom3, varRandom4, varRandom5, \ varRandom6, varRandom7, varRandom8) return scriptAssPadding2 # -- script 3 -- # elif rand == 3: scriptAssPadding3 = textwrap.dedent(""" {0} = '{6}' {1} = '{7}' {2} = '{8}' {3} = '{9}' {4} = '{10}' {5} = '{11}' if {0} != {3}: {1} = {2} for {5} in {3}: if {5} != {2}: {1} = {1} else: {4} = {0} else: {2} = {0} {0} = {4} if {2} == {0}: for {5} in {0}: if {5} == {2}: {2} = {0} else: {2} = {4} """).format(varRandom1, varRandom2, varRandom3, varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8, varRandom9, varRandom10, varRandom11, varRandom12) return scriptAssPadding3 # -- script 4 -- # elif rand == 4: scriptAssPadding4 = textwrap.dedent(""" {0} = '{4}' {1} = '{5}' {3} = '{7}' if {0} == {1}: {2} = '{6}' {2} = {0} else: {2} = '{6}' {2} = {3} """).format(varRandom1, varRandom2, varRandom3, varRandom4, \ varRandom5, varRandom6, varRandom7, varRandom8) return scriptAssPadding4 # -- script 5 -- # elif rand == 5: scriptAssPadding5 = textwrap.dedent(""" {0} = '{6}' {1} = '{7}' {2} = '{8}' {3} = '{9}' {4} = '{10}' {5} = '{11}' if {2} == {3}: for {5} in {4}: if {5} == {3}: {4} = {0} else: {3} = {1} """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8, varRandom9, \ varRandom10, varRandom11, varRandom12) return scriptAssPadding5 def AddScripts(self, codeArg, outputArg, mixerLevelArg): countScriptsAdded = 0 countLineAdded = 0 countLine = 0 checkLine = 0 checkPassing = 0 countRecursFiles = 0 if codeArg == "python": inputExt = "py" blockDirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), inputExt), recursive=True) ] # -- Count the number of lines that will be checked before filling -- # for output in recursFiles: if re.match(blockDirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if not eachLine: continue countLine += 1 for number in recursFiles: countRecursFiles += 1 print("\n[+] Running adding of random scripts in {0} file(s)...\n". format(countRecursFiles)) # -- Padding scripts added -- # with tqdm(total=countRecursFiles) as pbar: for output in recursFiles: pbar.update(1) if re.match(blockDirs, output): continue else: with fileinput.input(output, inplace=True) as inputFile: for eachLine in inputFile: print(eachLine) if eachLine == "\n": continue else: if codeArg == "python": spaces = len(eachLine) - len( eachLine.lstrip()) # Check line indent noAddScript = r"(^[\#]+.*)|(\@|\s+\@)|(\s+return)|(\s+#\s{1,10}\w+)" addIndentScript = r".*\:{1}\s" checkAddIndentScript = r".*\:{1}\s\w+" # -- Check if ',' char or '\' char,in end line -- # listCheckEndLine = [] for i in eachLine: listCheckEndLine.append(i) if "," in listCheckEndLine[ -2] or "\\" in listCheckEndLine[-2]: continue # -- Check code between """ or ''' -- # if '\"\"\"' in eachLine or "\'\'\'" in eachLine: checkPassing += 1 if checkPassing == 1: # Loop until the next """ or ''' continue else: checkPassing = 0 if re.match(noAddScript, eachLine) is not None: continue elif re.match(addIndentScript, eachLine) is not None: if re.match(checkAddIndentScript, eachLine) is not None: continue else: if spaces == 0: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 elif spaces == 4: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 elif spaces == 8: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 elif spaces == 12: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 else: continue else: if spaces == 0: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), "")) countScriptsAdded += 1 elif spaces == 4: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 elif spaces == 8: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 elif spaces == 12: print( textwrap.indent( Padding.ScriptsGenerator( self, codeArg, mixerLevelArg), " ")) countScriptsAdded += 1 else: continue # -- Check padding has added in output script -- # for output in recursFiles: if re.match(blockDirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if not eachLine: continue checkLine += 1 countLineAdded = checkLine - countLine if (self.remove.LineBreaks(codeArg, outputArg) == 0): if checkLine > countLine: print("\n-> {0} scripts added in {1} file(s)\n".format( countScriptsAdded, countRecursFiles)) print("-> {0} lines added in {1} file(s)\n".format( countLineAdded, countRecursFiles)) return EXIT_SUCCESS else: return EXIT_FAILURE else: EXIT_FAILURE
class Replace: def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() self.pythonExcludeWords = "exclude/python/exclude_python_words.txt" self.pythonIncludeWords = "include/python/include_python_words.txt" def EachLine(self, codeArg, eachLine, Dict, forFilesName): getIndexLineList = [] returnLine = [] charValue = [] checkCharAfterWord = 1 wordSetter = 0 checkGetKey = "" checkGetWord = "" getLine = "" breakLine = "" if codeArg == "python": regReplace = r"\.|\:|\)|\(|\=|\[|\]|\{|\}|\,|\+|\s|\*|\-" # -- Get list of all letters in line -- # for indexLine, letterLine in enumerate(eachLine): getIndexLineList.append(letterLine) # -- Loop in each letter of line -- # for indexLine, letterLine in enumerate(eachLine): # -- Add in final line list all chars mixed -- # if charValue != []: for obfIndex, obfValue in enumerate(charValue): if obfIndex == 0: # First letter in string mixed are already add in the final line continue returnLine.append(obfValue) charValue = [] # -- If the variable is only a letter, check if the next character is specific so as not to replace it -- # if re.match(regReplace, letterLine): returnLine.append(letterLine) # -- Count indexes of word to move after it --# countDeleteIndex = 0 for i in getWord: countDeleteIndex += 1 wordSetter = countDeleteIndex - 2 # -2 Is to letter already append and the letter in progress else: # -- The index numbers of variable is decremented to add the mixed letters that be replaced -- # if wordSetter > 0: wordSetter -= 1 continue else: try: # -- Loop in the dictionary with already mixed values-- # for key, value in Dict: for indexKey, letterKey in enumerate(key): for letterValue in value: # -- Check if letter of word is equal to letter of key -- # if letterKey == letterLine: # -- Begin process to check -- #s if indexKey == 0: indexExplore = indexLine + len(key) # Place index position after the word # -- If indexError return to next loop -- # try: getIndexLineList[indexExplore] except IndexError: continue # -- Check the char after and before the word -- # if re.match(regReplace, getIndexLineList[indexExplore]): indexExploreBefore = indexLine - 1 # Index check if word finded is not into the other word indexExploreAfter = indexLine + 2 # Index check char after the the char finded with regReplace regex if codeArg == "python": try: if not re.match(r"\w|\\", getIndexLineList[indexExploreBefore]): # -- Check if it's 'from' and 'import' word key in line to avoid replace name of file if variable is identic name to file -- # getLine = "".join(getIndexLineList) if forFilesName == False: if "import" in getLine: if "from" in getLine: # -- Cut the line from the current index and check if it is not there is the keyword "import" in the line -- # breakLine = getIndexLineList[:indexLine] breakLine = "".join(breakLine) if not "import" in breakLine: # -- It's file because only 'from'key word -- # checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 0 # -- Check if after char find by 'regReplace' variable there no is ' or " -- # elif re.match(r"\"|\'", getIndexLineList[indexExploreAfter]): checkCharAfterWord = 1 else: checkCharAfterWord = 0 # -- Only for -rfn, --replacefilesname feature -- # else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 except IndexError: checkCharAfterWord = 0 pass else: checkCharAfterWord = 1 if checkCharAfterWord == 0: # -- Initialize vars -- # getCharAllInKey = [] getWord = [] indexExploreStart = indexLine indexExploreEnd = indexLine + len(key) - 1 # Remove -1, first letter is already increment # -- List contain all letters of key -- # for getLetterKey in key: getCharAllInKey.append(getLetterKey) # -- Check if all letters of key is equal to all letters of word -- # for indexCheckLetter, checkLetter in enumerate(getIndexLineList): if indexCheckLetter >= indexExploreStart and indexCheckLetter <= indexExploreEnd: getWord.append(checkLetter) # -- Check if number of chars in key equal number of chars in word -- # if list(set(getCharAllInKey) - set(getWord)) == []: checkGetWord = "".join(getWord) checkGetKey = "".join(getCharAllInKey) # -- Check if key == word -- # if checkGetWord == checkGetKey: for obfChar in value: charValue.append(obfChar) letterLine = letterValue raise BreakLoop else: continue else: continue else: continue else: continue else: continue raise BreakLoop except BreakLoop: returnLine.append(letterLine) # -- Rewrite the line -- # returnLine = "".join(returnLine) return returnLine[:] def StringsToStrings(self, codeArg, outputArg, mixerLevelArg, verboseArg): variablesDict = {} classesDict = {} functionsDict = {} includeDict = {} allDict = {} checkWordsMixed = [] wordsExcluded = [] wordsExcludedFound = [] wordsIncludedFound = [] wordsIncludedNotFound = [] checkCountWordsMixed = 0 checkCountWordsValue = 0 checkQuotePassing = 0 numberReplaced = 0 countRecursFiles = 0 if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" blockFile = "__init__" functionsDefined = r"def\s(\w+)" # Functions classDefined = r"class\s(\w+)" # Classes variablesErrorDefined = r"except(\s+\w+\sas\s)(\w)" # Error variables variablesLoopDefined = r"for\s+([\w\s\,]+)(\s+in\s+)" # Loop variables variablesDefined = r"(^\w+|\w+)([\s|^\s]*=[\s|\w|\"|\'])" # Variables quoteOfCommentariesMultipleLines = r"^\s*[\"|\']{3}$" # """ and ''' without before variables and if commentaries is over multiple lines quoteInRegex = r"\={1}\s*r[\"|\']{1}" # If quote in regex quoteOfEndCommentariesMultipleLines = r"^\s*[\"|\']{3}\)?\.?" # """ and ''' without before variables, if commentaries is over multiple lines and he finish by .format() funtion quoteIntoVariable = r".*\={1}\s*\w*\.?\w*[\(|\.]{1}[\"|\']{3}|.*\={1}\s*[\"|\']{3}" # """ and ''' with before variables recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, self.utils.Platform(), detectFiles), recursive=True)] # -- Replace variables/classes/functions to random strings with length defined -- # for file in recursFiles: if blockDir in file: continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: # -- Variables -- # search = re.search(variablesDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in variablesDict: variablesDict[search.group(1)] = mixer # -- Error variables -- # search = re.search(variablesErrorDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(2) not in variablesDict: variablesDict[search.group(2)] = mixer # -- Loop variables -- # search = re.search(variablesLoopDefined, eachLine) if search != None: if "," in search.group(1): modifySearch = search.group(1).replace(",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer(mixerLevelArg) variablesDict[search.group(1)] = mixer # -- Functions -- # search = re.search(functionsDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in functionsDict: if codeArg == "python": if not blockFile in search.group(1): functionsDict[search.group(1)] = mixer # -- Classes -- # search = re.search(classDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in classesDict: classesDict[search.group(1)] = mixer # -- Remove excluded variables/classes/functions defined from 'exclude/python/exclude_python_words.txt' in dict -- # if os.path.exists(self.pythonExcludeWords) == True: with open(self.pythonExcludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcluded.append(word) else: print(ERROR_COLOUR + "[-] '{0}' file not found\n".format(self.pythonExcludeWords)) for word in wordsExcluded: if word in variablesDict.keys(): wordsExcludedFound.append(word) del variablesDict[word] if word in classesDict.keys(): wordsExcludedFound.append(word) del classesDict[word] if word in functionsDict.keys(): wordsExcludedFound.append(word) del functionsDict[word] # -- Include variables/classes/functions defined from 'include/python/include_python_words.txt' in dict -- # if os.path.exists(self.pythonIncludeWords) == True: with open(self.pythonIncludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsIncludedFound.append(word) else: print(ERROR_COLOUR + "[-] '{0}' file not found\n".format(self.pythonIncludeWords)) for word in wordsIncludedFound: if word not in variablesDict.keys() and word not in classesDict.keys() and word not in functionsDict.keys(): mixer = self.mixer.GetStringMixer(mixerLevelArg) includeDict[word] = mixer wordsIncludedNotFound.append(word) for file in recursFiles: if blockDir in file: continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for word in wordsIncludedNotFound: if word in eachLine: wordsIncludedNotFound.remove(word) for word in wordsIncludedNotFound: if word in includeDict.keys(): del includeDict[word] # -- Display variables/classes/functions found -- # if verboseArg: print("\n[+] Variables found :\n") if variablesDict == {}: print("-> No result") else: for key, value in variablesDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Classes found :\n") if classesDict == {}: print("-> No result") else: for key, value in classesDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Functions found :\n") if functionsDict == {}: print("-> No result") else: for key, value in functionsDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Include found :\n") if includeDict == {}: print("-> No result") else: for key, value in includeDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Exclude found :\n") if wordsExcludedFound == []: print("-> No result") else: for word in wordsExcludedFound: print("-> {0} : excluded".format(word)) # -- Merge all dicts -- # allDict = self.utils.DictMerge(allDict, variablesDict) allDict = self.utils.DictMerge(allDict, classesDict) allDict = self.utils.DictMerge(allDict, functionsDict) allDict = self.utils.DictMerge(allDict, includeDict) for number in recursFiles: countRecursFiles += 1 # -- Change variables/classes/functions to mixed values -- # print("\n[+] Running replacement of variables/classes/functions in {0} file(s)...\n".format(countRecursFiles)) with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: pbar.update(1) if blockDir in file: continue else: with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if not eachLine: continue else: if codeArg == "python": # -- Check code into """ or ''' -- # if re.match(quoteIntoVariable, eachLine): checkQuotePassing += 1 eachLine = Replace.EachLine(self, codeArg, eachLine, allDict.items(), False) print(eachLine) continue elif re.match(quoteOfCommentariesMultipleLines, eachLine) or re.match(quoteOfEndCommentariesMultipleLines, eachLine): checkQuotePassing += 1 eachLine = Replace.EachLine(self, codeArg, eachLine, allDict.items(), False) print(eachLine) if checkQuotePassing == 2: checkQuotePassing = 0 continue if checkQuotePassing == 1: print(eachLine) continue elif checkQuotePassing == 2: checkQuotePassing = 0 continue else: eachLine = Replace.EachLine(self, codeArg, eachLine, allDict.items(), False) print(eachLine) continue # -- Check if variables/classes/functions have been mixed -- # for file in recursFiles: if blockDir in file: continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for value in allDict.values(): if value in eachLine: checkWordsMixed.append(value) # -- Remove duplicated key -- # checkListWordsMixed = list(dict.fromkeys(checkWordsMixed)) for i in checkListWordsMixed: checkCountWordsMixed += 1 for i in allDict.values(): checkCountWordsValue += 1 if (self.remove.Backslashes(codeArg, outputArg) == 0): if checkCountWordsMixed == checkCountWordsValue: print("\n-> {0} variables/classes/functions replaced in {1} file(s)\n".format(checkCountWordsValue, countRecursFiles)) return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE def StringsToHex(self, codeArg, outputArg, mixerLevelArg): getLetterLineList = [] countRecursFiles = 0 checkPrint = 0 checkHexError = False checkPrintError = False hexLine = "" utils = Utils() mixer = Mixer() remove = Remove() if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" detectExecFunc = r"exec\(\w+\)" detectQuotes = r"[\'|\"]{3}" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, utils.Platform(), detectFiles), recursive=True)] for number in recursFiles: countRecursFiles += 1 print("\n[+] Running replace all strings to their hexadecimal value in {0} file(s)...\n".format(countRecursFiles)) # -- Replace all strings to their hexadecimal value -- # with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: checkPrint = 0 # initialize check print() func at the begining of each file pbar.update(1) if blockDir in file: continue else: # -- Add a new first random line and move the old first line to the second line to avoid replacing it -- # with open(file, "r") as inputFile: stringRandomMixer = mixer.GetStringMixer(mixerLevelArg) firstLine = "{0}\n".format(stringRandomMixer) line = inputFile.readlines() line.insert(0, firstLine) with open(file, "w") as inputFile: inputFile.writelines(line) # -- Replace all lines-- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if checkPrint == 0: varMixer = mixer.GetStringMixer(mixerLevelArg) print(varMixer + "=\"\"\"") checkPrint = 1 else: getLetterLineList = [] # initialize list for letterLine in eachLine: letterToHex = "\\x" + str(letterLine.encode().hex()) getLetterLineList.append(letterToHex) # Get list of all letters in line hexLine = "".join(getLetterLineList) print(hexLine) # -- Add exec funtions to interpret hex code in strings -- # with open(file, "a") as inputFile: inputFile.write("\"\"\"") inputFile.write("\nexec({0})".format(varMixer)) # -- Check if all lines are replaced of hexadecimal value -- # for file in recursFiles: if blockDir in file: continue else: with open(file, "r") as inputFile: for eachLine in inputFile: if not eachLine: continue else: if not "\\x" in eachLine: if re.match(detectQuotes, eachLine): continue elif re.match(detectExecFunc, eachLine): continue else: checkError = True else: continue if (remove.Backslashes(codeArg, outputArg) == 0): if checkHexError == False: return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE def FilesName(self, codeArg, outputArg, mixerLevelArg, verboseArg): filesNameDict = {} filesNameDictNoExt = {} filesNameFound = [] filesNameFoundNoExt = [] filesNameMixed = [] checkFilesFound = [] countRecursFiles = 0 checkRenameInDir = 0 checkRenameInCode = 0 unix = False win = False currentPosition = os.getcwd() utils = Utils() mixer = Mixer() remove = Remove() if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" blockFile = "__init__" detectImport = r"\s*from\s+|\s*import\s+" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, utils.Platform(), detectFiles), recursive=True)] for number in recursFiles: countRecursFiles += 1 for file in recursFiles: if blockDir in file or blockFile in file: continue else: if "\"" in file: parseFilePath = file.split("\"") win = True else: parseFilePath = file.split("/") unix = True checkFilesFound.append(file) mixer = self.mixer.GetStringMixer(mixerLevelArg) filesNameDict[parseFilePath[-1]] = mixer + ".py" filesNameDictNoExt[parseFilePath[-1].replace(".py", "")] = mixer filesNameFound.append(parseFilePath[-1]) filesNameMixed.append(mixer + ".py") removeExt = parseFilePath[-1].replace(".py","") filesNameFoundNoExt.append(removeExt) # -- Diplay all files found with their mixed values if verbose arg is actived -- # if verboseArg: print("\n[+] Files name found with their mixed values :\n") for key, value in filesNameDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Running replace files name in {0} file(s)...\n".format(countRecursFiles)) # -- Replace all files name to random strings with length defined -- # with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: pbar.update(1) if blockDir in file: continue else: # -- Rename all files in python code -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: try: for fileName in filesNameFound: for fileNameNoExt in filesNameFoundNoExt: if fileName in eachLine or fileNameNoExt in eachLine: if not ".py" in eachLine: if re.match(detectImport, eachLine): eachLine = Replace.EachLine(self, codeArg, eachLine, filesNameDictNoExt.items(), True) print(eachLine) raise BreakLoop else: continue else: eachLine = Replace.EachLine(self, codeArg, eachLine, filesNameDict.items(), True) print(eachLine) raise BreakLoop else: continue print(eachLine) except BreakLoop: continue # -- Rename all files in their directories -- # if "\"" in file: parseFilePath = file.split("\"") win = True else: parseFilePath = file.split("/") unix = True for key, value in filesNameDict.items(): if key == parseFilePath[-1]: parseFilePath.remove(parseFilePath[-1]) if unix == True: parseFilePathToMove = "/".join(parseFilePath) else: parseFilePathToMove = "\"".join(parseFilePath) os.chdir(parseFilePathToMove) # Move in directory to rename python file os.rename(key, value) else: continue os.chdir(currentPosition) # Return to old position # -- Check if all files name are been replaced to random strings with length defined -- # for i in checkFilesFound: i.replace(".py", "") # -- Check for file(s) name -- # for file in recursFiles: if blockDir in file or blockFile in file: continue else: for i in checkFilesFound: if i in file: checkFilesFound.remove(i) continue # -- Check for code if file(s) name -- # if checkFilesFound != []: for file in recursFiles: if blockDir in file or blockFile in file: continue else: with open(file, "r") as inputFile: for line in inputFile: for i in checkFilesFound: if i in line: checkFilesFound.remove(i) continue if checkFilesFound == []: if (remove.Backslashes(codeArg, outputArg) == 0): return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
def main(): if sys.version_info[0] != 3: print(Colors.ERROR + "[-] Intensio-Obfuscator only support Python 3.x" + Colors.DISABLE) sys.exit(0) if sys.platform != "win32" and sys.platform != "linux": print(Colors.ERROR + "[-] This tool support [windows - Linux] only !" + Colors.DISABLE) sys.exit(0) args = Args() utils = Utils() if len(sys.argv) > 1 and len(sys.argv) <= 15: pass else: print(Colors.ERROR + "[-] Incorrect number of arguments" + Colors.DISABLE + "\n") args.GetArgHelp() sys.exit(0) if args.GetArgsValue().input: if args.GetArgsValue().output: if re.match(Reg.detectMlenArg, str(args.GetArgsValue().mixerlength)): if re.match(Reg.detectIndentArg, str(args.GetArgsValue().indent)): pass else: print("\n" + Colors.ERROR + "[-] -ind, --indent argument [2|4|8] missing" + Colors.DISABLE + "\n") sys.exit(0) else: print( "\n" + Colors.ERROR + "[-] -mlen, --mixerlength argument [lower|medium|high] missing" + Colors.DISABLE + "\n") sys.exit(0) else: print("\n" + Colors.ERROR + "[-] Output [-o, --output] argument missing" + Colors.DISABLE + "\n") sys.exit(0) else: print("\n" + Colors.ERROR + "[-] Input [-i, --input] argument missing" + Colors.DISABLE + "\n") sys.exit(0) for line in INTENSIO_BANNER.split("\n"): time.sleep(0.05) print(line) print("\n\n" + Colors.SECTION + "********************************* [ START ] **********************************" \ + Colors.DISABLE + "\n") # -- Analysis and set up of the work environment -- # print("\n\n" + Colors.SECTION + "********************* [ Analyze and setup environment ] **********************" \ + Colors.DISABLE + "\n") analyzeData = Analyze() analyseDataInEnv = analyzeData.InputAvailable( inputArg=args.GetArgsValue().input, verboseArg=args.GetArgsValue().verbose) if analyseDataInEnv == 1: print("\n[+] Analyze input argument '{}' -> ".format(args.GetArgsValue().input) + Colors.SUCCESS + \ "Successful" + Colors.DISABLE) else: print("[-] Analyze input '{}' -> ".format(args.GetArgsValue().input) + Colors.ERROR + "failed" + Colors.DISABLE + "\n") sys.exit(0) analyseDataOutEnv = analyzeData.OutputAvailable( inputArg=args.GetArgsValue().input, outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if analyseDataOutEnv == 1: print("\n[+] Analyze and setup output argument environment '{}' -> " \ .format(args.GetArgsValue().output) + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print( "[-] Analyze output '{}' -> ".format(args.GetArgsValue().output) + Colors.ERROR + "failed" + Colors.DISABLE + "\n") sys.exit(0) # -- Obfuscation process -- # startObfuscationTime = time.time() print("\n\n" + Colors.SECTION + "********************** [ Obfuscation delete comments ] ***********************" \ + Colors.DISABLE + "\n") deleteData = Delete() deleteCommentsData = deleteData.Comments( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if deleteCommentsData == 1: print("[+] Obfuscation delete comments -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation delete comments -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") print("\n\n" + Colors.SECTION + "******************** [ Obfuscation delete line space(s) ] ********************" \ + Colors.DISABLE + "\n") if deleteData: pass else: deleteData = Delete() deleteLinesSpacesData = deleteData.LinesSpaces( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if deleteLinesSpacesData == 1: print("[+] Obfuscation delete lines spaces -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation delete lines spaces -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- If empty class (avert to generate an error) -- # print("\n\n" + Colors.SECTION + "******************* [ Correction padding empty class(es) ] *******************" \ + Colors.DISABLE + "\n") paddingData = Padding() paddingDataEmptyClass = paddingData.EmptyClasses( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, basicIndentArg=args.GetArgsValue().indent, verboseArg=args.GetArgsValue().verbose) if paddingDataEmptyClass == 1: pass else: print("\n[-] Padding empty class -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- If empty functions (avert to generate an error) -- # print("\n\n" + Colors.SECTION + "****************** [ Correction padding empty function(s) ] ******************" \ + Colors.DISABLE + "\n") if paddingData: pass else: paddingData = Padding() paddingDataEmptyFunc = paddingData.EmptyFunctions( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, basicIndentArg=args.GetArgsValue().indent, verboseArg=args.GetArgsValue().verbose) if paddingDataEmptyFunc == 1: pass else: print("\n[-] Padding empty function -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") print("\n\n" + Colors.SECTION + "************ [ Obfuscation replace string(s) to string(s) mixed ] ************" \ + Colors.DISABLE + "\n") if args.GetArgsValue().replacetostr: replaceData = Replace() replaceDataStrStr = replaceData.StringToString( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if replaceDataStrStr == 1: print("[+] Obfuscation replace string to string mixed -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation replace string to string mixed -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace string to string ] mixed no asked !") print("\n\n" + Colors.SECTION + "****************** [ Obfuscation adding padding script(s) ] ******************" \ + Colors.DISABLE + "\n") if args.GetArgsValue().paddingscript: if paddingData: pass else: paddingData = Padding() paddingDataGarbage = paddingData.AddRandomScripts( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, basicIndentArg=args.GetArgsValue().indent, verboseArg=args.GetArgsValue().verbose) if paddingDataGarbage == 1: print("[+] Obfuscation padding script -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation padding script -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ padding script ] no asked !") print("\n\n" + Colors.SECTION + "******************** [ Obfuscation replace file(s) name ] ********************" \ + Colors.DISABLE + "\n") if args.GetArgsValue().replacefilename: if args.GetArgsValue().replacetostr: pass else: replaceData = Replace() replaceDataStrFname = replaceData.FilesName( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if replaceDataStrFname == 1: print("\n[+] Obfuscation replace file name -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print("\n[-] Obfuscation replace file name -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace file name ] feature no asked !") print("\n\n" + Colors.SECTION + "****************** [ Obfuscation replace string(s) to hex ] ******************" \ + Colors.DISABLE + "\n") if args.GetArgsValue().replacetohex: if args.GetArgsValue().replacetostr or args.GetArgsValue( ).replacefilename: pass else: replaceData = Replace() replaceDataStrHex = replaceData.StringsToHex( outputArg=args.GetArgsValue().output, mixerLengthArg=args.GetArgsValue().mixerlength, verboseArg=args.GetArgsValue().verbose) if replaceDataStrHex == 1: print("\n[+] Obfuscation replace string to hex -> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) print("\n[!] care, only works for python 2 files") else: print("\n[-] Obfuscation replace string to hex -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) else: print("[!] Obfuscation [ replace string to hex ] feature no asked !") # -- Delete line spaces of padding scripts -- # if args.GetArgsValue().paddingscript: print("\n\n" + Colors.SECTION + "******************** [ Obfuscation delete line space(s) ] ********************" \ + Colors.DISABLE + "\n") if deleteData: pass else: deleteData = Delete() deleteLinesSpacesData = deleteData.LinesSpaces( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose) if deleteLinesSpacesData == 1: print("[+] Obfuscation delete lines spaces of padding scripts-> " + Colors.SUCCESS + "Successful" + Colors.DISABLE) else: print( "\n[-] Obfuscation delete lines spaces of padding scripts -> " + Colors.ERROR + "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print("\n[!] Retry with [-v, --verbose] parameter") # -- Delete if python pyc file in output directory -- # print("\n\n" + Colors.SECTION + "********************* [ Correction delete .pyc file(s) ] *********************" \ + Colors.DISABLE + "\n") if deleteData: pass else: deleteData = Delete() deletePycData = deleteData.TrashFiles( outputArg=args.GetArgsValue().output, verboseArg=args.GetArgsValue().verbose, ) if deletePycData == 1: pass else: print("\n[-] Delete .pyc file from {} directory -> ".format(args.GetArgsValue().output) + Colors.ERROR + \ "Failed" + Colors.DISABLE) if not args.GetArgsValue().verbose: print( "\n[!] Retry with [-v, --verbose] parameter for more informations" ) print("\n\n" + Colors.SECTION + "********************************** [ END ] ************************************" \ + Colors.DISABLE + "\n") # -- Result of execution time -- # endObfuscationTime = time.time() executionTime = endObfuscationTime - startObfuscationTime executionTime = str(executionTime) executionTime = executionTime.split(".") print("[*] Obfuscation Time : {} second(s)".format(executionTime[0]))
class Remove: def __init__(self): self.utils = Utils() def LineBreaks(self, codeArg, outputArg): checkLine = 0 numberFiles = 0 numberFileGood = 0 if codeArg == "python": detectFile = "py" blockDirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFile), recursive=True) ] # -- Delete line breaks -- # for output in recursFiles: if re.match(blockDirs, output): continue else: with fileinput.FileInput(output, inplace=True) as inputFile: for line in inputFile: if line.strip(): print(line.rstrip()) # -- Check if all line breaks are deleted -- # for output in recursFiles: checkLine = 0 # Initialize check vars for the next file if re.match(blockDirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if eachLine == "\n": checkLine += 1 if checkLine == 0: numberFileGood += 1 numberFiles += 1 else: numberFileGood += 0 numberFiles += 1 if numberFileGood == numberFiles: return EXIT_SUCCESS else: return EXIT_FAILURE def Commentaries(self, codeArg, outputArg): countLineOutput = 0 countLineInput = 0 noCommentary = 0 isCommentary = 0 countRecursFiles = 0 if codeArg == "python": classicCommentariesAfterLine = r"\s+\#.*" # '#' after line of code classicCommentariesBeginLine = r"^\#.*" # begin '#' quoteOfCommentariesMultipleLine = r"^[\"|\']{3}$" # """ and ''' without before variables and if commentaries is over multiple lines quoteOfCommentariesOneLine = r"[\"|\']{3}.*[\"|\']{3}" # """ and ''' without before variables and if commentary is over one line, (""" commentaries """) noQuoteOfCommentaries = r"\w+\s*[\=|\(]{1}\s*[\"|\']{3}" # """ and ''' with before variables detectFile = "py" blockDirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFile), recursive=True) ] # -- Count commentaries will be removed -- # for output in recursFiles: if re.match(blockDirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if codeArg == "python": searchClassicCommentariesAfterLine = re.search( classicCommentariesAfterLine, eachLine) searchClassicCommentariesBeginLine = re.search( classicCommentariesBeginLine, eachLine) if "coding" in eachLine or "#!" in eachLine: continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineInput += 1 continue elif isCommentary == 1 and noCommentary == 0: countLineInput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineInput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if searchClassicCommentariesBeginLine is not None: countLineInput += 1 elif searchClassicCommentariesAfterLine is not None: countLineInput += 1 else: pass # -- Initialize vars -- # isCommentary = 0 noCommentary = 0 # -- Remove commentaries -- # for number in recursFiles: countRecursFiles += 1 print("\n[+] Running remove commentaries in {0} file(s)...\n".format( countRecursFiles)) with tqdm(total=countRecursFiles) as pbar: for output in recursFiles: pbar.update(1) if re.match(blockDirs, output): continue else: # -- Remove commentaries -- # with fileinput.input(output, inplace=True) as inputFile: for eachLine in inputFile: searchClassicCommentariesAfterLine = re.search( classicCommentariesAfterLine, eachLine) searchClassicCommentariesBeginLine = re.search( classicCommentariesBeginLine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: print(eachLine) continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 continue elif isCommentary == 1 and noCommentary == 0: continue elif isCommentary == 0 and noCommentary == 1: print(eachLine) continue elif isCommentary == 2: isCommentary = 0 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 print(eachLine) continue else: pass if searchClassicCommentariesBeginLine is not None: eachLine = eachLine.replace( searchClassicCommentariesBeginLine.group( 0), "") print(eachLine) elif searchClassicCommentariesAfterLine is not None: eachLine = eachLine.replace( searchClassicCommentariesAfterLine.group( 0), "") print(eachLine) else: print(eachLine) # -- Initialize vars -- # isCommentary = 0 noCommentary = 0 # -- Check if all commentaries are removed -- # for output in recursFiles: countLineOutput = 0 if re.match(blockDirs, output): continue else: with open(output, "r") as readFile: countLineOutput = 0 readF = readFile.readlines() for eachLine in readF: searchClassicCommentariesAfterLine = re.search( classicCommentariesAfterLine, eachLine) searchClassicCommentariesBeginLine = re.search( classicCommentariesBeginLine, eachLine) if codeArg == "python": if "coding" in eachLine or "#!" in eachLine: continue if re.match(noQuoteOfCommentaries, eachLine): noCommentary += 1 elif re.match(quoteOfCommentariesMultipleLine, eachLine): isCommentary += 1 else: pass if re.match(quoteOfCommentariesOneLine, eachLine): isCommentary = 0 countLineOutput += 1 continue elif isCommentary == 1 and noCommentary == 0: countLineOutput += 1 continue elif isCommentary == 0 and noCommentary == 1: continue elif isCommentary == 2: isCommentary = 0 countLineOutput += 1 continue elif isCommentary == 1 and noCommentary == 1: isCommentary = 0 noCommentary = 0 continue else: pass if searchClassicCommentariesBeginLine is not None: countLineOutput += 1 elif searchClassicCommentariesAfterLine is not None: countLineOutput += 1 else: pass if (Remove.LineBreaks(self, codeArg, outputArg) == 0): if countLineOutput == 0: print("\n-> {0} lines of commentaries removed\n".format( countLineInput)) return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE def PrintFunc(self, codeArg, outputArg): countPrintLine = 0 countCheckPrintLine = 0 countRecursFiles = 0 if codeArg == "python": detectPrint = r"\s{2,}print|^print" detectFile = "py" blockDirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFile), recursive=True) ] for number in recursFiles: countRecursFiles += 1 print("\n[+] Running remove print function in {0} file(s)...\n".format( countRecursFiles)) with tqdm(total=countRecursFiles) as pbar: for output in recursFiles: pbar.update(1) if re.match(blockDirs, output): continue else: # -- Remove all print functions -- # with fileinput.input(output, inplace=True) as inputFile: for eachLine in inputFile: if re.match(detectPrint, eachLine): countPrintLine += 1 continue else: print(eachLine) # -- Check if all print functions are removed -- # for output in recursFiles: if re.match(blockDirs, output): continue else: with open(output, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if re.match(detectPrint, eachLine): countCheckPrintLine += 1 if (Remove.LineBreaks(self, codeArg, outputArg) == 0): if countCheckPrintLine == 0: print("\n-> {0} lines of print functions removed\n".format( countPrintLine)) return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
def main(): if sys.version_info[0] != 3: print(ERROR_COLOUR + "[-] Intensio-Obfuscator only support Python 3.x") sys.exit(0) if sys.platform != "win32" and sys.platform != "linux": print(ERROR_COLOUR + "[-] This tool support [windows - Linux] only !") sys.exit(0) try: from core.utils.intensio_design import INTENSIO_BANNER from core.utils.intensio_utils import Utils from core.utils.intensio_usage import Args from core.utils.intensio_error import EXIT_SUCCESS, ERROR_BAD_ENVIRONMENT, ERROR_INVALID_PARAMETER, \ ERROR_BAD_ARGUMENTS, ERROR_INVALID_FUNCTION, ERROR_FILE_NOT_FOUND from core.obfuscation.intensio_replace import Replace from core.obfuscation.intensio_padding import Padding from core.obfuscation.intensio_analyze import Analyze from core.obfuscation.intensio_remove import Remove except ImportError as e: print(ERROR_COLOUR + "[-] {0}\n".format(e)) sys.exit(0) args = Args() utils = Utils() if len(sys.argv) > 1 and len(sys.argv) <= 16: pass else: print(ERROR_COLOUR + "[-] Incorrect number of arguments\n") args.GetArgHelp() sys.exit(ERROR_BAD_ARGUMENTS) if args.GetArgsValue().input: if args.GetArgsValue().output: if args.GetArgsValue().code: if args.GetArgsValue().code == "python": if args.GetArgsValue().mixerlevel: if re.match(r"^lower$|^medium$|^high$", args.GetArgsValue().mixerlevel): if not args.GetArgsValue().paddingscripts and not args.GetArgsValue().replacetostr \ and not args.GetArgsValue().removecommentaries and not args.GetArgsValue().removeprint \ and not args.GetArgsValue().replacetohex and not args.GetArgsValue().replacefilesname: print( ERROR_COLOUR + "\n[-] Need at least one argument [-rts --replacetostr] or [-ps --paddingscripts] \ or [-rc --removecommentaries] or [-rp --removeprint] or [-rth --replacetohex] or [-rfn, --replacefilesname]" ) sys.exit(ERROR_BAD_ARGUMENTS) else: print( ERROR_COLOUR + "[-] Incorrect level of mixerlevel, [lower - medium - high] only supported\n" ) sys.exit(ERROR_INVALID_PARAMETER) else: print( ERROR_COLOUR + "[-] Mixerlevel [-m --mixerlevel] argument missing\n" ) sys.exit(ERROR_BAD_ARGUMENTS) else: print( ERROR_COLOUR + "[-] '{0}' Incorrect code argument, [python] only supported\n" .format(args.GetArgsValue().Code)) sys.exit(ERROR_INVALID_PARAMETER) else: print(ERROR_COLOUR + "[-] Code [-c --code] argument missing\n") sys.exit(ERROR_BAD_ARGUMENTS) else: print(ERROR_COLOUR + "[-] Output [-o --output] argument missing\n") sys.exit(ERROR_BAD_ARGUMENTS) else: print(ERROR_COLOUR + "[-] Input [-i --input] argument missing\n") sys.exit(ERROR_BAD_ARGUMENTS) for line in INTENSIO_BANNER.split("\n"): time.sleep(0.05) print(BANNER_COLOUR + line) # -- Analysis and set up of the work environment -- # print( SECTION_COLOUR + "\n\n*********************** [ Analyze and setup environment ] ************************\n" ) analyzeData = Analyze() if (analyzeData.InputAvailable( args.GetArgsValue().input, args.GetArgsValue().code, args.GetArgsValue().verbose) == EXIT_SUCCESS): print("\n[+] Analyze input argument '{0}' -> ".format( args.GetArgsValue().input) + SUCESS_COLOUR + "Successful") else: print("[-] Analyze input '{0}' -> ".format(args.GetArgsValue().input) + FAILED_COLOUR + "failed\n") sys.exit(ERROR_INVALID_FUNCTION) if (analyzeData.OutputAvailable( args.GetArgsValue().input, args.GetArgsValue().code, args.GetArgsValue().output, args.GetArgsValue().verbose) == EXIT_SUCCESS): print("\n[+] Analyze and setup output argument environment '{0}' -> ". format(args.GetArgsValue().output) + SUCESS_COLOUR + "Successful") else: print( "[-] Analyze output '{0}' -> ".format(args.GetArgsValue().output) + FAILED_COLOUR + "failed\n") sys.exit(ERROR_INVALID_FUNCTION) # -- Obfuscation process -- # print( SECTION_COLOUR + "\n\n********************** [ Obfuscation remove commentaries ] **********************\n" ) if args.GetArgsValue().removecommentaries: removeData = Remove() if (removeData.Commentaries( args.GetArgsValue().code, args.GetArgsValue().output) == EXIT_SUCCESS): print("[+] Obfuscation remove commentaries -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation remove commentaries -> " + FAILED_COLOUR + "Failed") else: print("[!] Obfuscation remove commentaries no asked !") print( SECTION_COLOUR + "\n\n*************** [ Obfuscation replace strings to strings mixed ] ****************\n" ) if args.GetArgsValue().replacetostr: replaceData = Replace() if (replaceData.StringsToStrings( args.GetArgsValue().code, args.GetArgsValue().output, args.GetArgsValue().mixerlevel, args.GetArgsValue().verbose) == EXIT_SUCCESS): print("[+] Obfuscation replace strings to strings mixed -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation replace strings to strings mixed -> " + FAILED_COLOUR + "Failed") else: print("[!] Obfuscation replace strings to strings mixed no asked !") print( SECTION_COLOUR + "\n\n************************ [ Obfuscation padding scripts ] ************************\n" ) if args.GetArgsValue().paddingscripts: paddingData = Padding() if (paddingData.AddRandomScripts( args.GetArgsValue().code, args.GetArgsValue().output, args.GetArgsValue().mixerlevel) == EXIT_SUCCESS): print("[+] Obfuscation padding random scripts -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation padding random scripts -> " + FAILED_COLOUR + "Failed") else: print("[!] Obfuscation add random scripts no asked !") print( SECTION_COLOUR + "\n\n************************* [ Obfuscation remove print ] **************************\n" ) if args.GetArgsValue().removeprint: if (removeData.PrintFunctions( args.GetArgsValue().code, args.GetArgsValue().output) == EXIT_SUCCESS): print("[+] Obfuscation remove print functions -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation remove print functions -> " + FAILED_COLOUR + "Failed") else: print("[!] Obfuscation remove print functions no asked !") print( SECTION_COLOUR + "\n\n********************** [ Obfuscation replace files name ] ***********************\n" ) if args.GetArgsValue().replacefilesname: if args.GetArgsValue().replacetostr: pass else: replaceData = Replace() if (replaceData.FilesName( args.GetArgsValue().code, args.GetArgsValue().output, args.GetArgsValue().mixerlevel, args.GetArgsValue().verbose) == EXIT_SUCCESS): print("\n[+] Obfuscation replace files name -> " + SUCESS_COLOUR + "Successful") else: print("\n[-] Obfuscation replace files name -> " + FAILED_COLOUR + "Failed") else: print("[!] Obfuscation replace files name no asked !") print( SECTION_COLOUR + "\n\n******************** [ Obfuscation replace strings to hex ] *********************\n" ) if args.GetArgsValue().replacetohex: if args.GetArgsValue().replacetostr or args.GetArgsValue( ).replacefilesname: pass else: replaceData = Replace() if (replaceData.StringsToHex( args.GetArgsValue().code, args.GetArgsValue().output, args.GetArgsValue().mixerlevel) == EXIT_SUCCESS): print("\n[+] Obfuscation replace strings to hex -> " + SUCESS_COLOUR + "Successful\n") else: print("\n[-] Obfuscation replace strings to hex -> " + FAILED_COLOUR + "Failed\n") else: print("[!] Obfuscation replace strings to hex no asked !\n") # -- Remove if python pyc file(s) in output directory -- # if (removeData.TrashFiles(args.GetArgsValue().code, args.GetArgsValue().output) >= 0): pass else: print( SECTION_COLOUR + "\n**************************** [ Remove pyc files ] *****************************\n" ) print("\n[-] Remove .pyc files in {0} directory -> " + FAILED_COLOUR + "Failed\n".format(args.GetArgsValue().output))
class ReplaceWords: def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() self.pythonExcludeWords = "exclude/python/exclude_python_words.txt" self.pythonIncludeWords = "include/python/include_python_words.txt" def EachLine(self, codeArg, eachLine, Dict): getIndexLineList = [] returnLine = [] charValue = [] checkCharAfterWord = 1 wordSetter = 0 checkGetKey = "" checkGetWord = "" getLine = "" breakLine = "" if codeArg == "python": regReplace = r"(\.)|(:)|(\))|(\()|(=)|(\[)|(\])|({)|(})|(,)|(\+)|(\s)|(\*)|(\+)|(\-)" # -- Get list of all letters in line -- # for indexLine, letterLine in enumerate(eachLine): getIndexLineList.append(letterLine) # -- Loop in each letter of line -- # for indexLine, letterLine in enumerate(eachLine): # -- Add in final line list all chars mixed -- # if charValue != []: for obfIndex, obfValue in enumerate(charValue): if obfIndex == 0: # First letter in string mixed are already add in the final line continue returnLine.append(obfValue) charValue = [] # -- If the variable is only a letter, check if the next character is specific so as not to replace it -- # if re.match(regReplace, letterLine): returnLine.append(letterLine) # -- Count indexes of word to move after it --# countDeleteIndex = 0 for i in getWord: countDeleteIndex += 1 wordSetter = countDeleteIndex - 2 # -2 Is to letter already append and the letter in progress else: # -- The index numbers of variable is decremented to add the mixed letters that be replaced -- # if wordSetter > 0: wordSetter -= 1 continue else: try: # -- Loop in the dictionary with already mixed values-- # for key, value in Dict: for indexKey, letterKey in enumerate(key): for letterValue in value: # -- Check if letter of word is equal to letter of key -- # if letterKey == letterLine: # -- Begin process to check -- # if indexKey == 0: # -- Place index position after the word -- # indexExplore = indexLine + len(key) # -- If indexError return to next loop -- # try: getIndexLineList[indexExplore] except IndexError: continue # -- Check the char after the word -- # if re.match( regReplace, getIndexLineList[ indexExplore]): # -- Check word finded is not into the other word -- # indexExploreBefore = indexLine - 1 if not re.match( r"\w|\\", getIndexLineList[ indexExploreBefore] ): if codeArg == "python": # -- Check if it's 'from' and 'import' word key in line to avoid replace name of file if variable is identic name to file -- # getLine = "".join( getIndexLineList) if "import" in getLine: if "from" in getLine: # -- Cut the line from the current index and check if it is not there is the keyword "import" in the line -- # breakLine = getIndexLineList[: indexLine] breakLine = "".join( breakLine) if not "import" in breakLine: # -- It's file because only 'from'key word -- # checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 0 else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 else: checkCharAfterWord = 1 if checkCharAfterWord == 0: # -- Initialize vars -- # getCharAllInKey = [] getWord = [] indexExploreStart = indexLine indexExploreEnd = indexLine + len( key ) - 1 # Remove -1, first letter is already increment # -- List contain all letters of key -- # for getLetterKey in key: getCharAllInKey.append( getLetterKey) # -- Check if all letters of key is equal to all letters of word -- # for indexCheckLetter, checkLetter in enumerate( getIndexLineList): if indexCheckLetter >= indexExploreStart and indexCheckLetter <= indexExploreEnd: getWord.append( checkLetter) # -- Check if number of chars in key equal number of chars in word -- # if list( set(getCharAllInKey) - set(getWord)) == []: checkGetWord = "".join( getWord) checkGetKey = "".join( getCharAllInKey) # -- Check if key == word -- # if checkGetWord == checkGetKey: for obfChar in value: charValue.append( obfChar) letterLine = letterValue raise BreakLoop else: continue else: continue else: continue else: continue else: continue raise BreakLoop except BreakLoop: returnLine.append(letterLine) # -- Rewrite the line -- # returnLine = "".join(returnLine) return returnLine[:] def VarsDefinedByUser(self, codeArg, outputArg, mixerLevelArg, verboseArg): variablesDict = {} classesDict = {} functionsDict = {} includeDict = {} allDict = {} checkWordsMixed = [] wordsExcluded = [] wordsExcludedFound = [] wordsIncludedFound = [] wordsIncludedNotFound = [] checkCountWordsMixed = 0 checkCountWordsValue = 0 checkQuotePassing = 0 numberReplaced = 0 countRecursFiles = 0 if codeArg == "python": variablesDefined = r"(^\w+|\w+)([\s|^\s]*=[\s|\w|\"|\'])" # Variables variablesErrorDefined = r"except(\s+\w+\sas\s)(\w)" # Error variables variablesLoopDefined = r"for\s+([\w\s\,]+)(\s+in\s+)" # Loop variables functionsDefined = r"def\s(\w+)" # Functions classDefined = r"class\s(\w+)" # Classes quoteOfEndCommentariesMultipleLines = r"^\s*[\"|\']{3}\)?\.?" # """ and ''' without before variables, if commentaries is over multiple lines and he finish by .format() funtion quoteOfCommentariesMultipleLines = r"^\s*[\"|\']{3}$" # """ and ''' without before variables and if commentaries is over multiple lines quoteInRegex = r"\={1}\s*r[\"|\']{1}" # If quote in regex quoteIntoVariable = r".*\={1}\s*\w*\.?\w*[\(|\.]{1}[\"|\']{3}|.*\={1}\s*[\"|\']{3}" # """ and ''' with before variables detectFile = "py" blockDirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFile), recursive=True) ] # -- Find variables/classes/functions and mixed it -- # for file in recursFiles: if re.match(blockDirs, file): continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: # -- Variables -- # search = re.search(variablesDefined, eachLine) if search != None: # -- Detect mixer -- # mixer = self.mixer.GetStringMixer(mixerLevelArg) # -- Add the mixer value of variables -- # if search.group(1) not in variablesDict: variablesDict[search.group(1)] = mixer # -- Error variables -- # search = re.search(variablesErrorDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(2) not in variablesDict: variablesDict[search.group(2)] = mixer # -- Loop variables -- # search = re.search(variablesLoopDefined, eachLine) if search != None: if "," in search.group(1): modifySearch = search.group(1).replace( ",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer( mixerLevelArg) variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer( mixerLevelArg) variablesDict[search.group(1)] = mixer # -- Functions -- # search = re.search(functionsDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in functionsDict: if codeArg == "python": if not re.match(r"__init__", search.group(1)): functionsDict[search.group(1)] = mixer # -- Classes -- # search = re.search(classDefined, eachLine) if search != None: mixer = self.mixer.GetStringMixer(mixerLevelArg) if search.group(1) not in classesDict: classesDict[search.group(1)] = mixer # -- Remove excluded variables/classes/functions defined from 'exclude/python/exclude_python_words.txt' in dict -- # if os.path.exists(self.pythonExcludeWords) == True: with open(self.pythonExcludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcluded.append(word) else: print("[-] '{0}' file not found\n".format(self.pythonExcludeWords)) for word in wordsExcluded: if word in variablesDict.keys(): wordsExcludedFound.append(word) del variablesDict[word] if word in classesDict.keys(): wordsExcludedFound.append(word) del classesDict[word] if word in functionsDict.keys(): wordsExcludedFound.append(word) del functionsDict[word] # -- Include variables/classes/functions defined from 'include/python/include_python_words.txt' in dict -- # if os.path.exists(self.pythonIncludeWords) == True: with open(self.pythonIncludeWords, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsIncludedFound.append(word) else: print("[-] '{0}' file not found\n".format(self.pythonIncludeWords)) for word in wordsIncludedFound: if word not in variablesDict.keys( ) and word not in classesDict.keys( ) and word not in functionsDict.keys(): mixer = self.mixer.GetStringMixer(mixerLevelArg) includeDict[word] = mixer wordsIncludedNotFound.append(word) for file in recursFiles: if re.match(blockDirs, file): continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for word in wordsIncludedNotFound: if word in eachLine: wordsIncludedNotFound.remove(word) for word in wordsIncludedNotFound: if word in includeDict.keys(): del includeDict[word] # -- Display variables/classes/functions found -- # if verboseArg: print("\n[+] Variables found :\n") if variablesDict == {}: print("-> No result") else: for key, value in variablesDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Classes found :\n") if classesDict == {}: print("-> No result") else: for key, value in classesDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Functions found :\n") if functionsDict == {}: print("-> No result") else: for key, value in functionsDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Include found :\n") if includeDict == {}: print("-> No result") else: for key, value in includeDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Exclude found :\n") if wordsExcludedFound == []: print("-> No result") else: for word in wordsExcludedFound: print("-> {0} : excluded".format(word)) # -- Merge all dicts -- # allDict = self.utils.DictMerge(allDict, variablesDict) allDict = self.utils.DictMerge(allDict, classesDict) allDict = self.utils.DictMerge(allDict, functionsDict) allDict = self.utils.DictMerge(allDict, includeDict) for number in recursFiles: countRecursFiles += 1 # -- Change variables/classes/functions to mixed values -- # print( "\n[+] Running replacement of variables/classes/functions in {0} file(s)...\n" .format(countRecursFiles)) with tqdm(total=countRecursFiles) as pbar: for file in recursFiles: pbar.update(1) if re.match(blockDirs, file): continue else: with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if not eachLine: continue else: if codeArg == "python": # -- Check code into """ or ''' -- # if re.match(quoteIntoVariable, eachLine): checkQuotePassing += 1 eachLine = ReplaceWords.EachLine( self, codeArg, eachLine, allDict.items()) print(eachLine) continue elif re.match( quoteOfCommentariesMultipleLines, eachLine ) or re.match( quoteOfEndCommentariesMultipleLines, eachLine): checkQuotePassing += 1 eachLine = ReplaceWords.EachLine( self, codeArg, eachLine, allDict.items()) print(eachLine) if checkQuotePassing == 2: checkQuotePassing = 0 continue if checkQuotePassing == 1: print(eachLine) continue elif checkQuotePassing == 2: checkQuotePassing = 0 continue else: eachLine = ReplaceWords.EachLine( self, codeArg, eachLine, allDict.items()) print(eachLine) continue # -- Check if variables/classes/functions have been mixed -- # for file in recursFiles: if re.match(blockDirs, file): continue else: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for value in allDict.values(): if value in eachLine: checkWordsMixed.append(value) # -- Remove duplicated key -- # checkListWordsMixed = list(dict.fromkeys(checkWordsMixed)) for i in checkListWordsMixed: checkCountWordsMixed += 1 for i in allDict.values(): checkCountWordsValue += 1 if (self.remove.LineBreaks(codeArg, outputArg) == 0): if checkCountWordsMixed == checkCountWordsValue: print( "\n-> {0} variables/classes/functions replaced in {1} file(s)\n" .format(checkCountWordsValue, countRecursFiles)) return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
class Remove: def __init__(self): self.utils = Utils() def LinesSpaces(self, outputArg=None, verboseArg=None): checkLinesSpace = {} checkEmptyLine = 0 countRecursFiles = 0 numberLine = 0 recursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False) for file in recursFiles: countRecursFiles += 1 # -- Remove all empty lines -- # with Bar(PROGRESS_COLOUR + "Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: with fileinput.FileInput(file, inplace=True) as inputFile: for eachLine in inputFile: if eachLine == "\n": pass else: sys.stdout.write(eachLine) bar.next(1) bar.finish() with Bar(PROGRESS_COLOUR + "Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLine = 0 with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLine += 1 if eachLine == "\n": checkLinesSpace[numberLine] = file checkEmptyLine += 1 bar.next(1) bar.finish() if checkEmptyLine == 0: return EXIT_SUCCESS else: if verboseArg: print("\n[!] Empty line that not been removed... :\n") for key, value in checkLinesSpace.items(): print("\n-> File : {0}".format(value)) print("-> Line : {0}".format(key)) return EXIT_FAILURE def Comments(self, outputArg=None, verboseArg=None): checkRemoved = {} countLineOutput = 0 countLineInput = 0 noComments = 0 multipleLinesComments = 0 countRecursFiles = 0 numberLine = 0 commentsBeginLine = r"^\#.*" quoteOfCommentsEndLines = r".*[\'\|\"]{3}\s*$" quoteInRegex = r"={1}\s*r[\"|\']{3}" quoteOfCommentsMultipleLines = r"^\s+[\"|\']{3}|^[\"|\']{3}" quoteOfCommentsOneLine = r".*[\"]{3}.*[\"]{3}|.*[\']{3}.*[\']{3}\s*$" quoteIntoVariableOrPrint = r"s*print.*\(?[\"|\']{3}|.*\=\s*[\"|\']{3}" commentsAfterLine = r"\s*\#[^\"|^\'|^\.|^\?|^\*|^\!|^\]|^\[|^\\|^\)|^\(|^\{|^\}].*" recursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False) for number in recursFiles: countRecursFiles += 1 # -- Remove comments and Count comments will be removed -- # print("\n[+] Running remove comments in {0} file(s)...\n".format( countRecursFiles)) with Bar(PROGRESS_COLOUR + "Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Remove comments -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if "coding" in eachLine or "#!" in eachLine: sys.stdout.write(eachLine) continue if multipleLinesComments == 1 or noComments == 1: if re.match(quoteOfCommentsEndLines, eachLine): if re.match(quoteInRegex, eachLine): countLineInput += 1 continue elif re.match(quoteIntoVariableOrPrint, eachLine): countLineInput += 1 continue else: if multipleLinesComments == 1: multipleLinesComments = 0 countLineInput += 1 else: noComments = 0 sys.stdout.write(eachLine) continue else: if noComments == 1: sys.stdout.write(eachLine) else: countLineInput += 1 continue elif multipleLinesComments == 0: if re.match(quoteOfCommentsMultipleLines, eachLine): if re.match(quoteOfCommentsOneLine, eachLine): countLineInput += 1 continue else: countLineInput += 1 multipleLinesComments = 1 continue elif re.match(quoteIntoVariableOrPrint, eachLine): noComments = 1 sys.stdout.write(eachLine) continue else: sys.stdout.write(eachLine) else: sys.stdout.write(eachLine) bar.next(0.5) with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if "coding" in eachLine or "#!" in eachLine: sys.stdout.write(eachLine) continue searchCommentsAfterLine = re.search( commentsAfterLine, eachLine) searchCommentsBeginLine = re.search( commentsBeginLine, eachLine) if searchCommentsBeginLine: countLineInput += 1 eachLine = eachLine.replace( searchCommentsBeginLine.group(0), "") sys.stdout.write(eachLine) elif searchCommentsAfterLine: eachLine = eachLine.replace( searchCommentsAfterLine.group(0), "") countLineInput += 1 sys.stdout.write(eachLine) else: sys.stdout.write(eachLine) bar.next(0.5) bar.finish() # -- Check if all comments are removed -- # noComments = 0 multipleLinesComments = 0 with Bar(PROGRESS_COLOUR + "Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: with open(file, "r") as readFile: readF = readFile.readlines() numberLine = 0 for eachLine in readF: numberLine += 1 if "coding" in eachLine or "#!" in eachLine: continue else: if multipleLinesComments == 1 or noComments == 1: if re.match(quoteOfCommentsEndLines, eachLine): if re.match(quoteInRegex, eachLine): countLineOutput += 1 continue elif re.match(quoteIntoVariableOrPrint, eachLine): countLineOutput += 1 continue else: if multipleLinesComments == 1: multipleLinesComments = 0 checkRemoved[ numberLine] = "{0} ( multiple lines comments )".format( file) countLineOutput += 1 else: noComments = 0 continue else: if noComments == 1: pass else: countLineOutput += 1 continue elif multipleLinesComments == 0: if re.match(quoteOfCommentsMultipleLines, eachLine): if re.match(quoteOfCommentsOneLine, eachLine): checkRemoved[numberLine] = file countLineOutput += 1 continue else: countLineOutput += 1 multipleLinesComments = 1 continue elif re.match(quoteIntoVariableOrPrint, eachLine): noComments = 1 continue else: pass else: pass bar.next(0.5) with open(file, "r") as readFile: readF = readFile.readlines() numberLine = 0 for eachLine in readF: numberLine += 1 if "coding" in eachLine or "#!" in eachLine: continue else: searchCommentsAfterLine = re.search( commentsAfterLine, eachLine) searchCommentsBeginLine = re.search( commentsBeginLine, eachLine) if searchCommentsBeginLine: checkRemoved[numberLine] = file countLineOutput += 1 elif searchCommentsAfterLine: checkRemoved[numberLine] = file countLineOutput += 1 else: pass bar.next(0.5) bar.finish() if countLineOutput == 0: print( "\n-> {0} lines of comments removed\n".format(countLineInput)) return EXIT_SUCCESS else: if verboseArg: print("\n[!] Comments that not been removed... :\n") for key, value in checkRemoved.items(): print("\n-> File : {0}".format(value)) if "multiple lines comments" in value: print( "-> Line : {0} ( This is the end line of multiple lines comments )" .format(key)) else: print("-> Line : {0}".format(key)) print("\n-> {0} lines of comments no removed\n".format( countLineOutput)) return EXIT_FAILURE def TrashFiles(self, outputArg=None, verboseArg=None): countRecursFiles = 0 removeFiles = 0 checkPycFile = [] currentPosition = os.getcwd() detectPycFiles = r".*\.pyc$" removePycFiles = r"\w+\.pyc$" recursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="pyc", blockDir="__pycache__", blockFile=False, dirOnly=False) for number in recursFiles: countRecursFiles += 1 if countRecursFiles == 0: print("[!] No .pyc file(s) found in {0}".format(outputArg)) return EXIT_SUCCESS print("\n[+] Running remove {0} .pyc file(s)...\n".format( countRecursFiles)) # -- Check if .pyc file(s) exists and remove it -- # with Bar(PROGRESS_COLOUR + "Setting up ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: if re.match(detectPycFiles, file): removeFiles += 1 checkPycFile.append(file) bar.next(1) bar.finish() # -- Remove pyc file(s) -- # with Bar(PROGRESS_COLOUR + "Correction ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: if re.match(detectPycFiles, file): extractPycFiles = re.search(removePycFiles, file) moveFolder = re.sub(removePycFiles, "", file) os.chdir(moveFolder) os.remove(extractPycFiles.group(0)) os.chdir(currentPosition) bar.next(1) bar.finish() checkRecursFiles = self.utils.CheckFileDir(output=outputArg, detectFiles="pyc", blockDir="__pycache__", blockFile=False, dirOnly=False) if checkRecursFiles != []: if verboseArg: for pycFile in checkRecursFiles: print("-> .pyc file no removed : {0}".format(pycFile)) return EXIT_FAILURE else: if verboseArg: for pycFile in checkPycFile: print("-> .pyc file removed : {0}".format(pycFile)) print("\n-> {0} .pyc file(s) removed".format(removeFiles)) return EXIT_SUCCESS
class Analyze: def __init__(self): self.utils = Utils() def InputAvailable(self, inputArg=None, verboseArg=None): inputFileFound = [] inputFileEmpty = [] inputFileFoundCount = 0 inputFileEmptyCount = 0 countRecursFiles = 0 numberLine = 0 if os.path.exists(inputArg) == True: if os.path.isdir(inputArg) == True: detectFiles = "py" blockDir = "__pycache__" recursFiles = [ file for file in glob.glob("{0}{1}**{1}*.{2}".format( inputArg, self.utils.Platform(), detectFiles), recursive=True) ] if recursFiles == []: print(ERROR_COLOUR + "[-] {0} directory empty or python file not found". format(inputArg)) return ERROR_DIR_EMPTY for number in recursFiles: countRecursFiles += 1 print("\n[+] Running analyze input of {0} file(s)...\n".format( countRecursFiles)) with Bar(PROGRESS_COLOUR + "Analysis ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: if blockDir in file: continue else: if os.path.getsize(file) > 0: inputFileFound.append(file) inputFileFoundCount += inputFileFoundCount + 1 else: inputFileEmpty.append(file) inputFileEmptyCount += inputFileEmptyCount + 1 bar.next(1) if inputFileFoundCount >= 1 and inputFileEmptyCount < inputFileFoundCount: if verboseArg: print("\n\n[+] File input found :\n") if inputFileFound == []: print("-> no result") else: for file in inputFileFound: print("-> {0}".format(file)) for file in inputFileEmpty: print("-> {0} : empty".format(file)) return EXIT_SUCCESS elif inputFileFoundCount == inputFileEmptyCount and inputFileFoundCount > 0: print( ERROR_COLOUR + "[-] All files in directory specified are emtpy !") return ERROR_FILE_EMPTY else: print( ERROR_COLOUR + "[-] No file available in '{0}'.".format(inputArg)) return ERROR_FILE_NOT_FOUND bar.finish() else: print(ERROR_COLOUR + "[-] '{0}' is not a directory".format(inputArg)) return ERROR_DIR_NOT_FOUND else: print(ERROR_COLOUR + "[-] '{0}' not exists".format(inputArg)) return ERROR_PATH_NOT_FOUND def OutputAvailable(self, inputArg=None, outputArg=None, verboseArg=None): outputFileFound = [] outputFileEmpty = [] outputFileFoundCount = 0 outputFileEmptyCount = 0 countRecursFiles = 0 if os.path.exists(outputArg) == True: removeRequest = input( "[!] Output '{0}' already exists, do you want remove it ? (Y/N) : " .format(outputArg)) removeRequest = removeRequest.upper() if removeRequest == "Y": try: shutil.rmtree(outputArg) if os.path.exists(outputArg) == False: shutil.copytree(inputArg, outputArg) if os.path.exists(outputArg) == True: if os.path.isdir(outputArg) == True: detectFiles = "py" blockDir = "__pycache__" recursFiles = [ file for file in glob.glob( "{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFiles), recursive=True) ] for number in recursFiles: countRecursFiles += 1 print( "\n[+] Running analyze output of {0} file(s)...\n" .format(countRecursFiles)) if recursFiles == []: print( ERROR_COLOUR + "[-] {0} directory empty, no copied file" .format(inputArg)) return ERROR_DIR_EMPTY with Bar(PROGRESS_COLOUR + "Analysis ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: if blockDir in file: continue else: if os.path.getsize(file) > 0: outputFileFound.append(file) outputFileFoundCount += outputFileFoundCount + 1 else: outputFileEmpty.append(file) outputFileEmptyCount += outputFileEmptyCount + 1 bar.next(1) if outputFileFoundCount >= 1 and outputFileFoundCount > outputFileEmptyCount: if verboseArg: print( "\n\n[+] Output files copy :\n" ) if outputFileFound == []: print("-> no result") else: for file in outputFileFound: print( "-> {0}".format(file)) for file in outputFileEmpty: print("-> {0} : empty". format(file)) return EXIT_SUCCESS else: print(ERROR_COLOUR + "[-] No files available in '{0}'" .format(outputArg)) return ERROR_FILE_NOT_FOUND bar.finish() else: print( ERROR_COLOUR + "[-] Copy '{0}' to '{1}' failed, this is not a output directory copied" .format(inputArg, outputArg)) return ERROR_DIR_NOT_FOUND else: print(ERROR_COLOUR + "[-] Copy '{0}' to '{1}' failed".format( inputArg, outputArg)) return ERROR_CAN_NOT_COPY else: print(ERROR_COLOUR + "[-] Remove '{0}' failed".format(outputArg)) return ERROR_CAN_NOT_REMOVE except Exception as e: print(ERROR_COLOUR + "[-] {0}".format(e)) return EXIT_FAILURE else: print(ERROR_COLOUR + "[-] Remove '{0}' failed, the user has refused".format( outputArg)) return ERROR_CAN_NOT_REMOVE else: try: shutil.copytree(inputArg, outputArg) if os.path.exists(outputArg) == True: if os.path.isdir(outputArg) == True: detectFiles = "py" blockDir = "__pycache__" recursFiles = [ file for file in glob.glob("{0}{1}**{1}*.{2}".format( outputArg, self.utils.Platform(), detectFiles), recursive=True) ] for number in recursFiles: countRecursFiles += 1 print( "\n[+] Running analyze output of {0} file(s)...\n". format(countRecursFiles)) if recursFiles == []: print(ERROR_COLOUR + "[-] {0} directory empty, no copied file". format(inputArg)) return ERROR_DIR_EMPTY with Bar(PROGRESS_COLOUR + "Analysis ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: if blockDir in file: continue else: if os.path.getsize(file) > 0: outputFileFound.append(file) outputFileFoundCount += outputFileFoundCount + 1 else: outputFileEmpty.append(file) outputFileEmptyCount += outputFileEmptyCount + 1 bar.next(1) if outputFileFoundCount >= 1 and outputFileFoundCount > outputFileEmptyCount: if verboseArg: print("\n\n[+] File output found :\n") if outputFileFound == []: print("-> no result") else: for file in outputFileFound: print("-> {0} : copy".format(file)) for file in outputFileEmpty: print("-> {0} : copy empty".format( file)) return EXIT_SUCCESS else: print(ERROR_COLOUR + "[-] No files available in '{0}'".format( outputArg)) return ERROR_FILE_NOT_FOUND bar.finish() else: print( ERROR_COLOUR + "[-] Copy '{0}' to '{1}' failed, this is not a output directory copied !" .format(inputArg, outputArg)) return ERROR_DIR_NOT_FOUND else: print(ERROR_COLOUR + "[-] Copy '{0}' to '{1}' failed".format( inputArg, outputArg)) return ERROR_CAN_NOT_COPY except Exception as e: print(ERROR_COLOUR + "[-] {0}".format(e)) return EXIT_FAILURE
def StringsToHex(self, codeArg, outputArg, mixerLevelArg): getLetterLineList = [] countRecursFiles = 0 checkPrint = 0 checkHexError = False checkPrintError = False hexLine = "" utils = Utils() mixer = Mixer() remove = Remove() if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" detectExecFunc = r"exec\(\w+\)" detectQuotes = r"[\'|\"]{3}" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, utils.Platform(), detectFiles), recursive=True)] for number in recursFiles: countRecursFiles += 1 print("\n[+] Running replace all strings to their hexadecimal value in {0} file(s)...\n".format(countRecursFiles)) # -- Replace all strings to their hexadecimal value -- # with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: checkPrint = 0 # initialize check print() func at the begining of each file pbar.update(1) if blockDir in file: continue else: # -- Add a new first random line and move the old first line to the second line to avoid replacing it -- # with open(file, "r") as inputFile: stringRandomMixer = mixer.GetStringMixer(mixerLevelArg) firstLine = "{0}\n".format(stringRandomMixer) line = inputFile.readlines() line.insert(0, firstLine) with open(file, "w") as inputFile: inputFile.writelines(line) # -- Replace all lines-- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if checkPrint == 0: varMixer = mixer.GetStringMixer(mixerLevelArg) print(varMixer + "=\"\"\"") checkPrint = 1 else: getLetterLineList = [] # initialize list for letterLine in eachLine: letterToHex = "\\x" + str(letterLine.encode().hex()) getLetterLineList.append(letterToHex) # Get list of all letters in line hexLine = "".join(getLetterLineList) print(hexLine) # -- Add exec funtions to interpret hex code in strings -- # with open(file, "a") as inputFile: inputFile.write("\"\"\"") inputFile.write("\nexec({0})".format(varMixer)) # -- Check if all lines are replaced of hexadecimal value -- # for file in recursFiles: if blockDir in file: continue else: with open(file, "r") as inputFile: for eachLine in inputFile: if not eachLine: continue else: if not "\\x" in eachLine: if re.match(detectQuotes, eachLine): continue elif re.match(detectExecFunc, eachLine): continue else: checkError = True else: continue if (remove.Backslashes(codeArg, outputArg) == 0): if checkHexError == False: return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
class Analyze: def __init__(self): self.utils = Utils() def InputAvailable(self, oneFileArg, inputArg, codeArg): inputFileFound = [] inputFileEmpty = [] inputFileFoundCount = 0 inputFileEmptyCount = 0 inputExt = "" ######################################### One file only ######################################### if oneFileArg == True: if os.path.exists(inputArg) == True: if os.path.isfile(inputArg) == True: if codeArg == "python": if ".py" in inputArg: if os.path.getsize(inputArg) > 0: return EXIT_SUCCESS else: print("[-] '{0}' is empty.".format(inputArg)) return ERROR_FILE_EMPTY else: print("[-] '{0}' is not python file.".format( inputArg)) return ERROR_BAD_FILE_TYPE else: print("[-] '{0}' is not a file.".format(inputArg)) return ERROR_BAD_FILE_TYPE else: print("[-] '{0}' not exists.".format(inputArg)) return ERROR_PATH_NOT_FOUND ######################################### Multiple files ######################################### else: if os.path.exists(inputArg) == True: if os.path.isdir(inputArg) == True: if codeArg == "python": inputExt = "py" blockdirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( inputArg, self.utils.Platform(), inputExt), recursive=True) ] for output in recursFiles: if re.match(blockdirs, output): continue else: if os.path.getsize(output) > 0: inputFileFound.append(output) inputFileFoundCount += inputFileFoundCount + 1 else: inputFileEmpty.append(output) inputFileEmptyCount += inputFileEmptyCount + 1 if inputFileFoundCount >= 2 and inputFileEmptyCount < 2: return EXIT_SUCCESS elif inputFileFoundCount == 1: print( "[-] Only one file available found in '{0}', select [-f --onefile] argument." .format(inputArg)) return ERROR_BAD_ARGUMENTS elif inputFileFoundCount == inputFileEmptyCount and inputFileEmptyCount > 0 and inputFileEmptyCount > 0: print("[-] All files output specified are emtpy !.") return ERROR_FILE_EMPTY else: print( "[-] No file available in '{0}'.".format(inputArg)) return ERROR_FILE_NOT_FOUND else: print("[-] '{0}' is not a directory.".format(inputArg)) return ERROR_NOT_DIR else: print("'{0}' not exists.".format(inputArg)) return ERROR_PATH_NOT_FOUND def OutputAvailable(self, oneFileArg, inputArg, codeArg, outputArg): outputFileFound = [] outputFileEmpty = [] outputFileFoundCount = 0 outputFileEmptyCount = 0 outputExt = "" if os.path.exists(outputArg) == True: removeRequest = input( "[!] Output '{0}' already exists, do you want remove it ? (Y/N) : " .format(outputArg)) removeRequest = removeRequest.upper() if removeRequest == "Y": ######################################### One file only ######################################### if oneFileArg == True: try: os.remove(outputArg) if os.path.exists(outputArg) == False: shutil.copy(inputArg, outputArg) if os.path.exists(outputArg) == True: if os.path.isfile(outputArg) == True: if os.path.getsize(outputArg) > 0: return EXIT_SUCCESS else: print( "[-] Copy '{0}' to '{1}' failed, the files is empty !." .format(inputArg, outputArg)) return ERROR_FILE_EMPTY else: print( "[-] Copy '{0}' to '{1}' failed, this is not a output file copy !." .format(inputArg, outputArg)) return ERROR_NOT_FILE else: print("[-] Copy '{0}' to '{1}' failed.".format( inputArg, outputArg)) return ERROR_CANNOT_COPY else: print("[-] Remove '{0}' failed.".format(outputArg)) return ERROR_CANNOT_REMOVE except Exception as e: print("[-] {0}".format(e)) return EXIT_FAILURE ######################################### Multiple files ######################################### else: try: shutil.rmtree(outputArg) if os.path.exists(outputArg) == False: shutil.copytree(inputArg, outputArg) if os.path.exists(outputArg) == True: if os.path.isdir(outputArg) == True: if codeArg == "python": inputExt = "py" blockdirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( inputArg, self.utils.Platform(), inputExt), recursive=True) ] for output in recursFiles: if re.match(blockdirs, output): continue else: if os.path.getsize(output) > 0: outputFileFound.append(output) outputFileFoundCount += outputFileFoundCount + 1 else: outputFileEmpty.append(output) outputFileEmptyCount += outputFileEmptyCount + 1 if outputFileFoundCount >= 2 and outputFileEmptyCount < 2: return EXIT_SUCCESS else: print( "[-] No files available in '{0}'.". format(outputArg)) return ERROR_FILE_NOT_FOUND else: print( "[-] Copy '{0}' to '{1}' failed, this is not a output directory copied !." .format(inputArg, outputArg)) return ERROR_NOT_DIR else: print("[-] Copy '{0}' to '{1}' failed.".format( inputArg, outputArg)) return ERROR_CANNOT_COPY else: print("[-] Remove '{0}' failed.".format(outputArg)) return ERROR_CANNOT_REMOVE except Exception as e: print("[-] {0}".format(e)) return EXIT_FAILURE else: print("[-] Remove '{0}' failed, the user has refused.".format( outputArg)) return ERROR_CANNOT_REMOVE else: ######################################### One file only ######################################### if oneFileArg == True: try: shutil.copy(inputArg, outputArg) if os.path.exists(outputArg) == True: if os.path.isfile(outputArg) == True: if os.path.getsize(outputArg) > 0: return EXIT_SUCCESS else: print( "[-] Copy '{0}' to '{1}' failed, the file is empty !." .format(inputArg, outputArg)) return ERROR_CANNOT_COPY else: print( "[-] Copy '{0}' to '{1}' failed, this is not a output file copied !." .format(inputArg, outputArg)) return ERROR_NOT_FILE else: print("[-] Copy '{0}' to '{1}' failed.".format( inputArg, outputArg)) return ERROR_CANNOT_COPY except Exception as e: print("[-] {0}".format(e)) return EXIT_FAILURE ######################################### Multiple files ######################################### else: try: shutil.copytree(inputArg, outputArg) if os.path.exists(outputArg) == True: if os.path.isdir(outputArg) == True: if codeArg == "python": inputExt = "py" blockdirs = r"__pycache__" recursFiles = [ f for f in glob.glob("{0}{1}**{1}*.{2}".format( inputArg, self.utils.Platform(), inputExt), recursive=True) ] for output in recursFiles: if re.match(blockdirs, output): continue else: if os.path.getsize(output) > 0: outputFileFound.append(output) outputFileFoundCount += outputFileFoundCount + 1 else: outputFileEmpty.append(output) outputFileEmptyCount += outputFileEmptyCount + 1 if outputFileFoundCount >= 2 and outputFileEmptyCount < 2: return EXIT_SUCCESS else: print( "[-] No files available in '{0}'.".format( outputArg)) return ERROR_FILE_NOT_FOUND else: print( "[-] Copy '{0}' to '{1}' failed, this is not a output directory copied !." .format(inputArg, outputArg)) return ERROR_NOT_DIR else: print("[-] Copy '{0}' to '{1}' failed.".format( inputArg, outputArg)) return ERROR_CANNOT_COPY except Exception as e: print("[-] {0}".format(e)) return EXIT_FAILURE
def FilesName(self, codeArg, outputArg, mixerLevelArg, verboseArg): filesNameDict = {} filesNameDictNoExt = {} filesNameFound = [] filesNameFoundNoExt = [] filesNameMixed = [] checkFilesFound = [] countRecursFiles = 0 checkRenameInDir = 0 checkRenameInCode = 0 unix = False win = False currentPosition = os.getcwd() utils = Utils() mixer = Mixer() remove = Remove() if codeArg == "python": detectFiles = "py" blockDir = "__pycache__" blockFile = "__init__" detectImport = r"\s*from\s+|\s*import\s+" recursFiles = [f for f in glob.glob("{0}{1}**{1}*.{2}".format(outputArg, utils.Platform(), detectFiles), recursive=True)] for number in recursFiles: countRecursFiles += 1 for file in recursFiles: if blockDir in file or blockFile in file: continue else: if "\"" in file: parseFilePath = file.split("\"") win = True else: parseFilePath = file.split("/") unix = True checkFilesFound.append(file) mixer = self.mixer.GetStringMixer(mixerLevelArg) filesNameDict[parseFilePath[-1]] = mixer + ".py" filesNameDictNoExt[parseFilePath[-1].replace(".py", "")] = mixer filesNameFound.append(parseFilePath[-1]) filesNameMixed.append(mixer + ".py") removeExt = parseFilePath[-1].replace(".py","") filesNameFoundNoExt.append(removeExt) # -- Diplay all files found with their mixed values if verbose arg is actived -- # if verboseArg: print("\n[+] Files name found with their mixed values :\n") for key, value in filesNameDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Running replace files name in {0} file(s)...\n".format(countRecursFiles)) # -- Replace all files name to random strings with length defined -- # with tqdm.tqdm(total=countRecursFiles) as pbar: for file in recursFiles: pbar.update(1) if blockDir in file: continue else: # -- Rename all files in python code -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: try: for fileName in filesNameFound: for fileNameNoExt in filesNameFoundNoExt: if fileName in eachLine or fileNameNoExt in eachLine: if not ".py" in eachLine: if re.match(detectImport, eachLine): eachLine = Replace.EachLine(self, codeArg, eachLine, filesNameDictNoExt.items(), True) print(eachLine) raise BreakLoop else: continue else: eachLine = Replace.EachLine(self, codeArg, eachLine, filesNameDict.items(), True) print(eachLine) raise BreakLoop else: continue print(eachLine) except BreakLoop: continue # -- Rename all files in their directories -- # if "\"" in file: parseFilePath = file.split("\"") win = True else: parseFilePath = file.split("/") unix = True for key, value in filesNameDict.items(): if key == parseFilePath[-1]: parseFilePath.remove(parseFilePath[-1]) if unix == True: parseFilePathToMove = "/".join(parseFilePath) else: parseFilePathToMove = "\"".join(parseFilePath) os.chdir(parseFilePathToMove) # Move in directory to rename python file os.rename(key, value) else: continue os.chdir(currentPosition) # Return to old position # -- Check if all files name are been replaced to random strings with length defined -- # for i in checkFilesFound: i.replace(".py", "") # -- Check for file(s) name -- # for file in recursFiles: if blockDir in file or blockFile in file: continue else: for i in checkFilesFound: if i in file: checkFilesFound.remove(i) continue # -- Check for code if file(s) name -- # if checkFilesFound != []: for file in recursFiles: if blockDir in file or blockFile in file: continue else: with open(file, "r") as inputFile: for line in inputFile: for i in checkFilesFound: if i in line: checkFilesFound.remove(i) continue if checkFilesFound == []: if (remove.Backslashes(codeArg, outputArg) == 0): return EXIT_SUCCESS else: return EXIT_FAILURE else: return EXIT_FAILURE
def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() self.pythonExcludeWords = "exclude_python_words.txt" self.pythonIncludeWords = "include_python_words.txt"
class Padding: def __init__(self): self.mixer = Mixer() self.utils = Utils() self.simpleSpace = " " def CheckBasicIndentation(self, recursPythonFiles): # -- Check basic indentation (2 - 4 - 8) of python files -- # allNumIndentations = [] headerPythonFile = r"\s*#!.*[python|1-9]|\s*#.*-*-$" for file in recursPythonFiles: with open(file, "r") as inputFile: for eachLine in inputFile: if re.match(headerPythonFile, eachLine): continue else: spaces = len(eachLine) - len(eachLine.lstrip()) if spaces == 0 or spaces == 1: continue else: allNumIndentations.append(spaces) if allNumIndentations == []: return 0 else: allNumIndentations.sort() return allNumIndentations[0] def ScriptsGenerator(self, randomClassesFunctions, mixerLengthArg): varRandom1 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom2 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom3 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom4 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom5 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom6 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom7 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom8 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom9 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom10 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom11 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom12 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom13 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) varRandom14 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) # ---------- Python random snippets code ---------- # if randomClassesFunctions == True: rand = random.randint(1, 15) else: rand = random.randint(1, 9) # -- snippet 1 -- # if rand == 1: scriptPadding1 = textwrap.dedent(""" {0} = '{5}' {1} = '{6}' {2} = '{7}' {3} = '{8}' {4} = '{9}' if {0} in {1}: {0} = {4} if {1} in {2}: {1} = {3} elif {1} in {0}: {2} = {1} if {2} in {1}: {1} = {4} """).format(varRandom1, varRandom2, varRandom3, varRandom4, varRandom5, \ varRandom6, varRandom7, varRandom8, varRandom9, varRandom10) return scriptPadding1 # -- snippet 2 -- # elif rand == 2: scriptPadding2 = textwrap.dedent(""" {0} = '{2}' {1} = '{3}' if {0} != {1}: {0} = '{3}' {1} = {0} {0} = '{2}' """).format(varRandom1, varRandom2, varRandom3, varRandom4) return scriptPadding2 # -- snippet 3 -- # elif rand == 3: scriptPadding3 = textwrap.dedent(""" {0} = '{6}' {1} = '{7}' {2} = '{8}' {3} = '{9}' {4} = '{10}' {5} = '{11}' if {0} != {3}: {1} = {2} for {5} in {3}: if {5} != {2}: {1} = {1} else: {4} = {0} else: {2} = {0} {0} = {4} if {2} == {0}: for {5} in {0}: if {5} == {2}: {2} = {0} else: {2} = {4} """).format(varRandom1, varRandom2, varRandom3, varRandom4, varRandom5, \ varRandom6, varRandom7, varRandom8, varRandom9, varRandom10, \ varRandom11, varRandom12) return scriptPadding3 # -- snippet 4 -- # elif rand == 4: scriptPadding4 = textwrap.dedent(""" {0} = '{3}' {1} = '{4}' {2} = '{5}' if {0} == {1}: {2} = '{5}' {2} = {0} else: {2} = '{5}' {2} = '{3}' """).format(varRandom1, varRandom2, varRandom3, varRandom4, \ varRandom5, varRandom6,) return scriptPadding4 # -- snippet 5 -- # elif rand == 5: scriptPadding5 = textwrap.dedent(""" {0} = '{6}' {1} = '{7}' {2} = '{8}' {3} = '{9}' {4} = '{10}' {5} = '{11}' if {2} == {3}: for {5} in {4}: if {5} == {3}: {4} = {0} else: {3} = {1} """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8, varRandom9, \ varRandom10, varRandom11, varRandom12) return scriptPadding5 # -- snippet 6 -- # elif rand == 6: scriptPadding6 = textwrap.dedent(""" {0} = '{4}' {1} = '{5}' {2} = '{6}' {3} = '{7}' if {1} == {0}: for {0} in {1}: if {1} == {1}: {2} = '{3}' elif {2} == {3}: {3} = {0} else: {0} = {1} elif {2} == {2}: for {2} in {1}: if {3} == {1}: {2} = '{3}' elif {2} == {3}: {3} = {0} else: {0} = {1} for {2} in {1}: if {3} == {1}: {2} = '{3}' elif {2} == {3}: {3} = {0} else: {0} = {3} else: {0} = {1} """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8) return scriptPadding6 # -- snippet 7 -- # elif rand == 7: scriptPadding7 = textwrap.dedent(""" {0} = '{7}' {1} = '{8}' {2} = '{9}' {3} = '{10}' {4} = '{11}' {5} = '{12}' {6} = [ '{7}', '{9}', '{11}', '{13}' ] for {0} in {5}: for {1} in {2}: if {3} == {4}: {1} = {0} elif {4} == {1}: {1} = {5} else: {4} = {5} for {1} in {6}: {2} = {1} """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8, varRandom9, \ varRandom10, varRandom11, varRandom12, \ varRandom13, varRandom14) return scriptPadding7 # -- snippet 8 -- # elif rand == 8: scriptPadding8 = textwrap.dedent(""" {0} = '{1}' """).format(varRandom1, varRandom2) return scriptPadding8 # -- snippet 9 -- # elif rand == 9: scriptPadding9 = textwrap.dedent(""" {0} = '{1}' {2} = '{3} {1}' """).format(varRandom1, varRandom2, varRandom3, \ varRandom4,) return scriptPadding9 # ---------- Python random functions ---------- # # -- snippet 10 -- # elif rand == 10: scriptPadding10 = textwrap.dedent(""" def {0}(): {1} = '{2}' {3} = True """).format(varRandom1, varRandom2, varRandom3, \ varRandom4,) return scriptPadding10 # -- snippet 11 -- # elif rand == 11: scriptPadding11 = textwrap.dedent(""" def {0}({1}): {1} = '{2}' {3} = '{4}' if {1} == {3}: for {5} in {3}: if {5} == {3}: continue else: {6} = False """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7) return scriptPadding11 # -- snippet 12 -- # elif rand == 12: scriptPadding12 = textwrap.dedent(""" def {0}({1}, {2}): {1} = '{3}' {2} = '{4}' try: for {5} in {1}: if {5} == {2}: {6} = [] {7} = None else: pass except: pass """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8) return scriptPadding12 # -- snippet 13 -- # elif rand == 13: scriptPadding13 = textwrap.dedent(""" def {0}({1}, {2}, {3}): {1} = '{4}' {2} = '{5}' {6} = True while {6}: break for {6} in {2}: {3} = False """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7) return scriptPadding13 # ---------- Python random classes ---------- # # -- snippet 14 -- # elif rand == 14: scriptPadding14 = textwrap.dedent(""" class {0}: def __init__(self): self.{1} = '{2}' self.{3} = '{4}' def {5}(self): {6} = True while {6}: break """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7) return scriptPadding14 # -- snippet 15 -- # elif rand == 15: scriptPadding15 = textwrap.dedent(""" class {0}: def __init__(self): self.{1} = '{2}' self.{3} = '{4}' self.{5} = [] def {6}(self): self.{5} = True self.{3} = '{7}' """).format(varRandom1, varRandom2, varRandom3, \ varRandom4, varRandom5, varRandom6, \ varRandom7, varRandom8) return scriptPadding15 def AddRandomScripts(self, outputArg, mixerLengthArg, verboseArg): countScriptsAdded = 0 countLineAdded = 0 countLine = 0 checkLine = 0 checkQuotePassing = 0 checkCharPassing = 0 checkOtherCharPassing = 0 countRecursFiles = 0 basicIndentation = None addIndentScript = r".*\:{1}\s*$" quotesIntoVariable = r".*={1}\s*[\"|\']{3}" quotesEndMultipleLines = r"^\s*[\"|\']{3}\)?\.?" quotesInRegex = r"={1}\s*r{1}[\"|\']{3}" noAddScript = r"^\@|\s+\@|\s+return|\s*def\s+.+\s*\:{1}|^class\s+.+\s*\:{1}|.*[\{|\[|\(|\)|\]|\}|,|\\|^]\s*$|\s+yield.*|\s+raise.*" recursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False ) if verboseArg: print("\n[*] Check basic indentation...\n") basicIndentation = Padding.CheckBasicIndentation(self, recursFiles) if verboseArg: print("[*] Basic indentation : {} spaces".format(basicIndentation)) for number in recursFiles: countRecursFiles += 1 print("\n[+] Running add of random scripts in {} file(s)...\n".format(countRecursFiles)) # -- Count the number of lines that will be checked before filling -- # with Bar("Setting up ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: with open(file , "r") as readFile: readF = readFile.readlines() for eachLine in readF: if not eachLine: continue countLine += 1 bar.next(1) bar.finish() # -- Padding script added -- # with Bar("Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: sys.stdout.write(eachLine) if eachLine == "\n": continue else: spaces = len(eachLine) - len(eachLine.lstrip()) # -- Detect code into 3 quotes excepted comments -- # if re.match(quotesIntoVariable, eachLine): if re.match(quotesInRegex, eachLine): pass else: checkQuotePassing += 1 continue elif re.match(quotesEndMultipleLines, eachLine): if re.match(quotesInRegex, eachLine): pass else: checkQuotePassing += 1 if checkQuotePassing == 2: checkQuotePassing = 0 continue if checkQuotePassing == 1: continue elif checkQuotePassing == 2: checkQuotePassing = 0 pass else: pass # -- Check dict, list, tuple in multiple lines -- # if checkCharPassing == 1: if re.match(r".*[\"|\'|\)|\]|\}|\w]\s*$", eachLine): checkCharPassing = 0 continue else: continue elif checkOtherCharPassing >= 1: if re.match(r".*[\"|\'|\)|\]|\}|\w]\s*$", eachLine): checkOtherCharPassing -= 1 continue else: if re.match(r".*[\(|\{|\[]\s*$", eachLine): checkOtherCharPassing += 1 continue else: pass if re.match(noAddScript, eachLine): if re.match(r".*[\\|,]\s*$", eachLine): if checkCharPassing == 1: continue else: checkCharPassing = 1 continue elif re.match(r".*[\(|\{|\[]\s*$", eachLine): checkOtherCharPassing += 1 continue else: continue # -- Adding scripts -- # elif re.match(addIndentScript, eachLine): spaces = spaces + basicIndentation # add indentation sys.stdout.write(textwrap.indent(Padding.ScriptsGenerator( self, randomClassesFunctions=False, mixerLengthArg=mixerLengthArg), self.simpleSpace * spaces) ) countScriptsAdded += 1 else: if spaces == 0: sys.stdout.write(textwrap.indent(Padding.ScriptsGenerator( self, randomClassesFunctions=True, mixerLengthArg=mixerLengthArg), self.simpleSpace * spaces) ) countScriptsAdded += 1 else: sys.stdout.write(textwrap.indent(Padding.ScriptsGenerator( self, randomClassesFunctions=False, mixerLengthArg=mixerLengthArg), self.simpleSpace * spaces) ) countScriptsAdded += 1 bar.next(1) bar.finish() # -- Check if padding has added in output script -- # with Bar("Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: with open(file , "r") as readFile: readF = readFile.readlines() for eachLine in readF: if not eachLine: continue checkLine += 1 bar.next(1) bar.finish() countLineAdded = checkLine - countLine if checkLine > countLine: print("\n-> {} scripts added in {} file(s)\n".format(countScriptsAdded, countRecursFiles)) print("-> {} lines added in {} file(s)\n".format(countLineAdded, countRecursFiles)) return 0 else: return 1 def EmptyClasses(self, outputArg, mixerLengthArg, verboseArg): countRecursFiles = 0 counterToCheckIndent = 0 numberLine = 0 numberLineInFile = 0 emptyClassInfo = {} emptyClassInfoCheck = {} basicIndentation = None classDefined = r"\s*class\s+(\w+)" detectClass = r"\s*class\s+\w+" recursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False ) basicIndentation = Padding.CheckBasicIndentation(self, recursFiles) for number in recursFiles: countRecursFiles += 1 with Bar("Correction ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLineInFile = 0 numberLine = 0 # -- Count all line(s) in file -- # with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLineInFile += 1 # -- Find empty class(es) in dict -- # with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLine += 1 if counterToCheckIndent == 1: spacesAfterClass = len(eachLine) - len(eachLine.lstrip()) counterToCheckIndent = 0 if spacesAfterClass == spacesClass: if search: emptyClassInfo[search.group(1)] = file numberLineInFile += 1 # Adding one line because padding will be added numberLine += 1 # Adding one line because padding will be added if re.match(detectClass, eachLine): spacesClass = len(eachLine) - len(eachLine.lstrip()) if numberLine == numberLineInFile: # If empty class in last line search = re.search(classDefined, eachLine) if search: emptyClassInfo[search.group(1)] = file else: counterToCheckIndent += 1 search = re.search(classDefined, eachLine) # -- Add padding in empty class(es) -- # numberLine = 0 with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: numberLine += 1 if counterToCheckIndent == 1: spacesAfterClass = len(eachLine) - len(eachLine.lstrip()) counterToCheckIndent = 0 if spacesAfterClass == spacesClass: paddingVar1 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) paddingVar2 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) finalVarPadding = "{} = '{}'\n".format(paddingVar1, paddingVar2) spacesClass = spacesClass + basicIndentation sys.stdout.write(textwrap.indent(finalVarPadding, self.simpleSpace * spacesClass)) numberLine += 1 sys.stdout.write(eachLine) if re.match(detectClass, eachLine): spacesClass = len(eachLine) - len(eachLine.lstrip()) if numberLine == numberLineInFile: # If empty class in last line paddingVar1 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) paddingVar2 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) finalVarPadding = "{} = '{}'\n".format(paddingVar1, paddingVar2) spacesClass = spacesClass + basicIndentation sys.stdout.write(textwrap.indent(finalVarPadding, self.simpleSpace * spacesClass)) else: counterToCheckIndent += 1 bar.next(1) bar.finish() # -- Check if class(es) is still empty -- # if emptyClassInfo != {}: with Bar("Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLineInFile = 0 numberLine = 0 with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLine += 1 if counterToCheckIndent == 1: spacesAfterClass = len(eachLine) - len(eachLine.lstrip()) counterToCheckIndent = 0 if spacesAfterClass == spacesClass: if search: emptyClassInfo[search.group(1)] = file numberLineInFile += 1 numberLine += 1 if re.match(detectClass, eachLine): spacesClass = len(eachLine) - len(eachLine.lstrip()) if numberLine == numberLineInFile: # If empty class in last line search = re.search(classDefined, eachLine) if search: emptyClassInfo[search.group(1)] = file else: counterToCheckIndent += 1 search = re.search(classDefined, eachLine) bar.next(1) bar.finish() if emptyClassInfoCheck == {}: for key, value in emptyClassInfo.items(): print("\n-> File : {}".format(value)) print("-> Padding added in : {} ( empty class )".format(key)) return 0 else: if verboseArg: print("\n[!] No padding added to empty class(es)... :\n") for key, value in emptyClassInfoCheck.items(): print("\n-> File : {}".format(value)) print("-> Class : {}".format(key)) return 1 else: print("[!] No empty class found in {}".format(outputArg)) return 0 def EmptyFunctions(self, outputArg, mixerLengthArg, verboseArg): countRecursFiles = 0 counterToCheckIndent = 0 numberLine = 0 numberLineInFile = 0 emptyFuncInfo = {} emptyFuncInfoCheck = {} basicIndentation = None functionDefined = r"\s*def\s+(\w+)" detectFunction = r"\s*def\s+\w+" recursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False ) basicIndentation = Padding.CheckBasicIndentation(self, recursFiles) for number in recursFiles: countRecursFiles += 1 with Bar("Correction ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLineInFile = 0 numberLine = 0 # -- Count all line(s) in file -- # with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLineInFile += 1 # -- Find empty function(s) in dict -- # with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLine += 1 if counterToCheckIndent == 1: spacesAfterFunc = len(eachLine) - len(eachLine.lstrip()) counterToCheckIndent = 0 if spacesAfterFunc == spacesFunc: if search: emptyFuncInfo[search.group(1)] = file numberLineInFile += 1 # Adding one line because padding will be added numberLine += 1 # Adding one line because padding will be added if re.match(detectFunction, eachLine): spacesFunc = len(eachLine) - len(eachLine.lstrip()) if numberLine == numberLineInFile: # If empty function last line search = re.search(functionDefined, eachLine) if search: emptyFuncInfo[search.group(1)] = file else: counterToCheckIndent += 1 search = re.search(functionDefined, eachLine) # -- Add padding in empty function(s) -- # numberLine = 0 with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: numberLine += 1 if counterToCheckIndent == 1: spacesAfterFunc = len(eachLine) - len(eachLine.lstrip()) counterToCheckIndent = 0 if spacesAfterFunc == spacesFunc: paddingVar1 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) paddingVar2 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) finalVarPadding = "{} = '{}'\n".format(paddingVar1, paddingVar2) spacesFunc = spacesFunc + basicIndentation sys.stdout.write(textwrap.indent(finalVarPadding, self.simpleSpace * spacesFunc)) numberLine += 1 sys.stdout.write(eachLine) if re.match(detectFunction, eachLine): spacesFunc = len(eachLine) - len(eachLine.lstrip()) if numberLine == numberLineInFile: # IIf empty function last line paddingVar1 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) paddingVar2 = self.mixer.GetStringMixer(mixerLengthArgDefined=mixerLengthArg) finalVarPadding = "{} = '{}'\n".format(paddingVar1, paddingVar2) spacesFunc = spacesFunc + basicIndentation sys.stdout.write(textwrap.indent(finalVarPadding, self.simpleSpace * spacesFunc)) else: counterToCheckIndent += 1 bar.next(1) bar.finish() # -- Check if function(s) is still empty -- # if emptyFuncInfo != {}: with Bar("Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLineInFile = 0 numberLine = 0 with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: numberLine += 1 if counterToCheckIndent == 1: spacesAfterFunc = len(eachLine) - len(eachLine.lstrip()) counterToCheckIndent = 0 if spacesAfterFunc == spacesFunc: if search: emptyFuncInfoCheck[search.group(1)] = file numberLineInFile += 1 numberLine += 1 if re.match(detectFunction, eachLine): spacesFunc = len(eachLine) - len(eachLine.lstrip()) if numberLine == numberLineInFile: # If empty function last line search = re.search(functionDefined, eachLine) if search: emptyFuncInfoCheck[search.group(1)] = file else: counterToCheckIndent += 1 search = re.search(functionDefined, eachLine) bar.next(1) bar.finish() if emptyFuncInfoCheck == {}: for key, value in emptyFuncInfo.items(): print("\n-> File : {}".format(value)) print("-> Padding added in : {} ( empty function )".format(key)) return 0 else: if verboseArg: print("\n[!] No padding added to empty function(s)... :\n") for key, value in emptyFuncInfoCheck.items(): print("\n-> File : {}".format(value)) print("-> Function : {}".format(key)) return 1 else: print("[!] No empty function found in {}".format(outputArg)) return 0
def __init__(self): self.mixer = Mixer() self.utils = Utils() self.pythonExcludeDefaultString = "exclude/string_to_string_mixed/exclude_word_do_not_modify.txt" self.pythonExcludeUserString = "exclude/string_to_string_mixed/exclude_word_by_user.txt" self.pythonExcludeUserFileName = "exclude/file_name/exclude_file_name_by_user.txt"
class Replace: def __init__(self): self.mixer = Mixer() self.remove = Remove() self.utils = Utils() self.pythonExcludeDefaultString = "exclude/string_to_string_mixed/exclude_word_do_not_modify.txt" self.pythonExcludeUserString = "exclude/string_to_string_mixed/exclude_word_by_user.txt" def EachLine(self, line="", dictionary={}, fileNameImport=False, listModuleImport=False): getIndexLineList = [] returnLine = [] charValue = [] checkCharAfterWord = 1 wordSetter = 0 checkGetKey = "" checkGetWord = "" getLine = "" breakLine = "" if listModuleImport == True: detectChars = r"\.|\:|\)|\(|\=|\[|\]|\{|\}|\,|\+|\s|\*|\-|\%|\/|\^|\'|\"" else: detectChars = r"\.|\:|\)|\(|\=|\[|\]|\{|\}|\,|\+|\s|\*|\-|\%|\/|\^" # -- Get list of all letters in line -- # for indexLine, letterLine in enumerate(line): getIndexLineList.append(letterLine) # -- Loop in each letter of line -- # for indexLine, letterLine in enumerate(line): # -- Add in final line list all chars mixed -- # if charValue != []: for obfIndex, obfValue in enumerate(charValue): if obfIndex == 0: # First letter in string mixed are already add in the final line continue returnLine.append(obfValue) charValue = [] # -- If the variable is only a letter, check if the next character is specific so as not to replace it -- # if re.match(detectChars, letterLine): returnLine.append(letterLine) # -- Count indexes of word to move after it --# countDeleteIndex = 0 for i in getWord: countDeleteIndex += 1 wordSetter = countDeleteIndex - 2 # -2 Is to letter already append and the letter in progress else: # -- The index numbers of variable is decremented to add the mixed letters that be replaced -- # if wordSetter > 0: wordSetter -= 1 continue else: try: # -- Loop in the dictionary with already mixed values-- # for key, value in dictionary: for indexKey, letterKey in enumerate(key): for letterValue in value: # -- Check if letter of word is equal to letter of key -- # if letterKey == letterLine: # -- Begin process to check -- # if indexKey == 0: indexExplore = indexLine + len(key) # Place index position after the word # -- If indexError return to next loop -- # try: getIndexLineList[indexExplore] except IndexError: continue # -- Check the char after and before the word -- # if re.match(detectChars, getIndexLineList[indexExplore]): indexExploreBefore = indexLine - 1 # Index check if word finded is not into the other word indexExploreAfter = indexLine + 2 # Index check char after the end string found with 'detectChars' regex try: if not re.match(r"\w|\\|\%", getIndexLineList[indexExploreBefore]): # -- Check if it's 'from' and 'import' file in line to avoid replace name of file if variable is identic name to file -- # getLine = "".join(getIndexLineList) if fileNameImport == False: if "import" in getLine: if "from" in getLine: # -- Cut the line from the current index and check if it is not there is the keyword "import" in the line -- # breakLine = getIndexLineList[:indexLine] breakLine = "".join(breakLine) if not "import" in breakLine: # -- It's file because only 'from'key word -- # checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 # -- Check if after char find by 'detectChars' variable it's not ' or " -- # elif re.match(r"\"|\'", getIndexLineList[indexExploreAfter]): if re.match(r"\[|\(|\{", getIndexLineList[indexExploreAfter - 1]): checkCharAfterWord = 0 else: checkCharAfterWord = 1 else: checkCharAfterWord = 0 # -- Only for [-rfn, --replacefilsname] feature -- # else: # -- check if file name is imported - # breakLine = getIndexLineList[:indexLine] breakLine = "".join(breakLine) # -- if file name is imported after 'import', the file name is not replaced -- # if "import" in breakLine: checkCharAfterWord = 1 else: checkCharAfterWord = 0 else: checkCharAfterWord = 1 except IndexError: checkCharAfterWord = 0 pass else: checkCharAfterWord = 1 if checkCharAfterWord == 0: # -- Initialize vars -- # getCharAllInKey = [] getWord = [] indexExploreStart = indexLine indexExploreEnd = indexLine + len(key) - 1 # Remove -1, first letter is already increment # -- List contain all letters of key -- # for getLetterKey in key: getCharAllInKey.append(getLetterKey) # -- Check if all letters of key is equal to all letters of word -- # for indexCheckLetter, checkLetter in enumerate(getIndexLineList): if indexCheckLetter >= indexExploreStart and indexCheckLetter <= indexExploreEnd: getWord.append(checkLetter) # -- Check if number of chars in key equal number of chars in word -- # if list(set(getCharAllInKey) - set(getWord)) == []: checkGetWord = "".join(getWord) checkGetKey = "".join(getCharAllInKey) # -- Check if key == word -- # if checkGetWord == checkGetKey: for obfChar in value: charValue.append(obfChar) letterLine = letterValue raise BreakLoop else: continue else: continue else: continue else: continue else: continue raise BreakLoop except BreakLoop: returnLine.append(letterLine) # -- Rewrite the line -- # returnLine = "".join(returnLine) return returnLine[:] def StringToString(self, outputArg=None, mixerLevelArg=None, verboseArg=None): variablesDict = {} classesDict = {} functionsDict = {} allDict = {} classFuncDict = {} checkWordsMixed = [] wordsExcludedUser = [] wordsExcludedUserFound = [] wordsExcludedDefault = [] wordsExcludedDefaultFound = [] checkAllWords = [] checkWordsError = [] checkKeyWordsMixed = [] checkCountWordsMixed = 0 checkCountWordsValue = 0 checkQuotePassing = 0 countRecursFiles = 0 # -- Catch all variable(s)/class(es)/function(s) name -- # functionsDefined = r"def\s+(\w+)" classDefined = r"class\s+(\w+)" variablesErrorDefined = r"except(\s+\w+\s+as\s+)(\w)" variablesLoopDefined = r"for\s+([\w\s\,]+)(\s+in\s+)" variablesDefined = r"(^[\s|a-zA-Z_]+[\,\s\w]{0,})+(\s*=\s*[\[|\{\(|\w+|\"|\'])" quotesIntoVariable = r".*={1}\s*[\"|\']{3}" quotesEndMultipleLines = r"^\s*[\"|\']{3}\)?\.?" quotesInRegex = r"={1}\s*r{1}[\"|\']{3}" recursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False ) for file in recursFiles: countRecursFiles += 1 print("\n[+] Running replacement of variables/classes/functions in {0} file(s), he can be long... you have time to make a coffee :)\n".format(countRecursFiles)) # -- Replace variables/classes/functions to random strings with length defined -- # with Bar(PROGRESS_COLOUR + "Setting up ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: # -- Variables -- # search = re.search(variablesDefined, eachLine) if search: if "," in search.group(1): modifySearch = search.group(1).replace(",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) i = i.strip() variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) modifySearch = search.group(1).strip() variablesDict[modifySearch] = mixer # -- Error variables -- # search = re.search(variablesErrorDefined, eachLine) if search: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) if search.group(2) not in variablesDict: variablesDict[search.group(2)] = mixer # -- Loop variables -- # search = re.search(variablesLoopDefined, eachLine) if search: if "," in search.group(1): modifySearch = search.group(1).replace(",", " ") modifySearch = modifySearch.split() for i in modifySearch: if i not in variablesDict: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) variablesDict[i] = mixer else: if search.group(1) not in variablesDict: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) variablesDict[search.group(1)] = mixer # -- Function(s) -- # search = re.search(functionsDefined, eachLine) if search: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) if search.group(1) not in functionsDict: if not "__init__" in search.group(1): functionsDict[search.group(1)] = mixer # -- Class(es) -- # search = re.search(classDefined, eachLine) if search: mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) if search.group(1) not in classesDict: classesDict[search.group(1)] = mixer bar.next(1) # -- Remove excluded variables/classes/functions defined from 'exclude/string_to_string_mixed/exclude_word_do_not_modify.txt' -- # if os.path.exists(self.pythonExcludeDefaultString) == True: with open(self.pythonExcludeDefaultString, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcludedDefault.append(word) else: print(ERROR_COLOUR + "[-] '{0}' file not found\n".format(self.pythonExcludeDefaultString)) # -- Remove excluded variables/classes/functions defined from 'exclude/string_to_string_mixed/exclude_word_by_user.txt' -- # if os.path.exists(self.pythonExcludeUserString) == True: with open(self.pythonExcludeUserString, "r") as readFile: for word in readFile: if "#" in word or word == "\n": continue else: word = word.rstrip() wordsExcludedUser.append(word) else: print(ERROR_COLOUR + "[-] '{0}' file not found\n".format(self.pythonExcludeUserString)) for word in wordsExcludedUser: for key in variablesDict.keys(): if word in key: if re.match(r"^" + re.escape(word) + r"$", key): wordsExcludedUserFound.append(word) for key in classesDict.keys(): if word in key: if re.match(r"^" + re.escape(word) + r"$", key): wordsExcludedUserFound.append(word) for key in functionsDict.keys(): if word in key: if re.match(r"^" + re.escape(word) + r"$", key): wordsExcludedUserFound.append(word) for word in wordsExcludedDefault: for key in variablesDict.keys(): if word in key: if re.match(r"^" + re.escape(word) + r"$", key): wordsExcludedDefaultFound.append(word) for key in classesDict.keys(): if word in key: if re.match(r"^" + re.escape(word) + r"$", key): wordsExcludedDefaultFound.append(word) for key in functionsDict.keys(): if word in key: if re.match(r"^" + re.escape(word) + r"$", key): wordsExcludedDefaultFound.append(word) for word in wordsExcludedUserFound: if word in variablesDict.keys(): del variablesDict[word] if word in classesDict.keys(): del classesDict[word] if word in functionsDict.keys(): del functionsDict[word] for word in wordsExcludedDefaultFound: if word in variablesDict.keys(): del variablesDict[word] if word in classesDict.keys(): del classesDict[word] if word in functionsDict.keys(): del functionsDict[word] bar.finish() # -- Display variables/classes/functions found -- # if verboseArg: print("\n[+] Variable(s) found :\n") if variablesDict == {}: print("-> No result") else: for key, value in variablesDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Class(es) found :\n") if classesDict == {}: print("-> No result") else: for key, value in classesDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] Function(s) found :\n") if functionsDict == {}: print("-> No result") else: for key, value in functionsDict.items(): print("-> {0} : {1}".format(key, value)) print("\n[+] String excluded found in '{0}' that have been matched from '{1}' :\n".format(self.pythonExcludeUserString, outputArg)) if wordsExcludedUserFound == []: print("-> No result") else: for word in wordsExcludedUserFound: print("-> {0} : excluded".format(word)) print("\n[+] String excluded found in '{0}' that have been matched from '{1}' :\n".format(self.pythonExcludeDefaultString, outputArg)) if wordsExcludedDefaultFound == []: print("-> No result") else: for word in wordsExcludedDefaultFound: print("-> {0} : excluded".format(word)) print("") # -- Merge all dicts -- # allDict = self.utils.DictMerge(dict1=allDict, dict2=variablesDict) allDict = self.utils.DictMerge(dict1=allDict, dict2=functionsDict) allDict = self.utils.DictMerge(dict1=allDict, dict2=classesDict) classFuncDict = self.utils.DictMerge(dict1=classFuncDict, dict2=classesDict) classFuncDict = self.utils.DictMerge(dict1=classFuncDict, dict2=functionsDict) # -- Change variables/classes/functions to mixed values -- # with Bar(PROGRESS_COLOUR + "Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Replace variable(s) only -- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if not eachLine: continue else: if re.match(quotesIntoVariable, eachLine): if re.match(quotesInRegex, eachLine): sys.stdout.write(eachLine) else: checkQuotePassing += 1 eachLine = Replace.EachLine( self, line=eachLine, dictionary=allDict.items(), fileNameImport=False, listModuleImport=False ) sys.stdout.write(eachLine) continue elif re.match(quotesEndMultipleLines, eachLine): if re.match(quotesInRegex, eachLine): sys.stdout.write(eachLine) else: checkQuotePassing += 1 eachLine = Replace.EachLine( self, line=eachLine, dictionary=allDict.items(), fileNameImport=False, listModuleImport=False ) sys.stdout.write(eachLine) if checkQuotePassing == 2: checkQuotePassing = 0 continue if checkQuotePassing == 1: sys.stdout.write(eachLine) elif checkQuotePassing == 2: checkQuotePassing = 0 else: if re.match(r"\s*__all__\s*=\s*\[", eachLine): eachLine = Replace.EachLine( self, line=eachLine, dictionary=classFuncDict.items(), fileNameImport=False, listModuleImport=True ) sys.stdout.write(eachLine) else: eachLine = Replace.EachLine( self, line=eachLine, dictionary=allDict.items(), fileNameImport=False, listModuleImport=False ) sys.stdout.write(eachLine) bar.next(1) bar.finish() with Bar(PROGRESS_COLOUR + "Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Check if variables/classes/functions have been mixed -- # with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: for key, value in allDict.items(): if value in eachLine: if re.match(r"\w+" + re.escape(value) + r"\w+", eachLine): pass else: checkWordsMixed.append(value) checkKeyWordsMixed.append(key) bar.next(1) # -- Remove duplicated words -- # checkListWordsMixed = list(dict.fromkeys(checkWordsMixed)) checkKeyWordsMixed = list(dict.fromkeys(checkKeyWordsMixed)) for i in checkListWordsMixed: checkCountWordsMixed += 1 for i in allDict.values(): checkCountWordsValue += 1 bar.finish() if checkCountWordsMixed == checkCountWordsValue: print("\n-> {0} variable(s)/class(es)/function(s) replaced in {1} file(s)\n".format(checkCountWordsValue, countRecursFiles)) return EXIT_SUCCESS else: if verboseArg: for key in allDict.keys(): checkAllWords.append(key) checkWordsError = list(set(checkAllWords) - set(checkKeyWordsMixed)) print("\n[!] Word(s) that not been replaced, check if an error will appear when will launch your obfuscated code... :\n") if checkWordsError != []: for wordNoReplaced in checkWordsError: print("-> Word : {0}".format(wordNoReplaced)) return EXIT_FAILURE def StringsToHex(self, outputArg=None, mixerLevelArg=None, verboseArg=None): checkHexError = {} getLetterLineList = [] countRecursFiles = 0 checkPrint = 0 numberLine = 0 checkError = False hexLine = "" detectExecFunc = r"exec\(\w+\)" detectQuotes = r"\'{3}|\"{3}" recursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False ) for number in recursFiles: countRecursFiles += 1 print("\n[+] Running replace all strings to their hexadecimal value in {0} file(s)...\n".format(countRecursFiles)) # -- Replace all strings to their hexadecimal value -- # with Bar(PROGRESS_COLOUR + "Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: # -- Add a new first random line and move the old first line to the second line to avoid replacing it -- # checkPrint = 0 # initialize check print() func at the begining of each file with open(file, "r") as inputFile: stringRandomMixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) firstLine = "{0}\n".format(stringRandomMixer) line = inputFile.readlines() line.insert(0, firstLine) with open(file, "w") as inputFile: inputFile.writelines(line) # -- Replace all lines-- # with fileinput.input(file, inplace=True) as inputFile: for eachLine in inputFile: if checkPrint == 0: varMixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) sys.stdout.write(varMixer + "=\"\"\"") checkPrint = 1 else: getLetterLineList = [] for letterLine in eachLine: letterToHex = "\\x" + str(letterLine.encode().hex()) getLetterLineList.append(letterToHex) # Get list of all letters in line hexLine = "".join(getLetterLineList) sys.stdout.write(hexLine) # -- Add exec funtions to interpret hex code in strings -- # with open(file, "a") as inputFile: inputFile.write("\"\"\"") inputFile.write("\nexec({0})".format(varMixer)) bar.next(1) bar.finish() with Bar(PROGRESS_COLOUR + "Check ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: numberLine = 0 # -- Check if all lines are replaced of hexadecimal value -- # with open(file, "r") as inputFile: for eachLine in inputFile: numberLine += 1 if not eachLine: continue else: if not "\\x" in eachLine: if re.match(detectQuotes, eachLine): continue elif re.match(detectExecFunc, eachLine): continue else: checkHexError[numberLine] = file checkError = True else: continue bar.next(1) bar.finish() if checkError == False: return EXIT_SUCCESS else: if verboseArg: print("\n[!] Line(s) that have not been replaced by their hexadecimal values... :\n") for key, value in checkHexError.items(): print("\n-> File : {0}".format(value)) print("-> Line : {0}".format(key)) else: print(ERROR_COLOUR + "\n[-] Line(s) that have not been replaced by their hexadecimal values") return EXIT_FAILURE def FilesName(self, outputArg=None, mixerLevelArg=None, verboseArg=None): checkFilesFoundCompare = {} filesNameDict = {} filesNameDictNoExt = {} filesNameFound = [] filesNameFoundNoExt = [] filesNameMixed = [] wordsExcluded = [] wordsExcludedFound = [] importNoCompliantFound = [] badNameDir = [] numberLine = 0 countRecursFiles = 0 checkCountRecursFiles = 0 unix = False win = False currentPosition = os.getcwd() detectImport = r"\s*from\s+|\s*import\s+" recursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile="__init__", dirOnly=False ) recursFilesWithInit = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile=False, dirOnly=False ) recursDirs = self.utils.CheckFileDir( output=outputArg, detectFiles="", blockDir="__pycache__", blockFile=False, dirOnly=True ) for file in recursFiles: countRecursFiles += 1 print("\n[+] Running replace files name in {0} file(s)...\n".format(countRecursFiles)) with Bar(PROGRESS_COLOUR + "Setting up ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for file in recursFiles: if "\"" in file: parseFilePath = file.split("\"") win = True else: parseFilePath = file.split("/") unix = True mixer = self.mixer.GetStringMixer(lenght=mixerLevelArg) filesNameDict[parseFilePath[-1]] = mixer + ".py" filesNameDictNoExt[parseFilePath[-1].replace(".py", "")] = mixer removeExt = parseFilePath[-1].replace(".py","") filesNameFound.append(parseFilePath[-1]) filesNameFoundNoExt.append(removeExt) filesNameMixed.append(mixer + ".py") # -- Check if directory have the same name for directory in recursDirs: for fileName in filesNameFoundNoExt: if re.match(r".*/{1}" + re.escape(fileName) + r"/{1}.*", directory): wordsExcluded.append(fileName) badNameDir.append(fileName) for word in wordsExcluded: for fileNameNoExt in filesNameFoundNoExt: if fileNameNoExt == word: wordsExcludedFound.append(word) filesNameFoundNoExt.remove(word) for fileName in filesNameFound: if fileName == word: filesNameFound.remove(word) if word in filesNameDictNoExt.keys(): del filesNameDictNoExt[word] word = word + ".py" if word in filesNameDict.keys(): del filesNameDict[word] # -- Check if file name in code is after 'import' native python function --# for file in recursFiles: with open(file, "r") as readFile: readF = readFile.readlines() for eachLine in readF: if re.match(detectImport, eachLine): searchFileName = re.search(r"(import\s+)(.*)", eachLine) if searchFileName.group(2): searchFileName = searchFileName.group(2).replace(",", "") searchFileName = searchFileName.split() for i in searchFileName: i = i.strip() for fileNameNoExt in filesNameFoundNoExt: if fileNameNoExt == i: importNoCompliantFound.append(i) filesNameFoundNoExt.remove(i) for fileName in filesNameFound: fileName = fileName.replace(".py", "") if fileName == i: i = i + ".py" filesNameFound.remove(i) if i in filesNameDictNoExt.keys(): del filesNameDictNoExt[i] i = i + ".py" if i in filesNameDict.keys(): del filesNameDict[i] bar.next(1) bar.finish() # -- Diplay all files found with their mixed values if verbose arg is actived -- # if verboseArg: print("\n[+] File(s) name found with their mixed values :\n") if filesNameDict == {}: print("-> No result") else: for key, value in filesNameDict.items(): print("-> {0} : {1}".format(key, value)) if importNoCompliantFound != []: print("\n[+] File(s) name no compliant for 'replace file name' feature :\n") for i in importNoCompliantFound: print("-> {0} : no compliant ( file name excluded automatically )".format(i)) if badNameDir != []: print("\n[!] Directory that have same name of python file(s) :\n") for i in badNameDir: print("-> {0} : no compliant ( file name has been excluded automatically)".format(i)) i = i.rstrip() print("") # -- Replace all files name to random strings with length defined -- # with Bar(PROGRESS_COLOUR + "Obfuscation ", fill="=", max=countRecursFiles, suffix="%(percent)d%%") as bar: for fileInCode in recursFilesWithInit: # -- Rename all files in python code -- # with fileinput.input(fileInCode, inplace=True) as inputFile: for eachLine in inputFile: if re.match(detectImport, eachLine): eachLine = Replace.EachLine( self, line=eachLine, dictionary=filesNameDictNoExt.items(), fileNameImport=True, listModuleImport=False ) sys.stdout.write(eachLine) continue else: sys.stdout.write(eachLine) bar.next(0.5) for file in recursFiles: # -- Rename all files in their directories -- # if "\"" in file: parseFilePath = file.split("\"") win = True else: parseFilePath = file.split("/") unix = True for key, value in filesNameDict.items(): if key == parseFilePath[-1]: parseFilePath.remove(parseFilePath[-1]) if unix == True: parseFilePathToMove = "/".join(parseFilePath) else: parseFilePathToMove = "\"".join(parseFilePath) os.chdir(parseFilePathToMove) # Move in directory to rename python file os.rename(key, value) else: continue os.chdir(currentPosition) bar.next(0.5) bar.finish() checkRecursFiles = self.utils.CheckFileDir( output=outputArg, detectFiles="py", blockDir="__pycache__", blockFile="__init__", dirOnly=False ) for file in checkRecursFiles: checkCountRecursFiles += 1 # -- Check if all files name are been replaced to random strings -- # with Bar(PROGRESS_COLOUR + "Check ", fill="=", max=checkCountRecursFiles, suffix="%(percent)d%%") as bar: for file in checkRecursFiles: numberLine = 0 # -- Check for file name in directory -- # for key, value in filesNameDict.items(): if key in file: checkFilesFoundCompare[key] = value bar.next(1) bar.finish() if checkFilesFoundCompare != {} : if verboseArg: if checkFilesFoundCompare != {}: print("\n[!] File name that have not been replaced by their random string value... :\n") for key, value in checkFilesFoundCompare.items(): print("\n-> File : {0}".format(key)) print("-> Value mixed : {0}".format(value)) else: print(ERROR_COLOUR + "\n[-] File name that have not been replaced by their random string value") return EXIT_FAILURE else: return EXIT_SUCCESS