爬虫05 /js加密/js逆向、常用抓包工具、移动端数据爬取

1. js加密、js逆向:案例1

  • 需求: 将这个网页中的代理ip和端口号进行爬取

  • 分析:

    1. 爬取的数据是动态加载

    2. 并且我们进行了抓包工具的全局搜索,没有查找到结果

      意味着:爬取的数据从服务端请求到的是加密的密文数据

    3. 页面每10s刷新一次,刷新后发现数据更新,但是浏览器地址栏的url没有变,说明加载出的数据是由ajax请求到的

      动态加载出来的数据是由ajax请求到的,并且请求到的数据为加密数据

    4. 定位到ajax数据包,从中可以看到url和动态变化的请求参数和加密的相应数据

    5. 将ajax请求到的密文数据捕获

      动态的获取动态变化的请求参数

      基于抓包工具进行了动态变化请求参数taken的全局搜索,定位到了taken产生的源头,就是如下js代码:

      var token = md5(String(page) + String(num) + String(timestamp));
    6. 对密文数据进行解密

      通过分析找到了解密的js函数:decode_str(encode_str),encode_str就是密文数据

    7. 查找encode_str的实现:

      js逆向:将js代码转换成python代码。开发环境只能执行python代码

  • js加密/js逆向源码相关代码:

    function get_proxy_ip(page, num, click_btn) {
    var timestamp = Date.parse(new Date());
    timestamp = timestamp / 1000;
    var token = md5(String(page) + String(num) + String(timestamp));
    $.get('../proxy?page=' + page + '&num=' + num + '&token=' + token + '&t=' + timestamp, function (result) {
    if (result.status === 'true') {
    var setHtml = "";
    $("#ip-list").html(setHtml);
    var encode_str = result.list;
    var items = str_to_json(decode_str(encode_str));
    for (var index = 0; index < items.length; ++index) {
    item = items[index];
    setHtml += "<tr>\n<td>" + (index + 1) + "</td>\n";
    setHtml += "<td>" + item.ip.toString() + "</td>\n";
    setHtml += "<td>" + item.port.toString() + "</td>\n";
    setHtml += "<td>" + item.time.toString() + "</td>\n</tr>\n";
    }
    $("#ip-list").html(setHtml);
    if (click_btn === 'next') {
    document.getElementById("last-page").disabled = false;
    if (items.length < 15) {
    document.getElementById("next-page").disabled = true;
    }
    } else {
    document.getElementById("next-page").disabled = false;
    if (page === 1) {
    document.getElementById("last-page").disabled = true;
    }
    } }
    });
    }

    js解密代码:

    function decode_str(scHZjLUh1) {
    // Base64.decode(scHZjLUh1)
    scHZjLUh1 = Base64["\x64\x65\x63\x6f\x64\x65"](scHZjLUh1);
    key = '\x6e\x79\x6c\x6f\x6e\x65\x72';#key = 'b'nyloner'
    len = key["\x6c\x65\x6e\x67\x74\x68"];
    code = '';
    for (i = 0; i < scHZjLUh1["\x6c\x65\x6e\x67\x74\x68"]; i++) {
    var coeFYlqUm2 = i % len;
    code += window["\x53\x74\x72\x69\x6e\x67"]["\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65"](scHZjLUh1["\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74"](i) ^ key["\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74"](coeFYlqUm2))
    }
    return Base64["\x64\x65\x63\x6f\x64\x65"](code)
    }

    对以上代码分析结果如下:

    function decode_str(scHZjLUh1) {
    // Base64.decode(scHZjLUh1)
    scHZjLUh1 = Base64.decode(scHZjLUh1);
    key = 'nyloner';
    len = key.length;
    code = '';
    for (i = 0; i < scHZjLUh1.length; i++) {
    var coeFYlqUm2 = i % len;
    code += window.String.fromCharCode(scHZjLUh1.charCodeAt(i) ^ key.charCodeAt(coeFYlqUm2))
    }
    return Base64.decode(code)
    } // '\x64\x65\x63\x6f\x64\x65'.encode('utf-8')
    // 注意:遇到类似字节的代码,一般不是加密数据,通过encode编码尝试是否可以得到有效信息
  • 代码实现:

    导入所需模块:

    import time
    import hashlib
    import requests
    import base64

    js逆向/将js代码转换成python代码:

    # js逆向之后的结果
    def decode_str(scHZjLUh1):
    # 解密成字符串
    scHZjLUh1 = base64.decodestring(scHZjLUh1.encode())
    key = 'nyloner'
    lenth = len(key)
    code = ''
    sch_lenth = len(scHZjLUh1)
    for i in range(sch_lenth):
    coeFYlqUm2 = i % lenth
    # chr(0-255)返回对应编码的字符
    # ord(a-z)返回编码数值
    code += chr(scHZjLUh1[i] ^ ord(key[coeFYlqUm2]))
    code = base64.decodestring(code.encode())
    code = code.decode('utf-8')
    return code

    生成请求所需的token值:

    def getToken():
    page = str(1)
    num = str(15)
    t = str(int(time.time()))
    md5 = hashlib.md5()
    md5.update((page+num+t).encode('utf-8'))
    token = md5.hexdigest()
    return token

    对响应数据解密:

    token = getToken()
    url = 'https://nyloner.cn/proxy'
    param = {
    'num':'15',
    'page':'1',
    't':str(int(time.time())),
    'token':token }
    headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
    'Cookie':'sessionid=20ryihg87smnkko2kx6634jbcf4umhfp'
    }
    code = requests.get(url,headers=headers,params=param).json().get('list')
    str_code = decode_str(code)
    str_code

