SECURITY SANDBOXING FOR PC2: WINDOWS VERSION

A Project

Presented to the faculty of the Department of Computer Science

California State University, Sacramento

Submitted in partial satisfaction of the requirements for the degree of

MASTER OF SCIENCE

in

Computer Science

by

Parita Shah

SPRING 2017

SECURITY SANDBOXING FOR PC2: WINDOWS VERSION

A Project

by

Parita Shah

Approved by:

______, Committee Chair Dr. John Clevenger

______, Second Reader Dr. V. Scott Gordon

______Date

ii

Student: Parita Shah

I certify that this student has met the requirements for format contained in the University format manual, and that this project is suitable for shelving in the and credit is to be awarded for the project.

______, Graduate Coordinator ______Dr. Jinsong Ouyang Date

Department of Computer Science

iii

Abstract

of

SECURITY SANDBOXING FOR PC2: WINDOWS VERSION

by

Parita Shah

The purpose of a Sandbox software is to execute a program under restricted environment to protect a computer system from malicious activities. The Security Sandbox tool will be developed to be used for the Programming Contest Control System, called PC2 for short. PC2 software is used to support programming contests of ACM and its

International Collegiate Programming Contests around the world. PC2 allows teams to submit their programs to the judges over the network. The judges can perform manual judging for the team’s submitted program. PC2 also supports automatic judging of these submitted programs. These are a few of the many functionalities of PC2.

When teams submit their programs for judging, their code might perform malicious activities on the system that is running the judging module. Opening a network socket, accessing important or personal files, running a script to delete files, trying to hamper working of PC2, etcetera are a few examples of the illegal activities that the team’s programs could do to harm the judge’s system. Sandbox will keep a check on all the activities that the team’s program does during its execution and will stop the execution of iv the program as soon as it finds that it is performing an illegal activity. It will fulfill its task by inspecting all system calls made by the team’s program. The list of permissible or non- permissible system calls will be provided to the Sandbox by the judges ahead of time, in the form of a policy file. Apart from team’s submitted programs, Sandbox should also be able to run any executable file, as a target program provided to it by PC2 and return its result. One of the other major features of Sandbox will the Input/Output Forwarding of data from PC2 to this target program and vice versa.

The deliverables of the project will be a Sandbox Software running on Windows and a report on the various details of this project.

______, Committee Chair Dr. John Clevenger

______Date

v

ACKNOWLEDGEMENTS

I would like to thank my professor, Dr. John Clevenger for his continuous support and encouragement during my research for this project. He helped me throughout the journey of the project development without which this project could not have reached its destination.

I also would like to thank Dr. Scott Gordon for fulfilling his role as a second reader and helping me in the completion of this project.

I would like to thank my husband, family and friends who have given me enormous strength, support and encouragement throughout my research and development for this project.

vi

TABLE OF CONTENTS

Page

Acknowledgements ...... vi

List of Figures ...... ix

Chapter

1. INTRODUCTION ...... 1

1.1 Programming Contest Control System ...... 1

1.2 Problem Description ...... 2

1.3 Sandbox definition ...... 2

2. EXISTING TECHNOLOGIES ...... 4

2.1 Sandboxes available in market ...... 4

2.1.1 Virtual Machines ...... 4

2.1.2 Cuckoo Sandbox ...... 4

2.1.3 Sandboxie ...... 6

2.1.4 Chromium Sandbox ...... 7

2.1.5 Security Sandbox for PC2: Version ...... 8

2.2 DLL Injection and API Hooking ...... 8

2.3 Conclusion ...... 11

vii

3. SANDBOX FOR PC2: SOFTWARE DESIGN AND APPROACH ...... 13

3.1 Design Flow ...... 13

3.1.1 PC2 ...... 13

3.1.2 Sandbox.exe ...... 14

3.1.3 Target program / Team Program / Child of Sandbox ...... 14

3.1.4 Policy File ...... 15

3.1.5 Log File...... 15

3.2 Use Case Diagram ...... 16

4. DLL INJECTION AND HOOKING IMPLEMENTATION ...... 18

4.1 Example: Blocking CreateFileA and DeleteFileA ...... 19

5. CHARACTERISTICS, LIMITATIONS AND FUTURE ENHANCEMENTS ...... 26

5.1 Characteristics ...... 26

5.2 Limitations ...... 27

5.3 Future Enhancements ...... 28

6. CONCLUSION ...... 30

Appendix A Source Code ...... 31

Bibliography ...... 55

viii

LIST OF FIGURES

Figures Page

1. Cuckoo Sandbox Architecture ...... 5

2. Steps of DLL Injection...... 9

3. Sandbox Data Flow Diagram ...... 13

4. Use Case Diagram...... 16

5. Policy File Creation GUI ...... 20

6. Policy File screenshot ...... 20

7. Log File screenshot ...... 25

ix

1

1. INTRODUCTION

1.1 Programming Contest Control System

PC2 is the abbreviation for Programming Contest Control system, pronounced as

"P-C-squared" or "P-C-Two". This software was developed at California State University,

Sacramento and it is designed to conduct programming contest operations on various computer environments. This software can support a programming contest occurring at multiple sites. It supports heterogeneous platform operations which includes Windows and

Linux Operating systems. It is also dynamic and can send updates in real-time regarding the contest status to all the sites. [1]

PC2 uses a client-server architecture for its operation [2]. When a contest is set up on a site, one PC2 server is configured per contest site which will administer the contest at that particular site. There are also multiple clients configured which communicate with that

PC2 server. A client can perform one of several roles using different types of accounts such as, Administrator, Team, Scoreboard or Judge. These clients will communicate with their respective site servers only.

The system takes the contestants’ (teams) programs as input and sends it to the contest judges over a network via TCP/IP. Once the team’s submitted program reaches the judges, they can judge it manually by compiling and executing the code. As an alternative,

2 the can also use the PC system for judging. After this they can send a response back to the team.

2

1.2 Problem Description

The PC2 runs the team’s program or target program on judge’s local machine. There is a chance that this target program will attempt to run some code which can harm the judge’s system in some way. For example, the program might try to open some files on the judge’s system or try to delete them. It might try to open a network socket to connect to the internet to download some virus or run a harmful script. It is very important that the target program that is going to be run on the judge’s system be checked to verify that it does not perform any such illegal activity.

1.3 Sandbox definition

In general terms, a Sandbox is an isolated test environment where you can restrict the actions of certain code changes so that the results do not affect the whole system on which the code will run. For example, programmers create a local copy of the code on their system. They can perform all the tests on this local copy to check the outcome and behavior of code. Once they agree upon all the changes they have made on the local copy, they can push these changes on the live servers. In this way, if any changes in code cause any damage, it can be identified on a local system before it affects data on the server. We are going to use this concept of sandboxing in order to predict the behavior of a program before it causes any damage to the judge’s local system.

In our case, a team’s program is going to run on the judge’s system through the PC2 judging module, and its behavior is unknown to the judges. There is a chance that the program might cause harm to judge’s system, access personal data from the system or

3

perform any action that is not permitted to them as participants of the programming contest.

By creating a Sandbox, we create an environment where we can stop any illegal activity performed by the team’s program on the judge’s system.

When a program is run on any system, it makes some system calls in user mode.

Creating or deleting a file, opening a network socket and writing to a file are examples of such system calls. The Sandbox will monitor these system calls made by the target program and match them against the non-permissible system calls specified in the policy file. It will stop the execution of the target program if it tries to execute any illegal system call.

The target program here can be any executable that can be invoked through the command line. It can be an executable created by compiling the team’s submitted program or just any executable file that you want to run within a restricted environment.

4

2. EXISTING TECHNOLOGIES

2.1 Sandboxes available in market

