反惡意軟件掃描接口(AMSI)基礎知識——amsi是專門針對混淆繞過的無文件攻擊腳本,在Windows 10 和Windows Server 2016 之后才有的,然后並不是所有的殺毒軟件都可以調用amsi接口。國內的基本不可以!我暈!


反惡意軟件掃描接口(AMSI)對抗學習 獎勵
黑白天安全實驗室  2021-02-21 22:37:45 79207

Amsi(Antimalware Scan Interface)基礎知識

The Windows Antimalware Scan Interface (AMSI) is a versatile interface
standard that allows your applications and services to integrate with
any antimalware product that's present on a machine. AMSI provides
enhanced malware protection for your end-users and their data,
applications, and workloads.

AMSI is agnostic of antimalware vendor; it's designed to allow for the
most common malware scanning and protection techniques provided by
today's antimalware products that can be integrated into applications.
It supports a calling structure allowing for file and memory or stream
scanning, content source URL/IP reputation checks, and other
techniques.

AMSI also supports the notion of a session so that antimalware vendors
can correlate different scan requests. For instance, the different
fragments of a malicious payload can be associated to reach a more
informed decision, which would be much harder to reach just by looking
at those fragments in isolation.

從前面微軟的文檔中我們可以知道Windows防病毒掃描界面(AMSI)是一個通用的接口標准,是開放給防病毒產品調用的一個接口。
這個接口支持允許不單單可以用來掃描腳本、代碼、命令或者cmdlet,也可以用來掃描任何文件、內存或者數據流,如字符串、即時消息、圖像或者視頻等等

我認為這個Amsi(Antimalware Scan Interface)主要是針對腳本來說的,目前來說腳本逐漸成為針對性攻擊的武器,諸如JavaScript,VBScript和PowerShell之類的腳本為我們攻擊提供了巨大的好處。它們是系統合法的軟件,並且執行文件不落地在內存中加載。

腳本語言比exe等等Pe文件要好混淆,可以從遠端或注冊表加載執行,並且腳本的動態特性允許攻我們容易地逃避反惡意軟件和類似的端點防護產品的檢測與分析。並且執行文件可以不落地直接在內存中加載。

那么 Windows 10可以通過反惡意軟件掃描接口(AMSI)提供查殺腳本的功能,還可以以腳本解釋程序的相同方式查看腳本內容 ,這樣的話就可以未加密和未混淆的形式來查看我們的攻擊腳本。

目前在微軟的文檔中我們可以知道
AMSI功能已集成到Windows 10的這些組件中。

用戶帳戶控制或UAC(EXE,COM,MSI或ActiveX)
PowerShell(腳本,交互使用和動態代碼評估)
Windows腳本主機(wscript.exe和cscript.exe)
JavaScript和VBScript
Office VBA宏

看到網上有python amsi的gist:https://gist.github.com/masthoon/8ada1d19e6e217481aa881fab16b5970
AMSI Interface in Python
amsi.py
import sys
import windows
import windows.winproxy
import windows.generated_def as gdef

class AMSIProxy(windows.winproxy.ApiProxy):
    APIDLL = "Amsi"
    default_error_check = staticmethod(windows.winproxy.no_error_check)

"""
HRESULT WINAPI AmsiInitialize(
  _In_  LPCWSTR      appName,
/*_In_  DWORD        coInit, REMOVED */
  _Out_ HAMSICONTEXT *amsiContext
);
"""
AmsiInitializePrototype = gdef.WINFUNCTYPE(gdef.BOOL, gdef.LPCWSTR, gdef.POINTER(gdef.PVOID))
AmsiInitializeParams = ((1, 'appName'),(1, 'amsiContext'))

@AMSIProxy('AmsiInitialize', deffunc_module=sys.modules[__name__])
def AmsiInitialize(appName, amsiContext):
    return AmsiInitialize.ctypes_function(appName, amsiContext)


"""
HRESULT WINAPI AmsiOpenSession(
  _In_  HAMSICONTEXT amsiContext,
  _Out_ HAMSISESSION *session
);
"""
AmsiOpenSessionPrototype = gdef.WINFUNCTYPE(gdef.BOOL, gdef.PVOID, gdef.POINTER(gdef.PVOID))
AmsiOpenSessionParams = ((1, 'amsiContext'),(1, 'session'))

@AMSIProxy('AmsiOpenSession', deffunc_module=sys.modules[__name__])
def AmsiOpenSession(amsiContext, session):
    return AmsiOpenSession.ctypes_function(amsiContext, session)


