[AntiCheat] More process security and debug priviledge acquisition

This commit is contained in:
momo5502 2017-03-04 13:51:41 +01:00
parent b2b20e5a1c
commit 1b4393f095
9 changed files with 66 additions and 18 deletions

View File

@ -357,12 +357,13 @@ namespace Components
unsigned long AntiCheat::ProtectProcess() unsigned long AntiCheat::ProtectProcess()
{ {
#ifdef PROCTECT_PROCESS #ifdef PROCTECT_PROCESS
Utils::Memory::Allocator allocator; Utils::Memory::Allocator allocator;
HANDLE hToken = nullptr; HANDLE hToken = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken)) if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_READ, &hToken))
{ {
if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken)) if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_READ, TRUE, &hToken))
{ {
return GetLastError(); return GetLastError();
} }
@ -384,6 +385,8 @@ namespace Components
} }
}); });
AntiCheat::AcquireDebugPriviledge(hToken);
DWORD dwSize = 0; DWORD dwSize = 0;
PVOID pTokenInfo = nullptr; PVOID pTokenInfo = nullptr;
if (GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) return GetLastError(); if (GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) return GetLastError();
@ -438,23 +441,13 @@ namespace Components
PACL pDacl = reinterpret_cast<PACL>(allocator.allocate(dwSize)); PACL pDacl = reinterpret_cast<PACL>(allocator.allocate(dwSize));
if (!pDacl || !InitializeAcl(pDacl, dwSize, ACL_REVISION)) return GetLastError(); if (!pDacl || !InitializeAcl(pDacl, dwSize, ACL_REVISION)) return GetLastError();
// Mimic Protected Process // Just give access to what steam needs
// http://www.microsoft.com/whdc/system/vista/process_vista.mspx static const DWORD dwPoison = 0UL | ~(SYNCHRONIZE | GENERIC_EXECUTE | GENERIC_ALL);
// Protected processes allow PROCESS_TERMINATE, which is
// probably not appropriate for high integrity software.
static const DWORD dwPoison =
/*READ_CONTROL |*/ WRITE_DAC | WRITE_OWNER |
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION |
PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE |
// In addition to protected process
PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE;
if (!AddAccessDeniedAce(pDacl, ACL_REVISION, dwPoison, psidArray[0])) return GetLastError(); if (!AddAccessDeniedAce(pDacl, ACL_REVISION, dwPoison, psidArray[0])) return GetLastError();
// Standard and specific rights not explicitly denied // Standard and specific rights not explicitly denied
static const DWORD dwAllowed = (~dwPoison & 0x1FFF) | SYNCHRONIZE; static const DWORD dwAllowed = 0UL | SYNCHRONIZE;
if (!AddAccessAllowedAce(pDacl, ACL_REVISION, dwAllowed, psidArray[1])) return GetLastError(); if (!AddAccessAllowedAce(pDacl, ACL_REVISION, dwAllowed, psidArray[1])) return GetLastError();
// Because of ACE ordering, System will effectively have dwAllowed even // Because of ACE ordering, System will effectively have dwAllowed even
@ -495,6 +488,19 @@ namespace Components
return 0; return 0;
#endif #endif
} }
void AntiCheat::AcquireDebugPriviledge(HANDLE hToken)
{
LUID luid;
TOKEN_PRIVILEGES tp = { 0 };
DWORD cb = sizeof(TOKEN_PRIVILEGES);
if (!LookupPrivilegeValueW(nullptr, SE_DEBUG_NAME, &luid)) return;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, cb, nullptr, nullptr);
//if (GetLastError() != ERROR_SUCCESS) return;
}
AntiCheat::AntiCheat() AntiCheat::AntiCheat()
{ {

View File

@ -28,6 +28,8 @@ namespace Components
static void ScanIntegrityCheck(); static void ScanIntegrityCheck();
static void FlagIntegrityCheck(); static void FlagIntegrityCheck();
static unsigned long ProtectProcess();
private: private:
enum IntergrityFlag enum IntergrityFlag
{ {
@ -50,8 +52,6 @@ namespace Components
static void PerformScan(); static void PerformScan();
static void PatchWinAPI(); static void PatchWinAPI();
static unsigned long ProtectProcess();
static void NullSub(); static void NullSub();
static void AssertCalleeModule(void* callee); static void AssertCalleeModule(void* callee);
@ -75,6 +75,8 @@ namespace Components
static void DObjGetWorldTagPosStub(); static void DObjGetWorldTagPosStub();
static void AimTargetGetTagPosStub(); static void AimTargetGetTagPosStub();
static void AcquireDebugPriviledge(HANDLE hToken);
static Utils::Hook LoadLibHook[4]; static Utils::Hook LoadLibHook[4];
}; };
} }

