iami233
iami233
文章156
标签37
分类4

文章分类

文章归档

抓包校友邦小程序实现自动签到

抓包校友邦小程序实现自动签到

由于 Android 7.0 之后不在信任用户证书,无法抓取 HTTPS 请求,根据网上的教程配置了一番无法配置成功,干脆使用了 Android 5.0 ,同时微信版本不要太高,貌似最新版本不兼容 Android 5.0,一直崩溃。

所用工具

工具除 Burpsuite 文末均会附上下载地址

  • 夜神模拟器
    我比较常用国际版6.5.0.3,国内最新版也行,注意最新版默认是 Android 7 需要在 多开器 中新建 Android 5
  • 微信 (旧版8.0.0)
  • Fiddler (汉化版5.0.2)
  • Burpsuite

配置环境

选择网卡

使用 ipconfig 查询本机网卡信息,网卡的选择随意即可,我这里选择了 Vmnet8 网卡,

image-20221215151352444

Burpsuite

新增一个 监听器监听地址 使用我们上面选择的 192.168.8.1,端口的话就默认 8080 即可

image-20221215151248441

Fiddler

在菜单栏 工具选项 中勾选配置如下图即可。

image-20221215151219960

连接 这里可以自定义 Fiddler 监听端口,我们保持默认 8888 即可

image-20221215151909746

这里配置 网关 的目的,是让流量可以被 Burpsuite 接收到,这里代理配置填写 Burpsuite 监听器中的配置。

image-20221215151225025

夜神模拟器

配置代理

WLAN 长按 修改网络 ,勾选 高级选项,然后在配置如下图所示

1
2
代理服务器主机名:填写你选择网卡IP
代理服务器端口:填写Fiddler监听的端口,默认8888

image-20221215150036716

安装证书

修改完毕后前往浏览器访问 代理IP:端口,点击 FiddlerRoot certficate下载证书

image-20221215150025007

然后在手机 设置安全 里选择 从SD卡中安装

image-20221215150345935

我们依次选择 内部存储空间Download,会看到 FidderRoot.crt,点击进行安装操作即可,名称随意。

image-20221215150345935

开始抓包

此时我们在模拟器中,访问一个页面,可以看到 FiddlerBurpsuite 均接收到了流量

image-20221215152200619

打开 校友邦 小程序,默认只能 微信登录 ,登录后在 设置退出登录 ,即可 手机号登录,可以通过 忘记密码 功能来重设密码。

image-20221225172318576

模拟登录

我们在账号密码登录的时候直接抓包,得到如下请求(已删除无用参数进行精简)

1
2
3
4
5
6
7
8
POST /login/login.action HTTP/1.1
Host: xcx.xybsyw.com
Connection: close
Content-Length: 39
charset: utf-8
content-type: application/x-www-form-urlencoded

username=手机号&password=md5(密码)

image-20221225173048459

响应如下,对我们有用的目前只发现 sessionIdloginId

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"code": "200",
"data": {
"activate": true,
"sessionId": "******",
"needComplete": false,
"loginerId": ******,
"phone": "手机号",
"loginKey": "手机号"
},
"msg": "登录成功",
"mstv": {
"t": 时间戳,
"m": "*****",
"s": "*****",
}
}

直接编写代码,实现登录功能(为方便演示代码使用的 Python ,但是感觉写起来没 PHP 顺手)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
globalData = {'username' : 13888888888, 'password' : '密码'}

def md5(s):
m = hashlib.md5()
m.update(s.encode('utf-8'))
return m.hexdigest()

def userLogin(u, p):
url = 'https://xcx.xybsyw.com/login/login.action'
data = {'username': u, 'password': md5(p)}
r = requests.post(url, data=data)
if r.json()['code'] == '200':
globalData['sessionId'] = r.json()['data']['sessionId']
globalData['loginerId'] = r.json()['data']['loginerId']
return(globalData)
else:
return(r.json()['msg'])

获取信息

继续抓包,得到一个包含 个人信息 的请求

1
2
3
4
POST /account/LoadAccountInfo.action HTTP/1.1
Host: xcx.xybsyw.com
Connection: close
cookie: JSESSIONID=*******

image-20221225175855340

继续编写代码,请求中的 Cookie 来自 登录成功 返回的 sessionId,取出 姓名学校ID,后面会用到