"""
HRESULT WINAPI AmsiScanBuffer(
  _In_     HAMSICONTEXT amsiContext,
  _In_     PVOID        buffer,
  _In_     ULONG        length,
  _In_     LPCWSTR      contentName,
  _In_opt_ HAMSISESSION session,
  _Out_    AMSI_RESULT  *result
);
"""
AmsiScanBufferPrototype = gdef.WINFUNCTYPE(gdef.BOOL, gdef.PVOID, gdef.PVOID, gdef.ULONG, gdef.LPCWSTR, gdef.PVOID, gdef.POINTER(gdef.ULONG))
AmsiScanBufferParams = ((1, 'amsiContext'),(1, 'buffer'),(1, 'length'),(1, 'contentName'),(1, 'session'),(1, 'result'))

@AMSIProxy('AmsiScanBuffer', deffunc_module=sys.modules[__name__])
def AmsiScanBuffer(amsiContext, buffer, length, contentName, session, result):
    return AmsiScanBuffer.ctypes_function(amsiContext, buffer, length, contentName, session, result)

"""
typedef 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
} AMSI_RESULT;
BOOL AmsiResultIsMalware(
  _In_ AMSI_RESULT r
);
"""

AMSI_RESULT_CLEAN = gdef.EnumValue("_AMSI_RESULT", "AMSI_RESULT_CLEAN", 0x0)
AMSI_RESULT_NOT_DETECTED = gdef.EnumValue("_AMSI_RESULT", "AMSI_RESULT_NOT_DETECTED", 0x1)
AMSI_RESULT_BLOCKED_BY_ADMIN_START = gdef.EnumValue("_AMSI_RESULT", "AMSI_RESULT_BLOCKED_BY_ADMIN_START", 16384)
AMSI_RESULT_BLOCKED_BY_ADMIN_END = gdef.EnumValue("_AMSI_RESULT", "AMSI_RESULT_BLOCKED_BY_ADMIN_END", 20479)
AMSI_RESULT_DETECTED = gdef.EnumValue("_AMSI_RESULT", "AMSI_RESULT_DETECTED", 32768)
class _AMSI_RESULT(gdef.EnumType):
    values = [AMSI_RESULT_CLEAN, AMSI_RESULT_NOT_DETECTED, AMSI_RESULT_BLOCKED_BY_ADMIN_START, AMSI_RESULT_BLOCKED_BY_ADMIN_END, AMSI_RESULT_DETECTED]
    mapper = {x:x for x in values}
AMSI_RESULT = _AMSI_RESULT


class AMSIScanner(object):
    def __enter__(self):
        self.context = gdef.PVOID()
        self.session = gdef.PVOID()

        if AmsiInitialize("TestEngine", self.context) != 0:
            print("AmsiInitialize failed!")

        if AmsiOpenSession(self.context, self.session) != 0:
            print("AmsiOpenSession failed!")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass # TODO release the AMSI engine

    def scan(self, buffer):
        result = AMSI_RESULT()
        AmsiScanBuffer(self.context, buffer, len(buffer), "fakefile.bin", self.session, result)
        return result


if __name__ == '__main__':
    with AMSIScanner() as scanner:
        print("Scanning ABC:")
        res = scanner.scan('ABC')
        print("\t{}".format(res))
        print("Scanning EICAR:")
        res = scanner.scan('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*')
        print("\t{}".format(res))

  也有人實現了python的amsi接口調用:

amsi.py
#!/usr/bin/env python3

#> ------------------------------------

#       Antimalware Scan Interface

#> ------------------------------------

import sys
from enum import IntEnum
from ctypes import HRESULT, POINTER, windll, byref
from ctypes.wintypes import HANDLE, LPCWSTR, UINT, LPCSTR
from comtypes.hresult import S_OK


#> ------------------------------------------------------------------------------
#   The AMSI_RESULT enumeration specifies the types of results returned by scans
#> ------------------------------------------------------------------------------
"""
    typedef enum AMSI_RESULT {
        AMSI_RESULT_CLEAN,
        AMSI_RESULT_NOT_DETECTED,
        AMSI_RESULT_BLOCKED_BY_ADMIN_START,
        AMSI_RESULT_BLOCKED_BY_ADMIN_END,
        AMSI_RESULT_DETECTED
    } ;
"""
class AMSI_RESULT(IntEnum):
    """ AMSI Results Class """
    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



