Browsing posts in: Apex Anticheat

Apex = Defeated?

Anderthalb Monate ist es her, seid der erste Post über Apex entstanden ist. Nun bin ich an dem Punkt angelangt, Apex als besiegt zu bezeichnen. Zwar weis ich noch lange nicht, wie all die unzähligen Apex Module arbeiten, aber es reicht für uns einen Hack zu schreiben ohne das Apex (frei nach Archimedes) unsere Kreise stört , Mir ist klar dass dieser Post vielleicht von anderen Kopiert wird und als Vorlage für andere Hacks benutzt wird, daher werde ich keinen kompletten Source posten.

Im letzten Post wurde erwähnt dass Apex uns nach dem Hook von End2DOptimized und RenderString Kicks verteilt. Auch sollte im Hinterkopf behalten werden, dass Apex uns nicht selbst kickt, sondern nur Daten an den zentralen Server weiterleitet. Des weiteren sollten wir uns in das Gedächnis rufen, dass die Detour-Library die ersten 6 Bytes einer Funktion mit einem JMP ersetzt. Das alles deutet darauf hin, dass Apex irgendwie den Funktionsanfang prüft, ob dort Hooks gesetzt sind oder nicht. Prompt wurde CheatEngine gezückt und der Debugger attached, welcher in auf Lesezugriffe am Anfang der gehookten End2DOptimized Funktion achtet. Das selbe wäre auch mit OllyDbg möglich gewesen, aber CheatEngine ist in diesem Fall bequemer zu bedienen.

ApexHashing

Mit allein diesem Resultat fangen wir wenig an. Wichtig ist zu wissen, dass generell 0x7XXXXXXX Adressen in den Kernelspace zeigen. Mit dem Debugger finden wir, dass 0x760575B2 in der Funktion IsBadReadPointer liegt und diese wohl unseren Funktionsanfang prüft. Der Call dazu erfolgt allerdings auf dem 0x0CCXXXXX Adressbereich. Wir wissen ja inzwischen, das Apex zwei große Module in den Speicher mapped, allerdings ist keines davon annährend in diesem Bereich. Ein Glück, dass VirtualAlloc gehooked ist und wir somit die dynamischen Speicherreservierungen mitbekommen. Darin finden wir:

14:08:20 Virtual Alloc! Size: 7d90, Addr: 0xcce0000, allocType: 1000, flProtect: 40

Continue Reading

0

Apex AntiCheat – Die kommunizierende Zwiebel

Kommunizieren kann Apex also auch noch! Nur leider noch nicht so ganz mit dem Reverser. Denn in diesem Post geht es um das Netzwerkprotokoll und natürlich wie Apex da mit drin hängt. Es werden aber auch die Apex-Module angeschnitten, die bereits in den letzen Posts Erwähnung fanden.

Ein direkter Mitschnitt von Netzwerktraffic ist schwer möglich, da auf jedes Packet auf eine ganz abscheuliche (und ziemlich schwer nachzuvollziehende) weiße von XOR und Bitshifting-Operationen gequält wird. Daher muss auf andere Wege zurückgegriffen werden, um das Netzwerkprotokoll zu durchschauen. In der CShell-Module finden sich eine Menge netter Strings, wie z.B:

CS_CH_GETUSERID_REQ

Die XRefs von IDA Pro führen auf eine Funktion, in der dieser String verwendet wird. Der interessante Teil beschränkt sich zunächst auf folgende Zeilen:

.text:0069D723                 call    memcpy
.text:0069D728                 mov     ecx, someGlobalManager
.text:0069D72E                 add     [ebp+var_C], esi
.text:0069D731                 add     dword_15BEF24, ebx
.text:0069D737                 mov     eax, [ecx]
.text:0069D739                 mov     eax, [eax+2D8h]
.text:0069D73F                 add     esp, 0Ch
.text:0069D742                 lea     edx, [ebp+Dst]
.text:0069D748                 push    edx
.text:0069D749                 call    eax
.text:0069D74B                 mov     eax, GlobalILTClient
.text:0069D750                 add     dword_15BEF24, ebx
.text:0069D756                 mov     ecx, [eax]
.text:0069D758                 mov     edx, [ecx+18h]
.text:0069D75B                 push    offset aCs_ch_getuseri ; "CS_CH_GETUSERID_REQ"
.text:0069D760                 push    eax             ; Args
.text:0069D761                 call    edx

