| < Threats, Techniques & Processor Execution Environment | BOF Main Page | C Function Call, Stack & The Shellcode > |


 

 

 

 

 

CHAPTER THREE:

PREPARING THE VULNERABLE ENVIRONMENT

 

 

 

 

 

 

What are in this section?

3.1   Introduction

3.2   The Specifications

3.3   Vulnerable Environment Preparation

3.3.1   Disabling the SELinux

3.3.2   Non-Executable Stack and Address Space Randomization

3.4   Preparing the Vulnerable Code

 

 

3.1    Introduction

 

The methodology used will be an experiment of escalating a normal user to root privilege by exploiting a buffer overflow that exists in a vulnerable program in a controlled environment. The flow of event during the demonstration will be analyzed and the analysis uses a reverse engineering technique.

First of all a vulnerable environment will be created by disabling the SELinux and address space randomization. Using the Fedora 9 which was installed as a virtual guest OS on Windows XP Pro SP 2, a stack-based buffer overflow program will be created and exploited. The vulnerable code (bofvulcode.c) is a typical setuid type C program that is owned by root but executable by user which will have a strcpy() function that vulnerable to a stack-based buffer overflow. Without any bound checking mechanism implemented, implicitly or explicitly, the buffer declared in the program which will be used by strcpy() function will be over flown with more bytes than it can hold. The last extra bytes will be precisely overwriting the return address of the function and this address is pointing to the environment variable that contains the shellcode (eggcode.c). This shellcode will act as the payload which contains setuid(0) and spawning shell operations. Another simple code (findeggaddr.c) will be used to find the address of the shellcode stored in the environment variable.

Briefly, the following flow of event will be demonstrated, observed, documented and analyzed.

 

  1. Preparing the vulnerable environment.

  2. Preparing the vulnerable code.

  3. Generate and test the shellcode which will act as the exploit payload.

  4. Storing the shellcode in the environment variable.

  5. Finding the address of the shellcode.

  6. setuid the vulnerable program.

  7. Run the vulnerable program.

 

3.2    The Specifications

 

The hardware and software specifications used in this controlled demonstration are listed below. Knowing the specifications is important because the compiled and exploit code should match the architecture, though the source code could be similar.

 

1.      Fedora 9 as guest OS on Win XP Pro SP2 (VMware 6.0.4).

2.      Intel x86 platform.

3.      Linux kernel 2.6.25-14.fc9.i686.

4.      GNU C Library, glibc 2.8-3.i686.

5.      GNU Compiler Collection, GCC 4.3.0 RedHat 4.3.0-8.i386.

6.      GNU Debugger, gdb 6.8-1.fc9.i386.

7.      GNU Assembler, as 2.18.50.0.6 (i386-redhat-linux).

8.      Login as normal user (amad).

9.      Using setuid program with strcpy() function as a vulnerable program.

10. It is a local exploit.

11. All the related debuginfo packages [57] were installed.

 

Take note that by using the Fedora 9 as a virtual machine, the 'reaction' of the OS against the buffer overflow for virtual machine can also be observed mainly from the memory management aspect.

 

3.3    Vulnerable Environment Preparation

 

There are already several general buffer overflow protections implemented on the Fedora 9. In this demonstration, the protections will be disabled in order to create a system wide vulnerable environment. Furthermore, by showing this, the current buffer overflow detection and prevention implementations can be explored. However this will be minimized in order to see only the related protections that are really in effect. Take note that protection mechanism is specific to this demonstration environment and others may be different. Some Linux distro for instance has its own patches for hardening the system which include the buffer overflow protection as can be found for Debian [58].

 

3.3.1   Disabling the SELinux

 

SELinux enforces mandatory access control policies on OS. The policies restrict and control user programs and system daemons (services) to just the minimum amount of privilege they need to complete their tasks.

Firstly, the SELinux [59] will be disabled to create a system wide vulnerable. In this case as root, SELinux will be disabled permanently by editing the /etc/sysconfig/selinux file and changing the SELINUX=permissive setting to SELINUX=disabled and then reboot the machine. The following Figure shows the selinux file content screen snapshot after the SELinux has been set to disabled.

 

Disabling the SELinux permanently by editing /etc/sysconfig/selinux file

 

Figure 3.1: Disabling the SELinux permanently by editing /etc/sysconfig/selinux file

 

Screenshot for /etc/sysconfig/selinux file content

 

Figure 3.2: Screenshot for /etc/sysconfig/selinux file content

 

