Ernestpneug 发表于 2025-8-31 22:39:13

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服务器,如有违规烦请告知)

huoxianghui913 发表于 2025-8-31 22:39:55

烦请所有遇到闪退的坛友,先认真阅读帖子内容,确实使用方法正确后,带版本号回帖。

huoxianghui913 发表于 2025-8-31 22:40:38

我记得有两款软件分别是PDF Shaper和Advanced PDF Password Recovery可以破解加密且可以正常查看的PDF文件的。

寒哥Gh61ac8 发表于 2025-8-31 22:40:51

PDF中维护了一个表,记录权限、权限密码、所有者密码。如果设置所有者密码,文件内容就被对等加密了,所以不可能解密。而如果只设置权限密码,那直接删除权限密码并将权限设为全部允许就可以了。
这种权限密码是靠软件自觉遵守ISO规范实现的。

huoxianghui913 发表于 2025-8-31 22:41:42


实测 能够去掉了密码和签名。

增加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

风之影赫 发表于 2025-8-31 22:41:49

你这里逻辑不对
```
HKEY_CLASSES_ROOT\*\shell\
```
是向所有文件右键菜单加选项,应该只向pdf后缀加。

```
HKEY_CLASSES_ROOT\SystemFileAssociations\.pdf\shell
```
或者
```
HKEY_CLASSES_ROOT\.pdf\shell
```

还是推荐用我发的1.1版本安装包,避免卸载残留:lol

风之影赫 发表于 2025-8-31 22:42:33

增加个图形界面的代码:

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()

风之影赫 发表于 2025-8-31 22:43:19

非常感谢https://static.52pojie.cn/static/image/smiley/default/17.gif

寒哥Gh61ac8 发表于 2025-8-31 22:44:16

还是挺需要这种小工具的。

huoxianghui913 发表于 2025-8-31 22:44:29

Win10运行直接闪退!
疑似需要运行环境或者框架
页: [1] 2
查看完整版本: PDF权限密码解密