目标网站

aHR0cHM6Ly9zdG9yZS5zdGVhbXBvd2VyZWQuY29tL2xvZ2luLz9yZWRpcj0mcmVkaXJfc3NsPTEmc25yPTFfNF80X19nbG9iYWwtaGVhZGVyTWVuZw==

查找加密接口

在发起请求之前,先把Network打开,然后清空所有记录,清空之后再发起请求,这样可以捕获到此次所有的请求,方便查找具体的加密接口。

在这里我们发现Network中只有两个请求是可能包含加密逻辑的请求,其余为字体和图片文件,这就很舒服了,如下图:

接下来,我们详细看一下这两个xhr请求,其中第一个请求是post请求,其携带两个参数,一个是donotcache,另一个是用户名。这里盲猜donotcacha是时间戳。当然也可以多请求几次,去找找规律。

也可以在控制台输出一下当前时间戳,可以发现两者非常相似,因此第一个请求并没有加密参数。

接下来看第二个请求,同样是一个post请求,该请求携带的参数较多,但大多数都为空,这里最明显的加密就是password,看其形式类似base64编码,可以直接使用base64加密试一下(如果能直接得到和加密后的密文相同的密文,那就不需要继续下面的分析了),(也有可能是先进行了其他加密,最后使用了base64编码),这里在使用base64对明文加密后发现和密文对应不上,所以我们需要接下来的分析。

这里发现还有一个参数rsatimestamp,这个参数是动态变化的。所以我们需要对该参数进行分析。

password分析

首先对password进行分析,可以直接对password参数进行搜索从而找到加密逻辑位置,也可以通过xhr断点进行调试,然后找到对应的位置。

直接搜索

直接搜索password参数,可以找到包含该参数的六个文件。

这里可以进一步搜索,比如加等号或冒号,这里只有六个文件,我们可以一一来对其进行分析。

首先排除两个css文件,接下来去查看js中对应password的逻辑,我们可以发现在login.js文件中,存在大量包含password的逻辑。同时还有一个password:encryptedPassword的操作,这里我们可以猜测encryptedPassword就是加密后的password

再找到具体的加密逻辑所在的文件之后,我们就需要进入文件内部进行更详细的分析。

进入文件之后,我们可以首先对文件进行格式化,以便调试,在该文件内部继续搜索password参数,这里我们找打了23处符合条件的位置,还能接受。当然也可以使用小技巧进一步缩小范围。

在这里我们一个一个查看,可以发现在387行,有一个RSA.encrypt(password, pubKey),其余地方没有。因此我们可以在此处打上断点以验证我们是否找到了真正的加密位置。

打上断点之后,再发起一次请求,我们可以看到,程序在我们打下断点的位置停住了。

这就说明我们找到了正确的加密位置,接下来就是要对具体的加密逻辑进行分析了。

分析加密逻辑

在这里我们可以看到该加密函数使用了两个参数,一个是password明文,另一个是pubKey(密钥)。

其中pubKey我们可以在文件的上方找到,

我们可以看到生成该密钥需要两个参数,我们可以进一步搜索一下这两个参数。在该文件并没有找到对应的生成位置,这时细心的朋友可以发现这两个参数和第一次请求返回的结果有些关系,(publickey_exp和publickey_mod),同时可以发现timestamp和我们之前找到的rsatimestamp有些类似,进一步查看,可以发现这里的timestamp和rsatimestamp是相同的。那么这个问题也就解决了。

接下来继续分析加密的逻辑,这里主要是使用了RSA这个对象的encrypt方法,在这里打上断点,我们可以跟到具体的方法里面,去看一下。

这里我们就可以看到具体的encrypt方法了,可以看到这里使用了Base64.encode() 和 Hex.decode() 方法,代表我们也需要找到这两个对应的方法。幸运的是,我们在该文件的上方找到了对应的方法实现。那么我们就可以确定该文件整体都是在加密的逻辑中不可或缺的。在接下来的写代码环节,我们就需要把其整体拿下来。

JS调试及实现

在这里,我们首先把上一步我们找到的加密文件的所有内容拿下来,放到一个js文件里面。然后,开始我们的调试(不确定只有这一段逻辑是否能够实现加密,所以在调试过程中要不断添加修改js代码)。

