Courses/Computer Science/CPSC 525.W2016/Tutorial Notes

Jump to: navigation, search

TA Info

Section 1 (TuTh 5:00PM - 6:50PM)

Section 2 (TuTh 3:00PM - 3:50PM)
Mike Clark
Tutorial Schedule/Material

Section 3 (TuTh 4:00PM - 4:50PM)
Mike Clark
Tutorial Schedule/Material

Tutorials 1 and 2 : Introduction, Familiarizing with 'Security' words, Hacking attempts

Exercise 1: Web browser password storing

Do you save password into your browser? Lets check where these passwords are saved and is it encrypted or clear text?


  • 1. Identify your browser ( Safari, Internet Explorer, Mozilla etc.)
  • 2. If you have already any saved password then go to step 3, otherwise save any password. For example, try to login to 'My UofC' and save password.
  • 3. Search youtube or google for your specific browser on how to hack browser password. I have provided one example in the slide for Safari.
  • 4. Whats your observation? How easy or difficult it is?
  • 5. Where these passwords are stored in your system?
  • 6. How do you protect those? (hint: using encryption) What is key-chain?

Exercise 2: Bypassing your OS login

Do you know that it is possible to bypass your OS login credentials and gain access? Lets do this exercise.


  • 1. Identify your Operating system name and version ( Windows xp/7/8, Mac OS x version / Linux etc.)
  • 2. In the slide I have provided an example of bypassing Mac OS. Search youtube for your version.
  • 3. Whats your result? Are you successful? If not, what was the barrier.
  • 4. How do you protect bypassing OS credential?

Exercise 3: Diff and patches

Make students learn how to diff two files and see modified changes.

Tutorials 3 and 4: Advantages and disadvantages of C programming

  • Introduction to C programming language
  • What are pointers? When shall we use them?
  • Forms of code injection
  • Unbounded string copies
  • Null-Termination Errors
  • String truncation
  • How does a buffer overflow work?
  • How does an integer overflow work?

Tutorial 5: Ptrace, inspect and manipulate the internal state of a program

  • Ptrace parameters.
  • Exercise: How to modify a piece of data with ptrace

Tutorial 6: ELF manipulation

  • ELF headers (readelf)
  • libelf
  • objdump
  • Exercise: How to create a new header section in ELF file.

Tutorial 7 : Introduction to 'Hacking the Abacus', Setting up VM environment for experiment

Exercise 4: Creating environment for experiment"


Installing Virtual Machine, for example, Oracle VM VirtualBox [[1]], VMWare [[2]] (STUDENTS WILL NEED TO BRING THEIR OWN MACHINES FOR THIS EXERCISE)

  • 1. Download: VirtualBox [[3]], VMWare [[4]]
  • 2. Install your preffered OS into the VM. [Note: Always download iOS files or other files from trusted sources. When you type "download linux ios" in google, how many links appear? Which one is trusted? ]
  • 3. Configure IP address.

Exercise 5: Beating up your OS

This exercise is from the tutorial book "Hacking the Abacus", Page 28

To get things started, we are going to ask you to abuse your OS in a number of ways. This lab exercise is a prime example of learning through failure modes. Rather than trying to memorize a long list of traditional OS principles and roles (i.e., schedul- ing, resource management, memory management, user management, persistent storage management, device management, security, protection, network and communications management), we’re going to ask you to test the limits of your system. What can’t it do? Just how many processes can you create? Why can’t you create more? Why can you not do some activity that seems perfectly plausible?

This first lab exercise should also provide some form of catharsis; we are giving you permission to be mean to your OS. Go wild.


In this exploratory task, you will abuse an operating system in a number of ways and report your observations.

Learning Outcomes

