如何暴力破解一个有点记住的aescrypt密码?

信息安全 密码 AES 蛮力 密码破解
2021-08-23 14:00:47

我有一个大约 5 年前通过 aescrypt 用 AES 加密的文件。我记得很多关于带有几个前缀和后缀的密码的事情。我有程序员的经验,但没有暴力破解密码。

我该如何去暴力破解我的加密档案?

我想我知道的是:我需要一个彩虹表(可能的单词列表)和一些方法来引导工具找到可能的后缀和特殊字符。

我不知道哪种工具最适合这种特定情况,也不知道如何设置它们。我一直在阅读 Ubuntu 包管理系统提供的许多工具的手册页,但说明侧重于不同的场景,我似乎无法找到一种方法来指示我需要指出的内容。

如果我要为它编写自己的解决方案,我知道我可以接受aescrypt命令并直接在命令行上传递密码猜测。如果密码失败,它将返回非零退出状态,因此很容易检查。为了性能,我会用 Rust 编写它,并对线程实现有所了解。但除了尝试排列可能需要注入其他一些字符之外,我知道的不多。

此密码的规则很简单。其中有两个句点,最多 8 个可能的单词与可能的连词混合在一起,可能的破折号或下划线,以及这些单词的可能缩写。如果那失败了,我希望它恢复到带有后缀的正常蛮力。

这应该给我最大的机会来检索我的文件。我非常感谢您通过一些入门技巧和概述的说明指出正确的方向。太感谢了!

2个回答

我将在这里发布我学到的东西以供后代使用。我已经找到了做我想做的事的方法,尽管我怀疑我是否拥有完成任务的系统能力。

我尝试的第一件事是我猜测的所有可能组合。首先,我编写了一个 Ruby 脚本来生成它。

#!/usr/bin/env ruby

JOINERS = ['', '-', '_', ' ']
PREFIX = %w[words for prefix]
CONJUNCTION = ['and', nil]
OPTIONAL = %w[words for optional]
SUFFIX = %w[.tar.gz .tgz .tar.gz.aes .tgz.aes]

def permute collection, length = nil
  (1..(length || collection.length)).
    flat_map {|qty| collection.permutation(qty).to_a }
end

def prefixer
  permute(PREFIX, 3).each do |prf|
    yield prf
  end
end

def optionaler(pfx, j, s, cap = false)
  permute(OPTIONAL, 3).each do |opt|
    opt = opt.map(&:capitalize) if cap
    CONJUNCTION.each do |cj|
      puts [pfx.join(j), cj, opt.join(j)].compact.join(j) + s
    end
  end
end

SUFFIX.each do |s|
  JOINERS.each do |j|
    prefixer do |prf|
      puts prf.join(j) + s
      optionaler(prf, j, s)

      prf = prf.map(&:capitalize)
      puts prf.join(j) + s
      optionaler(prf, j, s, true)
    end
  end
end

我运行了这个脚本,输出给了我将近 500,000 个条目。然后,我使用我的 FishShell 遍历其中的每一个并尝试输入密码。

for password in (ruby script.rb)
  aescrypt -d -p $password encrypted_file.aes 2>/dev/null
end

这些都不起作用,所以我不得不改用蛮力……这意味着我可能永远不会打开它。

所以我学会了如何按照 Matthew 的建议使用crunch,并结合 xargs 非常棒!

由于我每次都运行一个 shell 命令来尝试解密文件,我认为磁盘驱动器 IO 可能是性能考虑因素,所以我创建了一个tmpfs文件系统文件夹来放入文件并在 RAM 中操作所有内容。

mkdir tmpfs
sudo mount -t tmpfs -o size=800M,mode=0755 tmpfs tmpfs/
cp encrypted_file.aes tmpfs/
cd tmpfs

这是我制定的第一个命令。

crunch 3 26 abcdefhilmnoprstuvwyz0123456789\ -_. -d 1@ --stdout | \
xargs -r -P 4 -I PASSWORD bash -c \
"! aescrypt -d -p 'PASSWORD' encrypted_file.aes 2>/dev/null"

这是零件。 crunch生成以下参数的所有可能性。第一个数字是最小字符数,第二个是最大字符数。之后是用于每次尝试的字符列表。我已经排除了我确定不在其中的字符,因此字符列表更短,并且该过程将更快地完成。接下来我有-d 1@,它告诉 crunch 没有两个相同的字符会彼此相邻。

然后我将它通过管道传递给xargs,这是一个很好的工具,通常用于将流式输入数据作为参数传递给以下命令/参数。但在这种情况下,我们使用-I选项将其传送到特定位置,该选项确定要替换的文本。-r选项表示不会与空的输入运行。-P 4,告诉它运行在通过四个不同的参数并行4个实例(这需要我的系统上利用所有4个核心)。使用 4 个内核而不是 1 个内核可以节省大约 60% 的时间成本。

