网页逆向-某微博登录算法逆向

第一步还是抓包,发现加密字段pass

通过Initiator结合函数栈断点找到对应的关键代码,但是这里尝试在f.send方法处下断点的话,会不断地断在这个位置,原因是前端会不停地请求二维码的数据包,导致无法分析

使用xhr/fetch breakpoints断点来打断点,点击登录之后成功断下来,可以在console的位置处看到参数

接着回溯函数栈,找到h方法的const [L,U] = await pn("/sso/v2/login", C);代码

这里的C可以在上面看到,是一个对象,包含需要的各种属性

if (n.curType === "show_pw") 处断点,执行

进入Qh("".concat([cp(), ap()].join(" "), "\n").concat(s.form.password), n.pubkey)的Qh函数,下断点之后继续执行

console查看参数也不难发现,这是一个RSA的加密

而且参数t的值是'1741921196\t25XVEH\n111111',前面是时间戳,中间目前不知道,后面是密码

要想知道参数的含义,需要分析Qh函数的参数,也就是 "".concat([cp(), ap()].join(" "), "\n").concat(s.form.password) 里的cp()函数和ap()函数

函数定义如下

这是ES6的代码写法,代表调用cp函数的时候直接返回en,调用ap函数的时候直接返回br

br函数和en函数均在上面有使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let br;
const op = t => {
if (Qe || (Qe = new _a(!0)),
t === 0)
return Qe.clear(),
en = t,
!0;
if (t < 1294935546)
return !1;
const e = function() {
en && Qe && (en += is / 1e3,
Qe.start(is, e))
};
en = t,
Qe.start(is, e)
}
, lp = t => {
br = t
}

上面代码的意思是,br是在lp函数中被赋值为t变量,要想知道br是什么,还需要知道lp函数的参数t是什么,对于en函数同理,需要找到lp函数和op函数被调用的地方

在代码中全局搜索lp(,找函数被调用的地方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Ks(async () => {
n.entry = e.query.entry,
n.source = e.query.source;
const [C,L] = await pn("/sso/v2/web/config", {
method: "POST",
entry: n.entry,
source: n.source
});
C || L.data.retcode !== 2e7 || (n.show_pw = !!L.data.data.show_pw,
n.show_qq = !!L.data.data.show_qq,
n.show_qr = !!L.data.data.show_qr,
n.show_sms = !!L.data.data.show_sms,
n.show_wechat = !!L.data.data.show_wechat,
n.curType = L.data.data.first_show,
n.regUrl = L.data.data.reg_url || Wh,
n.forgetUrl = L.data.data.forget_url || Gh,
n.iconUrl = L.data.data.icon_url || Zh,
n.pubkey = L.data.data.pubkey,
n.rsakv = L.data.data.rsakv,
document.title = "登录 - ".concat(L.data.data.title),
i.countryCodeMenu = L.data.data.country_code.map(U => ({
code: U.country_code,
text: U.local.zh_CN
})),
lp(L.data.data.nonce),
op(L.data.data.servertime))
}

可以看到参数是通过请求/sso/v2/web/config这个接口返回的,可以抓包校验一下

这里抓包注意是刷新页面的时候看数据包,点击登录之后包就被莫名其妙丢了,或者用抓包工具抓

那么现在要做的就是把这里的代码给扣下来,找到Hh函数定义的js代码,有时候扣下来的代码不一定能直接运行,比如函数内部本来应该报错,但是被catch到了,导致运行的时候结果不对,这个时候就需要调试,如果报错缺少变量,说明扣少了

1
2
3
4
5
6
7
8
9
  , Qh = (t, e) => {
if (!e || !t)
return;
const n = new Hh({
default_public_exponent: "10001"
});
return n.setPublicKey(e),
Jh(n.encrypt(t))
}