Skip to content

百家网站(上上上)

更新: 2025/2/24 字数: 0 字 时长: 0 分钟

本章节将展示针对100家网站进行逆向的过程。

有道翻译

题目难度:简单

有道翻译网站地址:https://fanyi.youdao.com/

有道翻译是网易公司开发的一款翻译软件,其最大特色在于翻译引擎是基于搜索引擎,网络释义的,也就是说它所翻译的词释义都是来自网络。

首先我们输入一个词“逆向”,通过Chrome自带的开发者工具抓取数据包,在Network(网络部分)的Fetch/XHR选项筛选出返回内容的数据包,在Response部分可以看到返回的结果。

20210831155549

切换到header部分,比较两次相同内容的请求,发现Request Headers参数没有什么变化,但POST有三个参数有变化:

salt: 16303966363048
sign: a5ede67eabd2c6a8b06975b09e2c5a6b
lts: 1630396636304

20210831160402

可以看到 saltlts 参数差不多,有爬虫经验的人,第一直觉就是时间戳,因为这个两个参数随着时间在不断的变大,而且数值和时间戳类似,确保万一取数值的前10位进行验证一下:

20210831161333

看来时间戳猜想基本正确,**一般来说,网络上使用时间戳都会精确到毫秒。这里可以进行下一步确定,lts 参数是精确到毫秒的13位时间戳,salt 参数就是13位时间戳加1个未知参数。**现在我们未知参数就剩下 sign 参数和 salt 最后一位参数。我们全局搜索一下 salt 的名称:

20210831163937

发现就在一个js文件中出现了 salt 的名称,点击进入,跳转到Sources选项中查看 fanyi.min.js 文件,文件中所有的代码都在一行,点击下方的 {} 按钮进行代码格式化:

20210831164624

出现了 fanyi.min.js:formatted 这就是将 fanyi.min.js 文件中js代码格式化后的结果:

20210831164920

继续在文件中搜索 salt 名称,共有12处匹配,经过比对,在8979行找到了和POST参数最为接近的代码:

20210831170729

点击8988行处打上断点,点击翻译,代码运行卡在断点处,里面显示许多我们要使用的参数及来源:

20210831170958

通过观察可得出 saltsignltsbv 参数与js代码中的 r 参数关系密切,查看 r 参数就在上方面,构造也很简单,就是一个 v 类调用了 generateSaltSign() 方法传入了参数 n,即翻译的内容“逆向”。选中方法名称,提示来自于8383行,点击位置跳转。:

20210831172719

在8393行打上断点,点击翻译,断点卡住,绝大部分的参数都显示了内容,再将未知参数在Console控制台直接打印出来,所有的参数基本都豁然开朗了:

20210831174916

到这里就可以对参数做一个总结了:

r = {
  ts: 时间戳,
  bv: 浏览器user-agent的md5哈希,
  salt: 时间戳 + 0到9随机取整,
  sign: "fanyideskweb" + (查询的内容) + (字符串类型的时间戳 + 0到9随机取整) + "Y2FYu%TNSbMCxc3t2u^XT"的md5哈希
}

i: 动态值(查询的内容)
from: 默认值“AUTO”(被翻译的语言类型)
to: 默认值“AUTO”(翻译结果的语言类型)
smartresult: 固定值“dict”
client: 固定值“fanyideskweb”
salt: r参数.salt
sign: r参数.sign
lts: r参数.ts
bv: r参数.bv
doctype: 固定值“json”
version: 固定值“2.1”
keyfrom: 固定值“fanyi.web”
action: 固定值“FY_BY_CLICKBUTTION“

?> 提示:参数中使用了md5哈希,这里我已经验证过是标准的md5,因此可以直接调用Python中的第三方库hashlib来实现md5哈希。

百度翻译

题目难度:简单

地址:https://fanyi.baidu.com/

百度翻译依托互联网数据资源和自然语言处理技术优势,致力于帮助用户跨越语言鸿沟,方便快捷地获取信息和服务。支持全球200多个语言互译,包括中文(简体)、英语、日语等,覆盖4万多个翻译方向,通过开放平台支持超过40万企业和个人开发者,是国内市场份额第一的翻译类产品。

首先我们打开地址,检查cookie,在通过逐个排查发现cookie中没有 BAIDUID 字段的话会再次刷新获取:

20220331150650

而获取的方式,就在我们清空cookie刷新的第一次请求当中:

20220331151239