Optionally, SELinux can be disabled temporarily by executing the setenforce 1 (Permissive) command. The getenforce command can be used to check the status. However to set it to disabled, the /etc/sysconfig/selinux file need to be edited manually. The following steps show the getenforce and setenforce command examples.

[root@localhost bin]# getenforce

Enforcing

[root@localhost bin]# setenforce 0

[root@localhost bin]# getenforce

Permissive

[root@localhost bin]# setenforce 1

[root@localhost bin]# getenforce

Enforcing

[root@localhost bin]#

3.3.2   Non-Executable Stack and Address Space Randomization

 

The exec-shield that makes the stack non-executable will be disabled so that the injected shellcode in the stack can be run and the ASLR that provides the randomness to the layout of the virtual memory space will also be disabled in order to provide fixed addresses of the memory space. Take note that if the exploit does not depend on the address randomization, this step is 'useless'. In order to disable it temporarily do the following steps:

su -

Password: (your root password)

#/sbin/sysctl -w kernel.exec-shield=0

#/sbin/sysctl -w kernel.randomize_va_space=0

 

[root@localhost ~]# /sbin/sysctl -w kernel.exec-shield=0

kernel.exec-shield = 0

[root@localhost ~]# /sbin/sysctl -w kernel.randomize_va_space=0

kernel.randomize_va_space = 0

[root@localhost ~]#

The exec-shield can be disabled permanently by editing the /etc/sysctl.conf file and adding the following lines. This task may need a system reboot.

kernel.exec-shield=0

kernel.randomize_va_space=0

Figure 3.3 shows the sysctl.conf file content screen snapshot.

 

Disabling exec-shield for address space randomization by editing the sysctl.conf file

 

Figure 3.3: Disabling exec-shield for address space randomization by editing the sysctl.conf file

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.4    Preparing the Vulnerable Code

 

The vulnerable program (bofvulcode.c) is shown below. This code contains strcpy() function which is a public knowledge, vulnerable to the stack-based buffer overflow if not properly used. strcpy() does not do the bound checking for the destination buffer while copying data.

This program will receive an input from the second command line argument, argv[1]. The mybuff buffer, which is the destination buffer of the strcpy() parameter will be over flown. Then, the strcpy() return address can be 'precisely' overwritten with an address which point to the new address. Hopefully after finish copying the string from the command line argument, the program execution flow will be re-directed to the new return address instead of returning to main().

[amad@localhost projectbof11]$ cat bofvulcode.c

/* bofvulcode.c */

#include <unistd.h>

 

int main(int argc, char **argv)

{

  /* declare a buffer with max 512 bytes in size*/

  char mybuff[512];

 

  /* verify the input */

  if(argc < 2)

  {

    printf("Usage: %s <string_input_expected>\n", argv[0]);

    exit (0);

  }

  /* else if there is an input, copy the string into the buffer */

  strcpy(mybuff, argv[1]);

  /* display the buffer's content */

  printf("Buffer's content: %s\n", mybuff);

  return 0;

}

[amad@localhost projectbof11]$

The bofvulcode code screenshot

 

Figure 3.4: The bofvulcode code screenshot

 

Without any null byte as string terminator within the 512 and/or the input is more than 512 bytes, or any bound checking mechanism implemented explicitly, the 512 bytes buffer can be over flown. The extra string still be stored in the strcpy()’s stack frame, however without any protection mechanism, this extra string will overwrite the adjacent data in the allocated buffer.

As declared in the program, the buffer (array) in the program is 512 bytes long. If there is a string input, the program will copy the argument into the buffer. In the following steps, the program is tested with several number of string inputs. In this case the Perl command was used to stuff "A" characters into the buffer (the Ruby and other similar commands also can be used).

[amad@localhost projectbof11]$ gcc -g -w bofvulcode.c -o bofvulcode

[amad@localhost projectbof11]$ ./bofvulcode `perl -e 'print "A"x508'`

Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

[amad@localhost projectbof11]$ ./bofvulcode `perl -e 'print "A"x512'`

Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

[amad@localhost projectbof11]$ ./bofvulcode `perl -e 'print "A"x516'`

Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Segmentation fault

[amad@localhost projectbof11]$

Running the bofvulcode program with three different inputs

 

Figure 3.5: Running the bofvulcode program with three different inputs

 

The increment of 4 bytes were used in the example because of the word alignment of the memory for 32 bit system (4 bytes x 8 bits = 32 bits = 1 word). When the input is 516 bytes (4 bytes extra), the program exit with Segmentation fault.

By debugging the core dump file, what actually happened when inputting more than 512 bytes of string can be observed. Firstly, set the core dump file if needed. Then, re-run the program with more than 512 bytes of string input.

