Skip to content

Instantly share code, notes, and snippets.

@hugsy
Created March 17, 2019 20:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hugsy/d89c6ee771a4decfdf4f088998d60d19 to your computer and use it in GitHub Desktop.
Save hugsy/d89c6ee771a4decfdf4f088998d60d19 to your computer and use it in GitHub Desktop.
#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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment