
本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号【K哥爬虫】联系作者立即删除!
前言继上次粉丝提问,K哥出了对应站点的分析文章之后,又有不少小伙伴提出了在逆向一些网站的时候碰到的问题,态度都很友好,K哥会尽力满足粉丝需求,不过只能一个个慢慢来,本文先对其中一个进行逆向分析:

目标:某芯商城,逆向分析
网页:aHR0cHM6Ly9zZWFyY2guaWNrZXkuY24vP2tleXdvcmQ9RVJKVTAzRjEwMDJW
逆向过程抓包分析打开开发者人员工具,随便搜索一个型号的芯片,在Network中即会抓包到相应的数据接口,即/search/ajax-get-res-v001:

请求参数如下,keyword大概率就是加密的搜索内容,v_是固定值,font_ident、p、_csrf都会动态变化,需要逐个研究分析:

该网站存在风控,会弹出极验四代语序点选的验证码,这里就不赘述了,感兴趣的可以阅读K哥往期文章【验证码逆向专栏】极验三代、四代点选类验证码逆向分析:

该接口是XHR(XMLHttpRequest)类型的请求,可以直接下个XHR断点,这样定位到的位置通常在加密处理完成之后,已经准备发送请求了,优点是便于踪栈,更容易找到加密的地方。在开发者人员工具Source面板右侧的XHR/fetchBreakpoints中添加截取的接口URL:

刷新网页即会断住:

向上跟栈到ajax中,于s处打下断点,F8下步断点,断过来,可以看到,此时keyword参数的值是明文,也就是搜索的芯片型号:

接下来就需要找一下这段明文是在哪被加密的,向上跟栈到中,很明显,该js经过了OB混淆(Obfuscator),感兴趣的可以使用AST技术解一下,关键的加密逻辑大概率就藏在这里面。跟到下图处,出现了几个接口所需的请求参数,这里的keyword仍是明文状态:

直接在中ctrl+f搜索keyword,总共有23个结果,不多,逐个分析下,在可能是加密算法的位置打断点分析,ERJU03F1002V在下图处被加密成了RVJKVTAzRjEwMDJW:

