2016-09-26 13 views
1

예를 들어 버퍼가 스택의 반대 방향으로 커지는 대신 동일한 방향으로 커지게된다고 가정 해 봅시다. "Hello world"문자열이 포함 된 문자 버퍼가있는 경우 가장 낮은 주소에 'H'가 위치하는 대신 최상위 주소에 배치되는 등의 효과가 있습니다.프로세스의 가상 주소 공간 중 덮어 쓸 수있는 부분은 무엇입니까?

버퍼에 복사 된 입력 문자열이 오버플로되면 함수의 반환 주소를 덮어 쓸 수 없지만 확실히 덮어 쓸 수있는 다른 것이 있습니다. 내 질문은 - 입력 문자열이 충분히 길면 덮어 쓸 수있는 것은 무엇입니까? 덮어 쓸 수있는 힙과 스택 사이에 존재하는 라이브러리 함수가 있습니까? 힙 변수를 덮어 쓸 수 있습니까? 데이터 및 bss 섹션의 변수를 덮어 쓸 수 있지만 쓰기에서 보호 된 텍스트 세그먼트라고 가정합니다.

+3

당신은 내가 돈?에 대해 요구하는 특정 OS ' C 표준이 프로세스에서 메모리 레이아웃을 지정한다고 생각합니다. 시스템마다 다를 수 있습니다. – harmic

답변

1

메모리의 프로세스 레이아웃은 시스템마다 다릅니다. 이 대답은 x86_64 프로세서의 Linux에 적용됩니다.

Linux 프로세스의 메모리 레이아웃을 보여주는 좋은 기사가 있습니다. here.

버퍼가 로컬 변수 인 경우 다른 로컬 변수와 함께 스택에 저장됩니다.버퍼를 오버플로하면 가장 먼저 할 일은 동일한 함수의 다른 지역 변수입니다.

스택 끝에 도달하면 메모리의 다음 사용 세그먼트 전에 임의로 크기가 조정됩니다. 이 주소 공간에 쓰기를 계속하면 segfault가 트리거됩니다 (주소 공간은 실제 RAM에 매핑되지 않으므로).

크래시가 발생하지 않고 임의의 오프셋을 건너 뛰고 계속 덮어 쓰는 것으로 가정하면 다음으로 메모리 매핑 세그먼트가 발생합니다. 이 세그먼트에는 동적 공유 라이브러리를 주소 공간에 매핑하는 데 사용되는 파일 매핑과 익명 매핑이 포함 된 파일 매핑이 포함됩니다. 동적 라이브러리는 읽기 전용이 될 것입니다. 그러나 프로세스에 RW 매핑이 있다면 그 안에있는 데이터를 덮어 쓸 수 있습니다.

이 세그먼트 다음에 힙을 치기 전에 또 다른 임의의 오프셋이옵니다. 다시 한 번 임의의 오프셋의 주소 공간에 쓰려고하면 충돌이 발생합니다.

힙 아래에는 BSS, 데이터 및 마지막으로 텍스트 세그먼트가 뒤 따르는 임의의 오프셋이 있습니다. BSS 및 데이터 내의 정적 변수는 덮어 쓸 수 있습니다. 텍스트 세그먼트는 쓰기 가능하지 않아야합니다.

pmap 명령을 사용하여 프로세스의 메모리 맵을 검사 할 수 있습니다.

1

귀하의 질문에 대한 대답은 전적으로 어떤 운영 체제가 사용되고 있는지, 그리고 어떤 하드웨어 아키텍처에 따라 좌우됩니까? 운영 체제는 논리 메모리를 특정 방식으로 배치하고 아키텍처는 특정 목적을 위해 (매우 낮은) 메모리를 예약하는 경우가 있습니다.

기존 프로세스가 전체 논리 메모리 공간에 액세스 할 수 있지만이 용량은 거의 사용되지 않는다는 점을 이해해야합니다. 당신이 설명하는 것의 가장 큰 효과는 할당되지 않은 메모리에 접근하려고 시도 할 것이고 응답으로 segfault가 발생하여 프로그램이 충돌 할 것입니다.

