編集 (2020) : Excel 2013 以降、明らかに保護スキームが変更されました。したがって、元の答えはもはや歴史的な意味しかありません。
新しい保護により、最先端の SHA-512 ハッシュを使用してパスワードを取得することがほぼ不可能になります。しかし、数秒で簡単に引き抜くことができるのであれば、なぜそれを壊す必要がありますか。
.xlsx
または.xlsm
ファイルを解凍します
- 編集
xl/worksheets/sheet<num>.xml
<sheetProtection... />
タグを検索して削除する
- 保存して、もう一度圧縮して、お楽しみください
元の回答 (Excel 2010 まで)
魅力的 - コード スニペットは以前から知っていましたが、brettdj が投稿した説明は知りませんでした。他の人が説明したように、これはハッシュ衝突のブルートフォース検索です。実際には必要以上の作業を行うため、試行錯誤して作成されたようです (194560 の組み合わせが生成されますが、可能なハッシュ値は 32768 しかありません)。
Excel のハッシュ アルゴリズムの概要 ( http://chicago.sourceforge.net/devel/docs/excel/encrypt.htmlで説明):
- パスワードの各文字のアスキー コードを取得します。
- 16 ビットの符号付き数値として扱います。文字の位置に基づいてビットを左にシフトします (最初の文字は 1 ビット、2 番目の文字は 2 ビットなど)。
- すべての文字を一緒に XOR し、16 ビットの符号付き int >=0 を与えます。
- パスワードの長さとマジック ナンバーの XOR。
これを知っていれば、次のようにブルートフォース検索を考案できます。
- 最上位ビットは常に 0 なので、テストするビットは 15 ビットあります。
- それらをそれぞれ 5 ビットをカバーする 3 つのカウンターに分割します。そうすれば、各カウンターは印刷可能な ascii char を表すことができます。
- これらのカウンターの ASCII 表現をパスワード文字列にパックして、相互に影響を与えないようにします。
最も簡単な方法は、11 文字のパスワードを使用し、カウンターを 1、6、および 11 の位置に配置することです。ステップ 2 のビットシフトにより、カウンター ビットが正しい方法で整列されます。つまり、最初のカウンター ("x") が 1 ビットシフトされます。 、2 番目 (「y」) 6 ビット、3 番目 (「z」) 11 ビット。ハッシュのビット単位の表現では、カウンターは次のビットに影響します。
bit: 76543210 76543210
cnt: -zzzzyyy yyxxxxxz
XOR 引数は常に一定であるため、XOR 演算は無視できます。同じ理由で、一定のオフセット (たとえば 64) を追加できます。また、他のパスワード バイト (2 ~ 5、7 ~ 10) で使用される文字は問題ではありません。
x、y、z のすべての可能な組み合わせを反復することにより、元のパスワードと同じハッシュ値を与えるパスワードが最終的に見つかります。
Public Sub demo()
' http://stackoverflow.com/questions/12852095/how-does-excels-worksheet-password-protection-work
Dim x As Integer, y as Integer, z as Integer
Dim part1 As String, part12 As String
Dim sh As Worksheet
Set sh = ThisWorkbook.Worksheets(1)
sh.Protect "$ome_Insanely_Long_and_c0mplex_password! [(which i$ imp*ssible t0 re-member)]"
For x = 64 To 95
' pad with dots, so that x, y and z affect nonoverlapping bits of the hash.
part1 = Chr(x) + "...."
For y = 64 To 95
part12 = part1 + Chr(y) + "...."
For z = 64 To 95
On Error Resume Next
sh.Unprotect part12 + Chr(z)
If Err.Number = 0 Then
Debug.Print "Password: '" & part12 + Chr(z) & "'"
Exit Sub
End If
On Error GoTo 0
Next
Next
Next
End Sub