Skip to content

Commit

Permalink
Merge pull request #433 from ao-org/anticheat
Browse files Browse the repository at this point in the history
Integrate Epic EOS anti cheat
  • Loading branch information
RecoX authored Nov 6, 2023
2 parents 8ff4640 + 58ce21c commit fe0fa81
Show file tree
Hide file tree
Showing 14 changed files with 236 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ feature_toggle.ini
Logs/numusers.log
Database.db
AoServerTools.dll
AOACServer.pdb
Binary file added AOACServer.dll
Binary file not shown.
177 changes: 177 additions & 0 deletions Codigo/AntiCheat.bas
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
Attribute VB_Name = "AntiCheat"
Option Explicit


Public Enum e_ACInitResult
eOk = 0
eFailedPlatform
eFAiledConnectAC
End Enum

Private Type SINGLESTRINGPARAM
Ptr As Long
Len As Long
End Type

Public Type t_AntiCheatCallbacks
SendToClient As Long
LogMessage As Long
RegisterRemoteUserId As Long
ActionRequired As Long
End Type

Public Enum e_ActionRequiredType
eEOS_ACCCA_Invalid = 0
eEOS_ACCCA_RemovePlayer = 1
End Enum

Public Enum e_ActionRequiredReason
eEOS_ACCCAR_Invalid = 0
eEOS_ACCCAR_InternalError = 1
eEOS_ACCCAR_InvalidMessage = 2
eEOS_ACCCAR_AuthenticationFailed = 3
eEOS_ACCCAR_NullClient = 4
eEOS_ACCCAR_HeartbeatTimeout = 5
eEOS_ACCCAR_ClientViolation = 6
eEOS_ACCCAR_BackendViolation = 7
eEOS_ACCCAR_TemporaryCooldown = 8
eEOS_ACCCAR_TemporaryBanned = 9
eEOS_ACCCAR_PermanentBanned = 10
End Enum

Public Enum EOS_ELogLevel
EOS_LOG_Off = 0
EOS_LOG_Fatal = 100
EOS_LOG_Error = 200
EOS_LOG_Warning = 300
EOS_LOG_Info = 400
EOS_LOG_Verbose = 500
EOS_LOG_VeryVerbose = 600
End Enum

Private Declare Function InitializeAC Lib "AOACServer.dll" (ByRef Callbacks As t_AntiCheatCallbacks) As Long
Private Declare Sub UnloadAC Lib "AOACServer.dll" ()
Private Declare Sub Update Lib "AOACServer.dll" ()
Private Declare Sub AddPendingRegister Lib "AOACServer.dll" (ByRef UserReference As t_UserReference)
Private Declare Function QueryAndRemoveOldPendingRegistey Lib "AOACServer.dll" (ByRef UserReference As t_UserReference, ByVal ElapsedThreshold As Long) As Long
Private Declare Sub UnRegisterClient Lib "AOACServer.dll" (ByVal UserIndex As Integer)
Private Declare Sub HandleRemoteMessage Lib "AOACServer.dll" (ByRef UserReference As t_UserReference, ByRef Data As Byte, ByVal DataSize As Integer)

Dim EnableAnticheat As Boolean

Private Function GetStringFromPtr(ByVal Ptr As Long, ByVal size As Long) As String
Dim Buffer() As Byte
ReDim Buffer(0 To (size - 1)) As Byte
CopyMemory Buffer(0), ByVal Ptr, size
GetStringFromPtr = StrConv(Buffer, vbUnicode)
End Function

Private Function FARPROC(pfn As Long) As Long
FARPROC = pfn
End Function

Public Sub InitializeAntiCheat()
On Error GoTo InitializeAC_Err
EnableAnticheat = IsFeatureEnabled("anti-cheat")
If EnableAnticheat Then
Dim InitResult As e_ACInitResult
Dim Callbacks As t_AntiCheatCallbacks
Callbacks.SendToClient = FARPROC(AddressOf SendToClientCB)
Callbacks.LogMessage = FARPROC(AddressOf LogMessageCB)
Callbacks.RegisterRemoteUserId = FARPROC(AddressOf RegisterRemoteUserIdCb)
Callbacks.ActionRequired = FARPROC(AddressOf ClientActionRequired)
InitResult = InitializeAC(Callbacks)
If InitResult <> eOk Then
Call MsgBox("El juego se inicio sin activar el anti cheat, debe activarlo para poder conectarse a los servidores.")
End If
End If
Exit Sub
InitializeAC_Err:
Call TraceError(Err.Number, Err.Description, "AOAC.InitializeAC", Erl)
End Sub