Wie unschwer zu erkennen ist, wird ein statischer Zeiger geladen und dessen Pointer in EAX gespeichert. Dort wird im Anschluss die Adresse einer virtuellen Funktion geladen (ECX + 2D8h) und diese mit einem Argument in EDX aufgerufen. Wie sich später herrausstellt ist in EDX das eigentliche Packet gespeichert. Im Anschluss wird nochmals eine virtuelle Funktion geladen und aufgerufen, dieses mal allerdings zu Logzwecken. Wie können wir uns das zu nutze machen? Wir hooken beide Funktionen und loggen so alle Packete die Packetnamen in ein Logfile. Und das alles, bevor irgendetwas verschlüsselt wird . 😉

Continue Reading

0

Apex AntiCheat – Zwiebeln sorgen für Tränen

Weiter geht es direkt an der Stelle, an welcher der letzte Blogpost endete: Das Patchen der ersten Apex Schicht automatisieren und den Rest „debugbar“ zu bekommen. Dazu werden wir einen eigenen Loader schreiben, der es uns erlaubt DLLs vor Programmstart zu Injecten und somit bequem Patches ermöglicht.

Erfahrenere Leser dieses Blogs werden sich wundern, warum der Umweg über einen Loader genommen wurde, statt die zu importierenden DLLs direkt in die ImportTable zu schreiben (von welcher sie direkt geladen werden). Nun, Apex schickt Hashsummenchecks der Wolfteam-Binary an den Gameserver, der uns einen Kick spendiert wenn die Checksumme nicht stimmt.

Das Prinzip des Loaders ist quasi von Opcode0x90 Blog geklaut. Die Idee dahinter ist simpel: Wir starten den Prozess im Status „SUSPENDED“ und Patchen den Entry Point, welcher zuvor über die PE Header rausgeparst wird, mit EBFE. 0xEBFE ist Assembler-Code für eine Endlosschleife, also ein Sprung der immer auf sich zurückgeht. Somit haben wir ein „laufendes“ Programm, welches aber noch nicht richtig gestartet ist. An diesem Punkt können wir bequem DLLs Injecten und im Anschluss den Prozess wieder anhalten. Der EntryPoint wird wiederhergestellt und der Prozess fortgesetzt, dieses mal allerdings mit einem richtigen Programmstart. Da der Blogpost zu dieser Injecten-Technique so gut geschrieben ist, spare ich mir Codesamples aus meinem Loader.

Das nächste Problem ist der Fenstermodus: Um bequem debuggen zu können ist ein Fenstermodus von nöten, da die maximized Fenster bei einem Breakpoint meist einfrieren und sich im Vordergrund befinden. So kann der Debugger unmöglich bedient werden. Das „rausspringen“ aus dem Fenster über ALT+TAB liefert eine viel geringere Auflösung und einen nativen Fenstermodus bringt Wolfteam nicht mit. DxWnd, das Tool das bereits bei Sieder 3 gute Dienste geleistet hat, erkennt bei einem normalen Programmstart von Wolfteam das Fenster und setzt selbstständig die Hooks. Nicht so, wenn kein Child-Prozess verwendet wird (den wir ja durch Patchen der ersten Schicht „deaktivert“ haben). So muss DxWnd zu seinem Glück gezwungen werden, d.h. wir injecten die DxWnd.dll einfach von „Hand“. Die Hooks werden dementsprechend gesetzt und das Fenster startet gepatched ebenfalls im Fenstermodus. Continue Reading

0

Apex AntiCheat – Erste Schicht einer großen Zwiebel

Da hat das Reverse Engineering Fieber wieder zugeschlagen und mir dieses mal einen sehr hartnäckigen Gegner entgegen geworfen: Ein Anti-Cheat System Namens Apex (Avital), welches u.a. von den Spielen Wolfteam und StarGateZ verwendet wird. Im konkreten wird es in dieser Serie um das (hoffentliche erfolgreiche) Bypassen des AntiCheats für Wolfteam gehen.

