UFO ET IT

루트가 아닌 권한으로 추적 된 명령을 실행하기 위해 dtrace를 얻으려면 어떻게해야합니까?

ufoet 2021. 1. 8. 20:57
반응형

루트가 아닌 권한으로 추적 된 명령을 실행하기 위해 dtrace를 얻으려면 어떻게해야합니까?


OS X에는 리눅스가 strace없지만 dtrace훨씬 더 좋을 것으로 보입니다.

그러나 개별 명령에 대한 간단한 추적을 수행하는 기능이 그립습니다. 예를 들어, Linux strace -f gcc hello.c에서는 모든 시스템 호출을 caputre로 작성할 수 있습니다. 그러면 컴파일러에서 내 프로그램을 컴파일하는 데 필요한 모든 파일 이름 목록이 제공 됩니다 (이 트릭을 기반으로 우수한 memoize 스크립트가 빌드 됨).

Mac에서 memoize를 이식하고 싶으므로 일종의 strace. 내가 실제로 필요한 것은 gcc읽고 쓰는 파일 목록 이므로 필요한 것은 truss. 확실히 내가 말할 dtruss -f gcc hello.c수 있고 어느 정도 동일한 기능을 얻을 수 있지만 컴파일러는 루트 권한으로 실행되므로 분명히 바람직하지 않습니다 (대량의 보안 위험을 제외하고 한 가지 문제는 a.out파일이 이제 루트가 소유 한다는 것 입니다 :-)

그런 다음 시도 dtruss -f sudo -u myusername gcc hello.c했지만 이것은 약간 잘못된 느낌이며 어쨌든 작동하지 않습니다 ( a.out이번에는 파일이 없지만 이유는 확실하지 않습니다)

이 모든 긴 이야기는 내 원래 질문에 동기를 부여하려고 시도합니다. Linux 에서처럼 일반 사용자 권한으로 명령을 실행하려면 어떻게해야 합니까?dtracestrace

편집 :이 작업을 수행하는 방법을 궁금해하는 유일한 사람이 아닌 것 같습니다. 질문 # 1204256 은 내 것과 거의 동일합니다 (동일한 차선의 sudo 답변 :-)


질문에 대한 답이 아니라 알아야 할 것. OpenSolaris는 "권한"으로이 문제를 (부분적으로) 해결했습니다 . 이 페이지를 참조 하십시오 . OpenSolaris에서도 추가 권한없이 사용자가 자신의 프로세스를 삭제하도록 허용하는 것은 불가능합니다. 그 이유는 dtrace가 작동하는 방식 때문입니다 . 커널 에서 프로브 활성화 합니다. 따라서 권한이없는 사용자가 커널을 조사하도록 허용한다는 것은 사용자가 키보드 드라이버에서 프로브를 활성화하여 다른 사용자의 암호를 스니핑하는 등 원하지 않는 많은 작업을 수행 할 수 있음을 의미합니다!


가장 쉬운 방법은 sudo를 사용하는 것입니다.

sudo dtruss -f sudo -u $USER whoami

다른 해결책은 먼저 디버거를 실행하고 새로운 특정 프로세스를 모니터링하는 것입니다.

sudo dtruss -fn whoami

그런 다음 다른 터미널에서 간단히 실행하십시오.

whoami

그렇게 간단합니다.

매뉴얼에서 더 까다로운 주장을 찾을 수 있습니다. man dtruss


또는 Mac에서 실행중인 사용자 프로세스에 dtruss를 연결할 수 있습니다.

sudo dtruss -fp PID

또는 strace를 사용하여 Linux / Unix에서 유사합니다.

sudo strace -fp PID

또 다른 해키 트릭은 명령을 실행하고 그 직후 프로세스에 연결하는 것입니다. 여기 예시들이 있습니다 :

sudo true; (./Pages &); sudo dtruss -fp `pgrep -n -x Pages`
sudo true; (sleep 1 &); sudo dtruss -fp `pgrep -n -x sleep`
sudo true; (tail -f /var/log/system.log &); sudo dtruss -fp `pgrep -n -x tail`

노트 :

  • 첫 번째 sudo는 처음 실행할 때 암호를 캐싱하기위한 것입니다.

  • 이 트릭은 ls, date디버거가 프로세스에 연결될 때까지 시간이 걸리기 때문에 빠른 명령 줄에서는 작동하지 않습니다 .

  • 두 곳에 명령을 입력해야합니다.

  • &이미 실행중인 경우 프로세스를 백그라운드로 실행하는 것을 무시할 수 있습니다 .

  • 디버깅을 마친 후, 당신은 (예를 들어, 수동으로 백그라운드 프로세스를 종료해야합니다 killall -v tail)


-n인수하기 dtruss기다렸다가의 인수와 일치하는 프로세스를 검사 dtruss의 원인이됩니다 -n. -f옵션은에 일치하는 프로세스에서 분기 된 프로세스를 따르기 위해 계속 작동합니다 -n.