class Amsi(object):
    """ AMSI API Class """

    def __init__(self):
        # Inialize the context and session to utilize
        self.amsi_ctx     = self.amsi_initialize()
        self.amsi_session = self.amsi_open_session()


    #> -------------------------
    #   Initialize the AMSI API
    #> -------------------------
    """
        HRESULT AmsiInitialize(
            LPCWSTR      appName,
            HAMSICONTEXT *amsiContext
        );
    """
    def amsi_initialize(self):
        AmsiInitialize          = windll.amsi.AmsiInitialize
        AmsiInitialize.argtypes = [LPCWSTR, POINTER(HANDLE)]  # Specify the argument data types
        AmsiInitialize.restype  = HRESULT

        amsi_ctx  = HANDLE(0)  # Return this context
        amsi_hres = AmsiInitialize("amsi-test", byref(amsi_ctx))

        # If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code
        if amsi_hres != S_OK:
            print(f"[!]\tAmsiInitialize Error: {amsi_hres}")
            sys.exit()  # Exit if initialization fails

        return amsi_ctx


    #> ----------------------------------------------------------------------------------
    #   Remove the instance of the AMSI API that was originally opened by AmsiInitialize
    #> ----------------------------------------------------------------------------------
    """
        void AmsiUninitialize(
            HAMSICONTEXT amsiContext
        );
    """
    def amsi_uninitialize(self):
        AmsiUninitialize          = windll.amsi.AmsiUninitialize
        AmsiUninitialize.argtypes = [HANDLE]
        AmsiUninitialize(self.amsi_ctx)

        return None


    #> -----------------------------------------------------------------------
    #   Opens a session within which multiple scan requests can be correlated
    #> -----------------------------------------------------------------------
    """
        HRESULT AmsiOpenSession(
            HAMSICONTEXT amsiContext,
            HAMSISESSION *amsiSession
        );
    """
    def amsi_open_session(self):
        AmsiOpenSession          = windll.amsi.AmsiOpenSession
        AmsiOpenSession.argtypes = [HANDLE, POINTER(UINT)]  # Specify attribute data types
        AmsiOpenSession.restype  = HRESULT

        amsi_session = UINT(0)  # Return this session
        amsi_hres    = AmsiOpenSession(self.amsi_ctx, amsi_session)

        # If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code
        if amsi_hres != S_OK:
            print(f"[!]\tAmsiOpenSession Error: {amsi_hres}")
            sys.exit()  # Exit if session creation fails

        return amsi_session


    #> ----------------------------------------------------
    #   Close a session that was opened by AmsiOpenSession
    #> ----------------------------------------------------
    """
        void AmsiCloseSession(
            HAMSICONTEXT amsiContext,
            HAMSISESSION amsiSession
        );
    """
    def amsi_close_session(self):
        AmsiCloseSession          = windll.amsi.AmsiCloseSession
        AmsiCloseSession.argtypes = [HANDLE, UINT]  # Specify attribute data types
        AmsiCloseSession.restype  = HRESULT

        amsi_hres = AmsiCloseSession(self.amsi_ctx, self.amsi_session)

        return None


    #> ----------------------------
    #   Scans a string for malware
    #> ----------------------------
    """
        HRESULT AmsiScanString(
            HAMSICONTEXT amsiContext,
            LPCWSTR      string,
            LPCWSTR      contentName,
            HAMSISESSION amsiSession,
            AMSI_RESULT  *result
        );
    """
    def amsi_scan_string(self, data):
        AmsiScanString          = windll.amsi.AmsiScanString
        AmsiScanString.argtypes = [HANDLE, LPCWSTR, LPCWSTR, UINT, POINTER(UINT)]  # Specify attribute data types
        AmsiScanString.restype  = HRESULT

        amsi_res  = UINT(0)  # Return this scan result
        amsi_hres = AmsiScanString(self.amsi_ctx, data, "string-data", self.amsi_session, byref(amsi_res))

        # If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code
        if amsi_hres != S_OK:
            print(f"[!]\tAmsiScanString Error: {amsi_hres}")
            sys.exit()  # Exit if scan fails

        return amsi_res


    #> --------------------------------------------
    #   Scans a buffer-full of content for malware
    #> --------------------------------------------
    """
        HRESULT AmsiScanBuffer(
            HAMSICONTEXT amsiContext,
            PVOID        buffer,
            ULONG        length,
            LPCWSTR      contentName,
            HAMSISESSION amsiSession,
            AMSI_RESULT  *result
        );
    """
    def amsi_scan_buffer(self, data):
        AmsiScanBuffer          = windll.amsi.AmsiScanBuffer
        AmsiScanBuffer.argtypes = [HANDLE, LPCSTR, UINT, LPCWSTR, UINT, POINTER(UINT)]  # Specify attribute data types
        AmsiScanBuffer.restype  = HRESULT

        amsi_res  = UINT(0)  # Return this scan result
        amsi_hres = AmsiScanBuffer(self.amsi_ctx, data, len(data), "buffer-data", self.amsi_session, byref(amsi_res))

        # If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code
        if amsi_hres != S_OK:
            print(f"[!]\tAmsiScanBuffer Error: {amsi_hres}")
            sys.exit()  # Exit if scan fails

        return amsi_res


    #> ---------------------------------------------------------------------------------
    #   Determines if the result of a scan indicates that the content should be blocked
    #> ---------------------------------------------------------------------------------
    """
        void AmsiResultIsMalware(
            r
        );
    """
    def amsi_result_is_malware(self, amsi_res):
        # List of potential detection result codes
        AMSI_RESULTS = {
            AMSI_RESULT.AMSI_RESULT_BLOCKED_BY_ADMIN_END:   'BLOCKED_BY_ADMIN_END',
            AMSI_RESULT.AMSI_RESULT_BLOCKED_BY_ADMIN_START: 'BLOCKED_BY_ADMIN_START',
            AMSI_RESULT.AMSI_RESULT_DETECTED:               'DETECTED'
        }

        if amsi_res.value in AMSI_RESULTS.keys():
            return True

        else:
            return False

  

 