在把当前加密逻辑写入js文件之后,我们可以尝试运行一下js,可以使用python第三方库pyexecjs来模拟运行,也可以使用node.js运行,或者可以直接使用浏览器运行js。

这里,我们先把获取pubKey的函数所需的两个参数写成固定值,方便调试,放到浏览器里面运行结果如下:

这里提示BigInter is not defined 。也就是说,程序缺少了BigInter 这个对象,那么我们现在要做的就是去往现有代码中添加对象。

现在我们去刚才找到的代码文件中,去搜索一下这个关键字,可以发现其全是以new BigInteger 形式出现的,那么就代表其为一个对象,那么我们可以在对应位置设置断点,然后重新发起请求,并单步执行到BigInteger 的位置,然后跟进去,即可找到BigInteger对应的逻辑,如下图:

在进入到包含 BigInteger 对象逻辑的文件中后,我们便可以看到该文件内对BigInteger的具体实现,那么我们就可以把它拿出来,添加到我们已有的代码当中(这里也可以直接把整个文件中的代码全拿出来,测试是否可以执行(在这里结果是可行的,但并不是所有的都可行)),这次我并没有直接把所有代码拿出来,而是慢慢的去补充所需的代码。

这里我们把 BigInterger 补进去,然后再次执行。出现如下报错:

提示 this.fromString 不是一个函数,所以我们下一步就是要去找到其对应的代码,然后添加到我们的代码中。在源代码中搜索fromString,我们可以找到其对应的逻辑,在这里this表示的是拥有该函数的对象,即为BigInteger对象。通过搜索关键字我们可以发现其逻辑,如下图:

在下面还有一行代码,将该函数添加到BigInterger对象中。所以我们也要把这行代码添加进去。
BigInteger.prototype.fromString = bnpFromString;

添加完之后,我们再次执行代码,出现如下提示:

那我们就需要继续查找所缺的内容,并将其添加到我们的代码中去。直到找到所有的代码逻辑。在此过程要细心,最好是先打上断点(这里的断点要详细,我们主要是看其运行流程),跟一遍流程,然后我们就可以大概明白了其具体加密中用到了那些逻辑,然后我们在添加代码的过程中就可以对其留有印象,从而避免失误。

最终补完的代码如下:

