
Analyse statique de rétro-ingénierie des heuristiques d'entrée de mouvement dans le moteur Source 2, identifiant les cas limites structurels dans l'automatisation des entrées et les routines de limitation du taux de saut.
server.dll)Ce document présente une analyse statique de rétro-ingénierie de deux routines de vérification de mouvement côté client implémentées dans le moteur Counter-Strike 2 (server.dll) : l'évaluateur d'automatisation d'entrée / SOCD (sub_1801C6B30, désigné CVE-2026-1801C / QUANTUM-SHIFT) et le limiteur de débit des requêtes de saut (sub_180A7EDB0, désigné CVE-2026-180A7 / BAL-JUMP). Grâce à l'analyse de désassemblage et à la modélisation mathématique formelle des machines à états sous-jacentes, nous démontrons des cas limites structurels dans les deux heuristiques. Plus précisément, nous documentons comment la quantification temporelle discrète dans sub_1801C6B30 crée une frontière de classification invariante sous des décalages de phase fixes à tick unique, et comment sub_180A7EDB0 repose sur une métrique d'intervalle univariée ($\Delta t$) qui reste invariante sous des déclencheurs à impulsion unique verrouillés en phase.
sub_1801C6B30)server.dll (build commercial Win64)0x1C6B30void __fastcall sub_1801C6B30(int *pMovementServices, __int64 pPlayerController, __int64 pUserCmdPB)La routine évalue les événements de transition des boutons de mouvement (+moveleft / +moveright) soumis via les charges utiles client CBaseUserCmdPB. L'exécution suit un pipeline conditionnel :
sv_auto_cstrafe_attempt_window, valeur par défaut 100).sub_1801C6B30)void __fastcall sub_1801C6B30(int *pMovementServices, __int64 pPlayerController, __int64 pUserCmdPB)
{
if (!pPlayerController || (*(_BYTE *)(pUserCmdPB + 16) & 1) == 0)
return;
__int64 pPawn = sub_180B137A0(pPlayerController);
if (!pPawn || !(*(unsigned __int8 (__fastcall **)(__int64))(*(_QWORD *)pPawn + 3216i64))(pPawn))
return;
float *pVel = (float *)sub_1803CBD90(pPawn, &szVelocityBuf);
float vSq = (pVel[0] * pVel[0]) + (pVel[1] * pVel[1]) + (pVel[2] * pVel[2]);
// Filtrage : Seuil de vélocité minimale
if (vSq <= 18279.04f)
return;
int rawTicks = *(_DWORD *)(pUserCmdPB + 24);
bool bIsOverlap = (rawTicks >= 0);
int absTicks = bIsOverlap ? rawTicks : ~rawTicks;
double curTime = sub_1801F46D0(off_181C9F350);
if (curTime * 1e-9 * (double)absTicks >= 15.5)
return;
int roundedTicks = (int)V_roundd();
if ((unsigned int)roundedTicks > 15)
return;
// Attribution de symbole
char symbolCode;
if (roundedTicks == 0)
symbolCode = 1; // Succès / 0-tick parfait
else
symbolCode = bIsOverlap ? 2 : 3; // Chevauchement ou Sous-chevauchement
// Récupération des pointeurs de configuration ConVar
unsigned int windowCap = *GetConVarUInt(&unk_181DDBD30, &qword_181DDBD38);
if (windowCap - 1 > 999)
return;
sub_1801ECEA0(pMovementServices, windowCap);
// Ajout du symbole au tampon circulaire
int bufCap = pMovementServices[0];
if (bufCap > 0)
{
int writeIdx = pMovementServices[6];
if (writeIdx >= 0 && writeIdx < bufCap)
{
*(_BYTE *)(writeIdx + *((_QWORD *)pMovementServices + 1)) = symbolCode;
if (++pMovementServices[6] == bufCap)
pMovementServices[6] = 0;
}
}
// Mise à jour des histogrammes de fréquence de ticks discrets
if (bIsOverlap)
pMovementServices[roundedTicks + 7]++;
else
pMovementServices[roundedTicks + 23]++;
int seqLen = *GetConVarInt(&unk_181DDBD40, &qword_181DDBD48);
if ((unsigned int)(seqLen - 1) > 999)
return;
// Évaluation des métriques de séquence en fenêtre glissante
int totalValid = 0;
int totalOverlaps = 0;
int curSequenceSuccesses = 0;
int maxSequenceSuccesses = 0;
for (int i = 0; i < (int)windowCap; ++i)
{
if (i < bufCap)
{
int readIdx = i + pMovementServices[6] - bufCap;
if (i + pMovementServices[6] < bufCap)
readIdx = i + pMovementServices[6];
char sym = *(_BYTE *)(readIdx + *((_QWORD *)pMovementServices + 1));
if (sym != 0)
{
totalValid++;
if (sym == 2) totalOverlaps++;
else if (sym == 1) curSequenceSuccesses++;
}
}
// Mise à jour de la fenêtre glissante
if (i >= seqLen && (i - seqLen) >= 0)
{
if ((i - seqLen) < bufCap)
{
int popIdx = i + pMovementServices[6] - seqLen - bufCap;
if (i + pMovementServices[6] - seqLen < bufCap)
popIdx = i + pMovementServices[6] - seqLen;
if (*(_BYTE *)(popIdx + *((_QWORD *)pMovementServices + 1)) == 1)
curSequenceSuccesses--;
}
}
if (maxSequenceSuccesses < curSequenceSuccesses)
maxSequenceSuccesses = curSequenceSuccesses;
}
int minAttempts = *GetConVarInt(&unk_181DDBD20, &qword_181DDBD28);
float dynamicLimit = 0.0f;
if (totalValid >= minAttempts)
{
int minSuccessThreshold = *GetConVarInt(&unk_181DDBD50, &qword_181DDBD58);
if (maxSequenceSuccesses >= minSuccessThreshold)
{
float successRatio = 0.0f;
if (seqLen > minSuccessThreshold)
{
successRatio = (float)(maxSequenceSuccesses - minSuccessThreshold) /
(float)(seqLen - minSuccessThreshold);
}
float lowerPct = *GetConVarFloat(&unk_181DDBD70, &qword_181DDBD78); // Défaut 20.0%
float upperPct = *GetConVarFloat(&unk_181DDBD60, &qword_181DDBD68); // Défaut 5.0%
dynamicLimit = (lowerPct - upperPct) * successRatio + upperPct;
}
}
float observedOverlapPct = ((float)totalOverlaps / (float)totalValid) * 100.0f;
// Condition de violation : La limite dynamique dépasse le ratio de chevauchement observé
if (dynamicLimit > observedOverlapPct)
{
sub_1801ECEA0(pMovementServices, 0); // Vidage de l'état du tampon
bool bEnableKick = *GetConVarByte(&unk_181DDBD90, &qword_181DDBD98);
if (bEnableKick)
{
__int64 pEngine = qword_182012050;
void (__fastcall *pfnKickClient)(__int64, unsigned int, _QWORD, __int64) =
*(void (__fastcall **)(__int64, unsigned int, _QWORD, __int64))(*(_QWORD *)pEngine + 768i64);