阿里140-n值纯算

阿里140-n值纯算

前情提要

本章是继阿里140-语雀逆向分析的后续文章,主要介绍如何去纯算生成n值

n值的加密算法

加密前原始数据

bash 复制代码
加密的原始数据是一个庞大的数组
类似如下
[205,244,2,243,247,30,0,4,215,236,0,140,40,15,208,43,158,227,227,208,3,29,82,138,131,18,179,244,53,102,58,60,81,4,251,251,165,60,34,199,151,76,103,74,141,69,236,48,214,199,169,108,236,43,14,130,155,155,0,1,202,233,116,128,207,206,0,1,184,7,205,241,155,154,0,1,48,48,201,201,155,155,1,1,254,53,200,204,152,153,0,255,48,49,201,200,154,195,1,37,120,218,251,77,145,19,63,145,194,153,46,51,56,65,126,161,97,192,246,195,228,214,126,243,177,237,69,107,245,176,119,227,134,46,79,213,7,154,204,167,197,157,161,85,9,228,92,212,21,226,52,210,100,195,12,143,55,60,159,87,104,127,244,237,131,136,59,3,80,152,31,50,101,70,178,79,42,152,79,176,1,197,121,34,238,123,202,21,98,254,61,68,241,61,15,8,224,216,179,42,175,83,249,199,159,93,21,120,236,250,4,171,60,161,249,54,89,222,192,227,95,7,81,112,26,212,240,175,157,62,167,250,2,196,121,176,45,224,83,127,249,136,172,88,218,255,189,69,16,131,219,21,101,182,55,18,167,150,96,23,38,34,81,73,132,209,94,50,231,23,28,11,37,50,95,54,125,209,26,28,118,228,45,255,117,144,20,106,125,162,194,235,155,237,215,3,115,206,201,37,64,63,94,228,96,29,48,12,147,221,241,21,89,230,242,92,196,10,52,13,130,230,102,149,87,148,115,94,176,117,201,99,17,100,23,55,159,165,27,198,157,119,161,144,102,147,124,174,222,12,94,31,150,112,159,230,191,95,8,127,117,36,97,114,47,117,157,214,101,148,213,137,78,246,18,64,25,116,70,246,129,73,237,11,225,183,37,238,191,164,214,22,96,130,195,202,176,51,59,107,127,118,97,130,160,220,46,109,33,178,212,25,0,38,86,4,210,102,30,85,229,168,198,122,48,231,216,16,33,226,30,88,21,180,101,72,175,104,187,118,191,47,199,61,191,164,114,2,223,219,78,109,108,243,233,35,143,251,194,199,185,9,69,30,3,70,202,47,157,188,11,234,147,196,246,139,206,112,31,90,140,239,219,145,215,38,54,188,41,74,119,124,103,150,8,93,198,143,109,15,155,217,205,55,43,10,85,210,213,58,139,12,9,13,60,231,117,20,74,224,208,184,196,245,77,135,63,139,99,68,113,53,146,125,80,63,248,94,197,169,120,67,106,109,164,130,190,218,11,32,23,73,82,152,19,64,120,168,204,34,140,97,132,100,53,19,214,214,31,105,30,240,75,237,11,134,105,53,234,132,159,136,174,106,121,128,156,108,208,98,163,236,23,105,9,158,209,252,230,145,59,121,234,120,160,20,95,38,154,2,121,26,183,197,54,230,18,35,89,240,31,177,121,14,75,136,220,92,53,215,46,6,74,88,163,103,227,175,164,146,64,178,248,82,31,153,121,123,162,160,150,147,120,87,104,114,9,199,66,245,52,177,187,225,89,106,217,70,71,178,128,251,162,74,19,141,14,4,155,169,7,39,60,117,222,221,35,231,13,132,136,77,157,43,46,215,230,118,122,150,64,199,178,113,238,206,232,130,17,45,100,165,12,57,232,27,226,62,55,114,248,227,236,105,66,181,146,137,127,52,149,214,104,80,142,23,235,91,70,153,242,246,135,93,105,190,70,108,79,101,70,19,5,113,164,122,4,242,101,91,101,37,11,217,241,248,130]

