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_size | 0x91 |
| 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_size | 0x91 |
| 0xf0 → 0x60 | ||
| c | 0x210 | 0x110 |
이제 system은 b2 chunk의 존재를 잊어버린다.
4. d = malloc(0x300)
| a | prev_size | 0x111 | |
| b1 | d | prev_size | 0x311 |
| b2 | prev_size | 0x91 | |
| 0xf0 → 0x60 | |||
| c | 0x210 | 0x110 | |
d chunk에 접근해서 b2 chunk를 변경할 수 있다.