欢迎您访问科普小知识本站旨在为大家提供日常生活中常见的科普小知识,以及科普文章!
您现在的位置是:首页  > 科普文章

穷举破解EXCEL、WORD文档密码

科普小知识2022-12-09 10:36:54
...

摘要:本文讨论了如何使用vb编程,通过穷举法解除excel文档和word文档的密码。并在破解过程中加入了中断,以方便用户随时中断破解过程。

关键字:穷举法、解密、excel文档、word文档、密码

excel和word提供了多种方法限制访问用户文档,以免未经授权者的查看和更改。但在信息化的今天,用户需要记忆的密码太多,一旦密码丢失,用户将无法打开或访问该文档,给用户造成很大的损失。能否借助计算机的高速运行,解开密码呢?通过尝试,笔者认为:在无法弄清excel和word加密算法的情况下,利用穷举法尝试解密文档,是解密唯一的选择。

1. 实现原理

本程序选用vb6.0编写,并充分利用了office组件中的对象库,穷举尝试各种口令,达到解密文档的目的。

⑴ 巧用整数的取整及取余,产生密码字符串

excel和word文档密码可以是字母、数字、空格以及符号的任意组合,最长可达 15 个字符,且区分大小写。

本程序的破解过程利用一个两层循环,产生选定字符的排列组合(尝试密码),其中外层循环控制密码的位数,内层循环生成n位密码的所有排列组合。产生尝试密码的方法是:将一个n位字符串密码(password)作为一个“数值”,该“数值”每个位上的“数字”属于选定字符范围,且该“数值”与一个整数(x)一一对应,并满足以下条件: 0 ≤x ≤arraylenn-1(arraylen是选定密码字符范围的总字符数,如:仅选定数字时,arraylen=10;仅选定数字和小写字母时,arraylen=10+26=36);对x整除、取余n-1次,对每次的余数y做以下操作:password = password + chararray(y) (注:chararray是存放选定字符的一维数组),最后做以下操作:password = chararray(x mod arraylen) + password,产生的password 就是整数x对应的n位字符串。WwW.11665.coM

⑵ 利用vb的错误处理功能,尝试口令破解

当运行程序尝试一个密码时(用该密码打开文档),若密码错误,则会产生运行错误。为此,必须在尝试口令前,使用on error 语句打开一个错误处理程序;由于本程序是尝试各种口令,当一个口令错误时,直接尝试下一个口令即可,因此,应使用 “on error resume next”语句。

那么,如何得知找到口令了呢? vb有一个内部错误对象err,它的 number 属性中的值是用来确定发生错误的原因。在尝试一个口令后,检查err.number中的值,以确定该口令是否正确。

⑶ 破解过程中的中断

利用穷举法解密对系统资源的占用是十分惊人的,在解密的过程中cpu的利用率几乎是100%,若不加入解密过程中的中断,计算机系统会处于一种假死机状态。为此,在破解过程的内循环中加入了doevents函数。doevents函数提供了一种取消任务的简便方法,它将控制切换到操作环境内核。只要此环境中的所有应用程序都有机会响应待处理事件,应用程序就又恢复控制。使用该函数的优点是:不会使应用程序放弃焦点,且后台事件能够得到有效处理。

2. 具体实现过程

编程实现时,需要机器安装有vb应用程序及microsoft office组件。

⑴ 新建vb工程,并对其初始化

新建一个vb工程,取名get_password,将启动窗体命名为frmmain。首先选择“工程”菜单中的“引用”,在“引用”对话框中选择“microsoft excel10.0 object library”和“microsoft word10.0 object library”(注意:如果安装的是office2000或office97,应该选择excel对象库和word对象库的9.0版或8.0版)。其次在“工程”菜单中“部件”对话框中,选择添加“microsoft windows common controls -2.5(sp2)”和“microsoft common dialog control 6.0”,以便在窗体设计中使用微调控件和对话框控件。

⑵ 在frmmain窗体上添加控件

在frmmain窗体上,按照下图的位置添加表1中的控件,然后根据表1修改每个对象的属性。