// Digit conversions
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr,vv;
rr = "0".charCodeAt(0);
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
rr = "a".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
rr = "A".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;function nbv(i){ var r = nbi(); this.t = 1;this.s = (i<0)?-1:0;if(i > 0) this[0] = i;else if(i < -1) this[0] = i+DV;else this.t = 0;return r; }
BigInteger.ONE = nbv(1);// 修改了name
var navigator = {'Name':"Netscape"};
var j_lm = true;
var dbits;
function am3(i,x,w,j,c,n) {var xl = x&0x3fff, xh = x>>14;while(--n >= 0) {var l = this[i]&0x3fff;var h = this[i++]>>14;var m = xh*l+h*xl;l = xl*l+((m&0x3fff)<<14)+w[j]+c;c = (l>>28)+(m>>14)+xh*h;w[j++] = l&0xfffffff;}return c;
}
function am1(i,x,w,j,c,n) {while(--n >= 0) {var v = x*this[i++]+w[j]+c;c = Math.floor(v/0x4000000);w[j++] = v&0x3ffffff;}return c;
}
if(j_lm && (navigator.Name == "Microsoft Internet Explorer")) {BigInteger.prototype.am = am2;dbits = 30;
}
else if(j_lm && (navigator.Name != "Netscape")) {BigInteger.prototype.am = am1;dbits = 26;
}
else { // Mozilla/Netscape seems to prefer am3BigInteger.prototype.am = am3;dbits = 28;
}
BigInteger.prototype.DM = ((1<<dbits)-1);
BigInteger.prototype.DB = dbits;
BigInteger.prototype.DV = (1<<dbits);var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2,BI_FP);
BigInteger.prototype.F1 = BI_FP-dbits;
BigInteger.prototype.F2 = 2*dbits-BI_FP;function Classic(m) { this.m = m; }
function cConvert(x) {if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);else return x;
}
function cRevert(x) { return x; }
function cReduce(x) { x.divRemTo(this.m,null,x); }
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;
function montConvert(x) {var r = nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);return r;
}
function montRevert(x) {var r = nbi();x.copyTo(r);this.reduce(r);return r;
}
function montReduce(x) {while(x.t <= this.mt2)    // pad x so am has enough room laterx[x.t++] = 0;for(var i = 0; i < this.m.t; ++i) {// faster way of calculating u0 = x[i]*mp mod DVvar j = x[i]&0x7fff;var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;// use am to combine the multiply-shift-add into one callj = i+this.m.t;x[j] += this.m.am(0,u0,x,i,0,this.m.t);// propagate carrywhile(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }}x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}// r = "x^2/R mod m"; x != r
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }// r = "xy/R mod m"; x,y != r
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;
function Barrett(m) {// setup Barrettthis.r2 = nbi();this.q3 = nbi();BigInteger.ONE.dlShiftTo(2*m.t,this.r2);this.mu = this.r2.divide(m);this.m = m;
}
function barrettConvert(x) {if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);else if(x.compareTo(this.m) < 0) return x;else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
}
function barrettReduce(x) {x.drShiftTo(this.m.t-1,this.r2);if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);x.subTo(this.r2,x);while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}// r = x^2 mod m; x != r
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }// r = x*y mod m; x,y != r
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function barrettRevert(x) { return x; }
Barrett.prototype.revert = barrettRevert;
Barrett.prototype.convert = barrettConvert;
Barrett.prototype.reduce = barrettReduce;
Barrett.prototype.mulTo = barrettMulTo;
Barrett.prototype.sqrTo = barrettSqrTo;
function NullExp() {}
function nNop(x) { return x; }
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
function nSqrTo(x,r) { x.squareTo(r); }
NullExp.prototype.convert = nNop;
NullExp.prototype.revert = nNop;
NullExp.prototype.mulTo = nMulTo;
NullExp.prototype.sqrTo = nSqrTo;function Montgomery(m) {this.m = m;this.mp = m.invDigit();this.mpl = this.mp&0x7fff;this.mph = this.mp>>15;this.um = (1<<(m.DB-15))-1;this.mt2 = 2*m.t;
}
function BigInteger(a,b,c) {if(a != null)if("number" == typeof a) this.fromNumber(a,b,c);else if(b == null && "string" != typeof a) this.fromString(a,256);else this.fromString(a,b);
}
function bnpFromString(s,b) {var k;if(b == 16) k = 4;else if(b == 8) k = 3;else if(b == 256) k = 8; // byte arrayelse if(b == 2) k = 1;else if(b == 32) k = 5;else if(b == 4) k = 2;else { this.fromRadix(s,b); return; }this.t = 0;this.s = 0;var i = s.length, mi = false, sh = 0;while(--i >= 0) {var x = (k==8)?s[i]&0xff:intAt(s,i);if(x < 0) {if(s.charAt(i) == "-") mi = true;continue;}mi = false;if(sh == 0)this[this.t++] = x;else if(sh+k > this.DB) {this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;this[this.t++] = (x>>(this.DB-sh));}elsethis[this.t-1] |= x<<sh;sh += k;if(sh >= this.DB) sh -= this.DB;}if(k == 8 && (s[0]&0x80) != 0) {this.s = -1;if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;}this.clamp();if(mi) BigInteger.ZERO.subTo(this,this);
}
function bnpClamp() {var c = this.s&this.DM;while(this.t > 0 && this[this.t-1] == c) --this.t;
}
function intAt(s,i) {var c = BI_RC[s.charCodeAt(i)];return (c==null)?-1:c;
}
function bnBitLength() {if(this.t <= 0) return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
}
function nbits(x) {var r = 1, t;if((t=x>>>16) != 0) { x = t; r += 16; }if((t=x>>8) != 0) { x = t; r += 8; }if((t=x>>4) != 0) { x = t; r += 4; }if((t=x>>2) != 0) { x = t; r += 2; }if((t=x>>1) != 0) { x = t; r += 1; }return r;
}function bnAbs() { return (this.s<0)?this.negate():this; }
function bnpInvDigit() {if(this.t < 1) return 0;var x = this[0];if((x&1) == 0) return 0;var y = x&3;        // y == 1/x mod 2^2y = (y*(2-(x&0xf)*y))&0xf;    // y == 1/x mod 2^4y = (y*(2-(x&0xff)*y))&0xff;    // y == 1/x mod 2^8y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;    // y == 1/x mod 2^16// last step - calculate inverse mod DV directly;// assumes 16 < DB <= 32 and assumes ability to handle 48-bit intsy = (y*(2-x*y%this.DV))%this.DV;        // y == 1/x mod 2^dbits// we really want the negative inverse, and -DV < y < DVreturn (y>0)?this.DV-y:-y;
}
function nbi() { return new BigInteger(null); }
function bnpExp(e,z) {if(e > 0xffffffff || e < 1) return BigInteger.ONE;var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;g.copyTo(r);while(--i >= 0) {z.sqrTo(r,r2);if((e&(1<<i)) > 0) z.mulTo(r2,g,r);else { var t = r; r = r2; r2 = t; }}return z.revert(r);
}
function bnModPowInt(e,m) {var z;if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);return this.exp(e,z);
}
function bnpDLShiftTo(n,r) {var i;for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];for(i = n-1; i >= 0; --i) r[i] = 0;r.t = this.t+n;r.s = this.s;
}
function bnpDivRemTo(m,q,r) {var pm = m.abs();if(pm.t <= 0) return;var pt = this.abs();if(pt.t < pm.t) {if(q != null) {this.t = 1;this.s = (0<0)?-1:0;if(0 > 0) this[0] = x;else if(0 < -1) this[0] = 0+DV;else this.t = 0;};if(r != null) this.copyTo(r);return;}if(r == null) r = nbi();var y = nbi(), ts = this.s, ms = m.s;var nsh = this.DB-nbits(pm[pm.t-1]);    // normalize modulusif(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }else { pm.copyTo(y); pt.copyTo(r); }var ys = y.t;var y0 = y[ys-1];if(y0 == 0) return;var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;var i = r.t, j = i-ys, t = (q==null)?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t) >= 0) {r[r.t++] = 1;r.subTo(t,r);}BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);    // "negative" y so we can replace sub with am laterwhile(y.t < ys) y[y.t++] = 0;while(--j >= 0) {// Estimate quotient digitvar qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {    // Try it outy.dlShiftTo(j,t);r.subTo(t,r);while(r[i] < --qd) r.subTo(t,r);}}if(q != null) {r.drShiftTo(ys,q);if(ts != ms) BigInteger.ZERO.subTo(q,q);}r.t = ys;r.clamp();if(nsh > 0) r.rShiftTo(nsh,r);    // Denormalize remainderif(ts < 0) BigInteger.ZERO.subTo(r,r);
}
function bnpLShiftTo(n,r) {var bs = n%this.DB;var cbs = this.DB-bs;var bm = (1<<cbs)-1;var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;for(i = this.t-1; i >= 0; --i) {r[i+ds+1] = (this[i]>>cbs)|c;c = (this[i]&bm)<<bs;}for(i = ds-1; i >= 0; --i) r[i] = 0;r[ds] = c;r.t = this.t+ds+1;r.s = this.s;r.clamp();
}
function bnCompareTo(a) {var r = this.s-a.s;if(r != 0) return r;var i = this.t;r = i-a.t;if(r != 0) return r;while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;return 0;
}
function bnpSubTo(a,r) {var i = 0, c = 0, m = Math.min(a.t,this.t);while(i < m) {c += this[i]-a[i];r[i++] = c&this.DM;c >>= this.DB;}if(a.t < this.t) {c -= a.s;while(i < this.t) {c += this[i];r[i++] = c&this.DM;c >>= this.DB;}c += this.s;}else {c += this.s;while(i < a.t) {c -= a[i];r[i++] = c&this.DM;c >>= this.DB;}c -= a.s;}r.s = (c<0)?-1:0;if(c < -1) r[i++] = this.DV+c;else if(c > 0) r[i++] = c;r.t = i;r.clamp();
}
function bnpRShiftTo(n,r) {r.s = this.s;var ds = Math.floor(n/this.DB);if(ds >= this.t) { r.t = 0; return; }var bs = n%this.DB;var cbs = this.DB-bs;var bm = (1<<bs)-1;r[0] = this[ds]>>bs;for(var i = ds+1; i < this.t; ++i) {r[i-ds-1] |= (this[i]&bm)<<cbs;r[i-ds] = this[i]>>bs;}if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;r.t = this.t-ds;r.clamp();
}
function bnpCopyTo(r) {for(var i = this.t-1; i >= 0; --i) r[i] = this[i];r.t = this.t;r.s = this.s;
}
function bnpDRShiftTo(n,r) {for(var i = n; i < this.t; ++i) r[i-n] = this[i];r.t = Math.max(this.t-n,0);r.s = this.s;
}
BigInteger.prototype.DV = (1<<dbits);function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
//  注意this.t
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.modPowInt = bnModPowInt;
BigInteger.prototype.exp = bnpExp;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
// BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.bitLength = bnBitLength;
// 注意
BigInteger.prototype.DB = dbits;var RSAPublicKey = function($modulus_hex, $encryptionExponent_hex) {this.modulus = new BigInteger( $modulus_hex, 16);this.encryptionExponent = new BigInteger( $encryptionExponent_hex, 16);
};var Base64 = {base64: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode: function($input) {if (!$input) {return false;}var $output = "";var $chr1, $chr2, $chr3;var $enc1, $enc2, $enc3, $enc4;var $i = 0;do {$chr1 = $input.charCodeAt($i++);$chr2 = $input.charCodeAt($i++);$chr3 = $input.charCodeAt($i++);$enc1 = $chr1 >> 2;$enc2 = (($chr1 & 3) << 4) | ($chr2 >> 4);$enc3 = (($chr2 & 15) << 2) | ($chr3 >> 6);$enc4 = $chr3 & 63;if (isNaN($chr2)) $enc3 = $enc4 = 64;else if (isNaN($chr3)) $enc4 = 64;$output += this.base64.charAt($enc1) + this.base64.charAt($enc2) + this.base64.charAt($enc3) + this.base64.charAt($enc4);} while ($i < $input.length);return $output;},decode: function($input) {if(!$input) return false;$input = $input.replace(/[^A-Za-z0-9\+\/\=]/g, "");var $output = "";var $enc1, $enc2, $enc3, $enc4;var $i = 0;do {$enc1 = this.base64.indexOf($input.charAt($i++));$enc2 = this.base64.indexOf($input.charAt($i++));$enc3 = this.base64.indexOf($input.charAt($i++));$enc4 = this.base64.indexOf($input.charAt($i++));$output += String.fromCharCode(($enc1 << 2) | ($enc2 >> 4));if ($enc3 != 64) $output += String.fromCharCode((($enc2 & 15) << 4) | ($enc3 >> 2));if ($enc4 != 64) $output += String.fromCharCode((($enc3 & 3) << 6) | $enc4);} while ($i < $input.length);return $output;}
};var Hex = {hex: "0123456789abcdef",encode: function($input) {if(!$input) return false;var $output = "";var $k;var $i = 0;do {$k = $input.charCodeAt($i++);$output += this.hex.charAt(($k >> 4) &0xf) + this.hex.charAt($k & 0xf);} while ($i < $input.length);return $output;},decode: function($input) {if(!$input) return false;$input = $input.replace(/[^0-9abcdef]/g, "");var $output = "";var $i = 0;do {$output += String.fromCharCode(((this.hex.indexOf($input.charAt($i++)) << 4) & 0xf0) | (this.hex.indexOf($input.charAt($i++)) & 0xf));} while ($i < $input.length);return $output;}
};var RSA = {getPublicKey: function( $modulus_hex, $exponent_hex ) {return new RSAPublicKey( $modulus_hex, $exponent_hex );},encrypt: function($data, $pubkey) {if (!$pubkey) return false;$data = this.pkcs1pad2($data,($pubkey.modulus.bitLength()+7)>>3);if(!$data) return false;$data = $data.modPowInt($pubkey.encryptionExponent, $pubkey.modulus);if(!$data) return false;$data = ($data).toString(16);if(($data.length & 1) == 1)console.log($data)$data = "0" + $data;return Base64.encode(Hex.decode($data));},pkcs1pad2: function($data, $keysize) {if($keysize < $data.length + 11)return null;var $buffer = [];var $i = $data.length - 1;while($i >= 0 && $keysize > 0)$buffer[--$keysize] = $data.charCodeAt($i--);$buffer[--$keysize] = 0;while($keysize > 2)$buffer[--$keysize] = Math.floor(Math.random()*254) + 1;$buffer[--$keysize] = 2;$buffer[--$keysize] = 0;return new BigInteger($buffer);}
};var publickey_mod = 'xxxxxx';
publickey_exp = 'xxxxxx';var pubKey = RSA.getPublicKey(publickey_mod, publickey_exp);
console.log(RSA.encrypt("123456", pubKey));

