{"id":7477,"date":"2019-04-29T23:05:34","date_gmt":"2019-04-29T23:05:34","guid":{"rendered":"https:\/\/hackmethod.com\/?p=7477"},"modified":"2022-06-03T05:37:10","modified_gmt":"2022-06-03T05:37:10","slug":"overthewire-narnia-3","status":"publish","type":"post","link":"https:\/\/hackmethod.com\/overthewire-narnia-3\/","title":{"rendered":"OverTheWire \u2013 Narnia 3"},"content":{"rendered":"\n<p>Welcome back! Now that we&#8217;ve conquered Level 2 and gained the password for Level 3 it&#8217;s time to keep pressing. <\/p>\n\n<h2 id=\"introduction\">Introduction<\/h2>\n\n<p>Same thing from before. Log into the lab server as Narnia3 and look at the source code for <code>narnia3.c<\/code>.<\/p>\n\n<pre><code class=\"C language-C\">\/*\n   This program is free software; you can redistribute it and\/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n\n   You should have received a copy of the GNU General Public License\n   along with this program; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n*\/\n\n#include &lt;stdio.h&gt;\n#include &lt;sys\/types.h&gt;\n#include &lt;sys\/stat.h&gt;\n#include &lt;fcntl.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;string.h&gt;\n\nint main(int argc, char **argv){\n\n    int  ifd,  ofd;\n    char ofile[16] = \"\/dev\/null\";\n    char ifile[32];\n    char buf[32];\n\n    if(argc != 2){\n        printf(\"usage, %s file, will send contents of file 2 \/dev\/null\\n\",argv[0]);\n        exit(-1);\n    }\n\n    \/* open files *\/\n    strcpy(ifile, argv[1]);\n    if((ofd = open(ofile,O_RDWR)) &lt; 0 ){\n        printf(\"error opening %s\\n\", ofile);\n        exit(-1);\n    }\n    if((ifd = open(ifile, O_RDONLY)) &lt; 0 ){\n        printf(\"error opening %s\\n\", ifile);\n        exit(-1);\n    }\n\n    \/* copy from file1 to file2 *\/\n    read(ifd, buf, sizeof(buf)-1);\n    write(ofd,buf, sizeof(buf)-1);\n    printf(\"copied contents of %s to a safer place... (%s)\\n\",ifile,ofile);\n\n    \/* close 'em *\/\n    close(ifd);\n    close(ofd);\n\n    exit(1);\n}\n<\/code><\/pre>\n\n<h2 id=\"staticcodeanalysis\">Static Code Analysis<\/h2>\n\n<p>I won&#8217;t go over the already known preprocessor directives. For information regarding them check out the last post. I will however, go over the new ones we see here.<\/p>\n\n<pre><code class=\"C language-C\">#include &lt;sys\/types.h&gt;\n#include &lt;sys\/stat.h&gt;\n#include &lt;fcntl.h&gt;\n#include &lt;unistd.h&gt;\n<\/code><\/pre>\n\n<p>The first preprocessor directive <code>#include &lt;sys\/types.h&gt;<\/code> contains some of the more common data types that are used in the system. Although these are meant to be used within the kernel, most of the system data types are accessible also to user code. Check out more information on this header file <a href=\"https:\/\/man.openbsd.org\/NetBSD-7.0.1\/types.3\">here<\/a>. Or, look over the header file yourself with this command: <code>less \/usr\/include\/x86_64-linux-gnu\/sys\/types.h<\/code> <\/p>\n\n<p>Next, we have <code>#include &lt;sys\/stat.h&gt;<\/code> and this header file defines the structure of the data that is returned by the <em>stat()<\/em>, <em>fstat()<\/em>, and <em>lstat()<\/em> functions. Check out more information on this header file <a href=\"http:\/\/man7.org\/linux\/man-pages\/man0\/sys_stat.h.0p.html\">here<\/a>. The header file is located here: <code>\/usr\/include\/x86_64-linux-gnu\/sys\/stat.h<\/code><\/p>\n\n<p>The <code>#include &lt;fcntl.h&gt;<\/code> directive shall define the following requests and arguments for use by the functions <em>fcntl()<\/em> and <em>open()<\/em>. This is mostly used to retrieve or modify open file flags given a file descriptor. Check out more information on this header file <a href=\"http:\/\/pubs.opengroup.org\/onlinepubs\/007908799\/xsh\/fcntl.h.html\">here<\/a>. The header file is located here: <code>\/usr\/include\/fcntl.h<\/code><\/p>\n\n<p>Lastly, we have <code>#include &lt;unistd.h&gt;<\/code> and this directive provides access to the Portable Operating System Interface (POSIX) operating system API. Check out more information on this header file <a href=\"http:\/\/pubs.opengroup.org\/onlinepubs\/007908799\/xsh\/unistd.h.html\">here<\/a>. The header file is located here: <code>\/usr\/include\/unistd.h<\/code><\/p>\n\n<p>As we can clearly see from the preprocessor directives, this is a much more robust program. We still have the same <em>main()<\/em> function declaration which tells us that we will need to supply an argument. We also have more variables declared than prior levels.<\/p>\n\n<pre><code class=\"C language-C\">    int  ifd,  ofd;\n    char ofile[16] = \"\/dev\/null\";\n    char ifile[32];\n    char buf[32];\n<\/code><\/pre>\n\n<p>First we have two integers declare, <em>ifd<\/em> and <em>ofd<\/em>. Then we have three arrays, <em>ofile[16]<\/em>, <em>ifile[32]<\/em>, and <em>buf[32]<\/em>. Immediately we see an issue here with the variable <em>ofile[16]<\/em> only having 16 bytes in value and the other two arrays having 32. Ok, getting an idea here. Let&#8217;s continue.<\/p>\n\n<p>The next line is an if-statement telling us if the command-line argument, <em>argc<\/em> is not equal to 2 then print <code>usage, %s file, will send contents of file 2 \/dev\/null\\n<\/code>. Then an <code>exit(-1)<\/code>? What?! We know that <code>exit(0)<\/code> is a successful program termination and <code>exit(1)<\/code> is an indication of an unsuccessful program termination. Looking ahead we see that the other if-statements both return the same <code>exit(-1)<\/code> while the end of the <em>main()<\/em> exits with a <code>exit(1)<\/code>. Let&#8217;s keep moving forward.<\/p>\n\n<pre><code class=\"C language-C\">    if(argc != 2){\n        printf(\"usage, %s file, will send contents of file 2 \/dev\/null\\n\",argv[0]);\n        exit(-1);\n    }\n<\/code><\/pre>\n\n<p>Next is a function called <em>strcpy()<\/em> which is actually kind of famous. Check out the <code>man<\/code> page for <em>strcpy()<\/em> with the command <code>man strcpy<\/code> and press <code>Shift+gg<\/code>.<\/p>\n\n<blockquote>\n  <p>If the  destination string of a strcpy() is not large enough, then anything might happen.  Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine.  Any time a program reads or copies data into a buffer, the program first needs to check that there&#8217;s enough space.  This may be unnecessary if you can show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.<\/p>\n<\/blockquote>\n\n<p>Alright, so this function is known to cause buffer overflows and we can add this to our arsenal of possibilities. Looking at the function it accepts two arguments, <code>ifile<\/code> and <code>argv[1]<\/code> and we know from the variable declaration that <code>ifile[32]<\/code> has a value of 32 bytes and <code>argv[1]<\/code> is a pointer to the first command line argument supplied. <\/p>\n\n<pre><code class=\"C language-C\">    \/* open files *\/\n    strcpy(ifile, argv[1]);\n<\/code><\/pre>\n\n<p>Then we have another if-statement that states if the variable <code>ofd<\/code> equals the <em>open()<\/em> function with the variable <code>ofile<\/code> filed and <code>O_RDWR<\/code> flag set is less than 0 then print <code>error opening %s\\n<\/code>. The <code>O_RDWR<\/code> is the <code>File Access Mode<\/code> flag for the <em>open()<\/em> function. This is necessary to read and write to the file. Read more about it <a href=\"http:\/\/man7.org\/linux\/man-pages\/man2\/open.2.html\">here<\/a>. <\/p>\n\n<pre><code class=\"C language-C\">    if((ofd = open(ofile,O_RDWR)) &lt; 0 ){\n        printf(\"error opening %s\\n\", ofile);\n        exit(-1);\n    }\n<\/code><\/pre>\n\n<p>The next if-statement is similar however, the <em>open()<\/em> function is opening the <code>ifile<\/code> variable and the <code>File Access Mode<\/code> flag is set to <code>O_RDONLY<\/code> which is Read-Only and being compared to the <code>ifd<\/code> variable.<\/p>\n\n<pre><code class=\"C language-C\">    if((ifd = open(ifile, O_RDONLY)) &lt; 0 ){\n        printf(\"error opening %s\\n\", ifile);\n        exit(-1);\n    }\n<\/code><\/pre>\n\n<p>So, from what we can tell we will be opening two files and the first command-line argument will be copied into the <code>ifile<\/code> variable. \nNext we have the heavy lifting of the program. First is the <em>read()<\/em> function taking three arguments, the <code>ifd<\/code> variable, the <code>buf<\/code> variable, and then <code>sizeof(buf)-1<\/code>. To better understand this we need to look at the <em>read()<\/em> function, <code>man read<\/code>. <\/p>\n\n<pre><code>READ(2)\n\nNAME\n       read - read from a file descriptor\n\nSYNOPSIS\n       #include &lt;unistd.h&gt;\n\n       ssize_t read(int fd, void *buf, size_t count);\n\nDESCRIPTION\n       read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.\n<\/code><\/pre>\n\n<p>So the last portion of the function <code>sizeof(buf)-1<\/code> is the count bytes. So the function will read the file up to the size of <code>buf<\/code> which is 32 minus 1 making is 31. The same goes for the <em>write()<\/em> function as well. Then finally the files are closed and the program exits. Easy enough.<\/p>\n\n<pre><code class=\"C language-C\">    \/* copy from file1 to file2 *\/\n    read(ifd, buf, sizeof(buf)-1);\n    write(ofd,buf, sizeof(buf)-1);\n    printf(\"copied contents of %s to a safer place... (%s)\\n\",ifile,ofile);\n\n\n    \/* close 'em *\/\n    close(ifd);\n    close(ofd);\n\n    exit(1);\n}\n<\/code><\/pre>\n\n<h2 id=\"exploitstaging\">Exploit Staging<\/h2>\n\n<p>With our static code analysis finished it&#8217;s time to start working on our exploitation of this program. We know the exploit will be a buffer overflow. What else do we know? We know that <em>strcpy()<\/em> will take everything from <code>argv[1]<\/code> and copy to <code>ifile[32]<\/code>. However, the buffer for <code>ifile[32]<\/code> is only 32 bytes. If we supply an argument for <code>argv[1]<\/code> that was longer than 32 bytes then we would have our buffer overflow condition. Ok, now we&#8217;re getting somewhere. We need a file that is larger than 32 bytes. \nTo make our file and to ensure that we are able to read and write to it I am going to create my file in the <code>\/tmp\/<\/code> directory using <code>python<\/code>. The file, including the <code>\/tmp\/<\/code> need to equal 32 charcters. <\/p>\n\n<pre><code>python -c 'print(len(\"\/tmp\/\" + \"A\"*27))'\nmkdir -p $(python -c 'print (\"\/tmp\/\" + \"A\"*27 + \"\/tmp\")')\ncd $(python -c 'print (\"\/tmp\/\" + \"A\"*27 + \"\/tmp\")')\n<\/code><\/pre>\n\n<p>This creates a directory in <code>\/tmp\/<\/code> named <code>AAAAAAAAAAAAAAAAAAAAAAAAAAA<\/code> which contains another <code>\/tmp\/<\/code> directory. Now we can test our exploit theory by passing our current working directory to the <code>narnia3<\/code> binary.<\/p>\n\n<pre><code>\/narnia\/narnia3 `pwd`\/abc\n<\/code><\/pre>\n\n<p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/hackmethod.com\/wp-content\/uploads\/2019\/04\/Narnia3-3.png?w=1080&#038;ssl=1\" alt=\"\"><\/p>\n\n<p>We receive an error which tells us that our argument is too large however, the error did not provide the entire working directory. Lets examine and disassemble the binary to find out what is getting overrun. To do this we can use <code>gdb<\/code> like before in the previous Narnia write ups or we can use <code>objdump<\/code>.<\/p>\n\n<p>A little bit about <code>objdump<\/code>. If you have not used <code>objdump<\/code> before then I would suggest playing around with this great tool. <code>objdump<\/code> is a great command-line tool that can be used for a wide variety of things. Such as, listing headers for an executable, disassembling an executable and even display debug information. This doesn&#8217;t do <code>objdump<\/code> justice and there are many more use cases. For more information check out the <code>man<\/code> page <a href=\"https:\/\/linux.die.net\/man\/1\/objdump\">here<\/a> or type <code>man objdump<\/code>. Now back to exploiting the <code>narnia3<\/code> binary.<\/p>\n\n<p>To disassemble the binary with <code>objdump<\/code> we will be issuing the <code>-d<\/code> flag. Futhermore, we will set our disassembly flavor to into with the <code>-M<\/code> flag followed by <code>intel<\/code> and then the path to the binary. <\/p>\n\n<pre><code>objdump -d -M intel \/narnia\/narnia3\n<\/code><\/pre>\n\n<p>Running the above command will fill the screen with the entire binary disassembled and might be a bit overwhelming. We will be focusing on the <code>&lt;main&gt;<\/code> function.\n<img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/hackmethod.com\/wp-content\/uploads\/2019\/04\/Narnia3-1.png?w=1080&#038;ssl=1\" alt=\"\"><\/p>\n\n<p>Using the above screenshot as a reference because your memory addresses may be different. The first two operations are used to build the stack frame and you will typically see these at the beginning of every function.<\/p>\n\n<pre><code> 804850b:    55                      push   ebp\n 804850c:    89 e5                   mov    ebp,esp\n<\/code><\/pre>\n\n<p>Then we have the stack pointer <code>esp<\/code> with the value <code>0x58<\/code> which is the hex value 88. This is the space needed for our variables. Then we have the <code>mov<\/code> operand to move a pointer to <code>ebp-0x18<\/code> the hex value 24, then <code>ebp-0x14<\/code> the hex value 20, then <code>ebp-0x10<\/code> hex value 16, the <code>ebp-0xc<\/code> the hex value 12, and lastly <code>ebp-0x8<\/code> the hex value of 8 but this operand isn&#8217;t a <code>mov<\/code> but rather a <code>cmp<\/code>. The <code>cmp<\/code> operand is used to compare the first source operand with the second source operand. Which all add up to 80 leaving room for local variables. <\/p>\n\n<h2 id=\"exploitdevelopment\">Exploit Development<\/h2>\n\n<p>So what do we know? We know that <code>ifile[32]<\/code> is copied at <code>0x0804855a<\/code>. We also know from the source code that <code>ifile<\/code> is copied from <code>argv[1]<\/code> which is then copied into <code>ofile<\/code>. So, in order for us to overflow <code>ofile<\/code> the value must exceed 32 characters. Then we have 16 characters for <code>ofile<\/code> which contains &#8220;\/dev\/null&#8221;. Let&#8217;s provide the executable an input file which contains or references the password and an output file which we control. To solve this, I created a folder within <code>\/tmp<\/code> called <code>AAAAAAAAAAAAAAAAAAAAAAAAAAA<\/code>. The total length of the following string is 32 bytes. Therefore, anything that follows the above path will overwrite the output file. To solve that, I created an output file within <code>\/tmp<\/code> named <code>output<\/code>. I also created an input file named <code>output<\/code> within a folder named tmp  which nests under <code>\/tmp\/AAAAAAAAAAAAAAAAAAAAAAAAAAA\/tmp<\/code>. If we symbolically link this file to the password file, we can use it as the input file and the output file will be re-written to <code>\/tmp\/output<\/code> which is a file we can view.<\/p>\n\n<p><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/hackmethod.com\/wp-content\/uploads\/2019\/04\/Narnia3-2.png?w=1080&#038;ssl=1\" alt=\"\"><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>If you missed out on Narnia Level 2 click the button on the left to check it out.  If you\u2019re all caught up and want to see more, check out  the Narnia Level 3 by clicking the button on the right. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-columns has-2-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-button aligncenter\"><a class=\"wp-block-button__link\" href=\"https:\/\/hackmethod.com\/overthewire-narnia-2\/\">Narnia Level 2<\/a><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-button aligncenter\"><a class=\"wp-block-button__link\" href=\"https:\/\/hackmethod.com\/overthewire-narnia-4\/\">Narnia Level 4 <\/a><\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Welcome back! Now that we&#8217;ve conquered Level 2 and gained the password for Level 3 it&#8217;s time to keep pressing. Introduction Same thing from before. Log into the lab server as Narnia3 and look at the source code for narnia3.c. \/* This program is free software; you can redistribute it and\/or modify it under the [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":1842,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[52,49],"tags":[165,163,162,45,50,164],"class_list":["post-7477","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hacking","category-tutorials","tag-buffer-overflow","tag-level-3","tag-narnia","tag-overthewire","tag-tutorial","tag-walkthrough"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/hackmethod.com\/wp-content\/uploads\/2016\/01\/NarniaImage.jpeg?fit=600%2C400&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5zY4D-1WB","_links":{"self":[{"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/posts\/7477","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/comments?post=7477"}],"version-history":[{"count":15,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/posts\/7477\/revisions"}],"predecessor-version":[{"id":21610,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/posts\/7477\/revisions\/21610"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/media\/1842"}],"wp:attachment":[{"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/media?parent=7477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/categories?post=7477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackmethod.com\/wp-json\/wp\/v2\/tags?post=7477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}