[007]爬虫系列 | 某条加密参数_signature(短)逆向解析

一、背景

最近脑子瓦特了,无法专心学习,只能写写逆向了。记得前端时间也有人问过我关于某条_signature参数问题,现在就写篇文章叭。

该文章主要提供交流学习使用,请勿利用其进行不当行为!

如本篇文章侵犯了贵公司的隐私,请联系我马上删除!

如因滥用解密技术而产生的风险与本人无关! 

 备注:本文仅仅分析短_signature参数,长_signature参数下次再解析。

二、正文

1、找到_signature位置

打断点分析:

调试器调试

很明显_signature参数通过j函数生成,进去看下j函数详情并断点调试:

分析后发现,真正生成_signature参数的函数:

n = window.byted_acrawler
a = n.sign
a.call(n, o)

o的值为:

{url:'xxxxxxxxxxxx'}

 byted_acrawler是什么?全局搜索一下:

上面我们发现两个东西:

1、

<script src="//sf1-cdn-tos.toutiaostatic.com/obj/rc-web-sdk/acrawler.js" crossorigin="anonymous"></script>

2、

<script>
            window.byted_acrawler && window.byted_acrawler.init({
                aid: 24,
                dfp: !0
            })
        </script>

那么我们先模拟一下浏览器生成_signature参数

2、模拟生成_signature参数

<script src="//sf1-cdn-tos.toutiaostatic.com/obj/rc-web-sdk/acrawler.js" crossorigin="anonymous"></script>
<script>
    window.byted_acrawler && window.byted_acrawler.init({
        aid: 24,
        dfp: !0
    })
    var i = {url:''}
    var a = window.byted_acrawler;
    var r = a.sign;
    var c = r.call(a,i);
    document.write(c);
</script>

可以正常生成!!!

3、逻辑&扣代码

3.1扣代码

将整一个acrawler.js直接扣下来,通过node运行:

 

报错!补代码

3.2补代码 

既然浏览器可以正常运行,但是通过node无法运行,那么肯定就是环境问题,既然涉及浏览器环境,那么就肯定和window属性有关!补window属性!

var window = global;

不存在referrer属性?百度一下referrer属性在哪!?

 

在 window.document里面。那么我们直接去浏览器调试调试,看看里面的referrer里面到底是什么!

 补上之后,再运行,发现并没有报错了!补完之后如下:

3.3补上逻辑,生成_signature参数

var i = {url:'xxxxxx'}
var a = window.byted_acrawler;
var r = a.sign;
var c = r.call(a,i);
console.log(c)

补完之后发现并不存在a.sign函数:

 我们打印一下window看看,并不存在byted_acrawler:

依然还是原本的解析:既然浏览器可以生成,node不可以,那么就是环境的问题。似乎好像都没啥问题了,后来发现了一个传入参数e里面存在三目运算符,很有可能就是这里存在问题:

[, , "undefined" != typeof exports ? exports : void 0, "undefined" != typeof module ? module : void 0, "undefined" != typeof define ? define : void 0, "undefined" != typeof Object ? Object : void 0, void 0, "undefined" != typeof TypeError ? TypeError : void 0, "undefined" != typeof document ? document : void 0, "undefined" != typeof InstallTrigger ? InstallTrigger : void 0, "undefined" != typeof safari ? safari : void 0, "undefined" != typeof Date ? Date : void 0, "undefined" != typeof Math ? Math : void 0, "undefined" != typeof navigator ? navigator : void 0, "undefined" != typeof location ? location : void 0, "undefined" != typeof history ? history : void 0, "undefined" != typeof Image ? Image : void 0, "undefined" != typeof console ? console : void 0, "undefined" != typeof PluginArray ? PluginArray : void 0, "undefined" != typeof indexedDB ? indexedDB : void 0, "undefined" != typeof DOMException ? DOMException : void 0, "undefined" != typeof parseInt ? parseInt : void 0, "undefined" != typeof String ? String : void 0, "undefined" != typeof Array ? Array : void 0, "undefined" != typeof Error ? Error : void 0, "undefined" != typeof JSON ? JSON : void 0, "undefined" != typeof Promise ? Promise : void 0, "undefined" != typeof WebSocket ? WebSocket : void 0, "undefined" != typeof eval ? eval : void 0, "undefined" != typeof setTimeout ? setTimeout : void 0, "undefined" != typeof encodeURIComponent ? encodeURIComponent : void 0, "undefined" != typeof encodeURI ? encodeURI : void 0, "undefined" != typeof Request ? Request : void 0, "undefined" != typeof Headers ? Headers : void 0, "undefined" != typeof decodeURIComponent ? decodeURIComponent : void 0, "undefined" != typeof RegExp ? RegExp : void 0]

