【问题标题】:How to enter/answer a terminal prompt from a Perl script?如何从 Perl 脚本输入/回答终端提示?
【发布时间】:2021-01-12 13:01:46
【问题描述】:

我正在尝试破解一个忘记的 luks 分区密码。我生成了一个组合列表,现在我正在尝试从 Perl 脚本中解密该卷。

问题是从脚本本身输入提示,因为:system('cryptsetup', ('open', '/dev/sdd1', 'crypt-vol', '--type=luks')) 只是吐出Enter passphrase for /dev/sdd1 并等待我手动输入。

我该如何处理?

非常感谢您的帮助。

* 这是我的卷,我没有完全忘记密码,所以我创建了组合列表,前提是我记得一些细节。这就像> 6k的可能性,所以打破它应该是可行的。

【问题讨论】:

  • 这是同一个问题吗? stackoverflow.com/questions/11236307/…
  • 忘记 perl。使用expect,它旨在处理从/dev/tty读取的交互式程序。
  • 或许使用 Perl 模块 Expect
  • @Jens 我已经用 Perl Expect 模块创建了一些东西。似乎可以运行,现在我最多会等待大约 20 个小时(我的估计),然后根据结果我会发布一些东西,或者是答案(如果有效)或更新问题。
  • @TLP 是的,我现在正在这样做。唯一的可能?问题可能是我在每个 while 循环中创建了一个新的 expect 实例,因为 crypsetup 在第二个或第三个 atemt 以代码 512 退出以输入密码

标签: perl terminal prompt interactive non-interactive


【解决方案1】:

不要,在 cryptsetup 中使用“密钥文件”。密钥文件可以是 STDIN。

所以:

echo "passphrase_here" | cryptsetup -d - <other  options>

在 perl 中,您可以为此使用 IPC::Run2,它允许您读取/写入 FH,但如果您只需要返回码来测试密码,则不需要。

例如https://blog.sleeplessbeastie.eu/2019/03/27/how-to-test-luks-passphrase/

所以:

open ( my $crypter, '|-', "cryptsetup luksOpen -d - --test-passphrase " )

print {$crypter} "Your passphrase";

close ( $crypter );
print "Got return code of $?"

【讨论】:

    【解决方案2】:

    我真的很喜欢使用 STDIN 的想法,所以如果有人在此页面上点亮,请考虑是否可以在您的情况下使用 STDIN。

    但我想发布我自己的答案,它使用 Expect Perl 模块,因为:

    • 我使用了它,并且证明它至少可以在 Linux 上运行(尽管 cmets 中的问题提到该模块在 Windows 上运行时存在问题);
    • 由于问题的标题没有提及cryptsetup(可以接受STDIN上的密码),所以Expect模块在这里就像一个通用的解决方案,它应该适用于其他工具;

    我的解决方案如下。我没有阅读太多文档,所以可能有更好的方法来做到这一点。对我来说,掌握对象实例化的概念和期望/发送方法就足够了。

    您创建一个实例,就像您刚刚在终端中启动一个程序一样:

    my $exp = Expect->new('progName', ($arg1, $arg2, $etc));
    

    然后可以通过expect(等待/确认程序向用户的输出)和send(允许用户“输入”)方法与之交互。

    expect 可以在标量或列表上下文中调用(我使用的是列表之一),它接受一个字符串或正则表达式,表示期望的输出和持续多长时间。如果在指定时间内没有出现预期的输出,则会引发错误:

                           #sec to wait for  #use regexp (don't match exactly) #regexp to match against
    my @out = $exp->expect(10,               '-re',                            'smth');
    

    send 只接受输入

    $exp->send('some chars');
    

    就是这样,只需要创建一个脚本,它就可以像人类用户一样工作。


    以防万一它对某人有用,我将发布我完整的 cryptsetup 特定解决方案(我已经在一个虚拟卷上对其进行了测试,它能够挂载,并且我已经在一个尝试了 6k 组合的真实音量,没有任何明显的问题):

    *我忘了在这里关闭文件描述符,所以应该在适当的地方添加close($fd)

    use strict;
    use warnings;
    use feature 'say';
    
    
    # I installed Expect with its deps locally in my situation, so I had to change @INC
    BEGIN {
      unshift(@INC, './perl-mods/lib/perl5/');
      unshift(@INC, './perl-mods/lib/perl5/x86_64-linux-thread-multi/');
    }
    
    use Expect;
    
    my $devName = '/dev/sdb3';
    my $combinationsFileName = 'combs.txt';
    open(my $fd, '<', $combinationsFileName);
    my $lineCount = 0;
    
    while (<$fd>) {
      my $pass = $_;
      chomp($_);
      say $_ . ' ' . ++$lineCount;
    
      my $exp = Expect->new('cryptsetup', ('open', $devName, 'crypt-vol')) or die 'err 1';
      my @out = $exp->expect(10, '-re', 'Enter passphrase') or die 'err 2';
      $exp->send($pass);
      @out = $exp->expect(10, '-re', 'No key available') or die 'err 3';
    
      #if cryptsetup returned an error code
      if ($out[1]) {
        die $out[1] . ' ' . $pass;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 2020-03-08
      • 1970-01-01
      相关资源
      最近更新 更多