申 请 I D:tzwsoho
个人邮箱:tzwsoho@126.com
原创技术文章:关于pandownload的一般性研究
众所周知,最近由于某些特殊原因,pandownload关闭了默认搜索功能,所以一直使用畅快的我感到了前所未有的掣肘的感觉。但首先很感谢pandownload的作者提供了这么好用的功能,希望事情过去后仍然可以把功能开放一下。本文仅供学习研究使用,禁止用作非法用途,如有不妥之处请告之,本人会在第一时间修改删除。
这篇文章主要是对pandownload(下面简称PD)这个软件一些功能的挖掘,主要挖掘了两大功能:
软件环境:
默认搜索功能
一直在用PD的朋友都应该知道,自从2019年8月30日开始,该软件不再提供强大的默认搜索功能。而大家可以在PD的目录中看到,一些如盘多多之类的插件,都是通过lua脚本来实现的,这时我们很容易就联想到,会不会默认搜索也是同样适用lua来实现呢?猜测的答案其实是肯定的,并且我们可以通过hook lua53的一些函数就可以把默认搜索的lua脚本提取出来,但因为默认搜索功能已经关闭的原因,其实PD已不再加载默认搜索的脚本,这个我们可以通过wireshark抓包知道。
首先我们打开wireshark,设置过滤器为http,再打开PD,我们可以看到,PD会先访问一个初始化的地址,然后会通过访问
http://pandownload.com/api/script/list?clienttype=0&referral=&t=1567735359&version=2.1.3
来获取脚本的配置信息
这个脚本配置是个JSON文本,目前是这样的
[JavaScript] 纯文本查看 复制代码 {
"scripts": [
{
"name": "search_pandown.lua",
"remove": true
},
{
"name": "search_ncckl.lua",
"remove": true
},
{
"name": "search_quzhuanpan.lua",
"remove": true
},
{
"name": "anime_01.lua",
"remove": true
},
{
"name": "anime_02.lua",
"id": 1000,
"url": "http://static.pandownload.com/scripts/anime_agefans_0.0.5.lua",
"md5": "2d5d32f3294e7617bb0e5f0d942b29c9"
},
{
"name": "anime_dilidili.lua",
"id": 1001,
"url": "http://pandownload.com/static/scripts/anime/anime_dilidili_0.0.4.lua",
"md5": "197927c0ad7098f59c2c8674fd7054a8"
},
{
"name": "s",
"id": 2,
"url": "http://pandownload.com/static/scripts/s005",
"md5": "93c6666f6b10c40ac6d55771ddb98367"
},
{
"name": "anime",
"id": 3,
"url": "http://static.pandownload.com/scripts/anime_0.0.2",
"md5": "5fd63dc5bf617225ebfb3b16413879cb"
},
{
"name": "default",
"id": 0,
"url": "http://pandownload.com/static/scripts/default_0.3.8",
"md5": "363d53675fdd959d2ec5ad30c160435d",
"key": "3ae81c85790faeccd3ed39d533816b32"
}
],
"code": 0,
"message": "success"
}
我们可以看到,search_pandown.lua就是默认搜索的脚本,而它的当前remove状态已经是true,所以已经不会从服务器里下载下来。
但是,大家其实可以通过https://pandownload.com/2.0.6这个链接来下载v2.0.6版本的PD,解压之后你可以看到里面就有一个search_pandown.lua。这个文件其实是已经编译过的luac格式的文件,我们可以通过执行
java -jar unluac_2015_06_13.jar search_pandown.lua > C:\search_pandown.lua
反编译出lua代码(如果反编译出现错误,需要用WinHex把文件打开,把所有的0D0A字节替换成0A,这个不知道是不是作者使用Windows自带记事本来写lua的原因,以下操作雷同),这时可以看到,这个版本的脚本访问的搜索URL并没有附加sign字段,可能是之前PD作者没考虑到会被盗链吧。但本人很有幸,在PD作者关闭默认搜索脚本功能之前,我已经把最新版本的默认搜索的代码dump了下来。dump脚本的方法很简单,因为PD使用了lua53.dll,我们就可以在lua的官网上下载一份源码,使用VS编译出修改后的dll并替换掉原来的,那便可以为所欲为了!这里我自己修改了lua_loadbufferex函数:
[C++] 纯文本查看 复制代码 LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
const char *name, const char *mode) {
FILE* f = NULL;
char fn[50];
LoadS ls;
ls.s = buff;
ls.size = size;
sprintf(fn, "D:\\%d.luac", rand() * 100000);
f = fopen(fn, "w");
fwrite(buff, size, 1, f);
fclose(f);
return lua_load(L, getS, &ls, name, mode);
}
替换掉原来的DLL后,打开PD,随便搜索一些东西再关闭PD,我们可以看到D:盘下生成了许多“数字.luac”文件,我们再次使用unluac_2015_06_13.jar将他们逐一反编译,可以看到一份源码是这样的(由于边幅过长,我去掉了一些与本文无关紧要的代码):
[Lua] 纯文本查看 复制代码 local L1_1
L0_0 = require
L1_1 = "lcurl.safe"
L0_0 = L0_0(L1_1)
L1_1 = require
L1_1 = L1_1("cjson.safe")
script_info = {
title = "默认",
description = "",
version = "0.0.5"
}
function onSearch(A0_2, A1_3)
local L2_4, L3_5
L2_4 = os
L2_4 = L2_4.time
L2_4 = L2_4()
L3_5 = "http://search.pandown.cn/api/query?clienttype=0&highlight=1&key="
L3_5 = L3_5 .. pd.urlEncode(A0_2) .. "&page=" .. A1_3 .. "×tamp=" .. L2_4 .. "&sign=" .. e(A0_2, A1_3, L2_4)
return parse(get(L3_5))
end
function onItemClick(A0_6)
...
end
function get(A0_9)
...
end
function parse(A0_13)
...
end
function replace(A0_22, A1_23)
...
end
function getIcon(A0_25, A1_26)
...
end
function e(A0_33, A1_34, A2_35)
local L3_36
L3_36 = ""
if pd.makeSign then
L3_36 = pd.makeSign(A0_33 .. "_" .. A1_34 .. "_" .. A2_35)
end
return L3_36
end
这时我们可以清晰地看到,PD实现默认搜索,其实就是访问了下面的一个URL,然后对服务器返回的内容进行解析再以列表的形式展示出来:
http://search.pandown.cn/api/query?clienttype=0&highlight=1&key=编码后的关键字&page=页码×tamp=当前时间&sign=pd.makeSign(原关键字 + "_" + 页码 + "_" + 当前时间)
而pd.makeSign是一个PD使用C++写的内置函数,并不是脚本实现,所以很可惜我虽然通过跟踪lua_pushstring和lua_pushcclosure两个函数,找到了makeSign的实现汇编代码,但由于能力所及并不能知道这个函数的实现原理。
到了这里,聪明的读者是不是觉得,虽然我们并不知道pd.makeSign的实现方法,但是既然我已经知道了默认搜索的实现代码,而PD又支持插件功能,自己再写一个脚本不就同样可以实现默认搜索的功能?但是很遗憾的是,PD的作者在服务器端也将此功能关闭了,目前访问这个URL,得到的回复都只会是{"code":-1,"message":"服务器维护中"},所以一切只能等PD的作者恢复默认搜索功能才能愉快地玩耍了。
提取码搜索功能
我觉得PD之所以如此受大众喜爱,除了突破了某种限制,还有强大得无人能敌的默认搜索功能,最重要的我觉得就是网盘提取码的搜索功能。这个功能的挖掘相对简单,使用WireShark即可。同样我们先打开WireShark,设置http过滤器,然后打开PD,复制一个网盘分享链接(比如:https://pan.baidu.com/s/1GmaGU1FmZ5uwMtE8lUWKOA),这时PD会自动搜索提取码
我们可以看到,PD通过访问这个URL来获取提取码:
http://search.pandown.cn/api/query?clienttype=0&referral=&surl=1naiIOD7m8gZSrVk-Zr30dg&t=1567738781&version=2.1.3
其中,surl参数是网盘链接/s/后面的那段路径,t是当前时间,其他参数固定。返回的内容也是JSON格式的文本,如果找不到提取码,会返回以下内容
[JavaScript] 纯文本查看 复制代码 {
"code": 0,
"message": "success",
"total": 0,
"data": []
}
如果找到了提取码,就会返回这样的格式:
[Asm] 纯文本查看 复制代码 {
"code": 0,
"message": "success",
"total": 1,
"data": [
{
"id": "3Nzk91",
"password": "mj8d",
"title": "彩虹岛",
"ctime": "1567679677",
"expired": "0",
"isdir": "1"
}
]
}
同时,如果在找不到提取码的情况下,PD还允许用户自行输入提取码,并且PD还内置了SQLite数据库,当提取码正确的时候,PD会把提取码记录到PanData\share.db文件里面,下次用户再访问同一个分享链接便不需要再向服务器请求提取码了,这个数据库还有已下载的任务列表数据库(PanData\task.db)都可以使用常用的SQLite数据库管理器如Navicat来打开,而看着像是用户数据库的user.db文件由于进行了加密,并不能正常打开。 |