2. js加密、js逆向:案例2

  • 需求: url:https://www.aqistudy.cn/html/city_detail.html ,对其气象数据进行爬取

  • 分析:

    1. 点击不同气象指标的选项卡,发现没有相关的请求发送,说明当页面加载出来的时候,所有的气象数据已经加载完毕。

    2. 分析数据是否为动态加载 ,得出数据是动态加载出来的

    3. 修改查询的条件(城市的切换,时间的修改),点击搜索按钮就会加载出新数据。

    4. 在抓包工具的XHR中捕获到了两个数据包

      • url一样
      • 都有一个d这样的请求参数
      • 两个数据包的请求参数d的数据值不同
      • d这个请求参数是经过加密且动态变化
    5. 处理动态变化且加密的请求参数d

      对请求参数d进行全局搜索(不可行)

      点击页面中的搜索按钮后,在抓包工具中就捕获到了那两个ajax请求的数据包

      • 点击按钮发起ajax请求,找按钮的点击事件(click)
      • 借助火狐浏览器的开发者工具进行按钮点击事件的定位 ,根据点击事件定位到 getData()js函数
    6. 分析getData这个js函数的实现:目的就是为了找到ajax请求对应的js代码

      type=="HOUR":按照小时为时间单位进行查询

      并没有在该函数的实现中发现ajax请求对应的代码,但是发现了另外的两个函数调用getAQIData();getWeatherData();

    7. 分析getWeatherData();和getAQIData()这两个函数的定义,想要去找到ajax请求对应的代码:

      这两个函数实现的区别: method变量赋值的字符串不一样 GETDETAIL / GETCITYWEATHER

      相同: 都没有出现ajax请求对应的代码,但是发现了另一个函数的调用: getServerData(method,param,匿名函数,0.5)

    8. 对getServerData(method,param,匿名函数,0.5) 参数进行分析

      method:GETDETAIL或者GETCITYWEATHER

      param:字典,有四组键值对

      • city:查询城市的名称
      • type:HOUR
      • startTime:查询开始的时间
      • endTIme:查询结束的时间
    9. 对getServerData(method,param,匿名函数,0.5)函数进行分析

      getServerData(method,param,匿名函数,0.5)这个函数的实现,还是为了找到ajax请求对应的代码:

      基于抓包工具的全局搜索才可以找到

      发现这个函数的实现代码看不懂,函数的实现好像是一组密文 / 网站对js函数的实现加密

    10. 插入两个概念/上面密文用到了js混淆:

      JS混淆:对js函数的实现代码进行加密

      JS反混淆:将加密的js代码解密成原文

    11. 暴力破解: https://www.bm8.com.cn/jsConfusion/

    12. 分析getServerData函数的实现:

      终于找到了ajax请求对应的代码

      参数d是由getParam(method, object)函数返回的

      method:method

      object:param字典,四个键值分别是城市名称。type,起始时间,结束时间

    13. 请求到的密文数据的解密方式:

      decodeData(data):data参数就是响应的密文数据,返回值就是解密后的原文数据

    14. JS逆向:python可以使用 PyExecJS 库来实现模拟JavaScript代码执行。

    15. 环境的安装:

    ```python
    pip install PyExecJS
    ```
    1. 必须还要安装nodeJs的开发环境 /PyExecJS是依赖nodeJs环境运行的

    2. 请求到加密的响应数据

    3. 将加密的响应数据进行解密

  • 代码实现:

    import execjs
    import requests
    headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
    }
    node = execjs.get()
    file = 'test.js'
    ctx = node.compile(open(file,encoding='utf-8').read()) # 如何五个变量会作为getPostParamCode的参数
    method = 'GETDETAIL' # GETCITYWEATHER
    city = '北京'
    type = 'HOUR'
    start_time = '2018-01-25 00:00:00'
    end_time = '2018-01-25 23:00:00'
    # 模拟执行getPostParamCode函数
    js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
    params = ctx.eval(js)
    # print(params) # 请求参数d
    url = 'https://www.aqistudy.cn/apinew/aqistudyapi.php'
    data = {
    'd':params
    }
    # 获取了加密的响应数据
    response_code = requests.post(url=url,headers=headers,data=data).text
    # response_code # 模拟执行decodeData函数对密文数据进行解密
    js = 'decodeData("{0}")'.format(response_code)
    page_text = ctx.eval(js)
    print(page_text)

