29

JS逆向-某娱乐指数加密逻辑分析

 3 years ago
source link: http://xianyucoder.cn/2020/02/28/每日JS-娱乐指数-AES/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

AES 的案例之前有推荐大家关于 AES 加密的案例文章,不少朋友问我加密解决了有什么用?

最大的用途当然就是不用模拟请求,大大提高了爬取效率。

可能之前举例都是使用的 AES 加密的密码,所以不少朋友只关注了加密没注意实现后的用途,所以这次再写一个其他的 AES 加密作为示例。

这个例子来自 JS 逆向课程的预售群,偶然看到有群友提问,这里简单分析一下。

分析加密

抓包可以看到这里 data 部分是加密的。【图1-1】

rmMby2V.png!mobile

直接搜索 data 这个加密参数可以看到有很多的相关项【图1-2】

fiAJRbF.png!mobile

那么如何快速定位这个加密内容解密的地方呢?

我们把请求返回的内容先美化一下,看看有没有什么点可以追踪一下。

可以看到在返回内容里和加密相关的字段有一个 isEncrypt 通过参数的名字我们可以猜测这个字段是用来标识内容是否加密。【图1-3】

UjMjaam.png!mobile

我们检索这个字段看看有什么样的结果。【图1-4】

n6FzErJ.png!mobile

可以看到只有两个相关的内容,我们在第一个找到了解密相关的内容。【图1-5】

7fq63ea.png!mobile

接下来就可以参考我前面的文章套路直接把关键的解密代码套进去就可以解密了。

可以直接套用 JS 的解密代码,也可以参考我们文章举例的 Python 代码

Python 复写加密

我们先把上次的 Python 代码 CV 过来。

import base64
from Crypto.Cipher import AES
import random


def pkcs7padding(text):
    """
    明文使用PKCS7填充
    最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理
    :param text: 待加密内容(明文)
    :return:
    """
    bs = AES.block_size  # 16
    length = len(text)
    bytes_length = len(bytes(text, encoding='utf-8'))
    # tips:utf-8编码时,英文占1个byte,而中文占3个byte
    padding_size = length if(bytes_length == length) else bytes_length
    padding = bs - padding_size % bs
    # tips:chr(padding)看与其它语言的约定,有的会使用'\0'
    padding_text = chr(padding) * padding
    return text + padding_text


def pkcs7unpadding(text):
    """
    处理使用PKCS7填充过的数据
    :param text: 解密后的字符串
    :return:
    """
    length = len(text)
    unpadding = ord(text[length-1])
    return text[0:length-unpadding]


def encrypt(key, content):
    """
    AES加密
    key,iv使用同一个
    模式cbc
    填充pkcs7
    :param key: 密钥
    :param content: 加密内容
    :return:
    """
    key_bytes = bytes(key, encoding='utf-8')
    iv = key_bytes
    cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
    # 处理明文
    content_padding = pkcs7padding(content)
    # 加密
    encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8'))
    # 重新编码
    result = str(base64.b64encode(encrypt_bytes), encoding='utf-8')
    return result


def decrypt(key, content):
    """
    AES解密
     key,iv使用同一个
    模式cbc
    去填充pkcs7
    :param key:
    :param content:
    :return:
    """
    key_bytes = bytes(key, encoding='utf-8')
    iv = key_bytes
    cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
    # base64解码
    encrypt_bytes = base64.b64decode(content)
    # 解密
    decrypt_bytes = cipher.decrypt(encrypt_bytes)
    # 重新编码
    result = str(decrypt_bytes, encoding='utf-8')
    # 去除填充内容
    result = pkcs7unpadding(result)
    return result


def get_key(n):
    """
    获取密钥 n 密钥长度
    :return:
    """
    c_length = int(n)
    source = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
    length = len(source) - 1
    result = ''
    for i in range(c_length):
        result += source[random.randint(0, length)]
    return result

按照代码上的注释,我们找找这里我们 key 和 iv 是怎么生成的。【图2-1】

2aQ7Nj.png!mobile

参考【图1-3】这个 lastFetchTime 就是请求返回的值。

所以我们按照 JS 逻辑直接把加密内容和 key 传入即可。

data = 'WPZVRdF+hMHReWs0rgM+SR+uV3TjVPhsVKOCrW+cOF8jfhT/JL/faU3tYyBVPkyJsV+P6ReJ46/Pi0...'
encrypt_en = decrypt('1572353144793000',data)
print(encrypt_en)

解密的结果如下:【图2-2】

Avmamy7.png!mobile

以上就是 AES 加密的另一种在爬虫中的运用了。

EOF


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK