{"id":3545,"date":"2025-05-11T11:48:38","date_gmt":"2025-05-11T02:48:38","guid":{"rendered":"https:\/\/h4ck.kr\/?p=3545"},"modified":"2025-05-11T15:35:33","modified_gmt":"2025-05-11T06:35:33","slug":"how2heap-glibc2-39-decrypt_safe_linking","status":"publish","type":"post","link":"https:\/\/h4ck.kr\/?p=3545","title":{"rendered":"[how2heap\/glibc2.39] decrypt_safe_linking"},"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<p>glibc 2.32 \ubc84\uc804\ubd80\ud130 <strong>fastbin \ubc0f tcache \uac19\uc740 \ub2e8\uc77c \uc5f0\uacb0 \ub9ac\uc2a4\ud2b8\uc5d0\ub294<\/strong><br><strong>safe-linking \uba54\ucee4\ub2c8\uc998\uc73c\ub85c \uc778\ud574 fd\uac00 \uc554\ud638\ud654\ub41c\ub2e4.<\/strong><br><strong>\ub530\ub77c\uc11c \ud574\ub2f9\uae00\uc740 fd \uac12\uc744 \ub2e4\uc2dc \ubcf5\ud638\ud654\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4.<\/strong><\/p>\n\n\n\n<p>\uc5ec\uae30\uc11c fd\ub294 \uccad\ud06c\uac00 free\ub418\uba74 \ub4e4\uc5b4\uac00\ub294 \uac12\uc73c\ub85c, <br>\uc544\uc9c1 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc740 \ub2e4\uc74c chunk\uc758 \uc8fc\uc18c\ub97c \uc758\ubbf8\ud55c\ub2e4.<\/p>\n\n\n\n<p><strong>fd \ubcf5\ud638\ud654 \ucf54\ub4dc<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def decrypt(cipher):\n    key = 0\n    plain = 0\n\n    for i in range(1, 6):\n        bits = 64-12*i\n        if bits &lt; 0:\n            bits = 0\n        plain = ((cipher ^ key) >> bits) &lt;&lt; bits\n        key = plain >> 12\n\n    return plain<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ub0b4\uc6a9<\/h3>\n\n\n\n<p>\uc774 \uae30\ubc95\uc740 safe-linking \uba54\ucee4\ub2c8\uc998\uc73c\ub85c \uc778\ud574 \ubcc0\uc870\ub41c \uac12\uc5d0\uc11c \uc6d0\ub798\uc758 \ub0b4\uc6a9\uc744 \ubcf5\uad6c\ud558\ub294 \ubc29\ubc95\uc744 \ubcf4\uc5ec\uc90d\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774 \uacf5\uaca9\uc740 \ud3c9\ubb38(\ud3ec\uc778\ud130)\uc758 \ucc98\uc74c 12\ube44\ud2b8\uac00 \uc54c\ub824\uc838 \uc788\uace0, \ud0a4(ASLR \uc2ac\ub77c\uc774\ub4dc)\uac00 \ud3ec\uc778\ud130\uc758 \uc0c1\uc704 \ube44\ud2b8\uc640 \ub3d9\uc77c\ud558\ub2e4\ub294 \uc0ac\uc2e4\uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uacb0\uacfc\uc801\uc73c\ub85c, \ud3ec\uc778\ud130\uac00 \uc800\uc7a5\ub41c \uccad\ud06c\uac00 \ud3ec\uc778\ud130 \uc790\uccb4\uc640 \uac19\uc740 \ud398\uc774\uc9c0\uc5d0 \uc788\ub294 \ud55c, \ud3ec\uc778\ud130\uc758 \uac12\uc744 \uc644\uc804\ud788 \ubcf5\uad6c\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uadf8\ub807\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uc5d0\ub3c4, \uc800\uc7a5 \uc704\uce58\uc640 \ud3ec\uc778\ud130 \uc0ac\uc774\uc758 \ud398\uc774\uc9c0 \uc624\ud504\uc14b\uc744 \uc774\uc6a9\ud574 \ud3ec\uc778\ud130\ub97c \ubcf5\uad6c\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc5ec\uae30\uc11c \uc2dc\uc5f0\ud558\ub294 \uac83\uc740 \ud398\uc774\uc9c0 \uc624\ud504\uc14b\uc774 0\uc778 \ud2b9\uc218\ud55c \uacbd\uc6b0\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1.<\/h3>\n\n\n\n<p>\uba3c\uc800 a\uc640 b \uccad\ud06c\uc5d0 \uac01\uac01 0x20\ub9cc\ud07c \ucc28\ub840\ub300\ub85c \ud560\ub2f9\ud568. <br>\uc774\ud6c4, \ubcd1\ud569\uc744 \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ud328\ub529 \uccad\ud06c(padding chunk)\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 0x10\ub9cc\ud07c \ud560\ub2f9\ud568.<\/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=\"\">\/\/ step 1: allocate chunks\n\tlong *a = malloc(0x20);\n\tlong *b = malloc(0x20);\n\tprintf(\"First, we create chunk a @ %p and chunk b @ %p\\n\", a, b);\n\tmalloc(0x10);\n\tputs(\"And then create a padding chunk to prevent consolidation.\");<\/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=\"\">First, we create chunk a @ 0x5555555592a0 and chunk b @ 0x5555555592d0\nAnd then create a padding chunk to prevent consolidation.<\/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=\"\">gef\u27a4  heap chunks\nChunk(addr=0x555555559010, size=0x290, flags=PREV_INUSE)\n    [0x0000555555559010     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]\nChunk(addr=0x5555555592a0, size=0x30, flags=PREV_INUSE)\n    [0x00005555555592a0     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]\nChunk(addr=0x5555555592d0, size=0x30, flags=PREV_INUSE)\n    [0x00005555555592d0     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]\nChunk(addr=0x555555559300, size=0x20d10, flags=PREV_INUSE)  \u2190  top chunk\n\ngef\u27a4  heap chunk 0x5555555592a0\nChunk(addr=0x5555555592a0, size=0x30, flags=PREV_INUSE)\nChunk size: 48 (0x30)\nUsable size: 40 (0x28)\nPrevious chunk size: 0 (0x0)\nPREV_INUSE\n\ngef\u27a4  heap chunk 0x5555555592d0\nChunk(addr=0x5555555592d0, size=0x30, flags=PREV_INUSE)\nChunk size: 48 (0x30)\nUsable size: 40 (0x28)\nPrevious chunk size: 0 (0x0)\nPREV_INUSE<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"601\" height=\"245\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-8.png\" alt=\"\" class=\"wp-image-3546\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-8.png 601w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-8-300x122.png 300w\" sizes=\"auto, (max-width: 601px) 100vw, 601px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2.<\/h3>\n\n\n\n<p>glibc2.32?\ubd80\ud130 safe linking\uacfc\uc815\uc774 \ucd94\uac00\ub418\uc5c8\ub294\ub370 <br><strong>\uc544\uc9c1 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc740 \ub2e4\uc74c chunk\uc758 \uc8fc\uc18c\ub97c \uc758\ubbf8\ud558\ub294 fd\ub294 <code>fd ^ (heap_chunk &gt;&gt; 12)<\/code> \ubcc0\ud658\ud574\uc11c \ub4e4\uc5b4\uac04\ub2e4.<\/strong><\/p>\n\n\n\n<p><strong><code>mangled = (real_fd ^ (chunk_address &gt;&gt; 12));<\/code><\/strong><\/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=\"\">\/\/ step 2: free chunks\n\tputs(\"Now free chunk a and then free chunk b.\");\n\tfree(a);\n\tfree(b);\n\tprintf(\"Now the freelist is: [%p -> %p]\\n\", b, a);\n\tprintf(\"Due to safe-linking, the value actually stored at b[0] is: %#lx\\n\", b[0]);<\/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 free chunk a and then free chunk b.\nNow the freelist is: [0x5555555592d0 -> 0x5555555592a0]\nDue to safe-linking, the value actually stored at b[0] is: 0x55500000c7f9<\/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=\"\">Breakpoint 1, 0x00005555555551ae in main ()\ngdb-peda$ parseheap\naddr                prev                size                 status              fd                bk\n0x555555559000      0x0                 0x290                Used                None              None\n0x555555559290      0x0                 0x30                 Freed        0x555555559              None\n0x5555555592c0      0x0                 0x30                 Freed     0x55500000c7f9              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: 0x5555555592f0 (size : 0x20d10)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x0\n(0x30)   tcache_entry[1](2): 0x5555555592d0 --> 0x5555555592a0<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"347\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-12.png\" alt=\"\" class=\"wp-image-3552\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-12.png 623w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/05\/image-12-300x167.png 300w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3.<\/h3>\n\n\n\n<p>\ud558\uc9c0\ub9cc safe linking\uc73c\ub85c \uc778\ud574 \ubcc0\ud658\ub41c enc_fd\ub294 \ub2e4\uc2dc \ubcf5\ud638\ud654\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \ud55c\ub2e4.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\ubcf5\ud638\ud654\ub294 \ud3c9\ubb38(fwd \ud3ec\uc778\ud130)\uc758 \ucc98\uc74c 12\ube44\ud2b8\uac00 \uc54c\ub824\uc838 \uc788\ub2e4\ub294 \uc0ac\uc2e4\uc744 \uc774\uc6a9\ud558\uba70, \uc774\ub294 12\ube44\ud2b8 \uc2ac\ub77c\uc774\ub529 \ub355\ubd84\uc774\ub2e4.<br>\uadf8\ub9ac\uace0 \ud0a4\uc778 ASLR \uac12\uc740 \ud3c9\ubb38(fwd \ud3ec\uc778\ud130)\uc758 \uc0c1\uc704 \ube44\ud2b8\ub4e4\uacfc \ub3d9\uc77c\ud558\ub2e4.<\/p>\n<\/blockquote>\n\n\n\n<p>\ubcf4\ub2e4\uc2dc\ud53c b\uccad\ud06c\uc5d0 \uc788\ub358 \uc6d0\ub798\uc758 \uac12\uc778 fd\uac12\uc774 \ub098\uc654\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=\"\">long decrypt(long cipher)\n{\n        puts(\"The decryption uses the fact that the first 12bit of the plaintext (the fwd pointer) is known,\");\n        puts(\"because of the 12bit sliding.\");\n        puts(\"And the key, the ASLR value, is the same with the leading bits of the plaintext (the fwd pointer)\");\n        long key = 0;\n        long plain;\n\n        for(int i=1; i&lt;6; i++) {\n                int bits = 64-12*i;\n                if(bits &lt; 0) bits = 0;\n                plain = ((cipher ^ key) >> bits) &lt;&lt; bits;\n                key = plain >> 12;\n                printf(\"round %d:\\n\", i);\n                printf(\"key:    %#016lx\\n\", key);\n                printf(\"plain:  %#016lx\\n\", plain);\n                printf(\"cipher: %#016lx\\n\\n\", cipher);\n        }\n        return plain;\n}\n\n        \/\/ step 3: recover the values\n        puts(\"Now decrypt the poisoned value\");\n        long plaintext = decrypt(b[0]);\n\n        printf(\"value: %p\\n\", a);\n        printf(\"recovered value: %#lx\\n\", plaintext);\n        assert(plaintext == (long)a);<\/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 decrypt the poisoned value\nThe decryption uses the fact that the first 12bit of the plaintext (the fwd pointer) is known,\nbecause of the 12bit sliding.\nAnd the key, the ASLR value, is the same with the leading bits of the plaintext (the fwd pointer)\nround 1:\nkey:    0000000000000000\nplain:  0000000000000000\ncipher: 0x0055500000c7f9\n\nround 2:\nkey:    0x00000550000000\nplain:  0x00550000000000\ncipher: 0x0055500000c7f9\n\nround 3:\nkey:    0x00000555550000\nplain:  0x00555550000000\ncipher: 0x0055500000c7f9\n\nround 4:\nkey:    0x00000555555550\nplain:  0x00555555550000\ncipher: 0x0055500000c7f9\n\nround 5:\nkey:    0x00000555555559\nplain:  0x005555555592a0\ncipher: 0x0055500000c7f9\n\nvalue: 0x5555555592a0\nrecovered value: 0x5555555592a0<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\ud658\uacbd Ubuntu GLIBC 2.39-0ubuntu8.4 \/ Ubuntu 24.04.1 LTS x86_64 \uc694\uc57d glibc 2.32 \ubc84\uc804\ubd80\ud130 fastbin \ubc0f tcache \uac19\uc740 \ub2e8\uc77c \uc5f0\uacb0 \ub9ac\uc2a4\ud2b8\uc5d0\ub294safe-linking \uba54\ucee4\ub2c8\uc998\uc73c\ub85c \uc778\ud574 fd\uac00 \uc554\ud638\ud654\ub41c\ub2e4.\ub530\ub77c\uc11c \ud574\ub2f9\uae00\uc740 fd \uac12\uc744 \ub2e4\uc2dc \ubcf5\ud638\ud654\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc124\uba85\ud55c\ub2e4. \uc5ec\uae30\uc11c fd\ub294 \uccad\ud06c\uac00 free\ub418\uba74 \ub4e4\uc5b4\uac00\ub294 \uac12\uc73c\ub85c, \uc544\uc9c1 \uc0ac\uc6a9\ub418\uc9c0 \uc54a\uc740 \ub2e4\uc74c chunk\uc758 \uc8fc\uc18c\ub97c \uc758\ubbf8\ud55c\ub2e4. fd \ubcf5\ud638\ud654 \ucf54\ub4dc \ub0b4\uc6a9 \uc774 \uae30\ubc95\uc740 safe-linking \uba54\ucee4\ub2c8\uc998\uc73c\ub85c \uc778\ud574 \ubcc0\uc870\ub41c&hellip;&nbsp;<a href=\"https:\/\/h4ck.kr\/?p=3545\" rel=\"bookmark\">\ub354 \ubcf4\uae30 &raquo;<span class=\"screen-reader-text\">[how2heap\/glibc2.39] decrypt_safe_linking<\/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":[51,25],"class_list":["post-3545","post","type-post","status-publish","format-standard","hentry","category-how2heap","tag-how2heap","tag-pwnable"],"_links":{"self":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3545","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=3545"}],"version-history":[{"count":3,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3545\/revisions"}],"predecessor-version":[{"id":3553,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3545\/revisions\/3553"}],"wp:attachment":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}