自定义字符集

n值的加密算法是自定义base64加密,它的自定义字符如下图所示

Python实现

python 复制代码
def serialize_array_to_bytes(number_array: list[int]) -> bytes:
    byte_stream = bytearray()

    for num in number_array:
        if num < 0:
            num = 0

        if 0 <= num <= 255:
            byte_stream.append(num)
        else:
            num_bytes_needed = (num.bit_length() + 7) // 8
            byte_stream.extend(num.to_bytes(num_bytes_needed, 'big'))

    return bytes(byte_stream)
def custom_base64_encode(data: bytes) -> str:
    ALPHABET = "zxoDrdnc+34K2LmHFZWPfACwut/qXRBjQ5E8MelUT6gk1GhYbiVISyv0spJNO97a="
    PADDING_CHAR = "="

    encoded_chars = []
    data_len = len(data)

    for i in range(0, data_len, 3):
        chunk = data[i: i + 3]

        byte1 = chunk[0]
        byte2 = chunk[1] if len(chunk) > 1 else 0
        byte3 = chunk[2] if len(chunk) > 2 else 0

        index1 = byte1 >> 2
        index2 = ((byte1 & 3) << 4) | (byte2 >> 4)
        index3 = ((byte2 & 15) << 2) | (byte3 >> 6)
        index4 = byte3 & 63

        encoded_chars.append(ALPHABET[index1])
        encoded_chars.append(ALPHABET[index2])

        if len(chunk) > 1:
            encoded_chars.append(ALPHABET[index3])
        else:
            encoded_chars.append(PADDING_CHAR)

        if len(chunk) > 2:
            encoded_chars.append(ALPHABET[index4])
        else:
            encoded_chars.append(PADDING_CHAR)

    return "".join(encoded_chars)

加密后的结果