그렇다면 이러한 다른 메모리 세그먼트는 확실히 수정할 수 있지만 읽기/쓰기 권한에 따라 달라집니다.

Low memory to high memory: 
.text - program code 
.data - initialized static variables 
.bss - uninitialized static variables 
.heap - grows up 
memory map segments - dynamic libraries 
.stack - grows down 

는 .text 세그먼트는 기본적으로 전용/실행 파일 읽기 표시되어 있으므로이는 .text 메모리 위치에 쓰기를 시도하면 당신은 얻을 것이다 : 예를 들어, 학교에서 배운 전형적인 메모리 레이아웃입니다 세그멘테이션 오류. .text를 쓰기 가능으로 변경할 수는 있지만 일반적으로 끔찍한 생각입니다.

.data, .bss, .heap 및 .stack 세그먼트는 모두 기본적으로 읽기/쓰기가 가능하므로 프로그램 오류없이 이러한 섹션을 덮어 쓸 수 있습니다.

메모리 맵 세그먼트에는 모두 처리 할 자체 권한이 있습니다. 이 세그먼트 중 일부는 쓰기 가능하고 대부분은 그렇지 않습니다 (따라서 쓰는 것이 segfault를 만듭니다).

마지막으로주의해야 할 점은 대부분의 최신 OS가 이러한 세그먼트의 위치를 ​​무작위로 지정하여 해커가 더 어려워 질 수 있다는 것입니다. 이로 인해 서로 다른 세그먼트 사이에 간격이 생길 수 있습니다 (액세스하려는 경우 세그 폴트가 다시 발생합니다).

Linux의 경우 명령 'pmap'을 사용하여 프로세스의 메모리 맵을 인쇄 할 수 있습니다. 0x851000에서 시작 세그먼트 실제로 PMAP 더 자세한보고 모드와 함께 당신을 말할 것이다 힙 (의 시작,하지만 더 자세한 모드

10636: vim hello.text 
0000000000400000 2112K r-x-- vim 
000000000080f000  4K r---- vim 
0000000000810000  88K rw--- vim 
0000000000826000  56K rw--- [ anon ] 
0000000000851000 2228K rw--- [ anon ] 
00007f7df24c6000 8212K r--s- passwd 
00007f7df2ccb000  32K r-x-- libnss_sss.so.2 
00007f7df2cd3000 2044K ----- libnss_sss.so.2 
00007f7df2ed2000  4K r---- libnss_sss.so.2 
00007f7df2ed3000  4K rw--- libnss_sss.so.2 
00007f7df2ed4000  48K r-x-- libnss_files-2.17.so 
00007f7df2ee0000 2044K ----- libnss_files-2.17.so 
00007f7df30df000  4K r---- libnss_files-2.17.so 
00007f7df30e0000  4K rw--- libnss_files-2.17.so 
00007f7df30e1000  24K rw--- [ anon ] 
00007f7df30e7000 103580K r---- locale-archive 
00007f7df960e000  8K r-x-- libfreebl3.so 
00007f7df9610000 2044K ----- libfreebl3.so 
00007f7df980f000  4K r---- libfreebl3.so 
00007f7df9810000  4K rw--- libfreebl3.so 
00007f7df9811000  8K r-x-- libutil-2.17.so 
00007f7df9813000 2044K ----- libutil-2.17.so 
00007f7df9a12000  4K r---- libutil-2.17.so 
00007f7df9a13000  4K rw--- libutil-2.17.so 
00007f7df9a14000  32K r-x-- libcrypt-2.17.so 
00007f7df9a1c000 2044K ----- libcrypt-2.17.so 
00007f7df9c1b000  4K r---- libcrypt-2.17.so 
00007f7df9c1c000  4K rw--- libcrypt-2.17.so 
00007f7df9c1d000 184K rw--- [ anon ] 
00007f7df9c4b000  88K r-x-- libnsl-2.17.so 
00007f7df9c61000 2044K ----- libnsl-2.17.so 
00007f7df9e60000  4K r---- libnsl-2.17.so 
00007f7df9e61000  4K rw--- libnsl-2.17.so 
00007f7df9e62000  8K rw--- [ anon ] 
00007f7df9e64000  88K r-x-- libresolv-2.17.so 
00007f7df9e7a000 2048K ----- libresolv-2.17.so 
00007f7dfa07a000  4K r---- libresolv-2.17.so 
00007f7dfa07b000  4K rw--- libresolv-2.17.so 
00007f7dfa07c000  8K rw--- [ anon ] 
00007f7dfa07e000 152K r-x-- libncurses.so.5.9 
00007f7dfa0a4000 2044K ----- libncurses.so.5.9 
00007f7dfa2a3000  4K r---- libncurses.so.5.9 
00007f7dfa2a4000  4K rw--- libncurses.so.5.9 
00007f7dfa2a5000  16K r-x-- libattr.so.1.1.0 
00007f7dfa2a9000 2044K ----- libattr.so.1.1.0 
00007f7dfa4a8000  4K r---- libattr.so.1.1.0 
00007f7dfa4a9000  4K rw--- libattr.so.1.1.0 
00007f7dfa4aa000 144K r-x-- liblzma.so.5.0.99 
00007f7dfa4ce000 2044K ----- liblzma.so.5.0.99 
00007f7dfa6cd000  4K r---- liblzma.so.5.0.99 
00007f7dfa6ce000  4K rw--- liblzma.so.5.0.99 
00007f7dfa6cf000 384K r-x-- libpcre.so.1.2.0 
00007f7dfa72f000 2044K ----- libpcre.so.1.2.0 
00007f7dfa92e000  4K r---- libpcre.so.1.2.0 
00007f7dfa92f000  4K rw--- libpcre.so.1.2.0 
00007f7dfa930000 1756K r-x-- libc-2.17.so 
00007f7dfaae7000 2048K ----- libc-2.17.so 
00007f7dface7000  16K r---- libc-2.17.so 
00007f7dfaceb000  8K rw--- libc-2.17.so 
00007f7dfaced000  20K rw--- [ anon ] 
00007f7dfacf2000  88K r-x-- libpthread-2.17.so 
00007f7dfad08000 2048K ----- libpthread-2.17.so 
00007f7dfaf08000  4K r---- libpthread-2.17.so 
00007f7dfaf09000  4K rw--- libpthread-2.17.so 
00007f7dfaf0a000  16K rw--- [ anon ] 
00007f7dfaf0e000 1548K r-x-- libperl.so 
00007f7dfb091000 2044K ----- libperl.so 
00007f7dfb290000  16K r---- libperl.so 
00007f7dfb294000  24K rw--- libperl.so 
00007f7dfb29a000  4K rw--- [ anon ] 
00007f7dfb29b000  12K r-x-- libdl-2.17.so 
00007f7dfb29e000 2044K ----- libdl-2.17.so 
00007f7dfb49d000  4K r---- libdl-2.17.so 
00007f7dfb49e000  4K rw--- libdl-2.17.so 
00007f7dfb49f000  20K r-x-- libgpm.so.2.1.0 
00007f7dfb4a4000 2048K ----- libgpm.so.2.1.0 
00007f7dfb6a4000  4K r---- libgpm.so.2.1.0 
00007f7dfb6a5000  4K rw--- libgpm.so.2.1.0 
00007f7dfb6a6000  28K r-x-- libacl.so.1.1.0 
00007f7dfb6ad000 2048K ----- libacl.so.1.1.0 
00007f7dfb8ad000  4K r---- libacl.so.1.1.0 
00007f7dfb8ae000  4K rw--- libacl.so.1.1.0 
00007f7dfb8af000 148K r-x-- libtinfo.so.5.9 
00007f7dfb8d4000 2048K ----- libtinfo.so.5.9 
00007f7dfbad4000  16K r---- libtinfo.so.5.9 
00007f7dfbad8000  4K rw--- libtinfo.so.5.9 
00007f7dfbad9000 132K r-x-- libselinux.so.1 
00007f7dfbafa000 2048K ----- libselinux.so.1 
00007f7dfbcfa000  4K r---- libselinux.so.1 
00007f7dfbcfb000  4K rw--- libselinux.so.1 
00007f7dfbcfc000  8K rw--- [ anon ] 
00007f7dfbcfe000 1028K r-x-- libm-2.17.so 
00007f7dfbdff000 2044K ----- libm-2.17.so 
00007f7dfbffe000  4K r---- libm-2.17.so 
00007f7dfbfff000  4K rw--- libm-2.17.so 
00007f7dfc000000 132K r-x-- ld-2.17.so 
00007f7dfc1f8000  40K rw--- [ anon ] 
00007f7dfc220000  4K rw--- [ anon ] 
00007f7dfc221000  4K r---- ld-2.17.so 
00007f7dfc222000  4K rw--- ld-2.17.so 
00007f7dfc223000  4K rw--- [ anon ] 
00007ffcb46e7000 132K rw--- [ stack ] 
00007ffcb475f000  8K r-x-- [ anon ] 
ffffffffff600000  4K r-x-- [ anon ] 
total   163772K 

입니다

: 다음은 정력의 인스턴스에이 프로그램의 출력 맞지 않았다).

