私はいくつかのExcel 2003マクロを更新するように頼まれました、しかしVBAプロジェクトはパスワードで保護されています、そしてそれはドキュメンテーションの欠如があるようです...誰もがパスワードを知りません。
VBAプロジェクトでパスワードを削除または解読する方法はありますか?
HEX編集を必要としないこの直接的なVBA
アプローチを試すことができます。どのファイル(* .xls、*。xlsm、*。xlam ...)でも機能します。
テスト済みで動作
Excel 2007
エクセル2010
Excel 2013 - 32ビットバージョン。
Excel 2016 - 32ビットバージョン。
64ビット版をお探しですか? https://stackoverflow.com/a/31005696/4342479 を参照してください。
使い方
私はそれがどのように働くかを説明するために最善を尽くします - 私の英語を許してください。
コードを使用
まずファイルをバックアップしてください。
新しいxlsmファイルを作成し、このコードをModule1に格納します。
code credited to Siwtom (nick name), a Vietnamese developer
Option Explicit
Private Const PAGE_EXECUTE_READWRITE = &H40
Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Long, Source As Long, ByVal Length As Long)
Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Long, _
ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _
ByVal lpProcName As String) As Long
Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, _
ByVal pTemplateName As Long, ByVal hWndParent As Long, _
ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As Long
Dim Flag As Boolean
Private Function GetPtr(ByVal Value As Long) As Long
GetPtr = Value
End Function
Public Sub RecoverBytes()
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub
Public Function Hook() As Boolean
Dim TmpBytes(0 To 5) As Byte
Dim p As Long
Dim OriginProtect As Long
Hook = False
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
If TmpBytes(0) <> &H68 Then
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
p = GetPtr(AddressOf MyDialogBoxParam)
HookBytes(0) = &H68
MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
HookBytes(5) = &HC3
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
Flag = True
Hook = True
End If
End If
End Function
Private Function MyDialogBoxParam(ByVal hInstance As Long, _
ByVal pTemplateName As Long, ByVal hWndParent As Long, _
ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
If pTemplateName = 4070 Then
MyDialogBoxParam = 1
Else
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
hWndParent, lpDialogFunc, dwInitParam)
Hook
End If
End Function
このコードをModule1の上記のコードの下に貼り付けて実行します。
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
VBAプロジェクトに戻って楽しんでください。
.xls
フォーマットのスプレッドシートを使用している限り、はい、あります(Excelの2003年までのデフォルト)。 Excel 2007以降では、デフォルトは.xlsx
です。これはかなり安全な形式であり、この方法は機能しません。
Trebが言うように、それは簡単な比較です。 1つの方法は、16進エディタを使用してファイル内のパスワードエントリを単純にスワップアウトすることです(Windows用 Hexエディタ を参照)。ステップバイステップの例:
以下のキーで始まる行をコピーします。
CMG=....
DPB=...
GC=...
FIRST BACKUPVBAのパスワードがわからないExcelファイルを16進エディタで開き、ダミーファイルから上記のコピーした行を貼り付けます。
Excel 2007または2010で作業する必要がある場合は、以下に役立つその他の回答がいくつかあります。特にこれらは 1 、 2 、 3 です。
EDIT2015年2月:非常に有望に見える別の方法については、この新しい答えをご覧ください。Đc ThanhNguyễnさん。
サイズの問題がない、(もう少し簡単な)解決方法があります。私は今日(2003 XLSファイルで、Excel 2007を使用して)この方法を使用し、成功しました。
DPB=...
部分を見つけます。DPB=...
文字列をDPx=...
に変更します*注:パスワードを新しい値に変更したことを確認してください。そうしないと、次回スプレッドシートを開くときにExcelからエラー(予期しないエラー)が報告され、VBAモジュールのリストにアクセスすると名前が表示されます。ソースモジュールですが、forms/code/etcを開こうとすると別のエラーを受け取ります。これを解決するには、VBAプロジェクトのプロパティに戻り、パスワードを新しい値に設定します。 Excel文書を保存して再度開くと、うまくいくはずです。
私は、この方法が64ビットバージョンのExcelで機能することを可能にするために、ĐứcThanhNguyễnの素晴らしい答えに基づいています。 64ビットWindows 7上でExcel 2010 64ビットを実行しています。
新しいxlsmファイルを作成し、このコードを Module1 に格納します。
Option Explicit
Private Const PAGE_EXECUTE_READWRITE = &H40
Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As LongPtr, Source As LongPtr, ByVal Length As LongPtr)
Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (lpAddress As LongPtr, _
ByVal dwSize As LongPtr, ByVal flNewProtect As LongPtr, lpflOldProtect As LongPtr) As LongPtr
Private Declare PtrSafe Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As LongPtr
Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, _
ByVal lpProcName As String) As LongPtr
Private Declare PtrSafe Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer
Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As LongPtr
Dim Flag As Boolean
Private Function GetPtr(ByVal Value As LongPtr) As LongPtr
GetPtr = Value
End Function
Public Sub RecoverBytes()
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub
Public Function Hook() As Boolean
Dim TmpBytes(0 To 5) As Byte
Dim p As LongPtr
Dim OriginProtect As LongPtr
Hook = False
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
If TmpBytes(0) <> &H68 Then
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
p = GetPtr(AddressOf MyDialogBoxParam)
HookBytes(0) = &H68
MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
HookBytes(5) = &HC3
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
Flag = True
Hook = True
End If
End If
End Function
Private Function MyDialogBoxParam(ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer
If pTemplateName = 4070 Then
MyDialogBoxParam = 1
Else
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
hWndParent, lpDialogFunc, dwInitParam)
Hook
End If
End Function
このコードを Module2 に貼り付けて実行します。
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
_免責事項_ これは私のために働きました、そして、私はそれが誰かに役立つことを願ってそれをここに文書化しました。 十分にテストしていません 。このオプションに進む前に、開いているファイルをすべて保存してください。
Colin Pickardは素晴らしい答えを持っていますが、これには「気を付けて」1つあります。ファイル内の "CMG = ........ GC = ...."エントリの合計の長さが1つのExcelファイルと異なる場合があります(まだ原因を特定していません)。次。場合によっては、このエントリは137バイトになり、他の場合には143バイトになります。 137バイトの長さは奇数なので、 '1234'のパスワードでファイルを作成したときにこれが発生する場合は、別のファイルを作成するだけで、143バイトの長さにジャンプするはずです。
誤ったバイト数をファイルに貼り付けようとすると、Excelでファイルを開こうとするとVBAプロジェクトが失われます。
_編集_
これはExcel 2007/2010ファイルには無効です。標準の.xlsxファイル形式は、実際には、xmlデータとして格納されたフォーマット、レイアウト、コンテンツなどを含む多数のサブフォルダを含む.Zipファイルです。保護されていないExcel 2007ファイルの場合は、拡張子.xlsxを.Zipに変更してからZipファイルを開き、すべてのxmlデータを調べることができます。とても簡単です。
ただし、Excel 2007ファイルをパスワードで保護すると、実際には.Zip(.xlsx)ファイル全体がRSA暗号化を使用して暗号化されます。拡張子を.Zipに変更してファイルの内容を参照することはできなくなりました。
.xlsm
または.dotm
ファイルタイプの場合は、少し異なる方法で行う必要があります。
.xlsm
ファイルの拡張子を.Zip
に変更します。vbaProject.bin
ファイルを解凍してHex Editorで開きます(私は HxD を使います。これは完全無料で軽量です)DPB
を検索し、DPx
に置き換えてファイルを保存します。vbaProject.bin
ファイルをこの新しいonに置き換えます。.xlsm
に戻します。.xlsm
ファイルを保存してください。Excel 2007(xlsm)ファイルがある場合は、それをExcel 2003(xls)ファイルとして保存し、他の回答で概説されている方法を使用することができます。
あなたは単にOpenOffice.orgでそれらを単に開こうとしましたか?
私はしばらく前に同様の問題を抱えていましたが、ExcelとCalcは互いの暗号化を理解していなかったので、ほぼすべてのものに直接アクセスすることができました。
これは少し前のことなので、それが私の側の単なる偽物ではない場合は、パッチも適用されている可能性があります。
Excel 2007以降の場合は、ファイル拡張子を.Zipに変更する必要があります。アーカイブ内にサブフォルダxlがあり、その中にvbaProject.binがあります。上記の手順に従ってvbaProject.binを実行してから、アーカイブに保存します。あなたの拡張機能を修正してください。 (上記の手順に従うことを意味します)
'known password'ファイル内のCMG="XXXX"\r\nDPB="XXXXX"\r\nGC="XXXXXX"
のブロックが 'unknown password'ファイル内の既存のブロックより短い場合は、正しい長さになるように16進文字列を末尾のゼロで埋めてください。
例えば.
CMG="xxxxxx"\r\nDPB="xxxxxxxx"\r\nGC="xxxxxxxxxx"
未知のパスワードファイルでは、
ファイル長を保持するためのCMG="XXXX00"\r\nDPB="XXXXX000"\r\nGC="XXXXXX0000"
。
2007年のオフィスでも私はこれを.XLA(97/2003フォーマット)ファイルでも動作させることができました。
Access、Excel、PowerPoint、またはWord文書(拡張子2007, 2010, 2013 or 2016
を持つ.ACCDB .XLSM .XLTM .DOCM .DOTM .POTM .PPSM
バージョン)のVBAプロジェクトパスワードは、簡単に削除されるになります。
ファイル名の拡張子を.Zip
に変更し、ファイルを解凍し、既存のパスワードを壊すために基本的な16進エディタ( XVI32 など)を使用するだけで、Officeが新しいパスワードの入力を求められます。次回ファイルが開かれたとき。
.Zip
という拡張子を付けます。Zip
を開き、XL
フォルダーに移動します。vbaProject.bin
を抽出し、それを16進エディタで開きます。DPB
をDPX
に変更することで、 "Search&Replace"から "replace all"へ。.bin
ファイルをZipに戻して通常の拡張子に戻し、通常どおりにファイルを開きます。VBA Project Properties
を選択します。Protection
タブで、新しいパスワードを設定します。OK
をクリックし、ファイルを閉じて再度開き、ALT + F11を押します。この時点で、必要に応じてパスワードを完全に削除できます。
完全な指示 私が作った段階的なビデオを使って"時には戻る"がオンになっています YouTube ここ 。
この回避策が何年も前から出てきていることはちょっと衝撃的です、そしてマイクロソフトは問題を解決していません。
物語の道徳は?
Microsoft Office VBAプロジェクトのパスワードは信頼しないでくださいのセキュリティのためにany機密情報 。セキュリティが重要な場合は、サードパーティの暗号化ソフトウェアを使用してください。
Colin Pickardが最も正しいのですが、ファイル全体の「開くためのパスワード」保護とVBAパスワード保護を混同しないでください。これは前者とはまったく異なり、Office 2003と2007では同じです(Office 2007では、名前の変更)。ファイルを.Zipして、Zip内のvbaProject.binを探します。そして技術的にファイルを編集する正しい方法はCFXのようなOLE複合ドキュメントビューアを使って正しいストリームを開くことです。もちろん、単にバイトを置き換えているだけなら、普通の古いバイナリエディタでうまくいくかもしれません。
ところで、あなたがこれらのフィールドの正確なフォーマットについて疑問に思っているならば、彼らは今それを文書化しています:
http://msdn.Microsoft.com/ja-jp/library/dd926151%28v=office.12%29.aspx
私の順番では、これはkaybee99の優れた答えに基づいています。この答えは、この方法がx86とAMD64の両方のバージョンのOfficeで機能するように、ĐứcThanhNguyễnの素晴らしい答えに基づいています。
変更点の概要は、32ビットアドレスに制限されているPush/retを避け、mov/jmp regに置き換えたものです。
テスト済みで動作
Word/Excel 2016 - 32ビット版 。
Word/Excel 2016 - 64ビット版 。
使い方
上記と同じ種類の新しいファイルを作成し、このコードを Module1 に保存します。
Option Explicit
Private Const PAGE_EXECUTE_READWRITE = &H40
Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As LongPtr, Source As LongPtr, ByVal Length As LongPtr)
Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (lpAddress As LongPtr, _
ByVal dwSize As LongPtr, ByVal flNewProtect As LongPtr, lpflOldProtect As LongPtr) As LongPtr
Private Declare PtrSafe Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As LongPtr
Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, _
ByVal lpProcName As String) As LongPtr
Private Declare PtrSafe Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer
Dim HookBytes(0 To 11) As Byte
Dim OriginBytes(0 To 11) As Byte
Dim pFunc As LongPtr
Dim Flag As Boolean
Private Function GetPtr(ByVal Value As LongPtr) As LongPtr
GetPtr = Value
End Function
Public Sub RecoverBytes()
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 12
End Sub
Public Function Hook() As Boolean
Dim TmpBytes(0 To 11) As Byte
Dim p As LongPtr, osi As Byte
Dim OriginProtect As LongPtr
Hook = False
#If Win64 Then
osi = 1
#Else
osi = 0
#End If
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
If VirtualProtect(ByVal pFunc, 12, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, osi+1
If TmpBytes(osi) <> &HB8 Then
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 12
p = GetPtr(AddressOf MyDialogBoxParam)
If osi Then HookBytes(0) = &H48
HookBytes(osi) = &HB8
osi = osi + 1
MoveMemory ByVal VarPtr(HookBytes(osi)), ByVal VarPtr(p), 4 * osi
HookBytes(osi + 4 * osi) = &HFF
HookBytes(osi + 4 * osi + 1) = &HE0
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 12
Flag = True
Hook = True
End If
End If
End Function
Private Function MyDialogBoxParam(ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer
If pTemplateName = 4070 Then
MyDialogBoxParam = 1
Else
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
hWndParent, lpDialogFunc, dwInitParam)
Hook
End If
End Function
このコードを Module2 に貼り付けて実行します。
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
ファイルが有効なZipファイル(最初の数バイトが50 4B
- .xlsm
のような形式で使用されている)である場合は、ファイルを解凍し、サブファイルxl/vbaProject.bin
を探します。これは.xls
ファイルとまったく同じCFBファイルです。 (サブファイルに適用される)XLSフォーマットの指示に従い、次に内容をZipするだけです。
XLSフォーマットについては、この記事の他のいくつかの方法に従うことができます。私は個人的にはDPB=
ブロックを探してテキストを置き換えることを好みます
CMG="..."
DPB="..."
GC="..."
空白スペースを入れます。これにより、CFBコンテナサイズの問題が解消されます。
私は上記の解決策をいくつか試してみましたが、どれもうまくいきませんでした(Excel 2007 xlsmファイル)。それから私はそれを解読するだけでなく、パスワードさえ検索する別の解決策を見つけました。
このコードをモジュールに挿入して実行し、しばらく時間を置いてください。それは強引にあなたのパスワードを回復します。
Sub PasswordBreaker()
'Breaks worksheet password protection.
Dim i As Integer, j As Integer, k As Integer
Dim l As Integer, m As Integer, n As Integer
Dim i1 As Integer, i2 As Integer, i3 As Integer
Dim i4 As Integer, i5 As Integer, i6 As Integer
On Error Resume Next
For i = 65 To 66: For j = 65 To 66: For k = 65 To 66
For l = 65 To 66: For m = 65 To 66: For i1 = 65 To 66
For i2 = 65 To 66: For i3 = 65 To 66: For i4 = 65 To 66
For i5 = 65 To 66: For i6 = 65 To 66: For n = 32 To 126
ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & _
Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & _
Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
If ActiveSheet.ProtectContents = False Then
MsgBox "One usable password is " & Chr(i) & Chr(j) & _
Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & _
Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n)
Exit Sub
End If
Next: Next: Next: Next: Next: Next
Next: Next: Next: Next: Next: Next
End Sub
ElcomSoft makes 高度なOfficeパスワードブレイカー そして 高度なオフィスパスワード回復 ドキュメントがOffice 2007以前に作成されている限り、この場合に適用される可能性のある製品。
トム - バイトサイズを見なかったので最初は男子生徒のエラーをしましたが、代わりに次のエントリに設定された「CMG」からコピーして貼り付けました。しかし、これは2つのファイル間で2つの異なるテキストサイズであり、Stewbobが警告したように私はVBAプロジェクトを失いました。
HxDを使用して、選択しているファイルの量を追跡するカウンターがあります。 CMGからカウンターが8F(143の16進数)を読み取るまで、そして同様にロックされたファイルにペーストする時にコピーします。ペーストの最後に2倍の "..."が付きました不自然ですが、うまくいきました。
それが重要かどうかはわかりませんが、ファイルをExcelで再度開く前に、16進エディタとExcelの両方をシャットダウンしたことを確認しました。それから、メニューをたどってVBエディタを開き、VBProjectのプロパティに移動して、新しいパスワードを入力してコードのロックを解除する必要がありました。
これが役に立つことを願っています。
私のツール VbaDiff は、ファイルから直接VBAを読み込むので、16進エディタに頼ることなく、ほとんどのオフィス文書から保護されたVBAコードを回復するのに使用できます。
保護は、Excelでの単純なテキスト比較です。お気に入りのデバッガにExcelをロードし( Ollydbg 私が選んだツールです)、比較を行うコードを見つけて、常にtrueを返すように修正します。これでマクロにアクセスできるはずです。
excelファイルの拡張子がxmlに変わります。メモ帳で開きます。パスワードテキストはxmlファイルにあります。
あなたは下の行のように見えます。
Sheets("Sheet1").Unprotect Password:="blabla"
(英語が下手ですみません)
Windows 10マシン上のExcel 2016 64ビットの場合、保護されたxlaのパスワードを変更できるように16進エディターを使用しました(他の拡張機能でこれをテストしていません)。 ヒント:これを行う前にバックアップを作成します。
私が取ったステップ:
これが皆さんの一部に役立ったことを願っています!
Java
で作業しているなら、 VBAMacroExtractor
を試すことができます。 .xlsm
からVBAスクリプトを抽出した後、プレーンテキストでパスワードが見つかりました。