跟进到_0x7f9865[_0xfe4009(0x82c)]函数中,直接把算法扣下来:
functionorOperator(_0x1e4532,_0x39fc6b){return_0x1e4532|_0x39fc6b;}functionandOperator(_0x241af9,_0x10df1e){return_0x241af9_0x10df1e;}functionlessCompare(_0x58aa60,_0x251729){return_0x58aa60_0x251729;}functionRightShiftOperator(_0x50cbd4,_0x2a3840){return_0x50cbd4_0x2a3840;}functionaddOperator(_0xea955f,_0x17d167){return_0xea955f+_0x17d167;}functionutf8Encode(_0xe407f5){_0xe407f5=_0xe407f5["replace"](/\r\n/g,'\x0a');for(var_0xeefa10='',_0x4fcfd7=0x0;_0x4fcfd7_0xe407f5["length"];_0x4fcfd7++){var_0x1451bf=_0xe407f5["charCodeAt"](_0x4fcfd7);lessCompare(_0x1451bf,0x80)?_0xeefa10+=String["fromCharCode"](_0x1451bf):_0x1451bf0x7f_0x1451bf0x800?(_0xeefa10+=String["fromCharCode"](_0x1451bf0x6|0xc0),_0xeefa10+=String["fromCharCode"](orOperator(0x3f_0x1451bf,0x80))):(_0xeefa10+=String["fromCharCode"](orOperator(_0x1451bf0xc,0xe0)),_0xeefa10+=String["fromCharCode"](_0x1451bf0x60x3f|0x80),_0xeefa10+=String["fromCharCode"](0x3f_0x1451bf|0x80));}return_0xeefa10;}functionencryptKeyword(_0x3a29c2){letkeyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";let_0x40e006,_0x2e7dee,_0x2f707d,_0x70f89f,_0x1d4342,_0x55ace3,_0xee897c,_0x482490='',_0x4326f6=0x0;for(_0x3a29c2=utf8Encode(_0x3a29c2);_0x4326f6_0x3a29c2["length"];)_0x40e006=_0x3a29c2["charCodeAt"](_0x4326f6++),_0x2e7dee=_0x3a29c2["charCodeAt"](_0x4326f6++),_0x2f707d=_0x3a29c2["charCodeAt"](_0x4326f6++),_0x70f89f=_0x40e0060x2,_0x1d4342=(0x3_0x40e006)0x4|RightShiftOperator(_0x2e7dee,0x4),_0x55ace3=(0xf_0x2e7dee)0x2|_0x2f707d0x6,_0xee897c=andOperator(0x3f,_0x2f707d),isNaN(_0x2e7dee)?_0x55ace3=_0xee897c=0x40:isNaN(_0x2f707d)(_0xee897c=0x40),_0x482490=addOperator(addOperator(_0x482490,(_0x70f89f))+(_0x1d4342),(_0x55ace3))+(_0xee897c);return_0x482490;}letsearchKeyWord="ERJU03F1002V";letsearchKeyWordEncryptResult=encryptKeyword(searchKeyWord);(searchKeyWordEncryptResult);//RVJKVTAzRjEwMDJW我们来分析下这是什么算法,倒着看,_0x70f89f、_0x1d4342之类的是一些十进制数,(_0x70f89f)就是获取keyStr字符串特定位置的字符值,最后拼接起来:
_0x482490=addOperator(addOperator(_0x482490,(_0x70f89f))+(_0x1d4342),(_0x55ace3))+(_0xee897c);
keyStr就是源码中的this["_keyStr"],其值如下,长度为65位:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
这一串完全符合Base64编码索引表的特征,包含大写字母(A-Z)、小写字母(a-z)、数字(0-9)、加号(+)和斜杠(/),64位,还有一个填充字符(=),Base64编码的基本流程如下,例如编码Hello字符串:
首先,将Hello转换为ASCII码,得到72101108108111;
然后,每三个字节一组(数据块,不足三个则在末尾填充零),得到72101108和1081110;
每组的三个ASCII码,分别转为八位二进制数,不足的在前面补0,比如72101108得到010010000110010101101100,首尾相连,形成24位的二进制数;
将24位的二进制数,拆分为四个6位的小组;
将每组二进制数转换为十进制,并从Base64索引表中查找对应的字符;
使用填充字符"="添加到编码结果的末尾,以保证编码结果的长度为4的倍数。
ASCII码表和Base64索引表可于公众号回复关键词ascii或base64获取,Base64编码图解:

其实该数据接口对于Base64编码也有所提示乛◡乛:

可以去K哥爬虫工具站验证一下,结果一致:

至此keyword参数就分析完成了。
v参数前文提到几个加密参数都在一块,如下图所示,断住后观察一下,v为_0x501622,定义在上面几行,就是13位时间戳:
_0x501622=JSON["stringify"](newDate()["getTime"]());

font_ident直接从this中取到,其值不是通过加密算法生成的,在该网页的源代码中,可以直接使用xpath或者正则表达式匹配出来:

p参数值长度为32位,看着很像是MD5加密,我们来跟一下,p参数在下图处生成:

跟到_0x101cba[_0xfe4009(0x412)函数中去,p参数的值就是window['x']:

直接hook一下window中的x参数,断住后跟栈分析,使用Fiddler或者油猴之类的都可以,hook脚本如下:
(function(){'usestrict';(window,'x',{get:function(){debugger;return"";},set:function(value){debugger;returnvalue;},});})();刷新网页,成功断住,此时window['x']的值已经生成了:

向上跟栈到VM中,可以看到=hex_md5('xxx'),这里像是MD5加密的源码:

我们直接拿加密内容去爬虫工具站测试一下,发现值并不一样,这里的MD5算法可能经过了魔改:

先直接将整段代码扣下来,保存到本地,简单改改能直接运行:

来看看传入的17104110xxx是什么,接着向上跟栈到下图处,这里的逻辑就很有意思了,_0x4c3be9就是MD5加密的参数:
eval(_0x24f5ec["decode"](_0x2b037f)["replace"]("mwqqppz","'"+_0x4c3be9+"'"));
跟进到_0x24f5ec["decode"]函数中分析一下,取消hook,断进去,_0xc8f1ce就是_0x2b037f,是一个固定的字符串,这里的算法逻辑是不是很眼熟,和keyword参数一样,是base64,不过这里是解码的过程,将一大串字符串还原成了刚刚的MD5算法,用replace方法替换mwqqppz字符串传入待加密值,最后使用eval方法执行解码出的JavaScript代码,实现加密操作:

接着跟栈分析17104110xxx,跟到handleParamsV1中去,加密参数就是由p1、p2_、code三个参数拼接而成的:

往后跟下栈就会发现,p1参数是个时间戳,其值和前文所讲的v参数的值相同,p2_就是搜索的芯片型号经过base64编码后得到的值,code定义如下:
tmp=$.md5(p1+p2_),code=eval(+'("'+tmp+'")');与前面的不同,$.md5使用的是标准的MD5加密算法:

的值会变化,其值需要从该页面的源代码中获取:

生成code同样使用到了eval方法,逻辑就是将tmp参数值传到了函数中,生成了最终的code值,较为别致,跟进到这个函数中去:

跳转到79baf82e5b7315e32957b68b5b3d0260文件中,这个文件名是会动态变化的,每次刷新页面都不一样,同样可以从网页源代码中提取出来,完整链接:

就是套了两个switch,做了些运算,不同文件4|1|2|3|6|5|0的顺序会变,但算法的执行顺序其实是固定的,唯一会变的值就是_0x5b2c03['lQMEJ'],先将函数部分扣下来:

JavaScript代码:
functionxb9397d46e271a79d37e14478d0bbd99d(_0x3589bd){var_0x5b2c03={'NMqMe':function(_0xf40245,_0x5f3db1){return_0xf40245_0x5f3db1;},'dutuH':function(_0x305515,_0x16b9ff){return_0x305515%_0x16b9ff;},'FgcEp':function(_0x4f1496,_0x4a009b){return_0x4f1496/_0x4a009b;},'Krfyp':function(_0x5e7e97,_0x3a2b65){return_0x5e7e97-_0x3a2b65;},'cuUNs':function(_0x482dab,_0x2d4aa7){return_0x482dab/_0x2d4aa7;},'KYiBU':function(_0x63165e,_0x35b40d){return_0x63165e+_0x35b40d;},'vAfft':function(_0x59664e,_0x587b82){return_0x59664e+_0x587b82;},'lQMEJ':"abcd"},_0x34838f="4|1|2|3|6|5|0"["split"]('|'),_0xdf0619=0x0;while(!![]){switch(_0x34838f[_0xdf0619++]){case'0':return_0x27369a;case'1':var_0x5c31de="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";continue;case'2':var_0x5e9e9b=36;continue;case'3':var_0x7c3dbb=['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];continue;case'4':var_0x27369a='';continue;case'5':for(var_0xb3aee8=0x0;_0x5b2c03['NMqMe'](_0xb3aee8,32);_0xb3aee8++){var_0x34f9cc="4|0|5|2|3|1|6"["split"]('|'),_0x1ff8ce=0x0;while(!![]){switch(_0x34f9cc[_0x1ff8ce++]){case'0':_0x1da465=_0x5b2c03["dutuH"](_0x3b7479,_0x5e9e9b);continue;case'1':_0x3a7eff=_0x5b2c03["dutuH"](_0x3b7479,_0x5e9e9b);continue;case'2':_0x38b5d0=_0x5b2c03["dutuH"](_0x3b7479,_0x5e9e9b);continue;case'3':_0x3b7479=_0x5b2c03["FgcEp"](_0x5b2c03["Krfyp"](_0x3b7479,_0x38b5d0),_0x5e9e9b);continue;case'4':_0x3b7479=_0x3589bd["charCodeAt"](_0xb3aee8);continue;case'5':_0x3b7479=_0x5b2c03["cuUNs"](_0x5b2c03["Krfyp"](_0x3b7479,_0x1da465),_0x5e9e9b);continue;case'6':_0x27369a+=_0x5b2c03["KYiBU"](_0x5b2c03["KYiBU"](_0x5b2c03["vAfft"](_0x7c3dbb[_0x3a7eff],_0x7c3dbb[_0x38b5d0]),_0x7c3dbb[_0x1da465]),_0x5b2c03["lQMEJ"]);continue;}break;}}continue;case'6':var_0x3b7479,_0x1da465,_0x38b5d0,_0x3a7eff;continue;}break;}}(xb9397d46e271a79d37e14478d0bbd99d('9b6ed790af9bae4b109a79870590af51'));Python复现:
defget_md5_encrypt_str(_0x3589bd):dynamic_parameter='abcd'_0x27369a=''_0x5e9e9b=36_0x7c3dbb=['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']_0x3b7479,_0x1da465,_0x38b5d0,_0x3a7eff=0,0,0,0for_0xb3aee8inrange(len(_0x3589bd)):_0x3b7479=ord(_0x3589bd[_0xb3aee8])_0x1da465=_0x3b7479%_0x5e9e9b_0x3b7479=int((_0x3b7479-_0x1da465)/_0x5e9e9b)_0x38b5d0=_0x3b7479%_0x5e9e9b_0x3b7479=int((_0x3b7479-_0x38b5d0)/_0x5e9e9b)_0x3a7eff=_0x3b7479%_0x5e9e9b_0x27369a+=_0x7c3dbb[_0x3a7eff]+_0x7c3dbb[_0x38b5d0]+_0x7c3dbb[_0x1da465]+dynamic_parameterreturn_0x27369aprint(get_md5_encrypt_str('9b6ed790af9bae4b109a79870590af51'))前文提到,下图的这个值是会改变的:

我们来分析一下,这个值为什么会变,跟进到_0x2a0d2b函数中去,这里都是通过传一个整数和一个字符串,_0x2c3e()就是个大数组,会变化,从数组中按索引取值然后计算得到最终的参数值,0x1c2位置的值也并非固定的,数组和这个值都需要匹配出来:

_0x7ebea5(大数组)以及一些值需要动态提取,这段代码简化后如下:
function_0x1497(_0x187038,_0x57dea3){_0x7ebea5=["w3RcVeZcUG","WPruWOZcQgu","W741WO7cGCkw","WOSBzhPY","W78+WRNdM8oKuHpcImorWOOgWOa","zmkojCkPja","xCk4WRVcRce","F0iPWR3cImkXAYRdV1pdKLC","BvFdP2ldOW","s8oSubiw","WOD/W67cJSku","WRJdNf1hW6tcNSoQ","W5eaW414W5GRWPFdMG","W4/dNtFcL8k/vCk6W5iaWRj8qG","m8okEd9L","WQ8SW6CsW6a","CCk5W7xcVtO","W7xdNLjHW5K","imohcmkieq","cmk7W49TEq","WPvDCSoZW6u","ChldUh4S","WOVcS3tcKMi","kf8Gdai","mfjGWOFdNIe","W6pcUqZdVmknW44","k0vKWPm","WQumW6ioW5a","WOVcP8o3W5hdQ8oeEb4","W7G+WPpcQSkD","WQ1+W7/cUHnO","DSklWQFdUM0","WR4dE8kD","qCozWPNcVCoY","wmoQDSorWRK","cSo/FqTr","t8kqmSkIkG","lxu9aXS","EutcHmkGjW","WOaCyKXC","FmkEWOdcSXO","aCoEomk5na","W7lcVJ/cHCo8queWWOe","Bd8oC8oc","FCk6WQFcPHqf","WQjuW5/cVmkg","CNxdI8kXW6RcSW","tvOZiu16W4VcVSouW4OgWPtcN8owpG","lbFcUtJcUxLnW6OSW5rcWO7cTxNdQW","W77dKg1iW4C","WPn9WOtcK2m","WPrKWRdcNre","c8oyW6xdK8kY","awS/gZW","W6hcVrtdSSkEW4FdNg7dJW","W7u/WRNdLCoKwWNcG8o1WOWmWRy","CgxdN04+W5i","WPSFBgTubGVdTSoXW4u","qCkpW7rKWOPnWOm","DSouzZal","WPqeALT9","WQ5vW6TmW5u","WPnAuSozzeDjpbdcLmoD","FrG8q8oSW6FdKtddGSku","WQ1TWOFcGb8","W6dcLsFdSmks","W4hcIHRdUmk4","lCozp8ozW4jZnSk8W5XQlCk7bW","W7BdVJlcG8o+q0OSWQZcVmoeW69fWQLbWOTAW6i9WPRdK3BcKGv+qSonjq/dJtrLdmoGov3cVrpdTdr9EZq8DSk3fSotfqdcOW3cS8kLcvK9CsHNW6mlydGxWRxdRmoSwCoHWPbvW5OeWRFdQcqUW4/cVcxcI8kUDmofW43cJ10NdCovrbJcKWxdO8kWn8owWQ0nW6ZcHXeiWQ8wWP7cMSkbW6hcISo7W44PW78lWOymifNdKCoOnCkAzaWnhMq","dmkEW7LSBG","ACk7WPpcIHi","WQNcVmkDwmoh","FIijWRbh","wCoaWPNcLSos","W7uBWPLCW7y","WR5LWOVcQgJcQK/dKrnd","gmoXhmkmjmk8wG","bcDOcgq","BKFdQCkqW5G","W5zuWQZcS2u6omkzWQFcSSocoq","aCozW7VdV8kH","WRnrumoZW7rAW65D","DKZcI8kyhq","WRrJWO7cV1pcIK0","WQtcHuNdLSoD","jCobqWHP","DWmTw8oc","WRdcJeBdVCoD","WPHmWOtcLfS","WQyCW5ykW7e","WPfhWPpcNL0","WPtcNwBdGq","tfXIFdq5WQZdQG","W60mfsLR","vSkAWPtdH0NcVW","xghdVCkrW6K","W65fl8onW5dcGCo2iXDbWQ00","tCorAWhcMxdcTSkuWPDtiCkiW7aSeSkdWRVcK8k/W7JcV8oJyxW2W5ldMNuFu8o0WP5nWRy0AG","sv9SzGa+WRVdPq","WRdcJwZdLSo1","W6ZcLH/cTmoB","WQLFWQhcLZq","zSoRxW","wCoJW7JdHmk6W4fm","WRPcrmoJyq","bmkOW75tDG","jmk6bvLNWQBdPSorWQRdPCoLWQi","WQdcMLxcO2m","oCkWW5fIWPq","WRmivSkXWQu","WPrdW6VcQCkx","W58QpYm","W5SvWQHAW4m","W5bFjtC8qetcUSkBWPGKka","cmoRrIin","w8ouWORcU8od","gwjUWPtdKG","tmooWP7cG8oCWPxcL8kMEmkkWO/dN8kuCf/cPdRdNSkJW4hdSqC3WQ3dPaPnWQXctLFdSmkbW7veW6ddUs4","W7ZdPwH5W64","W6vdkSolW5ZcH8oFhYH5WR4b","iSoCW4FdOCkd","uCk1W43cKX0","WQdcPh3cGe0","CKldPwZdOYe","s8omrI4g","zSkoWR3dTfi","W6WnprXmW74SeSoBb8okWRP9CmkAW5L+WOVcMmktW4bzW5vwW4bDWQ7dJdq","WQ94WOJcVgG","eW9VDrCI","nCkshMRdMG","fSkOW6jwEW","aJH8W6ldVq","zwJcSGVcVqFcR3FcIG","WRCbBSkxWP0","WRf9W4pcOCkv","t0JcMCkAdgZcPG","WQuuF8kjWOFdMq","u8k+WPJcNCoRWPLQnd5CdCoC","WPXquSonzf0","WRtcPNldVSo2","W7q/WR3dN8oQuaRcSCoWWQCnWPu","cXJcHmkcdNVcH8kp","W6BdRcRdJtlcMGNdNc9IWP/dKq","WO9ZWQFcGcaKs2y","zCktWOFcJra","WQfpW6VdOmoEWOS4CWRdPx/dNq","CHuZvSoBW6a","D1BdKSkfW78","WPXFWRNcRMu","aCoeW7ZdS8kI","zLpdL1iq","hNulWO1O","WQD4W4P/W44","WQubCSksWPa","WQD/W53cOCki","FSk6WP7cGYi","d8odsbjR","W7KAWRtcV8ktW5m","fCkQkeldVW","bSkuW5rRWOW","WPdcP8kkr8oi","WReKwN1K","WPu5z8kDWO0","s8oEWQtcGCo4WQtcG8kGsCoFWONdLG","ecjpxs0","b2mWWO9l","F1FdU2FdRG","WQxdSwnKW4S","omoxoCkdiW","haD8W4ldLSogtqZdSLBdGeFdRCkMCIywW6OMlmoVW7zAW7OzWOpcKSkEWPVcSq7dNCkZptP2qW1JAsfPW4VdPHbiq20vW6tdUhhcM0BcTqtdH8kfW4S5WORcHmoqW4BdHM5NvCkSW5VdJCowW6fqWQBdK13cHZ0HnapdJmkRWPtdQSkaWQbGpCoxkSkJW6dcVa","WPu5t8k0WOS","wCoEAraG","smonWO3cVCow","kxqHpG0","WPZcTSkpvSot","WQT/WQtcVN0","tw7cQw3cIG","W5JcTHFdLmk8","W5m0W5ZdMNLKdIGZW6CjyW","W7ZcJ2PEW5/cKmoefW","WPbXWQ7cUbS","jcjonwe","xKlcH8kfgx3cTSkzWPDcWRG","c2ldSxJdJrKjE8kBWP5h","WQTrymoMW7jAW69u","tvS1ivv4WOZdMmkIWPPVWQu","WQZdJeniW7hcLmoGdG","aSo8W43dJa","W4BcJZxdV8kk","w1FcGXRcQG","D8oaymocWOjN","WQP3W7JcH8kM","WRhcI0NdHCoI","DmkfW5JcVay","lcTKqrm","EmonB8oxWRvGymkLWQ1I","mmo5vZWZ","tSkNWRtdHfm","F8oVWP7cJ8oD","W5xcIc3dT8kS","tCkwWQtdUfm","f8kBW6XaWQi","wSoCxISb","wSkQbNDmWPbUW6ibbxHX","uxVcKKBcVa","WQ1iW4FcR8k7","WRddVg9fW5i","wCodWPJcMmojWQxcJmk1","W6BcSGBdVSkbW6NdJG","vYK7q8oH","vCkbW6NcNW","y8kyWQhdOf8","W4W6WO3cVmkX","uCogsay4","f8kuW5XcWOe","WQX4r8otW4C"];if(_0x1870380x1c2){_0x187038=_0x187038-0x1c2;}var_0x979086=_0x7ebea5[_0x187038];var_0x18815a=function(_0x12f3cc){var_0x4baee4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var_0x34cff1='',_0x32f5a8='',_0x5720b1=_0x34cff1+_0x18815a;for(var_0x5baceb=0x0,_0x464e32,_0x444df3,_0x286151=0x0;_0x444df3=_0x12f3cc['charAt'](_0x286151++);~_0x444df3(_0x464e32=_0x5baceb%0x4?_0x464e32*0x40+_0x444df3:_0x444df3,_0x5baceb++%0x4)?_0x34cff1+=_0x5720b1['charCodeAt'](_0x286151+0xa)-0xa!==0x0?String['fromCharCode'](0xff_0x464e32(-0x2*_0x5baceb0x6)):_0x5baceb:0x0){_0x444df3=_0x4baee4['indexOf'](_0x444df3);}for(var_0x2093c7=0x0,_0x3586f3=_0x34cff1['length'];_0x2093c7_0x3586f3;_0x2093c7++){_0x32f5a8+='%'+('00'+_0x34cff1['charCodeAt'](_0x2093c7)['toString'](0x10))['slice'](-0x2);}returndecodeURIComponent(_0x32f5a8);};var_0x39e653=function(_0x218a50,_0x1ead99){var_0x4ec5dd=[],_0x568ad6=0x0,_0x4d9de0,_0x4a61ba='';_0x218a50=_0x18815a(_0x218a50);var_0x590931;for(_0x590931=0x0;_0x5909310x100;_0x590931++){_0x4ec5dd[_0x590931]=_0x590931;}for(_0x590931=0x0;_0x5909310x100;_0x590931++){_0x568ad6=(_0x568ad6+_0x4ec5dd[_0x590931]+_0x1ead99['charCodeAt'](_0x590931%_0x1ead99['length']))%0x100,_0x4d9de0=_0x4ec5dd[_0x590931],_0x4ec5dd[_0x590931]=_0x4ec5dd[_0x568ad6],_0x4ec5dd[_0x568ad6]=_0x4d9de0;}_0x590931=0x0,_0x568ad6=0x0;for(var_0x2312e7=0x0;_0x2312e7_0x218a50['length'];_0x2312e7++){_0x590931=(_0x590931+0x1)%0x100,_0x568ad6=(_0x568ad6+_0x4ec5dd[_0x590931])%0x100,_0x4d9de0=_0x4ec5dd[_0x590931],_0x4ec5dd[_0x590931]=_0x4ec5dd[_0x568ad6],_0x4ec5dd[_0x568ad6]=_0x4d9de0,_0x4a61ba+=String['fromCharCode'](_0x218a50['charCodeAt'](_0x2312e7)^_0x4ec5dd[(_0x4ec5dd[_0x590931]+_0x4ec5dd[_0x568ad6])%0x100]);}return_0x4a61ba;};var_0x55e8a2=_0x7ebea5[0x0],_0x2a1bd8=_0x187038+_0x55e8a2;_0x979086=_0x39e653(_0x979086,_0x57dea3);return_0x979086;}(_0x1497(633,'Wc%L'));一般情况下,可以使用AST技术或者正则表达式,将上述动态变化的值匹配出来,然后传入到算法中,即可得到最终的结果:

跟到'_csrf':_0x66ec8(_0x506031(0x1e8)+'rf')[_0x370168(0x7a1)]()中分析一下就会发现,_csrf参数与font_ident参数一样,都是从网页源代码中获取到的:

至此,所有参数都分析完成了。
cookies中有个参数值seaut,如果该值或者加密参数不对,是无法获取到数据的(网页端的cookies可删除、修改参数值):
结果验证