VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • 汽车之家配置页面 破解伪元素和混淆JS

本篇介绍如何破解汽车之家配置页面的伪元素和混淆的JS。 

 

** 温馨提示:如需转载本文,请注明内容出处。**

本文链接:https://www.cnblogs.com/grom/p/9242156.html 

(本文分多次编辑,可从原文章查看最新更新)

 

笔者爬取得网站中,印象最为深刻的就是汽车之家的网站了,也是麻烦最多的网站之一了,特点是页面大面积使用伪元素代替关键字,解析伪元素的JS进行了动态混淆,每次刷新后的JS都是不同的,页面被禁用右键菜单,无法选中或复制。

(因为破解了一周,怕分享出来后汽车之家就改了所以到现在运行了半年后才分享出来= =)

网站地址:http://car.autohome.com.cn/config/spec/25898.html

 

 

基本就是这样,如果单纯的抓取页面元素后会是这样:

 

 开始分析:

1.整个页面通过及配置数据都是直接Write出来的,因为配置项的详情在页面JS里同页面一起生成,并非通过接口。

2.配置项数据在页面上

 

(PS小妙招:将网页保存本地后发现文字依旧显示,然后大面积删除JS后刷新页面,如果文字依旧显示,继续删,直到找到加载数据的JS为止)

事后发现第一个变量keyLink是左边配置名称的超链接

第二个变量config是我们要的配置上半页(到车轮制动那),

第三个变量option是主/被动安全装备及以下,

第三四个变量color和innerColor是外观内饰颜色

 

 其他的没什么用,第五个可能是什么运动套装之类的,豪车才有,没仔细看。

3.解密JS在这里

这个JS是被混淆过的,不可以根据变量名去获取。

 

4.破解流程,拿到这个配置JSON串,然后找到解析JS,计算JS的变量得到字典集(一大串文字)和下标集(一大串数字集合)根据下标取字典里对应的文字,得到真正的数据字典,然后替换指定的伪元素。

5.解析被混淆的JS,格式化后可以得到这样的一串JS

 

提供一个完整的JS,有兴趣的小伙伴可以去研究研究

 替换伪元素的整个JS

 6.全文所有JS代码因为被混淆,可能会有差异,但结构一样,可仔细寻找。

 

开始解析:

如上图所示,里面有好多函数和变量,里面会返回一段文字或者符号,这些零零散散的文字将被组成一个完成数据字典库,

大致分为这几种:

  直接变量赋值的,如

 var mH_ = '例'

  通过函数为变量赋值的,值等于return后面的字符串,如

 var lI_ = function() {
     'return lI_';
     return '3;7';
 };

  函数,调用的时候获得值,值等于return后面的字符串,如

复制代码
  function hw_() {
      function _h() {
          return 'hw_';
      };
      if (_h() == 'hw__') {
          return _h();
      } else {
          return 're';
      }
  }
复制代码

(其实笔者想过使用.net直接运行JS,后来发现他们这个JS是有错误的,并且(……)(document)这种形式使用MSScriptControl.ScriptControl和JScript都无法识别,只能硬着头皮分析了。。。如果有能识别这种JS,求留言推荐,十分感谢。)

众所周知,函数是需要被调用才能运行的,那么入口呢,就很巧妙的隐藏在了这里 ↓

 var HH_ = $FillDicData$('iU_');

 接着会跳到这个函数

 

这个就是调用上面的那些大部分的变量组成字典集

 

紧接着下面的这个方法就是获取下标集合

 

这个方法实现根据坐标集取得字典 ,注意这个方法是不混淆的!可以直接搜索方法名找到。

 

"77,7"就是"环保" 通过这种方式替换页面的伪元素

 

分析到这里了,后面也就不难了,不再详细说明,如有不明白的,可以留言给我。

 

获取数据字典,模拟了刚才分析的JS