接下来通过几次变换词语,点击翻译后,抓到v2transapi?from=zh&to=en这条接口地址,可以看到Form Data表单,其中除了sign和token以及query(待翻译字符)外其余参数可以设置为固定值。

20220331142919

首先我们来解决token,通过全局搜索发现,token第一次被赋值就出现在最开始的第二次请求当中,而搜索下面有行注释引人注目,就是没有cookie的话,是不会返回token的,这也就解释了为什么最开始会有两次请求:第一次请求就是获取cookie,第二次请求需要带上cookie来获取token。

20220331151554

经过测试成功获取token,说明前面的逻辑完全正确:

20220331152607

接下来搜索sign看看是否能找到加密入口:

20220331143347

找到单独的sign高亮,且有赋值的过程,在可疑点上打断点:

20220331143627

20220331143634

接下来再次点击翻译,看到断点停到了7045行处,细心一点的朋友可以看到token也在这里:

20220331143806

sign:f(n) 这里sign是就是 f(n) 函数的返回值,n看上面有调试信息 n = "兔子",看看 f() 函数的内容:

20220331143909

进入e函数后看到如下代码块:

20220331144213

现在将e函数拷贝下来,进行输出,发现报错 i 未定义:

20220331144555

先看这段代码:u = null !== i ? i : (i = window[l] || “”) || “”; 大致意思就是 u=i=window[l],经过几次调试发现 window[l] 是一个固定值320305.131321201,所以我们可以直接添加一个定义 i = 320305.131321201 变量: 20220331144847

我们再次运行js代码,提示n未定义:

20220331145115

我们返回网页看看,提示n是一个外部引入的函数:

20220331145240

进入n函数:

20220331145308

将n函数的代码拷贝下来运行,正常输出结果:

20220331145437

新榜查询

题目难度:简单

地址:https://newrank.cn/public/info/search.html?value=gzyxgzyx&isBind=false

新榜是上海看榜信息科技有限公司旗下的一款产品。

首先,访问地址,在搜索框随便输入一个关键词进行查询,定位到相关请求:由于该接口查询一次会产生6次接口,返回6个不同的响应,且参数都大体相同,我们这里就拿返回数据最多的WeixinData接口,经过几次测试改变的参数主要有三个。

keyName: 查询关键词
nonce: 加密参数
xyz: 加密参数

20220406105512

点击Initiator选项卡,跳过上面常规的jquery文件开头,直接点击第三个,进行跳转:

20220406105852

跳转后,可以看到是发送的ajax请求的 data 数据部分的值是 l,而上面有 l = k.objParameter; 这个关系,我们在Console输出 k.objParameter 的值,发现就是我们post传递的参数,再上面又有 k = g(a, d) 这个关系,其中a就是接口的后半段 /xdnphb/data/weixinuser/searchWeixinDataByCondition 的值,d就是一个对象 {keyName: '关键词', order: 'relation', filter: '', hasDeal: 'false'} 的值,现在重点关注的就是 g() 函数的生成逻辑了。

20220406110430

选中 g() 函数出现来源,点击进行跳转:

20220406111354

跳转后,重点观察 g() 函数最后返回值的逻辑,发现参数 nonce 的值来源于 j() 函数的返回值,变量 h 的值就是一个固定的字符串加上 nonce 的值,即 '/xdnphb/data/weixinuser/searchWeixinDataByCondition?AppKey=joker&filter=&hasDeal=false&keyName=qq&order=relation&nonce=加上nonce的值',参数 xyz 的值来源于 d(h) 返回值,在下面输出了该值和post传递的 xyz 的值长度一样:

20220406112215

到这里,其实分析就结束了,后面就是把d函数的代码抠下来,补上运行中缺失的函数和变量,最后经过优化的js代码并不长,可以直接放入爬虫当中。

微信公众平台

题目难度:简单

地址:https://mp.weixin.qq.com/

微信公众平台,简称公众号。

首先访问网站,输入账号和密码均为 [email protected],点击登录,定位发送登录的请求,关键参数如下:

20220406144311

username: 账号
pwd: 加密参数
imgcode: 
f: json
userlang: zh_CN
redirect_url: 
token: 
lang: zh_CN
ajax: 1

点击Initiator选项,观察发现有一个_loginPost,和我们定位发送登录的请求相符,点击跳转:

20220406144522

跳转后,发现有一个pwd参数,打上断点调试,和Post发送的pwd的值相同,而pwd的值就是 f(密码) 函数的返回值:

20220406145146

选中 f() 函数,展示来源,点击跳转:

20220406145641