There are many open and closed source Sandbox software programs available in the market. For example, most web browsers like Mozilla Firefox, and

Google Chrome run the code embedded in the web pages, in a Sandbox. The Sandbox restricts the web pages from accessing certain resources on the underlying system.

Accessing files on a system, opening a webcam without the user’s permission and running illegal scripts are a few things the Sandbox can protect the user’s system from [3].

Sandboxes have also been developed to run as stand-alone applications on

Windows and Linux Systems. For example, Adobe Reader runs a PDF file in Sandbox mode.

2.1.1 Virtual Machines

VirtualBox [4] and VMware [5] are examples of Virtual Machine programs that create a virtual environment on your system. This includes creating virtual hardware devices that can be used to run an which will reside on your system. Any program or software can be run on this setup and its behavior can be analyzed. This way, the whole Operating system is sandboxed and nothing that is run inside the Sandbox will affect the actual system on which the Virtual Machine is installed.

2.1.2 Cuckoo Sandbox [6]

Cuckoo is a software designed to protect the system from Malware. Malware can be any suspicious files or programs that can harm your system. Cuckoo Sandbox will

5

analyze these files and provide back detailed results showing their behavior when they were executed in an isolated Sandbox. Apart from malicious files like executables, Java scripts and documents, Cuckoo can also analyze malicious websites. It can also trace system calls made during the execution of a certain program. There are many other features of Cuckoo Sandbox including modularity in design, allowing the user to customize software according to user needs.

Cuckoo Sandbox is an open source freely available software which can run any file under Windows, Linux, Android or OS X operating systems. The image below describes the architecture of Cuckoo Sandbox:

Figure 1 Cuckoo Sandbox Architecture [7]

6

As seen in the figure above, Cuckoo Sandbox is comprised of a central host that manages all the analysis, transferring data to the guest machines and generating logs after the analysis. Meanwhile, the actual analysis is launched in an isolated Virtual Machine created by Cuckoo, which acts as the Guest system. These virtual machines are the location where the malware is run safely followed by the analysis of the execution. Executing the malware in a separate environment guards the actual Host system from the effects that can be caused by the malware.

The designers of the software recommend using Linux/GNU, Mac operating systems on the host system for Cuckoo Sandbox setup and execution. Windows XP Service

Pack 3, or are the recommended operating systems to be used on guests.

2.1.3 Sandboxie [8]

Sandboxie is essentially a closed-source software that will isolate the target program from the Operating system. Isolating the memory on which it runs the program, it protects the personal data, files and other programs running on that system that are not

Sandboxed.

Sandboxie creates an isolated section of memory in which the target program makes its changes. By analyzing the output in this isolated space, Sandboxie will inform the user if it notices any suspicious activity. If the target program tries to perform any illegal activity, it will be within the Sandboxie protected area and thus will not affect the system on which it is running in any way.

7

If any web-browser is run in Sandboxie, it will protect the system by blocking viruses, corrupt scripts, phishing attacks and ransomware that can be run on a user’s system by malicious web-pages and emails. It will also stop websites from retrieving any data from your system. Windows applications can also be run in Sandboxie and illegal changes made by them on the underlying system can be prevented.

2.1.4 Chromium Sandbox [9]

The Chromium Sandbox was primarily designed to sandbox the processes running on Chromium browser, but can be modified by users to make their own Sandbox implementations. It has different implementations for Windows, Linux and Mac OS X.

Since our project is about implementing Sandbox for Windows OS, we shall only discuss the Windows implementation of Chromium Sandbox.

Chromium is somewhat similar to Cuckoo Sandbox in that the code or program that requires sandboxing runs as a different process than the main program that controls all the sandboxing operations. The main process is called the broker process which is the browser process. It basically supervises all the activities of Chromium Sandbox such as defining policy for a target process, create a process for target program and hosting various services.

Meanwhile, the target process executes the code to be sandboxed and intercepts the function calls for the broker process to decide how to treat them using Inter-Process

Communication (IPC). The broker process can choose to either execute the function calls made by target program or fail them, depending on the policy.

8

Chromium Sandbox makes use of primary security provided by operating system and allows non-threatening code to execute without any restriction. By changing the properties related to any process, the sandbox can restrict the access of that target process to various resources like I/O devices, memory, screen and etcetera. Any system calls made by the program on a Windows platform for accessing these resources pass through security check and it is the task of Sandbox to set up things for these security checks to fail the system calls not permitted to the target process.

2.1.5 Security Sandbox for PC2: Linux Version [10]

A Linux version of Security Sandbox for PC2 has already been developed by

Adithya, Vikram Chidanand in 2011 as his M.S. project at California State University,

Sacramento. This software is a working model of a Linux based Sandbox i.e. it can be executed only on Linux based platforms.

The goal of this Sandbox is exactly the same as our goal. It intercepts the system calls made by the target program and checks them against a policy file to prohibit unauthorized system calls. The security sandbox will be deployed on the judge’s or administrator’s system of PC2 and will protect their system from any harm that can be potentially caused by team’s program or any other target program.

2.2 DLL Injection and API Hooking

Inserting code into the memory of a running process is defined as DLL Injection.

This code can be in the form of an executable file, any handwritten code or usually a

9

Dynamic Link Library (DLL). DLLs can be injected into a program and then can be loaded dynamically during run-time.

DLL Injection can be divided into 4 steps as displayed below:

Figure 2 Steps of DLL Injection [11]

The first step of the DLL injection process is to create a process for the code to be injected, with appropriate access rights so that we can work with it later. Next we need to allocate some memory into this newly created process. Within this memory, we can either inject the whole DLL or its full path. By injecting only the path and not the whole DLL itself, we can save some memory of the process. The address of the path of the DLL is now

10

passed as a parameter to a function called ‘LoadLibraryA’. This function is a part of

Kernel32.dll [12] file which is one of the dynamic-link libraries supported by Windows

Operating System. This DLL file can be copied into a processes’ memory at runtime to execute the required APIs, contained in it. By creating a new remote in the last step, we can run the LoadLibraryA module which will in turn load our DLL. There are many programming techniques, discussed in the subsequent chapters that can help achieve the discussed steps.

API hooking is a method of intercepting a system/function calls and alter their behavior by executing another code instead of the original routine. Data that is passed to user mode function call can also be extracted by intercepting it before it is actually executed by the kernel. For example, we can intercept a system call to open a particular file to see which user made the system call, which file the user wants to open and whether the file was being opened for reading or writing. The code that is inserted to handle all these details is known as a hook. API hooking can be performed on both Linux and Windows operating systems.

API Hooking can be done before executing a particular application by modifying any executable code or library. Alternatively, it can also be done during the runtime of a process (provided user has proper permission for it). [13] Windows and Linux provide features where the user can insert hooks to modify execution of events. For Runtime modification of functions, the first few instructions of the target function are changed to jump to the location of the injected code.

11

2.3 Conclusion

Our goal is to stop any events or operations that can harm the judge’s local system.

Moreover, we only want to stop the unauthorized events produced by the target program.

No other program running on the system should be affected in any way due to our Sandbox.

Monitoring all the programs running on the system can affect the performance of the system. Currently, Cuckoo Sandbox has a limitation of being deployed only on systems running Linux. Our goal for Sandbox is to create a software than can be deployed on

Windows system. Moreover, Cuckoo Sandbox and Sandboxie rely on an architecture where they need to run the target programs on guest Virtual systems. We wanted an approach that does not rely on a Virtual Machine for target program execution. Chromium

Sandbox accesses the target process information and manipulates that information to restrict the target process from using the underlying system’s resources. This needs a very deep knowledge of how Windows OS tokens work and how to manipulate them. We are going to use a simpler procedure for our Sandbox.