复制代码
  1   #region  获取汽车之家车辆信息
  2         /// <summary>
  3         /// 获取汽车之家车辆信息
  4         /// </summary>
  5         /// <param name="Parameter">参数(汽车之家ID或者Url)</param>
  6         /// <param name="Url">是否为Url</param>
  7         /// <param name="JsonKeyLink"></param>
  8         /// <param name="JsonConfig"></param>
  9         /// <param name="JsonOption"></param>
 10         /// <param name="JsonColor"></param>
 11         /// <param name="JsonInnerColor"></param>
 12         /// <param name="JsonBag"></param>
 13         /// <param name="ErrorMessage"></param>
 14         /// <returns></returns>
 15         public bool GetAutoHomeCarInfo(string Parameter, bool Url, ref string JsonKeyLink, ref string JsonConfig, ref string JsonOption, ref string JsonColor, ref string JsonInnerColor, ref string JsonBag, ref string ErrorMessage)
 16         {
 17             if (Url) return false;
 18             #region
 19             try
 20             {
 21                 //这里的变量是车型ID
 22                 string strUrl = Url ? Parameter : "http://car.autohome.com.cn/config/spec/" + Parameter + ".html";
 23                 HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(strUrl);
 24                 webrequest.AllowAutoRedirect = true;
 25                 webrequest.Timeout = 30000;
 26                 CookieContainer c = new CookieContainer();
 27                 webrequest.CookieContainer = c;
 28                 HttpWebResponse response = (HttpWebResponse)webrequest.GetResponse();
 29                 StreamReader read = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"));
 30                 string strAllHTML = read.ReadToEnd();
 31 
 32                 #region 获取数据字典
 33                 string[] KeyLink = null;
 34                 string[] Configpl = null;
 35                 string[] Optionpl = null;
 36                 GetAutoHomeDictionary(strAllHTML, ref KeyLink, ref Configpl, ref Optionpl);
 37                 #endregion
 38 
 39                 MatchCollection carInfoMatches = Regex.Matches(strAllHTML, "<script type=\"text/javascript\">((?:.|\\n)*?)</script>");
 40                 string strCarInfo = string.Empty;
 41                 for (int i = 0; i < carInfoMatches.Count; i++)
 42                 {
 43                     if (carInfoMatches[i].Result("$1").Trim().IndexOf("var option =") > 0) strCarInfo = carInfoMatches[i].Result("$1").Trim();
 44                 }
 45                 if (strCarInfo != string.Empty)
 46                 {
 47                     Hashtable htCarInfo = new Hashtable();
 48                     if (strCarInfo.IndexOf("var keyLink =") > -1) htCarInfo.Add(strCarInfo.IndexOf("var keyLink ="), "JsonKeyLink");
 49                     if (strCarInfo.IndexOf("var config =") > -1) htCarInfo.Add(strCarInfo.IndexOf("var config ="), "JsonConfig");
 50                     if (strCarInfo.IndexOf("var option =") > -1) htCarInfo.Add(strCarInfo.IndexOf("var option ="), "JsonOption");
 51                     if (strCarInfo.IndexOf("var color =") > -1) htCarInfo.Add(strCarInfo.IndexOf("var color ="), "JsonColor");
 52                     if (strCarInfo.IndexOf("var innerColor =") > -1) htCarInfo.Add(strCarInfo.IndexOf("var innerColor ="), "JsonInnerColor");
 53                     if (strCarInfo.IndexOf("var bag =") > -1) htCarInfo.Add(strCarInfo.IndexOf("var bag ="), "JsonBag");
 54                     ArrayList arrayList = new ArrayList(htCarInfo.Keys);
 55                     arrayList.Sort();
 56                     for (int i = 0; i < arrayList.Count; i++)
 57                     {
 58                         //有些没有的字典和解析JS要筛掉
 59                         string JsonTemp = string.Empty;
 60                         if (i == arrayList.Count - 1)
 61                         {
 62                             continue;
 63                             JsonTemp = strCarInfo.Substring(int.Parse(arrayList[i].ToString()), strCarInfo.Length - int.Parse(arrayList[i].ToString()));
 64                             JsonTemp = JsonTemp.Substring(0, JsonTemp.IndexOf("]}};")) + "]}};";
 65                         }
 66                         else
 67                         {
 68                             JsonTemp = strCarInfo.Substring(int.Parse(arrayList[i].ToString()), int.Parse(arrayList[i + 1].ToString()) - int.Parse(arrayList[i].ToString()));
 69                         }
 70                         //if (JsonTemp.IndexOf("_baikeVJ") > 0)
 71                         if (Regex.IsMatch(JsonTemp, @"<span class='hs_kw.*?_baike\w{0,2}'></span>"))
 72                         {
 73                             string tmp = JsonTemp.Substring(JsonTemp.IndexOf("_baike") , 8);
 74                             for (int j = 0; j < KeyLink.Length; j++)
 75                             {                            
 76                                 JsonTemp = JsonTemp.Replace("<span class='hs_kw" + j + tmp + "'></span>", KeyLink[j]);
 77                             }
 78                         }
 79                         if (Regex.IsMatch(JsonTemp, @"<span class='hs_kw.*?_config\w{0,2}'></span>"))
 80                         {
 81                             string tmp = JsonTemp.Substring(JsonTemp.IndexOf("_config"), 9);
 82                             for (int j = 0; j < Configpl.Length; j++)
 83                             {
 84                                 JsonTemp = JsonTemp.Replace("<span class='hs_kw" + j + tmp + "'></span>", Configpl[j]);
 85                             }
 86                         }
 87                         if (Regex.IsMatch(JsonTemp, @"<span class='hs_kw.*?_option\w{0,2}'></span>"))
 88                         {
 89                             string tmp = JsonTemp.Substring(JsonTemp.IndexOf("_option"), 9);
 90                             for (int j = 0; j < Optionpl.Length; j++)
 91                             {
 92                                 JsonTemp = JsonTemp.Replace("<span class='hs_kw" + j + tmp + "'></span>", Optionpl[j]);
 93                             }
 94                         }
 95                         switch (htCarInfo[arrayList[i]].ToString())
 96                         {
 97                             //这里只解析了左边配置栏和上下配置,其他可自行修改
 98                             case "JsonKeyLink":
 99                                 JsonTemp = JsonTemp.Replace("var keyLink =", string.Empty).Replace(";", string.Empty).Trim();
100                                 JsonKeyLink = JsonTemp;
101                                 break;
102                             case "JsonConfig":
103                                 JsonTemp = JsonTemp.Replace("var config =", string.Empty).Replace(";", string.Empty).Trim();
104                                 JsonConfig = JsonTemp;
105                                 break;
106                             case "JsonOption":
107                                 JsonTemp = JsonTemp.Replace("var option =", string.Empty).Replace(";", string.Empty).Trim();
108                                 JsonOption = JsonTemp;
109                                 break;
110                         }
111                     }
112                 }
113                 return true;
114             }
115             catch (Exception Ex)
116             {
117                 ErrorMessage = Ex.Message;
118                 return false;
119             }
120             #endregion
121         }
122         #endregion        
复制代码

 

