{"id":11196,"date":"2021-05-14T14:33:06","date_gmt":"2021-05-14T14:33:06","guid":{"rendered":"http:\/\/www.max-sperling.bplaced.net\/?p=11196"},"modified":"2024-02-16T10:16:17","modified_gmt":"2024-02-16T10:16:17","slug":"crackmes-one-example-2","status":"publish","type":"post","link":"http:\/\/www.max-sperling.bplaced.net\/?p=11196","title":{"rendered":"crackmes.one (Example 2)"},"content":{"rendered":"<p><strong>Setup<\/strong><\/p>\n<p><u>Data<\/u><\/p>\n<ul>\n<li>URL: <a href=\"https:\/\/crackmes.one\/crackme\/5f05ec3c33c5d42a7c66792b\">BitFriends&#8217;s simple overflow<\/a><\/li>\n<li>Language: C\/C++<\/li>\n<li>Platform: Unix\/Linux (ELF64)<\/li>\n<li>Description: &#8220;This is a very simple crackme. The goal is to get &#8220;you are logged in as admin&#8221;. Patching is not allowed. The solution should contain an exact description, how this works. Have fun!&#8221;<\/li>\n<\/ul>\n<p><u>Output<\/u><\/p>\n<pre>\r\n$ .\/a.out\r\nenter password: pass\r\nuid: 1\r\nyou are logged in as user\r\n<\/pre>\n<hr>\n<p><strong>Analysis<\/strong><\/p>\n<p><u>Tools<\/u><br \/>\nCutter\/Radare2<\/p>\n<p><u>Disassembly<\/u> (Origin, Commented)<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n151: login ();\r\n; var char *s @ rbp-0x10\r\n; var void *var_8h @ rbp-0x8\r\n; Setup stack for function\r\n0x00001169      push    rbp\r\n0x0000116a      mov     rbp, rsp\r\n0x0000116d      sub     rsp, 0x10\r\n; Printf(&quot;enter password: &quot;)\r\n0x00001171      lea     rdi, str.enter_password: ; 0x2004 ; const char *format\r\n0x00001178      mov     eax, 0\r\n0x0000117d      call    printf     ; sym.imp.printf ; int printf(const char *format)\r\n; Malloc of chunk1 (password)\r\n0x00001182      mov     edi, 0x10  ; size_t size\r\n0x00001187      call    malloc     ; sym.imp.malloc ;  void *malloc(size_t size)\r\n0x0000118c      mov     qword [s], rax\r\n; Malloc of chunk2 (uid)\r\n0x00001190      mov     edi, 8     ; size_t size\r\n0x00001195      call    malloc     ; sym.imp.malloc ;  void *malloc(size_t size)\r\n0x0000119a      mov     qword [var_8h], rax\r\n; *chunk2 = 1\r\n0x0000119e      mov     rax, qword [var_8h]\r\n0x000011a2      mov     dword [rax], 1\r\n; Fgets(chunk1, 0xA0, stdin)\r\n0x000011a8      mov     rdx, qword [stdin] ; obj.stdin__GLIBC_2.2.5\r\n                                   ; 0x4050 ; FILE *stream\r\n0x000011af      mov     rax, qword [s]\r\n0x000011b3      mov     esi, 0xa0  ; int size\r\n0x000011b8      mov     rdi, rax   ; char *s\r\n0x000011bb      call    fgets      ; sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)\r\n; Printf(&quot;uid: %d\\n&quot;, *chunk2)\r\n0x000011c0      mov     rax, qword [var_8h]\r\n0x000011c4      mov     eax, dword [rax]\r\n0x000011c6      mov     esi, eax\r\n0x000011c8      lea     rdi, str.uid:__d ; 0x2015 ; const char *format\r\n0x000011cf      mov     eax, 0\r\n0x000011d4      call    printf     ; sym.imp.printf ; int printf(const char *format)\r\n; If (*chunk2 == 0)\r\n0x000011d9      mov     rax, qword [var_8h]\r\n0x000011dd      mov     eax, dword [rax]\r\n0x000011df      test    eax, eax\r\n0x000011e1      jne     0x11f1\r\n; Then puts(&quot;you are logged in as admin&quot;)\r\n0x000011e3      lea     rdi, str.you_are_logged_in_as_admin ; 0x201e ; const char *s\r\n0x000011ea      call    puts       ; sym.imp.puts ; int puts(const char *s)\r\n0x000011ef      jmp     0x11fd\r\n; Else puts(&quot;you are logged in as user&quot;)\r\n0x000011f1      lea     rdi, str.you_are_logged_in_as_user ; 0x2039 ; const char *s\r\n0x000011f8      call    puts       ; sym.imp.puts ; int puts(const char *s)\r\n0x000011fd      nop\r\n0x000011fe      leave\r\n0x000011ff      ret\r\n<\/pre>\n<p><u>Decompiled<\/u> (Commented)<\/p>\n<pre class=\"brush: cpp; gutter: false; title: ; notranslate\" title=\"\">\r\nvoid login(void)\r\n{\r\n    undefined8 uVar1;\r\n    int32_t *piVar2;\r\n    char *s;\r\n    void *var_8h;\r\n    \r\n    printf(&quot;enter password: &quot;);\r\n    uVar1 = malloc(0x10);\r\n    piVar2 = (int32_t *)malloc(8);\r\n    *piVar2 = 1;\r\n    fgets(uVar1, 0xa0, _reloc.stdin);\r\n    printf(&quot;uid: %d\\n&quot;, *piVar2);\r\n    if (*piVar2 == 0) {\r\n        puts(&quot;you are logged in as admin&quot;);\r\n    } else {\r\n        puts(&quot;you are logged in as user&quot;);\r\n    }\r\n    return;\r\n}\r\n<\/pre>\n<p><u>Conclusion<\/u><br \/>\nTo become a admin the uid (chunk2) has to be zero. A buffer overflow attack is possible cause the fgets reads more (0xA0) then the size of the password buffer (0x10). The important thing to know is that the chunk size on the heap for a x64 machine is 32 (0x20) bytes. For both password and uid one chunk is enough. It&#8217;s not garantueed, but most likely, that these two chunks are right behind one another. By the way the missing frees leading to memory leaks.<\/p>\n<p>The memory layout on the heap most likely looks like this:<\/p>\n<pre>\r\n... | password (chunk1, 0x20 bytes) | uid (chunk2, 0x20 bytes) | ...\r\n<\/pre>\n<p>In my test example (entered &#8216;pass&#8217;) it would look like this:<\/p>\n<pre>\r\n... | x70x61x73x73x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 | \r\n      x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00 | ...\r\n<\/pre>\n<hr>\n<p><strong>Solution<\/strong><\/p>\n<p><u>Overflow<\/u><br \/>\nInsert a string that contains 32 (0x20) bytes of anything to fill the password (chunk1) and then a 0x00 to replace the 0x01 of the uid (chunk2). Let&#8217;s use a string with 31 (0x21) times the value of 0x00.<\/p>\n<p><u>Output<\/u><\/p>\n<pre>\r\n$ python -c 'print(\"\\x00\" * 31)' | .\/a.out\r\nenter password: uid: 0\r\nyou are logged in as admin\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Setup Data URL: BitFriends&#8217;s simple overflow Language: C\/C++ Platform: Unix\/Linux (ELF64) Description: &#8220;This is a very simple crackme. The goal<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false},"categories":[39],"tags":[],"_links":{"self":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/11196"}],"collection":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11196"}],"version-history":[{"count":1,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/11196\/revisions"}],"predecessor-version":[{"id":16711,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/11196\/revisions\/16711"}],"wp:attachment":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11196"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11196"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}