There are technologies available which can log events performed by applications in user mode. Event Tracing for Windows or ETW [14] is an example of such a facility.

But ETW will only be able to log the events after the execution of the target program is completed. This method could not have achieved our goal to stop the illegal system calls as and when they occur.

The approach that we are going to go forward with, will look after the user mode function calls on the judge’s system made by the target program. By using the combination

12

of DLL Injection and API Hooking, we will inject a library file with hooked APIs that will modify the execution of our target process according to our requirement. We will see in the further chapters how we will achieve our goal.

13

3. SANDBOX FOR PC2: SOFTWARE DESIGN AND APPROACH

3.1 Design Flow

The various components of the software design and the flow of data amongst them is presented in the following flow chart:

Figure 3 Sandbox Data Flow Diagram

Let us look at the various components of our software model in detail.

3.1.1 PC2

PC2 software is comprised of various modules. It will invoke the Sandbox process from a command line and provide various arguments that will be needed for sandboxing the team program. These arguments include the executable form of the target program, the path of the Policy File and the arguments required for the target program to run. All the arguments and their functionalities are explained in detail below.

14

3.1.2 Sandbox.exe

Sandbox.exe will be a precompiled executable file which performs many important functions. First of all, it will create a child process using the CreateProcess API [15] and begin the execution of team/target program. Also, the code to inject the DLL file into the process space of target program will be a part of the Sandbox code. The DLL file and its contents will be explained in the subsequent chapters.

Since the target program will be a child process of the Sandbox program, the

Sandbox process will be completed only after the completion of the target program.

3.1.3 Target program / Team Program / Child Process of Sandbox

The target program will also be an executable file and one of the arguments that

PC2 will pass on to Sandbox. This program can be any executable file that needs to be

Sandboxed. During a programming contest, the competing team’s compiled program passed by the judges will be our target program. The executable program will be invoked by the Sandbox process as its child process. All the data needed by this child process will be passed to it through the input channel between itself and its parent process i.e. the

Sandbox process.

Once the target program process completes its execution, the Sandbox program execution will also end.

15

3.1.4 Policy File

Policy File contains a list of non-permissible system calls for the target program. A

GUI will be provided to the judges which will have a list of system calls that they can currently choose from.

The judges can check the checkbox against the name of the system call that they want to stop the target program from executing. When the judge will click on the ‘Create’ button, all the names of the system calls checked on the GUI will be written onto a text file named ‘PolicyFile.txt’. When the Sandbox process will invoked by PC2, the path to this policy file will be provided as one of its arguments.

When Sandbox detects a system call by the target process, it will check if that system call is mentioned in the policy file and do the needful as described in the next chapter.

3.1.5 Log File

When Sandbox runs the target program as its child process, it will keep track of all the system calls the target program makes. Sandbox will match each system call with the list of unauthorized system calls mentioned in the Policy File. If any of the system calls made by the target program is listed in the Policy File, Sandbox will not only stop that system call from executing but will also print the names of such system call in a Log File.

Note that the target program execution will still complete but the illegal system calls will be suppressed and not be executed.

16

This Log File named ‘LogFile.txt’ will be saved in the same directory where your

Sandbox program resides. Judges can open this Log File at the end of the execution of

Sandbox to see the list of system calls that were made by the target program that it was not allowed to make.

3.2 Use Case Diagram

The following is the Use Case Diagram for the project:

Figure 4 Use Case Diagram

As demonstrated in the above use case diagram, Judge/Administrator creates the

Policy File and uses PC2 to invoke the Sandbox program. Meanwhile the team’s program

17

will be used as a target program for the Sandbox. This target program can also be any other executable program which needs to be Sandboxed. When the Sandbox program is invoked, it creates a child process from the target program executable. Sandbox process uses the policy file to decide which functions are marked illegal by the judges. So, when the target program process tries to make any of these illegal functions, Sandbox will suppress these calls by stopping their execution and note these functions in a Log File.

The flow diagram and the use case diagram give an overview of how the basic process of Sandboxing looks like. The magnified details about how Sandbox accomplishes the task of stopping the execution of unauthorized calls is explained in the next chapter with an example.

18

4. DLL INJECTION AND HOOKING IMPLEMENTATION

Sandbox process will be initiated when judging module of PC2 runs a command including the full path and name of the policy file, target program and all arguments needed for the target program to run. Now, there are 2 modules of this whole project. One module is when the Sandbox process runs and starts execution of its child process i.e. the target program. As we shall see later in this chapter, Sandbox will inject a DLL file into this child process. So, the second module is the process of DLL injection and API function hooking.

Basically, the DLL file will contain the hooked versions of all the function calls that can be potentially listed as harmful by the judges. It will also contain the code that does the actual hooking process for the API functions indicated as unauthorized by the judges in the policy file. We shall see in this chapter how we select the API functions we want to hook and how the actual hooking takes place. The DLL Injection process involves injecting this hooked DLL file into the memory space of the target program before it starts executing the code written in it. After this injection, during the target program execution, the hooked versions of the illegal system calls will be executed instead of their original routine. After the target process finishes its execution, the injected DLL file will be detached from the processes’ memory space. Windows API functions have been used for performing DLL file injection, running the target program and many other important functionalities in the above mentioned process. The Sandbox process execution completes after the completion of its child process i.e. the target program.

19

The example shown below shows how these 2 modules come together to complete the series of events that occur once PC2 invokes the command to run Sandbox. It also explains various Windows API functions that are used in this project to perform various functions seamlessly.

4.1 Example: Blocking CreateFileA and DeleteFileA

A target program will try to do two file operations, creating a file and deleting a file. Our goal is to Sandbox this target program and stop the function calls that create and delete a file. CreateFileA [16] and DeleteFileA [17] are two APIs in Kernel32.dll library that are hooked in this example to achieve our goal. The complete end-to-end flow of the project execution is mentioned below:

1. To begin with, judges are provided a GUI based application, which lets them select the

API functions that they do not want the target program to execute. In our example, we

select the functions, CreateFileA and DeleteFileA and displayed below:

20

Figure 5 Policy File Creation GUI

Based on above made selection, the policy file “PolicyFile.txt” will be created and populated. This text file will have the names of the system calls which have just been selected by the judges. For our example, we select the functions CreateFileA and

DeleteFileA. The generated text file would look like this:

Figure 6 Policy File screenshot

21

The judges can manually edit this policy file without using the GUI by typing the

unauthorized system calls.

2. Now, Sandbox program will be invoked by the judges through command line or from

PC2 and the arguments passed to it will be as follows:

Sandbox.exe Arguments of

Target Program

The judges need to provide the full absolute paths of the Sandbox program, the Policy

File and the Target program. They can pass one or more arguments that the target

program needs for its execution.

3. Sandbox process: As soon as the judges invoke the Sandbox program, Sandbox code

will firstly create a child process to execute the target program. CreateProcess is the

Windows function used to perform this task. The arguments provided to this function

include the name of the target program, the arguments to be passed to the target

program, pointers to process startup information and a few other details as displayed in

the code snippet here:

CreateProcess(ChildProcessPath, //Target/Child process location NULL, //CommandLine NULL, //Process Attributes NULL, //Thread Attributes FALSE, //Inherit Handles CREATE_SUSPENDED, //Creation Mode NULL, //Pointer to Environment Block NULL, //Path of Current Directory &si, //Pointer to startup information &pi) //Pointer to process information

22

The child process will be created in suspended mode as shown above. This means

the child process has just been initialized but is not executing the code of target program

yet. It has only acquired its process space and now waiting for it to be resumed.

Next, The VirtualAllocEx [18] function will allocate memory in the target process

space to store the path of our DLL file.

pLibRemote = VirtualAllocEx(pi.hProcess, NULL, sizeof(szLibPath),

MEM_COMMIT, PAGE_READWRITE);

In the above line of code, the variable szLibPath contains the path of the DLL file.

After allocating this memory, we copy the path of our DLL file onto this allocated

space using WriteProcessMemory [19] API function.

sizeof::WriteProcessMemory(pi.hProcess, pLibRemote, (void*)szLibPath,

(szLibPath), NULL);

The function CreateRemoteThread [20] is a Windows function used to run a

remote thread in the target process space. This function will be provided a pointer to

the function, LoadLibraryA [21] to load the DLL file. The newly created thread will

execute this LoadLibraryA function.

CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) :: GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL);

