[Pwn]how2heap-first_fit.c

김민주·2025년 9월 17일

security

목록 보기
2/13

how2heap 이란?

heap관련 취약점들의 원리를 소스코드와 주석으로 설명해 놓은 github repository
https://github.com/shellphish/how2heap

first_fit.c

how2heap에서 처음으로 분석할 자료이다.

복습1. 메모리 구조

메모리에 존재하는 영역

  • 데이터(data) 영역
    - 전역 변수, static 변수가 저장
  • 스택(stack) 영역
    - 지역변수, 매개변수가 저장
  • 힙(heap) 영역
    - malloc(), calloc()과 같은 함수에 의해 동적으로 생성된 변수를 저장
  • 코드(code, text) 영역
  • bss 영역

복습2. Heap Memory Management

  1. first fit(최초적합) 방식
  • 첫번째로 들어갈 수 있는 곳에 넣는다.
  1. best fit(최적적합) 방식
  • 데이터가 저장되기에 가장 적절한 곳에 데이터를 저장한다.
  1. worst fit(최악적합) 방식
  • 가장 크기가 안 맞는 곳에 데이터를 저장한다.

코드

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	fprintf(stderr, "This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.\n");
	fprintf(stderr, "glibc uses a first-fit algorithm to select a free chunk.\n");
	fprintf(stderr, "If a chunk is free and large enough, malloc will select this chunk.\n");
	fprintf(stderr, "This can be exploited in a use-after-free situation.\n");

	fprintf(stderr, "Allocating 2 buffers. They can be large, don't have to be fastbin.\n");
	char* a = malloc(0x512);
	char* b = malloc(0x256);
	char* c;

	fprintf(stderr, "1st malloc(0x512): %p\n", a);
	fprintf(stderr, "2nd malloc(0x256): %p\n", b);
	fprintf(stderr, "we could continue mallocing here...\n");
	fprintf(stderr, "now let's put a string at a that we can read later \"this is A!\"\n");
	strcpy(a, "this is A!");
	fprintf(stderr, "first allocation %p points to %s\n", a, a);

	fprintf(stderr, "Freeing the first one...\n");
	free(a);

	fprintf(stderr, "We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at %p\n", a);

	fprintf(stderr, "So, let's allocate 0x500 bytes\n");
	c = malloc(0x500);
	fprintf(stderr, "3rd malloc(0x500): %p\n", c);
	fprintf(stderr, "And put a different string here, \"this is C!\"\n");
	strcpy(c, "this is C!");
	fprintf(stderr, "3rd allocation %p points to %s\n", c, c);
	fprintf(stderr, "first allocation %p points to %s\n", a, a);
	fprintf(stderr, "If we reuse the first allocation, it now holds the data from the third allocation.\n");
}

실행결과

분석

  1. glibc는 first-fit algorithm을 사용한다.
  2. malloc 함수를 이용해서 0x512, 0x256 크기의 문자열 배열 a, b를, malloc을 하지 않은 포인터 문자열 c를 선언한다.
  3. a가 할당된 주소는 0x5ae5355e52a0, b가 할당된 주소는 0x5ae5355e57a0 이다.
  4. "this is A!"라는 문자열을 a에 넣고 a의 주소를 프린트하면 0x5ae5355e52a0이 나온다.
  5. a를 free 해보자.
  6. 0x512보다 작게 새로운 할당을 한다면 이는 a 자리에 들어갈 것 같다. 그렇지 않다면, 다른 공간을 찾을 것이다.
  7. 앞서 선언한 c에 0x500크기의 malloc을 해보자.
  8. c의 주소는 a가 할당되었던 주소인 0x5ae5355e52a0가 출력된다
  9. "this is C!"라는 문자열을 c에 넣고 3번째 할당인 c와 첫번째 할당인 a의 주소를 출력해보자.
  10. c와 a가 같은 주소를 가리킨다.

결론 : 첫번째 할당한 것을 다시 사용하게 되면, 세번째 할당한 데이터를 가지게 될 것이다.

0개의 댓글