Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-1801C — تحليل هندسة عكسية ثابتة لاستدلالات إدخال الحركة في محرك Source 2، مع تحديد الحالات الحدودية البنيوية في أتمتة الإدخال وروتينات الحد من معدل القفز. | Kitploit
أدوات/GitHubGitHub/misterdengi/cve-2026-1801c
تحليل الثغرات الأمنيةالاستغلالالهندسة العكسيةتحليل الملفات الثنائيةالأوراق والأبحاث
GitHubmisterdengi/cve-2026-1801c

CVE-2026-1801C

تحليل هندسة عكسية ثابتة لاستدلالات إدخال الحركة في محرك Source 2، مع تحديد الحالات الحدودية البنيوية في أتمتة الإدخال وروتينات الحد من معدل القفز.

عرض المستودع
23منذ شهر واحدلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

CVE-2026-1801C (QUANTUM-SHIFT) / CVE-2026-180A7 (BAL-JUMP): تحليل ثابت لخوارزميات التحقق من مدخلات الحركة في Source 2 (server.dll)

الملخص

تقدّم هذه الورقة تحليلاً هندسيًا عكسيًا ثابتًا لروتينين للتحقق من الحركة من جانب العميل مطبّقين في محرك Counter-Strike 2 (server.dll): مُقيّم أتمتة الإدخال / SOCD (sub_1801C6B30، المعيّن CVE-2026-1801C / QUANTUM-SHIFT) ومُحدِّد معدل طلبات القفز (sub_180A7EDB0، المعيّن CVE-2026-180A7 / BAL-JUMP). من خلال تحليل التفكيك والنمذجة الرياضية الرسمية لآلات الحالة الأساسية، نُظهر حالات حافة بنيوية في كلا الخوارزميتين. على وجه التحديد، نوثّق كيف يُنشئ التكميم الزمني المنفصل في sub_1801C6B30 حدًا تصنيفيًا ثابتًا تحت إزاحات طورية ثابتة بإطار واحد، وكيف يعتمد sub_180A7EDB0 على مقياس فاصل زمني أحادي المتغير ($\Delta t$) يبقى ثابتًا تحت محفزات نبضية مفردة مقفلة الطور.


1. التحقق من أتمتة الإدخال (sub_1801C6B30)

1.1 مواصفات الروتين

  • الملف الثنائي المستهدف: server.dll (إصدار Win64 Retail)
  • إزاحة الرمز: 0x1C6B30
  • الواجهة: void __fastcall sub_1801C6B30(int *pMovementServices, __int64 pPlayerController, __int64 pUserCmdPB)

1.2 خط أنابيب التنفيذ وتمثيل الحالة

يقيّم الروتين أحداث انتقال أزرار الحركة (+moveleft / +moveright) المُرسلة عبر حمولات CBaseUserCmdPB من العميل. يتبع التنفيذ خط أنابيب شرطيًا:

  1. بوابة السرعة: يجب أن يتجاوز مربع مقدار السرعة العددية ثنائية الأبعاد للشخصية عتبة ثابتة: $$|v_{xy}|^2 > (0.52 \cdot 260.0)^2 = 18279.04 \text{ وحدة}^2/\text{ثانية}^2$$
  2. التكميم الزمني: يتم تكميم فروق طور الانتقال ($\Delta t_{\text{trans}}$) إلى وحدات إطارات منفصلة: $$k = \text{round}\left( \frac{\Delta t_{\text{trans}}}{\tau_{\text{tick}}} \right), \quad \tau_{\text{tick}} \approx 15.625\text{ مللي ثانية}$$
  3. التصنيف الرمزي: القيمة الصحيحة $k \in [0, 15]$ تُرسم إلى رمز حدث منفصل $c \in {1, 2, 3}$: $$c = \begin{cases} 1 & \text{إذا كان } k = 0 \text{ (انتقال مثالي بصفر إطار)} \ 2 & \text{إذا كان } k \ge 1 \text{ والحالة Overlap} \ 3 & \text{إذا كان } k \ge 1 \text{ والحالة Underlap} \end{cases}$$
  4. تخزين الحلقة الدائرية: يُخزَّن رمز التصنيف $c$ في مصفوفة تاريخ دائرية بسعة $N$ (sv_auto_cstrafe_attempt_window، الافتراضي 100).

1.3 المنطق المُفكَّك (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]);
    
    // Gating: Minimum velocity threshold
    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;

    // Symbol Assignment
    char symbolCode;
    if (roundedTicks == 0)
        symbolCode = 1; // Success / Perfect 0-tick
    else
        symbolCode = bIsOverlap ? 2 : 3; // Overlap or Underlap

    // Fetch ConVar configuration pointers
    unsigned int windowCap = *GetConVarUInt(&unk_181DDBD30, &qword_181DDBD38);
    if (windowCap - 1 > 999)
        return;

    sub_1801ECEA0(pMovementServices, windowCap);

    // Append symbol to circular buffer
    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;
        }
    }

    // Update discrete tick frequency histograms
    if (bIsOverlap)
        pMovementServices[roundedTicks + 7]++;
    else
        pMovementServices[roundedTicks + 23]++;

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

    // Evaluate sliding window sequence metrics
    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++;
            }
        }

        // Sliding window update
        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); // Default 20.0%
            float upperPct = *GetConVarFloat(&unk_181DDBD60, &qword_181DDBD68); // Default 5.0%
            
            dynamicLimit = (lowerPct - upperPct) * successRatio + upperPct;
        }
    }

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

    // Violation Condition: Dynamic limit exceeds observed overlap ratio
    if (dynamicLimit > observedOverlapPct)
    {
        sub_1801ECEA0(pMovementServices, 0); // Flush buffer state
        
        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);
            
            // Disconnect Code 162: NETWORK_DISCONNECT_KICKED_INPUTAUTOMATION
            pfnKickClient(pEngine, (unsigned int)(slotIdx - 1), 0, 162);
        }
    }
}

1.4 النموذج الرياضي وتحليل التصنيف

لنفترض أن $\mathbf{S} = {s_1, s_2, \dots, s_N}$ يمثل تسلسل رموز الأحداث في مخزن التاريخ بحجم $N$. تشير المعلمة $S_{\text{max}}$ إلى الحد الأقصى لعدد رموز الكود $1$ ($s_i = 1$) داخل أي تسلسل فرعي متصل بطول $L$:

$$S_{\text{max}} = \max_{0 \le j \le N - L} \sum_{i=j}^{j+L-1} \mathbb{I}(s_i = 1)$$

دالة العتبة التكيفية $T(S_{\text{max}})$ مشروطة بـ $S_{\text{max}} \ge S_{\text{thresh}}$:

تنزيل الأداة