BackGround

Fangen wir mit ein paar Basics an und analysieren, wo wir Apex vermuten: Im Ordner von Wolfteam gibt es einen Unterordner „avital“ mit verschiedensten Dateien drin:

axxalog, TrayDlg.bin, ApexProgress.da_, LoadSysControl.da_, ApexProgress.dat, LoadSysControl.dat, SysDownLoad.dll, SysLoad.dll, TrayDlg.dll, ApexProgress.exe, LoadSysControl.exe, Config.ini, vssver2.scc, update.u, apexprogress.xoe, bootthunker.xoe, childprocboot.xoe, childprocfuncloader.xoe, chk.xoe, initgamer.xoe, loaddrv.xoe, packmodboot.xoe, parentprocboot.xoe, parentprocfuncloader.xoe, showerrorinfo.xoe, thegameonlymod.xoe, trdlg.xoe, usedrv.xoe, webd.xoe, AXCMN_DRVMAIN.XSE, axpack.xse

Die .xoe Dateien sind lediglich unbenannte DLL Dateien, welche jeweils 1-5 Funktionen exportieren. Diese werden per GetProcAddr geladen und anschließend aufgerufen. Damit können wir bisher wenig anfangen, denn alle Dateien einzeln zu analysieren wäre stundenlange Arbeit.

Der nächste Ansatz ist der Launcher, welcher Spieleupdates herrunterläd und Wolfteam im Anschluss Startet. Irgendwo hier muss auch Apex geladen werden! Die Vermutung liegt nahe, dass der Launcher das eigentliche Wolfteam-Spiel per CreateProcess startet, also direkt mal OllyDbg angeschmissen und reindebugged:

Address   Value      ASCII Comments
0018D108  /0018D388  ˆÓ   ; |ApplicationName = "C:\Program Files (x86)\Wolfteam\WolfTeam.bin"
0018D10C  |0018D490  Ô   ; |CommandLine = ""C:\Program Files (x86)\Wolfteam\WolfTeam.bin" easysurfer 6c65696465725f6e696368745f6d65696e5f7077 72"
0018D110  |00000000        ; |pProcessSecurity = NULL
0018D114  |00000000        ; |pThreadSecurity = NULL
0018D118  |00000000        ; |InheritHandles = FALSE
0018D11C  |00080000       ; |CreationFlags = 80000
0018D120  |00000000        ; |pEnvironment = NULL
0018D124  |00000000        ; |CurrentDirectory = NULL
0018D128  |0018D168  hÑ   ; |pStartupInfo = 0018D168 -> STARTUPINFOA {Size=72., Reserved1=NULL, Desktop=NULL, Title=NULL, X=0, Y=0, Width=0, Height=0, XCountChars=0, YCountChars=0, FillAttribute=0, Flags=0, ShowWindow=SW_HIDE, Reserved2=0, Reserved3=NULL, hStdInput=NULL, hStdOutput=
0018D12C  |0018D230  0Ò   ; \pProcessInformation = 0018D230 -> PROCESS_INFORMATION {hProcess=NULL, hThread=NULL, ProcessID=0 (0.), ThreadID=0}

Damit können wir doch schon mehr anfangen! Anscheinend startet der Launcher die Wolfteam.bin und übergibt als Argumente den Usernamen, das Passwort (Hex Codiert) und die Nummer 72, die vieleicht für das Patchlevel steht. In Zukunft brauchen wir den Launcher also nicht mehr, um Wolfteam zu starten! Wir Übergeben also Olly unsere Argumente und starten Wolfteam erneut, aber diesesmal direkt. Das Laden/Updaten des Anticheats blinkt kurz auf und schon ist unser Spiel im Fullscreen gestartet. Der Anticheat scheint also schnell geladen zu werden! In OllyDbg die Option setzen, dass er bei jedem neuen Module „anhalten“ soll schafft Abhilfe.

Continue Reading

0