我们再次运行这个代码,发现其不报错了,但是其返回的结果是C+y+wA==


运行后发现结果不对劲,内心很崩溃呀。
在这里,我们就要思考问题所在了,可能是有哪些变量没补正确,也可能是那些逻辑写错了。

由于结果不正确,所以在此处,我又重新进行了一次js逆向,一步一步的去不代码。最总发现结果还是一样的。

此时,已经可以感觉到不同寻常了 ,是不是代码都补正确了,但是在执行的过程中出现了一些偏差。

于是乎,我就在最终结果生成逻辑的位置加了一下console.log()以输出一些结果的值。最终发现,在$data转化为字符串时出现了错误,本该生成字符串的,但在我这里生成了[object Object],把本地代码放到浏览器运行也是同样的结果。(toString() 可以将对象转化为字符串也可以转化为[object Object],但同样的对象出现两种不同的结果,很迷惑)。

于是乎,我就在想,只要将其表示为字符串应该就没问题了,所以在此处我将其改为了json.stringify(),转换为字符串后在进行tostring(16)进行转换。

最终得到了正确的结果(因为rsa每次结果都不一样,每次都会对数据进行随机填充);

注意事项

在该案例中,需要注意的地方有以下几点:
1、在补代码的时候需要注意this.xxx这种变量,特别是当其只表示一个变量的时候,我们需要在源代码中找到其真正的数据,因为在我们本地使用nodejs执行js的时候,有些this.xxx我们没有找到正确的值,但运行并不会报错,只是可能造成的结果不一致。所以我们需要拿到源代码中真正的this.xxx 变量,才能保证我们最终获取到真正的结果。
**
**
2、在本次补代码的过程中,添加了一个函数,但在执行过程中,该函数被判定为对象,然后报没有该函数的错误,我在这里直接将其函数逻辑写到了代码中,并没有去调用。
暂时没有想到原因。
(为啥使用function 定义的函数被判定为对象?很奇怪)
**
**
3、有些时候,我们补完代码运行后的结果和真正的结果有偏差,这时我们首先要做的是检查阶段结果是否和正确结果保持一致,从而找到错误位置。而不是直接全盘否定,这样会浪费大量时间和精力。

