说明:仅供学习使用,请勿用于非法用途,若有侵权,请联系博主删除
作者:zhu6201976
一、 反爬分析
url1:aHR0cDovL3pmY2ouZ3ouZ292LmNuL3pmY2ovZnl4eC94a2I/c1Byb2plY3RJZD05MzBlMDQ0MmJjNjA0MTBkYTgzNzQ0MmQ5ZGRiN2UwMiZzUHJlU2VsbE5vPTIwMjQwMDA1
url2:aHR0cDovL3pmY2ouZ3ouZ292LmNuL3pmY2ovZnl4eC94bXhrYnh4Vmlldw==
浏览器访问url1得到销控表(楼栋列表),点击某一楼栋,下方展示房号列表:
但这一切只是在浏览器中发生的,中间所有的请求和过程,浏览器都帮我们完成了,我们感受不到中间到底发生了什么。真实情况是:我们访问url1,服务器只返回了上半部分内容,而下半部分房号列表信息是缺失的,需要我们POST请求url2,传递project_id、building_id、token等关键参数,才能拿到。然而,token参数是这样的:
到这里,我们可以非常明显的看到,网站做了核心数据的反爬。如果不能解决token参数的生成逻辑,想要协议模拟根本无法实现。
想想也非常正常,对于这个房地产网站,数据量最大,最具核心价值的资源,就在于房号信息。网站一方面为了保护核心数据的安全,另一方面为了防止爬虫程序的滥用,对服务器造成巨大压力,必须对网站进行反爬处理。
效果或许也非常明显,一些初级爬虫,看到这么一大串令人头疼的加密字符,估计已经第一时间放弃抵抗:抬走!
那么,它是如何实现的呢?采用了什么样的加密算法?
1. 首先,我们观察token值的特征,初步判断可能采用了现代密码学:RSA/AES/DES等。
iBVW+duWe26lZzi6HVffsw/foveymgr/3kAS3d/2c3TAg/6l1EqnJIXyIsiINANVjrNKzAHgsR80XaTJu2QX96FrVCrNHdCEONr0Iy4qTWHQ5w+Ddptv37bY0PLpX/UYYAAfltxpcCjnxDYGudT9QWqJqfqw2mOuO6rz74/lw8o=@QuZYt/TaVypfEAl0omOoYDP/p8Jn3V5RGz6Bh95bzztU2mEKTqKRY2HfPwgz2pUF9BnPW0BL1vsdvPc+ZHMSgt488Zg++hpXH3r/NcE1J4EofuvI4Ii8JgvtY8oZuR2FSjfwZkLZiwo7YxvcGb+C4J+TqoAyUSRrt9BOnTmS8LQ=@NsXfjXtuNeJX3D51rcd61cmWpTAYISPzw+a4P394pZiXw4TAMFlMwanMdGVLHprXJrv/64D0MIF0qZ+6IvpC7JRWSMUVwRACDTyWTBEyjQmn1YouboOtOr87PV34GUSbe9tXxNlcSVBff7n/3S+ZCHt4t4IDp6tB32ko8r7B3zw=@RENxFEgkEOsQlXZvsvOT4tz0LVzqJq+SwpP0rgbpfWc6KHRN/kpzwTd4563PPhDIY6ASoDVJPdxSZiggCM9jGq+EiaR3d2ZUV5xA7fcjVOC3MkjYoWYKKBAc97LuJ/JGUqpdHMawN6HBthf+iVXmeeeFSxGUzmduRziGfPLZw/g=@RdxwEZPC1HK2X1SxIB8cOQJ7CNX0irA+e76cQYRFRCwg3/Zth/KM6T3gQRdjwNSQ6p5DjnWrLuywSWA1UuXe7m55PXiQDnWIcWP9O46wQfhW7YTeqy1WrIr8THQ+OkfNK2QDj/CRX0wiuZugV5sVrwicqX15/mJv+WeBggoQHow=@FnosIVqEz6WFYIWTPlg/1V+S+ImqiCmv79yfdiQ+J9STWjG1uClgWOP72jkysPD15KxUX5MQA/+fOrNvQxG5ZePg3PbLALB89KIaUkrhFVTySV+FDpmtW/3H1pGC3y8eqQtYbLzKH9pKAA8GaS1gtcMl9tHovz8l8VlYtY3xqMo=@cEtL7FF07gSN8OJUBrDUDlEoAHaRL5S7jxcR2MTD7LfTa1b71upYmTd+xX4UKJ2K0Dpq0IVbiYEK/5JfGbLZ1ioJFXYQytWsJnry1S/Qw5MJ7SjEvDoAcy3w39h+4XQiEh6tedfRWNBeXaqJd0pPNN5tQ1JFkX0EqO6rpIpyFrM=
2. 其次,观察url1的返回document,很明显绑定了点击事件。
当我们点击具体楼栋时,会触发对应绑定的DoSearch函数,并执行对应JS逻辑,发送POST请求url2,获取对应楼栋房号列表信息。
3. 最后,DoSearch函数具体实现在哪?如何快速定位?
在JS逆向中,快速定位很重要。Python之父Guido van Rossum 曾说过:人生苦短,我用Python。那么,我想请问:此处用Python,对我们快速定位有帮助吗?
怎么快怎么来吧,投机取巧一把,全搜搜索 DoSearch 关键词,如果代码没有混淆,肯定是能找到的。果然不出所料,非常轻易的追踪定位到了,上边ak是RSA公钥,说明果然是RSA加密,这也太简单了吧?
二、扣取代码,模拟执行
既然token加密函数DoSearch已定位,那么,我已经迫不及待想扣取代码执行看看效果了。废话不多说,直接完整扣取,放到NodeJS中尝试执行:
function DoSearch(ak, sProjectId, buildingId, houseFunctionId, unitType, houseStatusId, totalAreaId, inAreaId) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(ak);
var token = encrypt.encrypt(sProjectId) + "@" + encrypt.encrypt(buildingId) + "@" + encrypt.encrypt(houseFunctionId) + "@" + encrypt.encrypt(unitType) + "@" + encrypt.encrypt(houseStatusId) + "@" + encrypt.encrypt(totalAreaId) + "@" + encrypt.encrypt(inAreaId);
return token;
}
var ak = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1nflpr8o4Jh74z0KPEIBSt+Q4+eCkz6LdyxGZESFgpiQcdIBbWXujhczBCpGO8n1Mo+purvzyxWJIM/I41wjY9JHQSKZF2FL0IfSP8d+V3knz9MA4QHiIzwtrQEpq5U2VmzvSrLsIcPILFPQLZHgaEdQkGVu0NGAzclsMxYmNSQIDAQAB';
var sProjectId = '930e0442bc60410da837442d9ddb7e02';
var buildingId = '63097ed0eb04496b8f9306fc408fe554';
var houseFunctionId = '0';
var unitType = '';
var houseStatusId = '0';
var totalAreaId = '0';
var inAreaId = '0';
var ret = DoSearch(ak, sProjectId, buildingId, houseFunctionId, unitType, houseStatusId, totalAreaId, inAreaId);
console.log(ret);
报错:ReferenceError: JSEncrypt is not defined
通过调试,发现JSEncrypt在文件jsencrypt.min.js中定义,行数大概2700,非常明显的RSA加密工具,直接扣取,再次尝试运行:
报错:ReferenceError: navigator is not defined
尝试补环境头:
var Navigator = function Navigator(){
}
Navigator.prototype.appName = 'Netscape';
var navigator = new Navigator();
再次运行:
报错:ReferenceError: window is not defined
尝试补环境头:
window = global;
成功出值!
PostMan测试生成的token是否可用,成功拿到正确结果:
三、 完整代码
项目已开源,请访问github获取,期待你的一键三连、star、交流。
github项目地址:https://github.com/zhu6201976/zfcj20240111
项目运行完整截图: