기본 콘텐츠로 건너뛰기

Heap-Syscall

Heap-Syscall

힙 메모리 할당과 시스템 호출

malloc은 OS에서 메모리를 얻기 위해 brk 또는 mmap syscall을 사용하여 메모리를 확보한다.

brk

brk: brk는 프로그램 중단 위치를 증가시켜 커널에서 메모리를 얻는다. 처음 시작(start_brk) 및 힙 세그먼트 끝(brk)은 동일한 위치를 가리킨다.

  • ASLR이 꺼지면 start_brkbrk는 data/bss 세그먼트 (end_data)`끝을 가리킨다.
  • ASLR이 켜지면 start_brkbrk는 data/bss 세그먼트 (end_data)끝에 임의의 brk 오프셋을 더한 것과 같다.
    enter image description here

위의 프로세스 가상 메모리 레이아웃 그림은 start_brk가 힙 세그먼트의 시작이고 brk(프로그램 중단)이 힙 세그먼트의 끝임을 보여준다.

예시

/* sbrk and brk example */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
   void *curr_brk, *tmp_brk = NULL;
   printf("Welcome to sbrk example:%d\n", getpid());

   /* sbrk(0) gives current program break location */

  tmp_brk = curr_brk = sbrk(0);
  printf("Program Break Location1:%p\n", curr_brk);
  getchar();
   	 
   /* brk(addr) increments/decrements program break location */

   brk(curr_brk+4096);

   curr_brk = sbrk(0);
   printf("Program Break Location2:%p\n", curr_brk);
   getchar();
    
   brk(tmp_brk);
   	 
   curr_brk = sbrk(0);
   printf("Program Break Location3:%p\n", curr_brk);
   getchar();
   	 
   return 0;
}

이제 컴파일 후 프로그램을 실행하여 살펴보자.

# gcc -o brk ./brk.c 
# ./brk
Welcome to sbrk example:19109
Program Break Location1:0x804a000

터미널 창을 하나 더 실행하여 프로세스 메모리 공간을 살펴보자.

# cat /proc/19109/maps
08048000-08049000 r-xp 00000000 08:01 1032560    /home/iamroot/workspace/heap/brk
08049000-0804a000 rw-p 00000000 08:01 1032560    /home/iamroot/workspace/heap/brk
b7e98000-b7e99000 rw-p b7e98000 00:00 0 
b7e99000-b7fd4000 r-xp 00000000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd4000-b7fd5000 r--p 0013b000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd5000-b7fd7000 rw-p 0013c000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd7000-b7fda000 rw-p b7fd7000 00:00 0 
b7fe3000-b7fe7000 rw-p b7fe3000 00:00 0 
b7fe7000-b8000000 r-xp 00000000 08:01 851989     /lib/ld-2.5.so
b8000000-b8002000 rw-p 00019000 08:01 851989     /lib/ld-2.5.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
  • Program break 증가 전: start_brk = brk = end_data = 0x804a000
[Enter 입력]
Program Break Location2:0x804b000
 # cat /proc/19109/maps
 08048000-08049000 r-xp 00000000 08:01 1032560    /home/iamroot/workspace/heap/brk
 08049000-0804a000 rw-p 00000000 08:01 1032560    /home/iamroot/workspace/heap/brk
 0804a000-0804b000 rw-p 00000000 00:00 0          [heap]
 b7e98000-b7e99000 rw-p b7e98000 00:00 0
 b7e99000-b7fd4000 r-xp 00000000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
 b7fd4000-b7fd5000 r--p 0013b000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
 b7fd5000-b7fd7000 rw-p 0013c000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
 b7fd7000-b7fda000 rw-p b7fd7000 00:00 0
 b7fe3000-b7fe7000 rw-p b7fe3000 00:00 0
 b7fe7000-b8000000 r-xp 00000000 08:01 851989     /lib/ld-2.5.so
 b8000000-b8002000 rw-p 00019000 08:01 851989     /lib/ld-2.5.so
 bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
 ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
  • Program break 증가 후: start_brk = end_data = 0x804a000, brk = 0x804b000
    • 0804a000-0804b000은 세그먼트의 가상 주소 범위이다.
    • rw-p는 Flags (읽기, 쓰기, 비실행, 비공개)이다.
    • 00000000 은 파일 오프셋이다.
    • 00:00 은 Major / Minor device number 이다.
    • 0 은 아이 노드 번호이다.

mmap

mmap: mallocmmap을 사용하여 private anonymous mapping 세그먼트를 생성한다. 주된 목적은 새 메모리(0으로 채워짐)를 할당하는 것으로, 이 새 메모리는 프로세스를 호출하여 독점적으로 사용된다.

/* Private anonymous mapping example using mmap syscall */
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

void static inline errExit(const char* msg)
{
    printf("%s failed. Exiting the process\n", msg);
    exit(-1);
}

int main()
{
    int ret = -1;
    printf("Welcome to private anonymous mapping example::PID:%d\n", getpid());
    printf("Before mmap\n");
    getchar();
    char* addr = NULL;
    addr = mmap(NULL, (size_t)132*1024, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (addr == MAP_FAILED)
             errExit("mmap");
    printf("After mmap\n");
    getchar();

   /* Unmap mapped region. */
   ret = munmap(addr, (size_t)132*1024);
   if(ret == -1)
            errExit("munmap");
   printf("After munmap\n");
   getchar();
   return 0;
}
# ./mmap 
Welcome to private anonymous mapping example::PID:20139
Before mmap
  • mmap 이전: 공유 라이브러리 libc.sold-linux.so에 속한 메모리 매핑 세그먼트만 볼 수 있다.
# cat /proc/20139/maps
08048000-08049000 r-xp 00000000 08:01 1032542    /home/iamroot/workspace/heap/mmap
08049000-0804a000 rw-p 00000000 08:01 1032542    /home/iamroot/workspace/heap/mmap
b7e98000-b7e99000 rw-p b7e98000 00:00 0
b7e99000-b7fd4000 r-xp 00000000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd4000-b7fd5000 r--p 0013b000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd5000-b7fd7000 rw-p 0013c000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd7000-b7fda000 rw-p b7fd7000 00:00 0
b7fe3000-b7fe7000 rw-p b7fe3000 00:00 0
b7fe7000-b8000000 r-xp 00000000 08:01 851989     /lib/ld-2.5.so
b8000000-b8002000 rw-p 00019000 08:01 851989     /lib/ld-2.5.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
[Enter 입력]
After mmap
  • mmap 이후: 매핑 세그먼트가 (b7e77000 ~ b7e98000)이 이미 존재하던 매핑 세그먼트(b7e98000 ~ b7e99000)와 결합된 것을 볼 수 있다.
# cat /proc/20139/maps
08048000-08049000 r-xp 00000000 08:01 1032542    /home/iamroot/workspace/heap/mmap
08049000-0804a000 rw-p 00000000 08:01 1032542    /home/iamroot/workspace/heap/mmap
b7e77000-b7e99000 rw-p 00000000 00:00 0
b7e99000-b7fd4000 r-xp 00000000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd4000-b7fd5000 r--p 0013b000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd5000-b7fd7000 rw-p 0013c000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd7000-b7fda000 rw-p b7fd7000 00:00 0
b7fe3000-b7fe7000 rw-p b7fe3000 00:00 0
b7fe7000-b8000000 r-xp 00000000 08:01 851989     /lib/ld-2.5.so
b8000000-b8002000 rw-p 00019000 08:01 851989     /lib/ld-2.5.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
  • b7e77000-b7e99000은 세그먼트의 가상 주소 범위이다.
  • rw-p는 Flags (읽기, 쓰기, 비실행, 비공개)이다.
  • 00000000 은 파일 오프셋이다.
  • 00:00 은 Major / Minor device number 이다.
  • 0 은 아이 노드 번호이다.
[Enter 입력]
After munmap
  • munmap 이후: 매핑되었던 메모리가 해제되었음을 볼 수 있다.
# cat /proc/20139/maps
08048000-08049000 r-xp 00000000 08:01 1032542    /home/iamroot/workspace/heap/mmap
08049000-0804a000 rw-p 00000000 08:01 1032542    /home/iamroot/workspace/heap/mmap
b7e98000-b7e99000 rw-p b7e98000 00:00 0
b7e99000-b7fd4000 r-xp 00000000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd4000-b7fd5000 r--p 0013b000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd5000-b7fd7000 rw-p 0013c000 08:01 886016     /lib/tls/i686/cmov/libc-2.5.so
b7fd7000-b7fda000 rw-p b7fd7000 00:00 0
b7fe3000-b7fe7000 rw-p b7fe3000 00:00 0
b7fe7000-b8000000 r-xp 00000000 08:01 851989     /lib/ld-2.5.so
b8000000-b8002000 rw-p 00019000 08:01 851989     /lib/ld-2.5.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]

이 블로그의 인기 게시물

데일 카네기 인간관계론 정리

Remove-Server-Header

응답 메시지 내 서버 버전 정보 제거 1. Apache 1) 조치 방법 “/etc/htpd/conf/httpd.conf” 파일 안에서 1. ServerTokens OS → ServerTokens Prod 2. ServerSignature On → ServerSignature Off 로 변경한 후 아파치를 재시작하면 헤더 값의 아파치 버전 정보 및 OS 정보를 제거할 수 있다. 2) 참고 URL http://zetawiki.com/wiki/CentOS_ 아파치_보안권장설정_ServerTokens_Prod,_ServerSignature_Off 2. IIS 1) 조치 방법 IIS 6.0 urlscan_setup 실행. 설치. \windows\system32\inetsrv\urlscan\urlscan.ini 파일을 열어 다음 수정(RemoveServerHeader=0 을 RemoveServerHeader=1 로 변경) 서비스에서 IIS Admin Service 재시작. IIS 7.0 IIS 관리자를 열고 관리하려는 수준으로 이동합니다. 기능 보기에서 HTTP 응답 헤더를 두 번 클릭합니다. HTTP 응답 헤더 페이지에서 제거할 헤더를 선택합니다. 작업 창에서 제거를 클릭하고 예를 클릭합니다. 2) 참고 URL IIS 6.0 : http://gonnie.tistory.com/entry/iis6- 응답헤더-감추기 IIS 7.0 : https://technet.microsoft.com/ko-kr/library/cc733102(v=ws.10).aspx 3. jetty 1) 조치 방법 “jetty.xml” 파일에서 jetty.send.server.version=false 설정 2) 참고 URL http://attenuated-perspicacity.blogspot.kr/2009/09/jetty-61x-hardening.html 4. Nginx ...

CVE-2017-11352

CVE-2017-11352 ImageMagick 에서 발생했던 CVE-2017-9144 취약점의 미흡한 조치로 인하여 동일한 취약점이 다시 발생되었다. 재 발생된 취약점 CVE-2017-11352은 coders/rle.c 에서 RLE 이미지에 대한 부적절한 EOF 처리가 원인이었다. EOF 란? 파일의 끝(End of File, EOF)으로 데이터 소스로부터 더 이상 읽을 수 있는 데이터가 없음을 나타낸다. ImageMagick Github Page 에 들어가보면 해당 이슈를 상세히 확인할 수 있다. 부적절한 EOF 처리 원인은 소스 코드 수정 시 유사한 코드를 복사 붙여넣기 하는 과정에서 검증해야할 변수 명을 고치지 않고 그대로 적용해서 발생했다. operand=ReadBlobByte(image); if (opcode == EOF) ThrowRLEException(CorruptImageError, "UnexpectedEndOfFile" ); 이로 인해서 조치 완료된 줄 알았던 CVE-2017-9144 취약점은 CVE-2017-11352이라는 새로운 취약점 명으로 다시 조치 되었다. case SkipLinesOp: { operand=ReadBlobByte(image); - if (opcode == EOF) + if (operand == EOF) ThrowRLEException(CorruptImageError, "UnexpectedEndOfFile" ); if (opcode & 0x40 ) { operand=ReadBlobLSBSignedShort(image); - if (opcode == EOF) + if (operand == EO...