16.04에서 DFB를 할때 fastbin은 size check가 있다.
if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
{
idx = fastbin_index (nb);
mfastbinptr *fb = &fastbin (av, idx);
mchunkptr pp = *fb;
do
{
victim = pp;
if (victim == NULL)
break;
}
while ((pp = catomic_compare_and_exchange_val_acq (fb, victim->fd, victim))
!= victim);
if (victim != 0)
{
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{
errstr = "malloc(): memory corruption (fast)";
errout:
malloc_printerr (check_action, errstr, chunk2mem (victim), av);
return NULL;
}
fastbin_index (chunksize (victim)) != idx
를 우회할 수 있는 fake chunk를 찾을때, 하위 4바이트만 신경써주면 된다.
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
fastbin_index
매크로가 unsigned int로 타입 캐스팅해서 비교하기 때문이다.
struct malloc_chunk {
INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
};
INTERNAL_SIZE_T가 64비트 환경이여서 8바이트여도, 하위 4바이트만 검증하기 때문에, 그 4바이트만 신경써주면 된다.
그래서 0x0168000000000060
가 fastbin_index (chunksize (victim)) != idx
를 우회할 수 있게 된다.