虚实相生------某网真假双滑块逆向分析

查看 24|回复 2
作者:buluo533   
在学习路上一直伴我逆向成长的某网(本来是个假滑块,最近更新了),现在变成真假双滑块了{:1_923:},都属于入门级的案例
食用地址(过期的链接都会弹出,不一定是这个,因为链接是动态更新的):
aHR0cHM6Ly9rbnMuY25raS5uZXQvdmVyaWZ5L2hvbWU/Y2FwdGNoYVR5cGU9YmxvY2tQdXp6bGUmaWRlbnQ9YmMzOTdjJmNhcHRjaGFJZD1lNGVkYzI0NS03NWYzLTRlNmMtYmUwYS0zMjYxNDI4MGYzMDQmcmV0dXJuVXJsPWlFQ0JEbmhyNzE2UWQ2cGJiN0VsMTBuZ3VQNVNibTlVUXhwenNZeFNBTS1KdVJlSUphalh0SHRBX0VkZXg0cWhpcnJIN0ZDUkNvb3ZaQXBrakFNbkxCRjZRMUEzNXk5WVNfUHBEVzZJeG11VWppTzJMeUFKUDJwY1VKMXhuSU1KSVBYOHhZZXVLSndmR3ZUQm1lM0VSWm01MF9IQm5STjhLVUx2ZW5wLTNCZ0pSVXJyN05BQ0pDNVl3azVqdXhILW1CVXVaQVBQMVVDTGRTQl9mN3V3ckxTd1JUQ3lmRnlSbGpjVEFYRXEzUHFQSVlmeWh5bjQ1V2tMWjJremloRWptWk5mUnJGUTk0RGhuX2k2c0oxTndEdlNXWE9iRWNRdE9sWDBkY3M2NlllRnpkeUhQbXpBa29lcVdIVmRhS3lIN3RiZmsySTJJRnNEdmZiWXJ3YnJLT2hlWjh3THlxWnNucFZkRGs2N1hqc1poOWphSHZoOE5nNXUzU1JOZjVCcw==
一、流程分析   
                     
                     


image.png (32.87 KB, 下载次数: 0)
下载附件
请求接口
2025-7-5 15:02 上传

                      比较简单的一个流程,直接看一下具体的返回参数信息,怎么去获取和使用的
                    


image.png (30.39 KB, 下载次数: 0)
下载附件
前置负载
2025-7-5 15:06 上传

                     


image.png (56.12 KB, 下载次数: 0)
下载附件
前置请求返回值
2025-7-5 15:06 上传

                     可以明显地看到两个图片地址写着base64,说明要用base64进行编码处理后存储。剩下的就是token和
[color=]secretKey,
多次请求查看具体哪些内容是动态变化的,可以看到前置请求时固定的,只有一个ts时间戳在变化的


      
token和
[color=]secretKey
也是动态返回的内容


         



image.png (31.07 KB, 下载次数: 0)
下载附件
校验接口负载
2025-7-5 15:10 上传

                      很熟悉的有一个值就是token,剩下的有点不是很熟悉,感觉前两个是定值,我们直接跟栈来看看情况,刷新下断点
                  


image.png (65.07 KB, 下载次数: 0)
下载附件
某网断点
2025-7-5 15:21 上传

                     


image.png (109.35 KB, 下载次数: 0)
下载附件
某网加密参数
2025-7-5 15:22 上传

                   跟栈到这里就会发现很明显的参数,偷懒的也可以直接搜:keai这样我们来做参数逆向和python还原
二、加密参数分析与还原
          经过分析我们知道需要处理的参数,先简单处理一下前置请求的内容                                                            
import requests
import time
import base64
import ddddocr
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
def main():
       cookies = {
    }
    headers = {
    }
    json_data = {
        'captchaType': 'blockPuzzle',
        'clientUid': 'a91a6829f4537dd20eb15da3781158f2',
        'ident': 'bc397c',
        'captchaId': 'e4edc245-75f3-4e6c-be0a-32614280f304',
        'ts': time.time() * 1000,
    }
    response = requests.post('脱敏处理', cookies=cookies, headers=headers,
                             json=json_data).json()
    res = response['data']
    secretKey = res['secretKey']
    token = res['token']
    jigsawImageBase64 = res['jigsawImageBase64']
    originalImageBase64 = res['originalImageBase64']
    gap_pic = base64.b64decode(jigsawImageBase64)
    bg_pic = base64.b64decode(originalImageBase64)
    with open('gap.jpg', 'wb') as f:
        f.write(gap_pic)
    with open('bg.jpg', 'wb') as f:
        f.write(bg_pic)
    det = ddddocr.DdddOcr(det=False, ocr=True, show_ad=False)
    with open('gap.jpg', 'rb') as f:
        target_bytes = f.read()
    with open('bg.jpg', 'rb') as f:
        background_bytes = f.read()
    rest = det.slide_match(target_bytes, background_bytes, simple_target=True)
    value = rest['target'][0]
    print(rest)
    print('识别到距离', value)
                       这样我们搞定了前置请求,获取到需要的内容,存储到了图片,用ddddocr获取滑块的距离
                       


image.png (108.52 KB, 下载次数: 0)
下载附件
背景图
2025-7-5 15:50 上传

                     


image.png (13.39 KB, 下载次数: 0)
下载附件
滑块图
2025-7-5 15:50 上传

                  


image.png (31.89 KB, 下载次数: 0)
下载附件
识别距离
2025-7-5 15:52 上传

             有了这些前提,我们来搞定后面的加密参数,先看看哪些内容是固定的,哪些是变化的
           


image.png (22.92 KB, 下载次数: 0)
下载附件
加密参数位置
2025-7-5 15:35 上传

             还是挺明显的,都是在this里面,可以肯定的是pointjson是通过函数f实现的加密
          var e = parseInt((this.moveBlockLeft || "").replace("px", ""));
e = 310 * e / parseInt(this.setSize.imgWidth);
            


image.png (30.17 KB, 下载次数: 0)
下载附件
滑动距离
2025-7-5 16:00 上传

             这里的e应该是一个简单的滑动距离做了取整的处理,接下来就是用f进行加密,同时传入了两个参数,一个是序列化后的x和y,然后是动态的密钥,是前置接口的返回值
         


image.png (27.25 KB, 下载次数: 0)
下载附件
aes
2025-7-5 16:03 上传

           很熟悉的一个加密,aes,ecb,都是熟悉的词汇(有不熟悉小伙伴可以看看密码学文章,前几篇帖子中都有直达链接,可以读一下),非常标准的加密,我们先用固定值测试一下结果。
       def aesEncrypt(plaintext, aes_key):
    if isinstance(plaintext, str):
        plaintext = plaintext.encode('utf-8')
    if isinstance(aes_key, str):
        aes_key = aes_key.encode('utf-8')
    cipher = Cipher(algorithms.AES(aes_key), modes.ECB(), backend=default_backend())
    encryptor = cipher.encryptor()
    padder = padding.PKCS7(128).padder()
    padded_data = padder.update(plaintext) + padder.finalize()
    ciphertext = encryptor.update(padded_data) + encryptor.finalize()
    return base64.b64encode(ciphertext).decode('utf-8')
function f (t, e="XwKsGlMcdPMEhR1B") {
            var n = l().enc.Utf8.parse(e)
              , r = l().enc.Utf8.parse(t)
              , i = l().AES.encrypt(r, n, {
                mode: l().mode.ECB,
                padding: l().pad.Pkcs7
            });
            return i.toString()
        }
              


image.png (13.3 KB, 下载次数: 0)
下载附件
加密值对照
2025-7-5 16:08 上传


         
            
     非常完美,搞定了这个加密参数,接下来看看其他的,还是多抓包分析看看哪些是不变的,要注意的是 returnUrl参数,我们搜索一下,因为他在this里面,不熟悉的大佬可以补补js基础
        


