// Detect It Easy: detection rule file
// Author: Levis <levintaeyeon@live.com>
// History:
// Update sign to detect version of Python from 1.0 to 3.4
// Update sign to detect version of Python from 3.4 to 3.13a1 (by LinXP)
// Update sign to detect forks of Python and Some other versions (by northkatz)
// Full info: https://github.com/python/cpython/blob/main/Lib/importlib/_bootstrap_external.py#L463
// Version history: https://github.com/python/cpython/blob/main/Include/internal/pycore_magic_number.h

meta("format", "Python Compiled Module");

function detect() {
    if (Binary.getSize() >= 64) {
        if (Binary.read_uint16(0x02) == 0x0099) {
            bDetected = true;
            switch (Binary.read_uint32(0)) {
                case 0x00999902: sVersion = "1.0"; break;
                case 0x00999903: sVersion = "1.1-1.2"; break;
                default: return;
            }
        } else if (Binary.read_uint16(0x02) == 0x0A0D && Binary.isSignaturePresent(0x10, 0x100, "00 00 00 00")) {
            bDetected = true;
            var magicValue = Binary.read_uint16(0);
            switch (magicValue) {
                case 11913: sVersion = "1.3"; break;
                case 5892: sVersion = "1.4"; break;
                case 20121: sVersion = "1.5-1.5.2"; break;
                case 50428: sVersion = "1.6"; break;
                case 50823: sVersion = "2.0-2.0.1"; break;
                case 60202: sVersion = "2.1-2.1.2"; break;
                case 60717: sVersion = "2.2"; break;
                case 62011: sVersion = "2.3a0"; break;
                case 62021: sVersion = "2.3a0"; break;
                case 62041: sVersion = "2.4a0"; break;
                case 62051: sVersion = "2.4a3"; break;
                case 62061: sVersion = "2.4b1"; break;
                case 62071: sVersion = "2.5a0"; break;
                case 62081: sVersion = "2.5a0"; break;
                case 62091: sVersion = "2.5a0"; break;
                case 62092: sVersion = "2.5a0"; break;
                case 62101: sVersion = "2.5b3"; break;
                case 62111: sVersion = "2.5b3"; break;
                case 62121: sVersion = "2.5c1"; break;
                case 62131: sVersion = "2.5c2"; break;
                case 62135: sVersion = "2.5 (Dropbox)"; break;
                case 62151: sVersion = "2.6a0"; break;
                case 62161: sVersion = "2.6a1"; break;
                case 62171: sVersion = "2.7a0"; break;
                case 62181: sVersion = "2.7a0"; break;
                case 62191: sVersion = "2.7a0"; break;
                case 62201: sVersion = "2.7a0"; break;
                case 62211: sVersion = "2.7a0"; break;
                case 62218: sVersion = "2.7 (PyPy)"; break;
                case 22138: sVersion = "2.7 (Pyston)"; break;
                case 2657: sVersion = "2.7 (Pyston-0.6.1)"; break;
                case 3000: sVersion = "3.0"; break;
                case 3010: sVersion = "3.0"; break;
                case 3020: sVersion = "3.0"; break;
                case 3030: sVersion = "3.0"; break;
                case 3040: sVersion = "3.0"; break;
                case 3050: sVersion = "3.0"; break;
                case 3060: sVersion = "3.0"; break;
                case 3061: sVersion = "3.0"; break;
                case 3071: sVersion = "3.0"; break;
                case 3081: sVersion = "3.0"; break;
                case 3091: sVersion = "3.0"; break;
                case 3101: sVersion = "3.0"; break;
                case 3103: sVersion = "3.0"; break;
                case 3111: sVersion = "3.0a4"; break;
                case 3131: sVersion = "3.0b1"; break;
                case 3141: sVersion = "3.1a1"; break;
                case 3151: sVersion = "3.1a1"; break;
                case 3160: sVersion = "3.2a1"; break;
                case 3170: sVersion = "3.2a2"; break;
                case 3180: sVersion = "3.2a3"; break;
                case 48: sVersion = "3.2 or 3.2 (PyPy)"; break;
                case 3187: sVersion = "3.2 (PyPy)"; break;
                case 3190: sVersion = "3.3a1"; break;
                case 3200: sVersion = "3.3a1"; break;
                case 3210: sVersion = "3.3a1"; break;
                case 3220: sVersion = "3.3a2"; break;
                case 3230: sVersion = "3.3a4"; break;
                case 64: sVersion = "3.3 (PyPy)"; break;
                case 3250: sVersion = "3.4a1"; break;
                case 3260: sVersion = "3.4a1"; break;
                case 3270: sVersion = "3.4a1"; break;
                case 3280: sVersion = "3.4a1"; break;
                case 3290: sVersion = "3.4a4"; break;
                case 3300: sVersion = "3.4a4"; break;
                case 3310: sVersion = "3.4rc2"; break;
                case 3320: sVersion = "3.5a1"; break;
                case 3330: sVersion = "3.5b1"; break;
                case 3340: sVersion = "3.5b2"; break;
                case 3350: sVersion = "3.5b3"; break;
                case 3351: sVersion = "3.5.2"; break;
                case 112: sVersion = "3.5 (PyPy)"; break;
                case 3360: sVersion = "3.6a0"; break;
                case 3361: sVersion = "3.6a1"; break;
                case 3370: sVersion = "3.6a2"; break;
                case 3371: sVersion = "3.6a2"; break;
                case 3372: sVersion = "3.6a2"; break;
                case 3373: sVersion = "3.6b1"; break;
                case 3375: sVersion = "3.6b1"; break;
                case 3376: sVersion = "3.6b1"; break;
                case 3377: sVersion = "3.6b1"; break;
                case 3378: sVersion = "3.6b2"; break;
                case 3379: sVersion = "3.6rc1"; break;
                case 192: sVersion = "3.6 (PyPy)"; break;
                case 160: sVersion = "3.6.1 (PyPy)"; break;
                case 3390: sVersion = "3.7a1"; break;
                case 3391: sVersion = "3.7a2"; break;
                case 3392: sVersion = "3.7a4"; break;
                case 3393: sVersion = "3.7b1"; break;
                case 3394: sVersion = "3.7b5"; break;
                case 240: sVersion = "3.7 (PyPy)"; break;
                case 3400: sVersion = "3.8a1"; break;
                case 3401: sVersion = "3.8a1"; break;
                case 3410: sVersion = "3.8a1"; break;
                case 3411: sVersion = "3.8b2"; break;
                case 3412: sVersion = "3.8b2"; break;
                case 3413: sVersion = "3.8b4 or 3.8.10 (Graal) or 3.8.12-3.8.16 (PyPy)"; break;
                case 256: sVersion = "3.8 (PyPy)"; break;
                case 21150: sVersion = "3.8.5 (Graal)"; break;
                case 3420: sVersion = "3.9a0"; break;
                case 3421: sVersion = "3.9a0"; break;
                case 3422: sVersion = "3.9a0"; break;
                case 3423: sVersion = "3.9a2"; break;
                case 3424: sVersion = "3.9a2"; break;
                case 3425: sVersion = "3.9a2 or 3.9.10-3.9.16 (PyPy)"; break;
                case 336: sVersion = "3.9 (PyPy)"; break;
                case 3430: sVersion = "3.10a1"; break;
                case 3431: sVersion = "3.10a1"; break;
                case 3432: sVersion = "3.10a2"; break;
                case 3433: sVersion = "3.10a2"; break;
                case 3434: sVersion = "3.10a6"; break;
                case 3435: sVersion = "3.10a7"; break;
                case 3436: sVersion = "3.10b1"; break;
                case 3437: sVersion = "3.10b1"; break;
                case 3438: sVersion = "3.10b1"; break;
                case 3439: sVersion = "3.10b1"; break;
                case 384: sVersion = "3.10 (PyPy)"; break;
                case 21280: sVersion = "3.10 (Graal)"; break;
                case 3450: sVersion = "3.11a1"; break;
                case 3451: sVersion = "3.11a1"; break;
                case 3452: sVersion = "3.11a1"; break;
                case 3453: sVersion = "3.11a1"; break;
                case 3454: sVersion = "3.11a1"; break;
                case 3455: sVersion = "3.11a1"; break;
                case 3456: sVersion = "3.11a1"; break;
                case 3457: sVersion = "3.11a1"; break;
                case 3458: sVersion = "3.11a1"; break;
                case 3459: sVersion = "3.11a1"; break;
                case 3460: sVersion = "3.11a1"; break;
                case 3461: sVersion = "3.11a1"; break;
                case 3462: sVersion = "3.11a2"; break;
                case 3463: sVersion = "3.11a3"; break;
                case 3464: sVersion = "3.11a3"; break;
                case 3465: sVersion = "3.11a3"; break;
                case 3466: sVersion = "3.11a4"; break;
                case 3467: sVersion = "3.11a4"; break;
                case 3468: sVersion = "3.11a4"; break;
                case 3469: sVersion = "3.11a4"; break;
                case 3470: sVersion = "3.11a4"; break;
                case 3471: sVersion = "3.11a4"; break;
                case 3472: sVersion = "3.11a4"; break;
                case 3473: sVersion = "3.11a4"; break;
                case 3474: sVersion = "3.11a4"; break;
                case 3475: sVersion = "3.11a5"; break;
                case 3476: sVersion = "3.11a5"; break;
                case 3477: sVersion = "3.11a5"; break;
                case 3478: sVersion = "3.11a5"; break;
                case 3479: sVersion = "3.11a5"; break;
                case 3480: sVersion = "3.11a5"; break;
                case 3481: sVersion = "3.11a5"; break;
                case 3482: sVersion = "3.11a5"; break;
                case 3483: sVersion = "3.11a5"; break;
                case 3484: sVersion = "3.11a5"; break;
                case 3485: sVersion = "3.11a5"; break;
                case 3486: sVersion = "3.11a6"; break;
                case 3487: sVersion = "3.11a6"; break;
                case 3488: sVersion = "3.11a6"; break;
                case 3489: sVersion = "3.11a6"; break;
                case 3490: sVersion = "3.11a6"; break;
                case 3491: sVersion = "3.11a6"; break;
                case 3492: sVersion = "3.11a7"; break;
                case 3493: sVersion = "3.11a7"; break;
                case 3494: sVersion = "3.11a7"; break;
                case 3495: sVersion = "3.11a7"; break;
                case 416: sVersion = "3.11 (PyPy)"; break;
                case 21290: sVersion = "3.11 (Graal)"; break;
                case 3500: sVersion = "3.12a1"; break;
                case 3501: sVersion = "3.12a1"; break;
                case 3502: sVersion = "3.12a1"; break;
                case 3503: sVersion = "3.12a1"; break;
                case 3504: sVersion = "3.12a1"; break;
                case 3505: sVersion = "3.12a1"; break;
                case 3506: sVersion = "3.12a1"; break;
                case 3507: sVersion = "3.12a1"; break;
                case 3508: sVersion = "3.12a1"; break;
                case 3509: sVersion = "3.12a1"; break;
                case 3510: sVersion = "3.12a2"; break;
                case 3511: sVersion = "3.12a2"; break;
                case 3512: sVersion = "3.12a2"; break;
                case 3513: sVersion = "3.12a4"; break;
                case 3514: sVersion = "3.12a4"; break;
                case 3515: sVersion = "3.12a5"; break;
                case 3516: sVersion = "3.12a5"; break;
                case 3517: sVersion = "3.12a5"; break;
                case 3518: sVersion = "3.12a6"; break;
                case 3519: sVersion = "3.12a6"; break;
                case 3520: sVersion = "3.12a6"; break;
                case 3521: sVersion = "3.12a7"; break;
                case 3522: sVersion = "3.12a7"; break;
                case 3523: sVersion = "3.12a7"; break;
                case 3524: sVersion = "3.12a7"; break;
                case 3525: sVersion = "3.12b1"; break;
                case 3526: sVersion = "3.12b1"; break;
                case 3527: sVersion = "3.12b1"; break;
                case 3528: sVersion = "3.12b1"; break;
                case 3529: sVersion = "3.12b1"; break;
                case 3530: sVersion = "3.12b1"; break;
                case 3531: sVersion = "3.12b1"; break;
                case 12897: sVersion = "3.12 (Rust)"; break;
                case 3550: sVersion = "3.13a1"; break;
                case 3551: sVersion = "3.13a1"; break;
                case 3552: sVersion = "3.13a1"; break;
                case 3553: sVersion = "3.13a1"; break;
                case 3554: sVersion = "3.13a1"; break;
                case 3555: sVersion = "3.13a1"; break;
                case 3556: sVersion = "3.13a1"; break;
                case 3557: sVersion = "3.13a1"; break;
                case 3558: sVersion = "3.13a1"; break;
                case 3559: sVersion = "3.13a1"; break;
                case 3560: sVersion = "3.13a1"; break;
                case 3561: sVersion = "3.13a1"; break;
                case 3562: sVersion = "3.13a1"; break;
                case 3563: sVersion = "3.13a1"; break;
                case 3564: sVersion = "3.13a1"; break;
                case 3565: sVersion = "3.13a1"; break;
                case 3571: sVersion = "3.13"; break;
                case 12641: sVersion = "3.13.0 (Rust)"; break;
                case 3600: sVersion = "3.14"; break;
                case 3627: sVersion = "3.14rc3"; break;
                default: sVersion = "Unknown";
            }

            if (X.isVerbose()) sVersion = sVersion.append("magic: " + magicValue);
        }
    }

    sLang = "Python";

    return result();
}