Public Sub OnNewPlayerConnect(ByVal UserIndex As Integer)
If EnableAnticheat Then
Dim UserRef As t_UserReference
Call SetUserRef(UserRef, UserIndex)
Call AddPendingRegister(UserRef)
Call WriteAntiCheatStartSeassion(UserIndex)
End If
End Sub

Public Sub KickUnregisteredPlayers()
If EnableAnticheat Then
Dim UserRef As t_UserReference
Dim Result As Long
Result = QueryAndRemoveOldPendingRegistey(UserRef, 10000)
If Result > 0 And IsValidUserRef(UserRef) Then
Call modNetwork.Kick(UserList(UserRef.ArrayIndex).ConnectionDetails.ConnID, "Anticheat detection timeout")
End If
End If
End Sub

Public Sub AntiCheatUpdate()
If EnableAnticheat Then
Call Update
Call KickUnregisteredPlayers
End If
End Sub

Public Sub UnloadAntiCheat()
If EnableAnticheat Then
Call UnloadAC
End If
End Sub
Public Sub SendToClientCB(ByRef TargetUser As t_UserReference, ByVal Data As Long, ByVal DataSize As Long)
If EnableAnticheat Then
If IsValidUserRef(TargetUser) Then
Call WriteAntiCheatMessage(TargetUser.ArrayIndex, Data, DataSize)
End If
End If
End Sub

Public Sub HandleAntiCheatServerMessage(ByVal UserIndex As Integer, ByRef Data() As Byte)
If EnableAnticheat Then
Dim UserRef As t_UserReference
Call SetUserRef(UserRef, UserIndex)
Call HandleRemoteMessage(UserRef, Data(0), UBound(Data))
End If
End Sub

Public Sub LogMessageCB(ByRef Message As SINGLESTRINGPARAM, ByVal LogLevel As Long)
Dim MessageStr As String
If Message.Len > 0 Then
MessageStr = GetStringFromPtr(Message.Ptr, Message.Len)
End If
If LogLevel Then
End If
If LogLevel < EOS_LOG_Warning Then
Call LogThis(0, "Anticheat: " & MessageStr, vbLogEventTypeError)
End If
End Sub

Public Sub RegisterRemoteUserIdCb(ByRef UserRef As t_UserReference, ByRef Id As SINGLESTRINGPARAM)
Dim IdStr As String
If Id.Len > 0 Then
IdStr = GetStringFromPtr(Id.Ptr, Id.Len)
End If
If IsValidUserRef(UserRef) Then
Call SaveEpicLogin(IdStr, UserRef.ArrayIndex)
End If
End Sub

Public Sub ClientActionRequired(ByRef UserRef As t_UserReference, ByVal Action As Long, ByVal ReasonCode As Long, ByRef ReasonString As SINGLESTRINGPARAM)
Dim ReasonStr As String
If ReasonString.Len > 0 Then
ReasonStr = GetStringFromPtr(ReasonString.Ptr, ReasonString.Len)
End If
If Action = eEOS_ACCCA_RemovePlayer And IsValidUserRef(UserRef) Then
Call modNetwork.Kick(UserList(UserRef.ArrayIndex).ConnectionDetails.ConnID, ReasonStr)
End If
End Sub

Public Sub OnPlayerDisconnect(ByVal UserIndex As Integer)
If EnableAnticheat Then
Call UnRegisterClient(UserIndex)
End If
End Sub
9 changes: 4 additions & 5 deletions Codigo/General.bas
Original file line number Diff line number Diff line change
Expand Up @@ -737,9 +737,7 @@ Sub Main()
'Ocultar
330 Call frmMain.InitMain(HideMe)




