已迁移平台:segmentfault,搜索 erma0
换平台了,发什么都锁定,广告一堆,趁早倒闭吧。
JavaScript逆向练习2
0x01 目标网址
http://www.miguvideo.com/
抓包或者右键查看框架源代码可以看到,弹出的登录框URL为:
https://passport.migu.cn/login?sourceid=203021&apptype=2&forceAuthn=true&isPassive=false&authType=&display=&nodeId=70027513&relayState=login&weibo=1&callbackURL=http%3A%2F%2Fwww.miguvideo.com%2Fmgs%2Fwebsite%2Fprd%2Findex.html%3FisIframe%3Dweb
0x02 定位JS
1. 随便输入账号密码验证码,,有验证码要输入正确的验证码,点击登录,查看提交的参数
可以看到,发出了两个请求,第一个是获取key,第二个是登录,在登录包里有加密过 的参数,密码enpassword
、伪指纹fingerPrint
、fingerPrintDetail
。
2. Ctrl+Shift+F调出搜索面板,搜索enpassword
,看到只要一个结果,而且是网页源码。
乍一看没有头绪,其实这里是通过Class来定位取值的,也就是说,这里可以试试再搜索一次Class的值:J_RsaPsd
,可以看到有两条结果,第二个是我们上一次搜索的结果,肯定不是加密点,所以应该是在第一个结果里。
点进第一个结果,点花括号格式化一下,Ctrl+F搜索J_RsaPsd
,发现有三个结果,稍作分析,在每一个可疑的地方都下断点。
3. 重新输入账号密码验证码,点击登录,JS被断了下来,我们要的加密点是在328-338行的位置,代码扣下来备用。
success: function(a) {
if (a.status = g.ajax.SUCCESS) {
c.each(function() {
var b = $(this),
c = new j.RSAKey;
c.setPublic(a.result.modulus, a.result.publicExponent);
var d = c.encrypt(b.val());
b.siblings(".J_RsaPsd").val(d)
});
var b = i.page.rsaFingerprint(a.result.modulus, a.result.publicExponent);
d.filter(".J_FingerPrint").val(b.result).end().filter(".J_FingerPrintDetail").val(b.details)
}
这段代码就是当异步请求Key(就是1中抓包看到的两条请求中的第一个)成功后,根据Key进行加密操作。
其中b.val()
是明文密码,a.result.modulus, a.result.publicExponent
是第一条请求得到的Key,直接固定,i.page.rsaFingerprint
是计算另外两个加密参数。
鼠标悬停在j.RSAKey
上(这里是new出来的对象,先要找到来源),点击弹出的内容,直接跳转进去。
4. 进入对象的定义函数中,发现全是this,那就直接把整个上一层全拿走,一直翻,找出的上层代码是3916行开始,到4521行结束。
define("lib/rsa/rsa", [], function(a, b, c) {
function d(a, b, c) {
null != a && ("number" == typeof a ? this.fromNumber(a, b, c) : null == b && "string" != typeof a ? this.fromString(a, 256) : this.fromString(a, b))
}
***
省略
***
ab.prototype.nextBytes = _,
db.prototype.doPublic = fb,
db.prototype.setPublic = eb,
db.prototype.encrypt = gb,
c.exports = {
RSAKey: db
}
}),
5. 到这里已经可以开始改写密码加密部分的内容了,但是还有两个参数也有加密,我还是一起扣出来再改写。
同上,在337行下个断点,再运行到这里。鼠标悬停在rsaFingerprint
上,点击弹出的内容,直接跳转进去。
直接把定义函数扣出来就可以。
rsaFingerprint: function(a, b) {
if (!$.fingerprint)
return {
details: "",
result: ""
};
var c = $.fingerprint.details
, d = $.fingerprint.result
, e = c.length
, f = ""
, g = new l.RSAKey;
g.setPublic(a, b);
for (var h = g.encrypt(d), i = 0; e > i; i += 117)
f += g.encrypt(c.substr(i, 117));
return {
details: f,
result: h
}
}
这其中参数a,b是第一条请求的Key,可以直接固定;$.fingerprint
可以到console输出看一下,是浏览器、请求头相关的信息,可以说是伪指纹,暂且固定,最后return的是个对象,正好是登录包里的另外两个参数。
0x03 改写JS
1. 先写一个调用函数。
var p1 = "00833c4af965ff7a8409f8b5d5a83d87f2f19d7c1eb40dc59a98d2346cbb145046b2c6facc25b5cc363443f0f7ebd9524b7c1e1917bf7d849212339f6c1d3711b115ecb20f0c89fc2182a985ea28cbb4adf6a321ff7e715ba9b8d7261d1c140485df3b705247a70c28c9068caabbedbf9510dada6d13d99e57642b853a73406817",
p2 = "010001";//因为另一个加密也要调用这两个值,所以定义在函数外面,作为全局变量用。
function getP(pass) {//密码加密计算函数,仿照加密点代码写的。
var c = new RSAKey;
c.setPublic(p1, p2);
var d = c.encrypt(pass);
return d;
}
2. 改写RSAKey对象定义处
window = this;
navigator = {}; //把需要用到的值先定义空对象
//把第一行删掉,把内部的函数暴露出来(对应的结尾部分的括号也删掉)
//define("lib/rsa/rsa", [], function(a, b, c) {
function d(a, b, c) {
null != a && ("number" == typeof a ? this.fromNumber(a, b, c) : null == b && "string" != typeof a ? this.fromString(a, 256) : this.fromString(a, b))
}
***
省略
***
ab.prototype.nextBytes = _,
db.prototype.doPublic = fb,
db.prototype.setPublic = eb,
db.prototype.encrypt = gb;
//把原来的逗号换成分号结束掉语句。
//,
//c.exports = {
// RSAKey: db
//}
//本来是用exports来对外导出,现在直接定义对象就可以。
var RSAKey = db;
//}),
现在就可以通过getP(pass)
来加密明文密码了。
3. 改写rsaFingerprint
定义
先把之前console里输出的浏览器信息定义成变量,再把函数部分改成正常的定义就可以了。
把开始的if判断给删除,另外这里还要把对应的值都给换一下,如*.RSAKey换成RSAKey。
var details = '{"user_agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safa","language":"zh-CN","color_depth":"24","pixel_ratio":"1.25","hardware_concurrency":"4","resolution":"1536,864","available_resolution":"1536,824","timezone_offset":"-480","session_storage":"1","local_storage":"1","indexed_db":"1","open_database":"1","cpu_class":"unknown","navigator_platform":"Win32","do_not_track":"unknown","regular_plugins":"Chromium PDF Plugin::Portable Document Format::application/x-google-chrome-pdf~pdf,Chromium PDF View","webgl_vendor":"Google Inc.~ANGLE (Intel(R) HD Graphics 530 Direct3D9Ex vs_3_0 ps_3_0)","adblock":"true","has_lied_languages":"false","has_lied_resolution":"false","has_lied_os":"false","has_lied_browser":"false","touch_support":"0,false,false","js_fonts":"Arial,Arial Black,Arial Narrow,Book Antiqua,Bookman Old Style,Calibri,Cambria,Cambria Math,Century,C"}',
result = "2754353484e6bed2ec7cf41dddba8bce"
rsaFingerprint = function() {
var c = details,
d = result,
e = c.length,
f = "",
g = new RSAKey;
g.setPublic(aaaa, "010001");
for (var h = g.encrypt(d), i = 0; e > i; i += 117)
f += g.encrypt(c.substr(i, 117));
return {
details: f,
result: h
}
}
此时就可以运行了。
0x04 代码
省略
PS
如果在加密后的登陆过程中出现异常,那可能是浏览器信息的问题,仔细对照看看哪里不一样就知道了。