4. DLL Hooking Program: DLL Hooking program will read the policy file and mark the

functions needed to be hooked, i.e. CreateFileA and DeleteFileA, in the data structure

shown below:

23

/** Struct to store which functions from DLL file need to be hooked and what should be the corresponding Hooked Function. */ typedef struct HOOKING_FUNCTION_REC_STRUCT { /// Data struct to store variables used for Hooking. HOOK Hook;

/// Name of the Function in the DLL to be Hooked.

char *FunctionName;

///Pointer to the Hooking Function. void *HookedFunction;

///Flag to capture if Hooking is needed for this function. BOOL IsHookingNeeded; }HOOKING_FUNCTION_REC[HOOK_FUNCTION_MAX];

The functions to be hooked are recorded in a global variable

HOOKING_FUNCTION_REC using the structure we just defined.

HOOKING_FUNCTION_REC gHookingRecord = { { { 0 }, "DeleteFileA", HookDeleteFileA, FALSE }, { { 0 }, "CreateFileA", HookCreateFileA, FALSE }, };

Sandbox selects the first function from this list of functions and finds the corresponding hooked function in this global variable. In this example, DeletefileA is selected from the DLL file and HookDeleteFileA is its corresponding hooked function.

All the next steps regarding the hooking of the APIs are repeated for all the functions that will be recorded in this global variable.

Now, the actual hooking is performed by replacing the location provided in the

JUMP instruction. JUMP is an assembly level instruction used to point at a particular address in the memory. We are replacing the address of the actual Windows system

24

call by the address of our hooked function call. Previously this instruction pointed to the start address of original functions, CreateFileA()/DeleteFileA(). Now we change it to point to the address of our hooked versions by using the function

InitializeAndInsertHook(). From this point onwards, any calls to

CreateFileA()/DeleteFileA() will be redirected to HookCreateFileA/HookDeleteFileA which are explained below.

All the function call APIs that can be potentially marked as illegal by the judges for a target program have their hooked versions in DLLHooking.cpp file. In our example, the hooked version for CreateFileA looks like this:

HANDLE WINAPI HookCreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { WRITE_TO_HOOK_LOG_FILE("CreateFileA");

return NULL; }

This hooked API will suppress the original API call and also log this event in the

LogFile.txt with the message, “Error CreateFileA called” and “Error DeleteFileA called”.

Once all the required API functions CreateFileA/DeleteFileA have been hooked, the target program, which was in a suspended mode will resume its execution. In our example, when the child process/target program will try to create a file and then delete it. But since they have been checked as unauthorized in the policy file, their respective

25

hooked functions will be executed. These hooked functions’ routines have a function called WRITE_TO_HOOK_LOG_FILE which will write to the policy file that

CreateFileA and DeleteFileA have been called.

Once the target program execution completes, Sandbox will perform all the cleanup. Cleanup means closing child process handles and freeing the memory space the child process had occupied. The DLL file will be detached which will unhook all the hooked functions, to release the memory that was allocated to store the DLL file path.

As soon as the execution of the child process completes, its parent process i.e.

Sandbox program execution also completes.

Judges can open the LogFile.txt to find if any of the unauthorized functions were called. In our example, the log file will look like this:

Figure 7 Log File screenshot

26

5. CHARACTERISTICS, LIMITATIONS AND FUTURE ENHANCEMENTS

5.1 Characteristics

1. This software has been written in C/C++ language using Visual Studio

Community 2015 environment, version 14.0.25431.01. The GUI application to create

the policy file has been written in C# language, again using the same version of Visual

Studio as described above. If any changes are made in future to the code, I would

recommend the programmer to use Microsoft Visual Studio environment. This will

ease the process of building the code and run it for testing. The community edition is

free to download and use.

2. This software can be run on any Windows platform with versions 7 or later. The various

API functions used to accomplish the various functions in the code can evolve with the

release of new Windows versions.

3. This application has been developed to support the judging module of PC2 as a

command line command for Sandboxing programs, so that it does not harm judge’s

local machine. But this program can also be used as a stand-alone application i.e.

without invoking it from PC2. It can thus be used to Sandbox any executable program

to stop it from calling pre-determined system calls. In this way a user can protect his

system from any harmful changes.

4. The Sandbox is not responsible for, and does not need to know, the purpose of the

target command which PC2 is passing to it. For example, PC2 will at various times pass

a command which is the name of a compiler to be executed, with arguments for the

27

compiler; or will pass a command which is the name of a team program to be executed

(with arguments to the program); or will pass a command which is the name of a

“validator” to be executed (with arguments). The sandbox does not need to know what

commands PC2 is passing to it, or why; it just needs to execute the command, passing

the arguments to it, and applying the specified policy restrictions.

5. Most of the Windows API functions listed in the GUI to create the policy file have

MSDN documentation available online. Users can have a look at their description to

understand what each of the functions do.

5.2 Limitations

There are certain limitations regarding the execution of this project and they are listed below:

1. This application is designed for Windows Operating System and cannot be deployed on any other Operating System. The Linux version for Sandbox for PC2 has already been implemented and is used currently during various collegiate and inter-collegiate levels of programming contests.

2. Currently this Sandbox application cannot run any target program which is written in an interpreted language such as JAVA, Python or Perl. It can only work on executable target programs which are written in C/C++ language or any executable file that can be invoked using command line.

28

5.3 Future Enhancements

1. Currently, Sandbox has a limited list of system call APIs that the judges can select from.

In future, if more APIs need to be added to this software, they have to be first added in the

GUI code that is used to create the Policy file. Secondly, they have to be added in the list of APIs to be hooked and new hooked APIs have to be created for them as discussed in the example in the previous chapter.

2. Any executable file written in any programming language can be executed using

Sandbox program. The project can be enhanced to add support for programs written in interpreted languages such as JAVA, Python or Perl.

3. In this project, I have tried to cover possibly harmful APIs. Some of the API functions that can be potentially hooked are part of some other DLLs. If we want to restrict these function calls for the target program, some more DLLs will have to be injected using DLL

Injection.

4. Currently, the hooking mechanism suppresses the unauthorized system calls made by the target program i.e. when unauthorized functions are called, they are caught by the hooked functions. Their original routine is not executed and an error message is printed in the Log file to let the judges know that the function was called. The target program then continues its normal execution. In future, a mechanism can be added in the policy file by which the execution of the target program can be completely stopped when unauthorized system calls are called, instead of suppressing them. There can also be a combination of

29

both of the above mechanisms where the judges can select through the policy file what they want to do with each system call execution, stop it completely or suppress it.

5. Security Sandbox for PC2 is now available for Windows and Linux platforms. But still, there is not support for Mac OS. In future this software can also be developed to support

Mac Operating System.

6. In future, a software log feature can be added for Sandbox which will have a detailed log describing all activities that Sandbox performs. In this way, if the software reports any crash or if any unusual activity, user can see the logs to debug the issue.

30

6. CONCLUSION

This project has been specially designed for Windows Operating System and mainly written in C/C++. This Security Sandbox will help to protect the user’s system from any malicious program by policing the events the program tries to execute. The Sandbox program can be easily run by invoking it from PC2. The GUI based functionality to generate the policy file will make user’s task easier in selecting the restrictions to be imposed on the target program.

As explained with the example used in Chapter 4, by using DLL Injection and API

Hooking technique, this project was able to achieve its goal to identify the unauthorized system calls at run-time and suppress them. When tested, the execution of the API functions CreateFileA/DeleteFileA mentioned in the policy file was stopped. It means that the target program was not able to create or delete the file that it wanted to create/delete.

Instead, the hooked versions of these function were executed which logged these events to the Log File. When these functions were not included in the policy file, the target program was able to create a file on the judge’s system and then delete it successfully. By knowing the effect before and after Sandboxing the target process, it was proved that the Sandbox program will effectively stop the unauthorized events from occurring and hence, protect the underlying system on which the program is run.

31

APPENDIX A

Source Code

1. SandboxWithDLL.cpp: This file is responsible for creating a child process from the target

program executable file. It also performs DLL Injection and cleanup after the target program

finishes its execution.

#include #include #include #include #include #include #include

using namespace std;

//This function will get paramters from commandline needed to create a child process //starting from parameter number 3 i.e. Child process executable file path. //First 2 arguments are Sandbox.exe and path of policy file.

void GetCommandLineParamsForChildProcess(int argc, CHAR *argv[], CHAR *pCmdLine) { //Need arguments more than 3 if (argc < 3) { return; } //Taking each argument one after the another and creating a string out of them to be passed to CreateProcess later. for (int i = 3; i < argc; i++) { int j = 0; while (argv[i][j] != '\0') { *pCmdLine++ = argv[i][j]; j++; }

//Keep adding space in between arguments until you reach the last argument. if (i < argc - 1) { *pCmdLine++ = ' '; } }

32

//Add null character at the end of string. *pCmdLine = '\0'; }

//Program execution starts here. void main(int argc, char *argv[]) { STARTUPINFOA si = {0}; PROCESS_INFORMATION pi = {0}; HMODULE hModule; int NumOfArgs;

if (argc < 2) { printf("Insufficient number of arguments exiting... \n"); }

cout << argv[1];

CHAR *ChildProcessName = argv[2];

CHAR *PolicyFilePath = "..\\..\\..\\PolicyFile.txt"; CHAR *LogFilePath = "..\\..\\..\\LogFile.txt"; CHAR CmdLine[256]; CHAR CmdPolicyFilePath[256]; ofstream FsPolicyFile; ofstream FsLogFile; ifstream FsPolicyFileCmd;

//Clearing out LogFile before use. FsLogFile.open(LogFilePath); FsLogFile.clear(); FsLogFile.close();

//copying the path of policy file providing as an argument to Sandbox. strcpy(CmdPolicyFilePath, argv[1]);

// Clear the contents of the Policy File which is already existing. FsPolicyFile.open(PolicyFilePath); FsPolicyFile.clear();

//Open the policy file provided in commandline FsPolicyFileCmd.open(CmdPolicyFilePath);

//Copy the contents from the commandline provided policyfile to our policy file, line by line. string line; while (getline(FsPolicyFileCmd, line)) { FsPolicyFile << line; FsPolicyFile << "\n"; } FsPolicyFile.close();

33

FsPolicyFileCmd.close();

GetCommandLineParamsForChildProcess(argc, argv, CmdLine);

//The following variables are for DLL injection HANDLE hThread; char szLibPath[_MAX_PATH] = "..\\..\\..\\..\\DLLHooking\\DLLHooking\\Debug\\DLLHooking.dll"; // (including full path!); void* pLibRemote; // The address (in the remote process) where szLibPath will be copied to; DWORD hLibModule; // Base address of loaded module (==HMODULE); HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32");

//Startup information for Child process si.cb = sizeof(si); printf("Sandbox Program Started \n");

// Start the child process.(team program) if (!CreateProcessA(ChildProcessName, CmdLine, // Command line NULL, NULL, FALSE, CREATE_SUSPENDED, //Creating process in suspended mode. Will resume later in the program NULL, NULL, &si, &pi) ) { printf("CreateProcess failed (%d).\n", GetLastError()); return; }

// DLL Injection begins here // Code Reference for DLL Injection: https://www.codeproject.com/Articles/4610/Three-Ways-to- Inject-Your-Code-into-Another-Proces // Allocate memory in the child process for DLL File path and write that path to the allocated memory pLibRemote = VirtualAllocEx(pi.hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(pi.hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL);

// Load "kernel32.dll" into the remote process hThread = CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL); WaitForSingleObject(hThread, INFINITE);

34

// Get handle of the loaded module GetExitCodeThread(hThread, &hLibModule);

// Clean up CloseHandle(hThread); VirtualFreeEx(pi.hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE);

//Resuming the suspended target process ResumeThread(pi.hThread);

// Wait until child process exits. WaitForSingleObject(pi.hProcess, INFINITE);

// Unload DLL from the target process hThread = CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32, "FreeLibrary"), (void*)hLibModule, 0, NULL); WaitForSingleObject(pi.hThread, INFINITE);

// Clean up CloseHandle(hThread);

// Close process and thread handles. CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }

2. DLLHook.h: This file includes all the structures needed for API hooking in the DLL file. It also

keeps the record of hooked versions of all the APIs that can be potentially listed as

unauthorized by the judges.

#include

#define LOG_FILE_PATH ("..\\..\\..\\..\\LogFile.txt")

#define WRITE_TO_HOOK_LOG_FILE(_func) \ ofstream LogFileStream; \ LogFileStream.open(LOG_FILE_PATH, fstream::app);\ LogFileStream << "Error " << _func << "Called \n" ;\ LogFileStream.close(); \

#define PAGE_SIZE (4096)

//Declaration of all Hook functions INT WINAPI HookDeleteFileA(LPCSTR file);

HANDLE WINAPI HookCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,

35

DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);

BOOL WINAPI HookDeleteFile(LPCTSTR lpFileName);

BOOL WINAPI HookCopyFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists);

