65.9K
CodeProject 正在变化。 阅读更多。
Home

通过互操作/自动化进行暴力密码搜索

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.76/5 (8投票s)

2018年6月14日

CPOL

10分钟阅读

viewsIcon

12247

downloadIcon

349

如何使用 Microsoft Interop/Automation 实现 Microsoft Office 文件密码的并行搜索。

引言

是否可以通过自动化恢复 Microsoft Office 文件中遗忘的密码?答案是肯定的,通过自动化/互操作、多线程和大量可量化的 CPU 时间进行暴力破解。

该软件的主要目标是验证互操作打开受密码保护文件的能力,并检查密码何时足够强大以抵御攻击。但该软件也可以在实际生活中使用,以查找您拥有文件的遗忘密码。事实上,它正是为了打开所有者忘记确切密码的文件而编写的。

在哪里获取?

包含算法的表单可以从此处下载 (^) 并插入到您的新 Visual Studio 项目中。

为什么要使用互操作/自动化?

Microsoft Interop 允许开发人员管理 MS Office 文件,并使其易于创建使用暴力破解查找遗忘密码的程序。

  • 它在 Microsoft Office 文档上运行良好。
  • 易于实现。
  • 它允许避免研究加密算法(及其可能存在的非标准实现)或花费时间研究和理解每种文件类型(Excel .xls.xlsx、Word .doc.docx 等)的文件结构。

反之

  • 在打开受密码保护的文件操作上,它的时间性能不佳。

软件要求

要使用由 Visual Studio 2017 开发的软件。目标计算机上需要安装 Microsoft Office(或 Excel 或 Word,根据要处理的文件类型)。

错误 CS0234

如果您遇到错误 CS0234,这意味着您需要引用 Office 库。打开菜单“项目”,选择“添加引用...”,然后选择“COM”选项卡,滚动列表到“Microsoft Word 16.0 对象库”或其他您拥有的版本。

完成任务所需时间

暴力破解攻击完成任务所需的时间是可预测的。它可以计算为可接受的chars 组合的乘方,其中乘方数为可测试的最大密码长度。

例如,如果我们要破解一个只由大写字母组成且长度在1到6之间的密码,那么我们有26个字符要测试,从“A”重复到“ZZZZZZ”。

要测试的总组合数(更准确的数学术语是排列)为

  • 1 个字符('A' 到 'Z'):26 ^ 1 = 26;
  • 2 个字符('AA' 到 'ZZ'):26 ^ 2 = 676;
  • 3 个字符('AAA' 到 'ZZZ'):26 ^ 3 = 17,576;
  • 4 个字符('AAAA' 到 'ZZZZ'):26 ^ 4 = 456,976;
  • 5 个字符('AAAAA' 到 'ZZZZZ'):26 ^ 5 = 11,881,376;
  • 6 个字符('AAAAAA' 到 'ZZZZZZ'):26 ^ 6 = 308,915,776;

总和是 321,272,406 个可能的密码。

现在,计算时间的最后一步是添加时间因素。

用于测试的旧硬件获得的每分钟测试量约为1500次。那么

  • 321,272,406 组合数 / 1,500 次测试/分钟 = 214,182 分钟
  • 214,182 分钟 / 60 分钟/小时 = 3,570 小时
  • 3,570 小时 / 24 小时/天 = 148 天(或 5 个月)。

在最坏情况下,148 天的情况由“ZZZZZZ”表示。最好的情况是密码只填充“A”,它会立即被测试并找到。

可以跳过过短的密码,例如,从 4 个字符长度的密码(即“AAAA”)开始。
当然,如果我们知道密码长度,那将大大节省时间。

通过算法避免诸如“RKWLPG”或“TMQNTZ”(仅仅因为它们毫无意义,因此难以记住或位于键盘的无序位置——与“QWERTY”相反——)等绝对不可能的密码来减少组合数,这是不可能的,并且存在跳过正确密码的具体风险。

要测试的标准字符集

为了完善信息,记住实际组合必须基于包含所有可能性的字符集是很有用的。至少

  • 小写字母:'a' 到 'z':26 个
  • 大写字母:'A' 到 'Z':26 个
  • 数字:'0' 到 '9':10 个
  • 特殊字符:括号(六个)、空格、货币符号(三个或更多)、标点符号(六个或更多)以及其他:超过 20 个。