表1:

序号 控件名称 控件属性及其属性值

1 frame name=frame1,caption=选择加密文件(*.doc、*.xls)

2 frame name=frame2,caption=选定密码字符范围:

3 frame name=frame3,caption=选择密码的长度:

4 combobow name=combo1

5 commandbutton name=cmdbrowse,caption=浏览

6 commandbutton name=cmdstartcrack,caption=开始破解

7 commandbutton name=cmdquit,caption=退出系统

8 checkbox name=chkdigital,caption=数字(10)

9 checkbox name=chklowercase,caption=小写字母(26)

10 checkbox name=chkuppercase,caption=大写字母(26)

11 checkbox name=chkspace,caption=空格(1)

12 checkbox name=chkbracket,caption=括号(6)

13 checkbox name=chkothers,caption=其他oem字符(26)

14 textbox name=txtpasswordstartlong, text=2

15 textbox name=txtpasswordendlong,text=2

16 textbox name=text1

17 updown name=updown1,buddyproperty=text,wrap=true,increment=1

buddycontrol=txtpasswordstartlong,max=15,min=

18 updown name=updown2,buddyproperty=text,wrap=true,increment=1

buddycontrol=txtpasswordendlong,max=15,min=1

19 commondialog name=dialog,dialogtitle=请选择加密的excel或word文档

filter=excel(*.xls),word(*.doc)|*.xls;*.doc

20 label name=label1, caption=破解进度:

21 label name=label3,caption=从:

22 label name=label5,caption=到:

⑶ 为以上对象编写下列代码

为了便于理解,程序中增加了适当的注释。

option explicit

private sub cmdbrowse_click()

dialog.showopen 'show the dialog

combo1.text = dialog.filename 'set the filename text box to the selected file

combo1.refresh

end sub

private sub cmdquit_click()

end

end sub

private sub cmdstartcrack_click()

static blnprocessing as boolean

dim wd as new word.application, xls as new excel.application

dim openreturn

dim strpath, pass, strtemp, all_char(100) as string

dim j, k, password_start_long, password_end_long, arraylen as integer

dim i, temp as long

arraylen = 0 '数组初始化

if chkdigital.value = 1 then

for j = arraylen to arraylen + 9

all_char(j) = chr(asc("0") + j - arraylen)

next j

arraylen = arraylen + 10

end if

if chklowercase.value = 1 then

for j = arraylen to arraylen + 25

all_char(j) = chr(asc("a") + j - arraylen)

next j

arraylen = arraylen + 26

end if

if chkuppercase.value = 1 then

for j = arraylen to arraylen + 25

all_char(j) = chr(asc("a") + j - arraylen)

next j

arraylen = arraylen + 26

end if

if chkspace.value = 1 then

all_char(arraylen) = " "

arraylen = arraylen + 1

end if

if chkbracket.value = 1 then

all_char(arraylen) = "("

all_char(arraylen+1) = ")"

all_char(arraylen+2) = "{"

all_char(arraylen+3) = "}"

all_char(arraylen+4) = "["

all_char(arraylen+5) = "]"

arraylen = arraylen + 6

end if

if chkothers.value = 1 then

for j = arraylen to arraylen + 6 '33 to 39

all_char(j) = chr(33 + j - arraylen)

next

arraylen = arraylen + 7

for j = arraylen to arraylen + 5 '42 to 47

all_char(j) = chr(42 + j - arraylen)

next j

arraylen = arraylen + 6

for j = arraylen to arraylen + 6 '58 to 64

all_char(j) = chr(58 + j - arraylen)

next j

arraylen = arraylen + 7

all_char(arraylen) = chr(92)

arraylen = arraylen + 1

for j = arraylen to arraylen + 2 '94 to 96

all_char(j) = chr(94 + j - arraylen)

next j

arraylen = arraylen + 3

all_char(arraylen) = chr(124)

all_char(arraylen+1) = chr(126)

arraylen = arraylen + 2

end if

if arraylen = 0 then