+0

응답 해 주셔서 감사합니다! – Connor

0

당신의 질문은 운영 체제에서 어떻게 작동하는지에 대한 근본적인 오해를 반영한다고 생각합니다. "버퍼"및 "스택"과 같은 것들은 운영 체제에 의해 정의되지 않는 경향이 있습니다.

운영 체제는 메모리를 커널 및 사용자 영역으로 나눕니다 (일부 시스템에는 추가 보호 영역이 있음).

사용자 영역의 레이아웃은 일반적으로 링커에 의해 정의됩니다. 링커는 로더에게 주소 공간을 설정하는 방법을 지시하는 실행 파일을 만듭니다. 다양한 링커는 서로 다른 제어 수준을가집니다. 일반적으로, 기본 링커 설정 그룹은 같은 같은 프로그램의 섹션 :

이 - 읽기/

가 - 읽기/더

- 읽기/쓰기를 실행 실행되지/

- 읽기/쓰기를 초기화/수요 0

일부 링커 중 하나는 이러한 특성을 가진 여러 프로그램 섹션을 만들 수 있습니다.

당신은 질문 : 가장 낮은 주소에 배치되는 대신에 'H'의 세상 안녕하세요 ","나는 문자열이 포함 된 문자 버퍼가있는 경우 "

, 그것은 등등 최상위 주소에 배치하고있다. "

van neumann 시스템에서 메모리는 메모리 사용과 독립적입니다. 동일한 메모리 블록은 동시에 문자열, 부동 소수점, 정수 또는 명령어로 해석 될 수 있습니다. 원하는 순서대로 편지를 쓸 수 있지만 대부분의 소프트웨어 라이브러리에서는 역순으로 인식하지 못합니다. 자신의 라이브러리가 거꾸로 저장된 문자열을 처리 할 수 ​​있다면 자신을 노크하십시오.

"내 질문은 - 입력 문자열이 길면 무엇을 덮어 쓸 수 있습니까?"

아무 것도 될 수 있습니다.

"힙과 스택 사이에 겹쳐 쓸 수있는 라이브러리 함수가 있습니까?"

이는 링커가 수행 한 작업에 따라 다릅니다.

"힙 변수를 덮어 쓸 수 있습니까?"

힙을 덮어 쓸 수 있습니다.

는 "나는 데이터와 BSS 섹션의 변수를 덮어하지만, 쓰기으로부터 보호 텍스트 세그먼트 할 수 있다고 가정? 일반적으로

, 예.