直接浏览器和node分别调试一下里面的值:

很明显就是这里的问题了!将其改为:

[, , void 0, void 0, "undefined" != typeof define ? define : void 0, "undefined" != typeof Object ? Object : void 0, void 0, "undefined" != typeof TypeError ? TypeError : void 0, "undefined" != typeof document ? document : void 0, "undefined" != typeof InstallTrigger ? InstallTrigger : void 0, "undefined" != typeof safari ? safari : void 0, "undefined" != typeof Date ? Date : void 0, "undefined" != typeof Math ? Math : void 0, "undefined" != typeof navigator ? navigator : void 0, "undefined" != typeof location ? location : void 0, "undefined" != typeof history ? history : void 0, "undefined" != typeof Image ? Image : void 0, "undefined" != typeof console ? console : void 0, "undefined" != typeof PluginArray ? PluginArray : void 0, "undefined" != typeof indexedDB ? indexedDB : void 0, "undefined" != typeof DOMException ? DOMException : void 0, "undefined" != typeof parseInt ? parseInt : void 0, "undefined" != typeof String ? String : void 0, "undefined" != typeof Array ? Array : void 0, "undefined" != typeof Error ? Error : void 0, "undefined" != typeof JSON ? JSON : void 0, "undefined" != typeof Promise ? Promise : void 0, "undefined" != typeof WebSocket ? WebSocket : void 0, "undefined" != typeof eval ? eval : void 0, "undefined" != typeof setTimeout ? setTimeout : void 0, "undefined" != typeof encodeURIComponent ? encodeURIComponent : void 0, "undefined" != typeof encodeURI ? encodeURI : void 0, "undefined" != typeof Request ? Request : void 0, "undefined" != typeof Headers ? Headers : void 0, "undefined" != typeof decodeURIComponent ? decodeURIComponent : void 0, "undefined" != typeof RegExp ? RegExp : void 0]

 即:

"undefined" != typeof exports ? exports : void 0, "undefined" != typeof module ? module : void 0

改为

void 0, void0

改完之后依然还是存在报错:

 

 还是和上面一样的解析:既然浏览器可以生成,node不可以,那么就是环境的问题。补window属性值!

 

window.location = {
    hash: "",
    host: "www.toutiao.com",
    hostname: "www.toutiao.com",
    href: "https://www.toutiao.com/",
    origin: "https://www.toutiao.com",
    pathname: "/",
    port: "",
    protocol: "https:"
}

补完之后依然报错:

继续补:

window.navigator = {
    userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}

 终于终于!!!最后可以生成了!

 三、代码

var window = global;
window.document = {
    referrer:"https://so.toutiao.com/"
}
window.location = {
    hash: "",
    host: "www.toutiao.com",
    hostname: "www.toutiao.com",
    href: "https://www.toutiao.com/",
    origin: "https://www.toutiao.com",
    pathname: "/",
    port: "",
    protocol: "https:"
}
window.navigator = {
    userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}

// 此部分和acrawler.js一样 =========
var glb;
(glb = "undefined" == typeof window ? global : window)._$jsvmprt = function(b, e, f) {
        //...................省略
,
(glb = "undefined" == typeof window ? global : window)._$jsvmprt("484e4f4a403f5243000d2d1aea78184c36c3d671000000000000ab440200 
     //...........................省略
, "undefined" != typeof RegExp ? RegExp : void 0]);
// =============