记一次js逆向详细过程相关推荐

  1. 2021-09-28 微博扫码登录获取cookie,附带账号密码js逆向解密过程

    一.前言 作者:tiezhu 本人和账号作者是朋友,以后将会公用此账号发布文章,也是一个学习爬虫的小白 此篇文章仅供学习交流,切勿用于其他用途,否则后果自负! 二.过程分析 需要使用的库 import ...

  2. 2021-09-29 微博扫码登录获取cookie,附带账号密码js逆向解密过程(完结)

    一.前言 作者:tiezhu 接下来就是微博的js逆向了,这里需要使用到WebStorm WebStorm下载 本文章仅供学习研究,如若侵犯到贵公司权益请联系229456906@qq.com第一时间进 ...

  3. JS逆向必会基础案例 | 百度翻译参数破解

    前情回顾:有道翻译参数破解 在上一篇博客中,我们系统地分析了有道翻译的JS逆向过程.不难看出,JS逆向其实就是用Python重新来复写Javascript的代码.但当JS代码很长时,弄懂里面的逻辑关系 ...

  4. JS逆向 | ob混淆一键还原工具

    声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!  在JS逆向的过程中,我们可能经常碰到类似如下的代码:  开头定义了一个大数组,然后对这个大数组里的内容进行位移, ...

  5. 爬虫js逆向获取信息,有道翻译逆向{‘errorCode‘: 50}及UA错误

    直奔错误记录,{'errorCode': 50}的错误原因,在我的这次学习过程错误是由于请求使用错误,用了get方法,有道翻译是需要用post才能请求: 切记留意请求方式,不要习惯性使用request ...

  6. 猿人学第一题超详细-JS逆向过程

    转自 [ 不止于python ] 目标网站 https://match.yuanrenxue.com/match/1 目标要求 抓取所有(5页)机票的价格,并计算所有机票价格的平均值,填入答案. 网站 ...

  7. JS逆向——破解百度翻译参数(sign)爬虫 超级详细

    一.分析请求参数 打开地址: https://fanyi.baidu.com/ 打开Chrome调试工具,然后随意输入一段文字,查看抓包结果. post请求 Form data 参数 如上图所示,Fo ...

  8. JS逆向-国税增值税发票查询平台的漫漫过程

    一.2019年下半年,因为工作需要,有大量增值税发票需要查询真伪,而且是每张必查,当时还不太懂爬虫原理,就用"C#+大漠插件+全球鹰验证码识别"写了个类似于按键精灵那样的桌面应用程 ...

  9. JS逆向 -- 分析某站aid、cid、w_rid和sid的加密过程

    接上节课内容 JS逆向 -- 分析某站buvid3和_uuid的加密过程 JS逆向 -- 分析某站b_lsid值加密过程 一.清除cookie信息,刷新网页,ctrl+f搜索sid,这样找到的数据是在 ...

