다른 프로세스의 스택을 읽습니까?


16

자식 프로세스의 스택을 읽으려고하지만 운이 없습니다. 나는 그것을 사용하는 것이 가능하다는 것을 알고 ptrace있지만ptrace 의 인터페이스를 사용하면 한 번에 한 단어 만 읽을 수 있으며 스택의 더 큰 부분을 스캔하려고합니다.

또한 ptrace를 사용하여 파일에 첨부 한 후 파일 /proc/$pid/mem에서 추출한 스택의 경계에서 읽기를 시도했지만 /proc/$pid/maps( 여기 에서 제안한 것처럼) 시도 할 때 동일한 코드가 성공하더라도 읽기는 계속 실패합니다 (루트로 실행될 때도) 프로세스의 다른 부분 (예 : 힙)에서 읽습니다.

내가 도대체 ​​뭘 잘못하고있는 겁니까? 다른 옵션이 있습니까?


당신은 전화 했 waitpid사이 ptrace(PTRACE_ATTACH,…)read(그렇지 않으면 거기에 가능한 경쟁 조건)? 어떤 오류가 발생 read합니까? 아이가 메모리 매핑에 특이한 일을하고 sleep있습니까? 간단한 아이로 코드를 시험해 볼 수 있습니까?
Gilles 'SO- 악마 그만해'

ptrace 후 wait를 사용했으며 자식을 스캔하도록 강제로 대기시킵니다.
user4537

이것은 Linux에서만입니까? 솔라리스는 또한 / proc 파일 시스템을 가지고 있지만, 철학적으로는 리눅스와 완전히 다릅니다. "이진 파일"이 많습니다.
Bruce Ediger

그냥 시스템 ( "pstack pid ")을 수행하고 출력을 구문 분석하십시오.
vrdhn

답변:


5

ptrace의 인터페이스를 사용하면 한 번에 한 단어 만 읽을 수 있으며 스택의 더 큰 부분을 스캔하려고합니다.

그렇다면 루프를 사용하십시오. 나는 그것이 그것이 어떻게 문제를 구성하는지 알지 못한다.ptrace . 프로세스에 원격으로 액세스하는 데 항상 사용합니다.

나는 이와 같은 것을 사용한다 :

static int memcpy_from_target(pid_t pid, char *dest, long src, size_t n)
{
    static int const align = sizeof(long) - 1;

    while (n)
    {
        size_t todo = MIN(n, sizeof(long) - (src & align));
        long data = ptrace(PTRACE_PEEKTEXT, pid, src - (src & align), 0);
        if (errno)
        {
            perror("ptrace_peektext (memcpy_from_target)");
            return -1;
        }
        memcpy(dest, (char *)&data + (src & align), todo);

        dest += todo; src += todo; n -= todo;
    }

    return 0;
}

안녕 샘, 코드는 실제로 수행하지만 실제로는 현재 수행중인 작업이지만 성능 오버 헤드가 큽니다.
user4537

@ user4536 : 알겠습니다. 글을 쓸 시간이있을 때 게시 할 다른 전략을 염두에두고 있습니다. 일반적인 스택 크기는 얼마입니까?
sam hocevar

내 연구에서 특정 스택 크기를 가정하지 않기 때문에 실제로 말하기는 어렵지만이 논쟁을 위해 적어도 두 페이지 이상이라고 가정 해보십시오. 전략에 대한 힌트를 줄 수 있습니까? 어쨌든 도움을 주셔서 감사합니다!
user4537

1

다음은 조정이 필요하지만 대량의 데이터 청크에서 더 효율적이어야하는 또 다른 전략입니다. 아이디어는 스택 내용을 검색하기 위해 원격 프로세스에서 syscall을 실행하는 것입니다. 특정 아키텍처 코드가 필요하지만 x86 / x86_64만을 대상으로하는 경우 너무 번거롭지 않아야합니다.

  1. 다음과 같은 명명 된 파이프를 만듭니다. "/tmp/fifo"호출 프로세스 .
  2. 그것을 사용하여 시스템 콜에서 반환 될 때까지 추적 과정에 단계 PTRACE_SYSCALL, 단계로 waitpid()대기하고 PTRACE_GETREGS/PTRACE_PEEKTEXT 현재 실행 오피 코드를 확인 할 수 있습니다.
  3. 원격 프로세스의 레지스터와 스택의 작은 영역을 백업하십시오.
  4. 자신의 데이터와의 스택을 재정 의하여 원격 프로세스에서 시스템 콜을 실행 open("/tmp/fifo"), write()스택의 내용을,close() 설명 .
  5. 원격 프로세스 상태를 복원하십시오.
  6. 호출 프로세스에서 fifo 데이터를 읽습니다.

명명 된 파이프에 대한 더 우아한 대안이있을 수 있지만 지금은 생각할 수 없습니다. 내가 syscalls 만 사용하는 이유는 다양한 보안 보호로 인해 최신 시스템에서 원격 코드 삽입이 신뢰할 수 없기 때문입니다. 단점은 원격 프로세스가 syscall을 수행 할 때까지 중단된다는 것입니다 (이는 대부분 계산을 수행하는 일부 프로그램에서 문제가 될 수 있음).

이 소스 파일 에서 대부분의 작업을 구현하는 무료 코드를 볼 수 있습니다 . 코드에 대한 의견을 환영합니다!



1

proc 파일 시스템을 사용하여 다른 프로세스의 스택을 쉽게 읽을 수 있습니다 (이 작업에는 루트 액세스 권한이 필요합니다). / proc / pid / mem에서 임의로 읽으려면 / proc / pid / maps를 참조해야합니다. 이 파일의 간단한 읽기는 많은 항목을 보여줍니다. 스택으로 표시된 항목에 관심이 있습니다. 이것을 얻으면 스택의 하한과 상한을 읽어야합니다. 이제 / proc / pid / mem 파일을 열고 스택의 하한을 찾고 올바른 크기의 데이터를 읽으십시오.


1
확실 mems하지 maps않습니까? ( mems/proc파일 시스템 아래에 항목이 표시되지 않습니다 .) OP는 이미 스택 경계를 읽는 것을 언급했습니다 /proc/$pid/maps.
JigglyNaga

오타를 수정했습니다. 나는 대답에서 언급 한 것을 정확하게 수행했으며 132KB의 스택 데이터를 덤프했습니다. OP가 무엇을 잘못했는지에 대한 자세한 정보가 필요합니다. OP는 스택 경계를 읽는 데 사용한 코드를 공유 할 수 있습니다. 그가 답장을 보내지 않으면 나는 내 것을 공유 할 것이다.
Ajay Brahmakshatriya

0

lsstack 시도해 볼 수 있습니다. 다른 모든 성공적인 "다른 프로세스의 스택 읽기"프로그램과 마찬가지로 ptrace를 사용합니다. / proc / $ pid / mem reading을 사용하여 프로그램을 작동시킬 수 없습니다. 논리적으로는해야하지만 그렇게 할 수는 없다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.