PDF权限密码解密
PDF权限密码解密用途
批量或单个对权限加密的PDF进行解密,同时可以去除签名。
权限加密指的是禁止编辑、禁止打印等,无法对打开文件需要密码的情况解密。符合上述情况可无需密码直接解密。
下载
制作了安装包,添加了右键菜单启动
v1.1 https://flt.lanzouo.com/idU6e30aav6
v1.0: https://flt.lanzouo.com/iGZvA309qcyf
用法
如您希望使用单文件,请下载v1.0,基本没有区别
报毒说明:经反馈,360报毒,好像是因为nuitka打包导致,具体见查毒报告
您可以review 代码,并使用nuitka/pyinstaller和inno setup自行打包使用,或使用同类软件。
选中PDF文件后右键点击移除权限
https://tc.z.wiki/autoupload/f/2G9DFBjlTqmzAWCgXZt0JUf4EiMp6e2MD203WvDVQx6yl5f0KlZfm6UsKj-HyTuv/20250721/Bhnm/0X0/202507042305712.webp或者在文件夹空白处右键点击移除PDF权限或者右键文件夹移除PDF权限或者将文件(多个文件也可以)或文件夹拖到v1.0.exe上即可,将在文件同一目录下生成_decrypt.pdf文件。
https://tc.z.wiki/autoupload/f/2G9DFBjlTqmzAWCgXZt0JUf4EiMp6e2MD203WvDVQx6yl5f0KlZfm6UsKj-HyTuv/20250721/mvOb/0X0/PixPin_2025-07-04_19-13-58-20250704191400-f2zh10k.webp
效果图
https://oss.flt6.top/imgs/20250704191454.png-init.webp
https://oss.flt6.top/imgs/20250704191547.png-init.webp
说明
因为代码简略,通过复制文件实现,因此文件较大时速度缓慢。
开源地址:https://git.flt6.top/flt/tools/src/branch/master/pdf_unlock
(由于github账号问题,更新不了存储库,暂时使用自建git服务器,如有违规烦请告知) 烦请所有遇到闪退的坛友,先认真阅读帖子内容,确实使用方法正确后,带版本号回帖。 我记得有两款软件分别是PDF Shaper和Advanced PDF Password Recovery可以破解加密且可以正常查看的PDF文件的。 PDF中维护了一个表,记录权限、权限密码、所有者密码。如果设置所有者密码,文件内容就被对等加密了,所以不可能解密。而如果只设置权限密码,那直接删除权限密码并将权限设为全部允许就可以了。
这种权限密码是靠软件自觉遵守ISO规范实现的。
实测 能够去掉了密码和签名。
增加2个bat文件实现程序右键菜单调用!
①用来添加右键菜单的bat,名称随意,我这里是【00_Add右键.bat】
@Echo Off
rem HJ合集A名称设置,可修改
set "HJ=Max小工具"
set "np=PDF移除密码签名"
set "p=%cd%\%np%.bat"
Reg.exe add "HKEY_CLASSES_ROOT\*\shell\%HJ%" /f /v "SubCommands" /t REG_SZ /d ""
Reg.exe add "HKEY_CLASSES_ROOT\*\shell\%HJ%" /f /v "Icon" /t REG_SZ /d "imageres.dll,-5310"
Reg.exe add "HKEY_CLASSES_ROOT\*\shell\%HJ%" /v "Position" /t REG_SZ /d "Top" /f
Reg.exe add "HKEY_CLASSES_ROOT\*\shell\%HJ%\shell\%np%\command" /ve /t REG_SZ /d "cmd /c \"\"%p%\" \"%%V\"\"" /f
Reg.exe add "HKCR\Directory\shell\%HJ%" /f /v "SubCommands" /t REG_SZ /d ""
Reg.exe add "HKCR\Directory\shell\%HJ%" /f /v "Icon" /t REG_SZ /d "imageres.dll,-5310"
Reg.exe add "HKCR\Directory\shell\%HJ%" /v "Position" /t REG_SZ /d "Top" /f
Reg.exe add "HKCR\Directory\shell\%HJ%\shell\%np%\command" /ve /t REG_SZ /d "cmd /c \"\"%p%\" \"%%V\"\"" /f
② 【PDF移除密码签名.bat】名称不要改,否则要改上面代码第7行set "np=PDF移除密码签名"
@echo off
"%~dp0PDF权限密码解密v1.0.exe" "%~nx1"
我这里程序名称由【v1.0.exe】改为【PDF权限密码解密v1.0.exe】
功能:文件夹上右键,可调用;PDF文件右键可调用
弄不明白的,可以下载成品 ↓↓↓
链接:https://pan.quark.cn/s/d5b84a3b3249 你这里逻辑不对
```
HKEY_CLASSES_ROOT\*\shell\
```
是向所有文件右键菜单加选项,应该只向pdf后缀加。
```
HKEY_CLASSES_ROOT\SystemFileAssociations\.pdf\shell
```
或者
```
HKEY_CLASSES_ROOT\.pdf\shell
```
还是推荐用我发的1.1版本安装包,避免卸载残留:lol 增加个图形界面的代码:
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import PyPDF2
from pathlib import Path
import threading
class PDFUnlockerGUI:
def __init__(self, root):
self.root = root
self.root.title("PDF解锁工具")
self.root.geometry("600x400")
self.root.resizable(True, True)
# 创建界面
self.create_widgets()
# 处理状态
self.is_processing = False
def create_widgets(self):
"""
创建界面组件
"""
# 主框架
main_frame = ttk.Frame(self.root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 配置网格权重
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
main_frame.columnconfigure(1, weight=1)
# 输入文件/目录选择
ttk.Label(main_frame, text="选择文件或目录:").grid(row=0, column=0, sticky=tk.W, pady=5)
self.path_var = tk.StringVar()
self.path_entry = ttk.Entry(main_frame, textvariable=self.path_var)
self.path_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(5, 5), pady=5)
self.browse_button = ttk.Button(main_frame, text="浏览...", command=self.browse_path)
self.browse_button.grid(row=0, column=2, padx=(5, 0), pady=5)
# 进度条
self.progress_var = tk.DoubleVar()
self.progress_bar = ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100)
self.progress_bar.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10)
# 状态标签
self.status_var = tk.StringVar(value="就绪")
self.status_label = ttk.Label(main_frame, textvariable=self.status_var)
self.status_label.grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=5)
# 结果文本框
self.result_text = tk.Text(main_frame, height=15, width=70)
self.result_text.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10)
# 滚动条
scrollbar = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=self.result_text.yview)
scrollbar.grid(row=3, column=3, sticky=(tk.N, tk.S))
self.result_text.configure(yscrollcommand=scrollbar.set)
# 开始按钮
self.start_button = ttk.Button(main_frame, text="开始处理", command=self.start_processing)
self.start_button.grid(row=4, column=1, pady=10)
# 配置结果文本框的网格权重
main_frame.rowconfigure(3, weight=1)
def browse_path(self):
"""
浏览文件或目录
"""
# 创建一个选择对话框
file_path = filedialog.askopenfilename(
title="选择PDF文件",
filetypes=[("PDF files", "*.pdf"), ("All files", "*.*")]
)
if not file_path:
# 如果没有选择文件,则尝试选择目录
dir_path = filedialog.askdirectory(title="选择包含PDF文件的目录")
if dir_path:
self.path_var.set(dir_path)
else:
self.path_var.set(file_path)
def copy_pdf_pages(self, input_path: str, output_path: str) -> bool:
"""
移除PDF文件的所有限制
Args:
input_path: 输入PDF文件路径
output_path: 输出PDF文件路径
Returns:
是否成功移除限制
"""
try:
with open(input_path, 'rb') as input_file:
reader = PyPDF2.PdfReader(input_file)
writer = PyPDF2.PdfWriter()
# 复制所有页面
for page in reader.pages:
writer.add_page(page)
# 写入新文件(不设置任何加密或限制)
with open(output_path, 'wb') as output_file:
writer.write(output_file)
return True
except Exception as e:
self.result_text.insert(tk.END, f"处理文件 '{input_path}' 时发生错误: {e}\n")
return False
def process_files(self):
"""
在后台线程中处理文件
"""
input_path = self.path_var.get().strip()
if not input_path:
messagebox.showerror("错误", "请选择要处理的文件或目录")
self.is_processing = False
return
path_obj = Path(input_path)
if not path_obj.exists():
messagebox.showerror("错误", "指定的文件或目录不存在")
self.is_processing = False
return
try:
if path_obj.is_dir():
files = list(path_obj.glob("**/*.pdf"))
else:
files =
total = len(files)
if total == 0:
self.result_text.insert(tk.END, "未找到PDF文件\n")
self.status_var.set("未找到PDF文件")
self.is_processing = False
return
self.result_text.insert(tk.END, f"找到 {total} 个PDF文件\n")
self.result_text.insert(tk.END, "=" * 50 + "\n")
success_count = 0
for i, pdf_file in enumerate(files, start=1):
if not self.is_processing:# 用户取消操作
break
# 更新进度
progress = (i / total) * 100
self.progress_var.set(progress)
self.status_var.set(f"正在处理: {pdf_file.name} ({i}/{total})")
self.root.update_idletasks()
if not pdf_file.is_file():
self.result_text.insert(tk.END, f"跳过非PDF文件: {pdf_file}\n")
continue
output_file = pdf_file.with_name(f"{pdf_file.stem}_decrypt.pdf")
success = self.copy_pdf_pages(pdf_file, output_file)
if success:
success_count += 1
self.result_text.insert(tk.END, f"✓ {pdf_file.name} 处理成功\n")
else:
self.result_text.insert(tk.END, f"✗ {pdf_file.name} 处理失败\n")
self.result_text.see(tk.END)
self.root.update_idletasks()
# 处理完成
self.progress_var.set(100)
self.status_var.set(f"处理完成: {success_count}/{total} 个文件成功处理")
self.result_text.insert(tk.END, "=" * 50 + "\n")
self.result_text.insert(tk.END, f"处理完成: {success_count}/{total} 个文件成功处理\n")
except Exception as e:
self.result_text.insert(tk.END, f"处理过程中发生错误: {e}\n")
self.status_var.set("处理出错")
finally:
self.is_processing = False
self.start_button.config(text="开始处理", state=tk.NORMAL)
def start_processing(self):
"""
开始或停止处理
"""
if self.is_processing:
# 停止处理
self.is_processing = False
self.start_button.config(text="开始处理", state=tk.NORMAL)
self.status_var.set("处理已停止")
else:
# 开始处理
self.is_processing = True
self.start_button.config(text="停止处理", state=tk.NORMAL)
self.result_text.delete(1.0, tk.END)
self.progress_var.set(0)
# 在新线程中处理文件,避免阻塞GUI
thread = threading.Thread(target=self.process_files)
thread.daemon = True
thread.start()
def main():
root = tk.Tk()
app = PDFUnlockerGUI(root)
root.mainloop()
if __name__ == "__main__":
main() 非常感谢https://static.52pojie.cn/static/image/smiley/default/17.gif 还是挺需要这种小工具的。 Win10运行直接闪退!
疑似需要运行环境或者框架
页:
[1]
2