이것리눅스 proc(5)
매뉴얼 페이지/proc/$pid/mem
"프로세스 메모리에 액세스하는 데 사용할 수 있는 페이지"를 알려줍니다 . 하지만 직접 사용하려고 하면 나에게
$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error
cat
왜 내 기억( )을 프린트 할 수 없나요 /proc/self/mem
? 쉘의 메모리를 인쇄하려고 할 때 발생하는 이상한 "해당 프로세스 없음" 오류는 무엇입니까( /proc/$$/mem
분명 프로세스가 존재하는 것 같습니다)? 그러면 어떻게 읽을 수 있나요 /proc/$pid/mem
?
답변1
/proc/$pid/maps
/proc/$pid/mem
Show $pid 메모리 내용은 프로세스와 동일한 방식으로 매핑됩니다. 즉, 오프셋의 바이트엑스의사 파일의 바이트는 주소의 바이트와 동일합니다.엑스진행 중입니다. 프로세스에서 주소가 매핑되지 않은 경우 파일의 해당 오프셋에서 읽으면 반환됩니다 EIO
(입력/출력 오류). 예를 들어, 첫 번째 바이트를 읽으면 프로세스의 첫 번째 페이지가 매핑되지 않으므로 항상 I/O 오류가 발생합니다 . 따라서 NULL
실수로 실제 메모리에 액세스하는 대신 포인터 역참조가 완전히 실패합니다./proc/$pid/mem
프로세스 메모리의 어느 부분이 매핑되어 있는지 알아내는 방법은 를 읽는 것입니다 /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", 'rb', 0)
output_file = open("self.dump", 'wb')
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
output_file.write(chunk) # dump contents to standard output
maps_file.close()
mem_file.close()
output_file.close()
/proc/$pid/mem
[다음 내용은 역사적으로 흥미롭습니다. 현재 커널에서는 작동하지 않습니다. ]
~부터커널 버전 3.3/proc/$pid/mem
, 매핑된 오프셋에만 액세스하고 권한 추적이 있는 한 정상적으로 액세스할 수 있습니다(ptrace
읽기 전용 액세스의 경우). 그러나 이전 커널에는 몇 가지 추가적인 문제가 있습니다.
다른 프로세스의 의사 파일을 읽으려고 하면 mem
작동하지 않습니다. ESRCH
(No such process) 오류가 발생합니다.
/proc/$pid/mem
( )에 대한 권한은 r--------
필요한 것보다 더 허용적입니다. 예를 들어 setuid 프로세스의 메모리를 읽을 수 없어야 합니다. 또한, 프로세스가 수정하는 동안 프로세스의 메모리를 읽으려고 하면 독자가 메모리에 대해 일관되지 않은 시각을 갖게 될 수 있으며, 더 나쁜 것은 Linux 커널의 이전 버전을 추적할 수 있는 경쟁 조건이 있다는 것입니다(에 따르면).이 lml 스레드, 세부 사항은 모르지만). 따라서 추가 확인이 필요합니다.
- 읽으려는 프로세스는 다음을
/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);
답변2
gdb의 이 명령은 메모리를 안정적으로 덤프합니다.
gcore pid
덤프 용량이 클 수 있으므로 -o outfile
현재 디렉터리에 공간이 충분하지 않은 경우 사용하세요.
답변3
실행하면 cat /proc/$$/mem
변수는 $$
자체 pid를 삽입하는 bash에 의해 평가됩니다. 그런 다음 cat
다른 PID를 사용하여 프로그램을 실행합니다 . 결국 cat
상위 프로세스의 메모리를 읽으려고 시도하게 됩니다 . bash
권한이 없는 프로세스는 자신의 메모리 공간만 읽을 수 있으므로 커널은 이를 거부합니다.
예는 다음과 같습니다.
$ echo $$
17823
계산 은 $$
17823입니다. 어떤 과정인지 살펴보겠습니다.
$ ps -ef | awk '{if ($2 == "17823") print}'
bahamat 17823 17822 0 13:51 pts/0 00:00:00 -bash
이것이 나의 현재 쉘입니다.
$ cat /proc/$$/mem
cat: /proc/17823/mem: No such process
여기서도 $$
내 쉘인 17823으로 평가됩니다. cat
내 쉘의 메모리 공간을 읽을 수 없습니다.
답변4
bash를 사용하여 읽기를 수행할 수도 있습니다.dd(1)
위에서 언급한 명령 중 일부가 없는 제한적이고 기본적인 Unix 시스템을 사용하는 경우( 이와 유사한 명령 python
까지 )memdump
를 사용할 수 dd(1)
있으며 대부분의 제한된 Unix 환경에서 작동합니다.
프로세스의 처음 몇 바이트를 덤프하는 예:
$ dd if=/proc/1337/mem of=/tmp/dump bs=1 skip=$((0x400000)) count=128
그런 다음 사용할 수 있습니다
hexdump -Cv ./tmp/dump