声明:本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!由于本人水平有限,如有理解或者描述不准确的地方,还望各位大佬指教!!
练习网站:Q3JhenkgUHJvTW9ua2V5IGh0dHBzOi8vdHh6YnF5Lm1paXQuZ292LmNuLyMvZ2F0ZXdheS9saXN0
网站分析:
点击首页,会弹出验证码校验
验证通过后,接口会返回一下信息
网站数据就会在另外一个接口中出现,其post请求参数如图
可以发现,验证码校验后的nonceStr即为数据接口的token参数,而且,有一定经验的大佬就能猜到校验后的blockSrc和cancasSrc两个参数肯定会有关系存在(根据参数名和大佬经验,会知道blockSrc就是滑块图片字节流信息,cancasSrc就是背景图片字节流信息,为了方便新手学习,下文中会来证实这个猜想)
实战演练:
那么,我们既然已经找到了加密的参数code,我们该如何定位该参数的加密入口和过程呢。根据小编的习惯,会先观察接口的启动器调用堆栈,如图
观察之后,也是根据经验,进入某个堆栈,这里小编选择的是 getCaptcha。进入该堆栈并在相应可疑位置打上断点,并翻页重新校验验证码,如图
我们会发现,这个s参数是由cancasSrc和nonceStr两个参数经过u方法实现的,那么我们紧跟u方法,发现u方法执行了一个AES加密(那么该加密在不知道是否经过魔改的情况下,建议大家按原生的方法先去实验),那么根据以上操作,我们现在已经拿到了两个带有以‘data;image/png;base64,’开头的图片信息,即参数blockSrc和s,那么将这两个数据进行解码和保存,会看到两个图片,前面的猜想也被证实
# 滑块
block_src = root.get('blockSrc', '').replace('data:image/png;base64,', '')
imgdata = base64.b64decode(block_src)
with open("f1.png", "wb") as fh:
fh.write(imgdata)
logger.info('滑块图片已保存')
# 背景图
canvas_src = root.get('canvasSrc', '')
bj_img = execjs.compile(fjm_sdk()).call('get_bj_img', canvas_src, nonce_str).replace('data:image/png;base64,', '')
bj_img = base64.b64decode(bj_img)
with open("f2.png", "wb") as fh:
fh.write(bj_img)
logger.info('背景图片已保存')
那么,根据以上信息,我们就能得到了两个验证码图片,下一步该做什么,大佬肯定会盲猜滑块在背景图中的偏移量,然后拿这个偏移量进行后续的操作。没错,这里小编就给大家介绍一个非常好用的工具库ddddocr,该库也是基于了cv2库进行的封装和实现,操作起来更便捷
#求偏移量
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
with open('f1.png', 'rb') as f:
target_bytes = f.read()
with open('f2.png', 'rb') as f:
background_bytes = f.read()
拿到偏移量之后,我们就要想办法知道它进行了怎样的操作,这里小编选择的是观察网站数据接口的调用堆栈,进入到onSuccess中,在相应位置打上断点,并翻页重新进行验证码校验,此时,在断点位置停留,显示如图信息
这里我们就会清楚的看到,数据接口请求的code参数就是e.value。那么,我们只需要找到e的生成逻辑就能模拟code参数进行网站请求了。这里请跟着小编逐级往上跟栈,直至找到如图可疑栈点
想必大家就知道了这个value就是e.value的值了,我们跟进d方法,如图
原来value即code的值就是由nonceStr和 t 进行了AES加密。那么我们再去找 t 是什么意思,网上看代码,发现 t 就是滑块的偏移量,正好前边我们已经拿到了偏移量,就可以直接拿来用作 t 的值就行了
那么,现在的所有逻辑都捋清楚了,我们就可以来进行复现了。我们将背景图和code两个加密进行模拟
const CryptoJS = require("crypto-js")
d = function(e, t) {
var a = CryptoJS.enc.Utf8.parse(t)
, i = CryptoJS.enc.Utf8.parse(e);
return CryptoJS.AES.encrypt(i, a, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).toString()
};
u = function(e, t) {
var a = CryptoJS.enc.Utf8.parse(t)
, i = CryptoJS.AES.decrypt(e, a, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return CryptoJS.enc.Utf8.stringify(i).toString()
};
function get_code(t, nonceStr){
var code = d(t, nonceStr);
return code
}
function get_bj_img(canvas, nonceStr){
var bj_img = u(canvas, nonceStr);
return bj_img
}
得到code 值之后,那我们就可以正常进行网站请求了,数据也就能正常获取了,如图
那么,今日的分享就到这里,想要学习更多的python爬虫和js逆向的相关技巧和知识的小伙伴们一定要点下关注哟,后期会不定时分享相关干货内容