总计 26+26+10+10 超过 70 个字符。因此,如果密码长度为 5 个字符,我们将得到 70^1 + 70^2 + 70^3 + 70^4 + 70^5 = 1,680,700,000 个可能的密码需要测试(而如果使用单个字母表集,则为 308,915,776 个,如前所述)。

我必须强调,如果此软件用于您的文件,它将非常有用,因为您可以降低所有可能性的复杂性。事实上,您知道

  • 哪些char集适用或不适用(例如,如果您从未使用某些特殊char或大写字母集,则可以将其从测试中排除)。
  • 密码的最小长度(例如,如果您使用8个或更多char的密码,这意味着您从该长度开始处理,从而节省大量时间)
梦想更快的 CPU 速度

测试由一台非常老的 Intel i5 760 2.80GHz 4 核处理器进行。对于那些需要性能的人来说,预计在 2018 年底,将推出 Intel® Core™ i9 Extreme Edition 处理器,拥有 18 核和 36 线程,其速度可以表示为一个 teraflop(1012 FLOPS):建议的计算时间将大大缩短。我猜从 1 个月缩短到 1 周。
如果您没有时间等待,现在存在一种每秒可以进行 200,000 万亿次计算的新型超级计算机(200 petaflops,200x 1015 FLOPS)。我猜时间将从一个月缩短到一天或更短。

可参数化内容

该软件提供了选择以下内容的可能性

  • 可用于猜测密码的字符类型:大写字母、小写字母、数字。目前,特殊字符未作为可用字符集插入。
  • 密码长度范围:要检查的最小和最大长度:这对于避免浪费时间验证过短的密码非常有用。
  • 要使用的核心数量:此功能旨在限制 CPU 负载,以保持日常负责的计算机。此外,任务以低优先级模式执行,因此它们不影响正常使用。

Using the Code

该软件使用一个表单,创建并启动多个线程:每个线程循环顺序测试由 PasswordNext() 函数获得的密码,直到 StopSearch()false。当找到密码时,将通过 StopSearch(true) 设置一个标志。

测试字符集

允许的 char 集合通过表单中的一些复选框定义,它将由 AllowedCharsToString() 函数返回:目前可以管理

  • 小写字母
  • 大写字母
  • 数字

创建非侵入式线程

暴力破解是一个大量消耗 CPU 资源的工具,它会将计算机变成僵尸。为了让您能够在几乎正常的情况下继续使用计算机,线程是以最低优先级创建的。CPU 会一直保持 100% 忙碌,但您通过其他软件或工作的交互具有优先权:操作系统将为您服务,并根据需要暂停暴力破解。

下面是创建和启动所有线程的代码:它们将被插入到 List<Thread> 中,以便后续引用。指令 T.Priority 用于将线程设置为最低优先级。

TTCll = new System.Collections.Generic.List<System.Threading.Thread>();
for (int numt = 0; numt < ThreadToUse; numt++)
{
    TextBox NumTxt = (TextBox)(EsecuzioneTLP.Controls
                     ["NumThread" + numt.ToString("00") + "Txt"]);
    var T = new System.Threading.Thread(() => { Runner(NumTxt); });
    T.Priority = System.Threading.ThreadPriority.Lowest;
    T.Start();
    TTCll.Add(T);                
}

显示运行状态

当面对长时间运行的循环时,告知用户一切正常且没有卡住非常重要。该软件可以使用可选数量的核,因此表单中将使用 TableLayoutPanel,其中将包含启动时生成的 LabelsTextboxes:每个都将绑定到不同的线程,并用于显示当前正在测试的密码。

int ThreadToUse = int.Parse(MaxTasksTxt.Text);
ThreadPanel_Create(ThreadToUse );

运行时表单如下所示。底部灰色背景区域,显示了 TableLayoutPanel,其中有四个编号从“00”到“03”的线程,分别显示它们当前正在测试的密码:“6K”、“6L”、“6J”、“6M”。

建议

如果您将启动测试,请记住禁用计算机的睡眠/待机功能,否则第二天您可能会发现计算机停止运行。

线程函数:Runner()

每个线程使用的主要函数名为 Runner()。使用参数 NumTxt,它是一个 TextBox,循环可以更新表单上当前要测试的密码。该 TextBox 是在 TableLayoutPanel 中动态创建的。

创建实例

