全站首发-Mitmproxy的使用实例-修改电脑上微信的文件传输助手保存图片的文件名称(如何快速二次开发现有网站的探索和思路)

微信的文件助手,我想大家一定有用到过,可以说是除了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文件,赶快登录测试下。

至此修改成功,我写这篇文章的目的,是想验证一下,能否修改某些网站返回的数据或操作,并不是鼓励大家去乱修改人家的网站或运用于黑客技术,技术都是由两面性的,是一把双刃剑,就看使用的人的素质了,我想通过分享这篇文章,对于有些想做快速二次网站开发的技术人员是一种很好的启发,当然了使用此方法,请注意修改网站的合法申明,防止自己陷入囧地,好了,话不多说了,请关注我后续的技术博文,谢谢大家的观看!

 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-19 23:18:08       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-19 23:18:08       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-19 23:18:08       45 阅读
  4. Python语言-面向对象

    2024-07-19 23:18:08       55 阅读

热门阅读

  1. 监测vuex中state的变化

    2024-07-19 23:18:08       17 阅读
  2. 算法面试题五

    2024-07-19 23:18:08       19 阅读
  3. c++一句话求前缀和,不用循环

    2024-07-19 23:18:08       16 阅读
  4. 双指针算法入门 —— 常见例题

    2024-07-19 23:18:08       12 阅读
  5. 什么是云服务器?

    2024-07-19 23:18:08       16 阅读
  6. C++知识点总结(48):树与二叉树

    2024-07-19 23:18:08       15 阅读