bash 复制代码
上述算法加密后的结果类似如下
GoMrxXpDzzFSNQo23FJb4pN8s9zre5V9bvK+e5orzYDeqgbzA29KXWbq7bMdVbp403TGDTgqlbzxVQSHbRUuzFcThODOlpTzzPzbVXlqlbrxImM96tluxz+bKOU+l61zlFZljwsQPtrPHpcolWsmzXRsU6hp3CUvHN8jKG0PbuJ8mlLmmaFblsQ+17GMfwEWjIKPRPsQMNTclve9IdGx03YFhh8xwLT/jgWyCaFQx4a16dN4lKdZCw/J+ve4eQHKsh7rBulISnmarRoOsChSXxzXuLivKtV92oYNbl9hO0baXxy6rg+H7fX838GMuMHrWNbBszgUmpGUdEyBD7r2Ly8EOjmrRNl2YpOSEtrbN8PgwaU15FIkLKb+jVeauJoI/NQsR70+Fw/7HM7hntM/2edyttbJ9niEQBoiQRYP2xNC0yfbPDOLLz9lLQPc57HdSrUzpkRTORZb1rioR9GcjXcC71PYKRxp+8C3IC2iQDIg33w90v3EZzo5nGhUx8MFQ5nXCkBWZcdjttKnB3W7jqH0uljGvqLp4mVHgv0yw2MNkNxmPgaygGvYeAd93VIp/WtrzMde9oAjpJ0SZpvt59xUlWSTAt5lP9D1nTrnKrsywjpf5HdVw2VE0E54GTIbPQKyv0AJ8dc7bMO2tMB3PgcyOwHeXPOApWJs6ZBu1RRvJ2ad5kijoxX+ktcmFttLflGtvW/rNJzrJydNTzm6CzKbq07/+b3nXnUTop9vnGYghqxWdv6S4RTIz80Zvs6DNAa38zehpPdZw8CMioUJDNdoazcnmtgqGbqN4+UGNkT8rgcc07v/9EIXvGTGMmhm4f2zyCcE5aDR5rEfzvS17o3zHyNMuxSvUW6KJgLbzIa+KvBFmPyej4i3xN4p3iLIuuMeAsEmgVpq4qMD6hIdf7g1pjjqqqo5BYOj7hPDPJoLeyrIMyfiDjHT+xQ+w48PaXxnp1V0r5gnZL1X/YC2eXVCM1Pi8VNp+wD0HDsGgSA1DYAtBNK6kwBEKTb/CuviyLoRpObKkxa0pz7tCMXtWtNKzNDZlf5JsUQ6CCeGUn3zULo1xEYF2+bogbvREeNRUMdNJf5OM6i4OH5DUORWuRG3NMSfCAnfZLQe9afYM5hfI9Zfw1S3TtAmAvB3kHFrMcWeHwbtvNCmRA5bdhuCLEAZyBO92H8VQep3TjBACEzppE4AnQQ7vZ/d9nu7Ak72R+29pDx+OoT1kHOG7U4wicOC9rdyVZvlztPr7U3RbvAG16HN01voJJWEPD653RKyLXvH0HlglFDk6BMPZr96XjoC9yOApYSX3e08VtSiQVnPm12jZoP4+eXft+KVaKU4ha+y956aC7zaxt0DWgod9LsJx2hjDNgc65Zygwfcq4+5
但是注意,要拼接140#
也就是
140#GoMrxXpDzzFSNQo23FJb4pN8s9zre5V9bvK+e5orzYDeqgbzA29KXWbq7bMdVbp403TGDTgqlbzxVQSHbRUuzFcThODOlpTzzPzbVXlqlbrxImM96tluxz+bKOU+l61zlFZljwsQPtrPHpcolWsmzXRsU6hp3CUvHN8jKG0PbuJ8mlLmmaFblsQ+17GMfwEWjIKPRPsQMNTclve9IdGx03YFhh8xwLT/jgWyCaFQx4a16dN4lKdZCw/J+ve4eQHKsh7rBulISnmarRoOsChSXxzXuLivKtV92oYNbl9hO0baXxy6rg+H7fX838GMuMHrWNbBszgUmpGUdEyBD7r2Ly8EOjmrRNl2YpOSEtrbN8PgwaU15FIkLKb+jVeauJoI/NQsR70+Fw/7HM7hntM/2edyttbJ9niEQBoiQRYP2xNC0yfbPDOLLz9lLQPc57HdSrUzpkRTORZb1rioR9GcjXcC71PYKRxp+8C3IC2iQDIg33w90v3EZzo5nGhUx8MFQ5nXCkBWZcdjttKnB3W7jqH0uljGvqLp4mVHgv0yw2MNkNxmPgaygGvYeAd93VIp/WtrzMde9oAjpJ0SZpvt59xUlWSTAt5lP9D1nTrnKrsywjpf5HdVw2VE0E54GTIbPQKyv0AJ8dc7bMO2tMB3PgcyOwHeXPOApWJs6ZBu1RRvJ2ad5kijoxX+ktcmFttLflGtvW/rNJzrJydNTzm6CzKbq07/+b3nXnUTop9vnGYghqxWdv6S4RTIz80Zvs6DNAa38zehpPdZw8CMioUJDNdoazcnmtgqGbqN4+UGNkT8rgcc07v/9EIXvGTGMmhm4f2zyCcE5aDR5rEfzvS17o3zHyNMuxSvUW6KJgLbzIa+KvBFmPyej4i3xN4p3iLIuuMeAsEmgVpq4qMD6hIdf7g1pjjqqqo5BYOj7hPDPJoLeyrIMyfiDjHT+xQ+w48PaXxnp1V0r5gnZL1X/YC2eXVCM1Pi8VNp+wD0HDsGgSA1DYAtBNK6kwBEKTb/CuviyLoRpObKkxa0pz7tCMXtWtNKzNDZlf5JsUQ6CCeGUn3zULo1xEYF2+bogbvREeNRUMdNJf5OM6i4OH5DUORWuRG3NMSfCAnfZLQe9afYM5hfI9Zfw1S3TtAmAvB3kHFrMcWeHwbtvNCmRA5bdhuCLEAZyBO92H8VQep3TjBACEzppE4AnQQ7vZ/d9nu7Ak72R+29pDx+OoT1kHOG7U4wicOC9rdyVZvlztPr7U3RbvAG16HN01voJJWEPD653RKyLXvH0HlglFDk6BMPZr96XjoC9yOApYSX3e08VtSiQVnPm12jZoP4+eXft+KVaKU4ha+y956aC7zaxt0DWgod9LsJx2hjDNgc65Zygwfcq4+5
才是最终的n值

