ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【新冠疫苗预约】Fiddler抓包新冠疫苗预约接口及脚本实现

2021-06-12 23:29:24  阅读:343  来源: 互联网

标签:Fiddler 加密 预约 rest headers token 疫苗 ybm appid


文章目录

1. 工具

  • Fiddler 抓包工具
  • 手机(与PC统一局域网)
  • Chrome浏览器
  • Postman

2. 接口抓包

打开fiddler软件,在Tools > Options 按以下设置:
在这里插入图片描述
设置连接信息,注意这里的端口是后面手机连接要用的:
在这里插入图片描述
在cmd命令行查看PC的IP地址:
在这里插入图片描述
手机连接到和PC相同的网络,并设置代理:
在这里插入图片描述
然后接下来从Fiddler里就可以抓取到手机端的请求了,预约入口这里使用【深圳疾控】公众号,请求过程如下:
在这里插入图片描述
下面就是查找的过程,找出对我们有用的请求并且分析,从下网上找:

1. 社康信息接口
这个接口可以查询社康列表,返回信息包括社康ID,社康名称,可打疫苗厂商,社康地址,当前状态等信息。
在这里插入图片描述
2. 获取深圳区列表
这个接口返回的区代码后面会有用,用来查询这个区的号源:
在这里插入图片描述
3. 获取疫苗厂商列表
这个接口是获取疫苗厂商列表信息,其中重要的数据是corpCode – 厂商代码。
在这里插入图片描述
4. 获取token接口
这个接口也可以不用分析,因为token很长时间不会过期,可以直接抓包拿到就可以,一般在请求头就可以找到。
在这里插入图片描述
5. 获取用户信息接口
这个接口返回真实用户信息,也包含token。
在这里插入图片描述
6. 查看当前社康这天每个时间段的号源情况
restSurplus 大于0表示有号,下面箭头指的说明9:30-10:001个号:
在这里插入图片描述
7. 预约接口
这里参数就包含了社康信息还有token一些参数,下节分析。
在这里插入图片描述
8. 查看预约结果信息
预约成功后,查看详细预约信息。
在这里插入图片描述

3. 参数解密过程

通过上一步分析,可以把有用的接口都捞出来了,接下来就是分析参数,然后用Postman来模拟请求,只有请求成功了才算真的分析清楚了。那么参数分析在那里分析方便呢?当然是浏览器啦,这里教大家一个小技巧,可以在Chrome上调试微信页面。

有小伙伴可能要问了,为什么是调试微信页面呢,其实公众号里面嵌入的是H5页面,因为我发现了有一个请求返回的是网页:
在这里插入图片描述
用这个请求地址在Chrome浏览器访问页面试一下(记得带上参数),结果是这样的:
在这里插入图片描述
哦~ 原来预约界面就是H5页面,如此就简单多了,谁说预约只能在手机上的,这不PC也可以吗?

那么调试起来是不是很方便呢,Fiddler抓包现在就可以不用了,开始用Chrome整吧,这里提一下不要觉得加密的参数太多就怕了,一般网站加密方法是一样的,只要破了一个其他的就都破了,就以获取社康列表信息这个接口来看:

首先最简单的是能看到请求地址:https://xgsz.szcdc.net/crmobile/outpatient/nearby
请求方式:POST
然后可以看到请求头里有一些加密的参数,还有Form-Data里也有一个params是加密的:
在这里插入图片描述
经过使用Postman模拟请求,筛选出Header中的tokenappidotnybm是必须的,token是后台传过来的(后面分析),appid是固定的,所以重要的是otnybm这俩参数,因为加密了,下面就来看看加密方法,先搜索ybm
在这里插入图片描述
搜到这个js中这里正是设置header的地方,刚好ybmotn是用的同一种加密方式,先看看加密方法的参数,这里c,p是上面生成的,后面是固定的字符串,在上面打个断点再刷新一下,可以查出上面的方法是啥:

这里的c=u()是返回的当前时间戳的相关字符串:
在这里插入图片描述
pd(e,c)得来的,etokenc就是上面的时间戳相关参数,d方法是字符串拼接:
在这里插入图片描述
接下来看看加密函数Object(_t.b)是啥,控制台先看下,是个函数:
在这里插入图片描述
调试进去看看:
在这里插入图片描述
额,这就不用多说了吧,一个是加密函数,一个是解密函数,参数都是传进来的,上面分析好了,接下来分析i方法是返回什么:
在这里插入图片描述
这个就是加密函数了,但是最后返回一个new ybzl.SM4(l)是什么鬼,感情这个方法只是处理参数而已,额,不急,我们进去看看:
在这里插入图片描述
好家伙!直接进去了bundle.min.js 里面都是算法啊,调试里面的太复杂了,我放弃了,但是我发现一件事:
在这里插入图片描述
其实这里会把这个函数输出到window对象上,这就好办了,不跟你玩了,直接把这个js文件下载下来,直接用,哈哈哈~

4. 解密方法整理重构