[amad@localhost projectbof11]$ ulimit -c unlimited

[amad@localhost projectbof11]$ ./bofvulcode `perl -e 'print "A"x516'`

Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Segmentation fault (core dumped)

[amad@localhost projectbof11]$

 

[amad@localhost projectbof11]$ ls -l

total 232

-rwxrwxr-x 1 amad amad   6536 2008-09-27 00:39 bofvulcode

-rwxr-xr-x 1 amad amad    470 2008-09-27 00:36 bofvulcode.c

-rw-r--r-- 1 amad amad    468 2008-09-27 00:28 bofvulcode.c~

-rw------- 1 amad amad 155648 2008-09-27 00:54 core.2986

-rwxr-xr-x 1 amad amad    640 2008-09-27 00:02 egg1.c

-rwxr-xr-x 1 amad amad    640 2008-09-27 00:02 egg1.c~

-rwxr-xr-x 1 amad amad     92 2008-09-27 00:02 eggfind.c

-rwxr-xr-x 1 amad amad     90 2008-09-27 00:02 eggfind.c~

-rwxr-xr-x 1 amad amad   1401 2008-09-27 00:02 info.txt

-rwxr-xr-x 1 amad amad   1417 2008-09-27 00:02 info.txt~

-rwxr-xr-x 1 amad amad   7311 2008-09-27 00:02 steps.txt

-rwxr-xr-x 1 amad amad   7311 2008-09-27 00:02 steps.txt~

-rwxr-xr-x 1 amad amad    528 2008-09-27 00:02 testshell.c

-rwxr-xr-x 1 amad amad    528 2008-09-27 00:02 testshell.c~

-rwxr-xr-x 1 amad amad    528 2008-09-27 00:02 testshellmercy.c

-rwxr-xr-x 1 amad amad    509 2008-09-27 00:02 testshellmercy.c~

-rwxr-xr-x 1 amad amad     95 2008-09-27 00:02 turnfullroot.c

Creating the core dumped file

 

Figure 3.6: Creating the core dumped file

 

 

Next, use the gdb to view the core dump file (core.2986 in this case) and the content of the registers when the segmentation fault happened.

[amad@localhost projectbof11]$ gdb -c core.2986 bofvulcode

GNU gdb Fedora (6.8-1.fc9)

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.  Type "show copying" and "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...

 

warning: Can't read pathname for load map: Input/output error.

Reading symbols from /lib/libc-2.8.so...Reading symbols from /usr/lib/debug/lib/libc-2.8.so.debug...done.

done.

Loaded symbols for /lib/libc-2.8.so

Reading symbols from /lib/ld-2.8.so...Reading symbols from /usr/lib/debug/lib/ld-2.8.so.debug...done.

done.

Loaded symbols for /lib/ld-2.8.so

