なんかこう色々あってパスワード付きPDFファイルのパスワードを解析してみることになったのでその時のあれこれ.
雑に言えば
1. hashcatとJown the Ripperを用意する
2. JownでPDFからハッシュを抜き取る
3. hashcatでグラボをいじめる
これだけ.意外と簡単.
今回の環境.解析速度に関わるのは実質GPUのみだけど一応.
・win10 home
・Ryzen9 5900X
・RX 6800XT (ドライバ 22.5.1)
・メモリ48G
・WSL: Ubuntu18.04
Johnを動かすときにLinux環境のほうがちょっとだけ手間が省けたのでWSLを使った.必須ではない.
今回はCPUは解析に使わなかったが,使うのであれば"OpenCL Runtime for Intel Core and Intel Xeon Processors"の16.1.1以降を導入する必要がある.AMD製CPUであってもこれを使うらしい.
AMD製GPU環境に関してはwindowsであれば20.2.2以降のドライバ,LinuxであればROCmの3.1以降が必要とのこと.RDNA2はROCm v5.0以降でないと正式にはサポートしてないらしい(4.5でも一応動くらしい)(無知).
NVIDIA製GPU環境だと440.64以降のドライバと9.0以降のCUDA Toolkitが必要.
準備
hashcatの導入
特に迷うことはなさげ.windows環境であればここからhashcat binariesをダウンロードして解凍するだけ.
今回はhashcat6.2.5を使った.
Jown the Ripperの導入
windows環境であれば "64-bit Windows binaries"をダウンロードして解凍すればよし.7zでもzipでもいいけどあまり速い回線ではなさそうだから7zのほうがいいかも.
今回はjohn-1.9.0-jumbo-1-win64を使った.
作業
Jownでのハッシュ抜き出し
john-1.9.0-jumbo-1-win64/runに色々とプログラムが用意されている.今回はPDFをゴニョゴニョしたいからpdf2john.plを使う.とりあえず同じフォルダにに今回パスワードを解析したいPDFを配置.
私のwindowsにPerlの実行環境は用意していなかったし(.plはperlのスクリプトファイル),このためだけに準備するのも面倒だからWSLを使う.WSLで/mntを開くとwindows側のディレクトリを開くことができる.それでフォルダ開いて
perl pdf2john.pl MyPDF.pdf > MyPDF.pdf.txt
MyPDF.pdfには解析したいPDFファイル名を入れる.MyPDF.pdf.txtに抽出したハッシュが保存される.
このままhashcatに読ませるとエラーを返すのでMyPDF.pdf.txtを開いて冒頭の
MyPDF.pdf:$pdf$~
のうちMyPDF.pdf:を削除,つまりコロンまでを消す.消さないとhashcatが
Hashfile 'Mypdf.pdf.txt' on line 1 (MyPDF....): Signature unmatched
No hashes loaded.
ってエラーを吐く
これでハッシュの準備は完了.
ちなみにオンラインでPDFのハッシュを抜いてくれるサイトも存在している.今回は使わなかったがオンラインに投げてもいいようなPDFであれば使ってもいいかもしれない.
hashcatでの解析
先ほど生成したMyPDF.pdf.txtをhashcatのフォルダに移動.そしたらWSLではなくwindows側でcmdを起動してhashcatのフォルダを開く.そして
hashcat.exe -m 10500 -a 3 Mypdf-Hash.txt
のような感じで実行.そして待つだけ.
実行が終わると
画像一番上行の
$pdf$4*4*128*-1060*1*16*1ecddfaccbcbd04d86df9af2c64e6165*32*0e339f51ae97d7418c5afc208760c74600000000000000000000000000000000*32*c431fab9cc5ef7b59c244b61b745f71ac5ba427b1b9102da468e77127f1e69d6:123456
のようにハッシュ値:パスワードの形で表示される.今回は123456がパスワード.
hashcatオプション等々
詳しいことはここ見て
以下なんとなく適当気味説明
-m ハッシュの選択
PDF系に関しては
10400 | PDF 1.1 - 1.3 (Acrobat 2 - 4) | Document 10410 | PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #1 | Document 10420 | PDF 1.1 - 1.3 (Acrobat 2 - 4), collider #2 | Document 10500 | PDF 1.4 - 1.6 (Acrobat 5 - 8) | Document 25400 | PDF 1.4 - 1.6 (Acrobat 5 - 8) - user and owner pass | Document 10600 | PDF 1.7 Level 3 (Acrobat 9) | Document 10700 | PDF 1.7 Level 8 (Acrobat 10 - 11) | Document
となっている.PDFのバージョンはPDFファイルをテキストエディタで開くと先頭に書かれているのでそれで判別可能.
たいていは10400,10500,10600,10700のどれかで対応できる.またAdobeによると,
- 「Acrobat 6.0 およびそれ以降」(PDF 1.5)を選択すると、128-bit RC4 を使用して文書が暗号化されます。
- 「Acrobat 7.0 およびそれ以降」(PDF 1.6)を選択すると、128-bit キーサイズの AES 暗号化アルゴリズムを使用して文書が暗号化されます。
- 「Acrobat X およびそれ以降」(PDF 1.7)を選択すると、256-bit AES を使用して文書が暗号化されます。Acrobat 8 および 9 で作成した文書に 256-bit AES 暗号化を適用するには、「Acrobat X およびそれ以降」を選択します。
とのことなのでハッシュ値の長さも手掛かりになる.ちなみにwordで作ったパスワード付きPDFはPDF1.5っぽいので10500でいける.
マスクについて
l | abcdefghijklmnopqrstuvwxyz [a-z] u | ABCDEFGHIJKLMNOPQRSTUVWXYZ [A-Z] d | 0123456789 [0-9] h | 0123456789abcdef [0-9a-f] H | 0123456789ABCDEF [0-9A-F] s | !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ a | ?l?u?d?s b | 0x00 - 0xff
たとえば数字6桁を指定したければ「?d?d?d?d?d?d」となる.
アルファベット小文字5つ+数字3桁を指定したければ「?l?l?l?l?l?d?d?d」となる.
カスタムマスク
「アルファベット大文字+アルファベット小文字」とかそういうのを表現したいときはカスタムマスクの定義が必要.やり方は
-1 ?l?u
-1で1つめのカスタムマスクであることを示してそのあとに?l?uで「アルファベット大文字+アルファベット小文字」を表現.
「アルファベット大文字+アルファベット小文字+数字」であれば
-1 ?l?u?d
となる.使うときは
hashcat.exe -m 10500 -a 3 Mypdf-Hash.txt -1 ?l?u?d ?1?1?1?1
とかする.これで「アルファベット大文字+アルファベット小文字+数字」で4桁
長さ指定
例えば数字6桁を指定したければ
?d?d?d?d?d?d
数字1~6桁ならば
--increment ?d?d?d?d?d?d
数字3~6桁なら
--increment --increment-min 3 --increment-max 6 ?d?d?d?d?d?d
数字以外の文字種でも同様.
-a アタックモード選択
公式によると
0 | Straight 1 | Combination 3 | Brute-force 6 | Hybrid Wordlist + Mask 7 | Hybrid Mask + Wordlist 9 | Association
だそうです(無知).
0:辞書攻撃
指定した辞書ファイルを使ってアタック.辞書ファイルの単語をそのままぶつけて確認してるのかな?実行時は辞書ファイルを渡す必要がある.
例)hashcat.exe -m 10500 -a 0 Mypdf-Hash.txt dic.txt
1:組み合わせ
辞書ファイル複数を組み合わせる.辞書ファイルとしてdic1.txtとdic2.txtがあってそれぞれ
dic1
dic2
があったときに
hashcat.exe -m 10500 -a 1 Mypdf-Hash.txt dic1.txt dic2.txt
とすると
- NvidiaGeforce
- NvidiaRadeon
- AMDGeforce
- AMDRadeon
で攻撃する.さらにそれぞれの辞書に追加でルールの適用が可能.-jで1番目の辞書に,-kで2番目の辞書にルールを適用する.単語は$で示す.例えば単語を「_」でつないで最後に「+」をつける場合は
hashcat.exe -m 10500 -a 1 -j $_ -k $+ Mypdf-Hash.txt dic1.txt dic2.txt
になる.このときの単語は
となる.
3:総当たり
皆さんおなじみ総当たり検索.クッソ時間はかかるがそのうち正解にはたどり着ける.マスクとか使って多少絞り込まないと非現実的な時間がかかる.
6:辞書+マスク
辞書ファイルの単語+マスクで攻撃する.例えばdic1.txtが
- LGA
だったときに
hashcat.exe -m 10500 -a 6 Mypdf-Hash.txt dic1.txt ?d?d?d?d
とすると
- LGA0000
- LGA0001
- LGA0002
- …
- LGA9998
- LGA9999
となる.
7:マスク+辞書
6の逆.
例えばdic1.txtが
- LGA
だったときに
hashcat.exe -m 10500 -a 7 Mypdf-Hash.txt dic1.txt ?d?d?d?d
とすると
- 0000LGA
- 0001LGA
- 0002LGA
- …
- 9998LGA
- 9999LGA
となる.
9:Association
わかりません(正直).
-w ワークロードプロファイル
# | Performance | Runtime | Power Consumption | Desktop Impact ===+=============+=========+===================+================= 1 | Low | 2 ms | Low | Minimal 2 | Default | 12 ms | Economic | Noticeable 3 | High | 96 ms | High | Unresponsive 4 | Nightmare | 480 ms | Insane | Headless
公式曰く↑らしい.雑に解釈すれば
1: 軽い
2: 普通
3: 重い
4: クソ重い
ってことか.思考停止で4を指定していいと思う.
おまけ princeprocessor
hashcatの関連ツール.文字列の組み合わせを生成するためのツール.普通に
sudo apt install princeprocessor
でインストールできる.例えばdic1.txtが
だったときに
princeprocessor --elem-cnt-min=1 --elem-cnt-max=3 dic1.txt > dic2.txt
とすればdic2.txtは
- radeon
- geforce
- nvidia
- amd
- radeongeforce
- radeonnvidia
- radeonamd
- geforceradeon
- …
- amdnvidiageforce
- amdradeongeforce
といった感じで指定した個数の組すべてを生成する.ファイルに出力しないでパイプとかでhashcatに渡したほうがいいように思える.
感想
このクソ暑い時期にグラボ全力Poweeeeeerrrrrr!!!したせいで室温が3℃も上がりました.提訴.
パスワード長くしていろんな文字種を混ぜるってのはすごーく有効だということが身をもって体感できた.うちのPCだと「アルファベット大文字+小文字+数字+記号」の8桁の時点で総当たりには5年かかるっぽい.辞書攻撃が可能だと桁数が意味をなさなくなるから「ランダムな文字列で大文字小文字数字記号を含む16桁」ぐらいあればまず解析されることはないんじゃないかなって.