Go Back   UnKnoWnCheaTs - Multiplayer Game Hacking and Cheats

  • A bunch of bad user-mode anti-cheat bypasses A bunch of bad user-mode anti-cheat bypasses
    sponsored advertisements
    Reply
     
    Thread Tools

    A bunch of bad user-mode anti-cheat bypasses
    Old 7th February 2018, 05:22 PM   #1
    harakirinox
    Eternal newbie

    harakirinox's Avatar

    Join Date: Nov 2016
    Location: UK & France
    Posts: 1,709
    Reputation: 100087
    Rep Power: 299
    harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!harakirinox has a huge epeen!
    Recognitions The UC Member of the Month award is a prestigious award given to a single community member on a monthly basis. Based on a vote from community members, the award is given to the forum member that has shown exemplary achievement and potential in the UnKnoWnCheaTs community, and has shown great commitment to upholding the principles upon which UnKnoWnCheaTs stands for. A member who has been awarded the Member of the Month award has been distinguished as an asset to the UnKnoWnCheaTs community. Member of the Month (1)
    Members who have contributed financial support towards UnKnoWnCheaTs. Donator (2)
    Points: 157,841, Level: 56
    Points: 157,841, Level: 56 Points: 157,841, Level: 56 Points: 157,841, Level: 56
    Level up: 66%, 2,059 Points needed
    Level up: 66% Level up: 66% Level up: 66%
    Activity: 2.6%
    Activity: 2.6% Activity: 2.6% Activity: 2.6%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    Arrow A bunch of bad user-mode anti-cheat bypasses

    Hey,

    A long time ago, in a galaxy far, far away...

    @JYam @mistree and I released a 3 versions of a bypass (ASAP Handles! v1, v2, and hSonic), along with an injector using the principle (MEMEInjector).
    Only a 2 or 3 weeks later, EAC already applied a patch (I didn't check for BattlEye).
    Some results from the experiments you are about to read indicates that in fact they did NOT fix the issue, they just found a way to prevent us from getting the new process notification in time to outrun the kernel notification routines, but the unsecure delay seems to still be there. More on that further down the article.

    I was a bit disappointed at first.
    I knew obviously that these guys were lurking, but you know...
    Sometimes you know something but you only realise it later, something happens and it become suddenly much more "real".
    That was how I felt at that moment.
    And it was extremely exciting.
    It means, when I write my UnknownCheats articles, these guys are there, reading too.
    The cat and mouse game just became more real, and at that moment, I set myself a challenge:
    I am going to pwn the anti-cheats using the process handle that we are left with AFTER they modify its permissions.
    In other words, I will use whatever is left past their security mechanisms and pwn them anyway with that.
    I thought that would be a damn good lolz, and I thought it would make you guys laugh, because I'm just a clown deep down
    To increase my motivation further, I even fired up Photoshop and made a little image that I intended to use in my future UC post, when I publish my results, I picked a name that suited the experiment: PwnBack



    Yeah it's a different name that this article, but I did not know what I would find at first, or if I would find at all.
    Even having one seemed challenging.
    So I started experimenting... A lot... And I found some stuff that might be valuable for you.
    Don't get too hyped though, I don't consider any bypass method in here satisfactory.
    Let me calm things down before we begin:
    Yes these bypasses DO have detection vectors, I myself consider them risky to use (some of them have less than others, you'll make your own opinion), and last but not least, they do not rely on any novel ground-breaking technique.
    However, this is a good demonstration that sometimes, you can do things without going complicated or overly-technical, you just need to have some ideas


    Enough setup, let's dive in.

    Attack surface for this challenge

    As I said, I am going to use a handle that went through anti-cheat protection mechanisms, so let's check what permissions these handles have.
    To get this information, I just do a simple OpenProcess requesting PROCESS_ALL_ACCESS on some protected games and check what permissions are left.
    While discussing privately with @dracorx I noticed that there are sometimes different handles and permissions variations for a same anti cheat on different games, so I decided to check on different games that I own (too bad I don't own any games on which the security had the reputation to be aggressive like PUBG, but anyway those games will do).

    EasyAntiCheat protecting 7 Days to die:
    0x11fbc5 (Query limited information, Set information, Set quotas, Set session ID, Create processes, Duplicate handles, Suspend/resume, Terminate, Synchronize, Delete)
    EasyAntiCheat protecting Miscreated:
    0x11fbc5 (Query limited information, Set information, Set quotas, Set session ID, Create processes, Duplicate handles, Suspend/resume, Terminate, Synchronize, Delete)
    BattlEye protecting Unturned:
    0x1ffbc5 (Query limited information, Set information, Set quotas, Set session ID, Create processes, Duplicate handles, Suspend/resume, Terminate, Synchronize, Delete, Read control, Write DAC, Write owner)
    BattlEye protecting DayZ:
    0x1ffbc5 (Query limited information, Set information, Set quotas, Set session ID, Create processes, Duplicate handles, Suspend/resume, Terminate, Synchronize, Delete, Read control, Write DAC, Write owner)

    Seems like the callbacks to "secure" handles by changing permissions are the same on different games for the same anti-cheat, and we also find commonalities between anti-cheats.
    That's what I am left with, and since EAC has more restrictive permissions after stripping, I am going to limit myself to the permissions left by EAC, so any bypass should be compatible with both ACs)

    In summary, I need to pwn them with Query limited information, Set information, Set quotas, Set session ID, Create processes, Duplicate handles, Suspend/resume, Terminate, Synchronize, and Delete...



    From dickin' around to pwnin' around

    My first choice was to start trying stuff with the Duplicate Handle permission, I tried some stuff with it, even dumb stuff that I myself didn't know where I was going with that, like GIVING handles to the game (WTF?)
    But I couldn't find anything worth mentioning.
    So, second choice: the Create Process permission.
    Actually if you think a bit more, this one is actually very promissing, we can get the inheritable handles of a game this way.
    So which kind of handles games have?
    I have been reversing and hacking a bit on Miscreated (EAC protected) these days, so I experimented on this game.
    It has natively several inheritable handles on some of its threads:

    I quickly checked and so does DayZ actually:

    I also checked a few games (non AC protected) and them too had inheritable thread handles.
    That's intriguing, there are probably some common graphic libraries that are coded to have inheritable threads or something?
    I can't imagine that being a willful decision from the game devs.
    Anyway, whatever.
    I make a code a small thing to spawn a program as child of another and inherit its inheritable handles (copy paste from hBastard).

    Code:
    #include <Windows.h>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    bool SetPrivilege(LPCWSTR lpszPrivilege, BOOL bEnablePrivilege = TRUE) {
    	TOKEN_PRIVILEGES priv = { 0,0,0,0 };
    	HANDLE hToken = NULL;
    	LUID luid = { 0,0 };
    	BOOL Status = true;
    	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
    		Status = false;
    		goto EXIT;
    	}
    	if (!LookupPrivilegeValueW(0, lpszPrivilege, &luid)) {
    		Status = false;
    		goto EXIT;
    	}
    	priv.PrivilegeCount = 1;
    	priv.Privileges[0].Luid = luid;
    	priv.Privileges[0].Attributes = bEnablePrivilege ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
    	if (!AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0)) {
    		Status = false;
    		goto EXIT;
    	}
    EXIT:
    	if (hToken)
    		CloseHandle(hToken);
    	return Status;
    }
    
    PROCESS_INFORMATION MakeBastardChild(DWORD dwParentPID, std::wstring childProcess, std::wstring cmdLineArgs) {
    	PROCESS_INFORMATION pi;
    	SecureZeroMemory(&pi, sizeof(pi));
    
    	// Initialising attributes for process creation
    	SIZE_T cbAttributeListSize = 0;
    	InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);
    	PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = NULL;
    	pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
    	if (NULL == pAttributeList)
    		return pi; // Failed
    	if (!InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize))
    		return pi; // Failed
    
    				   // Getting handle on parent with only PROCESS_CREATE_PROCESS permission (required by UpdateProcThreadAttribute)
    	HANDLE hParentProcess = NULL;
    	hParentProcess = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, dwParentPID);
    	if (NULL == hParentProcess)
    		return pi; // Failed
    
    				   // Updating the attribute list with the desired parent for the future process to start
    	if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess, sizeof(HANDLE), NULL, NULL))
    		return pi; // Failed
    
    				   // If child process is unspecified, we will spawning another instance of the current process, getting own path & image name
    	if (childProcess == L"") {
    		WCHAR thisProgram[MAX_PATH] = L"";
    		DWORD myLength = GetModuleFileName(NULL, (LPWSTR)&thisProgram, MAX_PATH);
    		childProcess = thisProgram;
    	}
    
    	// Command line arguments specified, formating the wide string to give CreateProcess
    	std::wstring cmdLineFullArgs;
    	if (cmdLineArgs != L"") {
    		cmdLineFullArgs = L'"' + childProcess + L'"' + L' ' + cmdLineArgs;
    		cmdLineFullArgs.resize(0x7FFF); // Getting the max possible size to avoid access violation (accordingly to CreateProcess documentation)
    	}
    
    	// Creating the bastard child process
    	STARTUPINFOEX sie = { sizeof(sie) };
    	sie.lpAttributeList = pAttributeList;
    	CreateProcess(childProcess.c_str(), (LPWSTR)cmdLineFullArgs.c_str(), NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, NULL, NULL, &sie.StartupInfo, &pi);
    
    	// Whether it succeeded or not, returning the PROCESS_INFORMATION (can check if failed if everything is null inside, since it's zeroed)
    	return pi;
    }
    
    int main() {
    	SetPrivilege(SE_DEBUG_NAME);
    	SetPrivilege(SE_TCB_NAME);
    	PROCESS_INFORMATION pi;
    	pi = MakeBastardChild(18000, L"C:\\Users\\user\\Box Sync\\Code\\EmptyProgram\\x64\\Release\\EmptyProgram.exe", L"");
    	system("pause");
    	return EXIT_SUCCESS;
    }
    And yep, my program receives the thread handles without having the permissions modified:



    If you experiment with your games to see what inheritable handles they have do not only start the game, for miscreated for example more handles are created when you go in certain menus and when you join the game. New libraries are loaded which can lead to more handle, or on the contrary some handles can be closed. Play a bit with it and see by yourself.

    Okay so now we have a full permission thread handle, but we can't do much with it.
    Being in possession of a full access thread handle is actually very frustrating: You know you are in control of execution, you know you can suspend, get the thread context and set it to execute something else but you don't have access to put a shellcode into an executable region of memory.
    So you can control execution, but not what's going to be executed.
    Yep, that kind of sucks.

    Okay so now the goal is to be able to push shellcode into the game's memory, how can we do that?
    A bunch of ideas came to my mind.

    A first bypass: Push shellcode with LSASS/CSRSS handle and execute with inherited thread handle
    This is just an idea, I did not experiment it, but maybe you'll be interested.
    It is obvious and absolutely not new but we could use LSASS or CSRSS handles with a stealthy enough method.
    Using their handle you write your shellcode in an already executable memory page and then you use the thread handle for execution.
    After all we just need to do 1 write operation, we wouldn't be putting a shared memory or named pipe permanent bypass that ends up doing thousands of operations per second with the handle.
    Plus these processes both import the functions to write to memory and make use of them in their normal execution (for example LSASS imports NtRVM and NtWVM and call it somwhere in lsasrv.dll).
    If you can make that one write stealthy enough, then you should be good for the detection related to tampering with system processes.
    I did not follow that road because I knew that most people in here are just fed up with handle hijacking stuff, and in addition to that, the ACs have set up monitoring methods on those processes looking for suspicious activity.
    But if I had to write it I would certainly write my shellcode at the end an executable region where we know there is unused bytes, at the end of ntdll.dll or kernel32.dll for example, in addition to that they are mapped at the same address in every process.
    You write the shellcode to NtWriteVirtualMemory your shellcode to be executed by the game at the end of ntdll.dll or kernel32.dll in LSASS, hijack a thread to execute and your shellcode pushed in the game at a known location, you can then hijack one of the game's thread with the inherited handles that we have.
    Once you can execute shellcode, you can pretty much do anything, like make the game manual map a DLL for you or anything else you want it to do.

    So how else could we push our shellcode and execute it?
    I decided to start small, simply succeeding to write my shellcode into the game's memory, even in a non-executable memory region, even if it would be easily detected would be a good start.
    With such as approach there are many ways possible, including using the existing system process handle, but also others:
    For example one simple (and brutal) way is to use an hexadecimal editor on a file that will be mapped to memory when the game loads, paste the bytes of your shellcode at the end of the file or anywhere it doesn't disturb too much, then you just send a thread at that location.
    However there is a problem to execute then: DEP (Data Execution Prevention)

    A second bypass: Turn DEP off (per process or system-wide) to allow execution in non executable pages
    Yep, you can simply turn DEP off, and in case you wonder:
    Yes you can play online, I tried on Unturned (BE) first, no ban, tried on Miscreated then (EAC), no ban, and DayZ (BE), no ban either.
    There are different ways you can turn off DEP: For the entire system, or per specific processes.
    You can turn it on and off with a single command line:
    Code:
    bcdedit.exe /set {current} nx AlwaysOn
    bcdedit.exe /set {current} nx AlwaysOff
    Otherwise you can turn it off for specific processes by: Right click on computer, properties, advanced tab, click settings in performance, data execution prevention tab.
    You'll get this:

    Note: I couldn't deactivate per process on my own system, only system-wide, perhaps you can solve this mystery or perhaps you'll just be luckier, I didn't searched to know why
    I don't know what's more suspicious: A system with DEP turned off entirely, or a system with DEP on but turned off for the game only... probably the latter.
    If you decide to experiment with DEP, there are some Windows API function useful:
    GetSystemDEPPolicy, SetSystemDEPPolicy, GetProcessDEPPolicy, SetProcessDEPPolicy mainly.

    Now let's be clear: This bypass idea is shit, absolute garbage, don't use it for actual cheating, consider it for educational purposes only, please.
    It is very suspicious, has lots of detection vectors, just shit I tell you.


    So okay let's now find solutions WITHOUT turning DEP off, please, that just sucks.

    Here comes the bit I am actually proud of.
    For some time I cheat with a method that requires to load a signed, unmodified, genuine, legitimate DLL into my games.
    This can be done by serveral ways, for example, you can simply go in your registry with Regedit, and add the DLL in the AppInit_DLLs list so it'll be loaded by all programs.
    However, EAC prevents DLLs from AppInit to load, so I also sometimes use DLL replacement.
    An easy way to do this is for example to have a program load an additional DLL, for example, if you turn on Discord Overlay, it'll load the overlay DLL into the game, the anti-cheat will obviously check the DLL signature and if it's whitelisted, it'll be loaded.
    Since I need to load a genuine DLL, I just replace physically on disk the DLL of Discord by my other genuine DLL and it passes the security checks, since it is a genuine DLL, it doesn't matter that it's a DLL signed with another certificate, only the certificate has to be validated.
    Okay so now we know that we can load any signed DLL into a protected game (and there's no easy fix for that, each computer as different drivers, programs, etc... that need to load various genuine DLLs to work).
    Well, this way we can tackle 2 problems of the previous technique that were bothering me:

    First, what if the game doesn't have an inheritable thread handle?
    Well, we could make a thread inheritable using Process Hacker in admin mode since it loads their driver KProcessHacker that lets you do just that, we could even do it programmatically, but let's not go that way (first I do not want Process Hacker's app or driver to be blacklisted, plus I bet that the anti-cheat detecting the sole presence of process hacker raises suspicion).
    With our new capacity to load signed DLL, we just have to find a DLL that when loaded creates a thread that is is inheritable and boom we can make any game to have an inheritable thread handle to allow thread hijacking.

    Second, how to be able to execute with DEP still on?
    Well, once again, we could find a DLL that when loaded gets an inheritable handle on an executable memory section.
    We could then just inherit this handle, push the shellcode, and use the inherited thread handle to execute it.
    But come on, this is one hell of a DLL that we are looking for now.
    First in general DLLs only export functions to give features to programs, they don't actually do things on their own.
    Second, generally, memory pages are created with VirtualAlloc which doesn't generate any handle, there's only a handle in special cases, like when creating shared memory for example (the handle is created by the call to CreateFileMapping in that case).
    It would be like looking for a needle in giant fucking haystack of DLLs.
    How would I find that DLL?

    MAP ALL THE DLLS!
    Well, I automated the process.
    I did a program that does the following operations:
    • Scan a directory (and its subdirectories) for DLLs
    • Write the full list of DLLs to a text file
    • Start a process of an empty program that does absolutely nothing (and has little to no inheritable handles)

    Then start a big loop that:
    • Start a program as child of the empty program
    • Wait a bit for complete initialisation/stabilisation
    • Take a snapshot of the handles that it has
    • Loads the next untested DLL
    • Wait a bit for complete initialisation
    • Take a second snapshot of the handles that it has
    • Write the results to the log file (= how many new handles, and new inheritable handles the DLL gave to the program)

    If you are interested here is the first version of my code that tests DLLs (it had a problem and stopped working after a few thousand DLLs tested but I can't find the last version anywhere)

    Code:
    #include <Windows.h>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <deque>
    #include <string>
    #include <algorithm>
    #include <TlHelp32.h>
    #include "GetHandles.hpp"
    
    #define DLL_LIST_FILE L"DLLs.txt"
    #define LAST_DLL_TREATED L"Last.txt"
    #define LOG_FILE L"Results.txt"
    #define PARENT_PROCESS L"EmptyProgram.exe"
    #define DLL_STARTUP_TIME 5000
    #define STABILISATION_TIME 2000
    #define MAX_TIMEOUT_ANTIFREEZE 90000
    
    #define CMDLINE_MAX_LENGTH 0x7FFF
    
    using namespace std;
    
    vector<wstring> FindFiles(wstring baseDirectory, wstring extension, bool recursively);
    PROCESS_INFORMATION MakeBastardChild(DWORD dwParentPID, std::wstring childProcess = L"", std::wstring cmdLineArgs = L"");
    std::vector<DWORD> GetPIDs(std::wstring targetProcessName = L"");
    void ProcessNext();
    void AntiFreeze();
    
    int main() {
    	// Protection against freeze (start a thread that waits a minute before exiting and treating next
    	CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)AntiFreeze, NULL, NULL, NULL);
    
    	// If DLLs.txt doesn't exist, scanning directory
    	WIN32_FIND_DATA FindDllList;
    	HANDLE hListDLLs = FindFirstFile(DLL_LIST_FILE, &FindDllList);
    	if (GetLastError() == ERROR_FILE_NOT_FOUND || hListDLLs == INVALID_HANDLE_VALUE) {
    		cout << "DLLs.txt doesn't exist. Scanning..." << endl;
    		vector<wstring> foundDLLs = FindFiles(L"C:\\Windows\\System32", L"dll", true);
    		if (foundDLLs.empty())
    			return EXIT_FAILURE;
    		wofstream dllFileCreation(DLL_LIST_FILE, ios::out | ios::trunc);
    		for (int i(0); i < foundDLLs.size(); ++i)
    			dllFileCreation << foundDLLs[i] << endl;
    		dllFileCreation.close();
    		cout << "Done." << endl;
    	}
    
    	// DLLs.txt exist, loading lines into a vector
    	cout << "Loading list of DLLs." << endl;
    	vector<wstring> listDLLs;
    	wifstream listDLLsFile(DLL_LIST_FILE);
    	wstring currentDLL;
    	while (listDLLsFile >> currentDLL)
    		listDLLs.push_back(currentDLL);
    	listDLLsFile.close();
    	
    	// Getting last DLL treated
    	wstring lastDLLtreated;
    	bool first = false;
    	wifstream checkLastDLL(LAST_DLL_TREATED);
    	if (!checkLastDLL) {
    		lastDLLtreated = listDLLs[0];
    		wofstream createLastDLL(LAST_DLL_TREATED, ios::out | ios::trunc);
    		createLastDLL << lastDLLtreated << endl;
    		createLastDLL.close();
    		first = true;
    	} else {
    		checkLastDLL >> lastDLLtreated;
    	}
    	checkLastDLL.close();
    
    	// Getting next DLL to treat
    	wstring nextDLL = lastDLLtreated;
    	ptrdiff_t lastDLLid = 0;
    	if (!first) {
    		lastDLLid = find(listDLLs.begin(), listDLLs.end(), lastDLLtreated) - listDLLs.begin();
    		nextDLL = listDLLs[lastDLLid + 1];
    	}
    	wcout << "[" << lastDLLid << "/" << listDLLs.size() << "] Analysing DLL" << endl;
    	wcout << nextDLL << endl;
    
    	// Analysing DLL-generated handles (listing initial handles, loading lib, listing new handles)
    	wofstream setNextAsLastFile(LAST_DLL_TREATED, ios::out | ios::trunc);
    	setNextAsLastFile << nextDLL << endl;
    	setNextAsLastFile.close();
    	Sleep(STABILISATION_TIME);
    	vector<HANDLE> initialHandles = GetCurrentHandlesIDs();
    	cout << "Handles initially: " << initialHandles.size() << endl;
    	HMODULE dllTested = LoadLibrary(nextDLL.c_str());
    	if (dllTested == NULL)
    		ProcessNext();
    	Sleep(DLL_STARTUP_TIME); // Giving time for the library to start its threads, create handles and shit
    	vector<HANDLE> postHandles = GetCurrentHandlesIDs();
    	cout << "Handles with DLL: " << postHandles.size() << endl;
    	vector<HANDLE> newHandles;
    	for (int j(0); j < postHandles.size(); ++j)
    		if (find(initialHandles.begin(), initialHandles.end(), postHandles[j]) == initialHandles.end())
    			newHandles.push_back(postHandles[j]); // New handle
    	cout << "New HANDLEs: " << newHandles.size() << endl;
    	vector<HANDLE> newHandlesInheritable;
    	for (int j(0); j < newHandles.size(); ++j) {
    		DWORD handleFlags = NULL;
    		GetHandleInformation(newHandles[j], &handleFlags);
    		if (handleFlags & HANDLE_FLAG_INHERIT)
    			newHandlesInheritable.push_back(newHandles[j]);
    	}
    	cout << "New inheritable HANDLEs: " << newHandlesInheritable.size() << endl;
    	FreeLibrary(dllTested);
    	wofstream logResults(LOG_FILE, ios::out | ios::app);
    	logResults << "[" << newHandlesInheritable.size() << "/" << newHandles.size() << "/" << postHandles.size() << "/" << initialHandles.size() << "] "
    		<< "(" << lastDLLid << "/" << listDLLs.size() << ") " << nextDLL << endl;
    	logResults.close();
    	ProcessNext();
    
    	return EXIT_SUCCESS;
    }
    
    void AntiFreeze() {
    	Sleep(MAX_TIMEOUT_ANTIFREEZE);
    	ProcessNext();
    }
    
    void ProcessNext() {
    	vector<DWORD> parentPIDs = GetPIDs(PARENT_PROCESS);
    	MakeBastardChild(parentPIDs[0]);
    	ExitProcess(EXIT_SUCCESS);
    }
    
    vector<wstring> FindFiles(wstring baseDirectory, wstring extension, bool recursively) {
    	vector<wstring> foundFiles;
    	deque<wstring> dirsToSearch;
    	dirsToSearch.push_back(baseDirectory);
    	do {
    		wstring currentDir = dirsToSearch.front();
    		wstring searchString = currentDir + L"\\*";
    		WIN32_FIND_DATA ffd;
    		HANDLE hFind = FindFirstFile(searchString.c_str(), &ffd);
    		if (hFind == INVALID_HANDLE_VALUE) { // Error, skipping directory
    			dirsToSearch.pop_front();
    			continue;
    		}
    		do {
    			// If recursive search, adding to the sub-directory double-ended queue for treatment
    			if (recursively && (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
    				wstring foundDir = ffd.cFileName;
    				if (foundDir == L"." || foundDir == L"..")
    					continue; // To avoid recursion in parent directories
    				wstring fullPathNewDir = currentDir + L"\\" + foundDir;
    				if (find(dirsToSearch.begin(), dirsToSearch.end(), fullPathNewDir) == dirsToSearch.end())
    					dirsToSearch.push_back(fullPathNewDir); // Directory not in the list, adding
    				continue;
    			}
    			// Found file, checking if matches search criteria and adding to the list
    			wstring foundFile = ffd.cFileName;
    			if (foundFile.substr(foundFile.find_last_of(L".") + 1) == extension) {
    				wstring fullPathNewFile = currentDir + L"\\" + foundFile;
    				if (find(foundFiles.begin(), foundFiles.end(), fullPathNewFile) == foundFiles.end())
    					foundFiles.push_back(fullPathNewFile); // DLL not in the list, adding
    			}
    		} while (FindNextFile(hFind, &ffd) != 0);
    		FindClose(hFind);
    		dirsToSearch.pop_front();
    	} while (!dirsToSearch.empty());
    	return foundFiles;
    }
    
    PROCESS_INFORMATION MakeBastardChild(DWORD dwParentPID, std::wstring childProcess, std::wstring cmdLineArgs) {
    	PROCESS_INFORMATION pi;
    	SecureZeroMemory(&pi, sizeof(pi));
    
    	// Initialising attributes for process creation
    	SIZE_T cbAttributeListSize = 0;
    	InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);
    	PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = NULL;
    	pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
    	if (NULL == pAttributeList)
    		return pi; // Failed
    	if (!InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize))
    		return pi; // Failed
    
    				   // Getting handle on parent with only PROCESS_CREATE_PROCESS permission (required by UpdateProcThreadAttribute)
    	HANDLE hParentProcess = NULL;
    	hParentProcess = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, dwParentPID);
    	if (NULL == hParentProcess)
    		return pi; // Failed
    
    				   // Updating the attribute list with the desired parent for the future process to start
    	if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess, sizeof(HANDLE), NULL, NULL))
    		return pi; // Failed
    
    				   // If child process is unspecified, we will spawning another instance of the current process, getting own path & image name
    	if (childProcess == L"") {
    		WCHAR thisProgram[MAX_PATH] = L"";
    		DWORD myLength = GetModuleFileName(NULL, (LPWSTR)&thisProgram, MAX_PATH);
    		childProcess = thisProgram;
    	}
    
    	// Command line arguments specified, formating the wide string to give CreateProcess
    	std::wstring cmdLineFullArgs;
    	if (cmdLineArgs != L"") {
    		cmdLineFullArgs = L'"' + childProcess + L'"' + L' ' + cmdLineArgs;
    		cmdLineFullArgs.resize(CMDLINE_MAX_LENGTH); // Getting the max possible size to avoid access violation (accordingly to CreateProcess documentation)
    	}
    
    	// Creating the bastard child process
    	STARTUPINFOEX sie = { sizeof(sie) };
    	sie.lpAttributeList = pAttributeList;
    	sie.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
    	sie.StartupInfo.wShowWindow = SW_HIDE;
    	CreateProcess(childProcess.c_str(), (LPWSTR)cmdLineFullArgs.c_str(), NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, NULL, NULL, &sie.StartupInfo, &pi);
    
    	// Whether it succeeded or not, returning the PROCESS_INFORMATION (can check if failed if everything is null inside, since it's zeroed)
    	return pi;
    }
    
    // Get PIDs from process name
    std::vector<DWORD> GetPIDs(std::wstring targetProcessName) {
    	std::vector<DWORD> pids;
    	if (targetProcessName == L"")
    		return pids; // No process name given
    	HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // All processes
    	PROCESSENTRY32W entry; // Current process
    	entry.dwSize = sizeof entry;
    	if (!Process32FirstW(snap, &entry)) // Start with the first in snapshot
    		return pids;
    	do {
    		if (std::wstring(entry.szExeFile) == targetProcessName)
    			pids.emplace_back(entry.th32ProcessID); // Names match, add to list
    	} while (Process32NextW(snap, &entry)); // Keep going until end of snapshot
    	CloseHandle(snap);
    	return pids;
    }
    And GetHandle.hpp:

    Code:
    #pragma once
    #include <Windows.h>
    #include <Winternl.h>
    #include <ntstatus.h>
    #include <Psapi.h>
    #include <string>
    #include <vector>
    #define SYSTEMHANDLEINFORMATION 16
    #pragma comment (lib, "ntdll.lib")
    
    typedef struct _SYSTEM_HANDLE {
    	ULONG ProcessId;
    	UCHAR ObjectTypeNumber;
    	UCHAR Flags;
    	USHORT Handle;
    	PVOID Object;
    	ACCESS_MASK GrantedAccess;
    } SYSTEM_HANDLE, *PSYSTEM_HANDLE;
    
    typedef struct _SYSTEM_HANDLE_INFORMATION {
    	ULONG HandleCount; // Or NumberOfHandles if you prefer
    	SYSTEM_HANDLE Handles[1];
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    
    typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
    	DWORD UniqueProcessId;
    	WORD HandleType;
    	USHORT HandleValue;
    	PVOID Object;
    	ACCESS_MASK GrantedAccess;
    } SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
    
    typedef struct _OBJECT_TYPE_INFORMATION {
    	UNICODE_STRING TypeName;
    	ULONG TotalNumberOfObjects;
    	ULONG TotalNumberOfHandles;
    	ULONG TotalPagedPoolUsage;
    	ULONG TotalNonPagedPoolUsage;
    	ULONG TotalNamePoolUsage;
    	ULONG TotalHandleTableUsage;
    	ULONG HighWaterNumberOfObjects;
    	ULONG HighWaterNumberOfHandles;
    	ULONG HighWaterPagedPoolUsage;
    	ULONG HighWaterNonPagedPoolUsage;
    	ULONG HighWaterNamePoolUsage;
    	ULONG HighWaterHandleTableUsage;
    	ULONG InvalidAttributes;
    	GENERIC_MAPPING GenericMapping;
    	ULONG ValidAccessMask;
    	BOOLEAN SecurityRequired;
    	BOOLEAN MaintainHandleCount;
    	UCHAR TypeIndex;
    	CHAR ReservedByte;
    	ULONG PoolType;
    	ULONG DefaultPagedPoolCharge;
    	ULONG DefaultNonPagedPoolCharge;
    } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
    
    EXTERN_C NTSTATUS NTAPI NtDuplicateObject(HANDLE, HANDLE, HANDLE, PHANDLE, ACCESS_MASK, BOOLEAN, ULONG);
    
    bool SetPrivilege(LPCWSTR lpszPrivilege, BOOL bEnablePrivilege = TRUE);
    
    // Find all handle IDs
    std::vector<HANDLE> GetCurrentHandlesIDs() {
    	std::vector<HANDLE> currentHandles;
    	SetPrivilege(SE_DEBUG_NAME); // Getting required privileges
    	NTSTATUS status = STATUS_UNSUCCESSFUL;
    	PVOID buffer = NULL;
    	ULONG buffersize = 0;
    	while (true) {
    		status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SYSTEMHANDLEINFORMATION, buffer, buffersize, &buffersize);
    		if (!NT_SUCCESS(status)) {
    			if (status == STATUS_INFO_LENGTH_MISMATCH) {
    				if (buffer != NULL)
    					VirtualFree(buffer, 0, MEM_RELEASE);
    				buffer = VirtualAlloc(NULL, buffersize, MEM_COMMIT, PAGE_READWRITE);
    			}
    			continue;
    		}
    		else
    			break;
    	}
    	// Enumerate all handles on system
    	PSYSTEM_HANDLE_INFORMATION handleInfo = (PSYSTEM_HANDLE_INFORMATION)buffer;
    	ULONG buffersize2 = 0;
    	for (ULONG i = 0; i < handleInfo->HandleCount; i++) {
    		PSYSTEM_HANDLE_TABLE_ENTRY_INFO Handle = (PSYSTEM_HANDLE_TABLE_ENTRY_INFO)&handleInfo->Handles[i];
    		if (!Handle || !Handle->HandleValue || Handle->UniqueProcessId != GetCurrentProcessId())
    			continue; // Error, no handle, empty handle value, or doesn't belong to this program
    		HANDLE localHandle = (HANDLE)Handle->HandleValue;
    		currentHandles.push_back(localHandle);
    		continue;
    	}
    	VirtualFree(buffer, 0, MEM_RELEASE); // Empties buffers to avoid memory leaks
    	return currentHandles;
    }
    
    // Function provided by    @etc thanks for finding the solution and providing the source !!
    bool SetPrivilege(LPCWSTR lpszPrivilege, BOOL bEnablePrivilege) {
    	TOKEN_PRIVILEGES priv = { 0,0,0,0 };
    	HANDLE hToken = NULL;
    	LUID luid = { 0,0 };
    	BOOL Status = true;
    	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
    		Status = false;
    		goto EXIT;
    	}
    	if (!LookupPrivilegeValueW(0, lpszPrivilege, &luid)) {
    		Status = false;
    		goto EXIT;
    	}
    	priv.PrivilegeCount = 1;
    	priv.Privileges[0].Luid = luid;
    	priv.Privileges[0].Attributes = bEnablePrivilege ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
    	if (!AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0)) {
    		Status = false;
    		goto EXIT;
    	}
    EXIT:
    	if (hToken)
    		CloseHandle(hToken);
    	return Status;
    }
    This code will test only the DLLs inside your System32 directory, but don't forget that many other certificates are whitelisted by anti-cheat, don't hesitate to test others like NVIDIA's for example ...

    Anyway, I have left that shit running for a long while and forgot about it and a few weeks later I finally decided to check the results and saw that I detected a bunch of DLLs that gave inheritable handles, so I decided to check that by myself (this code only logs the number of handles and inheritable handles, it doesn't check their type)
    The very FIRST DLL that I loaded absolutely BLEW MY MIND.

    Third bypass: Make the game load a signed DLL that make the loading process have an inheritable, all access, process handle ON ITSELF
    Yep, I felt so stupid not to have thought about it but yeah a legit DLL that when loaded makes the process either do an OpenProcess or a DuplicateHandle on itself does the trick...
    Once you have found such a DLL you can make you game load it with AppInit_DLL or DLL replacement then you spawn your cheat or your injector as child of the game, it'll have the handle:



    Advice though: Do some extra operations to break the parenthood and get rid of the handle as fast as you can, all this is rather suspicious!
    Okay now I am sorry to disappoint, but I won't be giving the list of DLLs that I found that allow just that, but there are SEVERAL in your own system.
    If I do give a list, they'll be blacklisted or detected or whatever, but you can find them easily using my DLL scanning code (and more if you improve it certainly)
    Only in System32 you have a few of them (don't get tricked though, you'll find several but some of them actually only load the same DLL that does get the handle, not all of them get the handle by themselves).

    To find the magic DLLs I mention here, just run the DLL analyser, this is the source code right above.

    Fourth bypass: Get executable memory section handle + thread hijacking
    That was the idea I was going after at the beginning:
    If you find a signed DLL that make the program loading it to have an inheritable handle on an executable section of memory, then you can just inherit it, write your shellcode, thread hijack to execute and you're done.
    This will be harder for you to find, oppositely to the process handle DLLs, I only found one DLL that does this.

    Hurry: The ACs are securing these techniques
    When I found the process handle DLL thing a few months ago, it worked on both EAC and BE, unfortunately, after helping @Janck7 to implement it on a BattlEye protected game (Fortnite), it appears that BattlEye strips the handle of inherited handles as well now, however, they don't filter the permissions of inherited handles of other types.
    And for EAC, strangely enough, it's the other way around: I had some thread handles with lowered permissions while the process handle was inherited with full permissions, weird.

    Pro tip: Automate the signed DLL "injection"/replacement
    One big downside of those crappy bypasses are that they are really "DIY", rather messy, you have to rename/copy/replace some DLLs to get them loaded to work, it's not very practical.
    One way to make that much easier is to use Discord.
    In Discord you can select PER GAME which will have the overlay (and therefore the overlay DLL injected):

    You can just place the DLL that gives you your wanted inheritable handle instead of the Discord overlay DLL and decide in one click in which games you want it to be loaded, easy

    Fifth (very good) bypass ahead
    This is probably what's most valuable for experienced hackers reading this article, because all this is fun to read, but it's very messy and not very usable.
    Remember that hSonic exploited an unsecure time period when the game starts during which we can OpenProcess and get our handle without it being modified?
    Well, this experience gives strong indication that the hSonic vulnerability is still there, uncorrected.
    They apparently just found a way to prevent us to get the notification on time using the technique that we used (using job object).
    How do I know that?
    Well, loading a DLL that does an OpenProcess or DuplicateHandle on the process itself gives a full access process handle right?
    Now that could be that the AC lets the game process do just that, so I decided to try myself, a minute after the game is loaded and started, use shellcode execution to OpenProcess or DuplicateHandle on itself, and guess what?
    The handle gets modified.
    That could indicate that the unsecure time period at the very beginning is still there, and you find a new way to get the notification, you have a new very elegant bypass, that I myself would consider satisfactory enough to use...

    I hope you enjoyed your read, and that you have new ideas of experiments in mind now.

    Happy hacking.

    Last edited by harakirinox; 8th February 2018 at 01:23 AM. Reason: Added GetHandle.hpp
    harakirinox is online now
    Reply With Quote

    Old 7th February 2018, 06:36 PM   #2
    ihatekirito
    h4x0!2

    ihatekirito's Avatar

    Join Date: Oct 2014
    Location: undefined
    Posts: 107
    Reputation: 2393
    Rep Power: 236
    ihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating communityihatekirito is a legend in the cheating community
    Points: 8,074, Level: 10
    Points: 8,074, Level: 10 Points: 8,074, Level: 10 Points: 8,074, Level: 10
    Level up: 44%, 626 Points needed
    Level up: 44% Level up: 44% Level up: 44%
    Activity: 0%
    Activity: 0% Activity: 0% Activity: 0%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    Always interesting stuff, nice read!
    ihatekirito is offline
    Reply With Quote

    Old 8th February 2018, 12:12 AM   #3
    hackedhacker
    UC Supporter

    hackedhacker's Avatar

    Join Date: Dec 2013
    Posts: 284
    Reputation: 4442
    Rep Power: 258
    hackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating communityhackedhacker is a legend in the cheating community
    Points: 14,794, Level: 15
    Points: 14,794, Level: 15 Points: 14,794, Level: 15 Points: 14,794, Level: 15
    Level up: 86%, 206 Points needed
    Level up: 86% Level up: 86% Level up: 86%
    Activity: 10.5%
    Activity: 10.5% Activity: 10.5% Activity: 10.5%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    Really informative read. I strive to be someone like you in the future. All of your posts give me idea in regard to many other anticheat and I thank you for that. <3
    hackedhacker is offline
    Reply With Quote

    Old 8th February 2018, 12:47 AM   #4
    kajm101
    n00bie

    kajm101's Avatar

    Join Date: Mar 2015
    Posts: 15
    Reputation: 48
    Rep Power: 222
    kajm101 has made posts that are generally average in quality
    Thanks for interesting read
    kajm101 is offline
    Reply With Quote

    Old 8th February 2018, 06:24 AM   #5
    cralsen
    n00bie

    cralsen's Avatar

    Join Date: Dec 2016
    Posts: 21
    Reputation: 25
    Rep Power: 180
    cralsen has made posts that are generally average in quality
    Points: 2,999, Level: 5
    Points: 2,999, Level: 5 Points: 2,999, Level: 5 Points: 2,999, Level: 5
    Level up: 25%, 601 Points needed
    Level up: 25% Level up: 25% Level up: 25%
    Activity: 0%
    Activity: 0% Activity: 0% Activity: 0%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    when the game load your signed DLL,just do everything you want in DllMain.So,why find inheritable handles after loaded?
    cralsen is offline
    Reply With Quote

    Old 8th February 2018, 09:00 AM   #6
    fisherprice
    Retired

    fisherprice's Avatar

    Join Date: May 2016
    Location: China
    Posts: 1,040
    Reputation: 27781
    Rep Power: 230
    fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!fisherprice has reputation that takes up 2GB of server space!
    Recognitions Members who have contributed financial support towards UnKnoWnCheaTs. Donator (1)
    Points: 40,899, Level: 30
    Points: 40,899, Level: 30 Points: 40,899, Level: 30 Points: 40,899, Level: 30
    Level up: 70%, 901 Points needed
    Level up: 70% Level up: 70% Level up: 70%
    Activity: 3.5%
    Activity: 3.5% Activity: 3.5% Activity: 3.5%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    Smile

    i like you work and commitment to try these things but it only show people how not to do things i think. your fifth method not good it apply to specific target and not transparent, it is easy patch so can never be "good" i think? steal handle and hijack dll at ring3 not going to ever be success story.

    but i like to read you work it very good otherwise.
    __________________
    Recent Projects: CS2, Microsoft Mapper, EFI Bot
    ---

    Last edited by dracorx; 11th February 2018 at 01:57 PM. Reason: dont make long quotes
    fisherprice is offline
    Reply With Quote

    Old 25th February 2018, 12:49 PM   #7
    maliczak
    n00bie

    maliczak's Avatar

    Join Date: Sep 2017
    Posts: 8
    Reputation: -65
    Rep Power: 0
    maliczak is becoming an outcast
    really interesting thread
    maliczak is offline
    Reply With Quote

    Old 25th February 2018, 01:29 PM   #8
    FrankoooEFC
    Banned

    FrankoooEFC's Avatar

    Join Date: Jan 2018
    Location: Google
    Posts: 775
    Reputation: 1819
    Rep Power: 0
    FrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all dieFrankoooEFC -- If this mans rep is lowered; we will all die
    Points: 10,405, Level: 12
    Points: 10,405, Level: 12 Points: 10,405, Level: 12 Points: 10,405, Level: 12
    Level up: 51%, 595 Points needed
    Level up: 51% Level up: 51% Level up: 51%
    Activity: 0%
    Activity: 0% Activity: 0% Activity: 0%
    Last Achievements A bunch of bad user-mode anti-cheat bypasses
    Smile

    +Rep Thanks sooo much for this use full information
    FrankoooEFC is offline
    Reply With Quote

    Old 25th February 2018, 02:16 PM   #9
    HHKB
    A God

    HHKB's Avatar

    Join Date: Feb 2018
    Location: South Korea
    Posts: 184
    Reputation: 2099
    Rep Power: 154
    HHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating communityHHKB is a legend in the cheating community
    Points: 4,492, Level: 6
    Points: 4,492, Level: 6 Points: 4,492, Level: 6 Points: 4,492, Level: 6
    Level up: 99%, 8 Points needed
    Level up: 99% Level up: 99% Level up: 99%
    Activity: 0%
    Activity: 0% Activity: 0% Activity: 0%
    Last Achievements A bunch of bad user-mode anti-cheat bypasses
    Are you 200IQ? nice info
    HHKB is offline
    Reply With Quote

    Old 3rd March 2018, 11:16 AM   #10
    Morritz
    Senior Member

    Morritz's Avatar

    Join Date: Jun 2016
    Posts: 78
    Reputation: 1283
    Rep Power: 192
    Morritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for meMorritz -- Punk buster made a most wanted list for me
    Points: 4,314, Level: 6
    Points: 4,314, Level: 6 Points: 4,314, Level: 6 Points: 4,314, Level: 6
    Level up: 80%, 186 Points needed
    Level up: 80% Level up: 80% Level up: 80%
    Activity: 0%
    Activity: 0% Activity: 0% Activity: 0%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    I read in one thread that thread context operations are blocked by EAC is that true or false ?
    Morritz is offline
    Reply With Quote

    Old 5th March 2018, 06:11 AM   #11
    asmjs
    I Own Everyone

    asmjs's Avatar

    Join Date: May 2017
    Location: Bumfuck
    Posts: 720
    Reputation: 16231
    Rep Power: 192
    asmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UCasmjs Will always be a legend at UC
    Recognitions The UC Member of the Month award is a prestigious award given to a single community member on a monthly basis. Based on a vote from community members, the award is given to the forum member that has shown exemplary achievement and potential in the UnKnoWnCheaTs community, and has shown great commitment to upholding the principles upon which UnKnoWnCheaTs stands for. A member who has been awarded the Member of the Month award has been distinguished as an asset to the UnKnoWnCheaTs community. Member of the Month (1)
    Points: 28,847, Level: 24
    Points: 28,847, Level: 24 Points: 28,847, Level: 24 Points: 28,847, Level: 24
    Level up: 97%, 53 Points needed
    Level up: 97% Level up: 97% Level up: 97%
    Activity: 1.8%
    Activity: 1.8% Activity: 1.8% Activity: 1.8%
    Last Achievements A bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypassesA bunch of bad user-mode anti-cheat bypasses
    Quote:
    Originally Posted by Morritz View Post
    I read in one thread that thread context operations are blocked by EAC is that true or false ?
    that's true, hook some function to hijack a thread instead
    asmjs is offline
    Reply With Quote

    Old 5th March 2018, 04:49 PM   #12
    ayazasker
    n00bie

    ayazasker's Avatar

    Join Date: Feb 2018
    Posts: 18
    Reputation: 10
    Rep Power: 151
    ayazasker has made posts that are generally average in quality
    Points: 560, Level: 1
    Points: 560, Level: 1 Points: 560, Level: 1 Points: 560, Level: 1
    Level up: 32%, 340 Points needed
    Level up: 32% Level up: 32% Level up: 32%
    Activity: 0%
    Activity: 0% Activity: 0% Activity: 0%
    It's a shame you can only Rep once.
    ayazasker is offline
    Reply With Quote
    Reply


    Similar Threads
    Thread Thread Starter Forum Replies Last Post
    [Help] Communicating between kernel-mode and user-mode HangMe General Programming and Reversing 11 31st January 2018 01:15 PM
    [Release] hBastard Bypass | 1-Line User-Mode Multi Anti-Cheat Bypass (exploiting inheritance) harakirinox Anti-Cheat Bypass 181 18th November 2017 01:21 PM
    [Help] Forcing a user-mode process to execute shellcode from kernel mode TheTerminal General Programming and Reversing 11 7th June 2016 08:45 PM

    Tags
    handles, handle, dll, set, thread, process, game, write, shellcode, games


    Forum Jump


    All times are GMT. The time now is 10:23 AM.

    Contact Us - Toggle Dark Theme
    Terms of Use Information Privacy Policy Information
    Copyright ©2000-2024, Unknowncheats™
    A bunch of bad user-mode anti-cheat bypasses A bunch of bad user-mode anti-cheat bypasses
    sponsored advertisement
    no new posts