Amsi(Antimalware Scan Interface)的工作流程。

As an application developer, you can actively participate in malware

  1. Specifically, you can help protect your customers from

  2. script-based malware, and from non-traditional avenues of

cyberattack.

By way of an example, let's say that your application is scriptable:
it accepts arbitrary script, and executes it via a scripting engine.
At the point when a script is ready to be supplied to the scripting
engine, your application can call the Windows AMSI APIs to request a
scan of the content. That way, you can safely determine whether or not
the script is malicious before you decide to go ahead and execute it.

This is true even if the script was generated at runtime. Script
(malicious or otherwise), might go through several passes of
de-obfuscation. But you ultimately need to supply the scripting engine
with plain, un-obfuscated code. And that's the point at which you
invoke the AMSI APIs.

從微軟的文檔中我們可以看到Amsi中的工作流程。
如果有一個應用程序接受任意腳本,並通過腳本引擎執行該腳本。
那么殺毒軟件可以調用amsi來查殺腳本。
可能有同學有疑問:殺毒軟件不是也能不靠amsi查殺腳本嗎?不不不 amsi的意義在於:無論我們的惡意腳本是經過多次模糊處理還是遠程執行amsi都可以在腳本注入內存前檢測到。而普通的靜態殺毒軟件是沒辦法的。

我們可以看微軟文檔給出的工作流程圖來理解:

請輸入圖片描述

其實不難理解,首先我們要知道我們的惡意腳本是如何注入內存執行的
bypass 殺毒軟件時我們的腳本一定是模糊處理的,但是無論我們什么樣模糊處理到注入內存執行的時候一定是純凈,清晰的代碼,不然腳本引擎無法理解和執行我們的惡意腳本。
那么問題就是在這里,amsi在腳本解密到注入內存之前去掃描查殺。這才是調用amsi的意義。

我們可以調用powershell來執行我們的惡意代碼來更好理解Amsi

AMSI的一個簡單測試是在PowerShell提示符–中鍵入AMSI旁路中常用的字符串amsiutils。如果端點安全產品支持AMSI,並且檢測到該字符串,那么PowerShell提示符將顯示錯誤,表明輸入的命令是惡意的。

1613918189_60326fed7bb4ed4b9008c.png!small?1613918189915

PS C:\Users\(123223Li)> amsiutils
所在位置 行:1 字符: 1
+ amsiutils
+ ~~~~~~~~~
此腳本包含惡意內容,已被你的防病毒軟件阻止。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ScriptContainedMaliciousContent

很好Amsi查殺並阻止了power shell執行命令。
我們來處理一下amsiutils,比如我們常用的base64加密和XOR編碼技術。

