python携程爬虫之逆向混淆js

前言

那些年携程工程师在代码里下的毒-反爬与反反爬的奇技淫巧
知乎上面的专栏,写出了逆向找到携程的Eleven参数来伪装浏览器发送ajax,获取携程的酒店房型列表。然而文章并没有给出全部的思路,我们获取到的页面内容内容是酱紫的:

python携程爬虫之逆向混淆js_第1张图片

python携程爬虫之逆向混淆js_第2张图片
所以没办法,只能自己撸出来,看看到底是怎么加密的。

DEBUG

首先还是查看ajax请求网址时
http://hotels.ctrip.com/Domestic/tool/AjaxHote1RoomListForDetai1.aspx?psid=&MasterHotelID=441351&hotel=441351&EDM=F&roomId=&IncludeRoom=&city=2&showspothotel=T&supplier=&IsDecoupleSpotHotelAndGroup=F&contrast=0&brand=0&startDate=2017-08-28&depDate=2017-08-29&IsFlash=F&RequestTravelMoney=F&hsids=&IsJustConfirm=&contyped=0&priceInfo=-1&equip=&filter=&productcode=&couponList=&abForHuaZhu=&defaultLoad=T&TmFromList=F&eleven=c4350e460862b69d9d76724e1325a0a54ef23c2e0648636c855a329418018a85&callback=CASuBCgrghIfIUqemNE&_=1503884369495
的代码, 寻找他的调用栈。
python携程爬虫之逆向混淆js_第3张图片

$.ajax(o, {
    onsuccess: function(e) {
        window[n](e.responseText)//
    },
    onerror: function() {
        window[n] = void 0,
        r()
    }
}

而执行函数的时候传入的参数就是我们刚刚ajax得到的的json内容。我们打上断点后可以发现e.responseText为访问页面得到的json转化而成字符串。
python携程爬虫之逆向混淆js_第4张图片
window[n]方法就在上方

 window[n] = function(e) {
      window[n] = void 0;
      var i = ["T", "F", "e", "s", "M", "a", "g", "r", "o", "B", "u", "l", "y", "m", "f", "t"];
      e = $.parseJSON(e),
      null == e ? r() : (hotelDomesticConfig.cas.Pretty && e["0|2|3|15|4|2|3|3|5|6|2|1|7|8|13|9|10|15|15|2|7|14|11|12".split("|").map(function(e) {
          return i[e]
      }).join("")].slice(-9999).indexOf("  ") !== -1 ? e.html = "" : !l && hotelDomesticConfig.cas.decrypt && (e.html = t(e.ComplexHtml, e.ASYS, e.html)),
      s(e)),
      $('script[src="' + o + '"]').remove()
  }

我们在return i[e]$('script[src="' + o + '"]').remove()处打上断点。执行的时候直接跳过了return i[e],我们再看一下各变量的值。
python携程爬虫之逆向混淆js_第5张图片

e 原本为传入的e.responseText的值,既字符串,如今变成了一个对象,浏览一下他的属性。发现有一个html的属性,内容如下:

<div class="htl_room_table J_roomTable"><table border="0" cellspacing="0" cellpadding="0" summary="详情页酒店房型列表" id="J_RoomListTbl"><tr><th class="col1" style="padding-left:10px;">房型</th><th class="col2"></th><th class="col3">床型</th><th class="col5">宽带</th><th class="col_person">入住人数</th></i><p>没有符合条件的房型,您可以减少当前筛选项或<a id="J_ShowAllRoomList" href="javascript:void(0);">查看全部房型</a></p></td></script>

由于太长我没有吧全部代码放出来。可以看出,这里就是我们想要的结果。
于是我排查了window[n]里的每一个句子,找到了(e.html = t(e.ComplexHtml, e.ASYS, e.html),其中e.ComplexHtml以及e.ASYS就是ajax得到的两个奇形怪状的字段,
跳转到t函数。

 function t(e, t, o) {
     var i = "";
     if ("function" != typeof NODEJS)
         return "";
     if ("undefined" == typeof e)
         return "";
     if (!e)
         return "";
     try {
         i = NODEJS(e, t)
     } catch (n) {
         i = ""
     }
     return i
 }

return i 的时候,i已经是html的字符串了。所以我们可以判断就是在方法名为NODEJS之中完成的解密。

NODEJS = function(n, t) {
    var r, o, e = "1", i = void 0 == e[0], c = i ? [] : "";
    for (r = 0; r < n.length; r++)
        o = t.charAt(n.charAt(r).charCodeAt(0) - 21760).charAt(0),
        i ? c.push(o) : c += o;
    return c = i ? c.join("") : c
}

把上面的函数e.ComplexHtmle.ASYS丢到node中执行,结果出来的就是html的字符串。
撒花完结
##总结
写了个python版本的,丢:

def decrypt(n, t):
    c = ""
    for i in n:
        try:
            o = t[ord(i) - 21760]
        except:
            o = ""
        c = c + o
    return c

你可能感兴趣的:(python携程爬虫之逆向混淆js)