Có thể dùng vba để xóa vba đc không?

Liên hệ QC

quykiemsau

Thành viên chính thức
Tham gia
4/8/10
Bài viết
66
Được thích
0
Em chào các anh chị!
Có code nào có thể test 1 điều kiện nào đó để xóa toàn bộ vba trong file Excel được không ạ?
Cụ thể là
ô A1! của sheet 1! em đặt điều kiện hoặc =0 hoặc =1.
Khi Open file:
ô a1=1 thì file chạy bình thường.
Nếu A1=0 thì toàn bộ vba trong file bị xóa sạch.
Có được không ạ?
 
Phát hiện thêm 1 chuyện nữa: Sau khi gọi hết tất cả các Add-Ins của MS lên (đương nhiên mấy Add-Ins này đều có Pass). Sau đó chạy code của siwtom thì toàn bộ các Add-Ins đều "mở cửa" ---> Xem code thoải mái
Quá sốc!_)()(-
Anh có thể cho em biết nếu đoạn code sau khi sử dụng với office 64b thì nên sửa thế nào không ạ. :(
Mã:
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
 
Upvote 0
Lại bị gọi lên bảng.
ndu nói thế là không đúng. Tự tôi không nghĩ ra được code vì cái khoản này nó thuộc "lập trình cao
cấp". Nhưng khi lập trình trong Delphi thì tôi cũng gặp và hiểu được cơ cấu của nó là như thế nào.
Và khi tôi đọc qua code có trong Excel.xls của quanghai gửi thì 99,99% tôi chắc chắn là nó sử dụng
"kỹ thuật lập trình cao cấp" mà tôi sẽ giải thích dưới đây.
Nếu các bạn có chút thời gian thì tôi sẽ giải thích nôm na nó như thế nào. Nôm na vì tôi sẽ dùng
ngôn ngữ thường ngày để giải thích chứ dùng ngôn ngữ "chuyên ngành" thì e rằng người không lập
trình khó hiểu.
---------------
1. Trước tiên nói về cái cửa sổ mà Excel bắt ta phải nhập mật khẩu. Như trong code Excel.xls "đã
chỉ rõ" thì Excel gọi hàm system là DialogBoxParam để hiển thị cửa sổ hộp thoại. Tất nhiên Excel
phải tạo một cửa sổ hộp thoại (template) đặt trong resource và truyền thông tin về nó cho hàm
DialogBoxParam. Hàm DialogBoxParam sẽ tạo (trên cơ sở template) hộp thoại và hiển thị. Excel
cũng phải lập một procedure cho cửa sổ (DialogProc) mà DialogBoxParam tạo và hiển thị. Để làm
gì? Để nhận các thông điệp. Vd. Windows sẽ gửi thông điệp WM_INITDIALOG khi cửa sổ được
khởi tạo. Ta có thể khi nhận được thông điệp này (tức ở thời điểm "chào buổi sáng") làm một số
việc thiết lập ban đầu, tạo thêm controls - nó giống như ta thiết lập một số cái trong
UserForm_Initialize ấy mà. Windows cũng gửi thông điệp khi user nhấn nút nào đấy (chỉ rõ là nút
nào) để DialogProc xử lý. Vd. nếu nút nhấn là Cancel thì code DialogProc "dọn đồ ra về" còn nếu là
OK thì kiểm tra dữ liệu nhập rồi cũng "dọn đồ" - tức hủy hộp thoại. Tất nhiên Windows còn gửi nhiều
thông điệp khác, nếu DialogProc "quan tâm" thì xử lý.
Khi người lập trình muốn hủy hộp thoại (user chọn Cancel?, chọn OK? ...) thì code của DialogProc
phải gọi EndDialog để system biết và hủy hộp thoại. Khi gọi EndDialog thì phải truyền kết quả trả
về dưới dạng thông số của EndDialog. Hàm DialogBoxParam cũng sẽ trả vể kết quả này. Từ cơ
cấu như trên thì người lập trình có thể viết code đại loại như sau:
a - Gọi hàm DialogBoxParam để tạo cửa sổ nhập mật khẩu - template sẽ gồm textbox (class "Edit"
của Windows) để nhập mật khẩu, nút OK và Cancel. Trong DialogProc nếu nhận được thông điệp
do Windows gửi nói là user nhấn Cancel thì gọi EndDialog(hDialog, 0) - hDialog là "handle to
dialog box", 0 là giá trị trả về, cũng là giá trị mà hàm DialogBoxParam trả về. Nếu thông điệp nói là
user nhấn OK thì: kiểm tra mật khẩu có đúng không, nếu đúng thì EndDialod(hDialog, 1) còn nếu sai
thì EndDialog(hDialog, 0)
Cũng cần nói rõ là khi gọi hàm DialogBoxParam và cửa sổ hiển thị thì hàm DialogBoxParam chỉ
trở về, và mọi code sau dòng gọi hàm DialogBoxParam được thực hiện, khi mà hộp thoại được
đóng (do code trong DialogProc gọi EndDialog). Trong suốt thời gian hộp thoại hiển thị thì chỉ có
code trong DialogProc được thực hiện mà thôi (kiểu như ShowModal ấy mà - cho tới khi cửa sổ
được đóng thì mọi code sau ShowModal "phải chờ")
b - Ở dòng code sau dòng gọi hàm DialogBoxParam thì người lập trình kiểm tra giá trị trả về bởi
hàm DialogBoxParam. Nếu là 0 (tức user chọn Cancel hoặc chọn OK nhưng mật khẩu sai) thì:
Mã:
MsgBox "Này ông tướng, phải nhập mật khẩu đúng mới được chiêm ngưỡng code đấy nhé"
Còn nếu là 1 (user chọn OK và nhập đúng mật khẩu) thì mở code cho user xem.
-----------------
Như trên đã thấy thì bình thường người lập trình sẽ làm trình tự như trên và Excel cũng làm như thế.
Bây giờ ta hình dung là ta viết code như sau:
Ta viết hàm DialogBoxParam "nhái" - vd. hàm MyDialogBoxParam, và đánh tráo nó với hàm
DialogBoxParam của system. Tất nhiên hàm "nhái" này phải có cấu trúc thông số y hệt hàm của
system. Lúc này nếu có "ai đó" gọi hàm DialogBoxParam thì Windows sẽ gọi hàm
MyDialogBoxParam. Hàm của ta nếu kiểm tra thấy template = 4070 thì chả hiển thị hộp thoại nào
cả mà hàm trả về luôn giá trị 1. Trong trường hợp ngược lại thì tráo lại thành hàm DialogBoxParam
của system và gọi nó - vì trong cùng thời điểm có thể những phần mềm khác trong system cũng gọi
hàm DialogBoxParam, ta phải trả lại "hiện trạng" cũ để các phần mềm đó hiển thị hộp thoại của
mình. Cách làm thế nào?
---------------
Tất cả các hàm của system đều nằm trong các thư viện động DLL. Mỗi thư viện như thế có nhiều
section, có header. Riêng về các function trong thư viện thì: Khi DLL được load vào RAM thì nó
nằm ở một chỗ nào đó, địa chỉ nào đó trong RAM. Lúc này mỗi function cũng nằm ở một địa chỉ
nào đó trong RAM. DLL là "dùng chung" cho mọi process, tức nếu A, B, C cùng "gọi" bla.dll thì
bla.dll sẽ được ánh xạ vào mỗi "không gian địa chỉ" của mỗi process A, B, C. "Địa chỉ" của mỗi
function có trong DLL sẽ được ghi trong RAM ở "đâu đó" trong phần header, mỗi function có 1
trường để ghi địa chỉ của nó. Ta xét vd. hàm DialogBoxParam. Giả sử "ở đấy ở đấy" có giá trị là
"123456789" thì bình thường khi process gọi hàm DialogBoxParam thì system sẽ tới "chỗ ấy chỗ
ấy" để đọc ra địa chỉ của hàm DialogBoxParam - sẽ đọc được "123456789". Lúc này sẽ có 1
bước nhẩy tới địa chỉ "123456789" và thực hiện code của DialogBoxParam vì code của
DialogBoxParam nằm ở địa chỉ ấy mà.
Bây giờ ta hãy tưởng tượng là ta viết hàm MyDialogBoxParam (hàm nhái) mà nó nằm ở địa chỉ
"abc...xyz" (đọc ra bằng AddressOf). Code sau đó nhẩy tới "chỗ ấy chỗ ấy" và ghi giá trị "abc...xyz"
đè lên "123456789". Từ lúc này mỗi khi process nào đó gọi DialogBoxParam thì system nhẩy tới
"chỗ ấy chỗ ấy" và đọc ra địa chỉ "abc...xyz" (chứ không phải "123456789" nữa) và nhẩy tới địa chỉ
"abc...xyz" để thực hiện code. Chỉ có điều ở "abc...xyz" là code của hàm nhái MyDialogBoxParam
chứ không phải của hàm DialogBoxParam.
Tất nhiên trước khi đánh tráo địa chỉ của hàm được ghi ở "đâu đó" (trong header của DLL) trong
RAM thì ta phải ghi nhớ nó để sau đó trả về hiện trạng cũ - lại tới "chỗ ấy chỗ ấy" và ghi vào
"123456789" đè lên "abc...xyz"
Những kỹ thuật: xin phép thao tác trong RAM ở vùng nào đó, ghi trong RAM, đánh tráo địa chỉ hàm
... là những kỹ thuật cao cấp. Người có trình độ trung bình cũng có thể thao tác trong RAM nhưng để
đánh tráo địa chỉ thì phải thông hiểu nhiều hơn mới biết cách làm - thay đổi những bai nào trong
RAM, ở đâu ...
----------------
Trở lại code của quanghai gửi nếu tôi không lầm thì hiện thời code "chưa làm gì cả". Vì khi hiển thị
FrmHookMain và nhấn nút "RemoveVBAPassword" thì code đánh tráo địa chỉ của hàm
DialogBoxParam (thay vì hướng tới DialogBoxParam thì hướng tới hàm nhái MyDialogBoxParam)
nhưng ta không click được vào VBAProject để xem code. Phải đóng FrmHookMain mới click vào
được. Nhưng khi đóng FrmHookMain thì địa chỉ cũ lại được trả lại (đánh tráo lại) trong
UserForm_Terminate nên lúc này có nhấn VBAProject thì hàm DialogBoxParam lại được thực hiện
chứ không phải hàm nhái nên ta lại thấy hộp thoại bắt nhập mật khẩu hiện ra.
Vậy trong tập tin đính kèm tôi làm như sau:
a - Trên Sheet có 2 nút: "Đánh tráo" và "Trả lại"
b - Trước tiên ta nhấn "Đánh tráo", code của nó là:
Mã:
If Hook Then
        MsgBox "VBA Password is Removed!", vbInformation, "Excel Tool"
End If
Từ lúc này mọi cuộc gọi hàm DialogBoxParam thì thực chất là gọi hàm nhái MyDialogBoxParam
mà nó sẽ trả về 1, tức Excel sau đó kiểm tra thấy 1 được trả về thì tưởng rằng user nhập đúng mật
khẩu và nhấn OK - y như cái procedure của hộp thoại mà nó thiết kế trả về khi user nhập đúng mật
khẩu và nhấn OK.
c - Ta nhấn VBAProject để xem và copy code
d - Ta nhấn "Trả lại" để thực hiện code RecoverBytes. Nó sẽ trả lại (trong RAM) địa chỉ cũ của hàm
DialogBoxParam.
-----------------
Nói đến test thì tôi lại là vua lười.
Vậy ndu hãy test và thông báo kết quả thế nào
Xin hỏi anh và các anh chị trên diễn đàn!.
Tôi sử dụng file thì thấy code báo lỗi đoạn code sau: (Tôi sử dụng Win 10 và office 2013) mong anh chị giúp

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
 
Upvote 0
Web KT
Back
Top Bottom