提要: 这些天在搞天猫的秒杀,但是很奇怪的是:在我自己电脑上跑的时候时间是0.5到1秒的时间,居然秒杀失败,然后别人写的秒杀时间是4秒左右都可以秒杀成功!这个我很不能接受。下面说一下我的思路: 1.提前5分钟登录淘宝获取登录后的cookie,保存。 2.设置秒杀时间(一般在快到秒杀的前3秒),一旦到时间激活程序,带上cookie模拟协议,执行秒杀流程。 3.然后利用死循环一直请求购买接口。 4.在秒杀程序激活之前已经把所有要的参数什么的都准备清楚了,只要一到时间就可以进行购买了。 以上就是整体的流程和思路,但是一直不成功,很奇怪,我的程序优化也到了极致,除去响应的时间我觉得整个流程应该是在瞬间级别的,如果有其他好的思路请指教一下哈。
下面进入正文:
工具和环境: 谷歌浏览器:86.0.4240.183(正式版本) (64 位) 开发环境:Anaconda3-5.2.0、python3.6、nodejs v14.15.1,windows10 IDE:PyCharm 2019.3.1 x64 登录验证的整个过程 淘宝的登录页:https://login.taobao.com/member/login.jhtml 滑块验证:https://login.taobao.com/newlogin/account/check.do?appName=taobao&fromSite=0(这个基本不会验证的) 账号密码验证:https://login.taobao.com/newlogin/login.do?appName=taobao&fromSite=0 验证st码:https://login.taobao.com/member/vst.htm?st={}
整体的流程是:先看看是否需要滑块验证,请求滑块验证的地址,如果返回一个字段isCheckCodeShowed则说明需要验证滑块,否则不需要,我测试到现在好像也没遇到过。然后验证账号密码是否正确,其中最重要的一个字段是passwor2,也是我们今天要js逆向破解的一个主题,放到后面讲,如果账号密码验证通过,会返回一个json,而我们需要的st码的申请地址就在[‘content’][‘data’][‘asyncUrls’]里面。最后访问前面提取到的st码的申请地址,返回的内容中用正则查找"data":{“st”:"(.*?)"}找到st码,在与上面的验证st码地址进行格式化后的到一个完整的验证地址,请求之后就成功登录了!
账号密码验证: 这里说一下:滑块验证和账号密码验证的接口的参数就差一个字段password2,所有拿账号密码验证的接口叙述一下。 先看params: appName: taobao fromSite: 0 这个是固定不变的,没啥可说的。 再看data: loginId:账号名 password2:密码js加密后的结果 keepLogin: false ua: 这个应该也是加密后的结果,但是我没有找到,好在他这个可以重复使用,直接从浏览器复制,但是不知道不同账号是不是也可以。 umidGetStatusVal: 255 screenPixel:电脑的分辨率 navlanguage: zh-CN navUserAgent: 谷歌浏览器的版本号 navPlatform: Win32 sub: true appName: taobao appEntrance: taobao_pc _csrf_token: 从登录页https://login.taobao.com/member/login.jhtml中获取 umidToken: 从登录页https://login.taobao.com/member/login.jhtml中获取 hsiz: 从登录页https://login.taobao.com/member/login.jhtml中获取 bizParams: style: default appkey: 00000000 from: tbTop isMobile: false lang: zh_CN returnUrl: https://shoucang.taobao.com/item_collect_n.htm?spm=a1z0k.6846577.0.0.56949d8fnx8L53&t=1607134148136 fromSite: 0 以上就是账号密码验证的所有参数了,重要的参数我已经标出黑体加粗了。首先来看看_csrf_token、umidToken、hsiz: 在https://login.taobao.com/member/login.jhtml中查看源码就能找到。 在看看screenPixel获取屏幕分辨率:
def _get_screen():
"""
捕获屏幕大小
:return:
"""
x = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
y = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
return str(x) + "x" + str(y)
最后来看看最最重要的password2: 1.先利用全局搜索找到password2有关的文件,发现只要一个https://x.alicdn.com/vip/havana-nlogin/0.5.46/index.js 2.打开源文件,查找password2,会看到下面的一段js代码: 可以看出passwor2是通过this.rsaPassword(this.passwordNode.value())执行后返回的结果,而this.passwordNode.value()是获取你所输入的密码,进入this.rsaPassword可以看到下面的js代码片段: 他这里创建了一个对象,具体我们打断点看看他做的什么,在return e.setPublic(i.config.rsaModulus, i.config.rsaExponent)处打个断点,可以看到t就是我们的没加密的密码,e是一个对象: 其实就是D函数,你可以进入到D函数中查看,然后再看看下面的i.config.rsaModulus和i.config.rsaExponent是什么东西: 我不知道你们是不是跟我一样的结果? 最后把断点在往下移到e.encrypt(t),这里其实就是加密的函数了,总的来说是通过e这个对象怎么进行加密的,其实我也看的不是很懂,js基础薄弱啊。但是你认证去找e是怎么构建的,还有加密过程,你会发现它们都进入到一个函数体里面进行的,所有大胆推测只要把这个函数扣出来在自己电脑上能运行的话,应该就可以实现加密的整个过程了,ok,我们来看看这个函数体:
function(t, e, n) {
"use strict";
var o;
e.__esModule = !0;
function i(t, e, n) {
null != t && ("number" == typeof t ? this.fromNumber(t, e, n) : null == e && "string" != typeof t ? this.fromString(t, 256) : this.fromString(t, e))
}
function r() {
return new i(null)
}
"Microsoft Internet Explorer" == navigator.appName ? (i.prototype.am = function(t, e, n, o, i, r) {
for (var a = 32767 & e, s = e >> 15; --r >= 0; ) {
var c = 32767 & this[t]
, u = this[t++] >> 15
, l = s * c + u * a;
i = ((c = a * c + ((32767 & l) << 15) + n[o] + (1073741823 & i)) >>> 30) + (l >>> 15) + s * u + (i >>> 30),
n[o++] = 1073741823 & c
}
return i
}
,
o = 30) : "Netscape" != navigator.appName ? (i.prototype.am = function(t, e, n, o, i, r) {
for (; --r >= 0; ) {
var a = e * this[t++] + n[o] + i;
i = Math.floor(a / 67108864),
n[o++] = 67108863 & a
}
return i
}
,
o = 26) : (i.prototype.am = function(t, e, n, o, i, r) {
for (var a = 16383 & e, s = e >> 14; --r >= 0; ) {
var c = 16383 & this[t]
, u = this[t++] >> 14
, l = s * c + u * a;
i = ((c = a * c + ((16383 & l) << 14) + n[o] + i) >> 28) + (l >> 14) + s * u,
n[o++] = 268435455 & c
}
return i
}
,
o = 28),
i.prototype.DB = o,
i.prototype.DM = (1 << o) - 1,
i.prototype.DV = 1 << o;
i.prototype.FV = Math.pow(2, 52),
i.prototype.F1 = 52 - o,
i.prototype.F2 = 2 * o - 52;
var a, s, c = "0123456789abcdefghijklmnopqrstuvwxyz", u = new Array;
for (a = "0".charCodeAt(0),
s = 0; s <= 9; ++s)
u[a++] = s;
for (a = "a".charCodeAt(0),
s = 10; s < 36; ++s)
u[a++] = s;
for (a = "A".charCodeAt(0),
s = 10; s < 36; ++s)
u[a++] = s;
function l(t) {
return c.charAt(t)
}
function f(t, e) {
var n = u[t.charCodeAt(e)];
return null == n ? -1 : n
}
function p(t) {
var e = r();
return e.fromInt(t),
e
}
function d(t) {
var e, n = 1;
return 0 != (e = t >>> 16) && (t = e,
n += 16),
0 != (e = t >> 8) && (t = e,
n += 8),
0 != (e = t >> 4) && (t = e,
n += 4),
0 != (e = t >> 2) && (t = e,
n += 2),
0 != (e = t >> 1) && (t = e,
n += 1),
n
}
function h(t) {
this.m = t
}
function g(t) {
this.m = t,
this.mp = t.invDigit(),
this.mpl = 32767 & this.mp,
this.mph = this.mp >> 15,
this.um = (1 << t.DB - 15) - 1,
this.mt2 = 2 * t.t
}
function y() {
this.i = 0,
this.j = 0,
this.S = new Array
}
h.prototype.convert = function(t) {
return t.s < 0 || t.compareTo(this.m) >= 0 ? t.mod(this.m) : t
}
,
h.prototype.revert = function(t) {
return t
}
,
h.prototype.reduce = function(t) {
t.divRemTo(this.m, null, t)
}
,
h.prototype.mulTo = function(t, e, n) {
t.multiplyTo(e, n),
this.reduce(n)
}
,
h.prototype.sqrTo = function(t, e) {
t.squareTo(e),
this.reduce(e)
}
,
g.prototype.convert = function(t) {
var e = r();
return t.abs().dlShiftTo(this.m.t, e),
e.divRemTo(this.m, null, e),
t.s < 0 && e.compareTo(i.ZERO) > 0 && this.m.subTo(e, e),
e
}
,
g.prototype.revert = function(t) {
var e = r();
return t.copyTo(e),
this.reduce(e),
e
}
,
g.prototype.reduce = function(t) {
for (; t.t <= this.mt2; )
t[t.t++] = 0;
for (var e = 0; e < this.m.t; ++e) {
var n = 32767 & t[e]
, o = n * this.mpl + ((n * this.mph + (t[e] >> 15) * this.mpl & this.um) << 15) & t.DM;
for (t[n = e + this.m.t] += this.m.am(0, o, t, e, 0, this.m.t); t[n] >= t.DV; )
t[n] -= t.DV,
t[++n]++
}
t.clamp(),
t.drShiftTo(this.m.t, t),
t.compareTo(this.m) >= 0 && t.subTo(this.m, t)
}
,
g.prototype.mulTo = function(t, e, n) {
t.multiplyTo(e, n),
this.reduce(n)
}
,
g.prototype.sqrTo = function(t, e) {
t.squareTo(e),
this.reduce(e)
}
,
i.prototype.copyTo = function(t) {
for (var e = this.t - 1; e >= 0; --e)
t[e] = this[e];
t.t = this.t,
t.s = this.s
}
,
i.prototype.fromInt = function(t) {
this.t = 1,
this.s = t < 0 ? -1 : 0,
t > 0 ? this[0] = t : t < -1 ? this[0] = t + this.DV : this.t = 0
}
,
i.prototype.fromString = function(t, e) {
var n;
if (16 == e)
n = 4;
else if (8 == e)
n = 3;
else if (256 == e)
n = 8;
else if (2 == e)
n = 1;
else if (32 == e)
n = 5;
else {
if (4 != e)
return void this.fromRadix(t, e);
n = 2
}
this.t = 0,
this.s = 0;
for (var o = t.length, r = !1, a = 0; --o >= 0; ) {
var s = 8 == n ? 255 & t[o] : f(t, o);
s < 0 ? "-" == t.charAt(o) && (r = !0) : (r = !1,
0 == a ? this[this.t++] = s : a + n > this.DB ? (this[this.t - 1] |= (s & (1 << this.DB - a) - 1) << a,
this[this.t++] = s >> this.DB - a) : this[this.t - 1] |= s << a,
(a += n) >= this.DB && (a -= this.DB))
}
8 == n && 0 != (128 & t[0]) && (this.s = -1,
a > 0 && (this[this.t - 1] |= (1 << this.DB - a) - 1 << a)),
this.clamp(),
r && i.ZERO.subTo(this, this)
}
,
i.prototype.clamp = function() {
for (var t = this.s & this.DM; this.t > 0 && this[this.t - 1] == t; )
--this.t
}
,
i.prototype.dlShiftTo = function(t, e) {
var n;
for (n = this.t - 1; n >= 0; --n)
e[n + t] = this[n];
for (n = t - 1; n >= 0; --n)
e[n] = 0;
e.t = this.t + t,
e.s = this.s
}
,
i.prototype.drShiftTo = function(t, e) {
for (var n = t; n < this.t; ++n)
e[n - t] = this[n];
e.t = Math.max(this.t - t, 0),
e.s = this.s
}
,
i.prototype.lShiftTo = function(t, e) {
var n, o = t % this.DB, i = this.DB - o, r = (1 << i) - 1, a = Math.floor(t / this.DB), s = this.s << o & this.DM;
for (n = this.t - 1; n >= 0; --n)
e[n + a + 1] = this[n] >> i | s,
s = (this[n] & r) << o;
for (n = a - 1; n >= 0; --n)
e[n] = 0;
e[a] = s,
e.t = this.t + a + 1,
e.s = this.s,
e.clamp()
}
,
i.prototype.rShiftTo = function(t, e) {
e.s = this.s;
var n = Math.floor(t / this.DB);
if (n >= this.t)
e.t = 0;
else {
var o = t % this.DB
, i = this.DB - o
, r = (1 << o) - 1;
e[0] = this[n] >> o;
for (var a = n + 1; a < this.t; ++a)
e[a - n - 1] |= (this[a] & r) << i,
e[a - n] = this[a] >> o;
o > 0 && (e[this.t - n - 1] |= (this.s & r) << i),
e.t = this.t - n,
e.clamp()
}
}
,
i.prototype.subTo = function(t, e) {
for (var n = 0, o = 0, i = Math.min(t.t, this.t); n < i; )
o += this[n] - t[n],
e[n++] = o & this.DM,
o >>= this.DB;
if (t.t < this.t) {
for (o -= t.s; n < this.t; )
o += this[n],
e[n++] = o & this.DM,
o >>= this.DB;
o += this.s
} else {
for (o += this.s; n < t.t; )
o -= t[n],
e[n++] = o & this.DM,
o >>= this.DB;
o -= t.s
}
e.s = o < 0 ? -1 : 0,
o < -1 ? e[n++] = this.DV + o : o > 0 && (e[n++] = o),
e.t = n,
e.clamp()
}
,
i.prototype.multiplyTo = function(t, e) {
var n = this.abs()
, o = t.abs()
, r = n.t;
for (e.t = r + o.t; --r >= 0; )
e[r] = 0;
for (r = 0; r < o.t; ++r)
e[r + n.t] = n.am(0, o[r], e, r, 0, n.t);
e.s = 0,
e.clamp(),
this.s != t.s && i.ZERO.subTo(e, e)
}
,
i.prototype.squareTo = function(t) {
for (var e = this.abs(), n = t.t = 2 * e.t; --n >= 0; )
t[n] = 0;
for (n = 0; n < e.t - 1; ++n) {
var o = e.am(n, e[n], t, 2 * n, 0, 1);
(t[n + e.t] += e.am(n + 1, 2 * e[n], t, 2 * n + 1, o, e.t - n - 1)) >= e.DV && (t[n + e.t] -= e.DV,
t[n + e.t + 1] = 1)
}
t.t > 0 && (t[t.t - 1] += e.am(n, e[n], t, 2 * n, 0, 1)),
t.s = 0,
t.clamp()
}
,
i.prototype.divRemTo = function(t, e, n) {
var o = t.abs();
if (!(o.t <= 0)) {
var a = this.abs();
if (a.t < o.t)
return null != e && e.fromInt(0),
void (null != n && this.copyTo(n));
null == n && (n = r());
var s = r()
, c = this.s
, u = t.s
, l = this.DB - d(o[o.t - 1]);
l > 0 ? (o.lShiftTo(l, s),
a.lShiftTo(l, n)) : (o.copyTo(s),
a.copyTo(n));
var f = s.t
, p = s[f - 1];
if (0 != p) {
var h = p * (1 << this.F1) + (f > 1 ? s[f - 2] >> this.F2 : 0)
, g = this.FV / h
, y = (1 << this.F1) / h
, m = 1 << this.F2
, v = n.t
, M = v - f
, w = null == e ? r() : e;
for (s.dlShiftTo(M, w),
n.compareTo(w) >= 0 && (n[n.t++] = 1,
n.subTo(w, n)),
i.ONE.dlShiftTo(f, w),
w.subTo(s, s); s.t < f; )
s[s.t++] = 0;
for (; --M >= 0; ) {
var b = n[--v] == p ? this.DM : Math.floor(n[v] * g + (n[v - 1] + m) * y);
if ((n[v] += s.am(0, b, n, M, 0, f)) < b)
for (s.dlShiftTo(M, w),
n.subTo(w, n); n[v] < --b; )
n.subTo(w, n)
}
null != e && (n.drShiftTo(f, e),
c != u && i.ZERO.subTo(e, e)),
n.t = f,
n.clamp(),
l > 0 && n.rShiftTo(l, n),
c < 0 && i.ZERO.subTo(n, n)
}
}
}
,
i.prototype.invDigit = function() {
if (this.t < 1)
return 0;
var t = this[0];
if (0 == (1 & t))
return 0;
var e = 3 & t;
return (e = (e = (e = (e = e * (2 - (15 & t) * e) & 15) * (2 - (255 & t) * e) & 255) * (2 - ((65535 & t) * e & 65535)) & 65535) * (2 - t * e % this.DV) % this.DV) > 0 ? this.DV - e : -e
}
,
i.prototype.isEven = function() {
return 0 == (this.t > 0 ? 1 & this[0] : this.s)
}
,
i.prototype.exp = function(t, e) {
if (t > 4294967295 || t < 1)
return i.ONE;
var n = r()
, o = r()
, a = e.convert(this)
, s = d(t) - 1;
for (a.copyTo(n); --s >= 0; )
if (e.sqrTo(n, o),
(t & 1 << s) > 0)
e.mulTo(o, a, n);
else {
var c = n;
n = o,
o = c
}
return e.revert(n)
}
,
i.prototype.toString = function(t) {
if (this.s < 0)
return "-" + this.negate().toString(t);
var e;
if (16 == t)
e = 4;
else if (8 == t)
e = 3;
else if (2 == t)
e = 1;
else if (32 == t)
e = 5;
else {
if (4 != t)
return this.toRadix(t);
e = 2
}
var n, o = (1 << e) - 1, i = !1, r = "", a = this.t, s = this.DB - a * this.DB % e;
if (a-- > 0)
for (s < this.DB && (n = this[a] >> s) > 0 && (i = !0,
r = l(n)); a >= 0; )
s < e ? (n = (this[a] & (1 << s) - 1) << e - s,
n |= this[--a] >> (s += this.DB - e)) : (n = this[a] >> (s -= e) & o,
s <= 0 && (s += this.DB,
--a)),
n > 0 && (i = !0),
i && (r += l(n));
return i ? r : "0"
}
,
i.prototype.negate = function() {
var t = r();
return i.ZERO.subTo(this, t),
t
}
,
i.prototype.abs = function() {
return this.s < 0 ? this.negate() : this
}
,
i.prototype.compareTo = function(t) {
var e = this.s - t.s;
if (0 != e)
return e;
var n = this.t;
if (0 != (e = n - t.t))
return this.s < 0 ? -e : e;
for (; --n >= 0; )
if (0 != (e = this[n] - t[n]))
return e;
return 0
}
,
i.prototype.bitLength = function() {
return this.t <= 0 ? 0 : this.DB * (this.t - 1) + d(this[this.t - 1] ^ this.s & this.DM)
}
,
i.prototype.mod = function(t) {
var e = r();
return this.abs().divRemTo(t, null, e),
this.s < 0 && e.compareTo(i.ZERO) > 0 && t.subTo(e, e),
e
}
,
i.prototype.modPowInt = function(t, e) {
var n;
return n = t < 256 || e.isEven() ? new h(e) : new g(e),
this.exp(t, n)
}
,
i.ZERO = p(0),
i.ONE = p(1),
y.prototype.init = function(t) {
var e, n, o;
for (e = 0; e < 256; ++e)
this.S[e] = e;
for (n = 0,
e = 0; e < 256; ++e)
n = n + this.S[e] + t[e % t.length] & 255,
o = this.S[e],
this.S[e] = this.S[n],
this.S[n] = o;
this.i = 0,
this.j = 0
}
,
y.prototype.next = function() {
var t;
return this.i = this.i + 1 & 255,
this.j = this.j + this.S[this.i] & 255,
t = this.S[this.i],
this.S[this.i] = this.S[this.j],
this.S[this.j] = t,
this.S[t + this.S[this.i] & 255]
}
;
var m, v, M, w = 256;
function b() {
!function(t) {
v[M++] ^= 255 & t,
v[M++] ^= t >> 8 & 255,
v[M++] ^= t >> 16 & 255,
v[M++] ^= t >> 24 & 255,
M >= w && (M -= w)
}((new Date).getTime())
}
if (null == v) {
var N;
if (v = new Array,
M = 0,
window.crypto && window.crypto.getRandomValues) {
var C = new Uint8Array(32);
for (window.crypto.getRandomValues(C),
N = 0; N < 32; ++N)
v[M++] = C[N]
}
if ("Netscape" == navigator.appName && navigator.appVersion < "5" && window.crypto && window.crypto.random) {
var T = window.crypto.random(32);
for (N = 0; N < T.length; ++N)
v[M++] = 255 & T.charCodeAt(N)
}
for (; M < w; )
N = Math.floor(65536 * Math.random()),
v[M++] = N >>> 8,
v[M++] = 255 & N;
M = 0,
b()
}
function I() {
if (null == m) {
for (b(),
(m = new y).init(v),
M = 0; M < v.length; ++M)
v[M] = 0;
M = 0
}
return m.next()
}
function j() {}
function D() {
this.n = null,
this.e = 0,
this.d = null,
this.p = null,
this.q = null,
this.dmp1 = null,
this.dmq1 = null,
this.coeff = null
}
j.prototype.nextBytes = function(t) {
var e;
for (e = 0; e < t.length; ++e)
t[e] = I()
}
,
D.prototype.doPublic = function(t) {
return t.modPowInt(this.e, this.n)
}
,
D.prototype.setPublic = function(t, e) {
null != t && null != e && t.length > 0 && e.length > 0 ? (this.n = function(t, e) {
return new i(t,e)
}(t, 16),
this.e = parseInt(e, 16)) : alert("Invalid RSA public key")
}
,
D.prototype.encrypt = function(t) {
var e = function(t, e) {
if (e < t.length + 11)
return alert("Message too long for RSA"),
null;
for (var n = new Array, o = t.length - 1; o >= 0 && e > 0; ) {
var r = t.charCodeAt(o--);
r < 128 ? n[--e] = r : r > 127 && r < 2048 ? (n[--e] = 63 & r | 128,
n[--e] = r >> 6 | 192) : (n[--e] = 63 & r | 128,
n[--e] = r >> 6 & 63 | 128,
n[--e] = r >> 12 | 224)
}
n[--e] = 0;
for (var a = new j, s = new Array; e > 2; ) {
for (s[0] = 0; 0 == s[0]; )
a.nextBytes(s);
n[--e] = s[0]
}
return n[--e] = 2,
n[--e] = 0,
new i(n)
}(t, this.n.bitLength() + 7 >> 3);
if (null == e)
return null;
var n = this.doPublic(e);
if (null == n)
return null;
var o = n.toString(16);
return 0 == (1 & o.length) ? o : "0" + o
}
;
e.default = D
}
这个只要能在我们的电脑上跑,我们就完成了所有的加密了!具体环境搭建和细节就不多说了,太多了,我直接上结果: ok,我们点到为止,以上就是password2的全加密过程了,希望能够帮助到你破解他。破解他后就按照上边的流程执行登录就可以登录淘宝了。
总结: 先在这里声明一下,这篇文章仅供学习,如果侵权立删。 其实前期踩了太多坑了,比如一段一段代码去扣,发现e对象缺少好多内容,最后发现他总是进到一个函数体里面执行,所有有了后面的想法,把整个函数体拿来跑。总的来说不是很难,也没有很深度的逆向,只是扣代码而已,感兴趣的可以自己去试试哈。
password2环境补全我已经上传到我的资源里面的,如果不想花积分下载,可以私信我哦。