Call InitializeAntiCheat


332 tInicioServer = GetTickCount()
Expand Down Expand Up @@ -775,6 +773,8 @@ Sub Main()
Call PerformTimeLimitCheck(PerformanceTimer, "General Update Effects over time")
DoEvents
Call PerformTimeLimitCheck(PerformanceTimer, "Do events")
Call AntiCheatUpdate
Call PerformTimeLimitCheck(PerformanceTimer, "Update anti cheat")
' Unlock main loop for maximum throughput but it can hog weak CPUs.
#If UNLOCK_CPU = 0 Then
Call Sleep(1)
Expand All @@ -784,7 +784,6 @@ Sub Main()
Call UnitClient.Poll
#End If
Wend

Call LogThis(0, "Closing the server " & Now, vbLogEventTypeInformation)
Exit Sub
Handler:
Expand Down Expand Up @@ -2243,7 +2242,7 @@ Public Sub CerrarServidor()
110 Call CloseSocket(LoopC)
End If
Next

Call UnloadAntiCheat
112 If Database_Enabled Then Database_Close

124 End
Expand Down
1 change: 1 addition & 0 deletions Codigo/Modulo_UsUaRiOs.bas
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ On Error GoTo Complete_ConnectUser_Err
End If
Call RestoreDCUserCache(UserIndex)
Call CustomScenarios.UserConnected(userIndex)
Call AntiCheat.OnNewPlayerConnect(UserIndex)
End With


Expand Down
3 changes: 3 additions & 0 deletions Codigo/PacketId.bas
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ Public Enum ServerPacketID
eRequestTelemetry
eUpdateCharValue 'updates some char index value based on enum
eSendClientToggles 'Get active feature Toggles from server
eAntiCheatMessage
eAntiCheatStartSession
eReportLobbyList
#If PYMMO = 0 Then
eAccountCharacterList
Expand Down Expand Up @@ -533,6 +535,7 @@ Public Enum ClientPacketID
eSendTelemetry
eSetHotkeySlot
eUseHKeySlot
eAntiCheatMessage
eRequestLobbyList
#If PYMMO = 0 Then
eCreateAccount
Expand Down
14 changes: 13 additions & 1 deletion Codigo/Protocol.bas
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,8 @@ On Error Resume Next
Call HandleSetHotkeySlot(UserIndex)
Case ClientPacketID.eUseHKeySlot
Call HandleUseHKeySlot(UserIndex)
Case ClientPacketID.eAntiCheatMessage
Call HandleAntiCheatMessage(UserIndex)
#If PYMMO = 0 Then
Case ClientPacketID.eCreateAccount
Call HandleCreateAccount(ConnectionId)
Expand Down Expand Up @@ -10725,9 +10727,19 @@ HandleUseHKeySlot_Err:
Call TraceError(Err.Number, Err.Description, "Protocol.HandleUseHKeySlot", Erl)
End Sub


Public Sub HandleAntiCheatMessage(ByVal UserIndex As Integer)
On Error GoTo AntiCheatMessage_Err:
Dim Data() As Byte
Call Reader.ReadSafeArrayInt8(Data)
Call HandleAntiCheatServerMessage(UserIndex, Data)
Exit Sub
AntiCheatMessage_Err:
Call TraceError(Err.Number, Err.Description, "Protocol.AntiCheatMessage", Erl)
End Sub

Public Sub HendleRequestLobbyList(ByVal UserIndex As Integer)
On Error GoTo HendleRequestLobbyList_Err:

Call WriteUpdateLobbyList(UserIndex)
Exit Sub
HendleRequestLobbyList_Err:
Expand Down
24 changes: 24 additions & 0 deletions Codigo/Protocol_Writes.bas
Original file line number Diff line number Diff line change
Expand Up @@ -5854,6 +5854,30 @@ PrepareActiveToggles_Err:
Call TraceError(Err.Number, Err.Description, "Argentum20Server.Protocol_Writes.PrepareActiveToggles", Erl)
End Function

