批改网无法粘贴实现——js逆向与解决方法
绕过网页禁止粘贴的方法
JS逆向分析
目标页面通过 init_no_paste() 函数实现粘贴限制,核心逻辑包括:
- 阻止右键菜单(
contextmenu) - 禁用文本选择(
selectstart) - 拦截粘贴事件(
onpaste)并提示限制 - 禁止拖拽功能(
dragenter)
关键变量 _no_paste 控制限制开关,值为 “1” 时启用限制。
解决方法
方法一
刷新网页,在 JS 加载完成前快速粘贴(利用加载时序差)。
方法二:书签注入法
刷新网页后,点击提前设置的书签注入以下代码:
javascript:(function(){
window.init_no_paste = function() {};
document.onpaste = null;
console.log("已解除粘贴限制 ✅");
})();
书签注入法复写JavaScript是一种在浏览器环境中,通过书签工具(Bookmarklet) 注入自定义代码,从而覆盖或修改网页原有JavaScript函数的技术。其核心原理是利用*浏览器书签的javascript:协议,将待执行的代码封装为可点击的书签,在目标网页上下文执行时,优先覆盖网页中原有的函数定义或事件绑定,从而绕过网页的功能限制(如禁用粘贴、右键等)。 具体来说,当用户点击书签时,封装的代码会在网页的全局作用域中运行,通过重写目标函数(如init_no_paste)或解除事件绑定(如document.onpaste),提前拦截网页原有的限制逻辑,使被禁用的功能(如粘贴)恢复正常。这种方法无需修改网页源码,仅通过浏览器自带的书签功能即可实现对JavaScript逻辑的动态复写,是前端调试和功能解锁的轻量型实用技巧。
Chrome 浏览器书签添加方法:



名称可根据需求随意设置,只需在书签的“网址”栏中填写封装好的JavaScript代码。使用时,需在网页加载阶段(如页面HTML已加载但目标JS未执行时)点击该书签,让注入的代码优先覆盖网页原有函数定义,从而实现功能复写。
方法三:油猴脚本注入
可借助Tampermonkey等浏览器脚本管理工具,将复写逻辑封装为油猴脚本。通过设置@run-at document-start(页面加载前执行),让脚本在网页原生JS加载前运行,从而从根源上覆盖目标函数,实现更持久、自动化的功能解锁。
方法四:Python脚本模拟输入
方法如题,只要不被检测到粘贴事件即可,这里附上python模拟输入的模板代码。
import tkinter as tk
from tkinter import ttk, messagebox
import pyautogui
import time
import threading
class PasteBypassTool:
def __init__(self, root):
self.root = root
self.root.title("粘贴绕过工具")
self.root.geometry("500x350")
self.root.resizable(True, True)
# 设置中文字体支持
self.style = ttk.Style()
self.style.configure("TLabel", font=("SimHei", 10))
self.style.configure("TButton", font=("SimHei", 10))
# 创建界面组件
ttk.Label(root, text="请输入要模拟输入的文本:").pack(pady=10, anchor="w", padx=20)
self.text_input = tk.Text(root, height=6, width=50, font=("SimHei", 10))
self.text_input.pack(pady=5, padx=20, fill=tk.BOTH, expand=True)
# 倒计时显示区域
self.countdown_frame = ttk.Frame(root, height=60)
self.countdown_frame.pack(pady=5, fill=tk.X)
self.countdown_frame.pack_propagate(False) # 防止框架大小被内容撑开
self.countdown_var = tk.StringVar(value="")
self.countdown_label = ttk.Label(
self.countdown_frame,
textvariable=self.countdown_var,
font=("SimHei", 24, "bold")
)
self.countdown_label.pack(side=tk.TOP, pady=10)
# 按钮区域
button_frame = ttk.Frame(root)
button_frame.pack(pady=10)
self.start_btn = ttk.Button(
button_frame,
text="开始模拟输入",
command=self.start_typing
)
self.start_btn.pack(side=tk.LEFT, padx=10)
self.stop_btn = ttk.Button(
button_frame,
text="停止",
command=self.stop_typing,
state=tk.DISABLED
)
self.stop_btn.pack(side=tk.LEFT, padx=10)
# 状态标签
self.status_var = tk.StringVar(value="就绪,请输入文本并点击开始")
ttk.Label(root, textvariable=self.status_var).pack(pady=5)
# 控制变量
self.is_typing = False
self.typing_thread = None
self.char_per_second = 10 # 每秒输入字符数
self.delay = 1.0 / self.char_per_second # 每个字符间隔时间
def start_typing(self):
"""开始模拟输入"""
text = self.text_input.get("1.0", tk.END).rstrip("\n") # 获取文本并去除末尾换行
if not text:
messagebox.showwarning("警告", "请先输入要模拟的文本")
return
self.is_typing = True
self.start_btn.config(state=tk.DISABLED)
self.stop_btn.config(state=tk.NORMAL)
self.status_var.set("准备开始,请切换到目标输入框")
# 创建并启动线程
self.typing_thread = threading.Thread(
target=self._type_text,
args=(text,)
)
self.typing_thread.daemon = True
self.typing_thread.start()
def stop_typing(self):
"""停止模拟输入"""
self.is_typing = False
self.start_btn.config(state=tk.NORMAL)
self.stop_btn.config(state=tk.DISABLED)
self.status_var.set("已停止")
self.countdown_var.set("") # 清空倒计时显示
def _update_countdown(self, value):
"""更新倒计时显示(在主线程中执行)"""
self.countdown_var.set(str(value))
def _type_text(self, text):
"""实际执行输入的函数,在单独线程中运行"""
# 倒计时5秒,让用户有时间切换到目标窗口
countdown_seconds = 5
for i in range(countdown_seconds, 0, -1):
if not self.is_typing:
# 在主线程中更新UI
self.root.after(0, self._update_countdown, "")
return
# 在主线程中更新UI
self.root.after(0, self._update_countdown, i)
time.sleep(1)
# 清空倒计时显示
self.root.after(0, self._update_countdown, "")
self.root.after(0, lambda: self.status_var.set("正在输入..."))
# 逐个字符输入
for char in text:
if not self.is_typing:
break
pyautogui.typewrite(char)
time.sleep(self.delay) # 控制输入速度
if self.is_typing: # 如果是正常完成而不是被停止
self.root.after(0, lambda: self.status_var.set("输入完成"))
self.root.after(0, lambda: self.start_btn.config(state=tk.NORMAL))
self.root.after(0, lambda: self.stop_btn.config(state=tk.DISABLED))
if __name__ == "__main__":
# 确保中文显示正常
root = tk.Tk()
app = PasteBypassTool(root)
root.mainloop()
声明
仅供学习使用,批改网泛指各种的禁止粘贴的一些网站,其中禁止粘贴功能以一些需要原创内容限制而著名,因而泛指。
收录于知乎专栏「js逆向实例」· 查看知乎原文