Core was generated by `./bofvulcode AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.

Program terminated with signal 11, Segmentation fault.

[New process 2986]

#0  0x080484b6 in main (argc=Cannot access memory at address 0x41414141

) at bofvulcode.c:20

20   }

(gdb)

(gdb) info reg

eax            0x0 0

ecx            0x41414141    1094795585

edx            0x2950d0 2707664

ebx            0x293ff4 2703348

esp            0x4141413d    0x4141413d

ebp            0xbffff200    0xbffff200

esi            0x0 0

edi            0x8048370     134513520

eip            0x80484b6     0x80484b6 <main+146>

eflags         0x10286  [ PF SF IF RF ]

cs             0x73 115

ss             0x7b 123

ds             0x7b 123

es             0x7b 123

fs             0x0 0

gs             0x33 51

(gdb)

The core dumped file content

 

Figure 3.7: The core dumped file content

 

Viewing the content of registers

 

Figure 3.8: Viewing the registers contents

 

Take note that from this paragraph and that follows must be cross referenced with the information discussed in section 2.5 and 2.6 for better understanding on the stack construction and destruction mechanisms.

The eip (instruction pointer) is pointing to (holding) the address of 0x41414141 ("AAAA"). This eip hold the return address, however, this is not a valid address anymore. To have the detail, the basic stack memory layout for x86 Linux is shown in the following Figure when the standard function call in C was invoked. This is important in determining the exact return address in the stack. This stack frame will be constructed when a function call was triggered. The frame is bounded by the stack frame pointer (ebp) at the bottom and the stack pointer (esp) at the top. The return address, pointed to or hold by the instruction pointer (eip = ebp + 4) will be pushed into the stack after the arguments. During the execution the stack frame may shrink and grow and after the function call completed, the return address will be used to return to the caller and program execution continues. Then, the stack frame will be destroyed, releasing the memory to the system for other use. A simple idea is, if the return address can be changed, the program execution flows also can be changed.

 

A typical stack frame layout for C function call

Figure 3.9: A typical stack frame layout for C function call

 

Referring to Figure 3.9, when the buffer was over flown by 4 more bytes after the ebp (ebp + 4), the eip that hold the return address can be overwritten. Let verify this statement by re-running the previous vulnerable program with 8 more bytes than the buffer can hold.

[amad@localhost projectbof11]$ ./bofvulcode `perl -e 'print "A"x520'`

Buffer's content: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAA

Segmentation fault (core dumped)

[amad@localhost projectbof11]$ ls -l

total 388

-rwxrwxr-x 1 amad amad   6536 2008-09-27 00:39 bofvulcode

-rwxr-xr-x 1 amad amad    470 2008-09-27 00:36 bofvulcode.c

-rw-r--r-- 1 amad amad    468 2008-09-27 00:28 bofvulcode.c~

-rw------- 1 amad amad 155648 2008-09-27 00:54 core.2986

-rw------- 1 amad amad 155648 2008-09-27 01:01 core.3000

-rwxr-xr-x 1 amad amad    640 2008-09-27 00:02 egg1.c

-rwxr-xr-x 1 amad amad    640 2008-09-27 00:02 egg1.c~

-rwxr-xr-x 1 amad amad     92 2008-09-27 00:02 eggfind.c

-rwxr-xr-x 1 amad amad     90 2008-09-27 00:02 eggfind.c~

[Trimmed]

-rwxr-xr-x 1 amad amad    528 2008-09-27 00:02 testshellmercy.c

-rwxr-xr-x 1 amad amad    509 2008-09-27 00:02 testshellmercy.c~

-rwxr-xr-x 1 amad amad     95 2008-09-27 00:02 turnfullroot.c

[amad@localhost projectbof11]$ gdb -c core.3000 bofvulcode

GNU gdb Fedora (6.8-1.fc9)

Copyright (C) 2008 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.  Type "show copying" and "show warranty" for details.

This GDB was configured as "i386-redhat-linux-gnu"...

 

warning: Can't read pathname for load map: Input/output error.

Reading symbols from /lib/libc-2.8.so...Reading symbols from /usr/lib/debug/lib/libc-2.8.so.debug...done.

done.

Loaded symbols for /lib/libc-2.8.so

Reading symbols from /lib/ld-2.8.so...Reading symbols from /usr/lib/debug/lib/ld-2.8.so.debug...done.

done.

Loaded symbols for /lib/ld-2.8.so

Core was generated by `./bofvulcode AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.

Program terminated with signal 11, Segmentation fault.

[New process 3000]

#0  0x080484b6 in main (argc=Cannot access memory at address 0x41413f39

) at bofvulcode.c:20

20   }

(gdb) info reg

eax            0x0 0

ecx            0x41414141    1094795585

edx            0x2950d0 2707664

ebx            0x293ff4 2703348

esp            0x4141413d    0x4141413d

ebp            0x41414141    0x41414141

esi            0x0 0

edi            0x8048370     134513520

eip            0x80484b6     0x80484b6 <main+146>

eflags         0x10286  [ PF SF IF RF ]

cs             0x73 115

ss             0x7b 123

ds             0x7b 123

es             0x7b 123

fs             0x0 0

gs             0x33 51

(gdb)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Generating the core dumped file

 

Figure 3.10: Generating the core dumped file

 

The core.3000 file content

 

Figure 3.11: The core.3000 file content

 

Viewing the content of processor registers

 

Figure 3.12: Viewing the registers contents

 

Viewing the dump core file content, with 8 more bytes, the ebp was completely and the eip was partially overwritten. The partially overwritten eip happened because of the stack boundary alignment. This issue will be resolved later and other related information that should be read together was discussed in section 2.5.3.2.

Well, if this return address can be overwritten, then the program’s flow can be controlled and pointed to other desired address. In this case, the eip was overwritten by "A" characters which does not represent a valid address where the program can continue execution. This is why the segmentation fault was generated.

With this knowledge, an address that would point to a new code and start a new program execution (the malicious one!) can be supplied. Figure 3.13 shows some of the creative ways that have been used and re-used in pointing the return address. In this demonstration, the environment variable will be used to store the shellcode.

 

Overwriting the return address and pointing to other location

Figure 3.13: Overwriting the return address and pointing to other location

 

 

 

 


 

| < Threats, Techniques & Processor Execution Environment | BOF Main Page | C Function Call, Stack & The Shellcode > |