본문 바로가기

system

[how2heap translation] poison_null_byte.c

다른 how2heap 의 내용보다 길기에 끊어서 설명하도록 하겠다..

poison null byte 2.0 에 온 거 환영한다@@

이거는 ubuntu 14.04 64bit 에서 진행했고~ 이 기술은 malloc 영역에 널바이트 off-by-one 이 있을 때 사용 가능하다.

 

0x100, 0x200, 0x100 만큼 malloc 해서 각각 a, b, c 변수에 반환된 주소 값 들어간다.

a : 0x603420

b : 0x603530

c : 0x603740

real_a_size : 0x108

b_size_ptr : 0x211

 

malloc_usable_size() 같은 경우 chunk 크기에서 다음 chunk 의 prev_size 까지 포함한 크기라고 함.

free 된 chunk 의 경우 이 값이 0 이지만, fastbin 에서는 prev_inuse bit 이 setting 되어 있기에 원래의 크기 반환한다.

 

이 기술은 free chunk 의 size metadata 를 overwrite 함으로써 이뤄진다.

우리는 'a' 의 overflow 를 이용해 'b' 의 metadata 에 하나의 널 바이트를 덮어쓰도록 한다.

-> free 된 b 의 size 를 0x200 으로 바꾸면서 unsorted bin 안에 있는 b 의 size 가 0x200 으로 바뀜..

 

b_size_ptr : 0x211 -> 0x200

c_prev_size_ptr : 0x210

보통 chunk size 는 metadata 가 차지하는 영역을 포함하기 때문에 chunk size 는 최하위 비트로 0x00 을 가질 수 없다.

 

b1 : 0x603530

c_prev_size_ptr : 0x210

c - 0x20 : 0xf0  <- c_prev_size 의 바뀐 값.

b1 을 malloc 했을 때 ,'b' 가 있던 곳에 배치된다. 이 시점에서 c 의 prev_size 는 update 되어야 하는데 그렇지 않았다.

흥미롭게도, c_prev_size 의 바뀐 값은 c_prev_size 의 -0x10bytes 자리에 쓰여진다. 

// 일반적으로 b2 (희생자) 는 우리가 제어하고자 하는 유용한 포인터가 있는 구조가 될 것이다.

 

b2 : 0x603640

b2 를 malloc 한 후, b2 영역에 'B' 를 0x80 만큼 넣는다.

 

잠시 메모리 상황을 보자. 가장 먼저 b1 을 볼 수 있고, 0x603640 에 b2 에 우리가 넣은 문자열들을 볼 수 있다.

그리고 c 의 prev_size 값이 여전히 0x210 인 것을 확인할 수 있다.

 

이제 'b1' 과 'c' 를 free 하자. 이것은 'b1' 과 'c' 를 병합할 것이다. ('b2' 에 관해서는 잊은 채)

 

d : 0x603530

 

마침내, 우리는 'd' 를 할당한다. 그리고 'b2' 와 overlapping 됨~

이를 확인하기 위해 'd' 영역에 0x300 만큼의 문자열을 넣고 확인해보자.

 

'd' 와 'b2' 가 오버래핑 되어 'b2' 에 값을 쓸 수 있따!