大神论坛

找回密码
快速注册
查看: 174 | 回复: 0

[思路] 对移动云盘分享得云朵逆向分析 附逆向源码

主题

帖子

0

积分

初入江湖

UID
586
积分
0
精华
威望
0 点
违规
大神币
68 枚
注册时间
2023-09-16 15:07
发表于 2024-03-12 21:51
本帖最后由 heyechuanmei 于 2024-03-12 21:51 编辑

前言

注册好几年了,才几十积分,想着写点东西刷刷积分争取早日到 200,可是空瓶子又倒不出啥技术,前段时间不是发了个某云盘每日任务的脚本么,干脆就记录一下抓取 API 的过程吧。

没有技术含量,就想着记录仔细点,万一哪个萌新看到了呢。

活动分析

先看看活动位置

 

理一下任务步骤

  1. 点击去查看,到达活动页面,发现就是底部栏的"发现"页面
  2. 点击分享,弹出分享方式
  3. 不分享直接退出活动,查看任务是否完成。(答案是并没有)
  4. 回到第二步,不过这次需要点击某个方式了
  5. 分享成功后,查看任务是否完成。(ok 的)
  6. 云盘这个任务点进 QQ 就行了,不用真发送也能成功完成任务

那么抓包就是重点分析第 4 步了,如果没成再看前面的(因为有时候活动需要前置请求激活才能完成)。

HttpCanary 抓包

通过上面的分析,我们在弹出分享方式后,打开抓包,点击 QQ 后停止抓包,这样可以获得较少的请求(如果没有找到想要的才扩大范围)。

抓取到 12 条请求

简单的查看 url 和 请求体,并没有发现可疑的有 share 关键字或者类似的请求。

先尝试下重放请求。发一条请求查看一下云朵记录,结果重放第一条就行了,这就是运气吧!再重放两次也是 OK 的。

请求分析

POST /datacenter/ HTTP/1.1
Host: datacenter.mail.10086.cn
Connection: keep-alive
Content-Length: 1731
sec-ch-ua: "Not A(Brand";v="99", "Android WebView";v="121", "Chromium";v="121"
Content-type: application/x-www-form-urlencoded
platform: h5
source: content-open
User-Agent: Mozilla/5.0 (Linux; Android 13; mi6 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/121.0.6167.178 Mobile Safari/537.36 MCloudApp/10.5.1
sec-ch-ua-mobile: ?1
sec-ch-ua-platform: "Android"
Accept: */*
Origin: https://h.139.com
X-Requested-With: com.chinamobile.mcloud
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://h.139.com/content/discoverNewVersion?columnId=20&token=STuid0000011008510086uasdjikoadakhbsw&targetSourceId=001005
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

data=eyJ0cmFjZUlkIjo5Nzxxxxxxxxxxxxxxxxn0%3D&ext=crc%3D-1412813306

可以看到在 Header 中既无 Cookie 也无 Authorization,那么鉴权信息只能是在请求体中了。

先看 data,eyJxxx 开头,最后%3D(就是=编码后的),典型的 base64 啊,打开在线工具查看一下,先 URL 解码(因为这个复制出来有%3D 之类的),再 Base64 解码

得到了

不急着分析字段,接下来看 ext。

ext=crc=-1412813306 这硬看也看不出啥名堂,只知道是 CRC 循环冗余校验

目光再次来到请求,发现 Referer 是个网页

这也就简单多了,直接查看调用栈,试着 debuger

先搜素一下关键字 crc=

搜索下 hashCode,好家伙,直接出结果了,debugger 都免了。这不就是 Java 的 hashCode 用 JavaScript 实现的么?

_.hashCode = function (str) {
if (typeof str !== 'string') {
return 0;
}
var hash = 0;
var char = null;
if (str.length == 0) {
return hash;
}
for (var i = 0; i < str.length; i++) {
char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash;
}
return hash;
};

把 data 传入尝试一下得到 -1412813306,ok,结束了。

编写代码

直接在浏览器中运行一下

const data = {
traceId: Number(Math.random().toString().substring(10)),
tackTime: Date.now(),
distinctId: '18d7cccee76678-08d30cfe3e81ee8-4c657b58-1327104-18d7cccee7711fc',
eventName: 'discoverNewVersion.Page.Share',
event: '$manual',
flushTime: Date.now(),
model: 'Nexus 5',
osVersion: '',
appVersion: '',
manufacture: 'LG',
screenHeight: 700,
os: 'Android',
screenWidth: 352,
lib: 'js',
libVersion: '1.17.2',
networkType: '',
resumeFromBackground: '',
screenName: '',
title: '【精选】一站式资源宝库',
eventDuration: '',
elementPosition: '',
elementId: '',
elementContent: '',
elementType: '',
downloadChannel: '',
crashedReason: '',
phoneNumber: '10086',
storageTime: '',
channel: '',
activityName: '',
platform: 'h5',
sdkVersion: '1.0.1',
elementSelector: '',
referrer: '',
scene: '',
latestScene: '',
source: 'content-open',
urlPath: '',
IP: '',
url: 'https://h.139.com/content/discoverNewVersion?columnId=20&token=STuid0000011008510086uasdjikoadakhbsw&targetSourceId=001005',
elementName: '',
browser: 'Edge',
elementTargetUrl: '',
referrerHost: '',
browerVersion: '122.0.0.0',
latitude: '',
pageDuration: '',
longtitude: '',
urlQuery: '',
shareDepth: '',
arriveTimeStamp: '',
spare: { mobile: '10086', channel: '' },
public: '',
province: '',
city: '',
carrier: '',
};

function hashCode(str) {
if (typeof str !== 'string') {
return 0;
}
var hash = 0;
var char = null;
if (str.length == 0) {
return hash;
}
for (var i = 0; i < str.length; i++) {
char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash;
}
return hash;
}

// btoa 是浏览器的内置方法,nodejs 没有,node 直接使用 Buffer
const base64 = btoa(JSON.stringify(data));

const res = await fetch('https://datacenter.mail.10086.cn/datacenter/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
platform: 'h5',
},
body: `data=${base64}&ext=${encodeURIComponent('crc=' + hashCode(base64))}`,
});

console.log(await res.json());

起初用的是最精简的 Header,并没有增加云朵,依次测试后发现 platform 是必须的。

直接修改 phoneNumber 为小号的手机号码,测试成功。

修改 traceId,distinctId 这些后也是成功的,最后发现其实大部分字段都是可以删除的,确定用户身份唯一字段就是 phoneNumber。也就是不需要登录,只要手机号码就可以完成这个任务了。

其他

编辑

有同学已经发现之前的代码再浏览器中并不能成功运行,出现了

VM2516:1 Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
at <anonymous>:1:1

值得庆幸的是,有人真的试了。但是为啥不去尝试解决呢。

翻译一下

无法在“Window”上执行“btoa”:要编码的字符串包含 Latin1 范围之外的字符。

直接百度你就能得到一个 btoa(unescape(encodeURIComponent(JSON.stringify(data)))) 这样的结果,不是太简单了么?

当然,你已经看完这篇文章,_.hashCode 找到了,用同样方式找到  _.base64Encode 不就行了。

发这个的目的不是为了发最后那几行代码,而是分析一个简单的过程,授人以鱼不如授人以渔。这几行代码没有太多的意义,我已经在站内分享了这个开源程序(前言提到的)


注:若转载请注明大神论坛来源(本贴地址)与作者信息。

返回顶部