1
2
3
4
5
6
7
8
9
10
def getUserInfo(c):
url = 'https://xcx.xybsyw.com/account/LoadAccountInfo.action'
headers = {'Cookie': 'JSESSIONID=' + c}
r = requests.get(url, headers=headers)
if r.json()['code'] == '200':
globalData['username'] = r.json()['data']['loginer']
globalData['schoolId'] = r.json()['data']['schoolId']
return globalData
else:
return None

健康上报

image-20221227122206457

其中 healthCodeImg 为健康码照片,留空则为不提交,如果提交的话,直接填写图片url地址即可。

1
2
3
4
5
6
7
8
9
def postHealthData(c, img):
url = 'https://xcx.xybsyw.com/student/clock/saveEpidemicSituation.action'
data = {'healthCodeStatus': 0, 'locationRiskLevel': 0, 'healthCodeImg': img}
headers = {'Cookie': 'JSESSIONID=' + c}
r = requests.post(url, data=data, headers=headers)
if r.json()['code'] == '200':
return True
else:
return None

进行签到

进入签到页面,发现请求了一个接口,返回如下(已删除无用参数,只展示一下我们用得到的),发现提供了经纬度(由于自己签了一次,不知道经纬度是最初报名时的还是最后一次签到时的),不过这个接口也可以用作签到判断。

image-20221227123753129

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"code": "200",
"data": {
"clockInfo": {
"inAddress": "签到地址",
"inTime": "00:15:02", // 签到时间
"outTime": "", // 签退时间
},
"postInfo": {
"address": "好像是报名时自行填写的地址",
"lat": '维度',
"lng": '经度'
}
}
}

请求该接口的时候提交了 traineeId 参数,翻一下历史流量找到了 traineeId 参数值的来源

image-20221227125702526

直接编写代码取出 traineeId

1
2
3
4
5
6
7
8
9
def getSignState(c, traineeId):
url = 'https://xcx.xybsyw.com/student/clock/GetPlan!detail.action'
data = {'traineeId': traineeId}
headers = {'Cookie': 'JSESSIONID=' + c}
r = requests.post(url, data=data, headers=headers)
if r.json()['code'] == '200':
return r.json()['data']
else:
return None

在从 实习成长 页面一步步进入 签到页面 中,每请起一次都会附带请求 behavior/Duration.action 接口,暂不知道用途,先模拟出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def getUserIP():
url = 'https://xcx.xybsyw.com/behavior/Duration!getIp.action'
r = requests.get(url)
if r.json()['code'] == '200':
return r.json()['data']['ip']
else:
return None

def postSignData(d):
url = 'https://app.xybsyw.com/behavior/Duration.action'
data = {
'app': 'wx_student',
'appVersion': '1.6.36',
'userId': d['loginerId'],
'deviceToken': '',
'userName': d['username'],
'country': d['location']['country'],
'province': d['location']['province'],
'city': d['location']['city'],
'deviceModel': 'microsoft',
'operatingSystem': 'android',
'operatingSystemVersion': '11',
'screenHeight': '800',
'screenWidth': '450',
'eventTime': int(time.time()),
'pageId': '2',
'pageName': '成长',
'pageUrl': 'pages/growup/growup',
'eventType': 'click',
'eventName': 'clickSignEvent',
'clientIP': getUserIP(),
'reportSrc': '2',
'login': '1',
'netType': 'WIFI',
'itemID': 'none',
'itemType': '其他'
}
headers = {'Cookie': 'JSESSIONID=' + d['sessionId']}
r = requests.post(url, data=data, headers=headers)
if r.json()['code'] == '200':
return r.json()
else:
return None

至此,该获取的东西基本就获取到了,直接开始进行签到操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def sign(c, traineeId, d):
url = 'https://xcx.xybsyw.com/student/clock/Post!autoClock.action'
data = {
'traineeId': traineeId,
'adcode': d['location']['adcode'],
'lat': d['location']['lat'],
'lng': d['location']['lng'],
'address': d['location']['address'],
'deviceName': 'microsoft',
'punchInStatus': '1',
'clockStatus': '2',
'imgUrl': '',
'reason': ''
}
headers = {'Cookie': 'JSESSIONID=' + c}
r = requests.post(url, data=data, headers=headers)
if r.json()['code'] == '200':
return True
else:
return None

写在后面

2023/3/22 更新:关于加密逻辑可以前往 校友邦小程序签到加密逻辑解析

本文作者:iami233
本文链接:https://5ime.cn/xybsyw.html
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可