BOOL WINAPI HookCreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );

BOOL WINAPI HookCreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize );

BOOL WINAPI HookCreateProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );

HANDLE WINAPI HookCreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );

DWORD HookEraseTape( HANDLE hDevice, DWORD dwEraseType, BOOL bImmediate );

36

VOID WINAPI HookExitProcess( UINT uExitCode );

VOID WINAPI HookExitThread( DWORD dwExitCode );

BOOL WINAPI HookGetComputerName( LPTSTR lpBuffer, LPDWORD lpnSize );

DWORD WINAPI HookGetCurrentProcessId(void);

DWORD WINAPI HookGetFileAttributes(LPCTSTR lpFileName);

BOOL WINAPI HookGetFileAttributesEx( LPCTSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation );

DWORD WINAPI HookGetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh );

BOOL WINAPI HookGetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize );

BOOL WINAPI HookGetFileTime( HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime );

DWORD WINAPI HookGetFileType( HANDLE hFile );

FARPROC WINAPI HookGetProcAddress( HMODULE hModule, LPCSTR lpProcName );

DWORD WINAPI HookGetProcessId( HANDLE Process );

37

void WINAPI HookGetSystemInfo( LPSYSTEM_INFO lpSystemInfo );

DWORD WINAPI HookGetThreadId( HANDLE Thread ); void APIENTRY HookLZClose( INT hFile );

INT WINAPI HookLZOpenFile( LPTSTR lpFileName, LPOFSTRUCT lpReOpenBuf, WORD wStyle );

INT WINAPI HookLZRead( INT hFile, LPSTR lpBuffer, INT cbRead );

BOOL WINAPI HookMoveFile( LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName );

BOOL WINAPI HookMoveFileEx( LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags );

HFILE WINAPI HookOpenFile( LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle );

BOOL WINAPI HookReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped );

BOOL WINAPI HookRemoveDirectory( LPCTSTR lpPathName

38

);

BOOL WINAPI HookReplaceFile( LPCTSTR lpReplacedFileName, LPCTSTR lpReplacementFileName, LPCTSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved );

BOOL WINAPI HookSetFileTime( HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime );

BOOL WINAPI HookSetLocalTime( const SYSTEMTIME *lpSystemTime );

BOOL WINAPI HookSetSystemTime( const SYSTEMTIME *lpSystemTime );

BOOL WINAPI HookWriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped );

BOOL WINAPI HookWriteFileEx( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );

/** Struct to define JMP instrution. */ typedef struct JMP_INSTR_STRUCT { /// Opcode for JMP char Opcode;

/// Address for JMP Instructure char Address[5];

39

}JMP_INSTR;

/** Struct to store information needed for Hooking. */ typedef struct HOOK_STRUCT { /// Variable to store Address of the Function to be hooked. bool isHooked;

void* FunctionAddress; JMP_INSTR JmpInstr;

/// Temporary Storing the Address of JMP of Original Function. void* APIFunction; }HOOK;

/** Enum which indexes into the list of the Functions for which Hooking is possible. */ typedef enum HOOK_FUNCTION_INDEX_ENUM { HOOK_FUNCTION_MIN = 0x0, HOOK_DELETEFILE_A = HOOK_FUNCTION_MIN, HOOK_CREATEFILE_A,

// Keep this as last HOOK_FUNCTION_MAX

}HOOK_FUNCTION_INDEX;

/** Struct to store what functions from DLL needs to be hooked and what should be the Hooked Function. */ typedef struct HOOKING_FUNCTION_REC_STRUCT { /// Data struct to store variables used for Hooking. HOOK Hook;

/// Name of the Function in the DLL to be Hooked. char *FunctionName;

///Pointer to the Hooking Function. void *HookedFunction;

///Flag to capture if Hooking is needed for this function. BOOL IsHookingNeeded; }HOOKING_FUNCTION_REC[HOOK_FUNCTION_MAX];

/** Global Variable Initiazed to store the Record for Hooking. */

40

HOOKING_FUNCTION_REC gHookingRecord = { { { 0 }, "DeleteFileA", HookDeleteFileA, FALSE }, { { 0 }, "CreateFileA", HookCreateFileA, FALSE }, { { 0 }, "DeleteFile", HookDeleteFile, FALSE }, { { 0 }, "CopyFile", HookCopyFile, FALSE }, { { 0 }, "CreateDirectory", HookCreateDirectory, FALSE }, { { 0 }, "CreatePipe", HookCreatePipe, FALSE }, { { 0 }, "CreateProcess", HookCreateProcess, FALSE }, { { 0 }, "CreateThread", HookCreateThread, FALSE }, { { 0 }, "EraseTape", HookEraseTape, FALSE }, { { 0 }, "ExitProcess", HookExitProcess, FALSE }, { { 0 }, "ExitThread", HookExitThread, FALSE }, { { 0 }, "GetComputerName", HookGetComputerName, FALSE }, { { 0 }, "GetCurrentProcessId", HookGetCurrentProcessId, FALSE }, { { 0 }, "GetFileAttributes", HookGetFileAttributes, FALSE }, { { 0 }, "GetFileAttributesEx", HookGetFileAttributesEx, FALSE }, { { 0 }, "GetFileSize", HookGetFileSize, FALSE }, { { 0 }, "GetFileSizeEx", HookGetFileSizeEx, FALSE }, { { 0 }, "GetFileTime", HookGetFileTime, FALSE }, { { 0 }, "GetFileType", HookGetFileType, FALSE }, { { 0 }, "GetProcAddress", HookGetProcAddress, FALSE }, { { 0 }, "GetProcessId", HookGetProcessId, FALSE }, { { 0 }, "GetSystemInfo", HookGetSystemInfo, FALSE }, { { 0 }, "GetThreadId", HookGetThreadId, FALSE }, { { 0 }, "LZClose", HookLZClose, FALSE }, { { 0 }, "LZOpenFile", HookLZOpenFile, FALSE }, { { 0 }, "LZRead", HookLZRead, FALSE }, { { 0 }, "MoveFile", HookMoveFile, FALSE }, { { 0 }, "MoveFileEx", HookMoveFileEx, FALSE }, { { 0 }, "OpenFile", HookOpenFile, FALSE }, { { 0 }, "ReadFile", HookReadFile, FALSE }, { { 0 }, "RemoveDirectory", HookRemoveDirectory, FALSE }, { { 0 }, "ReplaceFile", HookReplaceFile, FALSE }, { { 0 }, "SetFileTime", HookSetFileTime, FALSE }, { { 0 }, "SetLocalTime", HookSetLocalTime, FALSE }, { { 0 }, "SetSystemTime", HookSetSystemTime, FALSE }, { { 0 }, "WriteFile", HookWriteFile, FALSE }, { { 0 }, "WriteFileEx", HookWriteFileEx, FALSE } };

3. DLLHook.cpp: This file is contains the code to perform the actual hooking of the API calls

requested in the policy file. It also contains the routines of all the hooked APIs.

#include #include #include

41

#include #include "DLLHook.h" #include #include #include using namespace std;

/** \brief Hooking Function for DeleteFileA Function call.

After Hooking DeleteFileA this function will be called when user calls DeleteFileA

@param Params same as DeleteFileA @retval return 0 */ INT WINAPI HookDeleteFileA(LPCSTR file) { WRITE_TO_HOOK_LOG_FILE("DeleteFileA");

return 0; }

//Similar to the above two hooking functions, all the following functions until HookWriteFile are hooked versions of all functions. BOOL WINAPI HookCopyFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists) { WRITE_TO_HOOK_LOG_FILE("CopyFile");

return 0; }

BOOL WINAPI HookDeleteFile(LPCTSTR lpFileName) { WRITE_TO_HOOK_LOG_FILE("CopyFile");

return 0; }

BOOL WINAPI HookCreateDirectory( LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes ) { WRITE_TO_HOOK_LOG_FILE("CreateDirectory");

return 0; }

42

BOOL WINAPI HookCreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize) { WRITE_TO_HOOK_LOG_FILE("CreatePipe");

return 0; }

BOOL WINAPI HookCreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { WRITE_TO_HOOK_LOG_FILE("CreateProcess");

return 0; }

HANDLE WINAPI HookCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { WRITE_TO_HOOK_LOG_FILE("CreateThread");

return 0; }

DWORD HookEraseTape(HANDLE hDevice, DWORD dwEraseType, BOOL bImmediate) { WRITE_TO_HOOK_LOG_FILE("EraseTape");

return 0; }

VOID WINAPI HookExitProcess(UINT uExitCode) { WRITE_TO_HOOK_LOG_FILE("ExitProcess");

return VOID(); }

VOID WINAPI HookExitThread(DWORD dwExitCode) { WRITE_TO_HOOK_LOG_FILE("ExitThread");

return VOID(); }

BOOL WINAPI HookGetComputerName(LPTSTR lpBuffer, LPDWORD lpnSize) { WRITE_TO_HOOK_LOG_FILE("GetComputerName");

43

return 0; }

DWORD WINAPI HookGetCurrentProcessId(void) { WRITE_TO_HOOK_LOG_FILE("GetCurrentProcessId");

return 0; }

DWORD WINAPI HookGetFileAttributes(LPCTSTR lpFileName) { WRITE_TO_HOOK_LOG_FILE("GetFileAttributes");

return 0; }

