python爬虫- js逆向解密之破解AES(CryptoJS)加密的反爬机制v2
前言
其实有关AES,之前发过一版的博客文章,python爬虫- js逆向解密之破解AES(CryptoJS)加密的反爬机制
而这次虽然也是AES,但是这次的变化有点大了。
这次的目标对象同样也是我的老朋友给我的,还是老规矩,地址我不会给出来的
打开网址,界面如下:
不要问我为什么码了这么多,主要涉及到了手机号哈,马赛克必须马死
开始分析
首先,看XHR,用结果搜,没搜到
那行,接着看网站源码,用id为phonenum去整站搜索,然后找到以下几段代码块:
代码:
第一段:
key: "showEncryptPhone", value: function() { if (0 != $("#phonenum").length) { var e = getStoragePhone(); e ? ($("#phonenum").val(mobileEncrypt(e)), $("#phonenum").attr("disabled", "true")) : $("#changePhoneBtn").hide() } } } ------------ 第二段: $("#app").on("input propertychange", "#phonenum", function(e) { d("#phonenum"); var t = e.target.value; setStoragePhone(t) })
首先,可能稍微懂一点点js代码的,应该都能大概猜到,真正的代码其实是第一段,为啥呢,你看第二段,propertychange,这明显是监听修改的啊,再看第一个showEncryptPhone,这就是显示加密了的手机号,那一定是第一段代码了。
给第一段的每行代码
刷新页面,一步一步走,走到getStoragePhone()时,跳到里这个函数里:
当我鼠标放到window.msgTargetPhone时,已经有结果了
那么关键点就在getStoragePhone这个函数里了,重新打断点到这个函数上,之前的断点删除了,刷新看,结果立马就有了结果,那么,关键点就在window.msgTargetPhone上了,我用msgTargetPhone搜索,得到以下3个结果:
同样的,看名字,第三个肯定不是了,这不就是上面的那个被我们排除的函数一个原理吗?这第三个是监听是否改变值的,如果改变值就进入,而目标的整个页面里,手机号时是访问后就会自动出现的,并不是改变值出现的。而再看第一个,initUserMobileCache,看名字啊,初始化手机号,直觉告诉我就是这里了,先进这个函数看看咋回事
我正准备进入initUserMobileCache一顿分析时,我那朋友发来消息问我咋样了,我说,你可别急啊,我找到关键点了。
给这个函数打上断点:
刷新页面,一步一步往下走,直接走到下面这个函数,而且,这个e的参数看的太眼熟了,一看就是最开始的XHR请求得到的,这里我马死,就不展示了,这个s(e)走完之后就,手机号就出现了,那么,这么说,这个s(e)才是真正的关键点了
代码:
function s(e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : g;
if (!e)
return "";
var n = p(e, t, {
iv: f
});
return n.toString(CryptoJS.enc.Utf8)
}
找到关键点
再回到上级看下,就是AESDecrypt这个函数跳转过去的,看到这个函数名AESDecrypt,那么不用多说了,用的就是AES加密了
接着我另开一个标签页,然后试试这个s函数能不能直接调用:
结果就报了个g没有定义,这个g,就烦了,不能搜了,为啥呢,这个太大众化了,根本不好搜索它在哪,不信你看:
你不会说这几百个一个一个看吧,那得整到啥时候去了,此时,应该怎么办呢,看源码,但是得有章法的看,看下面这一纵列的函数定义,这些都应该在一个函数作用域里,那就看上下文这个自执行函数【!function(e){】的作用域里有没有定义过【g】
往下翻没几行就看到了下面这个,这里不就是定义了g吗,不止g,还有p也定义了
抠出核心代码
那么,我们就可以稍微改下s函数的源码:
function s(e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : CryptoJS.enc.Utf8.parse('e5b40d286cxfca34');
if (!e)
return "";
var n = CryptoJS.AES.decrypt(e, t, {
iv: CryptoJS.enc.Utf8.parse('Con-ere-ceD-cumt')
});
return n.toString(CryptoJS.enc.Utf8)
}
去控制台看下呢,我顺便改了下函数名cryp:
没引入CrpytoJS,在控制台引入下:
var script = document.createElement('script');
script.src = "http://cdn.staticfile.org/crypto-js/3.1.9-1/crypto-js.min.js";
document.getElementsByTagName('head')[0].appendChild(script);
或者你也可以直接把crpyto的源码赋值下来然后在控制台然后回车
现在再看,果然成功了
看来没毛病了,核心代码就是这个。
另外说下,我一开始是打算去扣cryptojs里的代码的,后面发现调用层级太多了,所以放弃了,直接引用整个crypto算了
用python实现
用crypto库实现
我之前的文章里,python爬虫- js逆向解密之破解AES(CryptoJS)加密的反爬机制 ,那套代码在这里没法用,所以,只能用下面的代码:
from Crypto.Cipher import AES
import base64
class AesCrypt():
def __init__(self, key, model, iv):
self.model = {'ECB': AES.MODE_ECB, 'CBC': AES.MODE_CBC}[model]
self.key = self.add_16(key)
self.iv = iv.encode()
if model == 'ECB':
self.aes = AES.new(self.key, self.model) # 创建aes对象
elif model == 'CBC':
self.aes = AES.new(self.key, self.model, self.iv) # 创建aes对象
def add_16(self, par):
# python3字符串是unicode编码,需要 encode才可以转换成字节型数据
par = par.encode('utf-8')
while len(par) % 16 != 0:
par += b'\x00'
return par
def aesdecrypt(self, text):
# CBC解密需要重新创建一个aes对象
if self.model == AES.MODE_CBC:
self.aes = AES.new(self.key, self.model, self.iv)
text = base64.decodebytes(text.encode('utf-8'))
self.decrypt_text = self.aes.decrypt(text)
return self.decrypt_text.decode('utf-8').strip('\0')
if __name__ == '__main__':
key = 'e5b40d286cxfca34'
iv = 'Con-ere-ceD-cumt'
word = 'xxxxxxx'
model = 'CBC'
pr = AesCrypt(key,model,iv)
print(pr.aesdecrypt(word))
执行,可行,结果能跟刚才控制台的结果对上:
用node.js实现
另外,不是说一定得python才能实现的,你也可以把crypto和这里抠出来的代码作为字符串,然后用execjs和js2py之类的库执行js,然后拿到结果,或者你还可以不用把crypto的源码拿出来,在你电脑上装上node.js,node里装上crypto,然后把js的环境设置到你本地的node环境也是可以的。
os.environ["NODE_PATH"] = "D:/xxzxx/node_modules"
还没完,找到刚才那个异步加载获得加密字段的xhr,发现这个平台的参数提交用的是payload类型:
没有键值对,也不是json,也不是类json,很强,这种的,我之前的文章里也说过,Python爬虫处理奇葩的请求参数payload,而这里的又完全不同的一种,不过方法是一样的,直接以字符串形式提交即可,看到了吗啊,里面的data的值直接就是一个字符串型即可
好,将两个对接上即可,完整的代码我就不给了,相信都走到这里了,各位朋友应该可以处理了。本次破解完毕
此时我将代码和结果甩给我那朋友,他发来三个字:【卧槽,稳】。我这个哥们儿一看到有新奇玩意儿就发给我让我搞,我其实挺感谢他的,能通过他一直保持学习是挺好的,而他也是技术出生,他做安全开发的,有很多东西我们都会交流,工作内容也有交集
结语
最近这几篇都是针对js的处理,也越来越觉得js是爬虫的大头,另外最近在某群里,有个老哥说他们公司招爬虫工程师,然后收到的简历上写的基本都是说会xpath处理,没有其他更多的技术呈现,那确实啊,很多人真的对爬虫的理解就是拿到数据,然后用正则或者bs4或者xpath就一顿操作,永远都写不完的表达式,不可能写一辈子的,想想你靠写xpath之类的,工资能提升吗?永远不可能的,还是要多学多用啊,涉及到的都要去了解,才能知道怎么逆向或者说怎么解析数据。就像我说的我这个朋友,他会时不时的给我一些网站让我去分析,为什么,是因为我之前很丧的时候就跟他说不想做开发了,他没有多说啥,而是时不时的给我点东西,让我找到点信心或者说乐趣,我才可以做到现在。