이것은 gdb에서 프로세스 가상 메모리를 살펴본 결과입니다. 이에 대해 몇 가지 질문이 있습니다.
가상 메모리의 일부가 중복되는 이유는 무엇입니까? 예를 들어, 우리 프로그램(stack6)과 libc 라이브러리가 서로 다른 부분으로 분할되어 있다면 왜 그럴까요? 모두 함께 모아 보는 것은 어떨까요?
최상위 경로(/opt/pro...)는 가상 메모리의 명령 부분(텍스트 부분)이며 명령만 포함합니까?
4개의 libc 크기가 왜 다른가요? 오프셋의 용도는 무엇입니까? 크기와 시작 주소가 이미 있는 경우 오프셋의 용도는 무엇입니까?
데이터, bss, 커널 및 힙 부분은 어디에 있습니까? 위 이미지의 일부 부분에 대한 정보가 없는 이유는 무엇입니까? 실제로 모든 섹션을 표시하는 더 나은 옵션이 gdb에 있습니까?
프로세스의 가상 메모리 부분을 더 잘 표시할 수 있는 gdb보다 더 나은 프로그램이 있습니까? 저는 실제 가상 메모리와 어떤 디버거가 최상의 결과를 제공하는지 명확하게 확인하고 싶습니다.
제가 언급한 부분:
답변1
출력에서 gdb
페이지 권한이라는 중요한 정보가 누락되었습니다. (그들은 보여줍니다솔라리스와 FreeBSD에서, 그러나 Linux에서는 그렇지 않습니다. ) ;을 보면 이러한 내용을 볼 수 있습니다 /proc/<pid>/maps
. Protostar 예시의 지도 표시
$ cat /proc/.../maps
08048000-08049000 r-xp 00000000 00:0f 2925 /opt/protostar/bin/stack6
08049000-0804a000 rwxp 00000000 00:0f 2925 /opt/protostar/bin/stack6
b7e96000-b7e97000 rwxp 00000000 00:00 0
b7e97000-b7fd5000 r-xp 00000000 00:0f 759 /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:0f 759 /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r-xp 0013e000 00:0f 759 /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rwxp 00140000 00:0f 759 /lib/libc-2.11.2.so
b7fd9000-b7fdc000 rwxp 00000000 00:00 0
b7fe0000-b7fe2000 rwxp 00000000 00:00 0
b7fe2000-b7fe3000 r-xp 00000000 00:00 0 [vdso]
b7fe3000-b7ffe000 r-xp 00000000 00:0f 741 /lib/ld-2.11.2.so
b7ffe000-b7fff000 r-xp 0001a000 00:0f 741 /lib/ld-2.11.2.so
b7fff000-b8000000 rwxp 0001b000 00:0f 741 /lib/ld-2.11.2.so
bffeb000-c0000000 rwxp 00000000 00:0f 0 [stack]
(Protostar 예제는 쉽게 해킹할 수 있는 VM에서 실행되며, 아마도 연습을 쉽게 하기 위해 NX 보호 및 ASLR이 없습니다.)
중복된 매핑으로 보이는 것이 실제로는 gdb
다른 권한을 가진 다른 매핑에 해당한다는 것을 위에서 볼 수 있습니다. 텍스트 세그먼트는 읽기 전용 및 실행 가능으로 매핑되고, 데이터 세그먼트는 읽기 전용으로 매핑되며 BSS와 힙은 읽기-쓰기로 매핑됩니다. 이상적으로 데이터 세그먼트, BSS 및 힙은 실행 불가능하지만 이 예에서는 NX 지원이 부족하므로 실행 가능합니다. 각 공유 라이브러리에는 자체 텍스트 세그먼트, 데이터 세그먼트 및 BSS 매핑이 있습니다. 네 번째 맵은 일반적으로 버퍼 오버플로를 방지하는 데 사용되는 읽기 불가능, 쓰기 불가능, 실행 불가능 세그먼트입니다(여기에 사용된 커널 및 C 라이브러리의 수명에 따라 달라질 수 있음).
주어진 오프셋은 파일 내 데이터의 오프셋을 나타내며 주소 공간에서의 위치와 반드시 관련이 있는 것은 아닙니다. 로드할 때 정렬 제약 조건이 적용됩니다. 예를 들어 libc-2.11.2.so
프로그램 헤더는 두 개의 "LOAD" 헤더를 지정합니다.
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x13d2f4 0x13d2f4 R E 0x1000
LOAD 0x13e1cc 0x0013f1cc 0x0013f1cc 0x027b0 0x0577c RW 0x1000
( readelf -l
이것을 보려면 그것을 사용하십시오.)
세그먼트에 매핑된 부품의 보호 플래그가 서로 다른 경우 동일한 오프셋에서 서로 다른 가상 주소를 사용하여 여러 매핑이 발생할 수 있습니다. 다음 stack6
과 같은 경우:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x00604 0x00604 R E 0x1000
LOAD 0x000604 0x08049604 0x08049604 0x00114 0x00128 RW 0x1000
proc info mappings
(이는 for stack6
: 각 헤더 요청이 4KiB 정렬을 사용하여 4KiB보다 작으므로 서로 다른 주소에서 동일한 오프셋을 가진 두 개의 4KiB 맵을 가져오는 작은 크기를 설명합니다.)
빈 매핑은 익명 매핑에 해당합니다.man 5 proc
더 알아보기. 당신은 그들이 무엇에 해당하는지 mmap
에 대한 깊은 이해가 필요합니다 .gdb
vsyscall
커널 맵( 일부 아키텍처의 레거시 맵 제외)은 프로세스 관점에서 중요하지 않기 때문에(액세스할 수 없음) 표시되지 않습니다 .
더 좋은 옵션이 있는지 모르겠어서 gdb
항상 /proc/$$/maps
.
바라보다프로그램 실행 방법: ELF 바이너리커널이 읽는 ELF 형식과 메모리 할당에 매핑하는 방법에 대한 자세한 내용은 더 많은 참조 자료를 참조하세요.