跳转后,发现是调用的是md5哈希算法里面的一个函数,其中参数(e, t, n)分别是(密码,undefined,undefined)的值:

20220406150149

和线上哈希后的数值一比对,发现一样,说明是标准的MD5哈希:

20230610184218

房天下登录

题目难度:简单

地址:https://passport.fang.com/?backurl=https%3A%2F%2Fwww.fang.com%2Fdefault.htm

房天下是房地产家居行业专业网络平台,1999年由莫天全先生创立,一直专注于新房、二手房、租房、家居、房地产研究等领域的互联网创新,为全球24个国家,658个城市提供服务,房天下APP累计装机量超2亿,在移动技术、产品、推广方面全面布局,锁定了移动领域的优势地位。2010年9月,房天下在美国纽交所上市。

首先我们访问房天下的登录地址,选择账号密码登录,输入账号:13588888888, 输入密码:88888888,点击登录,回看XHR中的请求所发送的表单信息:

uid: 账号
pwd: 加密参数
Service: soufun-passport-web(可能为固定值)
AutoLogin: 1(可能为固定值)

20220401165726

点击Initiator,点send跳转到发送该ajax请求的地方:

20220401170222

在该处打上断点,重新点击登录,断点卡住,看Call Stack(调用堆栈),忽略jquery常规文件,直接点击第三个 loginClickFn 进行跳转:

20220401170555

跳转后,我们在登录注释下面data中看到了和表单一样的数据结构,可以看到pwd的值是 encryptedString(key_to_encode, that.password.val()) 的返回值,现在我们在pwd行打上断点,重新登录:

20220401171006

断点过来后,选中 that.password.val() 发现就是密码本身:

20220401171939

选中 key_to_encode 发现是通过调用RSAKeyPair方法得到的一个对象:

20220401172854

我们全局搜索一下这个RSAKeyPair方法,发现第二个有个function很明显就是该方法,点击跳转,该方法就完整的展示我们面前了,仔细观察该方法,需要传入三个参数才能返回对象,而我们上面选中 key_to_encode 就已经是一个对象了,也就是已经完成了三个参数的传递了,那么是哪里生成了这个对象呢?图中最下面的 new RSAKeyPair 给了我们灵感:

20220401173303

点击跳转到 new RSAKeyPair 位置,给我们完整的展示了该对象的生成的所需参数:

20220401174240

最后剩下一个参数了,选中 encryptedString 是一个函数,点击进行跳转:

20220401174527

跳转后,就是 encryptedString 函数的完整方法了,扣下来补充缺失的变量和方法,再用一个函数包装一下:

20220401174740

黑猫投诉平台

难度:简单

网站地址:https://tousu.sina.com.cn/

黑猫投诉是新浪旗下的消费者服务平台,用户可以通过该平台投诉商家的不规范行为,同时还有企业信誉榜单,以帮助消费者进行消费行为抉择参考。2018年3月14日,微博和新浪网联合举办以“共建消费新生态”为主题的3·15论坛,双方联合推出的消费者服务平台黑猫投诉正式上线。首先,访问平台,输入关键词“游戏”进行搜索,找到网页内容的请求:

20230610231710

请求头中无关键加密字段,查看请求参数发现有三个关键字段:

20230610231947

我们全局搜索一下 signature 字段,只有在一个文件中出现,我们在这个文件中继续搜索该关键字,发现有9处,其中有一处刚好包含上面的三个关键字段,我们在此处打上断点:

20230610232212

刷新后,我们在控制打印相关信息,发现这个位置就是我们要找的接口,对应关系如下:

20230610232925

r = u([l, p, b, h, c, d["type" + e]].sort().join(""));
ts = l
rs = p
signature = r

在上面,我们找到了所有的参数:

20230611000937

在控制台进行打印,最后得到如下关键字对应关系:

20230610234712

javascript
// 时间戳
ts = 1686410750729;
// p函数返回的随机16个字符
rs = 'AyKy4kcdsIc5yjFH';
// u函数返回64个字符:7b3bd12aa9450c61d3e9d907b8476849ae0c649fd9cd3ef4ab46a823565b680a
signature = u('$d6eb7ff91ee257475%1101686410750729AyKy4kcdsIc5yjFH游戏');

可以看到 u 函数返回64个字符,这个长度就需要引起注意了,因为SHA256哈希算法的返回值就是64个字符,现在我们将字符串拿到线上加密,发现结果一模一样,说明 u 函数的功能就是SHA256哈希。

20230610235123

最后的爬虫效果如下:

20230611004035