명령 자체를 참조하면 별칭을 우회할 수 있다는 것을 알고 있습니다.
그러나 내장 기능이 동일한 이름을 가진 함수에 의해 "숨겨진" 경우 기본 내장 기능은 내장 기능을 사용하는 경우를 제외하고는 실행될 수 없는 것 같습니다. 당신이 그것을 할 수 있다면.
bash 매뉴얼 페이지를 인용하면 다음과 같습니다 LESS='+/^COMMAND EXECUTION' man bash
.
COMMAND EXECUTION
After a command has been split into words, if it results in a simple
command and an optional list of arguments, the following actions are
taken.
If the command name contains no slashes, the shell attempts to locate
it. If there exists a shell function by that name, that function is
invoked as described above in FUNCTIONS. If the name does not match a
function, the shell searches for it in the list of shell builtins. If
a match is found, that builtin is invoked.
그렇다면 새로운 쉘을 시작하지 않고도 다음과 같은 상황에서 복구가 가능할까요?
unset() { printf 'Haha, nice try!\n%s\n' "$*";}
builtin() { printf 'Haha, nice try!\n%s\n' "$*";}
command() { printf 'Haha, nice try!\n%s\n' "$*";}
나는 그것을 추가하지도 않았다 readonly -f unset builtin command
. 그 경우예위의 항목에서 복구가 가능합니까? 추가 질문으로 이것을 고려하십시오. 세 가지 기능이 모두 읽기 전용으로 표시되어 있으면 여전히 복구할 수 있습니까?
Bash에서 이 질문을 했지만 다른 쉘에도 적용할 수 있는지에도 관심이 있습니다.
답변1
세 가지 기능이 모두 읽기 전용으로 표시된 경우에도 복구할 수 있나요?
예, 일반적으로 가능합니다. 하지만 그렇다고 해서 그래야 한다는 의미는 아닙니다.
최고의 노력을읽기 전용 변수 설정 해제unbind_variable
아래와 같이 디버거를 연결하고 호출하여이 질문에 대한 anishsane의 답변, 읽기 전용 함수를 설정 해제하고 해당 이름을 전달하여 unbind_func
디버거를 사용할 수도 있습니다.
이는 읽기 전용이 아닌 경우(실제로 읽기 전용인 경우) 합리적인 접근 방식이 아닙니다.이 경우에는 다음을 사용해야 합니다.cuonglm의 솔루션unset
, 이는 POSIX 모델의 처리를 활용합니다 . 그 해결책실제 생활에서 실제로 사용할 수 있는 것입니다.
readonly
디버거를 사용하여 셸을 우회한 후에는 셸이 올바르게 실행된다는 실제 보장이 없으므로 exec
더 합리적인 대안이 있을 때마다(예: 셸을 종료하고 다시 시작하거나 셸을 새 것으로 교체하는 등) 사용하지 않는 것이 좋습니다.
그러고보니 이건아니쉬 사니(Anish Sani) 방법변수 대신 설정 해제 함수에 적응:
cat <<EOF | sudo gdb
attach $$
call unbind_func("unset")
call unbind_func("builtin")
call unbind_func("command")
detach
EOF
알아채다$$
연장되다EOF
in의 어떤 부분도 인용되지 않았기 때문에 입력되는 쉘의 프로세스 ID입니다 <<EOF
.
Ubuntu 16.04 LTS의 Bash 4.3.48(1) 릴리스에서 이것을 테스트했는데 작동합니다. gdb
다른 디버거에 적용할 수 있지만 이것이 필요합니다 . ~처럼아니쉬 사니 댓글에서 파이프의 목적은 cat
입력을 제공하는 프로세스가 중지 gdb
된 교착 상태를 방지하는 것입니다 gdb
. 나는 두 개 이상의 명령으로 구성된 파이프라인에서 Bash가 각 명령을 하위 쉘에서 실행하기 때문에 이 목표를 달성한다고 믿습니다. 그러나 이것이 가장 신뢰할 수 있는 방법인지는 확실하지 않습니다. 그러나 궁극적으로 Bash는 읽기 전용 변수와 함수가 변경되지 않는다는 완벽하게 합리적인 가정을 하기 때문에 이 접근 방식이 작동할 것이라는 실제 보장은 없습니다. 실제로 내 생각에는 이것이 실제로 항상 작동하는 것 같습니다.
이 기술을 작성된 대로 사용하려면 sudo
해당 기술을 설치하고 루팅할 수 있어야 합니다 sudo
. 물론 이를 다른 권한 상승 방법으로 대체할 수 있습니다. 실행 중인 운영 체제와 구성 방법에 따라 sudo
완전히 생략하고 gdb
루트가 아닌 사용자 자신으로 실행할 수도 있습니다. 예를 들어, Linux 커널은 /proc/sys/kernel/yama/ptrace_scope
다음 값을 참조합니다.sysctl을 통해 설정 가능다른 프로세스를 디버깅할 수 있는 프로세스를 결정하기 위해 읽거나 (루트로) 쓸 수 있습니다. 값이 이면 1
프로세스의 직계 부모(또는 루트로 실행되는 모든 프로세스)만 디버깅할 수 있습니다. 대부분의 최신 GNU/Linux 시스템에서는 으로 설정되어 있으므로 1
이를 포함시켰습니다 sudo
.
Linux 커널 동작에 대한 이러한 설명은 다른 값이 허용되고 ptrace_scope
원하는 관계가 조정될 수 있으므로 다소 지나치게 단순화되었습니다. 1
바라보다관련된 문서자세한 내용을 확인하세요.
답변2
posix 모드에 있을 때 bash
일부 내장 함수는 POSIX 표준을 준수하는 특수한 것으로 간주됩니다.
이러한 특수 내장 함수의 한 가지 특이한 점은 명령 조회 프로세스에서 해당 함수가 함수보다 먼저 발견된다는 것입니다. 이를 활용하려면 다음을 시도해 보세요.
$ unset builtin
Haha, nice try!
builtin
$ set -o posix
$ unset builtin
$ builtin command -v echo
echo
set
그러나 다음과 같은 함수로 재정의되면 작동하지 않습니다 set
.
$ set() { printf 'Haha, nice try!\n%s\n' "$*";}
$ set -o posix
Haha, nice try!
이 경우 posix 모드로 들어가 POSIXLY_CORRECT
도록 설정 bash
하면 모든 특수 내장 명령이 제공됩니다.
$ POSIXLY_CORRECT=1