그래서 키보드 LED(numlock 및 capslock)를 사용하여 데이터를 전송할 수 있는 간단한 Bash 스크립트를 만들었습니다(LTT의 "Do Not Plug This 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가 더 오랫동안 꺼져 있음을 의미함). 그러나 결함이 있습니다. stdin에서 EOF가 나올 때까지 기다리게 되는데, 이는 내가 원하는 것이 아닙니다. 나는 그것이 stdin에 기록될 때 데이터를 읽는 미니 모뎀처럼 작동하기를 원합니다(글쎄, 적어도 개행 문자 이후). 다음 없이 이 작업을 수행할 수 있는 방법이 있습니까?
- 프로그래밍 언어를 변경하고
- 전체 스크립트를 깨지 않고?
미리 감사드립니다.
답변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()
stty
그러나 bash(및 cat & perl & sed)에서 이 작업을 수행하려면 다음을 기반으로 뭔가를 시도해 볼 수 있습니다.
cat
첫째, stdin에서 이미 읽을 수 있는 프로그램(예: Perl 및 sed 및 기타 거의 모든 작업이 수행할 수 있음)에 데이터를 파이프 할 필요가 없다는 점을 인식하십시오 .그런 다음 Perl의 출력을 sed로 파이프할 때마다 아마도 뭔가 잘못된 일을 하고 있을 가능성이 높으며 sed에서 수행한 모든 작업을 Perl 스크립트에서 수행할 수 있다는 것을 깨달았습니다. Perl에는 sed와 마찬가지로 as/// 연산자도 있습니다.
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