BOOL WINAPI HookGetFileAttributesEx(LPCTSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation) { WRITE_TO_HOOK_LOG_FILE("GetFileAttributesEx");

return 0; }

DWORD WINAPI HookGetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) { WRITE_TO_HOOK_LOG_FILE("GetFileSize");

return 0; }

BOOL WINAPI HookGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) { WRITE_TO_HOOK_LOG_FILE("GetFileSizeEx");

return 0; }

BOOL WINAPI HookGetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime) { WRITE_TO_HOOK_LOG_FILE("GetFileTime");

return 0; }

DWORD WINAPI HookGetFileType(HANDLE hFile) { WRITE_TO_HOOK_LOG_FILE("GetFileType");

44

return 0; }

FARPROC WINAPI HookGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { WRITE_TO_HOOK_LOG_FILE("GetFileType");

return 0; }

DWORD WINAPI HookGetProcessId(HANDLE Process) { WRITE_TO_HOOK_LOG_FILE("GetProcessId");

return 0; } void WINAPI HookGetSystemInfo(LPSYSTEM_INFO lpSystemInfo) { WRITE_TO_HOOK_LOG_FILE("GetSystemInfo"); }

DWORD WINAPI HookGetThreadId(HANDLE Thread) { WRITE_TO_HOOK_LOG_FILE("GetThreadId");

return 0; } void APIENTRY HookLZClose(INT hFile) { WRITE_TO_HOOK_LOG_FILE("LZClose"); }

INT WINAPI HookLZOpenFile(LPTSTR lpFileName, LPOFSTRUCT lpReOpenBuf, WORD wStyle) { WRITE_TO_HOOK_LOG_FILE("LZOpenFile");

return 0; }

INT WINAPI HookLZRead(INT hFile, LPSTR lpBuffer, INT cbRead) { WRITE_TO_HOOK_LOG_FILE("LZRead");

return 0; }

BOOL WINAPI HookMoveFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName) { WRITE_TO_HOOK_LOG_FILE("MoveFile");

45

return 0; }

BOOL WINAPI HookMoveFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags) { WRITE_TO_HOOK_LOG_FILE("MoveFileEx");

return 0; }

HFILE WINAPI HookOpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle) { WRITE_TO_HOOK_LOG_FILE("OpenFile");

return 0; }

BOOL WINAPI HookReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { WRITE_TO_HOOK_LOG_FILE("ReadFile");

return 0; }

BOOL WINAPI HookRemoveDirectory(LPCTSTR lpPathName) { WRITE_TO_HOOK_LOG_FILE("RemoveDirectory");

return 0; }

BOOL WINAPI HookReplaceFile(LPCTSTR lpReplacedFileName, LPCTSTR lpReplacementFileName, LPCTSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved) { WRITE_TO_HOOK_LOG_FILE("ReplaceFile");

return 0; }

BOOL WINAPI HookSetFileTime(HANDLE hFile, const FILETIME * lpCreationTime, const FILETIME * lpLastAccessTime, const FILETIME * lpLastWriteTime) { WRITE_TO_HOOK_LOG_FILE("SetFileTime");

return 0; }

BOOL WINAPI HookSetLocalTime(const SYSTEMTIME * lpSystemTime) {

46

WRITE_TO_HOOK_LOG_FILE("SetLocalTime");

return 0; }

BOOL WINAPI HookSetSystemTime(const SYSTEMTIME * lpSystemTime) { WRITE_TO_HOOK_LOG_FILE("SetSystemTime");

return 0; }

BOOL WINAPI HookWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { WRITE_TO_HOOK_LOG_FILE("WriteFile");

return 0; }

BOOL WINAPI HookWriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { WRITE_TO_HOOK_LOG_FILE("WriteFileEx");

return 0; }

/** \brief Hooking Function for CreateFileA Function call.

After Hooking CreateFileA this function will be called when user calls CreateFileA

@param Params same as CreateFileA @retval return NULL */ HANDLE WINAPI HookCreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { WRITE_TO_HOOK_LOG_FILE("CreateFileA");

return NULL; }

/**

47

\brief Marks the functions which needs to be hooked.

Searches gHookingRecord table for the function name mentioned in parameter. If there is a match found then marks that function for hooking.

@param FunctionName Name of Function which needs to be hooked. @retval void. */ void MarkFunctionsForHooking(string FunctionName) { // Policy file should have the function in same order as the array of hooking static UINT32 Index = 0;

if (Index >= HOOK_FUNCTION_MAX) { return; }

while (Index < HOOK_FUNCTION_MAX) { if (FunctionName.compare(gHookingRecord[Index].FunctionName) == 0) { gHookingRecord[Index].IsHookingNeeded = TRUE; Index++; break; } Index++; } }

/** \brief Reads Policy File and marks the functions which needs to be hooked.

@param void. @retval void. */ void ReadPolicyFileAndMarkFunctionsForHooking() { ifstream PolicyFile; PolicyFile.open("..\\..\\..\\PolicyFile.txt");

string Line; while (getline(PolicyFile, Line)) { MarkFunctionsForHooking(Line); }

PolicyFile.close(); return; }

/**

48

\brief Initialized a hook and inserts it.

Modifies the DLL process memory to execute JMP Instruction to Hooked Function.

@param ModuleName Name of the DLL Module @retval HookIdx Index in gHookingRecord Array where Hook needs to be Inserted. */ bool InitializeAndInsertHook(char* ModuleName, int HookIdx) { HOOK* Hook = &gHookingRecord[HookIdx].Hook; HMODULE hModule; ULONG JmpInstrAddrSize = sizeof(Hook->JmpInstr.Address); ULONG JmpInstrSize = sizeof(Hook->JmpInstr); DWORD OriginalProtection;

if (Hook->isHooked) { return false; } hModule = GetModuleHandleA(ModuleName); if (hModule == NULL) { // debug only remove DWORD error = GetLastError();

Hook->isHooked = false; return false; }

// Get address of the function which needs to be hooked. Hook->FunctionAddress = GetProcAddress(hModule, gHookingRecord[HookIdx].FunctionName); if (Hook->FunctionAddress == NULL) { // debug only remove DWORD error = GetLastError();

Hook->isHooked = false; return false; }

// 0xe9 is the opcode for JMP Instruction Hook->JmpInstr.Opcode = 0xe9;

// Calculate Jump Instruction Address. *(PULONG)&Hook->JmpInstr.Address = (ULONG)gHookingRecord[HookIdx].HookedFunction - ((ULONG)Hook->FunctionAddress + JmpInstrAddrSize);

Hook->APIFunction = VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

if (Hook->APIFunction == NULL)

49

{ return false; }

// Copy the Address of function in DLL to be hooked. memcpy(Hook->APIFunction, Hook->FunctionAddress, JmpInstrAddrSize);

// Insert opcode for JMP instruction. *(LPBYTE)((LPBYTE)Hook->APIFunction + JmpInstrAddrSize) = Hook->JmpInstr.Opcode;

// Insert Address where JMP is to be performed. *(PULONG)((LPBYTE)Hook->APIFunction + JmpInstrSize) = ((ULONG)Hook->APIFunction - ((ULONG)Hook->FunctionAddress + JmpInstrAddrSize)); Hook->isHooked = true;

// Inserting the Hook

// Change the Protection of pages for the DLL. VirtualProtect(Hook->FunctionAddress, JmpInstrAddrSize, PAGE_EXECUTE_READWRITE, &OriginalProtection);

// Insert the address of the Hooked Function in place of address of Original Function. memcpy(Hook->FunctionAddress, &Hook->JmpInstr, JmpInstrAddrSize);

// Restore the Protection of pages for the DLL. VirtualProtect(Hook->FunctionAddress, JmpInstrAddrSize, OriginalProtection, &OriginalProtection);