이 모든 것은 whoami권한이없는 사용자로 실행중인 프로세스 (인수를 위해라고 가정 해 보겠습니다)를 dtruss 하려면 다음 단계를 따르십시오.

  1. 루트 셸 열기
  2. 운영 dtruss -fn whoami
    • 이것은 "whoami"라는 프로세스가 존재하기를 기다릴 것입니다.
  3. 권한이없는 셸 열기
  4. 운영 whoami
    • 이것은 정상적으로 실행되고 종료됩니다.
  5. dtruss 창에서 시스템 호출 추적 관찰
    • dtruss는 자체적으로 종료되지 않습니다. 일치하는 프로세스를 계속 기다릴 것입니다. 완료되면 종료하십시오.

이 답변은 @kenorb의 응답의 후반 부분을 복제하지만 일류 답변이 될 가치가 있습니다.


dtruss가 strace만큼 비 침습적 일 수 있는지 모르겠습니다.

"sudo [to root] dtruss sudo [back to nonroot] cmd"의 변형은 몇 가지 빠른 테스트에서 더 잘 작동하는 것 같습니다.

sudo dtruss -f su -l `whoami` cd `pwd` && cmd....

외부 sudo는 물론 dtruss가 루트로 실행됩니다.

내부 su가 나에게 돌아 왔고 -l을 사용하면 환경이 제대로 재생성됩니다.이 시점에서 시작된 위치로 다시 cd해야합니다.

I think "su -l user" is better than "sudo -u user" if you want the environment to be what that user normally gets. That'll be their login environment though; I don't know if there's a good way to let the environment inherit through the two user changes instead.

In your question, one additional complaint that you had about the "sudo dtruss sudo" workaround, other than ugliness, was that "I get no a.out file at all this time, not sure why". I don't know why either, but in my little test script, a "sudo dtruss sudo" variant also failed to write to a test output file, and the "sudo dtruss su" variant above did create the output file.


It seems that OS X does not support using dtrace to replicate all the features of strace that you need. However, I'd suggest trying to create a wrapper around suitable syscalls. It looks like DYLD_INSERT_LIBRARIES is the environment variable you want to hack a bit. That's basically the same as LD_PRELOAD for Linux.

A much easier way of doing library function overrides is using the DYLD_INSERT_LIBRARIES environment variable (analogous to LD_PRELOAD on Linux). The concept is simple: at load time the dynamic linker (dyld) will load any dynamic libraries specified in DYLD_INSERT_LIBRARIES before any libraries the executable wants loaded. By naming a function the same as one in a library function it will override any calls to the original.

The original function is also loaded, and can be retrieved using the dlsym(RTLD_NEXT, “function_name”); function. This allows a simple method of wrapping existing library functions.

According to the example by Tom Robinson you may need to set DYLD_FORCE_FLAT_NAMESPACE=1, too.

Copy of the original example (lib_overrides.c) that overrides only fopen:

#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>

// for caching the original fopen implementation
FILE * (*original_fopen) (const char *, const char *) = NULL;

// our fopen override implmentation
FILE * fopen(const char * filename, const char * mode)
{
    // if we haven’t already, retrieve the original fopen implementation
    if (!original_fopen)
        original_fopen = dlsym(RTLD_NEXT, "fopen");

    // do our own processing; in this case just print the parameters
    printf("== fopen: {%s,%s} ==\n", filename, mode);

    // call the original fopen with the same arugments
    FILE* f = original_fopen(filename, mode);

    // return the result
    return f;
}

Usage:

$ gcc -Wall -o lib_overrides.dylib -dynamiclib lib_overrides.c
$ DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=lib_overrides.dylib command-to-test

Disclaimer: this is derived from @kenorb's answer. It has some advantages though: PID is more specific than execname. And we can make a short-lived process wait for DTrace before it begins.

This is a bit race-conditiony, but…

Let's say we want to trace cat /etc/hosts:

sudo true && \
(sleep 1; cat /etc/hosts) &; \
sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $!; \
kill $!

We use sudo true to make sure that we clear sudo's password prompt before we start running anything time-sensitive.

We start a background process ("wait 1 sec, then do something interesting"). Meanwhile, we start DTrace. We've captured the background process's PID into $!, so we can pass that to DTrace as an arg.

The kill $! runs after we close DTrace. It's not necessary for our cat example (process closes on its own), but it helps us end long-running background processes like ping. Passing -p $! to DTrace is the preferred way to do this, but on macOS apparently requires a code-signed executable.


The other thing you can do is to run the command in a separate shell, and snoop that shell. See my answer.


I don't know of a way to run what you want as a normal user, as it seems that dtruss, which uses dtrace requires su privileges.

However, I believe the command you were looking for instead of

dtruss -f sudo -u myusername gcc hello.c

is

sudo dtruss -f gcc hello.c

After typing in your password, dtruss will run dtrace will sudo privileges, and you will get the trace as well as the a.out file.

Sorry I couldn't be of further help.

ReferenceURL : https://stackoverflow.com/questions/3007868/how-can-i-get-dtrace-to-run-the-traced-command-with-non-root-priviledges

반응형