摘 要:该文以Windows XP为平台,使用Visual Basic 6.0企业版编程工具,利用穷举法破解Microsoft Office XP Professional办公软件的Word文档和Excel文档设置的打开权限密码。
关键词:密码;解密;密码字符集;权限密码
为了安全,Microsoft Word和Excel可以通过设置“打开权限密码”来限制用户访问,以保护文档不被别人非法打开查看和修改,但如果用户不小心忘记了自己设置的密码,则可能会给用户带来不便和损失。本文研究利用穷举法来对已加密文档进行解密。
一、算法
(一)生成密码字符串
Microsoft Word和Excel文档的密码最多可以设置15个字符,可以是数字、字母(区分大小写)以及其他字符的任意组合。
利用穷举法破解文档密码的流程是先设定密码字符集合,并指破解密码的长度或范围,然后利用该集合的所有排列组合(即:尝试密码)去一个个尝试打开加密的文档,算法的关键是生成选定字符集中相应密码长度的所有排列组合。本程序主要利用两个For循环来生成选定字符集的所有排列组合,外层循环控制密码的位数K(1≤K≤15)的变化,内层循环生成K位密码的所有排列组合。
第一步,设置密码字符集。将选定的字符集合存储到一个字符数组password_char(ArrayLength)中。ArrayLength是选定字符集的长度。在设置密码字符集时,若只选择数字,则ArrayLength=10;若选择数字与小写字母,则ArrayLength=36。
第二步,产生K位密码组合字符串。假设密码长度为K位,那么共有ArrayLength的K次方(即:ArrayLengthK)种排列组合。用0~ArrayLengthK-1之间的一个整数N(即:0≤N≤ArrayLengthK-1)相对应于一组尝试密码,那么每一种密码组合都可以通过结合数值N和字符数组password_char(ArrayLength)来表示,从而得到密码长度为K时所有密码组合。
产生K位密码字符串的方法是:对于整数值N的来说,先对字符集长度进行整除运算(即:N=Int(N/ArrayLength));再用得到的新数值N对字符集长度求余(即:M=NMod ArrayLength),则数值M就对应于字符集里面的字符password_char(M),该字符就是密码字符串的第K-1位字符。不断重复上述先整除再求余的运算步骤K-1次,即可得到从第1位到第K-1位密码字符串。最后一位字符,也就是第K位字符,可直接用原来的整数值对数组长度求余来获得;
比如,当字符集为“ABC”时,字符数组为password_char(3)={“A”,“B”,“C”}。ArrayLength=3。对于长度为三位(K=3)的密码,共有排列组合ArrayLengthK =33=27种(即0≤N≤26)。当N=0时,对应的密码字符串为“AAA”;当N整数N=21时,对应的密码字符串为“CBA”;当N=26时,对应的密码字符串为“CCC”。
(二)尝试密码破解
当运行程序用一个密码去打开加密文档时,若密码不正确,则会产生运行错误,导致程序中止运行,这在穷举法中是我们不希望发生的,因此,必须使用On Error Resume Next语句打开一个错误处理程序。在尝试一个密码之后,通过检查Visual Basic内部错误对象Err的属性值 Number来确定该密码是否正确,如果密码正确,则给出破解成功提示信息并中止程序运行,否则继续尝试下一个密码。
二、程序设计
(一)程序流程***
(二)具体实现
1.新建VB工程
新建一个VB工程,取名GetPassword,将启动窗体命名为FrmMain。
选择“工程”菜单中的“引用”,在“引用”对话框中选择“Microsoft Excel10.0 Object Library”和“Microsoft Word10.0 Object Library”(注:其它版本的Office软件对象库各不相同,在“引用”对话框中视情况选择),以便程序能够引用Office组件的对象库。
在“工程”菜单中“部件”对话框中,选择添加“Microsoft Windows common controls -2.5(sp2)”,以便在窗体设计中使用微调控件。
2.窗体设计
在FrmMain窗体上,按照界面设计***添加控件,然后按对象属性表修改每个控件对象的属性(窗体设计***略)。
控件对象属性表:
3.程序代码
驱动器列表框:
Private Sub driveList_Change()
On Error GoTo DriveHandler
dirList.Path = driveList.Drive
Exit Sub
DriveHandler:
driveList.Drive = dirList.Path
End Sub
目录列表框:
Private Sub dirList_Change()
fileList.Path = dirList.Path
End Sub
复选框控件数组:
Private Sub chkCharSet_Click(Index As Integer)
Dim str As String
str = ""
If chkCharSet(0).Value = 1 Thenstr = "0123456789"
If chkCharSet(1).Value = 1 Then str = str & "abcdefghijklmnopqrstuvwxyz"
If chkCharSet(2).Value = 1 Thenstr = str & "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
If chkCharSet(3).Value = 1 Then str = str & " "
If chkCharSet(4).Value = 1 Then
str = str & "`~!@#$%^&*_|\()[]{}-+=,.;:?/"
str = str & Chr(39) '单引号
str = str & Chr(34) '双引号
End If
txtPassSet.Text = str
End Sub
开始破解按钮代码:
Private Sub cmdCrack_Click()
Dim wd As New Word.Application, xls As New Excel.Application
Dim filepath, pass, password_char() As String
Dim j, k, m, Password_Length_From, Password_Length_To, ArrayLength As Integer
Dim i, n As Long
Dim flag
Static blnStop As Boolean'破解过程中断标志,静态变量
If fileList.FileName = "" Then
MsgBox "请选择要破解的密码文档!", , "提示!"
Exit Sub
Else
filepath = fileList.Path & "\" & fileList.FileName
End If
数组初始化:
If txtPassSet.Text = "" Then
MsgBox "请设置密码字符集!", , "提示!"
Exit Sub
Else
ArrayLength = Len(txtPassSet.Text)
动态定义字符数组:
ReDim password_char(ArrayLength)
For j = 0 To ArrayLength - 1
password_char(j) = Mid(txtPassSet.Text, j + 1, 1) Next jEnd If
设置密码的长度范围:
Password_Length_From=Val(txtPasswordLengthFrom.Text)
Password_Length_To = Val(txtPasswordLengthTo.Text)
If Password_Length_From > Password_Length_To Then
Password_Length_From = Val(txtPasswordLengthTo.Text)
Password_Length_To = Val(txtPasswordLengthFrom.Text)
End If
If blnStop Then
blnStop = False
Else
blnStop = True
cmdCrack.Caption = "中断破解"
On Error Resume Next
If UCase(Right(filepath, 3)) = "DOC" Then
指定破解的是Word文档:
For k = Password_Length_From To Password_Length_To
For i = 0 To ArrayLength ^ k - 1
pass = ""
n = i
For j = 1 To k - 1
n = Int(n / ArrayLength)
m = n Mod ArrayLength
pass = password_char(m) + pass
Next j
pass = pass + password_char(i Mod ArrayLength)
txtPassword.Text = pass
Set flag = wd.Documents.Open(FileName:=filepath, passworddocument:=pass)
If Err.Number = 0 Then
MsgBox "文档密码是: " + pass, , "解密成功!"
wd.Quit
Set wd = Nothing
cmdCrack.Caption = "开始破解"
blnStop = False
Exit Sub
Else
Err.Clear
End If
DoEvents
If Not blnStop Then Exit For
Next i
If Not blnStop Then Exit For
Next k
wd.Quit
Set wd = Nothing
Else
指定破解的是 Excel文档:
代码与以上破解Word文档的代码相似,此处不再详述。使用尝试密码打开加密Excel文档的语句如下:
Set flag = xls.Workbooks.Open(FileName:=filepath, password:=pass)
End if
End If
If blnStop Then MsgBox "没有找到密码,可能是密码位数或者字符范围设置不对!", , "提示!"
cmdCrack.Caption = "开始破解"
blnStop = False
End Sub
三、程序分析
1.在设置密码字符集时,使用了复选框控件数组,在文本框中显示选定的字符集,可以根据需要修改文本框中字符集的内容,然后在程序中根据字符集的长度动态创建字符数组,能够灵活适应不同的要求。
2.程序算法的关键是根据设定的密码长度或范围,生成密码字符集中相应长度的所有排列组合,即产生密码字符串。
3.密码位数越多,组合越复杂,破解花费的时间也将越多。
4.利用穷举法解密对系统资源的占用是十分惊人的,在解密的过程中CPU的利用率几乎是100%,计算机系统会处于一种假死机状态,用户将无法进行其他操作,直到该程序运行结束,这样将可能给用户带来不便。为此,本文解决的方法是在循环中加入了DoEvents函数,在运行到DoEvents时,程序释放控制权,系统就可以接收事件消息。通过设置静态变量blnStop为中断标志,并在循环中通过检测其状态并进行相应处理来达到中断程序运行的目的。
参考文献:
[1]赛奎春,高春艳.Visual Basic精彩编程.北京:机械工业出版社,2003.
[2]龚沛曾.visual Basic 程序设计教程(第三版).北京:高等教育出版社,2006.
转载请注明出处学文网 » 破解Microsoft Word和Excel文档的密码