一、目标

目标网站:

http://60.173.254.126/

这算是一个列表页,展示了一些小区,然后单击小区跳转到小区详情,但是跳转链接被加密了,是通过JS算出来的:

合肥市房产市场信息平台跳转链接解密_github

本篇文章的目标就是破解这个加密。

 

二、分析

上一小节的图里可以看到,在单击链接的时候绑定了一个事件reurl,在开发者工具的console上输入reurl并回车:

合肥市房产市场信息平台跳转链接解密_python_02

拿到代码:

function reurl(a) {
    a.href = "/item/" + recode(a.id)
}

可以看到在这里修改了链接的地址,用到了链接里的一个id属性:

<a id="2714" style="cursor:pointer" onclick="reurl(this)" target="_blank" title="清樾园">清樾园</a>

同时id的解密还依赖了recode,同样的套路拿到它的代码:

function recode(a) {
    var n = nscaler(a);
    var c = SetObjNum(String(a).length);
    var d = SetObjNum(String(a).length);
    n = parseInt(n) + parseInt(d);
    var b = $("#iptstamp").val();
    b = nscaler(b.toString());
    return c + "-" + n + "-" + d + "-" + b
}

这个方法中依赖了两个方法和一个dom元素,先看nscaler,用同样的方法从console跟进去拿到它的代码:

function nscaler(a) {
    var b = "";
    var ar = String(a).split('');
    $.each(ar, function (i, e) {
        switch (e) {
            case "0":
                b += "0";
                break;
            case "1":
                b += "2";
                break;
            case "2":
                b += "5";
                break;
            case "3":
                b += "8";
                break;
            case "4":
                b += "6";
                break;
            case "5":
                b += "1";
                break;
            case "6":
                b += "3";
                break;
            case "7":
                b += "4";
                break;
            case "8":
                b += "9";
                break;
            case "9":
                b += "7";
                break
        }
    });
    return b
}

从逻辑上看,这个方法是将字符串使用一个映射表映射为一个新的值:

{
    0: 0,
    1: 2,
    2: 5,
    3: 8,
    4: 6,
    5: 1,
    6: 3,
    7: 4,
    8: 9,
    9: 7,
}

然后是SetObjNum,从console跟进去拿到源码,注意到跟进去的时候tab的标题是VMxxx格式的,说明可能是eval定义的:

function SetObjNum(n) {
    var a = "";
    for (var i = 0; i < n; i++) a += Math.floor(Math.random() * 10);
    return a
}

这个方法就是生成一个随机数,然后是$("#iptstamp").val();,在页面源代码:

view-source:http://60.173.254.126/

中搜索iptstamp可以找到,这就是服务器返回的一个时间戳:

合肥市房产市场信息平台跳转链接解密_html_03

至此,所有逻辑已经捋清楚,接下来就是编码实现。

 

三、编码实现
#!/usr/bin/env python3
# encoding: utf-8
"""
@author: CC11001100
"""
import random

import requests
from bs4 import BeautifulSoup


def crawl():
    url = "http://60.173.254.126/"
    html = requests.get(url).text
    doc = BeautifulSoup(html, features="html.parser")
    iptstamp = doc.select_one("#iptstamp")["value"]

    r = {}
    for x in doc.select("a[id][onclick][title][style]"):
        id = x["id"]
        link = "http://60.173.254.126/item/" + recode(id, iptstamp)
        title = x["title"]
        r[title] = link
    return r


def recode(s, iptstamp):
    n = nscaler(s)
    c = set_obj_num(len(n))
    d = set_obj_num(len(n))
    n = int(n) + int(d)
    b = nscaler(iptstamp)
    return str(c) + "-" + str(n) + "-" + str(d) + "-" + str(b)


def set_obj_num(n):
    r = 0
    for _ in range(0, n):
        r += int(random.random() * 10)
    return r


def nscaler(s):
    mapping = {
        0: 0,
        1: 2,
        2: 5,
        3: 8,
        4: 6,
        5: 1,
        6: 3,
        7: 4,
        8: 9,
        9: 7,
    }
    result = 0
    for x in s:
        result = result * 10 + mapping[int(x)]
    return str(result)


if __name__ == "__main__":
    print(crawl())

运行效果:

合肥市房产市场信息平台跳转链接解密_开发者工具_04

经验证无误。

本作品采用知识共享署名 4.0 国际许可协议进行许可。