The purpose of this task is to help you achieve the following outcomes:

  • 1. explore failure and error conditions in the context of an OS
  • 2. understand the power and semantics of a “superuser” user and the distinction between privileged kernel mode execution and merely being “root”
  • 3. learn about the limits of processing, disk, and memory allocation and deallocation
  • 4. develop an understanding of the resource limit mechanism in Linux


  • 1. Kill init. Without modifying the OS kernel, make your best attempt to kill the init process. What happens?
  • 2. Kill All Processes. Try to kill every process on the box. What happens? Can you be sure? What is the best order for doing this (i.e., what is the most reliable mechanism to do this)? Killing yourself before the job is done does not seem effective...
  • 3. Bye Bye File System. Delete the contents of your filesystem (hint: explore the use of the rm command at the root of your directory tree). Make sure you succeed in doing this. What happens to your machine? Can you successfully reboot?
  • 4. No More Room. Fill all available disk space. Describe what you did and what happens. How long did it take?
  • 5. No More Space. Write a program that allocates all available memory and searches it for the string “password”. What happens to your system when you run this program? What happens to your program when you run this program? How long does it take?
  • 6. Fork Bomb. Write a program that invokes fork(2) in an infinite loop. What, if anything, happens to your machine? Is this what you expect? Look at the kernel control path for the do fork implementation of fork(2). Hint: use a tool like LXR.
  • 7. Thick Filters. How many iptables rules can you insert before you noticeably affect the receipt and processing of network packets on your machine? This question will require you to (1) learn something about iptables (the Linux fire- wall) rules, (2) develop some way of measuring how long it takes for a packet to traverse your kernel. Consider the use of ICMP from a remote machine.
  • 8. Flip Bits. Write a program that opens /dev/mem and writes a random amount of randomly–generated bytes to an arbitrary location in the file. Repeat as long as you can. Keep track of the addresses you’ve written to. Catch and ignore SIGSEGV (which you might get if writing to a read-only address or memory location/range). Describe any errors you see. Perform this experiment for ten trials. Keep track of the most interesting errors as well as a log of all the ad- dresses you were able to write to. Did this work as expected? Could you write to all locations in memory? Why or why not? Again, look at the kernel source code that implements the /dev/mem psuedodevice.

 Notes, Hints, and Recommendations

You may perform the above tasks in any order you wish.

It may be useful to maintain several snapshots of your VM guest, one per task (so that, for example, after you delete the file system contents, you don’t have to do a full reinstall). For many of these tasks, you will probably wish to acquire root privileges.

Tutorial 8: Vulnerability Assessment and How it relates to "CIA"

Exercise 5: Finding vulnerabilities of our system

The purpose of this exercise is to find publicly known vulnerabilities of our operating system using a standard vulnerability scanner 'NESSUS'. NESSUS is a widely used tool for vulnerability scanning.


  • 1. Download the 7 day trial version and install it. You might need to use your ucalgary email address. download link : [[5]]
  • 2. Before scanning, you need to set up policy. Go to 'policy tab' and click '+New Policy'.
  • 3. There are different policies. For this exercise, lets set our policy to 'Basic Network Scan'. You can find details of other policies here [[6]].
  • 4. Now, Go to tab 'Scan' and click '+New Scan'. Here refer to the policy name that you've created just now. Run the scan.
  • 5. It'll generate a report. My system scan report looks like this one - [[7]].
  • 6. You'll find different vulnerabilities , Critical, High, Medium, Low, Info. [Note: How these are classified? CVSS is a vulnerability scoring system designed to provide an open and standardized method for rating IT vulnerabilities. Detail of CVSS : [[8]], Detail of scoring metrics: [[9]].
  • 7. NESSUS generated scan report [[10]] with one critical vulnerability "Mac OS X<10.9.5 Multiple Vulnerabilities " for my system. Lets select this vulnerability detail.
  • 8. In the detail page, you'll find different information. In the left side, there are Description(List of vulnerabilities and its description), Solution(How this can be patched), See Also (list of references for further analysis), Output, Ports, Host. In the Right side, you'll see, Plugin Details (NESSUS uses different plugins to identify vulnerability [[11]]), Risk Information(Risk calculated using CVSS parameters [[12]]), Vulnerability Information ( If it is exploitable, which tool can be used to exploit etc.), Reference Information (CVE IDs). This 2 links will help you to visualize. [[13]] and [[14]]

Exercise 6 : Understanding Vulnerability in detail and CVE

