Created
April 5, 2020 17:47
-
-
Save olealgoritme/e53f2e97d448caedbf55d93e8eddaf1d to your computer and use it in GitHub Desktop.
nvfbc
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
// from nvidia-patch hack | |
#include "pch.h" | |
#include "nvfbcdefs.h" | |
#ifdef _WIN64 | |
#define LIBNAME TEXT(".\\NvFBC64_.dll") | |
#else | |
#define LIBNAME TEXT(".\\NvFBC_.dll") | |
#endif | |
#define ENV_NVFBC_DUMPDIR TEXT("NVFBCWRP_DUMP_DIR") | |
#define ENV_NVFBC_PRIVDATA_FILE TEXT("NVFBCWRP_PRIVDATA_FILE") | |
#define NVFBC_PRIVDATA_DUMP_PREFIX TEXT("pd_") | |
extern "C" { | |
FARPROC ORIG_NvFBC_Create, ORIG_NvFBC_Enable, ORIG_NvFBC_GetSDKVersion, | |
ORIG_NvFBC_GetStatus, ORIG_NvFBC_GetStatusEx, ORIG_NvFBC_SetGlobalFlags, | |
ORIG_NvOptimusEnablement; | |
} | |
NvFBC_CreateFunctionExType ORIG_NvFBC_CreateEx; | |
// Default magic code which is passed as pPrivateData | |
// and enables NvFBC to work on GeForce | |
DWORD default_magic[] = { 0xAEF57AC5, 0x401D1A39, 0x1B856BBE, 0x9ED0CEBA }; | |
void* magic = default_magic; | |
NvU32 magic_size = sizeof(default_magic); | |
TCHAR* dumpPath = NULL; | |
TCHAR* getEnvVar(const TCHAR* name, DWORD size = MAX_PATH) { | |
TCHAR* buf = NULL; | |
try { | |
buf = new TCHAR[size]; | |
} | |
catch (std::bad_alloc&) { | |
return NULL; | |
} | |
DWORD ret = GetEnvironmentVariable(name, buf, size); | |
if (ret != 0 && size > ret) { | |
return buf; | |
} | |
else { | |
delete buf; | |
return NULL; | |
} | |
} | |
std::tuple<NvU32, void*> tryGetMagic() { | |
TCHAR* filename = getEnvVar(ENV_NVFBC_PRIVDATA_FILE); | |
if (!filename) { | |
return { 0, NULL }; | |
} | |
HANDLE hFile = INVALID_HANDLE_VALUE; | |
hFile = CreateFile(filename, | |
GENERIC_READ, | |
FILE_SHARE_READ, | |
NULL, | |
OPEN_EXISTING, | |
FILE_ATTRIBUTE_NORMAL, | |
NULL); | |
delete filename; | |
if (hFile == INVALID_HANDLE_VALUE) { | |
return { 0, NULL }; | |
} | |
LARGE_INTEGER size; | |
LARGE_INTEGER zero; | |
zero.QuadPart = 0; | |
if (!SetFilePointerEx(hFile, zero, &size, FILE_END)) { | |
CloseHandle(hFile); | |
return { 0, NULL }; | |
} | |
if (size.HighPart) { | |
CloseHandle(hFile); | |
return { 0, NULL }; | |
} | |
if (!SetFilePointerEx(hFile, zero, NULL, FILE_BEGIN)) { | |
CloseHandle(hFile); | |
return { 0, NULL }; | |
} | |
char* buf = NULL; | |
try { | |
buf = new char[size.LowPart]; | |
} | |
catch (std::bad_alloc&) | |
{ | |
CloseHandle(hFile); | |
return { 0, NULL }; | |
} | |
DWORD bytes_read = 0; | |
if (ReadFile(hFile, buf, size.LowPart, &bytes_read, NULL) && | |
bytes_read == size.LowPart) { | |
CloseHandle(hFile); | |
return { size.LowPart, buf }; | |
} | |
else { | |
CloseHandle(hFile); | |
delete buf; | |
return { 0, NULL }; | |
} | |
} | |
BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) | |
{ | |
HINSTANCE hL = 0; | |
if (reason == DLL_PROCESS_ATTACH) | |
{ | |
hL = LoadLibrary(LIBNAME); | |
if (!hL) return false; | |
// DllMain calls are serialized by system on process level, so we are clear | |
// to set required variables. | |
ORIG_NvFBC_Create = GetProcAddress(hL, "NvFBC_Create"); | |
if (!ORIG_NvFBC_Create) return false; | |
ORIG_NvFBC_CreateEx = (NvFBC_CreateFunctionExType)::GetProcAddress(hL, "NvFBC_CreateEx"); | |
if (!ORIG_NvFBC_CreateEx) return false; | |
ORIG_NvFBC_Enable = GetProcAddress(hL, "NvFBC_Enable"); | |
if (!ORIG_NvFBC_Enable) return false; | |
ORIG_NvFBC_GetSDKVersion = GetProcAddress(hL, "NvFBC_GetSDKVersion"); | |
if (!ORIG_NvFBC_GetSDKVersion) return false; | |
ORIG_NvFBC_GetStatus = GetProcAddress(hL, "NvFBC_GetStatus"); | |
if (!ORIG_NvFBC_GetStatus) return false; | |
ORIG_NvFBC_GetStatusEx = GetProcAddress(hL, "NvFBC_GetStatusEx"); | |
if (!ORIG_NvFBC_GetStatusEx) return false; | |
ORIG_NvFBC_SetGlobalFlags = GetProcAddress(hL, "NvFBC_SetGlobalFlags"); | |
if (!ORIG_NvFBC_SetGlobalFlags) return false; | |
ORIG_NvOptimusEnablement = GetProcAddress(hL, "NvOptimusEnablement"); | |
if (!ORIG_NvOptimusEnablement) return false; | |
// Check dump settings | |
if (TCHAR* dumpDirName = getEnvVar(ENV_NVFBC_DUMPDIR)) | |
{ | |
dumpPath = dumpDirName; | |
} | |
// Check external magic file | |
NvU32 new_magic_size; | |
void* new_magic; | |
std::tie(new_magic_size, new_magic) = tryGetMagic(); | |
if (new_magic) { | |
magic = new_magic; | |
magic_size = new_magic_size; | |
} | |
} | |
if (reason == DLL_PROCESS_DETACH && hL) | |
{ | |
FreeLibrary(hL); | |
if (dumpPath) { | |
delete dumpPath; | |
dumpPath = NULL; | |
} | |
if (magic != default_magic) { | |
delete magic; | |
magic = NULL; | |
} | |
return true; | |
} | |
return true; | |
} | |
void tryDumpPrivateData(NvU32 size, void* data) | |
{ | |
TCHAR szTmpFilename[MAX_PATH]; | |
if (dumpPath && GetTempFileName(dumpPath, NVFBC_PRIVDATA_DUMP_PREFIX, 0, szTmpFilename) != 0) { | |
// Privdata spying enabled and tempfile created. | |
// Attempt to dump private data. | |
HANDLE hTempFile = INVALID_HANDLE_VALUE; | |
hTempFile = CreateFile((LPTSTR)szTmpFilename, | |
GENERIC_WRITE, | |
0, | |
NULL, | |
CREATE_ALWAYS, | |
FILE_ATTRIBUTE_NORMAL, | |
NULL); | |
if (hTempFile != INVALID_HANDLE_VALUE) { | |
// File is open, dumping data. | |
WriteFile(hTempFile, data, size, NULL, NULL); | |
CloseHandle(hTempFile); | |
} | |
} | |
} | |
NVFBCRESULT NVFBCAPI PROXY_NvFBC_CreateEx(NvFBCCreateParams* params) { | |
if (params->dwPrivateDataSize == 0 && params->pPrivateData == NULL) { | |
//Backup old values | |
void* bkp_privdata = params->pPrivateData; | |
NvU32 bkp_privdatasize = params->dwPrivateDataSize; | |
// Inject private keys into structure | |
params->dwPrivateDataSize = magic_size; | |
params->pPrivateData = magic; | |
// Invoke original function | |
NVFBCRESULT res = ORIG_NvFBC_CreateEx(params); | |
// Rollback private data changes in params structure | |
params->pPrivateData = bkp_privdata; | |
params->dwPrivateDataSize = bkp_privdatasize; | |
return res; | |
} | |
else { | |
if (params->dwPrivateDataSize > 0 && params->pPrivateData != NULL) { | |
tryDumpPrivateData(params->dwPrivateDataSize, params->pPrivateData); | |
} | |
return ORIG_NvFBC_CreateEx((void*)params); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment