吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2453|回复: 22
上一主题 下一主题
收起左侧

[Web逆向] 乐某自研滑块逆向分析

  [复制链接]
跳转到指定楼层
楼主
buluo533 发表于 2025-6-20 22:04 回帖奖励
本帖最后由 buluo533 于 2025-6-21 09:16 编辑

接单遇到一个网站,发现登陆有个中等难度的滑块,话不多说。直接干:aHR0cHM6Ly93d3cubG9mdGVyLmNvbS9mcm9udC9sb2dpbi8=
                                                      

食用前提:
(1)python基础(python复现代码)
(2)js基础(看懂js加密逻辑)
(3)密码学基础(涉及sha256,aes,rsa,base64)
密码学学习文章:密码学常用基本数据类型和运算在不同语言当中的体现------aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3MvdFg2V3NFdHNic2FvOUtiUlFwZXJIQQ==
sha256:一文读懂SHA-2-------aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3MvUG5ScHJNc01vM3VxUG5JQ25KQlUzZw==
base64:一文读懂Base64-------aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3MvSVpjOVJIakxSZmJzQzhibDNUR3FIUQ==
aes:分析crypto-js当中AES的实现----aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3MvRlBjUzlvRUQ5UHFDOV9nLXpmTEhqUQ==
rsa: 加密的诗篇:RSA与Padding技术的艺术融合------aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3MvaU0xS1lldy13R1VORXBwWk1YTG5vdw==
RSA当中整数的表示方法 ------aHR0cHM6Ly9tcC53ZWl4aW4ucXEuY29tL3MvMWhQN090RUNOV2VqN2Vpd3RReExMQQ==
                        
经历过一次滑块(如果没有可以看我之前的文章),我们简单先整理一下处理滑块的思路
(1)一般的滑块最开始肯定要先加载图片的的地址,拿到图片信息用于后续的距离或者轨迹,同时可能包含后续会用的加密参数
(2)分析滑块的加密逻辑,根据上一次的经验,加密参数请求会返回值用于登录
(3) 整理返回的加密信息,完成登录


一、流程分析

        我们直接输入好账号密码,可以看到返回两个接口信息,第一个是登录的验证,第二个就是返回的图片信息(大胆假设,小心求证),我们先看一下,因为没有下断点,图片信息肯定也加载出来了,对比一下
            
           

        大致看一下,大概是一个是底图,一个是滑块的图片,有一个id,一个type(大概就是类似版本号的东西),
         
               
               
       很明显发现了端倪,返回值确实是图片地址,可以看出协议的信息data:image/png;base64,   说明可以通过base64编码读取图片信息,从而保存底图和滑块,id可以暂时留着,没看出来用处。
      这个的滑块和之前的有点差别,点击的的登录后加载的。
            
        
     可以看到我们的密码被加密了一次,同时呢,返回值是提示要求验证码进行校验,可以猜一下,大概是通过登录拿到cookie再去请求图片信息,这样再去通过滑块的验证,保险起见,可以测试,所以我们要先处理密码的加密方式
     接下来我们滑动一下看看情况.
      
            我们滑动测试一下发现,有一个校验的接口,接下来因为错误就重新加载了图片信息,看一下校验接口是怎么校验的信息。
                     
                    
                    
               
                 我勒个豆,还是挺多的三个加密点要处理,应该就是直接从这里返回值看看有没有成功,但是都是加密后的结果
                  


二、加密定位与还原
               1、登录接口,密码加密
     对密码的调用栈直接下断点,重新输入账号密码跟栈(上一篇文章有详细的跟栈思路)
            
            
           到这里我们可以明显地看到密码的加密逻辑,我们直接用标准的来进行测试然后用python还原
         
        还是很明显的一致,接下来用python还原登录
      
[Python] 纯文本查看 复制代码
from hashlib import sha256

def sha256_password(text):
    return sha256(text.encode('utf-8')).hexdigest()
              


         接下来实现登录的逻辑
[Python] 纯文本查看 复制代码
import time
def log_in(pass_word):
    time_temp = int(time.time() * 1000)
    passport = sha256_password(pass_word)
    cookies = {
    }

    headers = {
    }

    params = {
        'product': 'lofter-pc',
        '_': time_temp,
    }

    data = {
        'phone': '脱敏处理',
        'passport': passport,
        'type': '0',
        'clientType': '0',
        'deviceType': '3',
        'Target': 'www.lofter.com',
    }

    response = session.post('脱敏处理', params=params, cookies=cookies, headers=headers,
                            data=data).json()



   2、图片请求地址与距离识别
   
[Python] 纯文本查看 复制代码
def get_pic():
    cookies = {}

    headers = {}

    params = {
        'type': 'jigsaw',
    }

    response = session.get('脱敏处理', params=params, cookies=cookies,
                           headers=headers).json()
    pic_id = response['data']['id']
    pic_gap = response['data']['front']
    pic_bg = response['data']['bg']
    gap_pic = base64.b64decode(pic_gap)
    bg_pic = base64.b64decode(pic_bg)
    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()
    res = det.slide_match(target_bytes, background_bytes, simple_target=True)
    value = res['target'][0]
    print('识别到距离', value)
    return pic_id, value

    这一部分逻辑就很简单了,主要就是要理解他是怎么产生的,看懂协议,用base64编码后直接读取保存下来
   
     
  提取出图片之后直接用ddddocr识别到距离。


    3、滑块加密逻辑还原
           还是一样的
      
         
      
    这个跟栈也是非常的简单,核心是他的加密算法逻辑,命名非常的直接,我们明显看出的是aes和base64,这就要大佬们读读密码学的文章,方便后续的分析
     
     直接进到aes里面,先看一下传入的参数有哪些,很明显,我们之前请求剩下的id有用了,然后就是一个距离,我们通过ddddocr已经搞定了,这样的话我们就知道这个接口的请求体就是一个图片接口返回的id和一个距离
     

    同时我们可以看到iv,padding,key这些非常关键的参数,但是这个又有些不同寻常,我们经常看到的加密一般是这样的写的(举个例子)
   
[JavaScript] 纯文本查看 复制代码
let key = crypto.enc.Utf8.parse('key');
let iv = crypto.enc.Utf8.parse('iv' );
function aesEncrypt(plaintext) {
    let encrypted = crypto.AES.encrypt(
        crypto.enc.Utf8.parse(plaintext),
        key,
        {
            iv: iv,
            mode: crypto.mode.CBC,
            padding: crypto.pad.Pkcs7
        }
    );
    return encrypted.toString(); 
}

   但是这次很明显有一些不同,我们继续跟进encrprt的逻辑中进行分析

  继续进去
           
    这里我们能看到大概的逻辑了,就是一个非常明确的aes加密的逻辑,这里是一些初始化的操作。然后回到梦开始的地方,因为现在函数里面的内容都是在最开始传进来的
   
    其实我们稍微往上看一点就看到了key和iv随机生成的一个位置,随机生成的代码也清晰可见了
[JavaScript] 纯文本查看 复制代码
getRandomString = function(t) {
                for (var e = "", n = 0; n < t; n++)
                    e += Math.round(Math.random()) ? Math.floor(9 * Math.random()) : String.fromCharCode(Math.floor(25 * Math.random() + 97));
                return e
            }

    我们直接python还原一手,暂时没看到其他参数值的赋值,先写成16位
[Python] 纯文本查看 复制代码
import random
def getRandomString(t=16):
    s = ""
    for _ in range(t):
        if random.randint(0, 1):
            s += str(int(9 * random.random()))
        else: 
            s += chr(int(25 * random.random()) + 97)
    return s

接下来就是看看padding和加密模式,常见的有iv的就是CBC(不懂的还是建议补一补密码学基础),我们直接猜一下,也可以翻翻源码,也有惊喜的发现(我刚开始确实不是很熟悉这个,所以也是这样找到的,半猜半蒙)
  
   这样有了padding和加密模式,这样我们先用js还原一下测试一下,再用python来复现
            
        
      
     非常完美!!!一模一样,接下是python的还原,众所周知,crypto.enc.Utf8.parse(iv)在python中等价于iv.encode('utf-8')(不懂的还是密码学基础)
     这样我们继续还原
     
[Python] 纯文本查看 复制代码
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modesfrom cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.padding import PKCS7

def aesEncrypt(plaintext, aes_iv, aes_key):
    if isinstance(aes_iv, str):
        aes_iv = aes_iv.encode('utf-8')
    if isinstance(aes_key, str):
        aes_key = aes_key.encode('utf-8')
    cipher = Cipher(algorithms.AES(aes_key), modes.CBC(aes_iv), backend=default_backend())
    encryptor = cipher.encryptor()
    padder = padding.PKCS7(128).padder()
    padded_data = padder.update(plaintext.encode('utf-8')) + padder.finalize()
    ciphertext = encryptor.update(padded_data) + encryptor.finalize()
    return base64.b64encode(ciphertext).decode('utf-8')


     试试加密结果对照
     
    非常ok的搞定了,接下来就是base64编码的操作了
      
      
   至于怎么看出来的一个是js中的atob和btoa,以及密码学常用基本数据类型和运算在不同语言当中的体现(q佬文章),下一个就是对请求头参数的处理


4、请求头加密参数处理
     
    还是老规矩,跟进去看看
   
   这个还是很明显,一个公钥,加密内容是aes的key拼接一个-和iv,接下可以简单看一下rsa算法(求助过q佬,rsa的魔改点很少),可以简单结合文章和源码了解一下rsa
        
        
    很标准的rsa算法,大数组,我们找一下公钥,然后用python还原
   
   
  经常加密的大佬应该知道rsa以pem的格式存储公钥
   
[Python] 纯文本查看 复制代码
from Crypto.PublicKey import RSAfrom Crypto.Cipher import  PKCS1_v1_5

def x_encseckey_get(rsa_iv, rsa_key):
    with open('public.pem', 'r') as f:
        public_key = f.read()
    datas = key + "-" + iv
    text = datas.encode('utf-8')
    pk = RSA.importKey(public_key)
    cipher = PKCS1_v1_5.new(pk)
    cipher_text = cipher.encrypt(text)
    cipher_text_base64 = base64.b64encode(cipher_text).decode('utf-8')
    return cipher_text_base64

   我们的生成是没有问题的,这个可能不好检测,但是可以通过生成公私钥对来测试加密情况,方便检验rsa的效果
5.返回值参数解密算法分析
   
    我们可以看到,在对接口请求之后,就开始处理返回值的信息了,熟悉js的伙伴都知道,js请求都是异步操作,这也加大了还原的难度还有一个默认的arrayBuffer()函数,我们可以去js官方文档查查成分
   官方网址:
https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Getting_started/Your_first_website/Adding_interactivity

   
    也就是将返回值转化为二进制
   
   将断点到异步执行后后查看t的值
   
    这部分对应python的实现还是可以参考文章内容
   
[Python] 纯文本查看 复制代码
def array_buffer_to_base64(buffer):
    if isinstance(buffer, list):
        data = bytes(buffer)
    elif isinstance(buffer, bytearray):
        data = bytes(buffer)
    else:
        # 直接使用 bytes 对象
        data = buffer.encode('utf-8')

    return base64.b64encode(data).decode('utf-8')


def base64_to_array_buffer(base64_str):
    decoded_data = base64.b64decode(base64_str)
    return decoded_data

    接下来就是跟进去对t的一个处理逻辑
   
   嘎嘎熟悉的一个base64操作,btoa
    接下来就是通过aes进行的一个解密操作
   

   这里需要主义的就是n.parse和之前的s.parse不一样,我们可以跟进去看一下
   
   还是一个base64的运算操作,然后就是很常规的解密操作,key和iv都是之前生成的,以及s.parse的操作分析,接下里是一个base64decoed的函数操作,依旧跟进去看看
   
  
  
   我们可以看到w函数的位置,以及整个的调用逻辑(不清楚w是函数的可以看看js基础语法,箭头函数),这个能看出来或者借助ai工具能分析出来是一个base64的操作
   
  我们可以看到最后结果应该是这样子的,整体来说返回值是一个base64+aes解密过程,之前代码和思路很清晰了,大佬们可以尝试一下还原,评论区晒晒成果


三、总结
这段时间狠狠地研究和回顾了一下学习的过程,刚开始看到这个网站的时候以为很简单,后面越做越难受,发现还是对密码学理解太浅,在拷打ai和q佬的指导下也算是搞定了,狠狠地补了一下密码学。这一个滑块总的来说还是很有研究的价值,很多js的语法特性与密码学的结合,以及不同语言之前的特性糅合,适合进阶的小伙伴食用。我也可以安心去准备期末考试了,我还要肝下一篇ast


免费评分

参与人数 9吾爱币 +9 热心值 +8 收起 理由
MissJz + 1 + 1
不吃喵粮 + 1 + 1 热心回复!
AjiaJiShu + 1 + 1 我很赞同!
ImpJ + 1 + 1 谢谢@Thanks!
AdAStra + 1 + 1 我很赞同!
timeni + 1 + 1 用心讨论,共获提升!
抱歉、 + 1 用心讨论,共获提升!
liuxuming3303 + 1 + 1 谢谢@Thanks!
grekevin + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
ragkan 发表于 2025-6-20 22:59
NB,看着很强哟~~~
3#
Yifan2007 发表于 2025-6-20 23:59
你这js逆向成本太大了,这么正的图直接图色解决不省时间吗
4#
lqinyli 发表于 2025-6-21 00:24
5#
fanqie8 发表于 2025-6-21 06:32
牛,分析的真好,能学到不少知识
6#
 楼主| buluo533 发表于 2025-6-21 07:37 |楼主
Yifan2007 发表于 2025-6-20 23:59
你这js逆向成本太大了,这么正的图直接图色解决不省时间吗

自动化的速度相对来说太慢了 不符合企业的要求
7#
GJH588 发表于 2025-6-21 09:29
教程很详细,值得一看
8#
zhangshibo 发表于 2025-6-21 19:56
色弱特殊染色染
9#
异常马粥 发表于 2025-6-23 09:54
很好的一个了解密码学的教材。
10#
Pablo 发表于 2025-6-23 12:55
写的很好
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-7-20 20:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表