3. 常用的抓包工具

  • 抓包工具概述:

    本质就是一款代理服务器,适用于实现请求和相应的拦截

  • fiddler

    • 默认只可以抓起http协议的请求和相应
    • https:
      • tools-> options-> https-> detrypt HTTPS traffic
      • 含义:将fiddle的证书安装到本地
  • 青花瓷

  • miteproxy

4. 移动端数据的爬取

  • 配置相关的环境

    • fiddler的配置:

      • tools-> options-> connections-> Allow remote computers to connect/选中
      • 查看fiddler的端口号,并且记住端口号
    • 测试配置是否生效:
      • 在电脑的浏览器访问:http://localhost:端口号/,如果可以访问成共则表示配置成功
  • 网络设置:

    • fiddler所在的电脑开启一个热点,手机连接热点

      • 保证手机和电脑同处于同一个网段
  • 在手机中安装fiddler的证书

    • 手机浏览器访问:http://电脑的ip:端口号/

      • 点击下载证书的链接,进行证书下载
    • 在手机中新任且安装证书
  • 开启手机网络代理

    • wifi-> 点击感叹号-> 开启代理-> 代理的ip就是电脑的ip,端口就是fiddler的端口
  • appnium是一个基于手机应用自动化的模块

总结:

  1. js加密:为了防止爬虫,对js代码进行加密
  2. js逆向:对于python来说,就是将js代码转换成python代码
  3. js混淆:对js函数的实现代码进行加密
  4. JS反混淆:将加密的js代码解密成原文
  5. 看js函数是在定义函数还是在调用函数,查看后面是否跟着;号,有的话就是在调用/没有的话就是在定义

