Filed under: Excel VBA 範例, Top, 一般程序

VBA專案解鎖

by chijanzen on 五月 22nd, 2009 | View: 7,024 views

Tags
  • No Tags
Share Comments (1)
索   引 H0073
主   題 VBA專案解鎖
版   本 >= 12.0(Office 2007)
說   明

如果忘了VBA專案密碼通常都要借助 Passware 或 Advanced VBA Password Recovery等軟體,現在有更簡單的方法了

這支程式碼是ttui(AT)163.com作者所寫的,試用了一下覺得滿好的,我將程式碼轉成繁體中文了

他的做法是鑽VBE6.dll的漏洞,詳細的作法參閱程式碼有完整解說

參   考



複製以下程式碼到Module

Code



'***************************************************************************

'*
'* MODULE NAME:     Protected VBA project Picklock(PVP)
'* AUTHOR & DATE:   tt.t
'*                  23 April 2007
'* E-Mail:          ttui(AT)163.com, sohu郵箱垃圾郵件太多已經不用了
'*
'* Usage:           運行FrmHookMain窗口,點補丁,然後雙擊工程窗口中有密碼保護的模塊
'*                  應該能夠直接打開了:)
'*
'*
'* DESCRIPTION:     在寫中文字符串轉換為拼音函數(HzToPy)過程中,第一次發現VBA功能的強大.

'*                  於是這次嘗試將其他語言中比較好寫的API HOOK移植成VBA代碼,


'*                  正好順便把VBA密碼保護去掉,喜歡加密碼的朋友不要生氣啊:)


'*                  總的來說VBA的寫法和其他語言區別不大,但VBA畢竟不太方便,代碼必須放在標準模塊中.


'*                  再有就是對指針的支持實在有限,於是最後選擇了一種寫起來最簡單的API hook方法,


'*                  就是所謂的陷阱法.如果你不太清楚什麼是API HOOK,請求助於google.

'*

'* Theory:         這裡就不說API hook的方法了,都是傳統方法沒什麼可說的,這裡只


'*                  簡單說下VBA模塊密碼破解.其實這些我也不是很瞭解,畢竟知道加密過程

'*                  用處不大,這個問題上我比較關心結果:)

'*                  判斷有密碼以及提示輸入密碼都是VBE6.dll幹得好事.如果有密碼,

'*                  VBE6.dll會調用DialogBoxParamA顯示VB6INTL.dll資源中的第4070號
'*                  對話框(就是那個輸入密碼的窗口),若DialogBoxParamA返回值非0,
'*                  則VBE會認為密碼正確,然後乖乖展開加密模塊的資源.很顯然其中存在很大

'*                  漏洞,就像給日記本加上了鎖,但裡面全是活頁,我們不需要打開鎖,只要從側面


'*                  取出活頁就可以了.這個從側面取活頁的過程就是hook住DialogBoxParamA函數,

'*                  若程序調用DialogBoxParamA裝入4070號對話框,我們就直接返回1,讓
'*                  VBE以為密碼正確.
'*
'* PS:              PVP是在一個叫Advanced VBA Password Recovery (AVPR)的軟件啟發下
'*                  作出來的,AVPR提供了一個VBA Backdoor功能就是跳過密碼直接查看工程資源.
'*                  它的原理和PVP一樣,但用了通用性比較差的方法,適用系統比較有限,而PVP的方法

'*                  理論上適用於所有採用第4070號對話框錄入密碼的Office系統.

'*                  經測試PVP適用於Office 2002, 2003, 2007,其他版本尚未測試,但估計依然有效.

'*                  在2000和XP系統上測試通過,但條件限制沒有在Vista系統上測試,聽說Vista有些機制

'*                  可能影響API hook,暫時沒機會測試就先這樣吧~
'*

'*                  *64位操作系統下面的API hook代碼肯定運行出錯,就不要測試了

'*
'*

'***************************************************************************

Option Explicit

Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (Destination As Long, Source As LongByVal Length As Long)

Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Long, _
        ByVal dwSize As LongByVal flNewProtect As Long, lpflOldProtect As LongAs Long

Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As StringAs Long

Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _
        ByVal lpProcName As StringAs Long

Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, _
        ByVal pTemplateName As LongByVal hWndParent As Long, _
        ByVal lpDialogFunc As LongByVal dwInitParam As LongAs 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 LongAs Long
    '獲得函數的地址
    GetPtr = Value