接下来,我通过 bash 命令bash -c执行aescrypt ,并用传入的每个单独输入替换PASSWORD区域。我以 bang ( ! ) 开头的原因是因为当aescrypt没有成功解密它写入 STDERR 的文件时并给出一个失败的退出状态,这将立即停止整个命令。爆炸会翻转结果,以便在每次失败时它都会继续运行,但是当文件最终被解密时,它将否定积极响应并退出循环,因为我们的工作已经完成。

笔记

我意识到这不是最有效的方法,但我正在努力尝试。我将提供一些我见过的额外的性能观察。

使用xargs并行参数时,无论您走多高,您仍将获得与您拥有的核心数量相同的性能。但是,如果您使用xargs运行多个 shell,每个 shell 都要求比您拥有的内核更多,那么您将减慢所有 shell 的性能,就好像您只有 1 个内核一样。

由于我最好的猜测之一是密码以结尾,因此.tar.gz我通过将上面的命令更改为使用两个核心并将第二个命令的字符列表缩短为不包括gz或任何数字(因为如果扩展名存在数字)将任务分成两半此密码不存在)并且我已替换'PASSWORD''PASSWORD.tar.gz'. 第二个命令我还给出了 2 个并行进程。

因为我瞎了眼,我想知道进展如何,我研究了如何阅读管道中的内容。首先,您可以使用pidof crunch获取每个 crunch 实例的 PID 一旦你有了它,你可以通过以下方式观看通过每个单独的 PID 的流式传输:

sudo strace -pPID_NUM_HERE -s99999 -e write

从这里我可以写下进度,停止一个 crunch 过程,然后通过添加一个-s选项作为起点来重新启动我停止的 crunch 命令

迈向更好的表现

在两个字符的密码下,我每秒尝试大约 35 个密码,在 3 个字符的密码下,我每秒尝试大约 12 个密码。通过放在time -v --output=somefile上面的命令之前进行测试它并不快。

我意识到使用管道、xargs 和 bash 来运行这些命令每个都有自己的成本,而且我用 Rust 编写一个实现来完成上面所做的事情会更方便。我需要获取AES Crypt的源代码并将库链接到 Rust 以直接调用 C 代码。要么对crunch做同样的事情,要么只是手动实现我需要的部分(后者可能更好)。

如果我去掉所有的中间件外壳,只运行纯 Rust,它肯定会更高效。哎呀,如果我可以利用我的 GPU,那会很酷。但是我要到达那里有一点学习曲线。

我希望这些信息对其他人有用。随意分享和这个一样有启发性的答案。谢谢!


更新

Ori 问我是否测试过一条快乐的道路是否能按预期工作。事实证明,在这两种情况下我都没有考虑到这一点。我在这里有一个更新版本的 FishShell 脚本,它适用于快乐的路径。

for password in (ruby script.rb)
  if test -s the_file
    break
  else
    aescrypt -d -p $password the_file.aes 2>/dev/null
  end
end

测试test -s文件the_file是否为空白。 将在同一目录中写入一个没有扩展aescrypt名的相同文件名的空文件。.aes它也使用相同的名称来成功解密。在所有情况下都应考虑到这一点。

好的,新更新的crunchxargs代码将起作用:

crunch 3 26 abcdefhilmnoprstuvwyz0123456789\ -_. -d 1@ --stdout | \
xargs -r -P 4 -I PASSWORD bash -c \
"! aescrypt -d -p 'PASSWORD' -o 'PASSWORD' encrypted_file.aes \
2>/dev/null; if [[ -s \"PASSWORD\" ]]; then exit 255; fi"

无论当前密码是什么,这都会命名输出文件,如果文件不为空,则退出成功。我已经用一个例子对此进行了测试,它可以工作!

希望我现在可以解密我的文件。

2017 年 9 月 22 日更新:编写程序

我编写了一个名为abrute的多线程 AES 文件强力解密软件您需要在系统可执行路径中aescrypt才能正常工作。

而不是审查您的代码,特此开箱即用的解决方案。

“智能”字典攻击可能就是您要搜索的内容。尽管这确实需要足够的硬件来加快速度。静态字典攻击不是您要搜索的内容(除非您确实记住了密码),但像 Password Recovery Toolkit (PRTK) 这样的适当软件可能会为您提供帮助。PRTK 文档描述:

在字典攻击期间,PRTK 和 DNA 使用所选配置文件中的信息来创建传记和用户字典的变体、排列和组合。此外,它使用语音改变、添加前缀或后缀以及替换字符。

资料来源https ://ad-pdf.s3.amazonaws.com/PRTK_DNA_UserGuide.pdf