BattlEye ist vorwiegend ein deutscher Drittanbieter-Anti-Cheat, der hauptsächlich von dem 32-jährigen
Bastian Heiko Suter entwickelt wurde . Es bietet Spieleverlagen ein benutzerfreundliches Anti-Cheat-System, das allgemeine Schutzmechanismen sowie die Erkennung von Cheats für bestimmte Spiele verwendet, um die Sicherheit zu optimieren. Wie auf der Produktwebsite angegeben, ist es immer auf dem neuesten Stand der Technik und verwendet innovative Methoden zum Schutz und zur Erkennung. Das liegt natürlich an der Nationalität des Entwicklers:
QUALITY MADE IN GERMANY
. BattlEye besteht aus vielen Elementen, die zusammenarbeiten, um Betrüger in Spielen zu finden, die für die Verwendung des Produkts bezahlt wurden. Die vier Hauptelemente sind:
- BEService
- Ein Windows-Systemdienst, der mit dem BattlEye BEServer -Server kommuniziert und Client-Server-Kommunikation mit BEDaisy und BEClient bereitstellt .
- Bedaisy
- Ein Windows-Kerneltreiber, der vorbeugende Ereignisverarbeitungsmechanismen und Minifilter protokolliert, um zu verhindern, dass Betrüger das Spiel illegal ändern
- BEClient
- Eine dynamisch verbundene Windows-Bibliothek, die für die meisten Erkennungsvektoren verantwortlich ist, einschließlich der in diesem Artikel beschriebenen. Nach der Initialisierung wird es an den Spielprozess angehängt.
- Beserver
- Eigener Backend-Server, der für das Sammeln von Informationen und das Ergreifen spezifischer Maßnahmen gegen Betrüger verantwortlich ist.
Shellcode
Kürzlich ist ein Dump des BattlEye-Shell-Codes im Internet aufgetaucht, und wir haben beschlossen, darüber zu schreiben, wonach genau die aktuelle Version von BattlEye sucht. Wir haben BattlEye sechs Monate lang nicht analysiert, daher ist unser letzter Speicherauszug des Shellcodes höchstwahrscheinlich veraltet. Verschiedene Teile des Codes wurden nur aus dem Speicher dieses letzten Speicherauszugs wiederhergestellt, vorausgesetzt, BattlEye hat nur den Shell-Code vervollständigt und die vorherigen Erkennungsverfahren nicht gelöscht.
Wie?
BattlEye streamt angeblich Shellcode von seinem Server zu einem Windows-Dienst namens BEService. Dieser Dienst kommuniziert mit dem im Spiel befindlichen BEClient-Modul. Der Datenaustausch erfolgt über die
\.namedpipeBattleye
und war bis 2018 unverschlüsselt. Jetzt werden alle übertragenen Daten mit einem XOR-Verschlüsseler mit sehr kleinen Schlüsseln verschlüsselt, wodurch es extrem einfach ist, bekannte Klartextangriffe durchzuführen. Wenn der Shell-Code an den Client übertragen wird, befindet er sich außerhalb aller bekannten Module und wird ausgeführt, was die Ermittlung vereinfacht. Um einen Shellcode-Dump zu erstellen, können Sie entweder die Windows-Standard-API-Funktionen wie CreateFile, ReadFile usw. verarbeiten und den entsprechenden Speicherbereich aller aufrufenden Module sichern (Speicherinformationen für die zurückgegebene Adresse anfordern), die sich außerhalb aller bekannten Module befinden, oder Durchsuchen Sie regelmäßig den virtuellen Speicherbereich des Spiels auf der Suche nach ausführbarem Speicher außerhalb aller bekannten Module und speichern Sie ihn auf der Festplatte. Gleichzeitig müssen Sie nachverfolgen, welche Bereiche bereits entleert wurden, damit Sie nicht viele identische Entleerungen erhalten.
Erklärung
Die im Artikel vorgestellten Fragmente des Pseudocodes sind der Schönheit halber
stark modifiziert. Sie können den BattlEye-Shell-Code nicht ausgeben und diese Teile nicht sofort erkennen. Der Shellcode enthält keine Funktionsaufrufe, und viele Algorithmen im Artikel werden bereitgestellt. Tatsächlich ist dies jedoch nicht wichtig, denn wenn Sie mit dem Lesen dieser schrecklichen Antike fertig sind, haben Sie die Möglichkeit, sie zu umgehen (:
Speichersortierung
Der häufigste Erkennungsmechanismus bei Anti-Cheats ist die Speicheraufzählung und das Scannen des Speichers, um nach
bekannten Cheatbildern zu suchen. Es ist einfach zu implementieren und, wie die Vergangenheit gezeigt hat, mit dem richtigen Ansatz sehr effektiv, wenn Sie die Grundlagen von Assembler nicht vergessen und den Prolog einer gemeinsamen Funktion auf die schwarze Liste gesetzt haben.
Battleye durchläuft den gesamten Adressraum des Spielprozesses (der aktuelle Prozess in diesem Kontext) und führt verschiedene Überprüfungen der Leistung der Seite durch und findet den Shell-Code außerhalb des entsprechenden Speicherbereichs.
So wird es in Battleye implementiert:
Speicheranomalien
BattlEye markiert alle Anomalien im Speicheradressraum, hauptsächlich den Speicher der ausführbaren Module, die nicht dem geladenen Image entsprechen:
void memory::anomaly_check(MEMORY_BASIC_INFORMATION memory_information) {
Nach Mustern suchen
Wie oben erwähnt, durchsucht BattlEye auch den Speicher lokaler Prozesse auf das Vorhandensein verschiedener klar definierter Muster, wie aus der unten gezeigten Implementierung ersichtlich ist.
Wenn Sie diesen Pseudocode lesen, können Sie davon ausgehen, dass
diese Überprüfungen umgangen werden können, indem der Codebereich jedes geladenen Moduls neu geschrieben wird, da bei der Suche nach Mustern in bekannten Bildern keine Scans durchgeführt werden. Um nicht an Integritätsprüfungen teilzunehmen, müssen Sie alle gepackten und auf die Whitelist gestellten Bereiche herunterladen und die als
RWX gekennzeichneten
Codebereiche neu
schreiben , da wir keine Integritätsprüfungen durchführen können, ohne den Packer zu emulieren. In der aktuellen Version des BattlEye-Shellcodes sind diese Speichermuster fest codiert:
[05 18] ojectsPUBGChinese [05 17] BattleGroundsPrivate_CheatESP [05 17] [%.0fm] %s [05 3E] 0000Neck0000Chest0000000Mouse 10 [05 3F] PlayerESPColor [05 40] Aimbot: %d02D3E2041 [05 36] HackMachine [05 4A] VisualHacks.net [05 50] 3E232F653E31314E4E563D4276282A3A2E463F757523286752552E6F30584748 [05 4F] DLLInjection-master\x64\Release\ [05 52] NameESP [05 48] Skullhack [05 55] .rdata$zzzdbg [05 39] AimBot [05 39] EB4941803C123F755C623FEB388D41D0FBEC93C977583E930EB683E1DF [05 5F] 55E9 [05 5F] 57E9 [05 5F] 60E9 [05 68] D3D11Present initialised [05 6E] [ %.0fM ] [05 74] [hp:%d]%dm [05 36] 48836424380488D4C2458488B5424504C8BC848894C24304C8BC7488D4C2460 [05 36] 741FBA80000FF15607E0085C07510F2F1087801008B8788100EB [05 36] 40F2AA156F8D2894E9AB4489535D34F9CPOSITION0000COL [05 7A] FFE090 [05 79] %s00%d00POSITION0000COLOR0000000 [05 36] 8E85765DCDDA452E75BA12B4C7B94872116DB948A1DAA6B948A7676BB948902C [05 8A] n<assembly xmlsn='urn:schemas-mi
Diese Speichermuster enthalten auch einen Zwei-Byte-Header, nämlich den unbekannten statischen Wert
05
und eine eindeutige Kennung.
Was wir nicht sehen werden, ist, dass BattlEye auch Muster dynamisch von
BEServer streamt und sie an
BEClient sendet, aber wir werden dies im Artikel nicht diskutieren.
Sie werden iterativ mit dem folgenden Algorithmus gescannt:
void memory::pattern_check(void* current_address, MEMORY_BASIC_INFORMATION memory_information) { const auto is_user32 = memory_information.allocation_base == GetModuleHandleA("user32.dll"
Validierung spezifischer Module (Microsoft)
Modulprüfungen melden das Vorhandensein bestimmter Module, die in das Spiel geladen wurden:
void memory::module_specific_check_microsoft(MEMORY_BASIC_INFORMATION memory_information) { auto executable = memory_information.protect == PAGE_EXECUTE || memory_information.protect == PAGE_EXECUTE_READ || memory_information.protect == PAGE_EXECUTE_READWRITE auto allocated = memory_information.state == MEM_COMMIT if (!allocated || !executable) continue auto mmres_handle = GetModuleHandleA("mmres.dll" auto mshtml_handle = GetModuleHandleA("mshtml.dll" if (mmres_handle && mmres_handle == memory_information.allocation_base) { battleye_module_anomaly_report module_anomaly_report module_anomaly_report.unknown = 0 module_anomaly_report.report_id = 0x5B module_anomaly_report.identifier = 0x3480 module_anomaly_report.region_size = memory_information.region_size battleye::report(&module_anomaly_report, sizeof(module_anomaly_report), 0 } else if (mshtml_handle && mshtml_handle == memory_information.allocation_base) { battleye_module_anomaly_report module_anomaly_report module_anomaly_report.unknown = 0 module_anomaly_report.report_id = 0x5B module_anomaly_report.identifier = 0xB480 module_anomaly_report.region_size = memory_information.region_size battleye::report(&module_anomaly_report, sizeof(module_anomaly_report), 0 } }
Überprüfung bestimmter Module (unbekannt)
Dem System wurde eine Überprüfung bestimmter Module hinzugefügt, die dem Server signalisiert, dass Sie Module geladen haben, die
eines der folgenden Kriterien erfüllen:
void memory::module_specific_check_unknown(MEMORY_BASIC_INFORMATION memory_information) { const auto dos_header = (DOS_HEADER*)module_handle const auto pe_header = (PE_HEADER*)(module_handle + dos_header->e_lfanew const auto is_image = memory_information.state == MEM_COMMIT && memory_information.type == MEM_IMAGE if (!is_image) return const auto is_base = memory_information.base_address == memory_information.allocation_base if (!is_base) return const auto match_1 = time_date_stamp == 0x5B12C900 && *(__int8*)(memory_information.base_address + 0x1000) == 0x00 && *(__int32*)(memory_information.base_address + 0x501000) != 0x353E900 const auto match_2 = time_date_stamp == 0x5A180C35 && *(__int8*)(memory_information.base_address + 0x1000) != 0x00 const auto match_2 = time_date_stamp == 0xFC9B9325 && *(__int8*)(memory_information.base_address + 0x6D3000) != 0x00 if (!match_1 && !match_2 && !match_3) return const auto buffer_offset = 0x00
Wir wissen nicht, welche Module diese Kriterien erfüllen, aber wir vermuten, dass dies ein Versuch ist, eine sehr begrenzte Anzahl spezifischer Cheat-Module zu erkennen.
Nachtrag: @ how02 hat uns mitgeteilt, dass das
action_x64.dll
Modul einen
0x5B12C900
und einen Codebereich enthält, in den Sie schreiben können. Wie bereits erwähnt, kann dies zum Ausnutzen verwendet werden.
Speicherschutz
BattlEye implementiert auch eine sehr zweifelhafte Erkennungsprozedur, die unserer Meinung nach mit
gesetztem PAGE_GUARD- Flag nach Speicher
sucht , ohne tatsächlich zu überprüfen, ob das
PAGE_GUARD- Flag
gesetzt ist :
void memory::guard_check(void* current_address, MEMORY_BASIC_INFORMATION memory_information) { if (memory_information.protect != PAGE_NOACCESS) { auto bad_ptr = IsBadReadPtr(current_address, sizeof(temporary_buffer auto read = NtReadVirtualMemory( GetCurrentProcess(), current_address, temporary_buffer, sizeof(temporary_buffer), 0 if (read < 0 || bad_ptr) { auto query = NtQueryVirtualMemory( GetCurrentProcess(), current_address, 0, &new_memory_information, sizeof(new_memory_information), &return_length memory_guard_report.guard = query < 0 || new_memory_information.state != memory_information.state || new_memory_information.protect != memory_information.protect if (memory_guard_report.guard) { memory_guard_report.unknown = 0 memory_guard_report.report_id = 0x21 memory_guard_report.base_address = memory_information.base_address memory_guard_report.region_size = (int)memory_information.region_size memory_guard_report.memory_info = memory_information.type | memory_information.protect | memory_information.state battleye::report(&memory_guard_report, sizeof(memory_guard_report), 0 } } } }
Fenstersortierung
Der Shell-Code BattlEye durchläuft jedes der momentan im Spiel sichtbaren Fenster und umgeht die Fenster von oben nach unten (nach dem Z-Wert). Fenstergriffe im Spiel sind von dieser Aufzählung ausgeschlossen. Dies wird durch Aufrufen von
GetWindowThreadProcessId
. Daher können Sie die entsprechende Funktion an den falschen Eigentümer des Fensters binden, damit
BattlEye Ihr Fenster nicht überprüft .
void window_handler::enumerate() { for (auto window_handle = GetTopWindow window_handle window_handle = GetWindow(window_handle, GW_HWNDNEXT),
Anomalie suchen
Wenn weniger als zwei Fenster aktiviert sind, wird eine Benachrichtigung an den Server gesendet. Dies geschieht wahrscheinlich, um das Patchen der entsprechenden Funktionen zu verhindern, bei denen der BattlEye-Shell-Code keine Fenster untersuchen kann:
void window_handler::check_count() { if (window_handler::windows_enumerated > 1) return
Prozesssortierung
Durch Aufrufen von
CreateToolhelp32Snapshot
werden alle laufenden Prozesse durchlaufen, es werden
jedoch keine Fehler verarbeitet , wodurch das
CreateToolhelp32Snapshot
und Vermeiden der folgenden Erkennungsverfahren sehr einfach wird:
Pfadprüfung
Befindet sich das Image in mindestens zwei Unterverzeichnissen (beginnend mit dem Stammverzeichnis der Festplatte), markiert das System die Prozesse, wenn der Pfad zum entsprechenden Image mindestens eine der folgenden Zeilen enthält:
Desktop Temp FileRec Documents Downloads Roaming tmp.ex notepad. ...\. cmd.ex
Wenn der Pfad zur ausführbaren Datei einer dieser Zeilen entspricht, erhält der Server eine Benachrichtigung über den Pfad zur ausführbaren Datei sowie Informationen darüber, ob der übergeordnete Prozess einer der folgenden ist (enthält das entsprechende an den Server gesendete Flag-Bit):
steam.exe [0x01] explorer.exe [0x02] lsass.exe [0x08] cmd.exe [0x10]
Wenn der Client den Deskriptor nicht mit den entsprechenden
QueryLimitedInformation
Rechten
QueryLimitedInformation
, setzt er das Flag-Bit
0x04
, wenn die Fehlerursache beim Fehlschlagen des
OpenProcess
Aufrufs nicht
ERROR_ACCESS_DENIED
, wodurch wir den letzten Aufzählungscontainer für den entsprechenden Flag-Wert erhalten:
enum BATTLEYE_PROCESS_FLAG { STEAM = 0x1, EXPLORER = 0x2, ERROR = 0x4, LSASS = 0x8, CMD = 0x10 }
Wenn der übergeordnete Prozess Steam ist, wird das Flag sofort für den Benutzer gesetzt und der Server mit der Benachrichtigungs-ID
0x40
Bildname
Wenn der Prozess eines der vielen unten aufgeführten Kriterien erfüllt, wird sofort ein Flag gesetzt und dies wird mit der Benachrichtigungs-ID
0x38
an den Server
0x38
"Loadlibr" "Rng " "A0E7FFFFFF81" "RNG " "90E54355" "2.6.ex" "TempFile.exe"
Steam Game Overlay
BattlEye überwacht den Steam-Overlay-Prozess, der für das In-Game-Overlay verantwortlich ist, das den meisten Steam-Nutzern bekannt ist. Der vollständige Hostname des Steam Games-Overlays lautet
gameoverlayui.exe
. Es ist bekannt, dass es häufig zum Rendern von Exploits verwendet wird, da es recht einfach ist, illegale Renderings im Spielfenster zu hacken und durchzuführen. Die Überprüfung hat folgende Bedingung:
file size != 0 && image name contains (case insensitive) gameoverlayu
Weitere Überprüfungen, die für die Überlagerung von Steam-Spielen spezifisch sind, sind fast identisch mit den für den Spielprozess selbst durchgeführten Prozeduren, weshalb sie im Pseudocode weggelassen werden.
Steam-Overlay-Speicher-Scan
Das Überlagern von Steam-Spielen wird auf Muster und Anomalien überprüft. Wir konnten nicht tiefer in das Kaninchenloch eindringen und herausfinden, wozu diese Muster dienen, da sie sehr verallgemeinert sind und höchstwahrscheinlich mit Cheat-Modulen zusammenhängen.
void gameoverlay::pattern_scan(MEMORY_BASIC_INFORMATION memory_information) {
Der Scanvorgang sucht auch nach Anomalien in Form von ausführbarem Code außerhalb der heruntergeladenen Bilder, was darauf hindeutet, dass Cracker den Code in den Overlay-Prozess eingefügt haben:
void gameoverlay::memory_anomaly_scan(MEMORY_BASIC_INFORMATION memory_information) {
Steam Game Overlay-Schutz
Wenn der Prozess des Überlagerns von Steam-Spielen durch einen Schutz von Windows-Prozessen wie
Light (WinTcb) geschützt ist , erhält der Server eine Benachrichtigung darüber.
void gameoverlay::protection_check(HANDLE process_handle) { auto process_protection = 0 NtQueryInformationProcess( process_handle, ProcessProtectionInformation, &process_protection, sizeof(process_protection), nullptr if (process_protection == 0)
Wenn der entsprechende
OpenProcess- Aufruf
ERROR_ACCESS_DENIED an den Overlay-Prozess zurückgibt, wird außerdem eine Benachrichtigung über den Benutzer mit der ID
3B
gesendet.
Module sortieren
Es werden auch Steam-Game-Overlay-Prozessmodule durchsucht, insbesondere
vgui2_s.dll
und
vgui2_s.dll
. Für diese Module werden mehrere Prüfungen durchgeführt, beginnend mit
gameoverlayui.dll
.
Wenn diese Bedingung erfüllt ist:
[gameoverlayui.dll+6C779] == 08BE55DC3CCCCB8????????C3CCCCCC
, durchsucht der
[gameoverlayui.dll+6C779] == 08BE55DC3CCCCB8????????C3CCCCCC
die vtable an der in Bytes gespeicherten Adresse
????????
. Wenn sich eines dieser vtable-Elemente außerhalb des Quellmoduls gameoverlayui.dll befindet oder auf eine Anweisung
int 3
verweist, wird der Benutzer mit der Benachrichtigungs-ID
3B
an den Server gemeldet.
void gameoverlay::scan_vtable(HANDLE process_handle, char* buffer, MODULEENTRY32 module_entry) { char function_buffer[16 for (vtable_index = 0 vtable_index < 20 vtable_index += 4) { NtReadVirtualMemory( process_handle, *(int*)&buffer[vtable_index], &function_buffer, sizeof(function_buffer), 0 if (*(int*)&buffer[vtable_index] < module_entry.modBaseAddr || *(int*)&buffer[vtable_index] >= module_entry.modBaseAddr + module_entry.modBaseSize || function_buffer[0] == 0xCC )
Ein spezifisches Überprüfungsverfahren wird auch für das Modul
vgui2_s.dll
:
void vgui::scan() { if (!equals(vgui_buffer, "6A08B31FF561C8BD??????????FF96????????8BD????????8B1FF90")) { auto could_read = NtReadVirtualMemory( process_handle, module_entry.modBaseAddr + 0x48338, vgui_buffer, 8, 0) >= 0 constexpr auto pattern_offset = 0x48378
48378
, :
push 04 push offset aCBuildslaveSte_4 ; "c:\buildslave\steam_rel_client_win32"... push offset aAssertionFaile_7 ; "Assertion Failed: IsValidIndex(elem)"
:
push 04 push 00 push 02 push ??
vgui2_s.dll, , , vtable .
Steam
Steam :
void gameoverlay::check_thread(THREADENTRY32 thread_entry) { const auto tread_handle = OpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, 0, thread_entry.th32ThreadID if (thread_handle) { suspend_count = ResumeThread(thread_handle if (suspend_count > 0) { SuspendThread(thread_handle gameoverlay_thread_report.unknown = 0 gameoverlay_thread_report.report_id = 0x3B gameoverlay_thread_report.suspend_count = suspend_count battleye::report(&gameoverlay_thread_report, sizeof(gameoverlay_thread_report), 0 } if (GetThreadContext(thread_handle, &context) && context.Dr7) { gameoverlay_debug_report.unknown = 0 gameoverlay_debug_report.report_id = 0x3B gameoverlay_debug_report.debug_register = context.Dr0 battleye::report(&gameoverlay_debug_report, sizeof(gameoverlay_debug_report), 0 } } }
LSASS
Windows
lsass.exe , Local Security Authority, , :
if (equals(process_entry.executable_path, "lsass.exe")) { auto lsass_handle = OpenProcess(QueryInformation, 0, (unsigned int)process_entry.th32ProcessID if (lsass_handle) { for (address = 0 NtQueryVirtualMemory(lsass_handle, address, 0, &lsass_memory_info, 0x30, &bytes_needed) >= 0 address = lsass_memory_info.base_address + lsass_memory_info.region_size) { if (lsass_memory_info.state == MEM_COMMIT && lsass_memory_info.type == MEM_PRIVATE && (lsass_memory_info.protect == PAGE_EXECUTE || lsass_memory_info.protect == PAGE_EXECUTE_READ || lsass_memory_info.protect == PAGE_EXECUTE_READWRITE)) {
LSASS , , -, LSASS. BattlEye , /,
ReadProcessMemory
/
WriteProcessMemory
, BEDaisy. BEDaisy , . , , , .
BattlEye id
3C
. :
- WS_EX_TOPMOST :
- (Unicode)
- (Unicode)
- Window style
- Window extended style
- -
- -
- (VM_WRITE|VM_READ)
- :
- ….ContentPaksTslGame-WindowsNoEditor_assets_world.pak
- ….ContentPaksTslGame-WindowsNoEditor_ui.pak
- ….ContentPaksTslGame-WindowsNoEditor_sound.pak
- :
- ….BLGameCookedContentScriptBLGame.u
- NtGetContextThread
NoEye
BattlEye NoEye:
GetFileAttributesExA BE_DLL.dll
, .
void noeye::detect() { WIN32_FILE_ATTRIBUTE_DATA file_information if (GetFileAttributesExA("BE_DLL.dll", 0, &file_information)) { noeye_report.unknown = 0 noeye_report.report_id = 0x3D noeye_report.file_size = file_information.nFileSizeLow battleye::report(&noeye_report, sizeof(noeye_report), 0 } }
Beep Null; . , , - . driver device hijacking. , IOCTL .
void driver::check_beep() { auto handle = CreateFileA("\\.\Beep", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 if (handle != INVALID_HANDLE_VALUE) { beep_report.unknown = 0 beep_report.report_id = 0x3E battleye::report(&beep_report, sizeof(beep_report), 0 CloseHandle(handle } }
void driver::check_null() { auto handle = CreateFileA("\\.\Null", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 if (handle != INVALID_HANDLE_VALUE) { null_report.unknown = 0 null_report.report_id = 0x3E battleye::report(&null_report, sizeof(null_report), 0 CloseHandle(handle } }
Sleep delta
Darüber hinaus kann BattlEye eine Sekunde Inaktivität vom aktuellen Thread anfordern und den Unterschied in der Anzahl der Zyklen vor und nach Inaktivität (Ruhezustand) messen: void sleep::check_delta() { const auto tick_count = GetTickCount Sleep(1000 const auto tick_delta = GetTickCount() - tick_count if (tick_delta >= 1200) { sleep_report.unknown = 0 sleep_report.report_id = 0x45 sleep_report.delta = tick_delta battleye::report(&sleep_report, sizeof(sleep_report), 0 } }
7zip
BattlEye wurde um eine sehr langsame Integritätsprüfung erweitert, damit Benutzer die 7zip-Bibliothek nicht in Spielprozesse laden und Bereiche überschreiben können. Dies wurde von Benutzern durchgeführt, um den Schweregrad der zuvor beschriebenen Musterabtastungen und der Erkennung von Anomalien zu verringern. BattlEye hat einfach beschlossen, Integritätsprüfungen für diese bestimmte 7zip-Bibliothek hinzuzufügen. void module::check_7zip() { constexpr auto sz_7zipdll = "..\..\Plugins\ZipUtility\ThirdParty\7zpp\dll\Win64\7z.dll" const auto module_handle = GetModuleHandleA(sz_7zipdll if (module_handle && *(int*)(module_handle + 0x1000) != 0xFF1441C7) { sevenzip_report.unknown_1 = 0 sevenzip_report.report_id = 0x46 sevenzip_report.unknown_2 = 0 sevenzip_report.data1 = *(__int64*)(module_handle + 0x1000 sevenzip_report.data2 = *(__int64*)(module_handle + 0x1008 battleye::report(&sevenzip_report, sizeof(sevenzip_report), 0 } }
Hardware-Abstraktionsschicht
BattlEye prüft, ob eine dynamisch verknüpfte Windows-Hardwareabstraktionsschichtbibliothek (hal.dll) vorhanden ist, und teilt dem Server mit, ob sie im Spiel geladen ist. void module::check_hal() { const auto module_handle = GetModuleHandleA("hal.dll" if (module_handle) { hal_report.unknown_1 = 0 hal_report.report_id = 0x46 hal_report.unknown_2 = 2 hal_report.data1 = *(__int64*)(module_handle + 0x1000 hal_report.data2 = *(__int64*)(module_handle + 0x1008 battleye::report(&hal_report, sizeof(hal_report), 0 } }
Bildprüfungen
BattlEye überprüft auch verschiedene im Spiel geladene Bilder. Bei diesen Modulen handelt es sich angeblich um signierte Bilder, die auf irgendeine Weise manipuliert und in böswilliges Verhalten umgewandelt wurden. Wir können jedoch nichts weiter über sie sagen, nur über ihre Erkennung:nvToolsExt64_1
void module::check_nvtoolsext64_1 { const auto module_handle = GetModuleHandleA("nvToolsExt64_1.dll" if (module_handle) { nvtools_report.unknown = 0 nvtools_report.report_id = 0x48 nvtools_report.module_id = 0x5A8 nvtools_report.size_of_image = (PE_HEADER*)(module_handle + (DOS_HEADER*)(module_handle)->e_lfanew))->SizeOfImage battleye::report(&nvtools_report, sizeof(nvtools_report), 0 } }
ws2detour_x96
void module::check_ws2detour_x96 { const auto module_handle = GetModuleHandleA("ws2detour_x96.dll" if (module_handle) { ws2detour_report.unknown = 0 ws2detour_report.report_id = 0x48 ws2detour_report.module_id = 0x5B5 ws2detour_report.size_of_image = (PE_HEADER*)(module_handle + (DOS_HEADER*)(module_handle)->e_lfanew))->SizeOfImage battleye::report(&ws2detour_report, sizeof(ws2detour_report), 0 } }
networkdllx64
void module::check_networkdllx64 { const auto module_handle = GetModuleHandleA("networkdllx64.dll" if (module_handle) { const auto dos_header = (DOS_HEADER*)module_handle const auto pe_header = (PE_HEADER*)(module_handle + dos_header->e_lfanew const auto size_of_image = pe_header->SizeOfImage if (size_of_image < 0x200000 || size_of_image >= 0x400000) { if (pe_header->sections[DEBUG_DIRECTORY].size == 0x1B20) { networkdll64_report.unknown = 0 networkdll64_report.report_id = 0x48 networkdll64_report.module_id = 0x5B7 networkdll64_report.data = pe_header->TimeDatestamp battleye::report(&networkdll64_report, sizeof(networkdll64_report), 0 } } else { networkdll64_report.unknown = 0 networkdll64_report.report_id = 0x48 networkdll64_report.module_id = 0x5B7 networkdll64_report.data = pe_header->sections[DEBUG_DIRECTORY].size battleye::report(&networkdll64_report, sizeof(networkdll64_report), 0 } } }
nxdetours_64
void module::check_nxdetours_64 { const auto module_handle = GetModuleHandleA("nxdetours_64.dll" if (module_handle) { nxdetours64_report.unknown = 0 nxdetours64_report.report_id = 0x48 nxdetours64_report.module_id = 0x5B8 nxdetours64_report.size_of_image = (PE_HEADER*)(module_handle + (DOS_HEADER*)(module_handle)->e_lfanew))->SizeOfImage battleye::report(&nxdetours64_report, sizeof(nxdetours64_report), 0 } }
nvcompiler
void module::check_nvcompiler { const auto module_handle = GetModuleHandleA("nvcompiler.dll" if (module_handle) { nvcompiler_report.unknown = 0 nvcompiler_report.report_id = 0x48 nvcompiler_report.module_id = 0x5BC nvcompiler_report.data = *(int*)(module_handle + 0x1000 battleye::report(&nvcompiler_report, sizeof(nvcompiler_report), 0 } }
wmp
void module::check_wmp { const auto module_handle = GetModuleHandleA("wmp.dll" if (module_handle) { wmp_report.unknown = 0 wmp_report.report_id = 0x48 wmp_report.module_id = 0x5BE wmp_report.data = *(int*)(module_handle + 0x1000 battleye::report(&wmp_report, sizeof(wmp_report), 0 } }
Modul-Aufzählungs-IDs
Als Referenz geben wir die Aufzählungs-ID für die Module an: enum module_id { nvtoolsext64 = 0x5A8, ws2detour_x96 = 0x5B5, networkdll64 = 0x5B7, nxdetours_64 = 0x5B8, nvcompiler = 0x5BC, wmp = 0x5BE
TCP-Tabellen scannen
- BattlEye TCP- ( « TCP», TCP table) , IP- Cloudflare-, - pay-to-cheat
xera.ph . - , launcher, . , IP- Cloudflare- . , , .
pay-to-cheat
xera.ph , , .
xera.ph , , , , . , , , , -, , .
void network::scan_tcp_table { memset(local_port_buffer, 0, sizeof(local_port_buffer for (iteration_index = 0 iteration_index < 500 ++iteration_index) {
-:
enum BATTLEYE_REPORT_ID { MEMORY_GUARD = 0x21, MEMORY_SUSPICIOUS = 0x2F, WINDOW_TITLE = 0x33, MEMORY = 0x35, PROCESS_ANOMALY = 0x38, DRIVER_BEEP_PRESENCE = 0x3E, DRIVER_NULL_PRESENCE = 0x3F, MISCELLANEOUS_ANOMALY = 0x3B, PROCESS_SUSPICIOUS = 0x40, LSASS_MEMORY = 0x42, SLEEP_ANOMALY = 0x45, MEMORY_MODULE_SPECIFIC = 0x46, GENERIC_ANOMALY = 0x48, MEMORY_MODULE_SPECIFIC2 = 0x5B, }