数组的来源

这个原始数组主要来源于四个数组Ye ke B u

javascript 复制代码
Ye = Ye.concat(ke)
Ye = Ye.concat(B)
Ye = Ye.concat(u)

如下图所示



Ye数组的组成

Ye数组是由两个数组组成的一个是Ye = PP数组T = B.concat(g)的T数组

P数组

P数组是Ye数组的前12个,类似如下
[180, 41, 0, 0, 206, 67, 0, 0, 0, 0, 0, 140]

其中0, 00, 0, 0, 0, 0, 140是固定值

如何生成

生成一个32位的字符串

首先先生成一个32位的字符串,类似如下

1764664165090:0.10586600883659525

其中前13位毫秒时间戳

后面的是随机数Math.random()

将时间戳拆分成8个字节

取其中的时间戳拆分为8个字节

类似如下
[0, 0, 1, 154, 221, 251, 3, 36]取其中的最后两个字节组成新的R数组,而这个数组就是P数组的4-5位

W数组(通过32位字符串生成)

W数组是一个32位数组,而这个数组的生成是通过之前生成的32位字符串通过遍历每个字符串,通过获取字符的Unicode码点然后与255进行按位与运算得到的

将R数组与W数组进行计算

而这段代码位于(fo = W[oo] + Ye[R],Ve = fo + le,Ye[R] = 255 & Ve,li = 9761)

其中le为固定值154这里的Ye就是R数组,经过计算之后会得到新的数组,就是P数组的0-1位

生成最终的P数组

最终P数组 = [R数组与W数组进行计算] + [0, 0] + [毫秒时间戳拆分8字节取后2个字节] + [0, 0, 0, 0, 0, 140]

T数组

T数组的组成位置为T = B.concat(g)

在这里B其实g数组的长度

如何组成

生成初始g数组

首先是在g = g.concat(ie)生成一个g数组

类似如下
[1,0,1,0,0,1,154,222,181,234,205,1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,8,0,0,1,247,31,254,230,127,1,1,202,113,210,180,1,0,1,0,100,1,1,100]

注意一下其中[0,0,1,154,222,181,234,205]是之前所说过的毫秒时间戳拆分的8个字节

至于其它的是代码检测浏览器的一下属性所返回的(指纹数据)

生成二进制字符串(通过初始g数组)

上面通过检测浏览器属性构造的初始g数组,通过算数编码生成二进制字符串

这里需要注意三个参数动态字符映射表 静态字符数组 空字符串填充


最后生成的二进制字符串

生成ao数组(通过初始g数组与二进制字符串)

ao数组是通过初始g数组二进制字符串经过数据编码器生成

主要是三个步骤

  1. 通过g数组的长度确定编码数据长度也就是数组的1-2字节
  2. 二进制字符串转字节数组(每8位二进制字符串为一组)
  3. 边界情况处理(如果二进制字符串长度正好是8的倍数,就添加一个0)
生成B数组(通过ao数组)

B数组是通过ao数组经过分块加密轮流使用4种不同的变换算法进行处理

2字节用不同算法加密

