作为一个偶尔摸鱼玩页游的玩家,最近遇到了一个挺烦人的问题:一款页游把核心VIP功能做了充值限制,不充钱就没法解锁,体验感大打折扣。本来想弃坑,但转念一想,页游本质上是通过前端JS控制交互和功能权限,说不定能找到破解的突破口——毕竟前端代码都要加载到本地,只要能修改关键逻辑,就能绕过充值限制。
于是就有了这段从“临时凑活用”到“永久自动化”的实操过程,记录下来分享给有同样需求的朋友,也算是对自己解决问题的一次复盘,全程干货,新手也能跟着操作。
一、初遇转机:Chrome Override Content 临时破解
首先确认了这款游戏是纯页游,哪怕有客户端,本质也是套壳的浏览器内核,所有核心逻辑都在JS文件里。既然是页游,最直接的方法就是通过浏览器开发者工具修改前端代码,这也是网页类应用破解最基础、最易上手的方式。
具体操作很简单,用Chrome浏览器打开游戏地址,按下F12打开开发者工具,步骤如下:
- 切换到「Network」面板,勾选「Preserve log」(保留日志),刷新游戏页面,找到核心JS文件——也就是后面要重点操作的
Main.min.js(路径:https://xxx.com/main/Main.min.js); - 右键点击这个JS文件,选择「Override content」(覆盖内容),Chrome会提示选择一个本地文件夹,用于保存修改后的JS文件;
- 切换到「Sources」面板,找到刚才选中的JS文件,直接编辑里面的VIP权限判断逻辑(比如把“是否充值”的判断条件从
true改为false); - 保存修改后,刷新游戏页面,奇迹发生了——VIP功能居然解锁了,不用充值也能正常使用!
这种方法的优点是零门槛、快速生效,不需要任何额外工具,适合临时测试和验证思路。但缺点也很明显:不够方便,且只能在Chrome浏览器中生效。
因为游戏有独立客户端(虽然是套壳),每次想玩都要打开Chrome,还要确保开发者工具处于开启状态,一旦关闭浏览器、清除缓存,或者换一台设备,修改就会失效,每次都要重新操作一遍,非常繁琐。
于是萌生了一个念头:能不能实现「一次修改,永久生效」,不管是用浏览器还是游戏客户端,都能自动加载我修改后的JS文件?这就需要用到抓包代理工具——mitmproxy。
二、进阶方案:mitmproxy 拦截JS并替换本地文件
mitmproxy 是一款强大的开源HTTP/HTTPS代理工具,不仅能抓包查看网络请求,还能通过编写Python脚本,实现请求/响应的拦截、修改、替换等操作,相当于在客户端和服务器之间加了一个“中间站”,所有网络请求都会经过这个中间站,我们可以在这里做手脚,强制替换服务器返回的JS文件为我们本地修改好的版本。
核心思路很简单:拦截游戏向服务器请求 Main.min.js 的请求,不返回服务器的原始文件,而是返回我们本地修改好的JS文件,这样不管是浏览器还是游戏客户端,只要走我们的代理,就能加载到破解后的代码。
2.1 前期准备
在开始编写脚本前,需要做好两件事:
- 安装mitmproxy:通过pip命令安装,非常简单,打开CMD/PowerShell,输入
pip install mitmproxy即可完成安装(需要Python环境,建议Python3.8+); - 保存本地JS文件:将Chrome中修改好的
Main.min.js文件,保存到本地固定路径,我这里保存的路径是E:\main\Main.min.js(路径可以自定义,但要记住,后面脚本中需要用到)。
2.2 编写mitmproxy替换脚本
mitmproxy支持通过Python脚本扩展功能,我们需要编写一个简单的脚本,实现“拦截指定JS请求→替换为本地文件”的功能。
首先,新建一个文本文件,命名为 replace_js.py(文件名可自定义),然后复制下面的代码,修改对应的目标URL和本地文件路径即可:
"""
mitmproxy 脚本:拦截指定页游JS并替换为本地破解版(禁用304缓存)
功能:拦截游戏核心JS,强制返回本地修改后的文件,解决Chrome临时覆盖不便的问题
使用方法:mitmproxy -s replace_js.py
"""
import mitmproxy.http
from mitmproxy import ctx
# 要拦截的远程JS地址(游戏核心JS,从Chrome Network面板获取)
TARGET_URL = "https://xxx.com/main/Main.min.js"
# 本地修改后的JS文件路径(替换成你自己的保存路径)
LOCAL_JS_PATH = r"E:\main\Main.min.js"
class ReplaceJS:
def __init__(self):
ctx.log.info("✅ 页游JS替换脚本已加载(强制禁用304缓存)")
ctx.log.info(f"🎯 目标拦截URL: {TARGET_URL}")
ctx.log.info(f"📂 本地破解JS路径: {LOCAL_JS_PATH}")
# 核心:删除请求缓存头,避免服务器返回304(关键修复步骤)
def request(self, flow: mitmproxy.http.HTTPFlow):
if flow.request.pretty_url == TARGET_URL:
# 删除浏览器/客户端发送的缓存协商头,防止304缓存
if "If-None-Match" in flow.request.headers:
del flow.request.headers["If-None-Match"]
if "If-Modified-Since" in flow.request.headers:
del flow.request.headers["If-Modified-Since"]
ctx.log.info("🧹 已清除缓存头,强制服务器返回新内容")
# 替换响应:将服务器返回的JS替换为本地破解版
def response(self, flow: mitmproxy.http.HTTPFlow):
if flow.request.pretty_url == TARGET_URL:
try:
# 读取本地修改后的JS文件
with open(LOCAL_JS_PATH, "r", encoding="utf-8") as f:
local_content = f.read()
# 强制覆盖响应:设置状态码为200,替换响应内容
flow.response.status_code = 200
flow.response.text = local_content
# 双重保险:给响应添加禁用缓存头,避免浏览器缓存旧内容
flow.response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
flow.response.headers["Pragma"] = "no-cache"
flow.response.headers["Expires"] = "0"
ctx.log.info("✅ 成功替换为本地破解JS!")
except Exception as e:
ctx.log.error(f"❌ 读取本地JS失败: {str(e)}")
ctx.log.error(f"请检查本地文件路径是否正确: {LOCAL_JS_PATH}")
# 启动插件
addons = [ReplaceJS()]
2.3 脚本核心逻辑说明
很多朋友可能会遇到304缓存的问题(后面会详细说),所以这个脚本不仅实现了JS替换,还做了缓存优化,核心分为两步:
- 请求阶段(request):删除客户端发送的
If-None-Match和If-Modified-Since两个缓存头。这两个头是浏览器/客户端用来和服务器协商缓存的,有了它们,服务器会返回304状态码,不返回实际内容,导致我们的替换失效; - 响应阶段(response):读取本地破解后的JS文件,强制将响应状态码设为200(表示成功),并替换响应内容为本地文件,同时添加禁用缓存的响应头,避免浏览器缓存旧的JS内容。
三、踩坑与解决:304缓存导致替换失效
刚开始编写脚本时,我只写了响应阶段的替换逻辑,启动mitmproxy后,发现游戏依然加载的是服务器的原始JS,查看mitmproxy日志,发现状态码一直是304,没有执行替换操作——这就是最常见的缓存坑。
原因很简单:浏览器/游戏客户端会缓存之前加载过的JS文件,再次请求时,会带上 If-None-Match(文件哈希值)和If-Modified-Since(文件修改时间)两个头,服务器判断文件没有变化,就返回304,告诉客户端“用你本地缓存的文件就行”,这样我们的替换脚本就没有机会生效。
解决方法就是在脚本中添加「删除缓存头」的逻辑(也就是上面脚本中request方法的内容),让服务器无法识别客户端的缓存,只能返回200状态码和实际内容,这样我们的替换逻辑才能正常执行。
这一步也是整个实操过程中最关键的踩坑点,很多新手会因为忽略缓存问题,导致脚本编写完成后无法生效,这里特意重点说明,避免大家走弯路。
四、最终生效:启动代理,实现永久替换
脚本编写完成后,就可以启动mitmproxy,实现永久替换了,步骤如下:
- 启动mitmproxy:打开CMD/PowerShell,进入
replace_js.py脚本所在的文件夹,输入命令mitmproxy -s replace_js.py,启动代理服务(默认代理端口是8080); - 配置代理:不管是用Chrome浏览器还是游戏客户端,都需要配置mitmproxy代理——地址设为
127.0.0.1,端口设为8080(游戏客户端如果没有代理设置,可以在系统设置中配置全局代理); - 验证效果:打开游戏,刷新页面,查看mitmproxy日志,如果出现「成功替换为本地破解JS!」的提示,就说明生效了,此时不管是浏览器还是游戏客户端,都能加载到我们修改后的JS文件,VIP功能永久解锁,不用再重复操作。
五、优化升级:用Proxifier分流,避免影响其他进程
上面配置全局代理后,会导致电脑上所有进程(比如浏览器、微信、办公软件等)的网络请求都经过mitmproxy,不仅可能影响其他软件的正常使用,还会增加mitmproxy的负担,甚至出现不必要的网络异常。
因此,我们可以用Proxifier工具实现进程分流:只让游戏客户端的所有.exe进程走mitmproxy代理,其他进程正常走本地网络,既保证JS替换生效,又不影响日常使用,这也是实操中非常实用的优化步骤。
5.1 前期准备
- 安装Proxifier:网上搜索Proxifier(支持Windows系统),下载安装后打开,无需复杂配置,直接进入规则设置即可;
- 找到游戏进程目录:打开游戏客户端,右键点击任务栏中的游戏图标,选择「打开文件所在位置」,即可定位到游戏的安装目录(比如我的路径是
D:\Game\wzzx2_sanguo),该目录下会包含游戏的所有.exe可执行文件。
5.2 Proxifier分流配置步骤
配置核心:新建代理规则,仅匹配游戏目录下的所有.exe进程,将其分流到mitmproxy代理,具体步骤如下:
- 打开Proxifier,点击顶部菜单栏「Profile」→「Proxies」,点击「Add」添加mitmproxy代理;
- 在弹出的窗口中,填写代理信息:Address填
127.0.0.1,Port填8080(和mitmproxy默认端口一致),Protocol选择「HTTPS」,点击「OK」保存; - 点击顶部菜单栏「Profile」→「Rules」,点击「Add」新建分流规则;
- 在规则编辑窗口,进行3个关键设置: ① 「Name」:自定义规则名称,比如「页游JS替换分流」,方便后续识别; ② 「Applications」:点击「Browse」,选择游戏安装目录,勾选「Include subfolders」(包含子文件夹),然后在文件类型中选择「*.exe」,这样就能匹配该目录下所有的游戏进程; ③ 「Action」:下拉选择「Use proxy [127.0.0.1:8080]」(也就是我们刚才添加的mitmproxy代理);
- 点击「OK」保存规则,然后将该规则拖动到规则列表的顶部(确保优先级最高,避免被其他规则覆盖);
- 验证分流效果:启动mitmproxy和游戏客户端,打开Proxifier的「Log」面板,能看到只有游戏相关的.exe进程在走代理,其他进程(如Chrome、微信)无代理日志,说明分流成功。
5.3 分流注意事项
- 确保游戏目录选择正确,若游戏有多个.exe进程(比如主程序、更新程序),只要勾选「*.exe」,就能全部匹配,无需单独添加;
- Proxifier和mitmproxy需同时启动,且代理端口保持一致(默认8080),若修改了mitmproxy的端口,需同步修改Proxifier中的代理配置;
- 若后续游戏更新,安装目录发生变化,需重新修改Proxifier规则中的「Applications」路径,否则分流会失效。
六、总结与延伸
整个过程其实很简单,核心就是“前端逻辑可修改→临时覆盖验证→代理永久替换→分流优化”,从Chrome的临时方案,到mitmproxy的永久方案,再到Proxifier的分流优化,一步步解决了“便捷性、持久性、不影响其他进程”的问题。
回顾整个实操:
- Chrome Override Content 适合快速验证破解思路,零门槛,但不够便捷,无法跨客户端生效;
- mitmproxy 脚本适合实现永久替换,一次配置,终身生效,不管是浏览器还是套壳客户端都能使用,核心是解决304缓存问题;
- Proxifier 分流是关键优化,能精准匹配游戏进程,避免代理影响其他软件,让整个方案更完善、更实用;
- 本质上,页游的前端权限控制(比如VIP功能)都是通过JS逻辑判断的,只要能修改关键逻辑,就能绕过限制,这也是前端应用的一个常见特点——毕竟代码要加载到本地,就有被修改的可能。
最后提醒一句:本文仅用于个人学习和技术交流,破解游戏付费功能可能违反游戏用户协议,请谨慎使用,尊重开发者的劳动成果。如果是自己开发的页游,也可以通过这个思路,检查前端权限控制的漏洞,加强安全防护。
如果大家在操作过程中遇到问题(比如mitmproxy安装失败、代理配置无效、304缓存依然存在、Proxifier分流不生效等),可以在评论区留言,我会尽力解答~