url: https://www.epwk.com/login.html
分析过程
-
输入用户名和密码,看触发的流量包。
-
signature
参数明显是被加密过的,接下来就是去寻找加密的过程。关键词搜索signature
。
有两处,第二处是个固定值不需要看,关注点在第一处。 -
点进去看对应的代码,并打断点,重新登录,触发该断点。
查看该行代码所有变量的值。
总共是4个关注点,Object(f.a)
是个函数,U
、M
、l.j ? l.g : l.c
是传给Object(f.a)
函数的三个变量。 -
先看三个变量中的
l.j ? l.g : l.c
。l.j
为false,所以会取l.c
。
-
再看
U
变量。
U
的定义如下:
其中需要考虑的变量只有Timestemp
、NonceStr
和App-Id
,其余值都是固定的。
App-Id
的值最容易得到,由于l.j
为false,故App-Id
的值为l.b
的值。
Timestemp
的值就是个时间戳。
NonceStr
的变量稍微麻烦点,由Timestemp
和Object(h.e)()
拼接而成。看Object(h.e)()
是什么。
该函数本质上就是生成一个随机字符串并截取字符串中的第3位到第8位,既然是个随机函数,所以该值取什么无所谓。 -
最后看
M
变量。
其中的username和password和code就是我们输入的账号密码和图片验证码。refer可以理解成一个固定值,不用变。 -
变量看完了,最后来看
Object(f.a)
函数。
看到函数中的变量都跟arguments
有关,先看arguments
是什么。
arguments
是个字典,第一个键值对中的值就是U
变量,第二个键值对中的值就是M
变量,第三个键值对中的值是个定值。那么变量data
和e
很容易就能得到。
n = e + f(data) + f(t) + e
中需要知道f
函数的作用和变量t
是什么。
变量t
跟变量U
是一致的。
函数f
的实现如下。
如果我们看不懂具体代码是什么意思,可以将结果输出看看。
大概就是一个字符串的拼接。
最后看d
和v
函数。
d
函数是一个md5算法,v
算法是一个AES加密,只要知道了密钥、偏移量和加密模式即可。
上图中显示的key和iv都是字节,想要看到字符串类型的话可以采用toString函数。
-
一切加密过程都知道了,把相关代码复制,完整代码如下。
var CryptoJS = require("crypto-js");
function test(t, arguments) {
var data = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
, e = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "a75846eb4ac490420ac63db46d2a03bf"
, n = e + f(data) + f(t) + e;
return n = d(n),
n = v(n)
}
r = {};
r.a = function(e) {
return typeof e
};
function f(t) {
var e = "";
return Object.keys(t).sort().forEach((function(n) {
e += n + ("object" === Object(r.a)(t[n]) ? JSON.stringify(t[n], (function(t, e) {
return "number" == typeof e && (e = String(e)),
e
}
)).replace(/\//g, "\\/") : t[n])
}
)),
e
}
l = {
"key": {
"words": [
1717059670,
2034454870,
1987077226,
944915297
],
"sigBytes": 16
},
"iv": {
"words": [
0,
0,
0,
0
],
"sigBytes": 16
}
};
function d(data) {
return CryptoJS.MD5(data).toString()
}
function v(data) {
return function(data) {
return CryptoJS.AES.encrypt(data, l.key, {
iv: l.iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString()
}(data)
}
测试一下。
t = {
"App-Ver": "",
"Os-Ver": "",
"Device-Ver": "",
"Imei": "",
"Access-Token": "",
"Timestemp": 1713833424,
"NonceStr": "1713833424aoi0s",
"App-Id": "4ac490420ac63db4",
"Device-Os": "web"
};
arguments = {
"0": {
"App-Ver": "",
"Os-Ver": "",
"Device-Ver": "",
"Imei": "",
"Access-Token": "",
"Timestemp": 1713833424,
"NonceStr": "1713833424aoi0s",
"App-Id": "4ac490420ac63db4",
"Device-Os": "web"
},
"1": {
"username": "111111",
"password": "111111",
"code": "qwrd",
"hdn_refer": "https://www.epwk.com/"
},
"2": "a75846eb4ac490420ac63db46d2a03bf"
};
console.log(test(t, arguments));
结果如下:
可以得到正确的加密结果。
如果想要在python中运行,需要加入下述代码:
import time
import execjs
App_Ver = ""
Os_Ver = ""
Device_Ver = ""
Imei = ""
Access_Token = ""
App_Id = "4ac490420ac63db4"
Device_Os = "web"
timestamp = int(time.time())
NonceStr = "{}fj1e".format(timestamp)
t = {
"App-Ver": App_Ver,
"Os-Ver": Os_Ver,
"Device-Ver": Device_Ver,
"Imei": Imei,
"Access-Token": Access_Token,
"Timestemp": timestamp,
"NonceStr": NonceStr,
"App-Id": App_Id,
"Device-Os": Device_Os
}
arguments = {
"0": t,
"1": {
"username": "111111",
"password": "123456",
"code": "zyp6",
"hdn_refer": "https://www.epwk.com/"
},
"2": "a75846eb4ac490420ac63db46d2a03bf"
}
f = open("解密.js", mode="r", encoding="utf-8")
exec_js = f.read()
exec_code = execjs.compile(exec_js)
print(exec_code.call("test", t, arguments))
标签:威客,Ver,data,App,js,arguments,signature,Device,Os
From: https://www.cnblogs.com/sbhglqy/p/18152594