大量にあるパスワード付きZIPをフォルダ構成を維持しつつまとめてクラックして解凍?
こういうフォルダ構成だとする
階層例
フォルダA/
├フォルダB/
│ └フォルダC/
│ ├パス有ZIP_1.zip (パスワード分からん)
│ └パス有ZIP_2.zip (パスワード分からん)
└フォルダD/
├パス有ZIP_3.zip (パスワードかけたっけ?)
└パス無ZIP_4.zip (パスワードかけたっけ?)
「パス有/無ZIP_#.zip」内のすべての圧縮ファイルを「パス有/無ZIP_#」に解凍
このとき、個々のZIPのパスワードは総当たりとか辞書攻撃で突破する!
解凍後
フォルダ1/
├フォルダB/
│ └フォルダC/
│ ├パス有ZIP_1.zip
│ ├パス有ZIP_1/
│ │ ├ ・・・ ←「パス付ZIP_1.zip」の中身
│ │ :
│ └パス有ZIP_2.zip
│ └パス有ZIP_2/
│ ├ ・・・
│ :
└フォルダD/
├パス有ZIP_3.zip
├パス有ZIP_3/
│ ├ ・・・
│ :
├パス無ZIP_4.zip
└パス無ZIP_4/
├ ・・・
:
必須環境
- PowerShell 6 以上 (7.2で確認)
- 7Zip4Powershell (PowerShellギャラリー)
- John The Ripper (リリースに最新Buildがある。公式サイトは古い。)
スクリプト
#UTF-8 BOM
#親フォルダ以下のZipを探し、パスワード付きだったらJohn The Ripperでクラックし、Zipのある場所に解凍する。
$path = "E:\Parent\Folder\of\many\Zip"
$Zip2JohnPath = "C:\winX64_1_JtR\JtR\run\zip2john.exe"
$JtRPath = "C:\winX64_1_JtR\JtR\run\john.exe"
$HashPath = "E:\temporary\hash.txt"
$formatted_date = (Get-Date).ToString("yyyyMMddHHmmss")
$LogTextName = ".\Crack&ExPWZipJtR"+$formatted_date+".csv"
#親フォルダ以下のZIPスキャン
$archives = Get-ChildItem -LiteralPath $path -Include *.zip -Recurse
foreach($a in $archives){
#前処理
#フォルダパス作成
$FolderPath = Join-Path $a.Directoryname $a.BaseName
Write-Host ($a.FullName + "`t is crack target")
Write-Host ($FolderPath + "`t is extract destination")
#Run Zip2John
$cmdArgList = @($a.FullName)
& $Zip2JohnPath $cmdArgList | Out-File -LiteralPath $HashPath -Encoding utf8NoBOM
If((Get-Item -LiteralPath $HashPath).length -ne 0){ #パスワード付きZipではない場合クラックしない
#Run John クラック実行
$cmdArgList = @( $HashPath,"--incremental=Alpha", "--max-length=3" )
& $JtRPath $cmdArgList
#Run John クラック後パス取得
$cmdArgList = @( "--show", $HashPath )
$Password = & $JtRPath $cmdArgList
#下記の形式で出力されるのでSplitしてパスワードだけ取得
#file.zip:password::file.zip:contents1.txt, content2.png:C:\Original\Path\to\Archive.zip
$Password = $Password.Split(":")[1]
Write-Host ($a.FullName + "`t password is`t" + $Password)
}else{
$Password = ""
Write-Host ($a.FullName + "`t password is not set`t" + $Password)
}
#Zip解凍(パスワード無しの場合、どんなパスワード引数をつけても解凍可能)
Expand-7Zip -ArchiveFileName $a.FullName -TargetPath $FolderPath -Password $Password
#やっつけなログ出力部分
If(Test-Path -LiteralPath $FolderPath){ #Pathチェック
$ExtractCheck1 = (Get-ChildItem -LiteralPath $FolderPath -Recurse -Force | Measure-Object -Sum Length).Sum -eq $Null
$ExtractCheck2 = (Get-ChildItem -LiteralPath $FolderPath -Recurse -Force | Measure-Object -Sum Length).Sum -eq 0
If($ExtractCheck1 -or $ExtractCheck2){ #解凍したフォルダのサイズが0なら失敗
$Message = ($a.FullName + "`t failed cracking`t" + $FolderPath + "`t with password`t" + $Password)
}else{
$Message = ($a.FullName + "`t successed cracking`t" + $FolderPath + "`t with password`t" + $Password)
}
}else{
$Message = ($a.FullName + "`t failed folder creation`t" + $FolderPath + "`t with password`t" + $Password)
}
Write-Host $Message
Write-Output $Message | Out-File -LiteralPath $LogTextName -Append
}
使い方
-
UTF-8(BOM有り)でどこかに保存。
-
パス変数を書き換え。
パス変数 説明 $path
ZIPが沢山入っているフォルダの親フォルダ $Zip2JohnPath
zip2john.exeへのパス $JtRPath
john.exeへのパス $HashPath
ZIPのハッシュを一時保管する場所 -
77行目を利用ケースに合わせて変更。John the Ripperの使い方は他記事へ。
$cmdArgList = @( $HashPath,"--incremental=Alpha", "--max-length=3" )
-
お好きなTerminalから実行
特徴
- ファイルパスUnicode対応
- パス有りJohn the Ripperでクラック
- パス無しZIPも解凍してくれる
- やっつけなログを出力
最後に
CPU(i9-13900K)のみで実行した場合、ZIP 200個(内アルファベット3文字のパスワード付きZIP 120個)を全解凍するのに5分程度かかった。
John the ripperが対応している形式ならZIP以外でも少し書き換えれば使えると思います。