狂自私

导航

批量给未加密的word、Excel、rar、zip、pdf文件加密

前阵子对接的某个厂家被甲方的红队攻破了,底裤给都掀了。并且还波及到我们了,因为有一份我们系统的接入规范文件(word)在被攻破的服务器上,然后顺着文档里面写的几个ip地址继续渗透了。

我有些焦虑,想着把工作相关的文档文件都给加密上。

 

2025年06月24日更新:找到更全面的方式来确认docx、xlsx文档是否加密了,同时更新一下关于日志输出的逻辑


 

加密word

仅限于windows平台,并且必须要有office环境,wps不行。

<#
该脚本的一些细节只适合我的工作电脑,我的工作电脑只能正常安装使用office 2010,但是PowerShell不能正确的创建Word.Application对象,然后我安装了office 2019(但是只能安装,无法正常使用);
所以,我实际上在使用office 2019的DLL对象来生成能正常在office 2010中使用的docx文档。
#>
# 指定目录
$root_path = "D:\temp"
$word = New-Object -ComObject Word.Application
$word.Visible =$false
# 指定密码
#$password = 'Scsgcc12#$56_wordDocx'    # 特殊字符$不可以使用
$password = 'ScsgccDocx1@3$5'           #目前测试出,密码长度要小于16位,否则加密文档无论如何都打不开
# 日志
$date_now = Get-Date -Format 'yyyy年MM月dd日'
$log_dir_path = Join-Path $root_path $date_now
New-Item -Path $log_dir_path -ItemType Directory -Force > $null
$log_out_file = Join-Path $log_dir_path 'word文档加密_日志信息.txt'
$log_info=""
# 计数
$file_num=0
$word_files=Get-ChildItem -LiteralPath $root_path -Recurse -Filter *.doc?
try{
    $word_files|ForEach-Object{
    $file_num+=1
    if($file_num % 1000 -eq 0){
        $log_info >> $log_out_file
        $log_info=""
    }
    $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 正在处理 $($_.FullName) 文档。`n"
        $document=$null
        if($_.Extension -eq '.doc'){
            try{
                # 保存三个时间值
                $CreationTime=$_.CreationTime
                $LastWriteTime=$_.LastWriteTime
                $LastAccessTime=$_.LastAccessTime
                # 转换为docx并加密,然后删除doc文件
                $document = $word.Documents.Open($_.FullName,$false,$true)
                # $document = $word.Documents.Open($_.FullName,$false,$true,$false,$null,$null,$false,$null,$null,$null,$null,$null,$true)
                # 更改后缀
                $out_path = [System.IO.Path]::ChangeExtension($_.FullName, "docx")
                $document.SaveAs($out_path, 16, $null,$password)
                $document.Close()
                Remove-Item -LiteralPath $_.FullName -Force -Recurse
                #更新时间值
                $new_word_file_obj = Get-ChildItem -LiteralPath $out_path
                $new_word_file_obj.CreationTime = $CreationTime
                $new_word_file_obj.LastWriteTime = $LastWriteTime
                $new_word_file_obj.LastAccessTime = $LastAccessTime
                $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 已将 $($_.FullName) 转换为 $out_path 并加密。`n"
            }
            catch{
                if($document){
                    $document.Close()
                }
                New-Item -Path $path -ItemType Directory -Force > $null
                $log_info+="错误:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")`n"
                $log_info >> $log_out_file
                $log_info=""
                $_ >> $log_out_file
            }
            finally{
                # 释放 COM 对象
                if ($document) {
                    [System.Runtime.InteropServices.Marshal]::ReleaseComObject($document) | Out-Null
                    $document = $null
                }
            }
        }
        elseif($_.Extension -eq '.docx'){
            # 检查其是否加密,若是加密,则忽略,若是未加密,则加密
            try{
                $is_encrypt_1 = Select-String -LiteralPath $_.FullName -Quiet -SimpleMatch  -Pattern 'http://schemas.microsoft.com/office/2006/keyEncryptor/password'
                $is_encrypt_2 = Select-String -Pattern "M.i.c.r.o.s.o.f.t. .E.n.h.a.n.c.e.d. .R.S.A. .a.n.d. .A.E.S. .C.r.y.p.t.o.g.r.a.p.h.i.c. .P.r.o.v.i.d.e.r" -Path $_.FullName -Quiet
                $is_encrypt = $is_encrypt_1 -or $is_encrypt_2
                if(-not $is_encrypt){
                    # 保存三个时间值
                    $CreationTime=$_.CreationTime
                    $LastWriteTime=$_.LastWriteTime
                    $LastAccessTime=$_.LastAccessTime
                    # 加密
                    $document = $word.Documents.Open($_.FullName,$false,$true
) $out_path = $_.FullName + 'x' $document.SaveAs($out_path, 16, $null, $password) $document.Close($false) Remove-Item -LiteralPath $_.FullName -Force Rename-Item -LiteralPath $out_path -NewName $_.FullName #更新时间值 $new_word_file_obj = Get-ChildItem -LiteralPath $_.FullName $new_word_file_obj.CreationTime = $CreationTime $new_word_file_obj.LastWriteTime = $LastWriteTime $new_word_file_obj.LastAccessTime = $LastAccessTime $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 已将 $($_.FullName) 加密。`n" } } catch{ if($document){ $document.Close($false) } $log_info+="错误:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")`n" $log_info >> $log_out_file $log_info="" $_ >> $log_out_file } finally{ # 释放 COM 对象 if ($document) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($document) | Out-Null $document = $null } } } } } catch{ $log_info+="错误:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")`n" $log_info >> $log_out_file $log_info="" $_ >> $log_out_file } finally{ if($word){ $word.Quit() [System.Runtime.InteropServices.Marshal]::ReleaseComObject($word) | Out-Null } [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 已完成将 $root_path 目录下的word文档加密。`n" $log_info>> $log_out_file }

 

然后借助任务计划程序,可以实现每天自动执行。

加密Excel

仅限于windows平台,并且必须要有office环境,wps不行。

<#
该脚本的一些细节只适合我的工作电脑,我的工作电脑只能正常安装使用office 2010,但是PowerShell不能正确的创建Word.Application对象,然后我安装了office 2019(但是只能安装,无法正常使用);
所以,我实际上在使用office 2019的DLL对象来生成能正常在office 2010中使用的docx文档。
#>
# 指定目录
$root_path = "D:\temp"
# 指定秘密
$excel_password = 'Scsgcc!2#4%Xlsx'  # Excel 加密密码
$excel_files = Get-ChildItem $root_path -Recurse -Filter *.xls?
# 日志
$date_now = Get-Date -Format 'yyyy年MM月dd日'
$log_dir_path = Join-Path $root_path $date_now
New-Item -Path $log_dir_path -ItemType Directory -Force > $null
$log_out_file = Join-Path $log_dir_path 'excel文档加密_日志信息.txt'
$log_info=""
# 计数
$file_num=0
try {
    # 创建 Excel COM 对象
    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $false
    $excel.DisplayAlerts = $false  # 禁用警告弹窗

    $excel_files | ForEach-Object {
        $file_num+=1
        if($file_num % 1000 -eq 0){
            $log_info >> $log_out_file
            $log_info=""
        }
        $workbook = $null
        $excel_file_path = $_.FullName
        $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 正在处理 $($_.FullName) 文档。`n" 
        try {
            if ($_.Extension -eq '.xls') {
                # 处理旧版 .xls 文件(转换为 .xlsx 并加密)
                $CreationTime = $_.CreationTime
                $LastWriteTime = $_.LastWriteTime
                $LastAccessTime = $_.LastAccessTime

                $workbook = $excel.Workbooks.Open($_.FullName)
                $out_path = [System.IO.Path]::ChangeExtension($_.FullName, "xlsx")
                $workbook.SaveAs($out_path, 51, $excel_password)  # 51 = xlsx 格式
                $workbook.Close($false)

                # 恢复时间属性并删除原文件
                $newFile = Get-Item -LiteralPath $out_path
                $newFile.CreationTime = $CreationTime
                $newFile.LastWriteTime = $LastWriteTime
                $newFile.LastAccessTime = $LastAccessTime
                Remove-Item -LiteralPath $_.FullName -Force
                $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 已将 $($_.FullName) 转换为 $out_path 并加密。`n"
            }
            elseif ($_.Extension -eq '.xlsx') {
                # 检查是否已加密
                $is_encrypt_1 = Select-String -LiteralPath $_.FullName -Quiet -SimpleMatch  -Pattern 'http://schemas.microsoft.com/office/2006/keyEncryptor/password'
                $is_encrypt_2 = Select-String -Pattern "M.i.c.r.o.s.o.f.t. .E.n.h.a.n.c.e.d. .R.S.A. .a.n.d. .A.E.S. .C.r.y.p.t.o.g.r.a.p.h.i.c. .P.r.o.v.i.d.e.r" -Path $_.FullName -Quiet
                $is_encrypt = $is_encrypt_1 -or $is_encrypt_2
                if (-not $is_encrypt) {
                    # 加密现有 .xlsx 文件
                    $CreationTime = $_.CreationTime
                    $LastWriteTime = $_.LastWriteTime
                    $LastAccessTime = $_.LastAccessTime

                    $workbook = $excel.Workbooks.Open($_.FullName)
                    $temp_path = [System.IO.Path]::GetTempFileName() + ".xlsx"
                    $workbook.SaveAs($temp_path, 51, $excel_password)  # 51 = xlsx 格式
                    $workbook.Close($false)

                    # 替换原文件并恢复时间属性
                    Remove-Item -LiteralPath $_.FullName -Force
                    Move-Item -LiteralPath $temp_path -Destination $_.FullName -Force
                    $newFile = Get-Item -LiteralPath $_.FullName
                    $newFile.CreationTime = $CreationTime
                    $newFile.LastWriteTime = $LastWriteTime
                    $newFile.LastAccessTime = $LastAccessTime
                    $log_info+="信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 已将 $($_.FullName) 加密。`n"
                }
            }
        }
        catch {
            if ($workbook) { $workbook.Close($false) }
            $log_info+="错误:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")`n"
            $log_info>> $log_out_file
            $log_info=""
            $_ >> $log_out_file
        }
        finally {
            if ($workbook) {
                [System.Runtime.InteropServices.Marshal]::ReleaseComObject($workbook) | Out-Null
                $workbook = $null
            }
        }
    }
}
catch {
    $log_info+="错误:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")`n"
    $log_info>> $log_out_file
    $log_info=""
    $_ >> $log_out_file
}
finally {
    if ($excel) {
        $excel.Quit()
        [System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null
        $excel = $null
    }
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
    $log_info >> $log_out_file
    "信息:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") - 已完成将 $root_path 目录下的Excel文档加密。" >> $log_out_file
}

 

加密PDF

由于没有原生的pdf dll,所以这里使用了Python来实现。

 1 # 需先安装 Python 和 PyPDF2:pip install PyPDF2
 2 from PyPDF2 import PdfWriter, PdfReader
 3 import os,sys,win32file,pywintypes,ctypes
 4 def is_pdf_encrypted(file_path:str)->bool:
 5     '''
 6     检查是否加密
 7     '''
 8     try:
 9         with open(file_path, "rb") as f:
10             reader = PdfReader(f)
11             # 如果加密,尝试用空密码解密(不会修改文件)
12             if reader.is_encrypted:
13                 return True
14             return False
15     except Exception as e:
16         print(f"检测失败: {e}")
17         return False
18 
19 def 设置打开密码并替换文件(file_path:str,pw:str):
20     writer = PdfWriter()
21     reader = PdfReader(file_path)
22     for page in reader.pages:
23         writer.add_page(page)
24     writer.encrypt(pw)
25     new_pdf_path = os.path.join(os.path.dirname(file_path),os.path.basename(file_path))+'.tmp'
26     with open(new_pdf_path, "wb") as f:
27         writer.write(f)
28     # 获取时间
29     st = os.stat(file_path)
30     # 修改时间 (Last Modified Time)
31     mtime = st.st_mtime
32     # 访问时间 (Last Access Time)
33     atime = st.st_atime
34     # 创建时间 (Creation Time,仅Windows有效)
35     if os.name == 'nt':
36         ctime = st.st_ctime
37     else:
38         ctime = None  # Linux/Mac 无创建时间概念
39     # 修改时间
40     os.utime(new_pdf_path, (atime, mtime))
41      #将时间戳转换为 Windows 的 FILETIME 格式
42     ft = pywintypes.Time(ctime)
43     handle = win32file.CreateFile(
44         new_pdf_path,
45         win32file.GENERIC_WRITE,
46         0, None,
47         win32file.OPEN_EXISTING,
48         0, None
49     )
50     win32file.SetFileTime(handle, ft, None, None)
51     handle.Close()
52     # 清理文件的特殊属性,比如只读,删除只读文件会被拒绝
53     SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
54     FILE_ATTRIBUTE_NORMAL = 0x80
55     SetFileAttributes(file_path, FILE_ATTRIBUTE_NORMAL)
56     #删除源文件
57     os.remove(file_path)
58     # 重命名加密之后的pdf文件
59     while True:
60         try:
61             os.rename(new_pdf_path,file_path)
62             break
63         except Exception as e:
64             time.sleep(1)
65     pass;
66 def process_pdfs_in_directory(root_dir):
67     # 遍历目录及子目录
68     pdf_list=[]
69     for root, dirs, files in os.walk(root_dir):
70         for file in files:
71             if file.lower().endswith('.pdf'):
72                 file_path = os.path.join(root, file)
73                 pdf_list.append(file_path)
74     return pdf_list;
75 def main(root_path:str,pw:str):
76     pdf_list=process_pdfs_in_directory(root_path)
77     for pdf_path in pdf_list:
78         if(not is_pdf_encrypted(pdf_path)):
79             print(f'开始加密:【{pdf_path}】。')
80             设置打开密码并替换文件(pdf_path,pw);
81 if __name__ == "__main__":
82     root_path = r'D:\temp'
83     pw='1234567890'
84     main(root_path,pw)

 

