Skip to content

Instantly share code, notes, and snippets.

@hugsy
Created March 17, 2019 20:03
Show Gist options
  • Save hugsy/d89c6ee771a4decfdf4f088998d60d19 to your computer and use it in GitHub Desktop.
Save hugsy/d89c6ee771a4decfdf4f088998d60d19 to your computer and use it in GitHub Desktop.

Revisions

  1. hugsy created this gist Mar 17, 2019.
    119 changes: 119 additions & 0 deletions AllocateLargePool.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    #include <windows.h>
    #include <stdio.h>

    #pragma comment(lib, "ntdll.lib")

    #define SystemBigPoolInformation 0x42
    #define ThreadNameInformation 0x26

    #define DATA_TO_COPY "AAAAAAAAAAAAABBBBBBBBBBBBBBBCCCCCCCCCCCCCCCDDDDDDDDDDDDDDD"


    typedef struct
    {
    WORD Length;
    WORD MaximumLength;
    DWORD Padding;
    DWORD64 Buffer;
    } UNICODE_STRING, *PUNICODE_STRING;

    typedef struct
    {
    DWORD64 Address;
    DWORD64 PoolSize;
    char PoolTag[4];
    char Padding[4];
    } BIG_POOL_INFO, *PBIG_POOL_INFO;


    extern NTSYSAPI NTSTATUS NTAPI NtSetInformationThread(
    IN HANDLE ThreadHandle,
    IN THREAD_INFORMATION_CLASS ThreadInformationClass,
    IN PVOID ThreadInformation,
    IN ULONG ThreadInformationLength
    );

    extern NTSYSAPI NTSTATUS NTAPI NtQueryInformationThread(
    IN HANDLE ThreadHandle,
    IN THREAD_INFORMATION_CLASS ThreadInformationClass,
    OUT PVOID ThreadInformation,
    IN ULONG ThreadInformationLength,
    OUT PULONG ReturnLength OPTIONAL );



    ULONG_PTR LookForThreadNamePoolAddress(PVOID pBuffer, DWORD64 dwExpectedSize)
    {
    ULONG_PTR StartAddress = (ULONG_PTR)pBuffer;
    ULONG_PTR EndAddress = StartAddress + 8 + *( (PDWORD)StartAddress ) * sizeof(BIG_POOL_INFO);
    ULONG_PTR ptr = StartAddress + 8;
    while (ptr < EndAddress)
    {
    PBIG_POOL_INFO info = (PBIG_POOL_INFO) ptr;
    //printf("Name:%s Size:%llx Address:%llx\n", info->PoolTag, info->PoolSize, info->Address);
    if( strncmp( info->PoolTag, "ThNm", 4)==0 && dwExpectedSize==info->PoolSize )
    {
    return (((ULONG_PTR)info->Address) & 0xfffffffffffffff0) + sizeof(UNICODE_STRING);
    }
    ptr += sizeof(BIG_POOL_INFO);
    }
    return 0;
    }


    ULONG_PTR AllocateInBigPool(HANDLE hThread, WORD wPoolSize, LPVOID lpContent)
    {
    UNICODE_STRING target;
    target.Length = wPoolSize;
    target.MaximumLength = 0xffff;
    target.Buffer=(ULONG_PTR)lpContent;
    ULONG_PTR Addr = 0;

    HRESULT hRes = NtSetInformationThread(hThread,ThreadNameInformation, &target, sizeof(UNICODE_STRING));
    if (SUCCEEDED(hRes))
    {
    DWORD dwBufSize = 1024*1024;
    DWORD dwOutSize;
    LPVOID pBuffer = LocalAlloc(LPTR, dwBufSize);

    hRes = NtQuerySystemInformation(SystemBigPoolInformation, pBuffer, dwBufSize, &dwOutSize);
    if (SUCCEEDED(hRes))
    {
    DWORD dwExpectedSize = target.Length + sizeof(UNICODE_STRING);
    Addr = LookForThreadNamePoolAddress(pBuffer, dwExpectedSize);
    }

    LocalFree(pBuffer);
    }

    return Addr;
    }


    int wmain(int argc, wchar_t** argv)
    {
    DWORD dwTid = _wtoi(argv[1]);
    DWORD dwSize = _wtoi(argv[2]);
    LPVOID lpData = VirtualAlloc(0, dwSize, MEM_COMMIT, PAGE_READWRITE);

    RtlZeroMemory(lpData, dwSize);
    RtlCopyMemory(lpData, DATA_TO_COPY, strlen(DATA_TO_COPY));


    HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, dwTid);
    if(!hThread)
    return -1;

    wprintf(L"[+] tid=%d\n", dwTid);

    ULONG_PTR PoolChunk = AllocateInBigPool(hThread, (WORD)dwSize, (LPVOID)lpData);
    if(PoolChunk)
    {
    wprintf(L"[+] data stored at %p\n", PoolChunk);
    }

    VirtualFree(lpData, dwSize, MEM_RELEASE);

    CloseHandle(hThread);
    return 0;
    }