微信的文件助手,我想大家一定有用到过,可以说是除了PC端微信,我使用最多的手机与PC端互传软件,虽然同步文件很方便,但是我不知道出了什么问题,在同步图片的时候,保存到电脑的照片名称会是一串很奇怪的网址,如图:
而今天这篇文章就是带大家一步步来解决这个问题。
首先,我们来了解下微信的文件传输助手的用法,使用它有两种方法:1.直接网页搜索微信后点击网址登录。2.安装PC端微信,在登录微信的扫码界面登录,如下图:
而登录后,两者不一样的地方,就是登录的网址:
PC端,如图:
web端,如图:
可以看到,PC端只是多了个后缀,而域名都是同一个:https://filehelper.weixin.qq.com/
查看了两者的网页源代码,发现都是一样的,所以我们先分析源代码看看,使用Edge浏览器的开发者模式(F12)后,搜索关于"下载"按钮的源代码,如下操作:
搜索到的源代码如下:
图片可能看不清,我把部分源代码整理如下:
(0,
r.j4)("ul", {
key: 0,
class: "msg-context-menu",
ref: "contextMenu",
style: e.menuStyle
}, [e.download ? ((0,
r.wg)(),
(0,
r.j4)("li", pe, [(0,
r.Wm)("a", {
class: "msg-context-menu__item__inner",
href: "javascript:;",
onClick: t[17] || (t[17] = (0,
P.iM)((function(t) {
return e.handleDownload(e.download)
}
), ["prevent", "stop"]))
}, "下载")])) : (0,
r.kq)("v-if", !0), 3 === e.MsgType && (e.download || e.isLocal) ? ((0,
r.wg)(),
(0,
r.j4)("li", he, [(0,
r.Wm)("a", {
class: "msg-context-menu__item__inner",
href: "javascript:;",
onClick: t[18] || (t[18] = (0,
P.iM)((function(t) {
return e.handlePrint(e.download || e.url)
}
), ["prevent", "stop"]))
}, "打印")])) : (0,
r.kq)("v-if", !0), (0,
r.Wm)("li", {
class: "msg-context-menu__item",
onClick: t[19] || (t[19] = (0,
P.iM)((function() {
return e.handleDele && e.handleDele.apply(e, arguments)
}
), ["stop"]))
}, [ge])], 4)) : (0,
r.kq)("v-if", !0)])
}
;
上面是一段VUE编写的JavaScript源代码,你如果看不懂也没关系,我们可以在Edge浏览器的开发者模式的元素选项卡,点击这个"下载"按钮查看上面的JavaScript源码动态生成的dom对象,如下图:
如上图,我们可以看到"下载"按钮的元素已经被定位,查看这个元素的标签,我们可以明显发现,上面的VUE编写的js源码就是在构造这个元素,我们把重要部分提取出来看看,如下:
("a", { //下载按钮的元素标签是a
class: "msg-context-menu__item__inner",//下载按钮的classname
href: "javascript:;", //设置href属性
onClick: t[17] || (t[17] = (0,P.iM)((function(t)//设置标签的onclick点击事件
{return e.handleDownload(e.download)}), //点击事件的返回
["prevent", "stop"]))
}, "下载")])) //标记a元素的text属性为"下载",也就是显示出"下
//载"按钮
从上面的代码分析可以看出,核心的代码就是onclick事件,所以我们可以在函数的返回上下断点,如下图:
在上面红框的代码行下断后,我们实际点击下载按钮,下载图片,然后就可以中断在这一行,然后我们只有不停的F11单步运行调试代码,因为我们主要需要调试出,保存图片的代码位置,所以我们只要不停按F11直到图片下载就行。
我们可以看到在调试的过程中,网页代码运行的逻辑都能看到,如红框中的代码
上图的代码,构造发送了一个post参数请求,在网络选项卡可以明显看到,但是这个请求并不是实际下载保存图片的。
经过不停的F11和F10调试,我找到了关键代码位置,如下:
就是这个函数A.downloadImage,我们可以在中断在这个函数时,选中这个downloadImage,会弹出如下的框,定位到这个函数的源码位置,如下图:
A.downloadImage函数的定义位置如下:
这里的代码很简单,稍微懂一点js代码的也能看明白,我把代码注释下,方便大家理解:
function M(e, t) { /*e为元素标签href属性(javascript:;),t就是微信定义的那一串英文文件名(题外话,这
个文件名其实加上https://filehelper.weixin.qq.com/前缀,就是这张图片的下载地址,但是只能是当前登
录的文件传输助手的浏览器打开才行,比如edge打开的文件助手,只能在这个edge窗口程序中新建一个页面,
输入上面拼接的网址打开图片,换成chrome等其他浏览器就不行,换另一台电脑就更不可能了,这也是微信的隐
私保护措施*/
var n = e //通过定义变量n把href属性传入下面构造的一个临时标签a
, r = document.createElement("a"); //创建一个临时标签a,供下面的click事件点击
r.href = n, //传入href属性
r.download = t || "", //关键的代码:设置保存的文件名称
r.dispatchEvent(new MouseEvent("click")) //派发一个click事件,来点击上面的a标
//签
}
为了能够比较好的显示图片文件名称,我们就需要修改上面的函数,改成如下这样的:
function M(e, t) {
var n = e,
r = document.createElement("a");
//下面三句增加时间文件名称
var now = new Date();
t = `${now.toLocaleDateString()} ${now.toLocaleTimeString()}`;
t = t.replace(/\//g, '').replace(/:/g, '').replace(' ', '_');
(r.href = n),
(r.download = t || ""),
r.dispatchEvent(new MouseEvent("click"));
}
最终生成,以当前下载时间格式化,如下面的格式:20240719_173013的格式,这样唯一的时间戳也就不会有重复文件名的可能。
那么我们知道了怎么修改js代码,但是怎么能替换掉原始的js,其实python已经有这个库,那就是mitmproxy,安装方法如下:
pip install mitmproxy
安装完毕后,还需根据安装说明,安装下mitmproxy的签名,这个库的签名包括了window、macos、linux等各种系统,也就是只要能使用python的系统都能使用。
在命令提示符或者终端中输入如下命令:
mitmproxy
如下图,启动后的界面:
然后,在浏览器中访问 http://mitm.it
,根据你的操作系统下载相应的证书。
下载证书后,双击打开,点击两次下一步后,忽略下图的私钥选项,直接下一步。
最后选择导入受信任的根证书颁发机构,确认即可,导入证书成功。
这样mitmproxy就可以成功嗅探到https的流量了。(建议这步后把浏览器重启下)
我们接着可以编写如下的代码调用mitmproxy来替换文件助手里的js文件(之前截图里已提到这个js文件,可以通过后面的这个链接下载js文件:https://res.wx.qq.com/t/wx_fed/base/webwx-transfer/24052300/main.060f2b3fa370604828e2.js)
调用mitmproxy替换js的代码如下:
from mitmproxy import http
target_web_main_url = "https://filehelper.weixin.qq.com/"#浏览器中扫二维码进入文件助手的页面pc
target_win_main_url = "https://filehelper.weixin.qq.com/?from=windows&type=recommend"#同上web版
target_js_url = "//res.wx.qq.com/t/wx_fed/base/webwx-transfer/24052300/main.060f2b3fa370604828e2.js"# 需要替换的原始js链接
local_js_path = "http://localhost:8086/main.060f2b3fa370604828e2_hook.js"# 我们修改后的js链接
def response(flow: http.HTTPFlow) -> None:
print("----------response-----------",flow.request.url)
if flow.request.url == target_win_main_url :# pc版文件助手
print("正在替换js文件")
html = flow.response.get_text()
modified_html = html.replace(target_js_url, local_js_path)
flow.response.set_text(modified_html)
print("替换成功!")
elif flow.request.url == target_web_main_url:# web版文件助手
print("正在替换js文件")
html = flow.response.get_text()
modified_html = html.replace(target_js_url, local_js_path)
flow.response.set_text(modified_html)
print("替换成功!")
把上面代码保存成python文件后,通过如下的命令在cmd中运行:
mitmdump -s "hook文件助手.py"#请替换成自己的代码文件名和路径
如出现下面的报错,请把刚刚安装证书前运行的mtimproxy窗口关掉:
可以看到关闭上面的窗口后,mitmproxy的代码跑起来了,嗅探也都正常运行了。
可能有朋友要问,为什么我上面的代码需要替换两种文件助手主页的js链接,因为通过查看文件助手登录扫二维码的网页源码可知,我们需要替换的这个"main.060f2b3fa370604828e2.js",是放在这个二维码登录页,通过如下html代码调用的:
<script src="//res.wx.qq.com/t/wx_fed/base/webwx-transfer/24052300/main.060f2b3fa370604828e2.js" crossorigin="anonymous"></script>
我们只要通过mitmproxy嗅探到二维码的登录页的response返回内容,把返回内容里的上面的这句html代码替换成我们的js目录就行了,如果你们查看刚刚的mitmproxy替换代码可以发现一个问题。
local_js_path = "http://localhost:8086/main.060f2b3fa370604828e2_hook.js"
如上,我替换的js路径是一个本地的8086端口的http服务,我为了方便,使用了python自带的http服务器,使用如下的python代码调用:
import http.server
import socketserver
PORT = 8086
DIRECTORY = "E:\\vscode\\weixin" # 替换为你的文件目录路径
class CustomHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header("Access-Control-Allow-Origin", "*")
super().end_headers()
def do_GET(self):
self.path = self.path.replace("//", "/")
return super().do_GET()
def translate_path(self, path):
# 覆盖 translate_path 方法以支持本地文件路径
path = super().translate_path(path)
return path.replace('/', '\\') if '\\' in path else path
with socketserver.TCPServer(("", PORT), CustomHandler) as httpd:
print(f"Serving at port {PORT}")
httpd.serve_forever()
可以看到DIRECTORY = "E:\\vscode\\weixin" 这句就是我们修改的js代码文件的存放路径。这个以自己的实际情况修改就行。只要碰到8086端口号占用,可以随意修改成空闲端口即可,如下的运行效果:
如果你会深入研究上面的http服务器代码,你会发现,在使用本地服务器提供文件时,浏览器可能会阻止跨域请求(CORS),因为默认情况下本地服务器不会设置Access-Control-Allow-Origin
头。为了解决这个问题,我在本地服务器上设置了CORS头。同时,如果你想使用计算机的本地路径也是不行的,我已经尝试过了。
可以输入如下网址(http://localhost:8086/main.060f2b3fa370604828e2_hook.js)查看http服务器是否建立成功:
在上面的mitmproxy替换代码和http本地js服务器都运行后,我们还需要设置下浏览器的代理服务器,如图:
我们可以尝试运行下文件助手的二维码登录界面(记住:重要的步骤来了,请在输入网址后,按CTRL+F5,强制刷新下二维码网页,把之前的网页缓存去除,不然替换程序就没效果了)
查看下二维码html源码中是否替换成功:
可以看到上面的html代码已经替换成我们的js文件,赶快登录测试下。
至此修改成功,我写这篇文章的目的,是想验证一下,能否修改某些网站返回的数据或操作,并不是鼓励大家去乱修改人家的网站或运用于黑客技术,技术都是由两面性的,是一把双刃剑,就看使用的人的素质了,我想通过分享这篇文章,对于有些想做快速二次网站开发的技术人员是一种很好的启发,当然了使用此方法,请注意修改网站的合法申明,防止自己陷入囧地,好了,话不多说了,请关注我后续的技术博文,谢谢大家的观看!