|
출처 : http://ddart.net/xe/board/5187
1. 암호가 걸린 VBA(.xlsm) 엑셀매크로 파일을 연다.
2. 연 상태에서 바로 새로운 엑셀파일을 열어준다.
3. Alt+F11을 눌러 VBA를 실행하여, 새롭게 만든 프로젝트에서 아래 그림과 같이 새로운 프로젝트에서
마우스 오른쪽 버튼을 눌러 삽입->모듈을 클릭하여, 모듈을 생성한다.
4. 생성한 모듈에 다음의 소스코드를 입력한다.
Module1의 소스코드내용
32비트 버전용
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
64비트 버전용
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
5. 위의 모듈 추가 방법과 같이 Module2도 생성하여, 다음과 같이 소스코드를 입력한다.
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
6. 입력 후에, F5번 키를 눌러 다음과 같은 창이 뜨면, unprotected를 실행하고 나서, 원본프로젝트의 VBA 프로젝트를 열면, 암호를 묻지 않는다.
[출처] [Excel]VBA(엑셀 매크로) 암호 제거하는 방법|작성자 browniz1004
오피스 2007 엑셀에서는 암호가 걸려있는 매크로 통합문서는 실행이 안되도록 되어있습니다.
(암호가 걸려있으면 매크로 문서의 바이러스/악성코드 검사를 하지 못하기 때문에 암호걸린 매크로 통합문서의 매크로 실행을 금지한다고 하던가... -_-;)
그런데 레지스트리 값을 편집하면 가능합니다.
(HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Excel\Security\ExcelBypassEncryptedMacroScan 의
Dword 값을 1 로 세팅해 주면 암호걸린 매크로 통합문서도 실행가능)
주의할 점!
이걸 항상 1 값으로 세팅해 두면 악성코드 또는 바이러스 가 들어있는 암호걸린 매크로 파일이 언제라도 실행될 수 있으므로
각별한 주의가 요구됩니다.
해결할 수 있는 편법
신뢰할 수 있는 '암호걸린 매크로 통합문서'를 실행하기 전에
1. HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Excel\Security 내에
ExcelBypassEncryptedMacroScan 을 만들어 값을 1 로 세팅해주고
2. xlsm 파일을 실행하고
3. 다시 레지스트리 값을 0으로 세팅 / ExcelBypassEncryptedMacroScan 를 아예 삭제한다
근디.. 너무 번거롭다. -_-;
그래서 간단한 프로그램을 하나 만들었습니다.
기능은 위에서 설명한 편법을 통해 xlsm을 실행해 주는 놈입니다.
한가지 주의할 점은 '신뢰할 수 있는 xlsm' 만을 실행하여야 한다는 점이지요.
출처를 알 수 없는 xlsm파일을 실행하여 발생하는 문제는 전적으로 본인 책임입니다.
[출처] 2007 엑셀 암호걸린 매크로 통합문서 실행하는 프로그램.|작성자 미련곰팅
|