Public Sub WriteAntiCheatMessage(ByVal UserIndex As Integer, ByVal Data As Long, ByVal DataSize As Long)
On Error GoTo WriteAntiCheatMessage_Err
Dim Buffer() As Byte
ReDim Buffer(0 To (DataSize - 1)) As Byte
CopyMemory Buffer(0), ByVal Data, DataSize
Call Writer.WriteInt16(ServerPacketID.eAntiCheatMessage)
Call Writer.WriteSafeArrayInt8(Buffer)
Call modSendData.SendData(ToIndex, UserIndex)
Exit Sub
WriteAntiCheatMessage_Err:
Call Writer.Clear
Call TraceError(Err.Number, Err.Description, "Argentum20.Protocol_Writes.WriteAntiCheatMessage", Erl)
End Sub

Public Sub WriteAntiCheatStartSeassion(ByVal UserIndex As Integer)
On Error GoTo WriteAntiStartSeassion_Err
Call Writer.WriteInt16(ServerPacketID.eAntiCheatStartSession)
Call modSendData.SendData(ToIndex, UserIndex)
Exit Sub
WriteAntiStartSeassion_Err:
Call Writer.Clear
Call TraceError(Err.Number, Err.Description, "Argentum20.Protocol_Writes.WriteAntiStartSeassion", Erl)
End Sub

Public Sub WriteUpdateLobbyList(ByVal UserIndex As Integer)
On Error GoTo WriteUpdateLobbyList_Err
Dim IdList() As Integer
Expand Down
1 change: 1 addition & 0 deletions Codigo/TCP.bas
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,7 @@ End Sub
Sub ResetUserSlot(ByVal UserIndex As Integer)
On Error GoTo ResetUserSlot_Err
Call SaveDCUserCache(UserIndex)
Call AntiCheat.OnPlayerDisconnect(UserIndex)
With UserList(UserIndex)
100 .ConnectionDetails.ConnIDValida = False
102 .ConnectionDetails.ConnID = 0
Expand Down
4 changes: 4 additions & 0 deletions Codigo/modDatabase.bas
Original file line number Diff line number Diff line change
Expand Up @@ -1081,3 +1081,7 @@ End Sub
Public Sub ResetLastLogoutAndIsLogged()
Call Execute("Update user set last_logout = 0, is_logged = 0")
End Sub

Public Sub SaveEpicLogin(ByVal Id As String, ByVal UserIndex As Integer)
Call Query("insert or replace into epic_id_mapping (epic_id, user_id, last_login) values ( ?, ?, strftime('%s','now'))", Id, UserList(UserIndex).Id)
End Sub
1 change: 0 additions & 1 deletion Codigo/modNetwork.bas
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ Private Sub OnServerConnect(ByVal Connection As Long, ByVal Address As String)
End With
136 Call PendingConnections.Add(Connection, Connection)
138 Call modSendData.SendToConnection(Connection, PrepareConnected())
140 Debug.Print "Handle new connection"
Else
142 Call Kick(Connection, "El server se encuentra lleno en este momento. Disculpe las molestias ocasionadas.")
End If
Expand Down
Binary file added EOSSDK-Win32-Shipping.dll
Binary file not shown.
7 changes: 7 additions & 0 deletions ScriptsDB/20231101-01- add epic support.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS "epic_id_mapping" (
"epic_id" varchar(64) NOT NULL,
"user_id" integer NOT NULL,
"last_login" integer NOT NULL,
CONSTRAINT "fk_epic_id_mapping" FOREIGN KEY("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE,
CREATE UNIQUE INDEX epic_id_mapping_idx ON data(epic_id, user_id);
);
1 change: 1 addition & 0 deletions Server.VBP
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ Class=BonusDamageEffect; Codigo\EffectOverTime\BonusDamageEffect.cls
Class=NavalBoarding; Codigo\Scenearios\NavalBoarding.cls
Class=IInventoryInterface; Codigo\Scenearios\IInventoryInterface.cls
Module=PacketId; Codigo\PacketId.bas
Module=AntiCheat; Codigo\AntiCheat.bas
Module=InstanceManager; Codigo\InstanceManager.bas
IconForm="frmMain"
Startup="Sub Main"
Expand Down

0 comments on commit fe0fa81

Please sign in to comment.