End Function
 

Public Sub RecoverBytes()
    '若已經hook,則恢復原API開頭的6字節,也就是恢復原來函數的功能
    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

    'VBE6.dll調用DialogBoxParamA顯示VB6INTL.dll資源中的第4070號對話框(就是輸入密碼的窗口)
    '若DialogBoxParamA返回值非0,則VBE會認為密碼正確,所以我們要hook DialogBoxParamA函數
    pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")

    '標準api hook過程之一: 修改內存屬性,使其可寫
    If VirtualProtect(ByVal pFunc, 6, &H40, OriginProtect) <> 0 Then
        '標準api hook過程之二: 判斷是否已經hook,看看API的第一個字節是否為&H68,
        '若是則說明已經Hook
        MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
        If TmpBytes(0) <> &H68 Then
            '標準api hook過程之三: 保存原函數開頭字節,這裡是6個字節,以備後面恢復
            MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
            '用AddressOf獲取MyDialogBoxParam的地址
            '因為語法不允許寫成p = AddressOf MyDialogBoxParam,這裡我們寫一個函數
            'GetPtr,作用僅僅是返回AddressOf MyDialogBoxParam的值,從而實現將
            'MyDialogBoxParam的地址付給p的目的
            p = GetPtr(AddressOf MyDialogBoxParam)

            '標準api hook過程之四: 組裝API入口的新代碼
            'HookBytes 組成如下彙編
            'push MyDialogBoxParam的地址
            'ret
            '作用是跳轉到MyDialogBoxParam函數
            HookBytes(0) = &H68
            MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
            HookBytes(5) = &HC3

            '標準api hook過程之五: 用HookBytes的內容改寫API前6個字節
            MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
            '設置hook成功標誌
            Flag = True
            Hook = True
        End If
    End If
End Function
 


Private Function MyDialogBoxParam(ByVal hInstance As Long, _
        ByVal pTemplateName As LongByVal hWndParent As Long, _
        ByVal lpDialogFunc As LongByVal dwInitParam As LongAs Integer
    If pTemplateName = 4070 Then
        '有程序調用DialogBoxParamA裝入4070號對話框,這裡我們直接返回1,讓
        'VBE以為密碼正確了
        MyDialogBoxParam = 1
    Else
        '有程序調用DialogBoxParamA,但裝入的不是4070號對話框,這裡我們調用
        'RecoverBytes函數恢復原來函數的功能,在進行原來的函數
        RecoverBytes
        MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
                           hWndParent, lpDialogFunc, dwInitParam)
        '原來的函數執行完畢,再次hook
        Hook
    End If
End Function
 


複製以下程式碼到UserForm

Code


Private Sub CommandButton1_Click()
    RecoverBytes
    Label2.Caption = "正常"
End Sub
 


Private Sub CommandButton2_Click()
    If Hook Then Label2.Caption = "解鎖模式"
End Sub
 

Private Sub UserForm_Terminate()
    RecoverBytes
End Sub
 


File download

Code

 


File download

Code



檔案下載

Popularity: 71%

About the Author
    網路化名: chijanzen、中國龍、邪兵衛 經歷: 第二屆微軟社群之星 第三屆微軟「最有價值專家」 第五屆微軟「最有價值專家」
Leave a Comment »1 Comment
  • Reply » 小員工 三月 12, 2010

    高人真是利害...
    前人作的EXCEL VBA想要增加欄位...
    沒有密碼就不能用...
    要如何破解不太懂...
    請教小員工吧...

Get a GravatarLeave a Reply

Name: « Required

Email Address: « Required

Website URL: « Optional

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

About me
chijanzen 分享個人Excel VBA 學習經驗,架站心得, 日常生活記事等...

Add to Google

分類
Translator
Chinese (Simplified) flagItalian flagKorean flagEnglish flagGerman flag
French flagJapanese flagRussian flagBulgarian flagFinnish flag
相簿