var i = {url:'xxxxxx'}
var a = window.byted_acrawler;
var r = a.sign;
var c = r.call(a,i);
console.log(c)

四、说明

        上面的结果很明显和浏览器显示的_signature参数短很多,如果有详细看上文的话,会发现为什么那个init函数没了?

 原因:加了那个init函数之后会报错!

 至于怎么解决此报错呢?!又改如何生成长_signature参数呢?!

不好意思!要去吃饭了!下篇文章再说叭!

备注:

 

 

 

 

解决方案:

        补环境!!!因为会动态引入js。首先,知道其如何引入进去的!然后再补相关环境变量。对于script里面的值,可以通过网络请求响应回来再执行【eval】即可完成!!!

 

大家自己搞搞,哈哈哈!!!

### 闲鱼数据加密机制分析 闲鱼作为阿里巴巴旗下的二手交易平台,其数据传输和接口调用过程中采用了多种加密机制以保障用户数据的安全性。以下是关于闲鱼加密机制的详细分析: #### 1. 数据包加密与解密 在爬取闲鱼商品数据时,通常会遇到加密参数的问题。这些参数可能是通过前端 JavaScript 动态生成的,或者由后端服务器返回并经过加密处理[^1]。以下是一些常见的加密方法及其实现方式: - **AES 加密**:闲鱼可能使用 AES(Advanced Encryption Standard)对请求参数或响应数据进行加密。AES 是一种对称加密算法,密钥由客户端和服务端共享。在实际应用中,可以通过抓取网络请求,找到加密的请求头或请求体,并尝试逆向分析密钥生成逻辑。 - **RSA 加密**:对于敏感信息(如登录密码),闲鱼可能会采用 RSA 非对称加密算法。客户端将数据用公钥加密后发送到服务端,服务端再用私钥解密。这种加密方式可以有效防止中间人攻击。 - **HMAC 签名**:为了验证请求的合法性,闲鱼可能使用 HMAC(Hash-based Message Authentication Code)对请求参数进行签名。签名值通常基于一个固定的密钥和请求参数生成,服务端接收到请求后会重新计算签名并与请求中的签名值对比。 #### 2. 动态参数生成 闲鱼的 API 接口通常包含动态生成的参数,例如 `timestamp`、`nonce` 和 `signature`。这些参数的作用是防止重放攻击和非法请求。以下是它们的常见用途: - **Timestamp**:表示请求的时间戳,用于限制请求的有效期。服务端接收到请求后会检查时间戳是否在允许范围内。 - **Nonce**:随机数,确保每次请求的唯一性,防止重复提交。 - **Signature**:通过对请求参数按特定规则排序后,结合密钥生成的签名值。签名的生成逻辑可能涉及 MD5 或 SHA 系列哈希算法。 #### 3. 抓包与逆向分析 如果需要研究闲鱼的加密机制,可以通过以下步骤进行抓包和逆向分析: - 使用工具(如 Fiddler 或 Charles)捕获网络请求,找到加密参数的生成逻辑。 - 将捕获的 cURL 请求复制到爬虫工具库(如 Spidertools.cn)中,解析其中的加密参数。 - 在开发者工具(如 PyCharm)中编写脚本,模拟加密过程并发送请求。 #### 示例代码 以下是一个简单的 Python 脚本示例,展示如何使用 HMAC 签名生成加密参数: ```python import hmac import hashlib import time def generate_signature(params, secret_key): # 按照字典序排序参数 sorted_params = "&".join(f"{k}={params[k]}" for k in sorted(params)) # 生成签名 signature = hmac.new(secret_key.encode(), sorted_params.encode(), hashlib.sha256).hexdigest() return signature # 示例参数 params = { "timestamp": str(int(time.time() * 1000)), "nonce": "random_string" } secret_key = "your_secret_key" signature = generate_signature(params, secret_key) print(f"Generated Signature: {signature}") ``` #### 注意事项 在研究闲鱼的加密机制时,请务必遵守相关法律法规,避免未经授权的访问或数据抓取行为。此外,闲鱼的加密机制可能会随着版本更新而发生变化,因此需要定期更新分析方法。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值