image.png (29 KB, 下载次数: 0)
下载附件
retrunurl
2025-7-5 16:12 上传

             在这里看看下一个断点,重新刷新,他的操作大概就是先获取网站的链接,然后再通过k函数处理后赋值给e,进去看看k是怎么个事儿
         


image.png (24.95 KB, 下载次数: 0)
下载附件
k函数
2025-7-5 16:14 上传

            


image.png (37.63 KB, 下载次数: 0)
下载附件
裁剪拼接
2025-7-5 16:15 上传

              很明显是一个分割重组的过程,很多参数就是来自于这里,说明这个也是动态变化的,只是相对于我们这次分析是静态的内容,可以简单复现一下
            def k(t):
    e = []
    n = 0
    r = {}
    i = t.find("?")
    t = t[i + 1:]
    e = t.split("&")
    n = len(e)
    for o in range(n):
        parts = e[o].split("=", 1)
        if len(parts) > 1:
            r[parts[0]] = parts[1]
        else:
            r[parts[0]] = ''
    return r
             这样我们就是实现了完整的第一次真实滑块的任务,完善一下代码内容:
         def check(token, point_json):
    json_data = {
        'captchaType': 'blockPuzzle',
        'pointJson': point_json,
        'token': token,
        'ident': 'bc397c',
        'returnUrl': '自行修改'
    }
    response = requests.post('脱敏处理', cookies=cookies, headers=headers,
                             json=json_data).text
            


image.png (369.65 KB, 下载次数: 0)
下载附件
真实滑块结果
2025-7-5 16:20 上传

三、二次滑块分析与绕过
          所谓虚实相生,真的里面有假的,当我们点开这个返回值中的链接,惊喜的发现又是一个滑块,惊不惊喜,意不意外;www
         


image.png (1.15 MB, 下载次数: 0)
下载附件
假滑块
2025-7-5 16:23 上传

           大大的一个滑块,流程还在上面,我们再来一次检测一下。
         


image.png (43.49 KB, 下载次数: 0)
下载附件
滑动测试
2025-7-5 16:26 上传

            我勒个豆啊,没一点反应,就一直加载图片信息,有点恶心了,这样我可以猜测一下,有没有可能是cookie加密,或者是前端,但是为啥没有检验呢获取请求信息呢?查一下网页的源码.
        


image.png (111.32 KB, 下载次数: 0)
下载附件
源码
2025-7-5 16:32 上传

             大佬们可以自行阅读一下,我js也比较菜,大致我们可以分析出所有的操作都是在前端实现的,没有后端参与,说明什么,这是可以绕过的啊。我们让他滑动正确看看是什么情况(注意看包的加载,最好是借助抓包工具),我选择下一个xhr断点,当我们滑动正确时他断住了,我们往上跟一下看看
         


image.png (125.97 KB, 下载次数: 0)
下载附件
xhr
2025-7-5 16:39 上传

         


image.png (25.78 KB, 下载次数: 0)
下载附件
取值
2025-7-5 16:40 上传

        


image.png (32.11 KB, 下载次数: 0)
下载附件
元素
2025-7-5 16:40 上传

            好家伙灯下黑,就在这里,取了一个id为v-value的属性的值,然后做一个拼接跳转。{:1_918:}
四、总结
         入门级的网站大佬们可以玩玩,非常感谢我的小伙伴们@littlewhite11 ,还有几个偷着卷找不到{:1_932:},拓展了思路的滑块,绕过后面的步骤就是元素定位以及获取返回值,可以自行尝试,大佬们冲冲冲{:1_918:}

      
        

下载次数, 下载附件

zzyzy   

向大佬学习
buluo533
OP
  


zzyzy 发表于 2025-7-5 19:26
向大佬学习

太谦虚了,佬
您需要登录后才可以回帖 登录 | 立即注册

返回顶部