-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathAntiCheat.cpp
More file actions
143 lines (121 loc) · 3.89 KB
/
AntiCheat.cpp
File metadata and controls
143 lines (121 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// AntiCheat.cpp
// Javelin Project - Minimal Anti-Cheat guards
// Features: debugger detection, suspicious process scan, basic self-integrity (CRC32)
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
static const char* kTag = "[Javelin AntiCheat] ";
// --- Configurable lists ---
static std::vector<std::string> kSuspiciousProcesses = {
"cheatengine.exe",
"ollydbg.exe",
"x64dbg.exe",
"httpdebuggerui.exe",
"ida.exe",
"ida64.exe",
"scylla.exe",
"processhacker.exe"
};
// --- Utils ---
static std::string toLower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
}
// Simple CRC32 (polynomial 0xEDB88320)
static uint32_t crc32(const std::vector<uint8_t>& data) {
uint32_t crc = 0xFFFFFFFFu;
for (uint8_t b : data) {
crc ^= b;
for (int i = 0; i < 8; ++i) {
uint32_t mask = -(crc & 1u);
crc = (crc >> 1) ^ (0xEDB88320u & mask);
}
}
return ~crc;
}
static bool readFile(const std::wstring& path, std::vector<uint8_t>& out) {
std::ifstream f(path, std::ios::binary);
if (!f) return false;
f.seekg(0, std::ios::end);
std::streamsize size = f.tellg();
if (size <= 0) return false;
f.seekg(0, std::ios::beg);
out.resize(static_cast<size_t>(size));
if (!f.read(reinterpret_cast<char*>(out.data()), size)) return false;
return true;
}
// --- Checks ---
static bool checkDebugger() {
if (IsDebuggerPresent()) return true;
// Secondary anti-debug: CheckBeingDebugged flag in PEB (best-effort)
#ifdef _M_IX86
// 32-bit: fs:[30h] -> PEB, offset 2 = BeingDebugged (BYTE)
__try {
BYTE* peb = *(BYTE**)_readfsdword(0x30);
if (peb && peb[2]) return true;
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#elif defined(_M_X64)
// 64-bit: gs:[60h] -> PEB
__try {
BYTE* peb = *(BYTE**)_readgsqword(0x60);
if (peb && peb[2]) return true;
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#endif
return false;
}
static bool checkSuspiciousProcesses() {
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE) return false;
PROCESSENTRY32 pe{};
pe.dwSize = sizeof(pe);
if (!Process32First(snap, &pe)) {
CloseHandle(snap);
return false;
}
do {
std::string name = toLower(pe.szExeFile);
for (const auto& bad : kSuspiciousProcesses) {
if (name == toLower(bad)) {
CloseHandle(snap);
return true;
}
}
} while (Process32Next(snap, &pe));
CloseHandle(snap);
return false;
}
static bool checkSelfIntegrity(uint32_t expectedCrc) {
wchar_t path[MAX_PATH]{};
if (!GetModuleFileNameW(nullptr, path, MAX_PATH)) return false;
std::vector<uint8_t> bytes;
if (!readFile(path, bytes)) return false;
uint32_t current = crc32(bytes);
return current == expectedCrc;
}
// --- Entry helper (embed a baseline CRC once you ship a build) ---
#ifndef JAVELIN_EXPECTED_CRC32
#define JAVELIN_EXPECTED_CRC32 0u // Set this at build time (e.g., /DJAVELIN_EXPECTED_CRC32=0x12345678)
#endif
int main() {
std::cout << kTag << "starting checks...\n";
if (checkDebugger()) {
std::cerr << kTag << "Debugger detected. Exiting.\n";
return 0xDEB; // code for debugger
}
if (checkSuspiciousProcesses()) {
std::cerr << kTag << "Suspicious process detected. Exiting.\n";
return 0xBAD; // code for bad process
}
if (JAVELIN_EXPECTED_CRC32 != 0u) {
if (!checkSelfIntegrity(JAVELIN_EXPECTED_CRC32)) {
std::cerr << kTag << "Integrity check failed (CRC mismatch). Exiting.\n";
return 0xCRC; // custom code (note: non-standard, may be truncated)
}
}
std::cout << kTag << "All clear. Continue.\n";
return 0;
}