msgbox "错误:没有选择'密码使用的字符'", , "请选择密码使用的字符范围..."

exit sub

end if

if blnprocessing then

if msgbox("真的要中断解密过程吗?", vbyesno, "用户中断任务") = vbyes then blnprocessing = false

else

cmdstartcrack.caption = "中断破解"

blnprocessing = true

strpath = combo1.text

if strpath = "" then

msgbox "错误:没有选择'需要解密的文件'", , "请选择需要解密的文件..."

exit sub

end if

strpath = trim(strpath)

password_start_long = val(txtpasswordstartlong.text)

password_end_long = val(txtpasswordendlong.text)

if password_start_long > password_end_long then

password_start_long = val(txtpasswordendlong.text)

password_end_long = val(txtpasswordstartlong.text)

end if

label1.caption = "破解进度:"

label1.refresh

on error resume next

if ucase(right(strpath, 3)) = "xls" then

for k = password_start_long to password_end_long '破解excel开始

for i = 0 to arraylen ^ k - 1

pass = ""

temp = i

for j = 1 to k - 1

temp = temp \ arrayle

pass = all_char(temp mod arraylen) + pass

next j

pass = pass + all_char(i mod arraylen)

set openreturn = xls.workbooks.open(filename:=strpath, password:=pass)

text1.text = pass '显示破解进度

text1.refresh

if err.number 0 then '如果解密成功,打开文档,显示密码,退出过程

err.clear

else

label1.caption = "文档密码:"

text1.text = pass

me.refresh

xls.visible = true

cmdstartcrack.mousepointer = 0

cmdstartcrack.caption = "开始破解"

blnprocessing = false

set xls = nothing

exit sub

end if

doevents

if not blnprocessing then exit for

next i

if not blnprocessing then exit for

next k

xls.quit

set xls = nothing

else

for k = password_start_long to password_end_long '破解word开始

for i = 0 to arraylen ^ k - 1

pass = ""

temp = i

for j = 1 to k -

temp = temp \ arraylen

pass = all_char(temp mod arraylen) + pass

next j

pass = pass + all_char(i mod arraylen)

openreturn = wd.documents.open(filename:=strpath, passworddocument:=pass)

text1.text = pass '显示破解进度

text1.refresh

if err.number 0 then '如果解密成功,打开文档,显示密码,退出过程

err.clear

else

'msgbox "word password"

label1.caption = "文档密码:"

text1.text = pass

me.refresh

wd.visible = true

cmdstartcrack.mousepointer = 0

cmdstartcrack.caption = "开始破解"

blnprocessing = false

set wd = nothing

exit sub

end if

doevents

if not blnprocessing then exit for

next i

if not blnprocessing then exit for

next k

wd.quit

set wd = nothing

end if

cmdstartcrack.caption = "开始破解"

if blnprocessing then msgbox "没有找到密码,可能是密码位数不对!", , "提示信息..."

blnprocessing = false

end sub

3. 时间复杂度分析

一个算法的时间复杂度,是指该算法的时间耗费,是该算法所求解问题规模n的函数。根据前面讲的实现原理,我们知道,破解算法的时间耗费主要集中在尝试打开office文档上,因此,当我们假设破解一个n位字符串密码,且选定密码字符范围的总字符数为arraylen时,该算法的时间复杂度是o(arraylen^n)。即,当n确定后,该算法的时间复杂度是n次方阶;当arraylen确定后,该算法的时间复杂度是指数阶。都是高数量级的时间复杂度。

4. 说明

穷举法解密对系统资源的占用是十分惊人的,在解密的过程中最好不要运行其他应用程序。如果安装有瑞星等杀毒软件,应将杀毒软件的“office安全助手”去掉,以便加快程序的运行速度。

该程序在winxp+officexp+vb6.0环境下测试通过,笔者随便测试了一个5位数字密码,在p4机器上,8分钟左右即可解开口令。

参考文献:

[1] 王建华 译. visual basic 6 开发人员指南. 北京:机械工业出版社,1999