Aistudio逆向思路

碎碎念

博客发的第一个贴子,是刚入坑的萌新,所以有什么问题请多担待

逆向参数

参数

发现最下方有一个检验值,这次主要也就逆向这个值

监听 Click 事件

Click事件 感觉 metadata 有点用,";xFZKLc:W251bGwsIm1vZGVscy9nZW1pbmktMi41LXByby1wcmV2aWV3LTA2LTA1IixudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCw0XQ==;xFZKLc:W251bGwsIjAiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLDVd”

var g = f[NRa];

base64 解码 W251bGwsIm1vZGVscy9nZW1pbmktMi41LXByby1wcmV2aWV3LTA2LTA1IixudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCw0XQ==为 [null,“models/gemini-2.5-pro-preview-06-05”,null,null,null,null,null,null,4]

W251bGwsIjAiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLDVd 为 [null,“0”,null,null,null,null,null,null,5]

对消息的 digest 处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
return _.Hg(function () {
  var e, f;
  return _.D(function (g) {
    if (g.A == 1) return g.yield(_.pWa(d), 2);
    if (g.A != 3) return (e = g.B), g.yield(a.X.A(e), 3);
    f = g.B;
    _.xp(d, 5, f);
    return g.return(d);
  });
});

可知当 g.A 为 1 时是组合 d,

g.A != 3 时呢 g.B 为 “2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824”

第一次跳转

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
_.pWa = function (a) {
  var b;
  return _.D(function (c) {
    b = _.Qm(a, _.sE, 2, _.Rm())
      .flatMap(function (d) {
        return _.zs(d);
      })
      .map(_.Cn);
    return c.return(_.yC(b.join(" ")));
  });
};

跳转入_.yC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
_.yC = function (a) {
  a = new TextEncoder().encode(a);
  var b = new _.Ona();
  b.update(a);
  return qKa(b.digest());
};

qKa = function (a) {
  return Array.prototype.map
    .call(a, function (b) {
      b = b.toString(16);
      return b.length > 1 ? b : "0" + b;
    })
    .join("");
};

对 digest 的加密

继续追堆栈,你会追到一个如图所示的生成器,digest 和后续加密值均在这里以 d 出现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
aKa = function (a) {
  function b(d) {
    return a.next(d);
  }
  function c(d) {
    return a.throw(d);
  }
  return new Promise(function (d, e) {
    function f(g) {
      g.done ? d(g.value) : Promise.resolve(g.value).then(b, c).then(f, e);
    }
    f(a.next());
  });
};

条件断点断下 return a.next(d)

1
d && (d.startsWith("!") || d.startsWith("2c"));

覆写该 javascript 函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
aKa = function (a) {
  window.currentId ??= 0;
  window.currentId++;
  window.a_id_map ??= new Map();
  window.a_id_map[a] = window.currentId;
  console.log("当前a的id:", window.currentId);
  console.trace();
  function b(d) {
    const id = window.a_id_map[a];
    console.log("当时的id是:", id, "到上面找到这个id对应的trace");

    return a.next(d);
  }
  function c(d) {
    return a.throw(d);
  }
  return new Promise(function (d, e) {
    function f(g) {
      g.done ? d(g.value) : Promise.resolve(g.value).then(b, c).then(f, e);
    }
    f(a.next());
  });
};

然后追到了上游堆栈

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    _.rE.prototype.A = function(a) {
        var b = this;
        return _.D(function(c) {
            return c.A == 1 ? c.yield(b.F, 2) : b.B ? c.return(b.B.snapshot({
                Xka: {
                    content: a
                }
            })) : c.return("")
        })
    }

断点 return c.A == 1 ? c.yield(b.F, 2) : b.B ? c.return(b.B.snapshot({ 发现传入了一个hex,上面好像见过对吧 接着走会走到

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    RUa.prototype.snapshot = function(a) {
        if (this.isDisposed())
            throw Error("Sb");
        this.logger.cB("n");
        var b = this.logger.share();
        return this.D.then(function(c) {
            var d = c.HLa;
            return new Promise(function(e) {
                var f = new FUa(b,"n");
                d(function(g) {
                    f.done();
                    b.WT(g.length);
                    b.BM();
                    b.dispose();
                    e(g)
                }, [a.Xka, a.z8a, a.d9a, a.A8a])
            }
            )
        })
    }

一切都很清楚了 不过d似乎是动态的 现在又变成 var d = Lac.H; 了,剩下的动不了了,好创人 大概用jsdom就可以了

d变量对应内部文件

js.7z

感谢

il 提供的生成器向上追堆栈思路

原创:Github: Nekohy

Licensed under CC BY-NC-SA 4.0
这里也许没有你想要的东西...?