爬虫05 /js加密/js逆向、常用抓包工具、移动端数据爬取的更多相关文章

  1. Android 常用抓包工具介绍之Charles

    ➠更多技术干货请戳:听云博客 Charles是一款抓包修改工具,相比起TcpDump,charles具有界面简单直观,易于上手,数据请求控制容易,修改简单,抓取数据的开始暂停方便等等优势!前面介绍了如 ...

  2. Android常用抓包工具之TcpDump

    ➠更多技术干货请戳:听云博客 做为一个测试人员,工作中经常会用到数据抓包工具来进行数据分析和验证,下面就简单介绍一下工作中常用的抓包工具. TcpDump抓包 Tcpdump是一个用于截取网络分组,并 ...

  3. C#一步一步学网络辅助开发(1)--常用抓包工具的使用

    这次写的是一个系列,是让大家了解如何进行网络的辅助开发.要进行网络辅助开发抓包工具是必不可少的,下面就让大家熟悉一下常用的一些抓包工具, 1,Fiddler 这个工具是我目前用的最多的一款抓包工具,不 ...

  4. HTTP调试 抓包 工具 Fiddle 简介 示例

    简介 1.常用抓包工具对比: Firebug虽然可以抓包,但是对于分析http请求的详细信息,不够强大.模拟http请求的功能也不够,且firebug常常是需要"无刷新修改",如果 ...

  5. 芝麻HTTP:JavaScript加密逻辑分析与Python模拟执行实现数据爬取

    本节来说明一下 JavaScript 加密逻辑分析并利用 Python 模拟执行 JavaScript 实现数据爬取的过程.在这里以中国空气质量在线监测分析平台为例来进行分析,主要分析其加密逻辑及破解 ...

  6. 为什么用抓包工具看HTTPS包是明文的

    测试或者开发调试的过程中,经常会进行抓包分析,并且装上抓包工具的证书就能抓取 HTTPS 的数据包并显示.由此就产生了一个疑问,为什么抓包工具装上证书后就能抓到 HTTPS 的包并显示呢?不是说 HT ...

  7. 【爬虫】网页抓包工具--Fiddler--Request和Response

    [爬虫]网页抓包工具--Fiddler Fiddler基础知识 Fiddler是强大的抓包工具,它的原理是以web代理服务器的形式进行工作的,使用的代理地址是:127.0.0.1,端口默认为8888, ...

  8. Fiddler抓取https请求 & Fiddler抓包工具常用功能详解

    Fiddler抓取https请求 & Fiddler抓包工具常用功能详解   先来看一个小故事: 小T在测试APP时,打开某个页面展示异常,于是就跑到客户端开发小A那里说:“你这个页面做的有问 ...

  9. Python爬虫-02:HTTPS请求与响应,以及抓包工具Fiddler的使用

    目录 1. HTTP和HTTPS 1.1. HTTP的请求和响应流程:打开一个网页的过程 1.2. URL 2. 客户端HTTP请求 3. Fiddler抓包工具的使用 3.1. 工作原理 3.2. ...

随机推荐

  1. ecshop头部添加所在城市

    首先,在/includes/lib_main.php中,找到代码:function assign_template($ctype = '', $catlist = array())   ,在方法中添加 ...

  2. EAT表

    0X0 EAT表 在windows系统中,"库"是为了方便其他程序调用而集中包含相关的函数的文件(dll,sys).win32 API是最具有代表性的库. EAT是一种核心机制,它 ...

  3. jenkins构建报错 Error fetching remote repo 'origin'

    ERROR: Error fetching remote repo 'origin' Finished: FAILURE // 原因如下 原因一:可能是配置的git分支的权限问题,检查一下配置里面的源 ...

  4. 国外的教授都说,用这个方式21天就能学会python,这是中国速度

    你尝试过吗?按照这个方式,用21天就能学会python编程.     在今年的疫情期间,在家的时间何止21天,有这样一位做财务的朋友,为了提高自己的数据分析能力,在家通过这个方式,跟着21天的规划,坚 ...

  5. 多语言工作者の十日冲刺<5/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺--第五天(05.04) 作业正文 ...

  6. 从零开始手把手教你使用原生JS+CSS3实现幸运水果机游戏

    项目体验地址 免费视频教程 游戏介绍 幸运水果机是一款街机游戏,游戏界面由24个方格拼接成一个正方形,每个方格中都有一个不同的水果图形,方格下都有一个小灯.玩家使用游戏币选择希望押注的目标,按下开始后 ...

  7. Windows Server 2019 container容器化-Docker安装

    一.启用服务器Hyper-V,Containers特性 Install-WindowsFeature -Name Hyper-V,Containers -IncludeAllSubFeature -I ...

  8. TCP协议粘包问题详解

    TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...

  9. Python 中的元类到底是什么?这篇恐怕是最清楚的了

    类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...

  10. '%' For instance '%d'

    with each % indicating where one of the other (second, third, ...) arguments is to be substituted, a ...