Here, we'll try to understand what NESSUS has found as vulnerability. We'll look into any vulnerability and try to understand its detail.

Steps A case study

  • 1. Lets have a closer look into the critical vulnerability "Mac OS X<10.9.5 Multiple Vulnerabilities " for my system.
  • 2. In "See Also" section, there are several urls listed. Lets select the second one - [[15]].
  • 3. You'll find the detail information of the multiple vulnerabilities in terms of Available for, Impact, Description and CVE ID. Lets take the last one ruby.
  • 4. Detail of ruby

Available for: OS X Mavericks v10.9 to v10.9.4

Impact: A remote attacker may be able to cause arbitrary code execution

Description: A heap buffer overflow existed in LibYAML's handling of percent-encoded characters in a URI. This issue was addressed through improved bounds checking. This update addresses the issues by updating LibYAML to version 0.1.6


  • 5. Detail of CVE-2014-2525:

You'll find detail of CVE at [[16]]. You can have further idea of who is this organization, what they do, how they process CVE id. Common Vulnerabilities and Exposures (CVE®) is a dictionary of common names (i.e., CVE Identifiers) for publicly known information security vulnerabilities. CVE’s common identifiers make it easier to share data across separate network security databases and tools, and provide a baseline for evaluating the coverage of an organization’s security tools. If a report from one of your security tools incorporates CVE Identifiers, you may then quickly and accurately access fix information in one or more separate CVE-compatible databases to remediate the problem[[17]].

This page [[18]] describes CVE-2014-2525 as Heap-based buffer overflow in the yaml_parser_scan_uri_escapes function in LibYAML before 0.1.6 allows context-dependent attackers to execute arbitrary code via a long sequence of percent-encoded characters in a URI in a YAML file.

Exercise 7: Understanding CWE

From the above exercise, we were able to get the detail of vulnerability CVE-2014-2525. Here, we'll try to dig down a further to understand the exploit "Heap-based buffer overflow".


  • 1. There is a website which maintains all known software weaknesses. It is CWE - [[19]]. CWE™ International in scope and free for public use, CWE provides a unified, measurable set of software weaknesses that is enabling more effective discussion, description, selection, and use of software security tools and services that can find these weaknesses in source code and operational systems as well as better understanding and management of software weaknesses related to architecture and design.
  • 2. lets search "Heap-based buffer overflow" and find the detail here[[20]].
  • 3. It shows the detail as "A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc()". It also shows, Time of Introduction (of this weakness like architectural design or implementation), Available platform (like C/C++), Common Consequences ( in terms of CIA -Confidentiality, Integrity, Availability, Access Control or Other)

Exercise 8: How this vulnerability relates to code and CIA

From exercise 7, we get to know the weakness detail. It shows the consequences as below:

  • 1. Availability :

Technical Impact: DoS: crash / exit / restart; DoS: resource consumption (CPU); DoS: resource consumption (memory) Buffer overflows generally lead to crashes. Other attacks leading to lack of availability are possible, including putting the program into an infinite loop.

  • 2. Integrity, Confidentiality, Availability, Access Control

Technical Impact: Execute unauthorized code or commands; Bypass protection mechanism; Modify memory Buffer overflows often can be used to execute arbitrary code, which is usually outside the scope of a program's implicit security policy. Besides important user data, heap-based overflows can be used to overwrite function pointers that may be living in memory, pointing it to the attacker's code. Even in applications that do not explicitly use function pointers, the run-time will usually leave many in memory. For example, object methods in C++ are generally implemented using function pointers. Even in C programs, there is often a global offset table used by the underlying runtime.

  • 3. Example code:

While buffer overflow examples can be rather complex, it is possible to have very simple, yet still exploitable, heap-based buffer overflows:

Example Language: C

  1. define BUFSIZE 256