线程创建一个软件实例,用于尝试打开受密码保护的文件

var WApp = new Microsoft.Office.Interop.Word.Application(); 

主循环

测试各种可能密码的循环是一个 while,它通过 StopSearch() 检查线程是否必须停止,因为找到了正确的密码。

该函数的核心调用 Open(),参数为从 PasswordNext() 获取的密码。

如果密码正确

如果测试的密码能够打开文件,则例程将执行以下步骤

  • 调用 StopSearch(true) 来设置一个标志。
  • 调用 Achieved() 并使用密码作为参数来更新用户界面。

然后,可以释放资源 WDoc

try
{
    WDoc = WApp.Documents.Open(FileName, PasswordDocument: test , ReadOnly: true);
    StopSearch(true);

    Achivied(test); 

    WDoc.Close();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(WDoc);
}

如果密码不正确

在受密码保护的文件上使用错误的密码调用 WApp.Documents.Open() 会引发异常。这就是为什么需要用 try/catch 包装该指令的原因。

catch 内部不需要执行任何操作。事实上,WDocnull。如果您想对异常做些什么,ex.Message 字符串比较必须根据计算机上使用的语言进行更改。

if (ex.Message.Contains("La password non è corretta. Word non può aprire il documento."))

线程结束

例程的最后一步是使用指令释放 Interop 实例

ReleaseComObject(WApp);

为了使其更健壮,ReleaseComObject()try/catch 保护。

下一个密码是什么?

名为 PasswordNext() 的函数返回下一个要测试的密码。第一个值是“A”,后面将依次是每个字母,直到“Z”;之后,将从“a”到“z”以及从“0”到“9”开始(构成序列的字符类型来自 AllowedCharsToString())。

private char []  PasswordNext()
{
    char[] GiveBack; 

    lock (SyncLockerobjNewPassword)
    {
        // --- password to verify
        GiveBack = new char[PasswordToVerify.Length]; 

        // --- password to prepare to next round
        PasswordToVerify.CopyTo(GiveBack,0);
        //  prepare next pwd 
        bool riporto = false;
        for (int i = PasswordToVerify.Length - 1; i >= 0; i--)
        {
            // last char of the set?
            if (PasswordToVerify[i] != AllowedCC[AllowedlattertIdx])
            {       
                // increment
                PasswordToVerify[i] = 
                AllowedCC[(ammessistr.IndexOf(PasswordToVerify[i]) + 1)];                 
                riporto = false ;
                break;
            }
            else
            { 
                // zero
                PasswordToVerify[i] = AllowedCC[0];
                riporto = true;
            }
        }
        // --- insert new starting char on left side
        if ( riporto)
        {
            char [] tmp = new char[PasswordToVerify.Length ];
            PasswordToVerify.CopyTo( tmp,0) ;

            PasswordToVerify = new char[PasswordToVerify.Length + 1];
            PasswordToVerify[0] = AllowedCC[0];
            tmp.CopyTo(PasswordToVerify, 1);
        }
    }

    return GiveBack ;
}

我找到了!

这是处理结束时,找到密码后的表单。它报告了以下信息

  • 每个线程最后测试的密码(无用)
  • 找到的密码(本例中为“AB0”)
  • 开始时间
  • 结束时间
  • 完成任务所用的时间

启动按钮保持禁用状态,以防止用户不小心启动另一次运行。要运行另一次测试,必须重新启动软件。

更改目标文件

要针对 Excel 文件使用代码,需要修改的行是 WApp 声明,将其更改为

var WApp = new Microsoft.Office.Interop.Excel.Application();      

次要关注点

对于使用 TableLayoutPanel 的新开发者,ThreadPanel_Create() 是一个有用的函数,可以帮助理解如何在运行时创建列,并插入 LabelTextBox 等控件。需要注意的是,此控件始终有一个列。

对于接触线程的人来说,有一个关于创建和同步线程的很好的例子,可以根据其中一个线程变为真实的情况来停止它们。

结论

如果 Microsoft 密码保护遵循任何密码的简单规则:长度(超过 8 个字符)、使用大范围字符集:大写和小写字母、数字和特殊字符,那么它就足够强大。但是,如果您正在寻找丢失的密码,那么您有很大的机会恢复它。当然,如果您不着急的话!

历史

  • 2018 年 6 月 14 日:初始版本
© . All rights reserved.