return true; }

/** \brief Unhooks the function and Frees the hook.

Restores the original address of the Hooked Function and releases memory acquired for HOOK.

@param Hook HOOK struct used for hooking @retval TRUE if Unhook is successfull, FALSE otherwise. */ bool UnhookAndFreeHook(HOOK* Hook) { DWORD op; ULONG JmpInstrAddrSize = sizeof(Hook->JmpInstr.Address);

if (!Hook->isHooked) { return false; } VirtualProtect(Hook->FunctionAddress, JmpInstrAddrSize, PAGE_EXECUTE_READWRITE, &op); memcpy(Hook->FunctionAddress, Hook->APIFunction, JmpInstrAddrSize); VirtualProtect(Hook->FunctionAddress, JmpInstrAddrSize, op, &op);

50

Hook->isHooked = false; VirtualFree(Hook->APIFunction, 0, MEM_RELEASE); memset(Hook, 0, sizeof(HOOK*)); return true; }

/** \brief Initialized a hook and inserts it.

Modifies the DLL process memory to execute JMP Instruction to Hooked Function.

@param ModuleName Name of the DLL Module @retval TRUE if all hooks are inserted successfully, FALSE otherwise. */ bool InitializeAndInsertAllHooks(char *DllName) { for (int HookIdx = HOOK_FUNCTION_MIN; HookIdx < HOOK_FUNCTION_MAX; HookIdx++) { if (gHookingRecord[HookIdx].IsHookingNeeded == TRUE) { InitializeAndInsertHook(DllName, HookIdx); } } return TRUE; }

/** \brief Unhooks all the Functions and frees up memory.

Modifies the DLL process memory to execute JMP Instruction to Hooked Function.

@param [in] void. @param [out] bool TRUE if successfully Unhooked, FALSE if not. */ bool UnHookAndFreeAllHooks() { for (int HookIdx = HOOK_FUNCTION_MIN; HookIdx < HOOK_FUNCTION_MAX; HookIdx++) { if (gHookingRecord[HookIdx].IsHookingNeeded == TRUE) { UnhookAndFreeHook(&(gHookingRecord[HookIdx].Hook)); } } return TRUE; }

/** \brief Entry point of the DLL.

51

Called when DLL is loaded or unloaded. */ BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: // Read the PolicyFile ReadPolicyFileAndMarkFunctionsForHooking();

// Initialize and Insert Hooks InitializeAndInsertAllHooks("kernel32.dll"); break;

case DLL_PROCESS_DETACH: UnHookAndFreeAllHooks(); break; } return TRUE; }

4. HomePage.Designer.cs: This file includes the code to create the GUI for generating the

Policy file. It also contains the list of the Windows APIs from Kernel32.dll file which are

supported by our Sandbox.

namespace SandboxUI { partial class HomePage { ///

/// Required designer variable. /// private System.ComponentModel.IContainer components = null;

///

/// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); }

52

#region Windows Form Designer generated code

///

/// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.BannedAPIList = new System.Windows.Forms.CheckedListBox(); this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // BannedAPIList // this.BannedAPIList.CheckOnClick = true; this.BannedAPIList.FormattingEnabled = true; this.BannedAPIList.Items.AddRange(new object[] { "DeleteFileA", "DeleteFile", "CreateFileA", "CopyFile", "CreateDirectory", "CreatePipe", "CreateProcess", "CreateThread", "EraseTape", "ExitProcess", "ExitThread", "GetComputerName", "GetCurrentProcessId", "GetFileAttributes", "GetFileAttributesEx", "GetFileSize", "GetFileSizeEx", "GetFileTime", "GetFileType", "GetProcAddress", "GetProcessId", "GetSystemInfo", "GetThreadId", "LZClose", "LZOpenFile", "LZRead", "MoveFile", "MoveFileEx", "OpenFile", "ReadFile", "RemoveDirectory", "ReplaceFile", "SetFileTime", "SetLocalTime", "SetSystemTime",

53

"WriteFile", "WriteFileEx"}); this.BannedAPIList.Location = new System.Drawing.Point(13, 13); this.BannedAPIList.Name = "BannedAPIList"; this.BannedAPIList.Size = new System.Drawing.Size(232, 259); this.BannedAPIList.TabIndex = 0; // // button1 // this.button1.Location = new System.Drawing.Point(64, 286); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(124, 35); this.button1.TabIndex = 1; this.button1.Text = "Create"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.AddBtnClickEvent); // // HomePage // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(257, 333); this.Controls.Add(this.button1); this.Controls.Add(this.BannedAPIList); this.Name = "HomePage"; this.Text = "Policy File Creater"; this.ResumeLayout(false);

}

#endregion

protected System.Windows.Forms.CheckedListBox BannedAPIList; private System.Windows.Forms.Button button1; } }

5. HomePage.cs: This file contains the code that handles the event when ‘Create’ button is hit

by the user on the GUI to create policy file.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks;

54

using System.Windows.Forms; namespace SandboxUI { public partial class HomePage : Form { public HomePage() { InitializeComponent(); } private void AddBtnClickEvent(object sender, EventArgs e) { const string PolicyFilePath = "..\\..\\..\\..\\..\\PolicyFile.txt";

FileStream Fs = File.Open(PolicyFilePath, FileMode.Open, FileAccess.Write); Fs.SetLength(0);

for(int i = 0; i < BannedAPIList.Items.Count; i++) { if(BannedAPIList.GetItemCheckState(i) == CheckState.Checked) { Byte[] func = new UTF8Encoding(true).GetBytes(BannedAPIList.Items[i].ToString() + Environment.NewLine); Fs.Write(func, 0, func.Length); } } Fs.Close();

MessageBox.Show("Policy File Created");

Application.Exit(); } } }

55

BIBLIOGRAPHY

[1] An overview of PC2 (January 31, 2012) - http://pc2.ecs.csus.edu/pc2desc.html

[2] PC2 Contest Administrator’s Guide (June 7, 2016) -

http://pc2.ecs.csus.edu/doc/v9/9.3.4/pc2v9AdminGuide.pdf

[3] Chris Hoffman (August 2013) - https://www.howtogeek.com/169139/sandboxes-

explained-how-theyre-already-protecting-you-and-how-to-sandbox-any-program/

[4] VirtualBox - https://www.virtualbox.org/wiki/VirtualBox

[5] VMWare - http://www.vmware.com/

[6] Cuckoo Sandbox - https://cuckoosandbox.org/

[7] Cuckoo Sandbox Introduction -

https://downloads.cuckoosandbox.org/docs/introduction/what.html

[8] Sandboxie - https://www.sandboxie.com/

[9] Chromium Sandbox - https://www.chromium.org/developers/design-documents/sandbox

[10] Adithya, Vikram Chidanand (February 17, 2012). Security Sandbox for PC2 - Linux

Version - http://csus-dspace.calstate.edu/handle/10211.9/1525

[11] Brad Antoniewicz (January 2013). DLL Injection Basics –

http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html

[12] Kernel32.dll –

56

https://en.wikipedia.org/wiki/Microsoft_Windows_library_files#KERNEL32.DLL

[13] Physical and Runtime Modification (Wikipedia) –

https://en.wikipedia.org/wiki/Hooking

[14] Event Tracing for Windows (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/bb968803(v=vs.85).aspx

[15] CreateProcess API (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx

[16] CreateFileA API (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx

[17] DeleteFileA API (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/aa363915(v=vs.85).aspx

[18] VirtualAllocEx API (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366890(v=vs.85).aspx

[19] WriteProcessMemory API (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674(v=vs.85).aspx

[20] CreateRemoteThread API (MSDN) –

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx

[21] LoadLibraryA API (MSDN) –

57

https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx