Not By Me: Found On Other Website, I know Nothing About Scripting, I think this might Help Though.
!!!Not Sure If Still Works - Just Some Info For The Scriptors!!!
Defeating Punkbuster - by okidoki
Defeating PunkBuster
Here is a way to defeat punkbuster checks ( I used IDA Pro ).
First we need to find the "%c%c" or "%s NOT_FOUND" string in pbcl.dll:
.rdata:1005DADC aCC db '%c%c',0
.rdata:1005DACC aSNot_found db '%s NOT_FOUND',0
Then go to the DATA XREF:
Code:
.text:1002696E push offset aCC ; "%c%c"
.text:100269F1 push offset aSNot_found ; "%s NOT_FOUND"
Scroll up to the beginning of the function:
Code:
int __cdecl sub_100250E0(struct _MEMORY_BASIC_INFORMATION Buffer)
Now we can detour it:
Code:
typedef int ( *PBPerformCheck_t )( int iArg1, int iArg2, _MEMORY_BASIC_INFORMATION mbiArg3 );
PBPerformCheck_t pPBPerformCheck = 0;
int _PBPerformCheck( int iArg1, int iArg2, _MEMORY_BASIC_INFORMATION mbiArg3 )
{
return pPBPerformCheck( iArg1 , iArg2, mbiArg3 );
}
void Hook( )
{
DWORD dwPbclBase = ( DWORD )GetModuleHandle( "pbcl.dll" );
pPBPerformCheck = ( PBPerformCheck_t )DetourFunction( ( BYTE * )( dwPbclBase + 0x250E0 ), ( BYTE * )_PBPerformCheck, 6 );
}
Finally here is a method to filter/defeat the checks:
Code:
char *pszCheckString;
int _PBPerformCheck( int iArg1, int iArg2, _MEMORY_BASIC_INFORMATION mbiArg3 )
{
_asm mov pszCheckString, esi;
// if the pszCheckString's first char is |: Files white list check
// if the pszCheckString's first char is B: Cvar check
// if the pszCheckString's first char is N: MD5 check
// if the pszCheckString's first char is E: Key bind check
// Remove stuff
int iReturn = pPBPerformCheck( iArg1 , iArg2, mbiArg3 );
// Re-apply stuff
return iReturn;
}
The string also contains the names of the modules/cvars/path ... checked, and this code is 100% working for up to date FarCry 1.4 punkbuster client.
Happy filtering
Formatted Output Function - Roverturbo
Formatted Output Function
Here is PunkBuster's formated output function.
After hooking this function i found some interesting strings being passed, so here is the AAO reference incase you want to track it down/have a play about..
int __cdecl sub_10004BE0(char *,size_t,char *,char)
sub_10004BE0 proc near
arg_0= dword ptr 4
arg_4= dword ptr 8
arg_8= dword ptr 0Ch
arg_C= byte ptr 10h
mov ecx, [esp+arg_8]
push esi
mov esi, [esp+4+arg_4]
push edi
mov edi, [esp+8+arg_0]
lea eax, [esp+8+arg_C]
push eax ; va_list
push ecx ; char *
push esi ; size_t
push edi ; char *
call __vsnprintf
add esp, 10h
mov byte ptr [edi+esi-1], 0
pop edi
pop esi
retn
sub_10004BE0 endp
Screenshot Function Info
Screenshot Function Info
int sub_1002EAD0(int, int, int, byte)
** Routine is to big to post **
Now, if you hook this function and return 2 you will disable the screenshot feature on your client.. Also it's pretty common knowledge that they use ddraw to make the actual image and the call to that routine is located in the above function near the bottom.
Code:
1002F26F CALL 10018E60
The prototype for this is..
Code:
void 10018E60(void)
If you let the first function work correctly by returning the actual call to the real function, you can hook this instead with a empty void and you will create ddraw failed to initialize errors (Only the text portion of the screenshot is created).
Because i haven't posted the disassembled routines (to big) i will post a small straight to the point snippet hooking these two routines.. Notice the commented out return 2 that i mentioned above.
Code:
#include <windows.h>
#include <detours.h>
typedef INT (WINAPI *tSSRoutine)(INT, INT, INT, BYTE);
typedef VOID (WINAPI *tDDRoutine)(VOID);
tSSRoutine SSRoutine_;
tDDRoutine DDRoutine_;
INT _SSRoutine(INT, INT, INT, BYTE);
VOID _DDRoutine(VOID);
INT WINAPI DllMain(HMODULE Module, DWORD Reason, PVOID Reserved)
{
if(Reason == 1)
{
DWORD PB_SS = (DWORD)GetModuleHandle("pbcl.dll") + 0x2EAD0;
SSRoutine_ = (tSSRoutine)DetourFunction((PBYTE)PB_SS, (PBYTE)_SSRoutine);
DWORD PB_DD = (DWORD)GetModuleHandle("pbcl.dll") + 0x18E60;
DDRoutine_ = (tDDRoutine)DetourFunction((PBYTE)PB_DD, (PBYTE)_DDRoutine);
return 1;
}
return -1;
}
INT _SSRoutine(INT arg_0, INT arg_4, INT arg_8, BYTE arg_F14)
{
INT ReturnVal = SSRoutine_(arg_0, arg_4, arg_8, arg_F14);
return ReturnVal;
//return 2;
}
VOID _DDRoutine(VOID)
{
}
Anyway all this is just food for thought, there is alot more you can do when you study it proper. But how deep you go is upto you.
*DETECTED*Pre Sys Bypass
Pre Sys Bypass
this is before PB started loading its services and system files
int __cdecl npb_CompileHash( char* szFinal, int iSize, char* szWTF, char iAdd )
{
__asm
{
mov dwCurrentByte, esi; //current byte ( increment )
pushad;
mov ecx, [ ebp - 0x0DCC ];
mov dwCurrentScan, ecx; //address of the scan
popad;
}
if( dwCurrentScan == 0x943A3E ) //warrock player boxes cvar
{
if( dwCurrentByte == 0 )
{
_asm mov iAdd, 0; //cvar check
}
}
if( dwCurrentScan > dwD3D8 && dwCurrentByte < 7 ) //d3d8 dip scan
{
iAdd = ( char )dwDirectXBackup[ dwCurrentByte ];
//for DIP ( backup bytes to spoof the buffer )
}
return ppb_CompileHash( szFinal, iSize, szWTF, iAdd );
}
DWORD WINAPI dwPBWait( LPVOID )
{
CDetour pbcl_hash;
ppb_CompileHash = ( pb_CompileHash_t )pbcl_hash.Create( ( BYTE* )( ( dwPBCL ) + 0x3DFC ), ( BYTE* )npb_CompileHash, DETOUR_TYPE_PUSH_RET );
return 0;
}
it is detected and will result in a 1440 hardware ban, and a perm account ban in warrock but should work for older games, if you want to find the hashing information passed through these functions you can hook strlen or _vsnprintf, make sure to use returnaddress
key identifiers for hashes are generally, but not always start with "1_", they use it to hash d3d8 ( or d3d9 scans, as i found in BF2 before the update ) as well as game scans of sorts
I've heard this method is still undetected if you use SEH hooking
its very complicated in the inner-workings so i wont explain more then that, have fun
Clean Screenshots - by okidoki
Clean Screenshots ;)
Here is a way for returning clean PB screenshots.
First we have to find the DirectDrawCreate call in pbcl.dll ( I used IDA Pro ), it should look like that:
.text:1000C030 mov edx, [esp+560h+wndpl.rcNormalPosition.bottom]
.text:1000C034 mov ecx, [esp+560h+wndpl.rcNormalPosition.top]
.text:1000C038 push edi ; pUnkOuter
.text:1000C039 lea eax, [esp+564h+lpDD]
.text:1000C03D push eax ; lplpDD
.text:1000C03E sub edx, ecx
.text:1000C040 push edi ; lpGUID
.text:1000C041 mov [ebp+1Eh], dx
.text:1000C045 mov [esp+56Ch+var_534], edi
.text:1000C049 mov [esp+56Ch+lpDD], edi
.text:1000C04D call DirectDrawCreate
Then scroll up to the begining of the function that calls DirectDrawCreate, and find from where its called from:
Code:
.text:1000B920 ; int __stdcall sub_1000B920(int,int,__int16,__int16,int,char *hWnd,int)
Code:
.text:1000EDF2 push eax ; hWnd
.text:1000EDF3 push ecx ; int
.text:1000EDF4 mov ecx, [ebp+118h]
.text:1000EDFA push esi ; __int16
.text:1000EDFB push edi ; __int16
.text:1000EDFC push ebx ; int
.text:1000EDFD push edx ; int
.text:1000EDFE mov [esp+0AB4h+var_A84], 0B0h
.text:1000EE06 call sub_1000B920
Then scroll up to the beginning of the function:
Code:
.text:1000E030 ; int __fastcall sub_1000E030(int,int,int,int,unsigned int)
Now we can detour it:
Code:
typedef int ( *PBScreenshotSetup_t )( int iArg1 , int iArg2, int iArg3, int iArg4, unsigned int uiArg5 );
PBScreenshotSetup_t pPBScreenshotSetup = 0;
int _PBScreenshotSetup( int iArg1 , int iArg2, int iArg3, int iArg4, unsigned int uiArg5 )
{
int iReturn;
return pPBScreenshotSetup( iArg1 , iArg2, iArg3, iArg4, uiArg5 );
}
void Hook( )
{
DWORD dwPbclBase = ( DWORD )GetModuleHandle( "pbcl.dll" );
pPBScreenshotSetup = ( PBScreenshotSetup_t )DetourFunction( ( BYTE * )( dwPbclBase + 0xE030 ), ( BYTE * )_PBScreenshotSetup, 6 );
}
Now here is how to manage a clean screenshot using a modulo:
Code:
bool bSafeScreen = true;
int _PBScreenshotSetup( int iArg1 , int iArg2, int iArg3, int iArg4, unsigned int uiArg5 )
{
bSafeScreen = false;
static int iRequest = 0;
iRequest++;
int iReturn;
if( iRequest <= 1 )
iReturn = 2;
else
{
iReturn = 2;
if( iRequest % 16 == 1 )
{
iReturn = pPBScreenshotSetup( iArg1 , iArg2, iArg3, iArg4, uiArg5 );
bSafeScreen = true;
iRequest = 0;
}
}
return iReturn;
}
Usage:
if( bSafeScreen )
{
// Apply your visual modifications
}
You can pause the screenshot function less or more by changing the modulo value (16).
This code is 100% working for up to date FarCry 1.4 punkbuster client.
Might Make Another Post (Thanks This if it helped, I dont think it did but it mightve)