Post

Poison null byte

https://github.com/umbum/pwn/blob/master/how2heap/poison_null_byte.c

malloc’ed region에 off-by-one error가 발생할 때, next chunk size의 LSB를 0으로 만들어 size를 속이는 방법. 결과적으로 d chunk 내부에 b2 chunk가 위치하게 되므로 d chunk에 접근해 b2 chunk를 변경할 수 있다.

null byte off-by-one error는 종종 발생하기 때문에 많은 경우에 사용할 수 있는 테크닉이라는 점은 장점.

b2 chunk는 heap에만 존재할 수 있기 때문에 b2 chunk가 function pointer 등 유용한 데이터를 저장하고 있을 경우나, overlap을 이용한 leak이 필요할 경우 말고는 그다지 쓸모가 없다는 것이 단점.

1.
 a  prev_size 0x111




b prev_size 0x211




 0x200 
c 0x210 0x111 


0x210 & 0xff00 했으므로 0x200

2. free(b) AND off-by-one overflow
 a  prev_size 0x111




b prev_size 0x200




 0x200
c 0x210 0x110 


free(b) 했으므로 0x110

b->size의 LSB는 0x01이면 안된다. c->prev\_size가 업데이트 되지 않도록, 그 이전에 c fake\_next->prev\_size를 두어 이게 대신 업데이트 되도록 해야 하는데 0x01이면 그냥 c->prev_size가 업데이트 돼버린다.

3. b1 = malloc(0x100) , b2 = malloc(0x80)
 a  prev_size 0x111




b1 prev_size 0x111


  
b2 prev_size0x91



  
 0xf0 → 0x60 
 c 0x210 0x110


4. free(b1) , free(c)

free(b1)하지 않으면 [unlink ] corrupted double-linked list Error가 발생한다. PREV\_INUSE flag가 없는 상태에서 free(c)하게 되므로 prev_size를 따라가 prev chunk를unlink 하기 위해 fd / bk를 검사하기 때문. free’d area가 할당되어 둘로 나뉘어 질 때, 할당되지 않은 영역에 자동으로 fd / bk가 잡히며 nextchunk.prev_size가 자동으로 나뉘어진 chunk를 가리키도록 업데이트 되기 때문에 정상이라면 이 check를 통과할 수 있다. 그러나 off-by-one overflow로 b.size를 변경했기 때문에 nexchuck&c - 0x10에 있는 것으로 잡혀 c.prev_size는 계속 0x210으로, 업데이트 되지 않는다. 따라서 c - 0x210위치의 chunk에 fd / bk를 설정해야 하기 때문에 free(b1)로 이를 설정해 주고, free(c)한다.

 a  prev_size 0x111




b1 prev_size 0x20ef1(top)
 fd bk
  
b2 prev_size0x91



  
 0xf0 → 0x60 
c0x2100x110


이제 system은 b2 chunk의 존재를 잊어버린다.

4. d = malloc(0x300)
 a  prev_size 0x111




b1 d prev_size 0x311


  
b2 prev_size0x91



  
 0xf0 → 0x60 
c0x2100x110


d chunk에 접근해서 b2 chunk를 변경할 수 있다.

This post is licensed under CC BY 4.0 by the author.