View File

@ -54,7 +54,7 @@ namespace Components
void Stats::UpdateClasses(UIScript::Token) void Stats::UpdateClasses(UIScript::Token)
{ {
SendStats(); Stats::SendStats();
} }
Stats::Stats() Stats::Stats()

View File

@ -61,6 +61,13 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l
return FALSE; return FALSE;
} }
#ifndef DISABLE_ANTICHEAT
[]()
{
Utils::Hook::Interceptor::Install(_AddressOfReturnAddress(), Components::AntiCheat::ProtectProcess);
}();
#endif
DWORD oldProtect; DWORD oldProtect;
std::uint8_t* module = reinterpret_cast<std::uint8_t*>(GetModuleHandle(nullptr)); std::uint8_t* module = reinterpret_cast<std::uint8_t*>(GetModuleHandle(nullptr));
//VirtualProtect(module, 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect); // Unprotect the entire process //VirtualProtect(module, 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect); // Unprotect the entire process

View File

@ -18,6 +18,7 @@
#include <d3d9.h> #include <d3d9.h>
#include <Aclapi.h> #include <Aclapi.h>
#include <Psapi.h> #include <Psapi.h>
#include <tlhelp32.h>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>

View File

@ -44,6 +44,11 @@ namespace Utils
Hook::Signature::signatures.push_back(container); Hook::Signature::signatures.push_back(container);
} }
void Hook::Interceptor::Install(void* place, void* stub)
{
return Hook::Interceptor::Install(place, static_cast<void(*)()>(stub));
}
void Hook::Interceptor::Install(void* place, void(*stub)()) void Hook::Interceptor::Install(void* place, void(*stub)())
{ {
return Hook::Interceptor::Install(reinterpret_cast<void**>(place), stub); return Hook::Interceptor::Install(reinterpret_cast<void**>(place), stub);

View File

@ -34,6 +34,7 @@ namespace Utils
class Interceptor class Interceptor
{ {
public: public:
static void Install(void* place, void* stub);
static void Install(void* place, void(*stub)()); static void Install(void* place, void(*stub)());
static void Install(void** place, void(*stub)()); static void Install(void** place, void(*stub)());

View File

@ -47,4 +47,28 @@ namespace Utils
return (GetProcAddress(hntdll, "wine_get_version") != nullptr); return (GetProcAddress(hntdll, "wine_get_version") != nullptr);
} }
unsigned long GetParentProcessId()
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) return 0;
Utils::Memory::Allocator allocator;
allocator.reference(hSnapshot, [](void* handle) { CloseHandle(handle); });
PROCESSENTRY32 pe32;
ZeroMemory(&pe32, sizeof(pe32));
pe32.dwSize = sizeof(pe32);
DWORD pid = GetCurrentProcessId();
while (Process32Next(hSnapshot, &pe32))
{
if (pe32.th32ProcessID == pid)
{
return pe32.th32ParentProcessID;
}
}
return 0;
}
} }

View File

@ -9,6 +9,8 @@ namespace Utils
bool IsWineEnvironment(); bool IsWineEnvironment();
unsigned long GetParentProcessId();
template <typename T> inline void Merge(std::vector<T>* target, T* source, size_t length) template <typename T> inline void Merge(std::vector<T>* target, T* source, size_t length)
{ {
if (source) if (source)