Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-1801C — Análise estática de engenharia reversa das heurísticas de entrada de movimento no motor Source 2, identificando casos extremos estruturais na automação de entrada e nas rotinas de limitação de taxa de salto. | Kitploit
Ferramentas/GitHubGitHub/misterdengi/cve-2026-1801c
Análise de VulnerabilidadesExploraçãoEngenharia ReversaAnálise de BináriosPapers e Pesquisa
GitHubmisterdengi/cve-2026-1801c

CVE-2026-1801C

Análise estática de engenharia reversa das heurísticas de entrada de movimento no motor Source 2, identificando casos extremos estruturais na automação de entrada e nas rotinas de limitação de taxa de salto.

Ver Repositório
24há 1 mêsAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-1801C (QUANTUM-SHIFT) / CVE-2026-180A7 (BAL-JUMP): Análise Estática de Heurísticas de Entrada de Movimento no Source 2 (server.dll)

Resumo

Este artigo apresenta uma análise estática de engenharia reversa de duas rotinas de verificação de movimento no lado do cliente implementadas no motor do Counter-Strike 2 (server.dll): o avaliador de automação de entrada / SOCD (sub_1801C6B30, designado CVE-2026-1801C / QUANTUM-SHIFT) e o limitador de taxa de solicitações de pulo (sub_180A7EDB0, designado CVE-2026-180A7 / BAL-JUMP). Através de análise de desmontagem e modelagem matemática formal das máquinas de estado subjacentes, demonstramos casos extremos estruturais em ambas as heurísticas. Especificamente, documentamos como a quantização temporal discreta em sub_1801C6B30 cria uma fronteira de classificação invariante sob deslocamentos de fase fixos de tick único, e como sub_180A7EDB0 depende de uma métrica de intervalo univariante ($\Delta t$) que permanece invariante sob gatilhos de impulso único com bloqueio de fase.


1. Verificação de Automação de Entrada (sub_1801C6B30)

1.1 Especificação da Rotina

  • Binário Alvo: server.dll (Build Retail Win64)
  • Offset do Símbolo: 0x1C6B30
  • Interface: void __fastcall sub_1801C6B30(int *pMovementServices, __int64 pPlayerController, __int64 pUserCmdPB)

1.2 Pipeline de Execução e Representação de Estado

A rotina avalia eventos de transição de botões de movimento (+moveleft / +moveright) enviados via payloads CBaseUserCmdPB do cliente. A execução segue um pipeline condicional:

  1. Filtragem de Velocidade: A magnitude escalar ao quadrado da velocidade 2D do pawn do jogador deve exceder um limite estático: $$|v_{xy}|^2 > (0.52 \cdot 260.0)^2 = 18279.04 \text{ unit}^2/\text{s}^2$$
  2. Quantização Temporal: Os deltas de fase de transição ($\Delta t_{\text{trans}}$) são quantizados em unidades discretas de ticks de quadro: $$k = \text{round}\left( \frac{\Delta t_{\text{trans}}}{\tau_{\text{tick}}} \right), \quad \tau_{\text{tick}} \approx 15.625\text{ ms}$$
  3. Classificação Simbólica: O valor inteiro $k \in [0, 15]$ mapeia para um código de evento discreto $c \in {1, 2, 3}$: $$c = \begin{cases} 1 & \text{se } k = 0 \text{ (Transição ideal de 0 tick)} \ 2 & \text{se } k \ge 1 \text{ e o estado é Overlap} \ 3 & \text{se } k \ge 1 \text{ e o estado é Underlap} \end{cases}$$
  4. Armazenamento em Buffer Circular: O código de classificação $c$ é armazenado em um array de histórico circular com capacidade $N$ (sv_auto_cstrafe_attempt_window, padrão 100).

1.3 Lógica Decompilada (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]);
    
    // Filtragem: Limite mínimo de velocidade
    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;

    // Atribuição de Símbolo
    char symbolCode;
    if (roundedTicks == 0)
        symbolCode = 1; // Sucesso / 0-tick perfeito
    else
        symbolCode = bIsOverlap ? 2 : 3; // Overlap ou Underlap

    // Buscar ponteiros de configuração ConVar
    unsigned int windowCap = *GetConVarUInt(&unk_181DDBD30, &qword_181DDBD38);
    if (windowCap - 1 > 999)
        return;

    sub_1801ECEA0(pMovementServices, windowCap);

    // Anexar símbolo ao buffer circular
    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;
        }
    }

    // Atualizar histogramas de frequência de ticks discretos
    if (bIsOverlap)
        pMovementServices[roundedTicks + 7]++;
    else
        pMovementServices[roundedTicks + 23]++;

    int seqLen = *GetConVarInt(&unk_181DDBD40, &qword_181DDBD48);
    if ((unsigned int)(seqLen - 1) > 999)
        return;

    // Avaliar métricas de sequência de janela deslizante
    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++;
            }
        }

        // Atualização da janela deslizante
        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); // Padrão 20.0%
            float upperPct = *GetConVarFloat(&unk_181DDBD60, &qword_181DDBD68); // Padrão 5.0%
            
            dynamicLimit = (lowerPct - upperPct) * successRatio + upperPct;
        }
    }

    float observedOverlapPct = ((float)totalOverlaps / (float)totalValid) * 100.0f;

    // Condição de Violação: Limite dinâmico excede a proporção de overlap observada
    if (dynamicLimit > observedOverlapPct)
    {
        sub_1801ECEA0(pMovementServices, 0); // Limpar estado do buffer
        
        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);

            int slotIdx = -1;
            sub_181265470(pPlayerController, &slotIdx);
            
            // Código de Desconexão 162: NETWORK_DISCONNECT_KICKED_INPUTAUTOMATION
            pfnKickClient(pEngine, (unsigned int)(slotIdx - 1), 0, 162);
        }
    }
}

1.4 Modelo Matemático e Análise de Classificação

Baixar ferramenta