├── .gitattributes ├── .gitignore ├── README.md ├── hSonic.sln └── hSonic ├── hSonic.cpp ├── hSonic.vcxproj ├── hSonic.vcxproj.filters ├── main.cpp └── main.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | All credits goes to: https://www.unknowncheats.me/forum/anti-cheat-bypass/236761-hsonic-bypass-asap-handles-v3-1-line-user-mode-multi-anti-cheat-bypass.html 2 | 3 | https://sendvid.com/s5m0oef5 -------------------------------------------------------------------------------- /hSonic.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.6 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hSonic", "hSonic\hSonic.vcxproj", "{772F01E5-6F51-4659-A7B2-11C9C8C9F63B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Debug|x64.ActiveCfg = Debug|x64 17 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Debug|x64.Build.0 = Debug|x64 18 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Debug|x86.ActiveCfg = Debug|Win32 19 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Debug|x86.Build.0 = Debug|Win32 20 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Release|x64.ActiveCfg = Release|x64 21 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Release|x64.Build.0 = Release|x64 22 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Release|x86.ActiveCfg = Release|Win32 23 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /hSonic/hSonic.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | std::vector GetProcessIdsFromProcessName(const char* c_szProcessName) 4 | { 5 | std::vector vPIDs; 6 | 7 | auto hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 8 | if (!hSnapshot || hSnapshot == INVALID_HANDLE_VALUE) 9 | return vPIDs; 10 | 11 | PROCESSENTRY32 pt; 12 | pt.dwSize = sizeof(PROCESSENTRY32); 13 | 14 | if (Process32First(hSnapshot, &pt)) { 15 | do { 16 | std::string szProcessName = pt.szExeFile; 17 | std::transform(szProcessName.begin(), szProcessName.end(), szProcessName.begin(), tolower); 18 | 19 | if (strstr(szProcessName.c_str(), c_szProcessName)) 20 | vPIDs.emplace_back(pt.th32ProcessID); 21 | 22 | } while (Process32Next(hSnapshot, &pt)); 23 | } 24 | 25 | CloseHandle(hSnapshot); 26 | return vPIDs; 27 | } 28 | 29 | HANDLE GetSonicHandle(const std::string & szWatchedProcessName, const std::string & szTargetProcessName, DWORD dwDesiredAccess, BOOL bInheritHandle) 30 | { 31 | // Predefined veriables 32 | std::vector vWatchedProcessHandles; 33 | HANDLE hTarget = INVALID_HANDLE_VALUE; 34 | bool bAssignedToAnyProcess = false; 35 | std::thread handleReceiver; 36 | JOBOBJECT_ASSOCIATE_COMPLETION_PORT jobIOport; 37 | 38 | // Common arg checks 39 | if (szWatchedProcessName.empty() || szTargetProcessName.empty()) 40 | return hTarget; 41 | 42 | // Process infos 43 | printf("Watched process name: %s\n", szWatchedProcessName.c_str()); 44 | 45 | auto vWatchedProcessList = GetProcessIdsFromProcessName(szWatchedProcessName.c_str()); 46 | if (vWatchedProcessList.empty()) 47 | return hTarget; 48 | 49 | printf("Watched process list size: %u\n", vWatchedProcessList.size()); 50 | 51 | /* Creating job to get instant notification of new child processes */ 52 | auto hIOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, NULL); 53 | if (!hIOPort) 54 | goto clean; 55 | 56 | auto hJobObject = CreateJobObjectA(NULL, NULL); 57 | if (!hJobObject) 58 | goto clean; 59 | 60 | jobIOport.CompletionKey = NULL; 61 | jobIOport.CompletionPort = hIOPort; 62 | auto bSetInfoJobObjStatus = SetInformationJobObject(hJobObject, JobObjectAssociateCompletionPortInformation, &jobIOport, sizeof(jobIOport)); 63 | if (!bSetInfoJobObjStatus) 64 | goto clean; 65 | 66 | for (auto & dwCurrentWatchedProcessId : vWatchedProcessList) 67 | { 68 | printf("Watched process id: %u\n", dwCurrentWatchedProcessId); 69 | 70 | auto hWatchedProcess = OpenProcess(PROCESS_SET_QUOTA | PROCESS_TERMINATE, TRUE, dwCurrentWatchedProcessId); 71 | if (hWatchedProcess && hWatchedProcess != INVALID_HANDLE_VALUE) 72 | { 73 | printf("Watched process handle: %p\n", hWatchedProcess); 74 | 75 | if (AssignProcessToJobObject(hJobObject, hWatchedProcess)) 76 | bAssignedToAnyProcess = true; 77 | else 78 | printf("Error! Can not assigned to: %u\n", dwCurrentWatchedProcessId); 79 | 80 | vWatchedProcessHandles.emplace_back(hWatchedProcess); 81 | } 82 | } 83 | 84 | if (!bAssignedToAnyProcess) 85 | goto clean; 86 | 87 | /* Handle-receiver thread */ 88 | handleReceiver = std::thread([&]() 89 | { 90 | char buffer[MAX_PATH]; 91 | DWORD numberOfBytesTransferred; 92 | ULONG_PTR completionKey; 93 | LPOVERLAPPED overlapped; 94 | 95 | printf("handleReceiver | Handle receiver thread started!\n"); 96 | while (GetQueuedCompletionStatus(hIOPort, &numberOfBytesTransferred, &completionKey, &overlapped, INFINITE)) 97 | { 98 | HANDLE hSonicProcess = OpenProcess(dwDesiredAccess, bInheritHandle, reinterpret_cast(overlapped)); 99 | if (hSonicProcess && hSonicProcess != INVALID_HANDLE_VALUE) 100 | { 101 | GetModuleFileNameExA(hSonicProcess, 0, buffer, MAX_PATH); 102 | printf("handleReceiver | Sonic process handled %u(%p) %s\n", GetProcessId(hSonicProcess), hSonicProcess, buffer); 103 | 104 | std::string szProcessImageFileName = buffer; 105 | std::transform(szProcessImageFileName.begin(), szProcessImageFileName.end(), szProcessImageFileName.begin(), tolower); 106 | 107 | auto posLastSlash = szProcessImageFileName.find_last_of("\\/"); 108 | szProcessImageFileName = szProcessImageFileName.substr(posLastSlash + 1, szProcessImageFileName.length() - posLastSlash); 109 | 110 | printf("handleReceiver | Parsed name: %s\n", szProcessImageFileName.c_str()); 111 | 112 | if (szProcessImageFileName == szTargetProcessName) 113 | { 114 | if (WaitForSingleObject(hSonicProcess, 5000) == WAIT_TIMEOUT) // wait 5sec, if process still alive(handled process isn't a temporary process) we can continue 115 | { 116 | hTarget = hSonicProcess; 117 | PostQueuedCompletionStatus(hIOPort, NULL, NULL, NULL); 118 | break; 119 | } 120 | } 121 | CloseHandle(hSonicProcess); 122 | } 123 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 124 | } 125 | 126 | return EXIT_SUCCESS; 127 | }); 128 | 129 | /* Awaiting end of threads (the checker thread terminates the receiver) */ 130 | handleReceiver.join(); 131 | 132 | /* Cleanup before returning handle */ 133 | clean: 134 | for (auto & hCurrentWatchedProcess : vWatchedProcessHandles) 135 | { 136 | if (hCurrentWatchedProcess && hCurrentWatchedProcess != INVALID_HANDLE_VALUE) 137 | CloseHandle(hCurrentWatchedProcess); 138 | } 139 | 140 | if (hIOPort && hIOPort != INVALID_HANDLE_VALUE) 141 | CloseHandle(hIOPort); 142 | 143 | if (hJobObject && hJobObject != INVALID_HANDLE_VALUE) 144 | CloseHandle(hJobObject); 145 | 146 | return hTarget; 147 | } 148 | 149 | -------------------------------------------------------------------------------- /hSonic/hSonic.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {772F01E5-6F51-4659-A7B2-11C9C8C9F63B} 24 | Win32Proj 25 | hSonic 26 | 10.0.15063.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141_xp 33 | MultiByte 34 | 35 | 36 | Application 37 | false 38 | v141_xp 39 | true 40 | MultiByte 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | MultiThreadedDebug 93 | 94 | 95 | Console 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | 106 | 107 | Console 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | MultiThreaded 120 | 121 | 122 | Console 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | Level3 130 | 131 | 132 | MaxSpeed 133 | true 134 | true 135 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 136 | 137 | 138 | Console 139 | true 140 | true 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /hSonic/hSonic.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /hSonic/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #pragma comment(lib, "psapi.lib") 3 | 4 | int main() 5 | { 6 | std::cout << "[ ## ] hSonic Bypass demo - By harakirinox, JYam, and mistree @ UnknownCheats.me" << std::endl; 7 | std::cout << "[ ?? ] Internals: Outruns kernel notification routines with job objects (using method from PcaSvc)" << std::endl; 8 | std::cout << std::endl; 9 | std::cout << "[ !! ] Requires to know the parent of target process (e.g. Steam.exe for steam games, explorer for some others ...)" << std::endl; 10 | std::cout << "[ !! ] Use Process Hacker or Process Explorer to find parent processes easily" << std::endl; 11 | std::cout << std::endl; 12 | 13 | /* Prompts user for the process name to get a handle on and its parent */ 14 | std::string szProcessName = ""; 15 | std::cout << "[ -- ] Process name to get a handle on (e.g. Game.exe):" << std::endl; 16 | std::cout << "[ >> ] "; 17 | std::getline(std::cin, szProcessName); 18 | std::transform(szProcessName.begin(), szProcessName.end(), szProcessName.begin(), tolower); 19 | 20 | std::string szParentName = ""; 21 | std::cout << "[ -- ] Enter parent name (e.g. Steam.exe, leave blank to use explorer.exe):" << std::endl; 22 | std::cout << "[ >> ] "; 23 | std::getline(std::cin, szParentName); 24 | std::transform(szParentName.begin(), szParentName.end(), szParentName.begin(), tolower); 25 | 26 | std::cout << "[ !! ] Ready to get handle, please start target program." << std::endl; 27 | 28 | HANDLE hGame = GetSonicHandle(szParentName, szProcessName, PROCESS_ALL_ACCESS, FALSE); 29 | //HANDLE hGame = GetSonicHandle("Steam.exe", "Game.exe", PROCESS_ALL_ACCESS, FALSE); // Only use this in your cheat 30 | 31 | std::cout << "[ :) ] Got Handle ID: 0x" << std::hex << hGame << std::endl; 32 | std::cout << "[ .. ] Press ENTER to exit when you are done verifying handle (e.g. with Process Hacker or Process Explorer)" << std::endl; 33 | std::cin.get(); 34 | 35 | return EXIT_SUCCESS; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /hSonic/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern HANDLE GetSonicHandle(const std::string & szWatchedProcessName, const std::string & szTargetProcessName, DWORD dwDesiredAccess, BOOL bInheritHandle); 12 | 13 | --------------------------------------------------------------------------------