写在前面
Python 课最后的大作业,跟大哥们一起写这个小玩意,因为学院好像很喜欢刷这些东西,总体来说挺简单的
分到我的模块刚刚好需要手机抓包,网页端易班登陆进去没有发动态的模块了,模块在维护 后续会更新其他人的板块并尝试做出来真正的模拟登陆(逆向app或者使用appium提取loginToken)
源码
# -*- coding: utf-8 -*-
"""
@Time : 2021/5/5
@Author : C1everF0x
@File : dongtai
@Description :
"""
import re
import requests
import urllib.parse
def login():
'''
登录模块其实没有真正实现,网页端登录已经能通过逆向分析 login.js 文件来获取易班对密码在前端的加密算法,可以真正实现模拟登录
app端无法通过抓包或分析接口地址来找到加密方式
第一次输入密码登陆过后,app会将 loginToken 嵌入到 app 里,下次打开会提取拼接到 autologin 接口的 url中
目前能想到的 app 端实现真正模拟登录两种方法:
1、app 端在登录时候对密码的加密是嵌在 app 的源码里,真要做可以通过逆向分析 app 源码,找到加密代码逆向破解
2、使用类似于 seleium 的 appium 来实现模拟真正的人进行登录,再从中提取出 loginToken
目前实现只能够是抓包拿 loginToken 来给到 autologin 接口进行伪造登录
2021.05.07
:return:
'''
url = "https://mobile.yiban.cn/api/v3/passport/autologin?access_token=e3017321cf9cdae74e34061cf7adef4a"
header = {
'User-Agent': 'YiBan/4.9.9 Mozilla/5.0 (Linux; Android 5.1.1; MI 9 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36',
'Authorization': 'Bearer e3017321cf9cdae74e34061cf7adef4a',
'loginToken': 'e3017321cf9cdae74e34061cf7adef4a',
'AppVersion': '4.9.9',
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip, deflate'
}
try:
r = requests.get(url = url,headers = header)
r.raise_for_status() # 判断异常
r.encoding = r.apparent_encoding # 设置编码
return '登录成功'
except:
return '登录失败'
class DongTai:
def __init__(self,token,neirong_dongtai,neirong_pinglun): # 初始化类里面的私密属性
self.__token = token
self.neirong_dongtai = neirong_dongtai
self.__dongtai_hao = None
self.neirong_pinglun = neirong_pinglun
def release(self,neirong_dongtai):
'''
自动发布动态,动态内容需要进行一次 url 编码
动态发布成功后会返回一个 json ,里面有每个动态专属的一个九位数的号码
之后对动态进行的点赞、评论操作,需要通过该号码定位是哪条动态
:return:
'''
url = r'https://mobile.yiban.cn/api/v3/feeds/?access_token=' + self.__token + '&content=' + urllib.parse.quote(neirong_dongtai) + '&visibleScope=0&artwork=0&toUserIds=&address=&lat=&lng=&share=0&shareTitle=&shareUrl=&shareContent=&shareImage=&shareSource=&kind=1&hiddenAddress=0'
header = {
'User-Agent': 'YiBan/4.9.9 Mozilla/5.0 (Linux; Android 5.1.1; MI 9 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36',
'Authorization': 'Bearer e3017321cf9cdae74e34061cf7adef4a',
'loginToken': 'e3017321cf9cdae74e34061cf7adef4a',
'AppVersion': '4.9.9',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'gzip, deflate',
'Content-Length': '0',
}
try:
r = requests.post(url,headers = header)
r.raise_for_status()
r.encoding = r.apparent_encoding
response_json = r.text
re_response_json = re.findall(r'\d{9}',response_json) # 正则匹配提取动态号码
self.__dongtai_hao = ''.join(re_response_json) # 赋给私有变量
return '发布成功,该动态 id 为 {}'.format(self.__dongtai_hao)
except:
return '发布失败'
# 返回 json 样例,feedId 是动态号码
# {"response": 100, "message": "\u8bf7\u6c42\u6210\u529f",
# "data": {"feedId": 294594341, "feedCheckinReward": null}}
def give_good(self):
'''
自动给动态点赞
:return:
'''
url = r'https://mobile.yiban.cn/api/v3/feeds/' + self.__dongtai_hao + r'/ups?access_token=' + self.__token
header = {
'User-Agent': 'YiBan/4.9.9 Mozilla/5.0 (Linux; Android 5.1.1; MI 9 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36',
'Authorization': 'Bearer e3017321cf9cdae74e34061cf7adef4a',
'loginToken': 'e3017321cf9cdae74e34061cf7adef4a',
'AppVersion': '4.9.9',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'gzip, deflate',
'Content-Length': '0',
}
try:
r = requests.post(url, headers=header)
r.raise_for_status()
r.encoding = r.apparent_encoding
return '点赞成功'
except:
return '点赞失败'
def comments(self,neirong_pinglun):
'''
自动给动态评论,内容需要进行一次 url 编码,通过之前发布存入私有变量的动态号码来确定需要评论哪条动态
:return:
'''
url = r'https://mobile.yiban.cn/api/v3/feeds/' + self.__dongtai_hao + '/comments?access_token=' + self.__token + r'&content=' + urllib.parse.quote(neirong_pinglun) + r'&toUserId=&toCommentId='
header = {
'User-Agent': 'YiBan/4.9.9 Mozilla/5.0 (Linux; Android 5.1.1; MI 9 Build/NMF26X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36',
'Authorization': 'Bearer e3017321cf9cdae74e34061cf7adef4a',
'loginToken': 'e3017321cf9cdae74e34061cf7adef4a',
'AppVersion': '4.9.9',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'gzip, deflate',
'Content-Length': '0',
}
try:
r = requests.post(url, headers=header)
r.raise_for_status()
r.encoding = r.apparent_encoding
return '评论成功,评论内容为 {}'.format(neirong_pinglun)
except:
return '评论失败'
if __name__ == "__main__":
print(login())
token = 'e6262d37a192f6be11c159f4080326d9'
neirong_dongtai = input('请输入动态内容:')
neirong_pinglun = input('请输入评论内容:')
dongtai = DongTai(token,neirong_dongtai,neirong_pinglun) # 实例化动态类,需要提供 loginToken,发布动态内容和评论内容
print(dongtai.release(neirong_dongtai))
print(dongtai.comments(neirong_pinglun))
print(dongtai.give_good())
最后结果如图:
整体流程
流程图如下
知识点
使用 requests 库编写爬虫程序,实现模拟真实用户进行发布动态、评论动态和点赞动态的功能
使用 re 库对发布动态成功后的返回包进行解析,提取发布成功的动态的动态号码
搭建安卓虚拟机 + xposed 框架 + justTrustMe 模块,因为 app 可以自己检验 SSL 握手时服务器返回的证书是否合法,“SSL pinning” 技术指在 app 中只信任固定的证书和公钥,安卓 7.0 以上把证书分为系统证书和用户证书,有些 app 只信任系统证书,真实手机抓包会提示手机没网,所以需要使用 xposed 框架 + justTrustMe 模块,来 hook 掉本地证书强校验的逻辑,同时导入 burp 的证书,使其流量通过 burp,实现手机抓包
Xposed 框架是一款开源框架,其功能是可以在不修改 APK 的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作
JustTrustMe 一个用来禁用、绕过 SSL 证书检查的基于 Xposed 模块。简单来说,JustTrustMe 是将 APK 中所有用于校验 SSL 证书的 API 都进行了 Hook,从而绕过证书检查的
抓包分析各个功能对 api 请求的 url 构造格式和 http 请求头的伪造方法
使用面向对象编程,将三个功能封装成类,方便团队进行最后的代码拼接
模拟登录
模拟登录模块其实没有真正实现,网页端登录已经能通过逆向分析 login.js 文件来获取易班对密码在前端的加密算法,可以真正实现模拟登录 app 端无法通过抓包或分析接口地址来找到加密方式 在 app 里第一次输入密码成功登陆后,app 会将 loginToken 嵌入到 app 里,下次打开会提取拼接到请求 autologin api 接口的 url 中 目前能想到的 app 端实现真正模拟登录两种方法: 1、app 端在登录时候对密码的加密是嵌在 app 的源码里,真要做可以通过逆向分析 app 源码,找到加密代码逆向破解 2、使用类似于 seleium 的 appium 来实现模拟真正的人进行登录,再从中提取出 loginToken 目前实现只能够是抓包拿 loginToken 来给到 autologin 接口进行伪造登录
抓取 loginToken
- 假设已经配置好了安卓虚拟机环境,在安卓虚拟机上打开易班,同时用 burp 抓包
保存下来复制到代码里面,替换掉所有需要用到的地方
自动发布动态
自动发布动态,动态内容需要进行一次 url 编码 动态发布成功后会返回一个 json ,里面有每个动态专属的一个九位数的号码 之后对动态进行的点赞、评论操作,需要通过该号码定位是哪条动态
抓包分析
- 发布动态时需要在 url 中添加 access_token 参数,内容为之前抓取到的 loginToken,在 http 请求头里面还存在两个需要用到 loginToken 的头
自动评论动态
自动给动态评论,评论内容需要进行一次 url 编码,通过之前发布存入私有变量的动态号码来确定需要评论哪条动态
自动点赞动态
拼接需要点赞的动态号进入请求点赞 api 的 url 中,请求即可完成点赞