破解数据字典,其实就是模拟我们上面分析的JS解析过程,其中用到大量的正则分别处理不同格式的数据集

复制代码
  1         /// <summary>
  2         /// 获取数据字典
  3         /// </summary>
  4         /// <param name="strAllHTML"></param>
  5         /// <param name="keyLink"></param>
  6         /// <param name="configpl"></param>
  7         /// <param name="optionpl"></param>
  8         public void GetAutoHomeDictionary(string strAllHTML, ref string[] keyLink, ref string[] configpl, ref string[] optionpl)
  9         {
 10             MatchCollection carInfoMatches = Regex.Matches(strAllHTML, "<script>((?:.|\\n)*?)</script>");
 11             List<string> matcheslist = new List<string>();
 12             foreach (var item in carInfoMatches)
 13             {
 14                 if (item.ToString().IndexOf("try{document.") < 0 && item.ToString().Length > 500)
 15                 {
 16                     matcheslist.Add(item.ToString());
 17                 }
 18             }
 19             for (int i = 0; i < matcheslist.Count; i++)
 20             {
 21                 #region 生成文字集1
 22                 Dictionary<string, string> dc = new Dictionary<string, string>();
 23                 MatchCollection matchlist = Regex.Matches(matcheslist[i].Replace("})(document);</script>", " function"), @"function\s(\S){0,2}_\(\)\s*\{.*?\}.*?(?=function)");//取出function              
 24                 for ( int j = 0; j < matchlist.Count; j++)
 25                 {
 26                     string str1 = string.Empty, str2 = string.Empty;
 27                     getStr(matchlist[j].Value, ref str1, ref str2);
 28                     dc.Add(str1, str2);
 29                 }
 30                 try
 31                 {
 32                     MatchCollection matchlist2 = Regex.Matches(matcheslist[i], @"var\s?\S\S_=\s?'\S*'");//取出赋值变量
 33                     for (int j = 0; j < matchlist2.Count; j++)
 34                     {
 35                         string str1 = string.Empty, str2 = string.Empty;
 36                         getStr2(matchlist2[j].Value, ref str1, ref str2);
 37                         dc.Add(str1, str2);
 38                     }
 39 
 40                     MatchCollection matchlist3 = Regex.Matches(matcheslist[i], @"var\s?\S\S_=\s?function\s?\(\)\s?\{.*?return.*?return.*?\}");//取出赋值函数
 41                     for (int j = 0; j < matchlist3.Count; j++)
 42                     {
 43                         string str1 = string.Empty, str2 = string.Empty;
 44                         getStr3(matchlist3[j].Value, ref str1, ref str2);
 45                         dc.Add(str1, str2);
 46                     }
 47                 }
 48                 catch (Exception ex)
 49                 {
 50                     throw ex;
 51                 }
 52                 StringBuilder sb = new StringBuilder();
 53                 string str = Regex.Match(matcheslist[i], @"function\s*\$FillDicData\$\s*\(\)\s*?{.*?\$RenderToHTML").Value;
 54                 string tmp2 = str.Substring(str.IndexOf("$GetWindow$()"), str.IndexOf("$rulePosList$") - str.IndexOf("$GetWindow$()"));
 55                 string tmp3 = tmp2.Substring(tmp2.IndexOf(']') + 1);
 56                 string[] tmp4 = tmp3.Split('+');
 57                 try
 58                 {
 59                     for (int j = 1; j < tmp4.Length - 1; j++)
 60                     {
 61                         //if (Regex.IsMatch(tmp4[j], @"[\u4e00-\u9fbb]{1,5}"))
 62                         //{
 63                         //    sb.Append(Regex.Match(tmp4[j], @"[\u4e00-\u9fbb]{1,5}").ToString());
 64                         //}
 65                         if (Regex.IsMatch(tmp4[j], @"\(function\s{0,3}\(\)\{.*?return.*?return.*?\}\)"))
 66                         {
 67                             var strtmp = Regex.Match(tmp4[j], @"\(function\s{0,3}\(\)\{.*?return.*?return.*?\}\)").Value;
 68                             var strtmp2 = Regex.Match(strtmp, "return.*?(.*?).*?return.*(.*?)").Value.Split(new string[] { "return" }, StringSplitOptions.RemoveEmptyEntries);
 69                             foreach (var item in strtmp2)
 70                             {
 71                                 if (item.Split('\'').Length == 3) sb.Append(item.Split('\'')[1].Replace("'", "").Trim());
 72                             }
 73                         }
 74                         else if (Regex.IsMatch(tmp4[j], @"\('([A-Z]|[a-z]|[0-9]|[,]|[']|[;]|[\u4e00-\u9fbb]){1,10}'\)"))
 75                         {
 76                             sb.Append(Regex.Match(tmp4[j], @"\('([A-Z]|[a-z]|[0-9]|[,]|[']|[;]|[\u4e00-\u9fbb]){1,10}(?='\))").ToString().Substring(2));
 77                         }
 78                         else if (Regex.IsMatch(tmp4[j], @"\(\)"))
 79                         {
 80                             sb.Append(dc[tmp4[j].Replace("()", "")]);
 81                         }
 82                         else if (Regex.IsMatch(tmp4[j], @"'([A-Z]|[a-z]|[0-9]|[,]|[']|[;]|[\u4e00-\u9fbb]){1,10}'(?!\))"))
 83                         {
 84                             sb.Append(Regex.Match(tmp4[j], @"'([A-Z]|[a-z]|[0-9]|[,]|[']|[;]|[\u4e00-\u9fbb]){1,10}'").ToString().Replace("'",""));
 85                         }
 86                         else if (Regex.IsMatch(tmp4[j], @"\S{3}"))
 87                         {
 88                             sb.Append(dc[tmp4[j]]);
 89                         }
 90                         else
 91                         {
 92                             sb.Append("X");
 93                         }
 94                     }
 95                 }
 96                 catch (Exception ex)
 97                 {
 98                     throw;
 99                 }
100                 #endregion                
101 
102                 #region 取下标
103                 string tmp11 = str.Substring(str.IndexOf("$rulePosList$"));
104                 string tmp12 = tmp11.Substring(0, tmp11.IndexOf("$SystemFunction2$"));
105                 StringBuilder sb2 = new StringBuilder();
106                 string[] tmp13 = tmp12.Split('+');
107                 try
108                 {
109                     tmp13[tmp13.Length - 1] = tmp13[tmp13.Length - 1].Replace("),", "");
110                     for (int j = 1; j < tmp13.Length; j++)
111                     {
112                         if (Regex.IsMatch(tmp13[j], @"\('([A-Z]|[a-z]|[0-9]|[,]|[']|[;]|[\u4e00-\u9fbb]){1,10}'\)"))
113                         {
114                             sb2.Append(Regex.Match(tmp13[j], @"\('([A-Z]|[a-z]|[0-9]|[,]|[']|[;]|[\u4e00-\u9fbb]){1,10}(?='\))").ToString().Substring(2));
115                         }
116                         else if (Regex.IsMatch(tmp13[j], @"return\s{0,2}'([0-9]|[,]|[;]){1,10}'