美文网首页
逆向万例| No.00001【滑块篇】喜某拉某web端登录滑块逆

逆向万例| No.00001【滑块篇】喜某拉某web端登录滑块逆

作者: 逆向扬 | 来源:发表于2023-03-04 16:42 被阅读0次

    声明:本文仅供学习交流用途,切勿用于非法行为,否则由此产生的一切后果均与作者本人无关。未经授权禁止转载本文。如有侵权,请及时通过本人公众号「逆向扬」联系删除。

    0x1 开始之前

    网站地址:YUhSMGNITTZMeTkzZDNjdWVHbHRZV3hoZVdFdVkyOXRMdz09(提示:如果解密不成功,可以试着多考虑一步)

    本文目标:逆向该网站登录滑块验证

    进入网站后,选择密码登录,在输入账号(手机号或邮箱)和密码后,会弹出一个滑块验证:

    这个网站的滑块难度属于入门级别,因此很适合逆向新手将这个作为滑块逆向的入门例子。

    下面我们来逆向这个滑块。

    0x2 抓包分析

    2.1 整体流程

    首先我们对网站的整个登录请求过程进行分析。打开 chrome 的开发者工具,分析一下网络包。

    在点击登录按钮后,会发送请求,用于获取滑块的底图和缺口图片:

    滑块后,会发送一个 slider 请求。如果没滑到正确位置,会返回验证失败的响应信息:

    若滑到了正确位置,则会返回验证成功的信息和一个 token 值:

    这个 token 会被放到 cookie 的 fds_otp 中,并发送一个请求,获取之后请求登录接口所需要用到的 nonce 参数值:

    最后,会发起对登录接口的请求,不过在本文中不讲解这一步。关于如何逆向该网站登录接口的参数,将在之后的文章中讲到:

    2.2 关键包分析

    这里最关键的是滑块验证请求 slider 。

    这个包的请求参数分析:

    • bpId:固定值,到时候直接写死就行。
    • captchaText:关键参数,格式是:"鼠标在x方向的滑动距离,鼠标在y方向的滑动距离"
    • sessionId:固定值,直接写死就行。
    • startTime:滑动开始时间。
    • startX:滑动开始时,鼠标与浏览器左边界的距离。这个参数不是很关键,可以随便填,但有范围要求,只要在一个合理范围内即可,我简单验证过。
    • startY:滑动开始时,鼠标与浏览器下边界的距离。值的要求同 startX 。
    • type:固定值,写死就行。

    因此,在这里,我们需要弄明白的是captchaText这个参数是如何生成的,只要能逆向这个参数,就能拿下这个网站的滑块。下面我们开始分析。

    0x3 验证码底图获取

    通过 get 这个请求可以获取到验证码的底图,获取到底图后,需要注意网站会以 0.8 的比例显示滑块验证码图片:

    获取底图的代码:

    payload = {
        "bpId": "139",
        "sessionId": "xm_leqnng8w237jib"
    }
    
    r = requests.get("https://mobile.ximalaya.com/captcha-web/check/slide/get",
                     headers=headers,
                     params=payload,
                     cookies=cookie)
    
    print(r.json())
    data = r.json()["data"]
    
    image_url_list = {"fg": data["fgUrl"], "bg": data["bgUrl"]}
    for k, v in image_url_list.items():
        rr = requests.get(v, headers=headers)
        with open(f"{k}.png", "wb") as f:
            f.write(rr.content)
    

    拿到底图后,我们就可以用验证码识别库,比如 ddddocr 。可以直接拿着原图识别,而不需要事先将滑块图片和底图缩小为原来的 0.8,然后将通过原图识别出来的距离缩小为原来的 0.8 倍即可。

    要注意这里有个小坑,captchaText 的 x 值时,你直接写这个识别出来的距离再乘上 0.8 是不行的,得加上一个偏移量,在 10 像素左右都行,至于偏移量的来源,我目前还没不知道。如果有知道的大佬,欢迎在评论区留言。

    0x4 captchaText 参数分析

    废话不多说,直接开始调试分析。我们需要定位到这个参数是如何生成的。我个人目前比较习惯直接通过请求的调用栈来做定位。点击 slider 请求,可以找到下图的方法中出现了我们想要分析的参数:

    我们可以看到这里的实参 o 是从外部传到方法中的,因此继续往上跟栈,一步步跟,最终可以找到 captchaText 参数的生成位置:

    captchaText 的生成规则如下:

    其中,c 值就是滑动滑块时鼠标在 y 方向的滑动距离,a 值则是滑动滑块时鼠标在 x 方向的滑动距离。d.ZOOM 则是图像的缩小比例。

    按照常规来说,直接传递 a 值和 c 值给网站后台即可通过滑块验证,但是网站前端在 getSliderLeft 方法中还对 a 值进行了一些额外的计算处理。

    getSliderLeft 方法如下,其中的计算逻辑复现很简单,因此就不细讲了:

    用 python 复现一下 getSliderLeft 方法,供大家参考:

    def get_img_left(t):
        return -12 * 0.8 + (t + 10) * (380 - 84.8 + 24 * 0.8) / (380 - 40)
    
    def get_slider_left(t):
        return int(get_img_left(t) / 0.8 + 44)
    

    最后贴上滑块验证的代码:

    def verify_slide():
        payload = {
            "bpId": "139",
            "sessionId": "xm_leqnng8w237jib"
        }
    
        r = requests.get("https://mobile.ximalaya.com/captcha-web/check/slide/get",
                         headers=headers,
                         params=payload,
                         cookies=cookie)
    
        print(r.json())
        data = r.json()["data"]
    
        image_url_list = {"fg": data["fgUrl"], "bg": data["bgUrl"]}
        for k, v in image_url_list.items():
            rr = requests.get(v, headers=headers)
            with open(f"{k}.png", "wb") as f:
                f.write(rr.content)
    
        det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
        with open('fg.png', 'rb') as f:
            fg_bytes = f.read()
        with open('bg.png', 'rb') as f:
            bg_bytes = f.read()
        res = det.slide_match(fg_bytes, bg_bytes, simple_target=True)
        print(res)
    
        def get_img_left(t):
            return -12 * 0.8 + (t + 10) * (380 - 84.8 + 24 * 0.8) / (380 - 40)
    
        def get_slider_left(t):
            return int(get_img_left(t) / 0.8 + 44)
    
        x = int((res["target"][0] + 25) * 0.8) 
        distance = int(get_slider_left(x))
        slide_payload = {
            "bpId": 139,
            "sessionId": "xm_leqnng8w237jib",
            "type": "slider",
            "captchaText": f'{distance},0',
            "startX": 563,
            "startY": 357,
            "startTime": int((time.time() - 2) * 1000)
        }
    
        print(slide_payload)
        slide_r = requests.post("https://mobile.ximalaya.com/captcha-web/valid/slider",
                                headers=headers,
                                cookies=cookie,
                                json=slide_payload)
    
        print(slide_r.text)
        print(slide_r.json()["token"])
    

    验证

    可以看到滑块验证通过,并且拿到了 token 值:

    相关文章

      网友评论

          本文标题:逆向万例| No.00001【滑块篇】喜某拉某web端登录滑块逆

          本文链接:https://www.haomeiwen.com/subject/cumeldtx.html