加密rar、zip文件

强依赖WinRAR软件,原则上这份代码稍加修改就可以匹配更多类型的压缩文件。

 1 # 根路径
 2 $root_path="D:\temp"
 3 # 密码
 4 $password = '1234567890'
 5 
 6 $winrarPath  = "C:\Program Files (x86)\WinRAR\WinRAR.exe"
 7 $rar_zip_files = Get-ChildItem -Path $root_path -Include *.rar, *.zip -File -Recurse # 不能使用LiteralPath参数
 8 foreach($file in $rar_zip_files){
 9     #$dst_dir=Join-Path $file.DirectoryName -ChildPath $file.BaseName
10     $dst_dir=Join-Path $env:TEMP -ChildPath $file.BaseName
11     New-Item -ItemType Directory -Path $dst_dir -Force  > $null
12     
13     # Start-Process -FilePath "$env:comspec" -ArgumentList "/c","dir","`"%SystemDrive%\Program Files`""
14     # WinRAR.exe x $file (Join-Path $dst_dir '\') -p111 -Y
15     $t=Join-Path $dst_dir '\'
16     $ArgumentList = "x `"$file`" `"$t`" -p111 -Y"
17     $p=Start-Process -FilePath $winrarPath -ArgumentList  $ArgumentList -Wait -PassThru
18     $source_file_obj_CreationTime=$file.CreationTime
19     $source_file_obj_LastAccessTime=$file.LastAccessTime
20     $source_file_obj_LastWriteTime=$file.LastWriteTime
21     if($p.ExitCode -eq 1 -or $p.ExitCode -eq 0){
22         # 解压缩成功,说明没有设置密码"
23         "解压缩:【$($file.FullName)】到【$t】成功。"
24 
25         # 检查目录是否嵌套了
26         $嵌套_路径 = Join-Path $dst_dir -ChildPath $file.BaseName
27         $tt = Get-ChildItem $嵌套_路径 2>&1 $null
28         if($?){
29             # 存在嵌套目录,需要移动并覆盖
30             Move-Item -Path ($嵌套_路径+'/*') -Destination $dst_dir -Force
31             "移动文件【$嵌套_路径】到【$dst_dir】"
32             Remove-Item $嵌套_路径 -Force -ErrorAction SilentlyContinue -Recurse
33             "删除空文件夹【$嵌套_路径】。"
34         }
35         $source_file_obj = $file
36         $hp = '-hp' + $password
37         <# 原先是直接在当前路径操作的,后续改为了在$temp目录操作,就不需要这个判定了
38         if($source_file_obj.fullname -eq $source_file_obj.FullName){
39             Remove-Item -LiteralPath $source_file_obj.FullName -Force -Recurse
40             "删除路径:【$($source_file_obj.FullName)】。"
41         }
42         #>
43         Remove-Item -LiteralPath $source_file_obj.FullName -Force -Recurse
44         "删除路径:【$($source_file_obj.FullName)】。"
45         # 控制台 RAR 不能创建 ZIP 压缩文件。
46         $rar_path = [System.IO.Path]::ChangeExtension($source_file_obj.FullName, "rar")
47         $ArgumentList = "a `"$rar_path`" `"$dst_dir`" -ep1 -df $hp"
48         $p=Start-Process -FilePath $winrarPath -ArgumentList $ArgumentList -Wait -PassThru
49         if($p.ExitCode -eq 1 -or $p.ExitCode -eq 0){
50             "压缩:【$dst_dir】成功。"
51             $new_rar_file_obj = Get-ChildItem $rar_path
52             #恢复时间属性
53             $new_rar_file_obj.CreationTime = $source_file_obj_CreationTime
54             $new_rar_file_obj.LastAccessTime  = $source_file_obj_LastAccessTime
55             $new_rar_file_obj.LastWriteTime = $source_file_obj_LastWriteTime
56             # 移动文件到原来的位置
57             if($new_rar_file_obj.FullName -ne $file.FullName){
58                 Move-Item -LiteralPath $new_rar_file_obj.FullName -Destination $file.FullName -Force
59                 "移动文件:$($new_rar_file_obj.FullName) 到 $($file.FullName) 。"
60             }
61         }
62     }
63     elseif($p.ExitCode -eq 11){
64         Get-ChildItem -Path $dst_dir 2> $null
65         if($?){
66             # 目标目录存在,需要删除
67             Remove-Item -Path $dst_dir -Force -Recurse
68             "删除目录:【$dst_dir】。"
69         }
70     }
71     ""
72 }

没有实时检测的方案,实时的就需要人有这样的意识。

posted on 2025-06-19 14:52  狂自私  阅读(34)  评论(0)    收藏  举报