System Hacking/Study Notes

Large bin attack

S!_Jmini 2020. 5. 4. 14:54

glibc-2.23

#1. 소개

 

Large bin attack 은 how2heap에 자세히 소개되어있다

 

https://github.com/shellphish/how2heap/blob/master/glibc_2.26/large_bin_attack.c

 

 

들어가기에 앞서 간단히 large bin 에 대해서 설명해보자면

 

large bin은 0x400 size 이상의 chunk 들을 관리하며 이중 연결리스트로 동작한다

 

다른 bin들과 다르게 fd, bk 이외에 fd_nextsize 및 bk_nextsize 가 있는데

 

이 둘은 다음 사이즈의 large bin chunk 를 연결하고 있다

 

 

Large bin attack 은 이름 그대로 Large bin의 동작원리를 이해하여

 

임의 주소에 heap chunk 주소 값을 덮을 수 있다

 

 

위 결과를 얻기 위한 조건은 아래와 같다

 

Large bin 에 들어있는 chunk의 size 값, bk, bk_nextsize 를 조작할 수 있어야 한다

 

( 기본적으로 UAF가 가능해야한다는 의미이다 )

 

 

취약점을 발생시키는 방법은

 

1. large bin 크기에 해당하는 chunk 3개를 할당한다

( 단, p1의 size는 p2와 p3보다 작아야한다 )

 

2. p1과 p2를 차례로 free한 뒤 p1보다 작은 크기의 chunk 를 할당함으로써 p2를 large bin으로 보낸다

( 이 때 p1은 unsorted bin에 남아있다 )

 

3. 이후 p3를 free하여 unsorted bin에서 p1과 p3 가 연결되도록 한다

 

4. 앞선 전제조건을 바탕으로 p2의 size 값을 p3보다 작게만들고

bk에는 target-0x10, bk_nextsize 에는 target-0x20을 적는다

( 여기서 target은 우리가 덮고싶은 임의의 주소이다 )

 

5. 이후 줄어든 크기의 p1보다 작은 크기의 chunk 를 할당함으로써 p3를 large bin 으로 보낸다

 

이후에 target에 p3 청크의 주솟값이 남게된다

 

 

 

#2. 분석하기

 

* how2heap의 large_bin_attack.c 를 보고나서 작성하였음

( + malloc.c에서 large bin code 를 분석하기보다 직접 메모리를 보면서 확인하였음 )

 

 

먼저 왜 저 3가지 값들을 조작해야하는지 이해하기 위해서

 

how2heap의 playground 에서 뛰어놀아보고자 한다

( https://github.com/shellphish/how2heap/blob/master/malloc_playground.c )

 

 

1. 왜 size 값을 바꾸는 것일까?

 

large bin attack 을 위해서 p2와 p3 chunk 를 생성할 때

 

p2와 p3 chunk 의 size를 동일하게 만든 뒤 

 

p2 의 size를 UAF 를 통해 p3보다 작도록 수정하는 부분이 있다

 

만약 p2 의 size를 애초에 p3 보다 작으면 되지 않을까 라는 의문이 생겼고

 

이를 알아보기 위해 먼저 size 값을 다르게 만든 p2와 p3 를 생성해보았다

 

 

malloc 0x90 을 통해 p3 chunk 를 large bin 으로 보내기 전의 메모리 상황은 다음과 같다

 

p2 는 0x480 크기의 large bin에 관리되어 있다

 

다음은 malloc 0x90 을 통해 p3 chunk 를 large bin 으로 보낸 후의 메모리 상황이다

 

 

p2 와 p3 가 다른 size라 bk 를 통해 연속적으로 연결되어있지 않은 모습이다

 

이후 이 상황에서 p2의 bk와 bk_nextsize 값을 조작하더라도 취약점 트리거가 되지 않았다

 

더보기

 

0x90을 통해 p3를 large bin 으로 보내기 전

 

 

 

p3를 large bin 으로 보낸 이후

 

 

dl_open_hook 에 heap chunk 주소값을 남기는데 실패했다

 

아마도 size가 동일한 chunk 들끼리 bk와 bk_next 를 넘겨주는 과정이 필요한 것 같다

 

따라서 p2와 p3 가 같은 size 의 chunk 로 관리되도록 해야함을 알 수 있다

 

근데 이후 또다른 의문점이 하나 생긴다

 

 

 

 

 

2. 왜 p2의 size 는 p3보다 작아야하는가?

 

 

아래는 size 값을 변경하지 않은채 취약점을 트리거하려는 모습이다

 

먼저 p1,p2,p3 를 셋팅해두고

 

 

위 상태에서 p2의 size 값을 변경하지 않은 채 + bk와 bk_nextsize 를 변경하지 않은 채

 

malloc 0x90 을 통해 p3 를 large bin 으로 보낸 상황이다 ( 매우 정상적인 상황 )

 

 

 

 

보다시피 large bin 에 들어가있는 순서가

 

p2->p3 가 아닌 p3->p2 가 되어있는 모습이다

 

 

 

하지만 p2의 size 값을 p3 보다 작게한다면

 

 

p2->p3 로 연결되게 된다

 

 

따라서 p2 -> p3 순서로 연결되도록 한후

 

p2 의 bk값과 bk_nextsize 에 target-0x10,-0x20 을 적어둔다면

 

p3 다음 chunk 가 target chunk 라고 생각하여

 

p3의 bk와 nextsize은 target-0x10과 target-0x20을 적을 것이고

 

target의 fd위치에는 p3 chunk 주솟값이 들어갈 것이다

 

 

세줄요약

 

1. p2와 p3 입장에서는 서로가 연결되고 싶은 상황인데 임의의 값 조작을 통해서 p2 bk에는 이상한 값이 있는 상황임


2. p2는 자신의 bk를 p3로 미루기 위해서 p3의 bk에다가 target-0x10을 넘겨줌


3. p3 입장에서는 target-0x10이 p3다음이라는 걸 전달받아서 target-0x10의 fd(즉,target)에는 p3가 적힘

 

 

 

#3. 응용하기

 

 

여기 heap chunk 주소값을 덮어쓰기 좋은 함수가 하나 있다

 

이 함수는 abort() 가 실행될 때 참조되어지는데

 

dl_open_hook 에 있는 주솟값을 참조하여 jmp 를 실행한다

 

즉, dl_open_hook 에 0x602020 이라는 주솟값이 들어있으면, 0x602020 에 들어있는 0x41414141 로 jmp 한다

 

 

이 함수에 heap chunk 주솟값을 남기면 우리가 원하는 곳으로 jmp 할 수 있겠다

 

 

앞서 배운 내용을 바탕으로 p1 과 p2, p3 chunk 를 준비해두고

 

p2의 size와 bk, bk_nextsize 까지 dl_open_hook 을 target으로 조작해둔다

 

 

 

 

이후 p3를 large bin 으로 보내면 아래와 같은 상황이 발생한다

 

 

 

 

원래 NULL 값이 들어있던 dl_open_hook 을 성공적으로 덮은 모습이다

 

 

 

이후 0x604990 에 jmp 하고 싶은 함수들을 적으면 되겠다