因此,我制作了一个简单的 Bash 脚本,可以使用键盘 LED(numlock 和 capslock)来传输数据(受到 LTT 的“请勿插入此 USB In! – Hak5 Rubber Ducky”视频的启发)。这是我的脚本:
#!/bin/bash
for i in `cat /dev/stdin | perl -lpe '$_=unpack"B*"' | sed 's/./\ &/g'`
do export E=`expr $E + 1`
echo "Bit number $E has a value of $i"
if (( $i == 0 ))
then
xdotool key Caps_Lock
sleep 0.1
xdotool key Caps_Lock
else
xdotool key Num_Lock
sleep 0.1
xdotool key Num_Lock
fi
done
它做了一些不同的事情,那就是键盘的 LED 为公共低电平而不是公共高电平(这意味着与 Linus 的视频相比,LED 关闭的时间更长)。然而,它有一个缺陷。它会等到来自标准输入的 EOF,这不是我想要的。我希望它像迷你调制解调器一样,在将数据写入标准输入时读取数据(嗯,至少在换行符之后)。有没有一种方法可以做到这一点而无需:
- 改变编程语言,以及
- 而不破坏整个脚本?
先感谢您。
答案1
有很多方法可以做到这一点。由于您已经在使用 perl 完成部分工作,因此最简单的方法可能是在 perl 中完成整个工作,使用术语::读取密钥模块。例如:
#!/usr/bin/perl -l
use Term::ReadKey;
# trap INT so we can reset the terminal on ^C
$SIG{INT} = sub { exit };
ReadMode 3;
while ($_ = ReadKey 0) {
last if m/\cD/;
@bits = split //, unpack "B*";
for my $i (0..$#bits) {
print "Bit number $i has a value of $bits[$i]";
if ($bits[$i] == 0) {
system("xdotool key Caps_Lock; sleep 0.1; xdotool key Caps_Lock");
} else {
system("xdotool key Num_Lock; sleep 0.1; xdotool key Num_Lock");
};
};
};
END {
ReadMode 0;
};
或者,如果您不想从 CPAN 安装模块,则可以使用stty
中所述的perldoc -f getc
方法getc
一次读取一个字符。或者使用setattr()
POSIX 模块(包含在 perl 中)中的函数而不是运行stty
.
但是,由于您想在 bash (以及 cat & perl & sed)中执行此操作,因此您可以尝试基于此的操作:
首先,认识到您永远不需要使用
cat
管道将数据传输到已经可以从 stdin 读取的程序中(就像 perl 和 sed 以及几乎所有其他东西都可以做的那样)。然后意识到,每当您将 perl 的输出传输到 sed 时,您可能做错了,并且可以在 perl 脚本中执行您在 sed 中执行的任何操作。 Perl 也有 as/// 运算符,就像 sed 一样。
mapfile
请记住,bash 有数组,您可以使用 bash内置函数将程序的输出读取到数组中,流程替代。
和
- bash 可以使用 一次读取一个字符
read -n 1
。
#!/bin/bash
while read -n 1 char ; do
case "$char" in
$'\004') break ;; # Ctrl-D
esac
# This uses perl to print each bit separated by a newline. we could do it with s/// in perl,
# but here i'm using split and join. the output from perl is read into bash array $bits.
mapfile -t bits < <(printf '%s' "$char" | perl -lne 'print join("\n", split //, unpack"B*")')
# that expr stuff is incredibly ugly. and decades obsolete for shell arithmetic.
# i'm going to use let instead because I also find (( i=i+1 )) to be incredibly ugly.
count=0
for i in "${bits[@]}" ; do
let count+=1
echo "Bit number $count has a value of $i"
if [ "$i" -eq 0 ] ; then
xdotool key Caps_Lock
sleep 0.1
xdotool key Caps_Lock
else
xdotool key Num_Lock
sleep 0.1
xdotool key Num_Lock
fi
done
done