int main(int argc, char **argv) {

char *buf;

buf = (char *)malloc(sizeof(char)*BUFSIZE);

strcpy(buf, argv[1]);


The buffer is allocated heap memory with a fixed size, but there is no guarantee the string in argv[1] will not exceed this size and cause an overflow.

February 22th - 25th -- Tutorial 9

In our previous tutorial, we had seen, how to use a scanner to find a known vulnerability and how this vulnerability is related to some code like buffer overflow. Lets do a buffer overflow exploit. But, before doing that, we need to familiarize ourselves with some coding techniques and tools like debugger. So, in today's tutorial we'll play with file access and permissions. Often, you'll hear that "Hackers were able to gain access through some arbitrary code". So, knowing access and its properties is important. For example, how you'd be able to create a file and execute that file using root privilege (assuming you don't have root privilege)?

Exercise 9

In how many ways you can create file? Probably, if you are a Windows user, then you'll just right click and create a file. You can also use some shell/bash command like 'touch'. But today, we'll see how we can write a simple c code to create a file and give the file some access privileges.

  • We created a simple c code that accepts input as text from user and create the file, write the text to that file and close that file after saving.
  • We used file descriptor open(2). See man open(2).
  • We have seen how we can pass the parameters for a file with flags ReadOnly/WriteOnly/ReadWrite Only File/Create File/Append File.
  • We have seen the header <fcntl.h> and the actual binary values of these flags
  • After that, how the privileges read/write/execute can be given to User/Group/Other by using <sys/stat.h>
  • How to change the file privilege using chmod command (using numbers, u/g/o & +- r/w/x)
  • While passing these parameters, why we are using OR operator instead of AND
  • Finally, we understood what this piece of code mean
  fd = open(datafile, O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR)


//accepts a note as a command line argument and adds it to the end of the file
//file location /tmp/notes
//functions — usage(), fatal(), ec_malloc()
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <fcntl.h>
  #include <sys/stat.h>
  void usage(char *prog_name, char *filename) {
   printf("Usage: %s \n", prog_name, filename);
 void fatal(char *);            // A function for fatal errors
 void *ec_malloc(unsigned int); // An error-checked malloc() wrapper
 int main(int argc, char *argv[]) {
   int fd; // file descriptor
   char *buffer, *datafile;
   buffer = (char *) ec_malloc(100);
   datafile = (char *) ec_malloc(20);
   strcpy(datafile, "/tmp/notes);
   if(argc < 2)                 // If there aren't command-line arguments,
     usage(argv[0], datafile); // display usage message and exit.
  strcpy(buffer, argv[1]);     // Copy into buffer.
  printf("[DEBUG] buffer   @ %p: \'%s\'\n", buffer, buffer);
  printf("[DEBUG] data file @ %p: \'%s\'\n", datafile, datafile);
  strncat(buffer, "\n", 1); // Add a newline on the end.
 // Opening file
  fd = open(datafile, O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR);
    if(fd == -1)
     fatal("in main() while opening file");
    printf("[DEBUG] file descriptor is %d\n", fd);
 // Writing data
   if(write(fd, buffer, strlen(buffer)) == -1)
     fatal("in main() while writing buffer to file");
 // Closing file
  if(close(fd) == -1)
     fatal("in main() while closing file");
  printf("Note has been saved.\n");
 // A function to display an error message and then exit
  void fatal(char *message) {
  char error_message[100];
  strcpy(error_message, "[!!] Fatal Error ");
  strncat(error_message, message, 83);
 // An error-checked malloc() wrapper function
  void *ec_malloc(unsigned int size) {
  void *ptr;
  ptr = malloc(size);
  if(ptr == NULL)
     fatal("in ec_malloc() on memory allocation");
  return ptr; 

Tutorial 10: s-bit, User IDs(Real and Effective), Multiuser note taker

Understanding s-bit

Exercise 10

  • Using code from exercise 9, we'll create access control matrix for the files ./samplenote and /tmp/notes.
  • Then for three users (for example, Alice, Bob and Charlie), we'll try to execute ./samplenote and read /tmp/notes.
  • We'll analyze our observation.

Exercise 11

  • We'll add s bit to ./samplenote (chmod u+s ./samplenote).
  • Repeat exercise 11 and analyze our observation.
  • What happened and why?

Understanding User IDs

Exercise 12

  • A simple code uid_demo.c to understand real user and effective user.
  • Create access control matrix for ./uid_demo
  • For three users (like Alice, Bob and Charlie), we'll execute ./uid_demo and find real user id and effective user id.
  • Analyze our observation

Exercise 13

  • Add s bit (chmod u+s ./uid_demo)
  • Repeat exercise 12.
  • What happened and why?
  • Can we explain exercise 11 now?

Multiuser note taker

So far we've experimented with a single user of a file. What is the case, if we want a file can be written by 3 users but users are only able to view his/her portion? For example, Alice, Bob and Charlie can write to file notes but Alice can read only her writings not Bob's or Charlie's one.

Exercise 14

  • We'll look into the code notetaker.c and note search.c and explain the case

17, 18 Nov : Roll your own vulnerability

Exercise 15

This exercise is from "Hacking The Abacus"- Exercise 3.9

In it, we will create a very contrived, artificial vulnerability and “exploit” for it.

Understanding code injection vulnerabilities and exploits is a non-trivial topic precisely because the common understanding seems to rely on the same notion that underlies the act of cramming too many clothes in a suitcase. Sure, an “overflowed buffer” seems to sound a lot like a burst suitecase, but the analogy is ultimately misleading. A buffer overrun is not about piling copious amounts of data into a small space! Rather, it is about constructing a series of memory write operations to very specific locations; “buffers” (whatever they are) are simply an attractive target because they reside near important control flow artifacts and are often receptor sites for data memory write operations.


You will write a small program that writes to a buffer on its stack. You will also construct a payload to write to this buffer.

Learning Outcomes

Here, we intend you to have the following outcomes:

  • 1. Put into practice your knowledge of shellcode
  • 2. Learn about the function call calling convention
  • 3. Learn about activation records and structure on x86
  • 4. Get a hands-on appreciation of what a simple stack–based buffer overflow actually is


gcc. ld. an editor. nasm. udcli.

In the references below, there is a link that discusses x86 calling conventions, and how mixing control data and normal data in the same contiguous memory location entails risk. You should read it.


This is preparation for understanding basic stack-based buffer overflows, but the larger lesson is that anywhere control information and pointers are mixed with writeable data, you have an opportunity for employing a “write primitive” as an attacker. This includes dynamic instances of structure types on the heap. Or other dynamic memory areas, such as those created via mmap(2) or mapped in from files.

More importantly, this demonstrates how x86 systems fail to take advantage of segmentation support to differentiate between different types of memory. Systems need support for fine-grained separation of memory segments that can be efficiently enforced.

  • Task 1: Construct a Payload Write a small piece of standalone assembly code that executes a system call (do something interesting, like open, read, or write to a file, or fetch the process ID). You know how to do this from previous labs. Don’t create a valid ELF (or do, and just extract .text) Store the resulting bytes in a file. We will revisit it.
  • Task 2: Write a Vulnerable Program Write a small, intentionally-vulnerable program that opens the “payload” file and reads in the bytes to a buffer on the program’s stack; you should construct this buffer and the payload so that you overwrite the return address.

Make sure to disable any protections and enable something else (hints are below).

  • Task 3: Reconstruct a Payload Take your payload from Task 1 and rewrite it so that the right parts of it overwrite the return address on the stack.
  • Task 4: Make it Work Running your victim program on your payload should cause your “injected” shellcode to execute and achieve the goal of your shellcode.

Notes, Hints, and Recommendations

  • You will want to read the overview of calling conventions on x86 here:

  • You may or may not wish to use strcpy(3). Or write your own. Or use memset.
  • You probably want to turn off various protections to make this work:
    • compiling programs with fno-stack-protector
    • turning off ASLR: as root:
    • ‘echo 0 > /proc/sys/kernel/randomize_va_space’
    • marking executables as needing executable data areas: ‘execstack -s a.out’
  • You can see an example of a gdb trace of an overflow in action at:˜locasto/teaching/2011/ISSA/code/session.txt

19,20 Nov :Case Study: A Simple Stack-based Buffer Overflow (Exercise 3.10 from Hacking the Abacus)

Exercise 16

This lab is a guided exercise and walkthrough of the libpng stack-based vulnerability and a PoC exploit (thanks to Chris Evans).


In this lab, we will take an up-close look at a real vulnerability. The point isn’t to see this as the state of the art – instead, it is about seeing exactly what the semantics of a code injection attack are and how it depends on the environment of the program’s process address space and code! One special thing to note is how the actual control transfer happens way after the target buffer is overflowed and target state is corrupted!

Only after the program begins to return up a deep call chain (after doing a bunch of other valid processing) does the exploit complete and begin execution (well, crashing in this particular case b/c the payload is malformed).


The hardest part of this lab is actually the setup; you will need to fetch the vulnerable version of libpng from an archive and a library dependency (zlib). You then need to compile from source and then compile a utility (a sample PNG viewer) included with the libpng source. If you follow the instructions in the various Makefiles you will be fine. But consider this a baptism by fire of the Linux command line and Makefiles.

You should read these files first:


You can find a PoC file here: pngtest_bad.png

Learning Objectives

The point of this lab is to provide a hands-on assessment of an old stack-based buffer overflow vulnerability and the resulting exploit. This takes the previous lab and cranks it up a notch: the vuln is in real, widely used software, and we get a richer address space than just a simple program copying a string from a file.


Using gdb, this session we will take a guided tour of the operation and execution of a real exploit on a real (but old) vulnerability. While the specific type of vulnerability is less likely to be a problem or easily exploitable for most current commodity systems, the principles involved are illustrative from both an attack and defense perspective.

  • Task 1: Setup Find the vulnerable version of libpng and install it to a local subdirectory (not the whole machine) following the directions in the Makefile and documentation.
  • Task 2: Compile rpng-x In the contrib/gregbook directory, compile the rpng-x viewer against your vulnerable library.
  • Task 3: Run rpng-x on the PoC exploit PNG Run rpng-x on Chris Evan’s sample PNG. Does the program crash? Now run it in gdb and observe the state of the process when it crashes.
  • Task 4: Analysis Using gdb and the source code, diagnose what happened.

We can look at a wealth of information in both the source code (at the source level definition of various functions) and at the assembly level. We first observe how rpngx reacted when fed the proof-of-concept test case to exercise the vulnerability. We observe some output error messages and then a segfault. We start rpng-x in gdb and begin to place breakpoints from the png handle tRNS() function in the ’pngrutil.c’ file. Reconstruct the call chain from the source!

Hint: you can drive the initial location by searching for the error message. At each step, keep track of the state of the stack: what activation records are there, and what information do they contain?

We place breakpoints at different related functions (e.g., png crc finish, png read data, png default read data) and look at them both at the source level as well as disassembly within gdb. One tricky part of this procedure is that the call chain involves a function pointer, but simple stumbling around the right source files and reading the code will help you out. Also, the function pointer eventually resolves to a function that calls fread().

The key problem seemed to be that the length of a fixed-sized local buffer (256 declared bytes – find out what constant this is!) – and specifically the amount of space allocated on the stack (300 bytes) was smaller than the 512 bytes of data that fread(3) ultimately stuffs into that fixed-sized local buffer.

  • Task 5: Modify PoC We can able to modify the PoC exploit to include shell code that does something interesting, such as issuing a CC or invoking exit(2) with some value. Change the PoC file in a hex editor. Inject a NOP sled over Chris’s payload, then place a CC in a strategic spot. Where the code returns to depends on your environment, so you may have to fiddle a bit and map the offsets in the file to the address in memory on the stack.
  • Task 6: Drop a Shell If you are creative enough, you can spawn a shell once you get the return address correct (via stack examination of where the NOP sled landed on the


Notes, Hints, and Recommendations

Like the previous lab, your machine likely has a number of countermeasures in place already, and performing basic exploit research to understand the basic concepts (e.g., those presented in “Smashing the Stack for Fun and Profit” ) requires you to turn them off to remove some complexity. This includes, but isn’t limited to:

  • compiling programs with fno-stack-protector
*turning off ASLR: as root,
  • ‘echo 0 > /proc/sys/kernel/randomize_va_space’
*marking executables as needing executable data areas: execstack -s a.out