다른 프로세스의 스택을 읽으시나요?

다른 프로세스의 스택을 읽으시나요?

성공하지 못한 채 하위 프로세스의 스택을 읽으려고 합니다. 작동한다는 것을 알고 있지만 ptrace인터페이스 ptrace를 사용하면 한 번에 한 단어만 읽을 수 있는 반면, 저는 스택의 더 큰 부분을 스캔하려고 합니다.

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

내가 뭘 잘못했나요? 다른 옵션이 있나요?

답변1

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;
}

답변2

이는 조정이 필요할 수 있는 또 다른 전략이지만 대량의 데이터에 더 효과적입니다. 아이디어는 스택 내용을 검색하기 위해 원격 프로세스에서 시스템 호출을 수행하는 것입니다. 아키텍처별 코드가 필요하지만 x86/x86_64만 대상으로 하는 경우에는 큰 문제가 발생하지 않습니다.

  1. "/tmp/fifo"예를 들어 호출 프로세스에서 명명된 파이프를 만듭니다 .
  2. PTRACE_SYSCALL단계, waitpid()대기 및 PTRACE_GETREGS/ PTRACE_PEEKTEXT또는 현재 실행 중인 opcode를 확인 하여 시스템 호출에서 반환될 때까지 추적된 프로세스로 들어갑니다 .
  3. 원격 프로세스의 레지스터와 해당 스택의 작은 영역을 백업합니다.
  4. open("/tmp/fifo")자신의 데이터( , write()스택 내용, close()설명자) 로 스택을 덮어써서 원격 프로세스에서 시스템 호출을 실행합니다 .
  5. 원격 프로세스의 상태를 복원합니다.
  6. 호출 프로세스에서 FIFO 데이터를 읽습니다.

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

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

답변3

또 다른 제안.

메인 Linux 커널 트리에 승인되면 Christopher Yeoh의크로스 메모리 연결수리하다. 문서 보기process_vm_readv예를 들어.

답변4

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

관련 정보