Created
March 17, 2019 20:03
-
-
Save hugsy/d89c6ee771a4decfdf4f088998d60d19 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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