La idea es simple, hacer una copia de la función GetProcAddress de winapi solo con código nativo para así poder extraer la shellcode completamente funcional desde la sección .text del binario.
Con esto nos saltaremos el hook del EDR en esta función.

Código de GetProcAddress:

Código: Seleccionar todo

FARPROC _GetProcAddress(HMODULE hModule, LPCSTR lpProcName, unsigned short lpProcNameSize)
{
    if (!hModule || !lpProcName) return 0;

    PIMAGE_DOS_HEADER dosHeader = NULL;
    PIMAGE_NT_HEADERS ntHeaders = NULL;
    PIMAGE_EXPORT_DIRECTORY exportDirectory = NULL;
    PDWORD functionsAddr = NULL;
    PWORD ordinalsAddr = NULL;
    PDWORD namesAddr = NULL;

    dosHeader = (PIMAGE_DOS_HEADER)hModule;
    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;
    ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + dosHeader->e_lfanew);
    if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) return 0;
    exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hModule + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

    functionsAddr = (PDWORD)((BYTE*)hModule + exportDirectory->AddressOfFunctions);
    ordinalsAddr = (PWORD)((BYTE*)hModule + exportDirectory->AddressOfNameOrdinals);
    namesAddr = (PDWORD)((BYTE*)hModule + exportDirectory->AddressOfNames);

    for (DWORD i = 0; i < exportDirectory->NumberOfNames; ++i)
    {
        unsigned short j = 0;

        for (j = 0; j < lpProcNameSize; j++)
        {
            if (lpProcName[j] != ((CONST PCHAR)hModule + namesAddr[i])[j]) break;
            j++;
        }

        if (j == lpProcNameSize)
            return (FARPROC)((BYTE*)hModule + functionsAddr[ordinalsAddr[i]]);
    }
    return 0;
}[/i]

Para extraer el código ensamblador generado por el compilador basta con ver el Raw Address y Raw Size de la sección .text, ir a cualquier editor de hex y copiar ese fragmento como array de C.

Para probar que funcione la shellcode:

Código: Seleccionar todo

#include <iostream>
#include <Windows.h>

unsigned char shellcode[512] = { 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x20, 0x56, 0x83, 0x7D, 0x08, 0x00, 0x74, 0x06, 0x83, 0x7D, 0x0C, 0x00, 0x75, 0x07, 0x33, 0xC0, 0xE9, 0x3A, 0x01, 0x00, 0x00, 0xC7, 0x45, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x45, 0x08, 0x89, 0x45, 0xF0, 0x8B, 0x4D, 0xF0, 0x0F, 0xB7, 0x11, 0x81, 0xFA, 0x4D, 0x5A, 0x00, 0x00, 0x74, 0x07, 0x33, 0xC0, 0xE9, 0xF5, 0x00, 0x00, 0x00, 0x8B, 0x45, 0xF0, 0x8B, 0x4D, 0x08, 0x03, 0x48, 0x3C, 0x89, 0x4D, 0xEC, 0x8B, 0x55, 0xEC, 0x81, 0x3A, 0x50, 0x45, 0x00, 0x00, 0x74, 0x07, 0x33, 0xC0, 0xE9, 0xD7, 0x00, 0x00, 0x00, 0xB8, 0x08, 0x00, 0x00, 0x00, 0x6B, 0xC8, 0x00, 0x8B, 0x55, 0xEC, 0x8B, 0x45, 0x08, 0x03, 0x44, 0x0A, 0x78, 0x89, 0x45, 0xF8, 0x8B, 0x4D, 0xF8, 0x8B, 0x55, 0x08, 0x03, 0x51, 0x1C, 0x89, 0x55, 0xE0, 0x8B, 0x45, 0xF8, 0x8B, 0x4D, 0x08, 0x03, 0x48, 0x24, 0x89, 0x4D, 0xE4, 0x8B, 0x55, 0xF8, 0x8B, 0x45, 0x08, 0x03, 0x42, 0x20, 0x89, 0x45, 0xE8, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x09, 0x8B, 0x4D, 0xF4, 0x83, 0xC1, 0x01, 0x89, 0x4D, 0xF4, 0x8B, 0x55, 0xF8, 0x8B, 0x45, 0xF4, 0x3B, 0x42, 0x18, 0x73, 0x7F, 0x33, 0xC9, 0x66, 0x89, 0x4D, 0xFC, 0x33, 0xD2, 0x66, 0x89, 0x55, 0xFC, 0xEB, 0x0C, 0x66, 0x8B, 0x45, 0xFC, 0x66, 0x83, 0xC0, 0x01, 0x66, 0x89, 0x45, 0xFC, 0x0F, 0xB7, 0x4D, 0xFC, 0x0F, 0xB7, 0x55, 0x10, 0x3B, 0xCA, 0x7D, 0x33, 0x0F, 0xB7, 0x45, 0xFC, 0x8B, 0x4D, 0x0C, 0x0F, 0xBE, 0x14, 0x01, 0x8B, 0x45, 0xF4, 0x8B, 0x4D, 0xE8, 0x8B, 0x75, 0x08, 0x03, 0x34, 0x81, 0x0F, 0xB7, 0x45, 0xFC, 0x0F, 0xBE, 0x0C, 0x06, 0x3B, 0xD1, 0x74, 0x02, 0xEB, 0x0E, 0x66, 0x8B, 0x55, 0xFC, 0x66, 0x83, 0xC2, 0x01, 0x66, 0x89, 0x55, 0xFC, 0xEB, 0xB5, 0x0F, 0xB7, 0x45, 0xFC, 0x0F, 0xB7, 0x4D, 0x10, 0x3B, 0xC1, 0x75, 0x15, 0x8B, 0x55, 0xF4, 0x8B, 0x45, 0xE4, 0x0F, 0xB7, 0x0C, 0x50, 0x8B, 0x55, 0xE0, 0x8B, 0x45, 0x08, 0x03, 0x04, 0x8A, 0xEB, 0x07, 0xE9, 0x6D, 0xFF, 0xFF, 0xFF, 0x33, 0xC0, 0x5E, 0x8B, 0xE5, 0x5D, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

typedef FARPROC(*PROC_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName, unsigned short lpProcNameSize);

int main()
{
    DWORD oldFlag = 0;
    VirtualProtect(shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldFlag);
    PROC_GetProcAddress _GetProcAddress = (PROC_GetProcAddress)(void*)shellcode;
    std::cout << std::hex << _GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDelayExecution", 16);
    getchar();
    return 0;
}
Imagen
Intentando revivir un poco esta sección.
Un apunte: en el array shellcode se puede prescindir de los bytes con valor 0 del final
Imagen
Responder

Volver a “C/C++”