Загрузка...

X-Castle-Request-Token Header / Castle-Io Reverse Engineering

Тема в разделе Node.js создана пользователем sunlightx 7 дек 2024. (поднята 2 янв 2025) 869 просмотров

  1. sunlightx
    sunlightx Автор темы 7 дек 2024 TwiterLight - https://zelenka.guru/threads/6896688 169 11 дек 2018

    Всем привет, это мой первый реверс, который я куда либо выкладываю и в качестве первой темы выбрал X-Castle-Request-Token, я столкнулся с этим заголовком на Rockstar Games

    Просматривая код, я сразу обнаружил что в нем практически отсутствует обфускация, что значительно упрощает процесс реверса, поехали смотреть код

    Сделав поиск по "Castle" я сразу же наткнулся на функцию создания токена, но это не совсем то что нам нужно


    [IMG]


    Сделав несколько шагов вперед по стеку я обнаружил основную функцию, отвечающую за создание токена, это - ek().createRequestToken()


    [IMG]

    [IMG]

    Оказавшись в ней, я сразу заметил что Hw(n) - создает токен, по этому пошел по ее стеку и она привела меня к функции gw(n,t) - именно в ней генерируется токен


    [IMG]
    [IMG]

    Функции на этом скриншоте используются для сбора и хеширования отпечатка, если начать смотреть стек [n, fw(nw())] - станет сразу же понятно, что он собирает WebGL, userAgent, и парочку ивентов, я не стал заниматься реверсом отпечатка, я думаю что не обязательно делать реверс отпечатка для такой простой анти бот системы, по этому решил пропустить этот этап и просто взял отпечаток реального браузера для того что бы генерировать токен

    [IMG]


    Оказавшись в последней функции которая принимает в себе итоговый хеш отпечатка, я начал ее разбирать,
    вытащил все функции в локальное окружение, Bo - константа которая генерирует случайное шестнадцатеричное значение в диапазоне от "00" до "ff"


    [IMG]

    Собрал все функции, передал отпечаток и....

    [IMG]

    Скорее всего многим что то из этого будет мало понятно, это моя первая тема, я не умею что либо объяснять, по этому расписал и вкратце показал все что посчитал нужным, там довольно много функций и мне просто было лень все это показывать и объяснять, лично мне было довольно интересно в них ковыряться, надеюсь что кому то этот реверс пригодится



    GitHub - https://github.com/sunlightx/castle-io-reverse

    JS
    const crypto = require('crypto');

    const getLuValue = () => {
    const randomUUID = crypto.randomUUID();
    return randomUUID.replace(/-/g, '')
    }

    let fingerHash1 = `9f6fdb3216f2698031547436597a723157467a78724a436837577a4d5a7a5931724870615075644e43a770600ecb4c89ab8b58577baf8529ff2fa7f26431251ffe243808fb4a561cff31683b78af3c24fb3f1504ca3f0616b8db3853fd5267d558783d6e6c2d3043f32f477bfe5f6abf668ae7273264d9acd6d2a416df1b14933218e64b9568b250f58a7558f5c2cace08386e8aaddf91e2438ae6a926116bdd9db203c3d94f49c8d685d112972a3848d0bc447fda3bb8803f1cd7cbe47e48fe309af1223954822f88012892b735f1abff3491ac3cbc0c696dd0c1e758ff5414679b9310b5a93552882c3f97ffbb30171f457ec232d03080ab49c3f44112a6fb0b7bb913481c1d0ae1ef8fb51e57df3e5372ab4cf00ac34cac8c988203ee80078e02ca3f03b8655243b2bf96946d17c80cfc8887495aed4f2c0a042ee904105a5e9c303d675094bab42f4b3fe18b2c8d26c1a4bb7311a1cef7ccc025565040e427a11cb3f72f8d3d3a9e3ad7fffc39c16d0bdf1c142ccf42a5c9d151008d5292fc2f340cb200ccacf05c67f097325e2d2e6eac41eb3b9a27c2662021202ed131f527f33dd53d1bfa49280d1ca82b3679af40331aff5eb712f80da9b3ff2f381c4b2b4a69ff2f871efde83e9eff78da01fe0a0a1cfc2f381c9d2f381cff2f381cff2f381cff2f381cff2f381cff2f381cff2f381cff2f381cff2f385cbf6f785cbf2f381cff2f381cff2f381cff6fe9d6ff2f381cff2f551cff2f381700` // finger hash

    let fingerHash2 = `17faad0ab3aa698031547436597a723157467a78724a436837577a4d5a7a5931724870615075644e43a770600ecb4c89ab8b58577baf8529448a3619da6af6e12ddaebf628b485e22ccfbbc5ab51efda28c1c6fa19c1d5e86b25ebad2eacb42b8b86ee90bfd3e3bd20d194852da19f6766a8908ff9e84571cf8988f2076fe60aa3558754389eb0fa81e6623217f3c447e1604ac3d338b788367a5784defaf329e0a17dee5700873582aff0937a2f4876a02567195ba59bdbb954d00edb98368c37a835bd5bf6e71faa33d85e683dfe71737c5faa0a6d5ad93c17df8dd45b87ea1b17632bbd8c6b395bd2ec692c45e3e748d9369a006a5a7e788cacd3a51ac2330174b01f572d9e297ecd106cc3c4661c1166f03a64ead8f6d1b32f2265467c51efe08db596b90a1332d35275b16077904637404e4819f12a3abc88c9e8f6d8d6bf074554a8b1b252fde3cef4a175ffec34f4bec123ff9a0b921c742e1357bd7796e0844d24d15ec3e960e9292c02ea3fbef50ce2c7d21cbc763702afd37381722fd1e7f233e1c0ed4e29cd62d90dd82e4f28058e38c5ad7f6eae315bcb22909d0cf17a90dffacad2dd77dee27bd5e5877cbee0e42ca064ec2bf37a7d2f03d20e1c76eef683d1ebe22c65ef9059d1eb5d2ed32ce4aed1bc0031d0cee92c83ebe23151eb6c2c562de040022de02cd187f0ff17eae22ccef9f7ac17e98e39512de040582de040512de040c4f2b42e57d4b42ec46eddab17e98eac17e98e39022de02cd187f7ff17e9e22cbdfe6569c06be34e61eb492cd143552c012f50a010ebe22c79eb532cd1eb586c6babac629152e22cd1eba26c91aba26c81abb26c81ab5a94b58fa16f02b3b2e9d1ede228d17bef2cd1ebe9d3` // finger hash

    let Ur = function(n) {
    return me(n.match(/.{2}/g) || [], (function(n) {
    return parseInt(n, 16) & 255
    }
    ))
    }

    let me = (n, t) => {
    for (var e = [], r = 0, i = n; r < i.length; r++) {
    var o = i[r];
    e.push(t(o))
    }
    return e
    }

    let Gr = (n) => {
    for (var t = [], e = 0; e < Math.ceil(n.length / 4); e++)
    t.push(((n[4 * e] || 0) | (n[4 * e + 1] || 0) << 8 | (n[4 * e + 2] || 0) << 16 | (n[4 * e + 3] || 0) << 24) >>> 0);
    return t
    }

    let Fi = (n) => {
    return (n[0] >>> 0) + (n[1] >>> 0) + (n[2] >>> 0)
    };

    let Vr = (n) => {
    for (var t = [], e = 0; e < n.length; e++) {
    var r = n[e] >>> 0;
    t.push(255 & r, r >> 8 & 255, r >> 16 & 255, r >> 24 & 255)
    }
    return t
    }

    let Di = (n, t) => {
    var e = Gr(n)
    , r = e.length - 1;
    if (!(r < 1))
    for (var i, o, u = 0, a = e[r], c = e[0], s = ~~(6 + 52 / (r + 1)); s-- > 0; ) {
    for (i = (u = u + Fi([2650800128, 3633152, 2489]) >>> 0) >>> 2 & 3,
    o = 0; o < r; o++)
    c = e[o + 1],
    a = e[o] = e[o] + ((a >>> 5 ^ c << 2) + (c >>> 3 ^ a << 4) ^ (u ^ c) + (t[3 & o ^ i] ^ a)) >>> 0;
    c = e[0],
    a = e[r] = e[r] + ((a >>> 5 ^ c << 2) + (c >>> 3 ^ a << 4) ^ (u ^ c) + (t[3 & o ^ i] ^ a)) >>> 0
    }
    return e
    }

    let uintArr = (n) => {
    return [n.length, Vr(Di(n, [1164413191, 3891440048, 185273099, 2746598870]))]
    }

    let Ce = (n) => {
    return ze('0b', Ar(n[1].length - n[0]), Br(n[1]))
    }

    let ze = (...args) => {
    var e = function(n, t) {
    return n + t
    }

    var r = function(n, t, i) {
    var o;
    return t === i
    ? n[t]
    : e(r(n, t, o = ~~((t + i) / 2)), r(n, o + 1, i))
    };

    return r(args, 0, args.length - 1);
    }

    let Ar = (n) => {
    return ("0" + (n & 255).toString(16)).slice(-2)
    }

    let _e = (n, t, e) => {
    for (var r = e, i = 0, o = 0, u = n; o < u.length; o++)
    r = t(r, u[o], i),
    i++;
    return r
    }

    let Ir = (n) => {
    return Math.random() * n | 0
    }

    let Dr = (n) => {
    return _e(n.match(/.{2}/g) || [], (function(n, t) {
    return ze(n, String.fromCharCode(parseInt(t, 16) & 255))
    }
    ), '')
    }

    let ol = (t) => {
    var e = btoa(t);
    return null == e ? null : e.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")
    }

    let Le = (n,t) => {
    return n.charAt(t)
    }

    let Wr = (n, t) => {
    var e = 0;
    return _e(n.split(""), (function(n, r) {
    var i = parseInt(r, 16) ^ parseInt(Le(t, e), 16);
    return e = (e + 1) % t.length,
    ze(n, i.toString(16))
    }
    ), "")
    }

    let Br = (n) => {
    return _e(n, (function(n, t) {
    return ze(n, Ar(t))
    }
    ), "")
    }

    let Bo = Ar(Ir(255 + 1))

    let c = Ce(uintArr(Ur(fingerHash2)))

    let createCastleToken = (t) => {
    return {
    Lu: getLuValue(),
    Hu: ol(Dr(ze(Bo, Wr(ze(t, Ar(t.length)), Bo))))
    }
    }

    console.log('X-Castle-Request-Token: ' + createCastleToken(c).Hu)
     
    7 дек 2024 Изменено
  2. Миньон
    я обкончался :dancing:
     
  3. POISON
    POISON 11 дек 2024 Творчество сильнее выгоды... 4955 17 авг 2017
    неплохо разобрал, :+rep:
     
Загрузка...
Top