/proc/$pid/maps
/proc/$pid/mem
프로세스에서와 동일한 방식으로 매핑 된 $ pid의 메모리 내용을 나타냅니다. 즉, 의사 파일의 오프셋 x 에있는 바이트 는 프로세스에있는 주소 x 에있는 바이트와 같습니다 . 프로세스에서 주소가 매핑 해제되면 파일의 해당 오프셋에서 읽은 경우 EIO
(입력 / 출력 오류)가 반환 됩니다. 예를 들어, 프로세스의 첫 번째 페이지는 매핑되지 않으므로 ( NULL
실제로 메모리에 액세스하는 대신 포인터 역 참조가 제대로 실패하지 않으므로 ) 첫 번째 바이트를 읽으면 /proc/$pid/mem
항상 I / O 오류가 발생합니다.
프로세스 메모리에서 매핑되는 부분을 찾는 방법은 읽는 것 /proc/$pid/maps
입니다. 이 파일에는 다음과 같이 매핑 된 영역 당 한 줄이 포함됩니다.
08048000-08054000 r-xp 00000000 08:01 828061 /bin/cat
08c9b000-08cbc000 rw-p 00000000 00:00 0 [heap]
처음 두 숫자는 영역의 경계입니다 (첫 번째 바이트와 마지막 바이트 이후의 16 진수). 다음 열에는 권한이 포함되어 있으며 파일 매핑 인 경우 파일에 대한 정보 (오프셋, 장치, inode 및 이름)가 있습니다. 자세한 내용은 proc(5)
매뉴얼 페이지 또는 Linux / proc / id / maps 이해 를 참조하십시오.
다음은 자체 메모리의 내용을 덤프하는 개념 증명 스크립트입니다.
#! /usr/bin/env python
import re
maps_file = open("/proc/self/maps", 'r')
mem_file = open("/proc/self/mem", 'r', 0)
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
print chunk, # dump contents to standard output
maps_file.close()
mem_file.close()
/proc/$pid/mem
mem
다른 프로세스 의 의사 파일 에서 읽으려고하면 작동하지 않습니다. ESRCH
(No such process) 오류가 발생합니다.
/proc/$pid/mem
( r--------
) 에 대한 권한 은 상황보다 더 자유 롭습니다. 예를 들어 setuid 프로세스의 메모리를 읽을 수 없어야합니다. 또한, 공정 악화가 독자에게 메모리의 일관성보기를 줄 수있는 수정, 동안 프로세스의 메모리를 읽으려고, (에 따라 리눅스 커널의 이전 버전을 추적 할 수있는 경쟁 조건이 있었다 이 LKML 스레드 I 생각은, 세부 사항을 모른다). 따라서 추가 점검이 필요합니다.
- 읽을
/proc/$pid/mem
프로세스 ptrace
는 PTRACE_ATTACH
플래그를 사용하여 프로세스에 첨부해야합니다 . 디버거가 프로세스 디버깅을 시작할 때 수행하는 작업입니다. 또한 strace
프로세스의 시스템 호출에도 영향을줍니다. 리더가에서 읽기를 마치면 플래그 /proc/$pid/mem
로 호출 ptrace
하여 분리해야합니다 PTRACE_DETACH
.
- 관찰 된 프로세스가 실행되고 있지 않아야합니다. 일반적으로 호출
ptrace(PTRACE_ATTACH, …)
하면 대상 프로세스가 중지 STOP
되지만 (신호를 전송 함) 경쟁 조건 (신호 전달이 비동기 임)이 있으므로 추적 프로그램이 호출해야합니다 wait
(에 설명 된대로 ptrace(2)
).
루트로 실행중인 프로세스는을 호출 할 필요없이 프로세스의 메모리를 읽을 수 ptrace
있지만 관찰 된 프로세스를 중지해야합니다. 그렇지 않으면 읽기는 여전히을 반환 ESRCH
합니다.
Linux 커널 소스에서 프로세스 별 항목을 제공하는 코드 /proc
는에 fs/proc/base.c
있으며 읽을 함수 /proc/$pid/mem
는 mem_read
입니다. 추가 확인은에 의해 수행됩니다 check_mem_permission
.
다음은 프로세스에 첨부하고 mem
파일 청크를 읽는 샘플 C 코드입니다 (오류 검사 생략).
sprintf(mem_file_name, "/proc/%d/mem", pid);
mem_fd = open(mem_file_name, O_RDONLY);
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid(pid, NULL, 0);
lseek(mem_fd, offset, SEEK_SET);
read(mem_fd, buf, _SC_PAGE_SIZE);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
이미 /proc/$pid/mem
다른 스레드 에 덤프하기위한 개념 증명 스크립트를 게시했습니다 .