$bytes = [convert]::FromBase64String('YW1zaXV0aWxz') # YW1zaXV0aWxz為amsiutils的base64編碼 $string = -join ($bytes | % {[char] ($_ -bxor 0x33)}) #進行XOR編碼 iex $string #執行命令 

然后我們使用powershell ISE 執行來模擬我們在實戰中的無文件落地直接內存加載執行的手法

1613918180_60326fe4790c16ab764ef.png!small?1613918180846

毫不意外,amsi檢測到並攔截了powershell去執行我們的腳本。

我們可以使用下面命令來查看amsi中的查殺結果

Get-WinEvent 'microssoft-windows-windows defender/operational' | Where-Object id -EQ 1116 | format-list

1613918169_60326fd967d9843af1bd7.png!small?1613918169825

當然amsi也可以檢測vba和Java script
在實戰中,使用宏攻擊(釣魚)也是我們常用的手法,所以我們要知道amsi對宏文件的檢測流程

在微軟文檔中我們可以看到

The user receives a document containing a (malicious) macro, which
evades static antivirus software scans by employing techniques such as
obfuscation, password-protected files, or other. The user then opens
the document containing the (malicious) macro. If the document opens
in Protected View, then the user clicks Enable Editing to exit
Protected View. The user clicks Enable Macros to allow macros to run.
As the macro runs, the VBA runtime uses a circular buffer to log [1]
data and parameters related to calls to Win32, COM, and VBA APIs. When
specific Win32 or COM APIs that are considered high risk (also known
as triggers) [2] are observed, macro execution is halted, and the
contents of the circular buffer are passed to AMSI. The registered
AMSI anti-malware service provider responds with a verdict to indicate
whether or not the macro behavior is malicious. If the behavior is
non-malicious, then macro execution proceeds. Otherwise, if the
behavior is malicious, then Microsoft Office closes the session in
response to the alert [3], and the AV can quarantine the file.

微軟文檔中也給出了一個流程圖

請輸入圖片描述

通過閱讀理解微軟文檔我們可以知道amsi對宏的檢測查殺流程:

1.word等等釣魚文件加載宏
2.VBA宏運行時,運行時會有一個循環的緩沖區中記錄數據和參數調用Win32,COM, VBA等等api的情況。
3.amsi監控着緩沖區中的情況,一旦我們的宏調用了一些敏感的API或一些敏感的數據交互,就會觸發amsi的觸發器。
4.amsi停止宏執行並從循環緩沖區取出內容傳遞。
5.amsi從循環緩沖區取出內容傳遞給殺毒軟件。
6.殺毒軟件拿到數據后判斷宏是否為惡意的。
6.如果行為是無惡意的,那么宏可以執行。否則,關閉宏會話並發出響應警報和處理惡意文件。

我們可以看一個例子來理解amsi檢測查殺vba的流程:
跟powershell一樣我們也使用遠程加載powershell惡意代碼。這樣更貼近實戰。

1.使用cobat Strike生成我們的惡意代碼

1613918155_60326fcbb7a020b072baf.png!small?1613918156403

2.使用宏遠程加載我們的惡意代碼

#使用宏調用powershell遠程加載ps1
 Sub AutoOpen()
        Call Shell("powershell -Sta -Nop -Window Hidden -EncodedCommand shell")
End Sub

在沒有開amsi的情況下可以執行上線!

1613918146_60326fc2640886bdac4cb.png!small?1613918146879

在開了amsi的情況下無法執行了

1613918140_60326fbc7081f554464fe.png!small?1613918141067

 

amsi是所有殺毒軟件都可以調用嗎?並不是!

amsi是在Windows 10 和Windows Server 2016 之后才有的,然后並不是所有的殺毒軟件都可以調用amsi接口。國內的基本不可以哈哈哈。

在github上有一個項目記錄了可以調用amsi的殺毒軟件

https://github.com/subat0mik/whoamsi/wiki/Which-Endpoint-Protection-is-Using-AMSI%3F

殺軟對抗是一個動態對抗的過程,殺毒有新技術,免殺就有新手法。只有熟透殺軟才能更好免殺。

amsi解決的是遠程加載執行惡意腳本無文件落地的攻擊手法,過兩天看看跟大家學習一下bypass AMsi的手法。

我們學習了Antimalware Scan Interface(AMSI)的一些知識。作為滲透測試的我們了解殺軟是為了更好地進行免殺。

在對抗殺毒軟件的手法中,在大層面來說:

