一、数据接口分析
主页地址:某空气质量平台
1、抓包
(1) 反调试
该网站对鼠标右击以及F12进行了监听并拦截
虽然该网站无法打开Chrome控制台,导致我们无法抓包,但是道高一尺魔高一丈。既然我们无法在打开该网站的时候打开Chrome控制台,那么我们可以先在新标签页中打开Chrome控制台,再进入该网站。
(2)抓包
通过抓包可以发现数据接口是/apinew/aqistudyapi.php
2、判断是否有加密参数
-
请求参数是否加密?
通过查看“载荷”模块,可以发现有一个hXhY1B2Kd
加密参数
-
请求头是否加密?
无 -
响应是否加密?
通过查看响应模块,可以发现响应数据是密文
-
cookie是否加密?
无
二、加密位置定位
1、看启动器
查看启动器发现里面有一个sW7FumD53pAq3ysvobb
方法,点进去查看
可以发现这里就是发送ajax请求的位置,并且url就是数据接口。
在这里打上断点,再次获取数据,发现可以断住。密文是由pov0M2gfR
方法生成的,并且在success
中对响应进行了处理。
三、扣js代码
将加密以及解密方法扣出,缺啥补啥即可。扣代码时可以发现,网站使用的是标准的MD5和DES对数据进行加密,AES和DES对响应进行解密,所以可以直接使用标准模块进行加解密。
js源代码:
var CryptoJS = require('crypto-js')
const dckE15Yk15AF = "oHLKvpN54hwpLWjt";
const dcik4kPiOWjo = "pdgLk9FGBd5kXbm0";
const dsk9EbiUpi5W = "hIFclTxH0JalYZiu";
const dsi3gJ2aZe1f = "xMFHANC8X1TunaGs";
const askiZExYII01 = "aPnyDR5Ca6FMIfdw";
const asideGdRY692 = "bNpeyqJl34VlZ7ng";
var DES = {
encrypt: function (text, key, iv) {
var secretkey = (CryptoJS.MD5(key).toString()).substr(0, 16);
var secretiv = (CryptoJS.MD5(iv).toString()).substr(24, 8);
secretkey = CryptoJS.enc.Utf8.parse(secretkey);
secretiv = CryptoJS.enc.Utf8.parse(secretiv);
var result = CryptoJS.DES.encrypt(text, secretkey, {
iv: secretiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return result.toString();
},
decrypt: function (text, key, iv) {
var secretkey = (CryptoJS.MD5(key).toString()).substr(0, 16);
var secretiv = (CryptoJS.MD5(iv).toString()).substr(24, 8);
secretkey = CryptoJS.enc.Utf8.parse(secretkey);
secretiv = CryptoJS.enc.Utf8.parse(secretiv);
var result = CryptoJS.DES.decrypt(text, secretkey, {
iv: secretiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return result.toString(CryptoJS.enc.Utf8);
}
}
var AES = {
encrypt: function(text, key, iv) {
var secretkey = (CryptoJS.MD5(key).toString()).substr(16, 16);
var secretiv = (CryptoJS.MD5(iv).toString()).substr(0, 16);
secretkey = CryptoJS.enc.Utf8.parse(secretkey);
secretiv = CryptoJS.enc.Utf8.parse(secretiv);
var result = CryptoJS.AES.encrypt(text, secretkey, {
iv: secretiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return result.toString();
},
decrypt: function(text, key, iv) {
var secretkey = (CryptoJS.MD5(key).toString()).substr(16, 16);
var secretiv = (CryptoJS.MD5(iv).toString()).substr(0, 16);
secretkey = CryptoJS.enc.Utf8.parse(secretkey);
secretiv = CryptoJS.enc.Utf8.parse(secretiv);
var result = CryptoJS.AES.decrypt(text, secretkey, {
iv: secretiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return result.toString(CryptoJS.enc.Utf8);
}
};
var BASE64 = {
encrypt: function (text) {
// var b = new Base64();
// return b.encode(text);
var buffer = Buffer.from(text);
return buffer.toString('base64');
},
decrypt: function (text) {
var buffer = Buffer.from(text, 'base64');
return buffer.toString('utf8')
}
};
function ObjectSort(obj) {
var newObject = {};
Object.keys(obj).sort().map(function (key) {
newObject[key] = obj[key];
});
return newObject;
}
function pov0M2gfR(method, obj) {
var appId = '271c2aab7dd615dacbadcb41d3c77fa4';
var clienttype = 'WEB';
var timestamp = new Date().getTime();
var param = {
appId: appId,
method: method,
timestamp: timestamp,
clienttype: clienttype,
object: obj,
secret: CryptoJS.MD5(appId + method + timestamp + clienttype + JSON.stringify(ObjectSort(obj))).toString()
};
param = BASE64.encrypt(JSON.stringify(param));
param = DES.encrypt(param, dckE15Yk15AF, dcik4kPiOWjo);
return param;
}
function get_request_params(city='苏州') {
type = "GETDATA"
data = {
'city': city
}
period = 0.5
ktsu = CryptoJS.MD5(type + JSON.stringify(data)).toString()
var phqbwou = pov0M2gfR(type, data)
return { hXhY1B2Kd: phqbwou }
}
function get_response_data(data) {
data = AES.decrypt(data, askiZExYII01, asideGdRY692);
data = DES.decrypt(data, dsk9EbiUpi5W, dsi3gJ2aZe1f);
data = BASE64.decrypt(data);
return data;
}