gil
20th February 2006, 21:17
I released the final version public already, yes. However, I feel it is worth reposting this into the public forum. In this thread you'll be able to see how I came up with functions in the final version. Debate, and work togethor to see if you can recreate another version.
The final version can be found here:
http://www.unknowncheats.com/forum/downloads.php?do=file&id=55
==================================
Okay, new version of PB-Hack. Again, because I don't have a game to test on the outcome I don't know. However, I've made my own programs which do the same exact thing as PB - detect files. This works for it, so it should for pb as well.
Okay, here is the cool thing. Because there are no public D3D hooks available and I have a feeling most of you aren't exerpeinced with C++ enough to make your own. Well, using the method I'm releasing here should make them undetected by adding it to the source of the hack.
Theory: Punkbuster relies on Kernel32 API way to much, so I'm taking advantage of it as much as possible. The API, "Module32Next" is the victim in this version. Those of you who don't know anything about it, let me explain.
The function:
BOOL
WINAPI
Module32Next(
HANDLE hSnapshot,
LPMODULEENTRY32 lpme
);
#define Module32Next Module32NextW
What it does: In english, it basicly does what it sounds like, searches the next module in the processlist.
Parameters: The handle is obvious, its the process which you want the information from. Basicly, the parameter is set up like this:
HANDLE hModuleSnap = CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
The second parameter, "LPMODULEENTRY32" is more fun. What ever the return value for this function is can be used throughout a program to get the process information such as PID. However, it is more tricky. This is a full example of how to use it:
MODULEENTRY32 ptr32;
Module32Next(hModuleSnap, &ptr32);
Notice the "&" it is not there for fun!
What to use M32N for: Run through a list of running modules loaded in a process and retrieve the module information. PB uses this function to detect if a hack is loaded in the game, and such as a D3D hack. Remember the "invalid d3d8.dll" kick in the olden days? Well, that is from this function.
Intercepting the API:I use the same method I've used for every API interception I do. Get the module of which exported the API to Kernel32.dll, compare it to pbcl.dll. If it matches, patch the function with your own. (This is done in DllMain)
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID reserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
Log.WriteLogHeader();
Log.Log("Hooking Function...");
hDLL = hInst;
DisableThreadLibraryCalls(hInst);
GetModuleFileName(GetModuleHandle(NULL), cDLL, sizeof(cDLL));
PathStripPath(cDLL);
if (strcmp(cDLL, "pbcl.dll") == 0)
InterceptPBAPI(hInst, "kernel32.dll", "Module32Next", (DWORD)AnticheatAPIReplace);
Log.Log("Successfull");
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TlsFree((DWORD)hInst);
Log.Log("TrixnIce Unloaded");
}
return TRUE;
}
The Patch:Here is the part which replaces the code (yay!). First you have to know what you want to replace the function with. Should you return it FALSE? (Yes, Module32Next is a bool if you have forgotten ALREADY!) But if you do that, then any simple program can detect the function never succeded and use the function, "GetLastError()" and smack you with a, "No admin access" or, "Operation failed" alert. So here is my idea, why not let the function move along through the list of modules untill your module is up. Once that happens, smack it on the face with end of module list notification.
BOOL WINAPI AnticheatAPIReplace(LPSYSTEM_POWER_STATUS lpSystemPowerStatus)
{
DWORD dwPID = GetCurrentProcessId();
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 ptr32;
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}
ptr32.dwSize = sizeof(MODULEENTRY32);
if (strcmp(ptr32.szModule, "TrixnIce.dll") == 0)
return ERROR_NO_MORE_FILES;
CloseHandle(hModuleSnap);
return TRUE;
}
There you have it, the API is replaced and no harm has been done. The function will continue to run as normal through the files, and each time it comes to your module it will be alerted there are no more modules.
Thanks HockeyBuster & UC, great job.
The final version can be found here:
http://www.unknowncheats.com/forum/downloads.php?do=file&id=55
==================================
Okay, new version of PB-Hack. Again, because I don't have a game to test on the outcome I don't know. However, I've made my own programs which do the same exact thing as PB - detect files. This works for it, so it should for pb as well.
Okay, here is the cool thing. Because there are no public D3D hooks available and I have a feeling most of you aren't exerpeinced with C++ enough to make your own. Well, using the method I'm releasing here should make them undetected by adding it to the source of the hack.
Theory: Punkbuster relies on Kernel32 API way to much, so I'm taking advantage of it as much as possible. The API, "Module32Next" is the victim in this version. Those of you who don't know anything about it, let me explain.
The function:
BOOL
WINAPI
Module32Next(
HANDLE hSnapshot,
LPMODULEENTRY32 lpme
);
#define Module32Next Module32NextW
What it does: In english, it basicly does what it sounds like, searches the next module in the processlist.
Parameters: The handle is obvious, its the process which you want the information from. Basicly, the parameter is set up like this:
HANDLE hModuleSnap = CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
The second parameter, "LPMODULEENTRY32" is more fun. What ever the return value for this function is can be used throughout a program to get the process information such as PID. However, it is more tricky. This is a full example of how to use it:
MODULEENTRY32 ptr32;
Module32Next(hModuleSnap, &ptr32);
Notice the "&" it is not there for fun!
What to use M32N for: Run through a list of running modules loaded in a process and retrieve the module information. PB uses this function to detect if a hack is loaded in the game, and such as a D3D hack. Remember the "invalid d3d8.dll" kick in the olden days? Well, that is from this function.
Intercepting the API:I use the same method I've used for every API interception I do. Get the module of which exported the API to Kernel32.dll, compare it to pbcl.dll. If it matches, patch the function with your own. (This is done in DllMain)
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID reserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
Log.WriteLogHeader();
Log.Log("Hooking Function...");
hDLL = hInst;
DisableThreadLibraryCalls(hInst);
GetModuleFileName(GetModuleHandle(NULL), cDLL, sizeof(cDLL));
PathStripPath(cDLL);
if (strcmp(cDLL, "pbcl.dll") == 0)
InterceptPBAPI(hInst, "kernel32.dll", "Module32Next", (DWORD)AnticheatAPIReplace);
Log.Log("Successfull");
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TlsFree((DWORD)hInst);
Log.Log("TrixnIce Unloaded");
}
return TRUE;
}
The Patch:Here is the part which replaces the code (yay!). First you have to know what you want to replace the function with. Should you return it FALSE? (Yes, Module32Next is a bool if you have forgotten ALREADY!) But if you do that, then any simple program can detect the function never succeded and use the function, "GetLastError()" and smack you with a, "No admin access" or, "Operation failed" alert. So here is my idea, why not let the function move along through the list of modules untill your module is up. Once that happens, smack it on the face with end of module list notification.
BOOL WINAPI AnticheatAPIReplace(LPSYSTEM_POWER_STATUS lpSystemPowerStatus)
{
DWORD dwPID = GetCurrentProcessId();
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 ptr32;
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}
ptr32.dwSize = sizeof(MODULEENTRY32);
if (strcmp(ptr32.szModule, "TrixnIce.dll") == 0)
return ERROR_NO_MORE_FILES;
CloseHandle(hModuleSnap);
return TRUE;
}
There you have it, the API is replaced and no harm has been done. The function will continue to run as normal through the files, and each time it comes to your module it will be alerted there are no more modules.
Thanks HockeyBuster & UC, great job.