Hey all,
Punkbuster have changed their screenshot routine a few months back (I think), they are no longer using GetForegroundWindow() so the older methods don't work. To fix this, I hook the api function GetWindowThreadProcessId by modifing the IAT of the PBCL module and redirecting the function to our own. Then, we return null to get a blank. Tested on COD2/COD4, worked fine. Code below:
Code:
#include <windows.h>
#include <stdio.h>
// credits to osGB writers / temp2 for highlighting the func
DWORD xx IATHook(charxx DllWhichImports, charxx DllImportsFrom, charxx OldFunctionName)
{
DWORD dwIndex;
DWORD dwOffset;
HMODULE hDllWhichImports;
PIMAGE_DATA_DIRECTORY pDataDirectory;
PIMAGE_DOS_HEADER pDosHeader;
PDWORD pdwIAT;
PDWORD pdwINT;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_IMPORT_BY_NAME pImportName;
PIMAGE_OPTIONAL_HEADER pOptionalHeader;
PIMAGE_NT_HEADERS pPeHeader;
PSTR strCurrent;
hDllWhichImports = GetModuleHandleA(DllWhichImports);
if(!hDllWhichImports) return NULL;
pDosHeader = PIMAGE_DOS_HEADER(hDllWhichImports);
dwOffset = pDosHeader->e_lfanew;
pPeHeader = PIMAGE_NT_HEADERS(long(hDllWhichImports) + dwOffset);
pOptionalHeader = &pPeHeader->OptionalHeader;
pDataDirectory = pOptionalHeader->DataDirectory;
dwOffset = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
pImportDescriptor = PIMAGE_IMPORT_DESCRIPTOR(long(hDllWhichImports) + dwOffset);
for(dwIndex = 0; true; dwIndex++)
{
dwOffset = pImportDescriptor[dwIndex].Name;
if (!dwOffset) return NULL;
strCurrent = PSTR(long(hDllWhichImports) + dwOffset);
if(stricmp(strCurrent, DllImportsFrom) == 0) break;
}
dwOffset = pImportDescriptor[dwIndex].FirstThunk;
pdwIAT = PDWORD(long(hDllWhichImports) + dwOffset);
dwOffset = pImportDescriptor[dwIndex].OriginalFirstThunk;
pdwINT = PDWORD(long(hDllWhichImports) + dwOffset);
for(dwIndex = 0; true; dwIndex++)
{
dwOffset = pdwINT[dwIndex];
if (!dwOffset) return NULL;
pImportName = PIMAGE_IMPORT_BY_NAME(long(hDllWhichImports) + dwOffset);
strCurrent = PSTR(pImportName->Name);
if(stricmp(strCurrent, OldFunctionName) == 0)
{
return &pdwIAT[dwIndex];
}
}
return NULL;
}
/xx Our cloned func, we direct the calls to this and return null for blankies xx/
DWORD MyGetWindowThreadProcessId(HWND hWnd,LPDWORD lpdwProcessId)
{
return NULL;
}
/xx DLL Main, Hook is performed here... xx/
BOOL APIENTRY DllMain(HMODULE hDll, DWORD dwReason, PVOID lpReserved)
{
if(dwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hDll);
DWORD dwBackup;
DWORD dwOffset;
DWORD xxdwAddress = IATHook("pbcl.dll", "user32.dll", "GetWindowThreadProcessId");
if (dwAddress)
{
VirtualProtect(dwAddress, sizeof(DWORD), PAGE_READWRITE, &dwBackup);
xxdwAddress = PtrToUlong((DWORD)&MyGetWindowThreadProcessId);
VirtualProtect(dwAddress, sizeof(DWORD), dwBackup, &dwOffset);
dwAddress = NULL;
}
}
return 0x1;
}