├── .gitignore ├── CMakeLists.txt ├── README.md └── src ├── main.cpp └── vp-patch.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/ 2 | /build/ -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.19) 2 | project(VirtualProtectVMPBypass) 3 | set(CMAKE_CXX_STANDARD 20) 4 | set(CMAKE_CXX_STANDARD_REQUIRED True) 5 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 6 | set(SOURCE src/main.cpp) 7 | add_library(VirtualProtectVMPBypass SHARED ${SOURCE}) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vmp-virtualprotect-bypass 2 | 3 | Disables virtualprotect checks/hooks so you can modify memory and change memory protection in binaries protected by VMProtect. -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "vp-patch.hpp" 2 | 3 | DWORD WINAPI main_thread(PVOID module) 4 | { 5 | vmp_virtualprotect_check_disable(); 6 | FreeLibraryAndExitThread((HMODULE)module, 0); 7 | return 1; 8 | } 9 | 10 | // Entrypoint 11 | BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) 12 | { 13 | if (reason == DLL_PROCESS_ATTACH) 14 | { 15 | CreateThread(nullptr, 0, &main_thread, (void *)module, 0, nullptr); 16 | } 17 | return TRUE; 18 | } -------------------------------------------------------------------------------- /src/vp-patch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void vmp_virtualprotect_check_disable() 5 | { 6 | DWORD old_protect = 0; 7 | auto ntdll = GetModuleHandleA("ntdll.dll"); 8 | #if _WIN64 9 | BYTE callcode = ((BYTE *)GetProcAddress(ntdll, "NtQuerySection"))[4] - 1; // Since the syscall code is partially corrupted, we have to figure out what it is (always 1 less than NtQuerySection) since it changes based on windows version. 10 | BYTE restore[] = {0x4C, 0x8B, 0xD1, 0xB8, callcode}; // x64 ntdll 11 | #else 12 | BYTE callcode = ((BYTE *)GetProcAddress(ntdll, "NtQuerySection"))[1] - 1; 13 | BYTE restore[] = {0xB8, callcode, 0x00, 0x00, 0x00}; // x86 ntdll 14 | #endif 15 | auto nt_vp = (BYTE *)GetProcAddress(ntdll, "NtProtectVirtualMemory"); 16 | VirtualProtect(nt_vp, sizeof(restore), PAGE_EXECUTE_READWRITE, &old_protect); // They don't even check if we are vping vp 👎😹👎 17 | memcpy(nt_vp, restore, sizeof(restore)); 18 | VirtualProtect(nt_vp, sizeof(restore), old_protect, &old_protect); 19 | } --------------------------------------------------------------------------------