生成R数组(通过B数组)

R数组是通过B数组加上[0,0,0]进行校验和最终拆为高位字节低位字节

生成最终的T数组

最终的T数组 = [R数组 + B数组的长度] + R数组 + B数组

至此Ye的第二部分数组生成流程完毕

ke数组

生成ke数组的流程其实与生成Ye第二部分的T数组其实大致流程相同只是没有生成二进制字符串这一步骤

生成原始的Ra数组

M = Ra这里就是最终Ra数组的数据,类似如下
[1,0,0,1,154,222,239,86,62,1,0,1,196,136,12,60,1,1,0,1,0,0,0,0,1,0,1,1,244,12,1,4,2,1,0,255,0,1,0,1,0]

其中[0,0,1,154,222,239,86,62]毫秒时间戳拆分的8字节

生成re数组(通过Ra数组)

这里生成re数组是通过Ra数组进行分块加密(与之前Ye数组的生成ao数组方式一样)

生成ke数组(通过re数组)

ke数组是通过re数组加上[0,0,0]进行校验和最终拆为高位字节低位字节

生成最终的ke数组

最终的ke数组 = [ke数组+re数组长度] + ke数组 + re数组

B数组

这里B数组的生成流程与生成Ye数组的第二部分T数组一模一样

生成Ta数组

这里的Ta数组有两部分与一个庞大的数组有关,轨迹数组

生成二进制字符串

通过Ta数组生成二进制字符串

生成ke数组

通过Ta数组二进制字符串生成初始的ke数组

再次生成ke数组

通过上一步生成的ke数组再次进行计算生成新的ke数组

生成B数组

通过新的ke数组尾部添加[0, 0, 0]计算生成B数组

生成Se数组

通过B数组+新的ke数组计算生成Se数组

生成最终的B数组

最终的B数组 = Se数组 + B数组 + 新的ke数组

u数组

生成Y数组

这里面有部分是是需要取浏览器的部分数据以及部分这个js代码计算生成

如下图是部分展示

生成二进制字符串

生成y数组

通过Y数组二进制字符串生成y数组

生成新的y数组

通过y数组计算生成新的y数组

生成u数组

通过新的y数组尾部添加[0, 0, 0]计算生成u数组

生成第三个y数组

通过u数组+新的y数组计算第三个y数组

生成最终的u数组

最终的u数组 = 第三个y数组 + u数组 + 新的y数组

至此最终的加密前的数据基本组装完成

最终Ye数组的生成

先组装初始的Ye数组及Ye数组 + ke数组 + B数组 + u数组

通过之前的Ye第二部分T数组 ke数组 B数组 u数组通过计算变化初始Ye数组生成最终的Ye数组,代码如下

最后把这个Ye数组自定义base64加密之后加上140#前缀就是最后的n值

代码效果图






相关推荐
某林2121 小时前
在slam建图中为何坐标base_link,laser,imu_link是始终在一起的,但是odom 会与这位三个坐标在运行中产生偏差
人工智能·算法
Keep__Fighting1 小时前
【机器学习:逻辑回归】
人工智能·python·算法·机器学习·逻辑回归·scikit-learn·matplotlib
想唱rap1 小时前
C++之红黑树
开发语言·数据结构·c++·算法
测试19981 小时前
单元测试、系统测试、集成测试
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·集成测试
sin_hielo1 小时前
leetcode 3623
算法·leetcode·哈希算法
nil1 小时前
shortcutkey:跨平台快捷键管理工具的设计与实现
python·开源·github
攻城狮杰森1 小时前
Eudic → Maimemo 自动同步工具:欧路词典 & 墨墨背单词
python·api·shell·ai编程·欧路词典·墨墨本单词
( •̀∀•́ )9201 小时前
高性能拖拽排序
java·开发语言·算法
Ayanami_Reii1 小时前
进阶数据结构应用-区间最大公约数
开发语言·数据结构·算法·线段树·差分·树状数组·fenwick tree