关注微信公众号:K爬虫小哥,继续分享高级爬虫、JS/Android逆向等技术干货!声明本文所有内容仅供学习交流。抓拍内容、敏感网址、数据接口均已脱敏处理,严禁用于商业或非法用途。否则,由此产生的一切后果与作者无关。Infringement,pleasecontactmetodeleteimmediately!逆向目标目标:EtherRock(一种数字货币)空投接口AES256加密分析主页:aHR0cHM6Ly9ldGhlcnJvY2submV0L2FpcmRyb3Av接口:aHR0cHM6Ly9ldGhlcnJvY2submV0L2FpcmRyb3Atc3VibWl0逆向参数:FormData:content:U2FsdGVkX1/XnffSPZONOHb...key:jrwBwX2ll38bu/FFql+bAUYrRG8Ij...逆向分析来进入空投页面,输入任意一个ETH钱包地址,点击提交,即可抓包到提交界面,POST请求,FormData中的内容和关键参数已经加密,如如下图:老方法,尝试直接搜索,结果很多,不利于快速定位,XHR断点,很容易定位到加密位置,如下图:一步步分析,先定义内容对象:varcontent={address:$(this).find('input[name=address]').val(),ref:$(this).find('input[name=ref]').val(),uuid:uuid,tz:tz,tz_offset:tz_offset,屏幕:window.screen.width+'x'+window.screen.height+'x'+window.screen.colorDepth,user_agent:navigator.userAgent,cpu:navigator.hardwareConcurrency,lang:navigator.language||navigator.userLanguage,};address为钱包地址,ref,uuid为空,tz为时区,tz_offset是时区偏移量,即当前时区与格林威治标准时间(GMT)的时差,screen是屏幕相关信息,user_agent是浏览器信息,cpu是处理器数量,lang是语言。这些值可以是固定的,地址除外。接下来定义了一个key:varkey=random_string(36);,接着random_string()方法,我们可以看到已经进行了一些随机值和求幂运算,可以直接复制,如图下图:然后定义内容和生成的密钥用AES256加密:content=AES256.encrypt(JSON.stringify(content),k??ey);这里的AES256一般指的是密钥长度为32字节(256位/8位)的AES加密,不过大家不要被名字搞糊涂了,我们跟进看看:可以看到h.AES.encrypt()方法其实是调用的,查一下这个h,可以看到它引用了node-cryptojs-aes,支持AES对称密钥加密,这里比较简单,我们也可以直接在本地导入这个库,至此内容加密方式有被发现。接下来看键值,就更简单了。很明显,jsencrypt库是用来对原来生成的36位字符串的key进行RSA加密的,本地也可以直接引用该库。完整代码GitHub关注K哥的爬虫,持续分享爬虫相关代码!欢迎加星!https://github.com/kgepachong/下面只是演示了部分关键代码,不能直接运行!完整代码仓库地址:https://github.com/kgepachong...JavaScript加密代码函数randomString(N){if(!parseInt(N,10))N=6;varrs=Math.floor(Math.pow(36,N)*Math.random()).toString(36);返回(Math.pow(10,N)+rs).substr(-N);}varh=require("node-cryptojs-aes").CryptoJS,p={stringify:function(b){vare=h.enc.Hex.parse(b.salt.toString()).toString(h.enc.Latin1);b=b.密文。toString(h.enc.Latin1);返回h.enc.Latin1.parse("Salted__"+e+b).toString(h.enc.Base64)},解析:function(b){b=h.enc.Base64.parse(b).toString(h.enc.Latin1);if("Salted__"!==b.substr(0,8))throwError("解析盐时出错");vare=b.substr(8,8);b=b.substr(16);返回h.lib.CipherParams.create({密文:h.enc.Latin1.parse(b),盐:h.enc.Latin1.parse(e)})}};vare=randomString(36);functiongetContent(address){varb=JSON.stringify({"address":address,"ref":"","uuid":"","tz":"Asia/Shanghai","tz_offset":8,"screen":"1920x1080x24","user_agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/94.0.4606.81Safari/537.36","cpu":8,"lang":"zh"})returnh.AES.encrypt(b,e,{format:p}).toString()}functiongetKey(){JSEncrypt=require("jsencrypt")varcrypt=newJSEncrypt();varpub=['-----BEGINPUBLICKEY-----','MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVmYQhCYTnnkTPRMI5Ad3vfad9','lhjzOU92FZ3reUiN/vmqP/wC1DKKExYDsqa+w5xBP0AjGkfDWk3q4PlWu0UsBGZx','62Gvt0ds75u8FnmLv+ufMimF4962/9Lx7uyh9g1H3/ze5ZXscWYy3gtts9d2Ga0R','pl0X49Cz0JhYYicuGwIDAQAB','-----结束公钥-----',];crypt.setPublic键(pub.join('\n'));密钥=crypt.encrypt(e);returnkey}functiongetContentAndKey(address){result={"key":getKey(),"content":getContent(address)}returnresult}//测试样例//console.log(getContentAndKey("xxxxxxxxxxxxxxxx"))Python代码#==================================#--*--编码:utf-8--*--#@Time:2021-11-24#@Author:微信公众号:K哥笨虫#@FileName:airdrop_submit.py#@Software:PyCharm#==================================importexecjsimportrequestsdefget_content_and_key(address):withopen("get_content_and_key.js",encoding="utf-8")asf:ether_rock_js=f.read()content_and_key_dict=execjs.compile(ether_rock_js).call('getContentAndKey',address)returncontent_and_key_dictdefairdrop_submit(content_and_key_dict):submit_url="脱敏处理,完整代码关注GitHub:https://github.com/kgepachong/crawler"headers={"Accept":"text/html,*/*;q=0.01","Accept-Language":"zh,zh-CN;q=0.9,en-US;q=0.8,en;q=0.7","User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/94.0.4606.81Safari/537.36","X-Requested-With":"XMLHttpRequest","Host":"脱敏处理,完整代码关注GitHub:https://github.com/kgepachong/crawler","Origin":"脱敏处理,完整代码关注GitHub:https://github.com/kgepachong/crawler",}data={"content":content_and_key_dict["content"],"key":content_and_key_dict["key"]}response=requests.post(url=submit_url,数据=data,headers=headers)print(response.text)defmain():address=input("请输入接收空投的ETH钱包地址:")content_and_key_dict=get_content_and_key(address)airdrop_submit(content_and_key_dict)if__name__=='__main__':主要()