最新文章

  1. html表格立体效果,用HTML实现凸(凹)起的立体效果的表格
  2. python基础指令-Python基础——与Python的指令交互
  3. 计算机考研一定要去北上广吗,考研一定要去“北上广”吗?这几类学生可能更适合......
  4. shell批量创建随机文件名格式文件
  5. cannot resolve symbol ‘log‘问题解决
  6. HTML DOM教程 24-HTML DOM Frameset 对象
  7. 深入react技术栈(7):组件化实例:Tab栏组件
  8. Jsp和Servlet有什么区别?
  9. PAT1119 Pre- and Post-order Traversals(先序后序求中序)
  10. 时序分析基本概念介绍——STA概述
  11. 【IJCAI 2020】篇章要素识别和篇章结构评分(下)
  12. ./configure: line 4850: ` XIPH_PATH_OGG(, as_fn_error $? '
  13. 【Codeforces Global Round 2】A-E题解 【Frets On Fire、Pavel and Triangles】
  14. 点分十进制ip地址转为十进制数字地址-python3实现
  15. 注意,因为这样操作,zoom登录不上了
  16. python发微信给手机充值话费_微信充话费如何自定义金额?最低1元起充的技巧...
  17. P4839 P哥的桶 题解
  18. 温泉PHP网络授权系统,温泉PHP授权系统验证系统完整开源
  19. 04.jQuery++1201
  20. Android_Google Pay的添加使用

热门文章

  1. 尾部相关性尾部风险价圣分
  2. mysql导入xl_28 MySQL的使用
  3. 电路仿真软件proteus简单使用
  4. 直流马达驱动_ADC_PWM加减速(STM32F4 CubeMX)
  5. PCA9685--16路 PWM模块舵机驱动板--STM32 IIC接口模块
  6. iphone 文件app连接服务器,最快速 iPhone 和 Windows 之间传输文件的方法,无需安装APP!...
  7. 将list对象存储进redis中去
  8. [Thoughts]敏捷方法大全
  9. 如何通过事务消息保障抢购业务的分布式一致性?
  10. before和after怎么区分_before和after区别 关于before和after