问题:(1)接口返回值加密
1、接口返回的数据为加密后的文本,先根据密文长度无法直接判断具体的加密方式
2、个人比较喜欢用hook,所以先对几个常用的加解密函数进行hook,并进行控制台输出(hook的工具写在下面,需要的自行提取)
3、上图可以很清楚的看到,红色部分是接口链接的参数部分,绿色部分为已经解密过后的数据,也就是我们需要的,最下面蓝色部分也可以看到解密后的文本经过了json.parse解析成数据字典,这里可以从json.parse入手。
4、定位到 json.parse这行的hook函数中,并在此处打上断点,在进行下一页操作,到此处暂停后发现右侧调用栈里又个方法h( ),跟进去
5、 即可发现,t 为接口请求的密文,并且加密方式为AES.CBC,偏移量为
f = d.a.enc.Utf8.parse("jo8j9wGw%6HbxfFn")
m = d.a.enc.Utf8.parse("0123456789ABCDEF")
6、至此我们就可以用代码进行还原解密函数
var CryptoJS = require('C:/Data/npm/node_modules/crypto-js')
function getDecryptedData(t) {
var m = CryptoJS.enc.Utf8.parse("0123456789ABCDEF"),
f = CryptoJS.enc.Utf8.parse("jo8j9wGw%6HbxfFn"),
e = CryptoJS.enc.Hex.parse(t),
n = CryptoJS.enc.Base64.stringify(e),
a = CryptoJS.AES.decrypt(n, f, {
iv: m,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}),
r = a.toString(CryptoJS.enc.Utf8);
return r.toString()
}
var fs = require('fs')
fs.readFile('./jzsc_mohurd.txt','utf8',function(err,dataStr) {
if(err){
return console.log("读取文件失败!"+err.message)
}
console.log(getDecryptedData(dataStr))
})
7、请求接口,并执行以下方法,此处说下,我是用的cmd执行的node命令,由于我电脑环境下,接口的加密字符远远超过了命令行的最大字符数,所以采用了 jzsc_mohurd.txt 文件做中转。
def get_data(projectType, region_id, page):
'''
获取接口数据
@return:
'''
url = 'https://jzsc.mohurd.gov.cn/api/webApi/dataservice/query/project/list?projectType={}&projectRegionId={}&pg={}&pgsz=15'.format(
projectType, region_id, page)
headers = {
'Host': 'jzsc.mohurd.gov.cn',
'Referer': 'http://jzsc.mohurd.gov.cn/data/project',
'User-Agent': getUserAgent()
}
res = requests.get(url, headers=headers)
logger.debug('接口:{}'.format(url))
logger.debug('获取的密文为:{}'.format(res.text))
with open('./jzsc_mohurd.txt', 'w', encoding='utf-8') as f:
f.write(res.text)
decrypt_data()
def decrypt_data():
"""
解密接口数据
@param ciphertext:
@return:
"""
logger.debug('数据解密...')
cmd = "node jzsc_mohurd.js"
with os.popen(cmd) as fp:
bf = fp._stream.buffer.read()
try:
plaintext = bf.decode().strip()
except UnicodeDecodeError:
plaintext = bf.decode('gbk').strip()
logger.debug('解密后的数据为:{}'.format(plaintext))
return plaintext