经过了上面的分析,我自己写出了加密和解密的方法,如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script src="bundle.min.js"></script>
		<script>
			/**
			 * 1 获取疫苗厂商  token
			 * 2 获取区域列表  token appid
			 * 3 获取社康信息  token appid otn ybm  params
			 * 4 获取时间段疫苗数量  token appid otn ybm  params
			 * 5 获取用户信息  token appid
			 * 6 预约         token appid reservationtoken  Content-Type  json参数
			 * 7 查看预约信息  token appid reseId(预约成功返回)
			 */
			
			// 加密解密方法
			function i(t, e) {
				t = t || "di6N7eCJYFp3kB4Q,!@#$%&*",
				e = e || "u1r8jNhz07N7Zkn0";
				var n = t.split(",")
				  , i = n // r()(n, 2)
				  , a = i[0]
				  , o = i[1]
				  , s = a.split("");
				o.split("").map(function(t, e) {
					s[e + e + 1] = t
				}),
				s = s.join("");
				var l = {
					key: s,
					mode: "cbc",
					iv: e,
					cipherType: "base64"
				};
				return new ybzl.SM4(l)
			}
			
			// otn ybm 加密
			function u() {
				return (Date.now().toString() + (1e6 * Math.random().toFixed(6)).toString()).padEnd(19, "0")
			}
			function d(t, e) {
				if (!t || !e)
					return "";
				var n = t.substring(0, 5)
				  , i = t.substring(5, 10)
				  , a = t.substring(10, 12)
				  , o = t.substring(12);
				return n + e.substring(0, 14) + i + e.substring(9, 10) + a + e.substring(16, 17) + o
			}
			// token获取在下面介绍
			var token = "xxx";
			var c = u(), p = d(token, c);
			var ybm = i("1EzrokKlK2pFuEIT,~@#^%&*", "4h0VXhpqwWy89xBk").encrypt(c)
			var otn = i("1EzrokKlK2pFuEIT,~@#^%&*", "4h0VXhpqwWy89xBk").encrypt(p)
			console.log(ybm);
			console.log(otn);
			
			// params 加密
			let params = {
				areaCode: "440309",  // 区号
				bactCode: "5601",    // 新冠疫苗编号,不用改
				corpCode: "",        // 疫苗厂商代码
				numPerPage: 10,      // 每页显示记录数
				outpMapLatitude: "", // 地图纬度
				outpMapLongitude: "",// 地图经度
				outpName: "",        // 社康名称
				pageNum: 1           // 页数
			}
			let res = i("016BhmYAk7Oi1ajM,~@#^%&*","4h0VXhpqwWy89xBk").encrypt(JSON.stringify(params));
			console.log(res);
			
			// 从H5页面加密的参数中解密出 appId token reservationtoken cardNo
			let uri = "hYAPOVzzgsPD8XXKeSRfCIO2zdSKobI6YQFdzDUWwORNYoT1MDCf......."; // H5地址加密部分
			var true_params = i(undefined, undefined).decrypt(uri);
			console.log(true_params)
			// appId=xxx&token=xxx&cardNo=xxx&reservationToken=xxx&vaccineCode=
		</script>
	</body>
</html>

因涉及个人隐私,中间的参数我没有贴真实的返回结果,请自行测试。

5. 脚本实现

参数破解完后,最后一步就是实现自动化预约了,预约流程:

在这里插入图片描述
具体实现下面给个例子,因为现在号源也比较多,所以没有写脚本,需要的自己修改一下就行了:

# -*- coding: utf-8 -*-
import requests, time, copy
from urllib.parse import parse_qs, urlencode, urlparse

token = ""
appid = ""
otn = ""
ybm = ""
reservationtoken = ""

baseHeaders = {
    # "Cookie": findCookie,
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1326.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63010200)"
}


# 获取疫苗余量
def getRest():
    rest_url = "https://xgsz.szcdc.net/crmobile/reservationStock/timeNumber"
    params_1 = "4517CL5iSqYrVthaOYxxxxxxxxxx" # 先加密好
    rest_headers = copy.deepcopy(baseHeaders)
    rest_headers["token"] = token
    rest_headers["appid"] = appid
    rest_headers["otn"] = otn
    rest_headers["ybm"] = ybm
    rest_data = {
        "params": params_1
    }
    rest_res = requests.post(rest_url, json=rest_data, headers=rest_headers).json()
    return rest_res


# 预约
def save():
    post_url = "https://xgsz.szcdc.net/crmobile/reservation/saveAppointment"
    data = {
        "reusId": "6068111xxxxxxxxxxx",  # 用户的reusId 固定
        "depaId": "1698A7F4-CA7B-9FDA-FC3C-48DEE401491B",  # 社康ID (第1个请求获取)
        "corpCode": "80",  # 厂商代码
        "date": "2021-06-13",  # 日期
        "ouatId": "831",  # 时间段ID  (第2个请求获取)
        "vaccCodes": "5601"   # 新冠疫苗code
    }
    post_headers = copy.deepcopy(baseHeaders)
    post_headers["token"] = token
    post_headers["appid"] = appid
    post_headers["reservationtoken"] = reservationtoken
    post_headers["Content-Type"] = "application/json"
    rest_res = requests.post(post_url, json=data, headers=post_headers).json()
    return rest_res

6. 总结

这个抓取接口花了两次,第一次抓完后第二天官方就修改了参数,把原来的明文改为加密的了,后来又抓了一遍,通过参数的解密过程,大家会学会如何去分析、调试、并重构它,结果无所谓,主要是分析过程,希望能帮到大家。

点赞支持下,谢谢~

标签:Fiddler,加密,预约,rest,headers,token,疫苗,ybm,appid
来源: https://blog.csdn.net/zy1281539626/article/details/117827598

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有