一就是破壞殺毒軟件,使其無法正常運行;
二是繞過殺毒軟件,使其無法檢測到。

從小的層面來說:

靜態免殺
動態免殺
沙盒對抗
等等

前面我們說到AMSI是windows開放的一個接口,注冊的殺毒軟件可以通過調用amsi接口來完成監控查殺。
既然是接口,那么我們是不是可以使殺毒軟件無法調用這個amsi接口來bypass?

首先我們得知道殺毒軟件是如何調用amsi的:

在微軟文檔中給出了2種調用amsi接口的方法

There are two ways in which you can interface with AMSI in your application.

By using the AMSI Win32 APIs. By using the AMSI COM interfaces.

分別是:
1.通過使用AMSI Win32 API

Functions that your application can call to request a scan. AMSI provides the following functions. 
#函數,應用程序可以通過調用amsi,amsi提供以下函數

Function #函數    Description #功能
AmsiCloseSession    Close a session that was opened by AmsiOpenSession.#關閉打開的會話
AmsiInitialize    Initialize the AMSI API.#初始化AMSI API。
AmsiOpenSession    Opens a session within which multiple scan requests can be correlated.#打開一個會話中關聯多個掃描請求。
AmsiResultIsMalware    Determines if the result of a scan indicates that the content should be blocked.#    確定掃描的結果表明,內容應該是屏蔽
AmsiScanBuffer    Scans a buffer-full of content for malware. #    掃描惡意軟件的緩沖區已滿的內容。
AmsiScanString    Scans a string for malware.#惡意軟件掃描一個字符串。
AmsiUninitialize    Remove the instance of the AMSI API that was originally opened by AmsiInitialize.#刪除的實例AMSI API,

其中每個函數的調用方法有興趣可以去微軟種查看。

https://docs.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-functions

2.通過使用AMSI COM接口

這個中調用的是IAmsiStream接口(amsi.h)代表一個流被掃描,微軟文檔中給出了示例,

https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-iamsistream-getattribute

Inheritance The IAmsiStream interface inherits from the IUnknown
interface. IAmsiStream also has these types of members:
 
Methods Methods The IAmsiStream interface has these methods.
 
METHODS Method    Description IAmsiStream::GetAttribute    Returns a
requested attribute from the stream. IAmsiStream::Read    Requests a
buffer-full of content to be read. Requirements REQUIREMENTS
            Minimum supported client    Windows 10 [desktop apps only] 
          Minimum supported server    Windows Server 2016 [desktop apps only] Target
Platform    Windows Header    amsi.h

然后上面我們知道了如何調用amsi,但是調用amsi還要注冊才能調用,所以我們也得看看amsi是如何注冊的:

As a creator of antimalware products, you can choose to author and
register your own in-process COM server (a DLL) to function as an AMSI

  1. That AMSI provider must implement the IAntimalwareProvider
    interface, and it must run in-process.

Note that, after Windows 10, version 1709 (the Fall 2017 Creators'
Update), your AMSI provider DLL may not work if it depends upon other
DLLs in its path to be loaded at the same time. To prevent DLL
hijacking, we recommend that your provider DLL load its dependencies
explicitly (with a full path) using secure LoadLibrary calls, or equivalent.
We recommend this instead of relying on the LoadLibrary search behavior.

The section below shows how to register your AMSI provider. For full
sample code showing how to author your own AMSI provider DLL, see the
IAntimalwareProvider interface sample application.

Register your provider DLL with AMSI To begin with, you need to ensure
that these Windows Registry keys exist.

HKLMSOFTWAREMicrosoftAMSIProviders HKLMSOFTWAREClassesCLSID An
AMSI provider is an in-process COM server. Consequently, it needs to
register itself with COM. COM classes are registered in
HKLMSOFTWAREClassesCLSID.

當然在微軟文檔中也給出了示例,但是我們是要做免殺,理解一些必要的東西就行。
在微軟的文檔中我們可以知道

Note that, after Windows 10, version 1709 (the Fall 2017 Creators'
Update), your AMSI provider DLL may not work if it depends upon other
DLLs in its path to be loaded at the same time. To prevent DLL
hijacking, we recommend that your provider DLL load its dependencies
explicitly (with a full path) using secure LoadLibrary calls, orequivalent.
We recommend this instead of relying on the LoadLibrarysearch behavior.search behavior.

微軟中說:

1613918109_60326f9de9dd51c727742.png!small?1613918110354

也就是說存在dll劫持的例子。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM