diff --git a/ACKNOWLEDGEMENTS b/ACKNOWLEDGEMENTS new file mode 100644 index 0000000..d17122e --- /dev/null +++ b/ACKNOWLEDGEMENTS @@ -0,0 +1,15 @@ +ACKNOWLEDGMENTS / AUTHORS OF MODERN BINARY EXPLOITATION + +Original Authors + * Patrick Biernat + * Jeremy Blackthorne + * Alexei Bulazel + * Branden Clark + * Sophia D'Antoine + * Markus Gaasedelen + * Austin Ralls + +Special thanks to + * The RPI CS Department for giving us this opportunity and letting us run with it + * Professor Bülent Yener for sponsoring such a course + * Our students who put up with us all semester diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..612c599 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,36 @@ +# RPISEC copyright/license should go here + +cmake_minimum_required(VERSION 2.8) + +project(MBE) +enable_testing() +include_directories("./include") + +# Settings +set(MBE_FLAGS "-m32 -O0 -fno-inline-functions") +set(NO_MITS_FLAGS "-z execstack -z norelro -fno-stack-protector") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MBE_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MBE_FLAGS}") + +# Handy macro +MACRO(SUBDIRLIST result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + FOREACH(child ${children}) + IF(IS_DIRECTORY ${curdir}/${child}) + LIST(APPEND dirlist ${child}) + ENDIF() + ENDFOREACH() + SET(${result} ${dirlist}) +ENDMACRO() + +MACRO(SET_FLAGS target flags) + SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_FLAGS ${flags}) + SET_TARGET_PROPERTIES(${target} PROPERTIES LINK_FLAGS ${flags}) +ENDMACRO() + +# Where the files students get will go (install dir) +set(RELEASE_DIR "${CMAKE_BINARY_DIR}/release") + +### Build the code ### +add_subdirectory(src) diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..19603fc --- /dev/null +++ b/INSTALL @@ -0,0 +1,7 @@ +Build instructions + +Make an Ubuntu 14.04 x32 server VM for building/testing. + +mkdir ./build && cd ./build +cmake ../ +make && make install diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0b55b16 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2015, RPISEC +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e8caac9 --- /dev/null +++ b/README.md @@ -0,0 +1,289 @@ +# Modern Binary Exploitation - CSCI 4968 +This repository contains the materials as developed and used by [RPISEC](http://rpis.ec) to +teach Modern Binary Exploitation at [Rensselaer Polytechnic Institute](http://rpi.edu) in +Spring 2015. This was a university course developed and run solely by students to teach +skills in vulnerability research, reverse engineering, and binary exploitation. + +

+MBE +

+ +## About the Course + +Vulnerability research & exploit development is something totally outside the bounds of what +you see in a normal computer science curriculum, but central to a lot of what we RPISEC +members find ourselves doing in our free time. We also find that subjects in offensive +security tend to have a stigma around them in university that we would like to help shake +off. These are practical, applied skills that we're excited to share with those interested +in learning. + +The question this course posed was _'Can we teach a bunch of programmers how to pwn?'_ + +**Course website:** http://security.cs.rpi.edu/courses/binexp-spring2015/ + +**Syllabus:** http://security.cs.rpi.edu/courses/binexp-spring2015/Syllabus.pdf + +### Course Abstract + +>_Cybersecurity is one of the fastest growing fields in computer science, though its study is rarely covered in academia due to its rapid pace of development and its technical specificity. Modern Binary Exploitation will focus on teaching practical offensive security skills in binary exploitation and reverse engineering. Through a combination of interactive lectures, hands on labs, and guest speakers from industry, the course will offer students a rare opportunity to explore some of the most technically involved and fascinating subjects in the rapidly evolving field of security._ + +>_The course will start off by covering basic x86 reverse engineering, vulnerability analysis, and classical forms of Linux-based userland binary exploitation. It will then transition into protections found on modern systems (Canaries, DEP, ASLR, RELRO, Fortify Source, etc) and the techniques used to defeat them. Time permitting, the course will also cover other subjects in exploitation including kernel-land and Windows based exploitation._ + +### Prerequisite Knowledge +This course carried a prereq of +[Computer Organization - CSCI 2500](http://catalog.rpi.edu/preview_course_nopop.php?catoid=10&coid=16571) +at RPI. Computer Organization is RPI's basic computer architecture course that teaches +things like C, MIPS assembly, x86 assembly, Datapaths, CPU Pipelining, CPU Caching, +Memory Mapping, etc. + +Our expected demographic for Modern Binary Exploitation was students with zero reverse +engineering or binary exploitation knowledge. That said, to be able to take this course +you will probably need at least the following skills. +* Working knowledge of C/C++ +* Any assembly level experience +* Basic Linux command line experience + +### Lecture Breakdown +Lecture | Title | Topics +------- | ----- | ------ +01 | Syllabus and Review | Linux, C, x86 +02 | Introduction to Reverse Engineering | Tools and the VM +03 | Extended Reverse Engineering | GDB & IDA +04 | Intro to Memory Corruption | ELF, the stack, calling conventions, buffer overflows +05 | Shellcoding / Code Injection | Writing shellcode, developing scenario relevant payloads +06 | Format String Vulnerabilities | Format strings, DTOR/GOT overwrites +07 | DEP and ROP | Data Execution Prevention, writing ROP chains, ret2libc +08 | Secure Systems and Game Console Exploitation | OpenBSD, SELinux, GRSEC, Game Console Exploitation +09 | Address Space Layout Randomization (ASLR) | Overview, info leaks, partial overwrites, ASLR closure +10 | Heap Exploitation | Heap structure and concepts, corruption, use after free +11 | Misc Concepts and Stack Cookies | Signed/unsignedness issues, uninitialized data, etc, bypassing stack cookies +12 | C++ Differences and Concepts | C++ basics, structures, vTables, exceptions +13 | Linux Kernel Exploitation | Kernel basics, kernel exploitation, mitigations (mmap_min_addr, kallsyms, SMEP/SMAP), bypassing mitigations +14 | Exploitation on 64bit, ARM, Windows | Exploitation differences on other architectures & platforms +15 | Automation & The Future of Exploitation | Fuzzing, taint analysis, dynamic instrumentation, SMT/SAT solvers + +### Lab Breakdown +Lab | Topic | Corresponding Lectures +--- | ----- | ---------------------- +[01](/src/lab01) | Reverse Engineering | 01-03 +[02](/src/lab02) | Memory Corruption | 04 +[03](/src/lab03) | Shellcoding | 05 +[04](/src/lab04) | Format Strings | 06 +[P1](/src/project1) | Project 1 | 01-06 (Comprehensive) +[05](/src/lab05) | DEP and ROP | 07 +**XX** | **ASLR should always be enabled from this point on** | **See VM Information for details** +[06](/src/lab06) | ASLR | 09 +[07](/src/lab07) | Heap | 10 +[08](/src/lab08) | Misc and Stack Cookies | 11 +[09](/src/lab09) | C++ | 12 +[P2](/src/project2) | Project 2 | 01-12 (Comprehensive) +[10](/src/lab10) | Linux Kernel | 13 + +### Repository Breakdown +* [src/](/src) - Source code for labs +* [setup_wargame.sh](/setup_wargame.sh),[external_tools.sh](/external_tools.sh) - Install scripts to setup MBE on an Ubuntu 14.04 32-bit machine +* [MBE_release.tar.gz](https://github.com/RPISEC/MBE/releases/download/v1.0_release/MBE_release.tar.gz) - Binaries for labs and projects +* [MBE_lectures.tar.gz](https://github.com/RPISEC/MBE/releases/download/v1.0_release/MBE_lectures.tar.gz) - PDFs of all lecture slides +* [MBE_VM.vmdk.gz](https://github.com/RPISEC/MBE/releases/download/v1.0_release/MBE_VM.vmdk.gz) - A vmdk (disk image) of a VM that is already setup + +## Labs - The RPISEC Warzone + +The Warzone is a custom wargame that was built from the ground up for this course. It provided +a complete and consistent learning platform for us to release the labs and projects to the +students. The wargame was built ontop of a vanilla Ubuntu 14.04 32-bit server install, and is +modeled after existing local privilege escalation themed wargames. If you have ever played +the fantastic [SmashTheStack IO](http://io.smashthestack.org/) wargame, the Warzone has a +somewhat similar structure. + +

+RPISEC Warzone +

+ +Some basic tweaks have been made in an attempt to isolate players from each other and create +an individual experience, but it's probably far from perfect. It also comes pre-installed with +some tools, scripts, and configs that can make a beginner's life a bit easier in exploit +development. + +You can roll with the Warzone we designed, or you can try to setup your own using our scripts. +___ +### Option One - Pre-made Warzone VM +As the years pass, compilers will change, security will improve, and the challenges in this +repo may no longer be solvable. Because of this, we have created a virtual machine disk image +that closely replicates the universal Warzone wargame server we ran for the duration of this +course. The VM has all the tools setup, challenges pre-compiled, and lab accounts ready to go. +Hopefully it will endure the test of time. + +#### Virtual Machine Setup + +RPISEC is a huge advocate of VMware because of its quality and stability, so we recommend +using our disk image below with VMware Workstation, VMware Fusion, or VMware Player. That +said, it should also work with VirtualBox. + +VMware provides a great [2 minute video](https://www.youtube.com/watch?v=I6WfFLQwoPg) on how to setup a virtual machine using an existing disk image. + +

+Final +

+ +1. Download [MBE_VM.vmdk.gz](https://github.com/RPISEC/MBE/releases/download/v1.0_release/MBE_VM.vmdk.gz) from our release page +2. Extract the archive to obtain the disk image +3. Using VMware go to `File->New Virtual Machine...` and create a Custom VM +4. When prompted for `Guest Operating System Installation`, select `I will install the operating system later` +5. You can use the default options for almost all the prompts you encounter. For specs, we suggest the following: + * 1 processor / core + * 512 MB of RAM + * NAT Networking +6. When prompted to `Select a Disk`, select `Use an existing virtual disk` and navigate to the .vmdk you extracted +7. In the end your final screen should look something like this. Click Finish and then power on the VM. + +

+Final +

+ + +#### How to Play +We tried to keep the course fairly self contained but if you find yourself lost or struggling [OverTheWire's Bandit](http://overthewire.org/wargames/bandit/) is a great intro to Linux wargames. You can also poke people on [IRC](#contact) if you have questions. +* SSH is pre-setup on the VM, but we need an IP. First, sign in through the VMWare or VirtualBox console. To find the IP address type:
+ ```$ ip addr```
+

+ ip addr +

+ and then SSH using [PuTTY](http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe) or a command line client
+ ```$ ssh lab1C@172.16.29.130```
+ ```lab1C@172.16.130's password: lab01start```
+* Navigate to `/levels/labXX` to begin
+ ```$ cd /levels/lab01``` +* The Warzone is structured like any local privilege escalation wargame. +You must exploit a challenge to escalate your privileges and gain access to another user (level). +Once you exploit a level and escalate to the next user (confirm with `whoami`), read their password from their home dir
+ ```$ cat /home/lab1B/.pass``` +* SSH in using the new username and password to continue! + +#### VM information +* admin user: `gameadmin:gameadmin` +* rc files are in `/etc/cfg` + * All lab/project users have symlinks to these files in their home directories + * These files are also symlinked in `/etc/skel` +* To begin a lab, login as `labXC:lab0Xstart` + * e.g. `lab1C:lab01start` + * Projects are `projectX:projectXstart` +* Levels are in `/levels` +* Passwords are in `/home/$USER/.pass` +* Tools are installed in `/tools` and `/usr/local/bin` +* **ASLR must be enabled after completing the DEP/ROP lab, and stay enabled for the rest of the course** + * Until reboot: ```# echo 2 > /proc/sys/kernel/randomize_va_space``` + * Persist reboot: ```# echo 'kernel.randomize_va_space = 2' > /etc/sysctl.d/01-disable-aslr.conf``` + +___ +### Option Two - Make a Custom Warzone +We have provided a bash script that will fully setup the exact environment in the provided VM. + +**DO NOT RUN THIS SCRIPT ON YOUR PERSONAL COMPUTER, RUN IT IN A VIRTUAL MACHINE** + +1. Download [MBE_release.tar.gz](https://github.com/RPISEC/MBE/releases/download/v1.0_release/MBE_release.tar.gz) +2. Move the archive to your VM or machine and extract it
+ **NOTE: It is not recommended to run the script from /tmp, as the sticky bits can screw up wildcards**
+ ```$ tar xzvf MBE_release.tar.gz``` +3. Modify the configuration variables at the top of [setup_wargame.sh](/setup_wargame.sh) to suit your needs +4. Make the setup script executable and run it with sudo
+ ```$ chmod +x ./setup_wargame.sh```
```$ sudo ./setup_wargame.sh```
+It should take about 10-20 minutes to complete depending on your internet connection and the +number of Ubuntu updates. + +## Frequently Asked Questions + +#### Why can't I login to lab01c? +Account names are case sensitive, so please check that you're logging in as lab01**C** + +#### Where are the lab solutions? +Posting solutions spoils the fun and grind of the game, and as an academic resource it is +likely some of these materials may be re-used by other classes in the future. As goes with +most wargames, we would like to ask that you refrain from publicly posting writeups or +exploits to the labs and projects. + +If you are ever stuck on a problem or have any questions, you're more than welcome to +ask on [IRC](#contact). + +#### Why are the lecture slides for XYZ so sparse? +This was a very hands on course, so almost every lecture we had students slinging GDB commands +or following along with us on screen. The slides were accessory to the lectures and may have +gaps or experience brevity at times. With seven of us creating and giving lectures, the slides +and teaching styles vary a bit. We did our best to keep them consistent. + +#### Do you have videos of the lectures? +Sadly we did not record any of the lectures, maybe next time. + +#### Why provide the lab sources to the students? +We're huge fans of reversing / CTF challenges, but reversing is mostly a time problem. With +students juggling other classes and work during the school semester, we'd rather them focus on +learning the exploitation techniques without the overhead of reversing every binary. + +#### These challenges are really easy, what gives? +The 50 students that enrolled had little to no prior computer security experience. The labs +are not designed to be novel CTF challenges, they're meant to be more academic examples paced +to crystallize the concepts. Seasoned CTF'ers can probably blow through most of these +challenges in a day or two. + +#### Why didn't you cover subject XYZ? +If XYZ is related to vulnerability research, we're all ears. The course is far from perfect +and we are open to hear any feedback for improving it. + +#### Will this course be taught again at RPI? +There's a lot of interest in having it offered again, so it's being considered for Spring +2016. The feedback was almost exclusively positive with the students finding the material +challenging, but engaging. We've got dozens of ideas on how to make it even better next time. + +#### Where can I learn more? +Play more wargames: +* [SmashTheStack IO](http://io.smashthestack.org/) +* [Pwnable KR](http://pwnable.kr/) +* [OverTheWire](http://overthewire.org/wargames/) +* [Reversing KR](http://reversing.kr/) +* [W3Challs](http://w3challs.com/) + +And when they're happening, play [CTFs](https://ctftime.org/)! + +#### I have a question, how can I get in touch with you? +Our club keeps a pretty active [IRC](http://rpis.ec/irc) presence. Someone there can probably +answer your question. + +**Server:** `irc.rpis.ec` +**Port:** `6667`, or `6697` (SSL) + + +If you would like a more formal means of communication, you can reach us at `contact [at] rpis.ec` + + +# Licensing +This course was explicitly designed for academic & educational use only. Please keep this +in mind when sharing and distributing our course material. The specific licenses involved +can be found below. + +**Lecture Slides** + +The lectures are covered by the Creative Commons Attribution-NonCommercial 4.0 +International license [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/legalcode). +

+CC BY-NC 4.0 +

+**Code** + +The code in this repo is covered by the BSD 2-Clause license. You can view this license in [LICENSE](/LICENSE). + +# Acknowledgements +Hundreds of hours and countless all nighters went into the production and execution of +this course. This section serves to recognize those who made all of this possible. + +## Original Authors + * Patrick Biernat + * Jeremy Blackthorne + * Alexei Bulazel + * Branden Clark + * Sophia D'Antoine + * Markus Gaasedelen + * Austin Ralls + +## Special Thanks + * The [RPI CS Department](http://www.cs.rpi.edu/) for giving us this opportunity and letting us run with it + * Professor Bülent Yener for sponsoring such a course + * Our students who put up with us all semester diff --git a/external_tools.sh b/external_tools.sh new file mode 100644 index 0000000..f89eb5f --- /dev/null +++ b/external_tools.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +######################################### +# Install Tools +######################################### + +# install pip packages +function install_pip2s { + easy_install -U pip requests + pip2 install colorama git+https://github.com/Gallopsled/pwntools#egg=pwntools docopt capstone ropgadget libformatstr xortool + # capstone is weird + cp /usr/local/lib/python2.7/dist-packages/usr/lib/python2.7/dist-packages/capstone/libcapstone.so /usr/lib/libcapstone.so.3 + # patch pwntools in a terrible way + if [ `uname -i` == 'i686' ]; then + sed -i 's/platform\.machine()/"i386"/' /usr/local/lib/python2.7/dist-packages/pwnlib/asm.py + fi +} +export -f install_pip2s + +# setup gdb PEDA +function install_gdb_peda { + OPWD=$PWD + # remove gdb if it exists on this system + apt-get remove -y gdb + + # grab gdb + cd /tmp + wget -O gdb.pkg.tar.xz http://ftp.gnu.org/gnu/gdb/gdb-7.9.tar.xz + tar -Jxf gdb.pkg.tar.xz + + # compile gdb + cd gdb-* + ./configure --with-python=python2 --prefix=/usr + make + make install + cp -R gdb/data-directory/python /usr/share/gdb + + # remove gdb + cd .. + rm -rf gdb* + echo "gdb hold" | dpkg --set-selections + echo "[+] Installed gdb with python2!" + + cd $TOOLS_DIR + git clone https://github.com/longld/peda.git $TOOLS_DIR/peda + mkdir -p $SKEL_LINK_DIR + touch $GDBINIT + echo "source $TOOLS_DIR/peda/peda.py" >> $GDBINIT + echo "[+] Installed gdb PEDA!" + cd $OPWD +} +export -f install_gdb_peda + +# setup checksec +function install_checksec { + OPWD=$PWD + cd /usr/local/bin + wget https://github.com/slimm609/checksec.sh/raw/master/checksec -O checksec + chmod +x checksec + echo "[+] Installed checksec!" + cd $OPWD +} +export -f install_checksec + +# setup radare2 +function install_radare2 { + OPWD=$PWD + cd $TOOLS_DIR + sudo -u $REALUSER git clone https://github.com/radare/radare2.git + cd radare2 + sudo -u $REALUSER ./sys/install.sh + echo "[+] Installed radare2!" + cd $OPWD +} +export -f install_radare2 + +# setup fixenv +function install_fixenv { + OPWD=$PWD + cd /tmp + git clone https://github.com/hellman/fixenv.git + mv ./fixenv/r.sh /usr/local/bin/fixenv + chmod +x /usr/local/bin/fixenv + rm -rf /tmp/fixenv + echo "[+] Installed fixenv!" + cd $OPWD +} +export -f install_fixenv + +# setup shtest +function install_shtest { + OPWD=$PWD + cd /tmp + git clone https://github.com/hellman/shtest.git + cd shtest + gcc -Wall -m32 shtest.c -o shtest + mv shtest /usr/local/bin/shtest + cd .. + rm -rf shtest + echo "[+] Installed shtest!" + cd $OPWD +} +export -f install_shtest diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..83199d9 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,59 @@ +/* + * Tools for anti-debug/disasm + */ + +/* throws off esp analysis to thwart hexrays */ +#define deathrays \ + __asm__ volatile("push %eax \n"\ + "xor %eax, %eax\n"\ + "jz .+5 \n"\ + ".word 0xC483 \n"\ + ".byte 0x04 \n"\ + "pop %eax \n"); + +/* clear argv to avoid shellcode */ +#define clear_argv(_argv) \ + for (; *_argv; ++_argv) { \ + memset(*_argv, 0, strlen(*_argv)); \ + } +#define clear_envp(_envp) clear_argv(_envp) + +/* disables IO buffering on the file descriptor */ +#define disable_buffering(_fd) setvbuf(_fd, NULL, _IONBF, 0) + +/* clears stdin up until newline */ +void clear_stdin(void) +{ + char x = 0; + while(1) + { + x = getchar(); + if(x == '\n' || x == EOF) + break; + } +} + +/* gets a number from stdin and cleans up after itself */ +unsigned int get_unum(void) +{ + unsigned int res = 0; + fflush(stdout); + scanf("%u", &res); + clear_stdin(); + return res; +} + +void prog_timeout(int sig) +{ + asm("mov $1, %eax;" + "mov $1, %ebx;" + "int $0x80"); +} + +#include +#define ENABLE_TIMEOUT(_time) \ + __attribute__ ((constructor)) void enable_timeout_cons() \ + { \ + signal(SIGALRM, prog_timeout); \ + alarm(_time); \ + } diff --git a/resources/images/cc-by-nc.png b/resources/images/cc-by-nc.png new file mode 100644 index 0000000..5f98214 Binary files /dev/null and b/resources/images/cc-by-nc.png differ diff --git a/resources/images/final.png b/resources/images/final.png new file mode 100644 index 0000000..35548e6 Binary files /dev/null and b/resources/images/final.png differ diff --git a/resources/images/ip_addr.png b/resources/images/ip_addr.png new file mode 100644 index 0000000..d6041fd Binary files /dev/null and b/resources/images/ip_addr.png differ diff --git a/resources/images/mbe.jpg b/resources/images/mbe.jpg new file mode 100644 index 0000000..7c445f9 Binary files /dev/null and b/resources/images/mbe.jpg differ diff --git a/resources/images/vmware.png b/resources/images/vmware.png new file mode 100644 index 0000000..8e076df Binary files /dev/null and b/resources/images/vmware.png differ diff --git a/resources/images/warzone.png b/resources/images/warzone.png new file mode 100644 index 0000000..5d95f8c Binary files /dev/null and b/resources/images/warzone.png differ diff --git a/setup_wargame.sh b/setup_wargame.sh new file mode 100644 index 0000000..7916371 --- /dev/null +++ b/setup_wargame.sh @@ -0,0 +1,457 @@ +#!/bin/bash + +######################################### +# Pre-install checks +######################################### +if [ "$USER" != 'root' ]; then + echo "ERROR: Script must be run using root!" + exit +fi + +######################################### +# Per-Machine Install Variables +######################################### + +# change these things +export PUBKEY="" +export REALUSER='gameadmin' +export HOSTNAME='warzone' +export LEVELS_DIR='/levels' +export SKEL_DIR='/etc/skel' +export SKEL_LINK_DIR='/etc/cfg' +export TOOLS_DIR='/tools' +export TOOLOWNER='toolman' + +# leave as is +export VIMRC=$(echo $SKEL_LINK_DIR/.vimrc) +export SCREENRC=$(echo $SKEL_LINK_DIR/.screenrc) +export BASHRC=$(echo $SKEL_LINK_DIR/.bashrc) +export PROFILE=$(echo $SKEL_LINK_DIR/.profile) +export GDBINIT=$(echo $SKEL_LINK_DIR/.gdbinit) +export R2CONF=$(echo $SKEL_LINK_DIR/.radare2rc) + +######################################### +# Basic Setup +######################################### + +# hush login motd +touch .hushlogin + +# update and apt-get a ton of stuff +apt-get update +apt-get -y upgrade +apt-get -y install unattended-upgrades htop fonts-inconsolata git gdb gcc gcc-multilib g++ g++-multilib git ltrace linux-source openssh-server python-pip ipython python-dev vim guile-2.0 unzip socat libncurses5-dev texinfo +sudo dpkg-reconfigure -plow unattended-upgrades + +# Create main user +useradd -m -s /bin/bash $REALUSER +adduser $REALUSER sudo + +# install ssh key +HOME_DIR=$(eval echo ~$REALUSER) +sudo -u $REALUSER mkdir $HOME_DIR/.ssh +chmod 700 $HOME_DIR/.ssh +sudo -u $REALUSER echo $PUBKEY > $HOME_DIR/.ssh/authorized_keys +chmod 600 $HOME_DIR/.ssh/authorized_keys +chown $REALUSER:$REALUSER $HOME_DIR/.ssh/authorized_keys +restart ssh + +# set perms +chmod 0700 $HOME_DIR + +# set hostname +old_hostname=$(cat /etc/hostname) +hostname "$HOSTNAME" +cat /etc/hosts | sed s/"$old_hostname"/"$HOSTNAME"/ > /tmp/newhosts +mv /tmp/newhosts /etc/hosts +echo "$HOSTNAME" > /etc/hostname + +######################################### +# Configure Wargame Environment +######################################### + +# hardening / wargamification + +# restricting access mostly means make root accessible only, chmod 700 or s/t +chmod 700 `which dmesg` +chmod 700 `which fuser` +chmod 700 `which htop` +chmod 700 `which kill` +chmod 700 `which killall` +chmod 700 `which lsof` +chmod 700 `which pgrep` +chmod 700 `which pkill` +chmod 700 `which ps` +chmod 700 `which screen` +chmod 700 `which su` +chmod 700 `which tmux` +chmod 700 `which top` +chmod 700 `which ulimit` +chmod 700 `which users` +chmod 700 `which w` +chmod 700 `which wall` +chmod 700 `which who` +chmod 700 `which write` + +# restrict access to /proc/maps/ +sed -i 's/^exit 0$//' /etc/rc.local +echo -e 'mount -o remount,hidepid=2 /proc\n' >> /etc/rc.local +mount -o remount,hidepid=2 /proc +chmod 551 /proc + +# make /tmp be not world readable, have sticky bits +chmod 1773 /tmp + +# disable ssh'ing ? (not sure if possible, but these make it harder) +iptables -A OUTPUT -p tcp --dport 22 -j DROP +chmod 700 `which ssh` + +# disable aslr +echo 0 | tee /proc/sys/kernel/randomize_va_space +echo 'kernel.randomize_va_space = 0' > /etc/sysctl.d/01-disable-aslr.conf + +# resource management, stop forkbombs and filling the server (nproclimit) +# make group for wargame users +groupadd gameuser +echo -e '@gameuser\thard\tnproc\t500' >> /etc/security/limits.conf +echo -e '@gameuser\t-\tpriority\t15' >> /etc/security/limits.conf + +# on-login banner +chmod -x /etc/update-motd.d/* +echo -e '#!/bin/sh\ncat /etc/banner' > /etc/update-motd.d/00-banner +chmod +x /etc/update-motd.d/00-banner +echo 'G1swOzMxbSAgICAgICAgX19fX19fX19fX19fX19fX19fX18uX19fICBfX19fX19fX19fX19fX19f +X19fX19fX19fX19fXyAgICAgICAgICAgICAgICANCiAgICAgICAgXF9fX19fXyAgIFxfX19fX18g +ICBcICAgfC8gICBfX19fXy9cXyAgIF9fX19fL1xfICAgX19fIFwgICAgICAgICAgICAgICANCiAg +ICAgICAgIHwgICAgICAgXy98ICAgICBfX18vICAgfFxfX19fXyAgXCAgfCAgICBfXylfIC8gICAg +XCAgXC8gICAgICAgICAgICAgICANCiAgICAgICAgIHwgICAgfCAgIFx8ICAgIHwgICB8ICAgfC8g +ICAgICAgIFwgfCAgICAgICAgXFwgICAgIFxfX19fICAgICAgICAgICAgICANCiAgICAgICAgIHxf +X19ffF8gIC98X19fX3wgICB8X19fL19fX19fX18gIC8vX19fX19fXyAgLyBcX19fX19fICAvICAg +ICAgICAgICAgICANCiAgICAgICAgICAgICAgICBcLyAgICAgICAgICAgICAgICAgICAgICBcLyAg +ICAgICAgIFwvICAgICAgICAgXC8gICAgICAgICAgICAgICANChtbMDszNm0gX18gICAgICBfXyAg +X19fX18gX19fX19fX19fX19fX19fX19fX19fX19fX19fXyAgICBfX19fX19fICBfX19fX19fX19f +Xw0KLyAgXCAgICAvICBcLyAgXyAgXFxfX19fX18gICBcX19fXyAgICAvXF9fX19fICBcICAgXCAg +ICAgIFwgXF8gICBfX19fXy8NClwgICBcL1wvICAgLyAgL19cICBcfCAgICAgICBfLyAvICAgICAv +ICAvICAgfCAgIFwgIC8gICB8ICAgXCB8ICAgIF9fKV8gDQogXCAgICAgICAgLyAgICB8ICAgIFwg +ICAgfCAgIFwvICAgICAvXyAvICAgIHwgICAgXC8gICAgfCAgICBcfCAgICAgICAgXA0KICBcX18v +XCAgL1xfX19ffF9fICAvX19fX3xfICAvX19fX19fXyBcXF9fX19fX18gIC9cX19fX3xfXyAgL19f +X19fX18gIC8NCiAgICAgICBcLyAgICAgICAgIFwvICAgICAgIFwvICAgICAgICBcLyAgICAgICAg +XC8gICAgICAgICBcLyAgICAgICAgXC8gDQoNChtbMG0gICAgICAgIC0tLS0tLS0tLS0tLS0tLS0t +LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgICANCg0KICAgICAg +ICAgICAgICAgICAgICAgICBDaGFsbGVuZ2VzIGFyZSBpbiAvbGV2ZWxzICAgICAgICAgICAgICAg +ICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgUGFzc3dvcmRzIGFyZSBpbiAvaG9tZS9sYWIq +Ly5wYXNzICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgIFlvdSBjYW4gY3JlYXRlIGZp +bGVzIG9yIHdvcmsgZGlyZWN0b3JpZXMgaW4gL3RtcCAgICAgICAgICAgIA0KICAgICAgICAgICAg +ICAgICAgICANCiAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tWyAbWzA7OTJtY29udGFjdEBycGlz +LmVjG1swbSBdLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgICAgDQoNCg==' | base64 -d > /etc/banner +rm /etc/legal + +# disable crontab +touch /etc/cron.allow + +#more I'm sure + +######################################### +# Install Tools +######################################### + +# make tools owner +useradd -M -s /bin/false $TOOLOWNER + +# make tools dir +mkdir $TOOLS_DIR +chmod 777 $TOOLS_DIR + +source ./external_tools.sh +install_pip2s +install_gdb_peda +install_checksec +install_radare2 +install_fixenv +install_shtest + +# set perms +chown -R $TOOLOWNER:$TOOLOWNER $TOOLS_DIR/* +chmod 775 $TOOLS_DIR + +######################################### +# Create Skeleton User +######################################### + +# this should populate the skel folder with symlinks. That way any user we make later on the +# server will auto copy these settings, and they will be in a single location for editing. +export SKEL=$SKEL_DIR +mkdir $SKEL_LINK_DIR + +# setup vim config +touch $VIMRC +(echo syntax on \ +; echo set tabstop=4 softtabstop=4 shiftwidth=4 \ +; echo set expandtab ai number ruler \ +; echo highlight Comment ctermfg=green \ +; echo set viminfo=) >> $VIMRC +echo "[+] Configured VIM!" + +# setup .bashrc +cp $SKEL_DIR/.bashrc $BASHRC +(echo -e "\n# Start user config" \ +; echo "export TERM=screen-256color" \ +; echo "export PS1='\[\033[01;31m\]\u\[\033[00;37m\]@\[\033[01;32m\]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" \ +; echo "export ENV='/etc/profile'" \ +; echo "alias grep='grep --color=auto'" \ +; echo "alias ls='ls --color=auto -l'" \ +; echo "alias checksec='checksec --file'" \ +; echo "alias ropgadget='ROPgadget --binary'" \ +; echo "alias gdb='gdb -q'") >> $BASHRC +echo "[+] Configured bash!" + +# setup .profile +cp $SKEL_DIR/.profile $PROFILE +echo "[+] Configured profile!" + +# setup .gdbinit +(echo -e "\nset disassembly-flavor intel" \ +; echo "set detach-on-fork off" \ +; echo "set follow-fork-mode child") >> $GDBINIT +echo "[+] Configured gdb!" + +# setup radare2 config +echo 'e scr.utf8 = true' > $R2CONF +mkdir -p $SKEL_LINK_DIR/.config/radare2 +ln -s /dev/null $SKEL_LINK_DIR/.config/radare2/history + +# make sure the admin user gets these pretty confs, too +cp $SKEL_LINK_DIR/.* /home/$REALUSER/ +chown -R $REALUSER:$REALUSER $(eval echo ~$REALUSER) + +# start fresh and add symlinks +rm -rf $SKEL_DIR +mkdir $SKEL_DIR +ln -s $VIMRC $SKEL_DIR/.vimrc +ln -s $BASHRC $SKEL_DIR/.bashrc +ln -s $PROFILE $SKEL_DIR/.profile +ln -s $GDBINIT $SKEL_DIR/.gdbinit +ln -s $R2CONF $SKEL_DIR/.radare2rc +ln -s $SKEL_LINK_DIR/.config $SKEL_DIR/.config + +# disable bash history +ln -s /dev/null $SKEL_DIR/.bash_history +chattr -fR +i $SKEL_LINK_DIR + +######################################### +# Setup wargame +######################################### + +function setup_level { + if [ "$#" -ne 7 ]; then + echo "ERROR: Missing arguments" + exit + fi + # rename arguments + username=$1 + next_level=$2 + next_password=$3 + level_subdir=$4 + local level_files=("${!5}") + local level_owners=("${!6}") + local level_perms=("${!7}") + + # unchattr passwd + chattr -f -i /etc/passwd + chattr -f -i /etc/shadow + + # make current level user + user_home=$(eval echo ~$username) + id -u $username &> /dev/null; uexist=$?; + if [ "$uexist" -eq "1" ]; then + useradd -m -s /bin/bash -G gameuser $username + user_home=$(eval echo ~$username) + echo $username:$([ -f $user_home/.pass ] && cat $user_home/.pass \ + || echo $level_subdir"start") | chpasswd + fi + # make next level user + next_home=$(eval echo ~$next_level) + id -u $next_level &> /dev/null; uexist=$?; + if [ "$uexist" -eq "1" ]; then + useradd -m -s /bin/bash -G gameuser $next_level + next_home=$(eval echo ~$next_level) + echo $next_level:$next_password | chpasswd + echo $next_password > $next_home/.pass + chown $next_level:$next_level $next_home/.pass + chmod 0400 $next_home/.pass + fi + # make sure everything is unchattr'd + chattr -fR -i $user_home + chattr -fR -i $next_home + chattr -fR -i $LEVELS_DIR + + # add the levels and perms + llen=${#level_files[@]} + for (( i=0; i<${llen}; i++ )); do + chown ${level_owners[$i]} $LEVELS_DIR/$level_subdir/${level_files[$i]} + chmod ${level_perms[$i]} $LEVELS_DIR/$level_subdir/${level_files[$i]} + done + + # re-chattr levels/directories + chattr -fR +i $user_home + chattr -fR +i $next_home + chattr -fR +i $LEVELS_DIR + + # re-chattr passwd + chattr -f +i /etc/passwd + chattr -f +i /etc/shadow +} + +function add_simple_level { + local level_files=("$1" "$1.c") + local level_owners=("$2:$1" "$1:$1") + local level_perms=("4550" "0400") + setup_level $1 $2 $3 $4 level_files[@] level_owners[@] level_perms[@] +} + +function add_socat_on_start { + # $1 = working directory + # $2 = exec cmd + # $3 = listen part + # $4 = user to run exec as + echo -e "cd $1\nsocat TCP-LISTEN:$3,reuseaddr,fork,su=$4 EXEC:\"$2\" &" >> /etc/rc.local +} + +# Stick levels folder where it belongs +mkdir $LEVELS_DIR +if [ -d "./levels" ] +then + cp -R ./levels/* $LEVELS_DIR +else + echo "ERROR: ./levels not found" + exit +fi + +# Add LICENSE and ACKNOWLEDGEMENTS +cp LICENSE $LEVELS_DIR/LICENSE +cp ACKNOWLEDGEMENTS $LEVELS_DIR/ACKNOWLEDGEMENTS +chmod 444 $LEVELS_DIR/ACKNOWLEDGEMENTS +chmod 444 $LEVELS_DIR/LICENSE + +# Add lab01 +# Will throw some errors since no source file, but w/e +lab=lab1 +add_simple_level $lab'C' $lab'B' 'n0_str1ngs_n0_pr0bl3m' lab01 +add_simple_level $lab'B' $lab'A' '1337_3nCRyptI0n_br0' lab01 +add_simple_level $lab'A' $lab'end' '1uCKy_Gue55' lab01 + +# Add lab02 +lab=lab2 +add_simple_level $lab'C' $lab'B' '1m_all_ab0ut_d4t_b33f' lab02 +add_simple_level $lab'B' $lab'A' 'i_c4ll_wh4t_i_w4nt_n00b' lab02 +add_simple_level $lab'A' $lab'end' 'D1d_y0u_enj0y_y0ur_cats?' lab02 + +# Add lab03 +lab=lab3 +add_simple_level $lab'C' $lab'B' 'th3r3_iz_n0_4dm1ns_0n1y_U!' lab03 +add_simple_level $lab'B' $lab'A' 'wh0_n33ds_5h3ll3_wh3n_U_h4z_s4nd' lab03 +add_simple_level $lab'A' $lab'end' 'sw00g1ty_sw4p_h0w_ab0ut_d3m_h0ps' lab03 + +# Add lab04 +lab=lab4 +add_simple_level $lab'C' $lab'B' 'bu7_1t_w4sn7_brUt3_f0rc34b1e!' lab04 +add_simple_level $lab'B' $lab'A' 'fg3ts_d0e5n7_m4k3_y0u_1nv1nc1bl3' lab04 +add_simple_level $lab'A' $lab'end' '1t_w4s_ju5t_4_w4rn1ng' lab04 + +# Add lab05 +lab=lab5 +add_simple_level $lab'C' $lab'B' 's0m3tim3s_r3t2libC_1s_3n0ugh' lab05 +add_simple_level $lab'B' $lab'A' 'th4ts_th3_r0p_i_lik3_2_s33' lab05 +add_simple_level $lab'A' $lab'end' 'byp4ss1ng_d3p_1s_c00l_am1rite' lab05 + +# Add lab06 +lab=lab6 +add_simple_level $lab'C' $lab'B' 'p4rti4l_0verwr1tes_r_3nuff' lab06 +level_files=($lab'B' $lab'B.c' $lab'B.readme') +level_owners=($lab'A:'$lab'B' $lab'B:'$lab'B' $lab'B:'$lab'B') +level_perms=('0550' '0400' '0400') +setup_level $lab'B' $lab'A' 'strncpy_1s_n0t_s0_s4f3_l0l' lab06 level_files[@] level_owners[@] level_perms[@] +add_socat_on_start "$LEVELS_DIR/lab06" "timeout 300 $LEVELS_DIR/lab06/lab6B" 6642 $lab'A' +add_simple_level $lab'A' $lab'end' 'eye_gu3ss_0n_@ll_mah_h0m3w3rk' lab06 + +# Add lab07 +lab=lab7 +add_simple_level $lab'C' $lab'A' 'us3_4ft3r_fr33s_4re_s1ck' lab07 +level_files=($lab'A' $lab'A.c' $lab'A.readme') +level_owners=($lab'end:'$lab'A' $lab'A:'$lab'A' $lab'A:'$lab'A') +level_perms=('0550' '0400' '0400') +setup_level $lab'A' $lab'end' '0verfl0wz_0n_th3_h3ap_4int_s0_bad' lab07 level_files[@] level_owners[@] level_perms[@] +add_socat_on_start "$LEVELS_DIR/lab07" "timeout 60 $LEVELS_DIR/lab07/lab7A" 7741 $lab'end' + +# Add lab08 +lab=lab8 +add_simple_level $lab'C' $lab'B' '3v3ryth1ng_Is_@_F1l3' lab08 +add_simple_level $lab'B' $lab'A' 'Th@t_w@5_my_f@v0r1t3_ch@11' lab08 +level_files=($lab'A' $lab'A.c' $lab'A.readme') +level_owners=($lab'end:'$lab'A' $lab'A:'$lab'A' $lab'A:'$lab'A') +level_perms=('0550' '0400' '0400') +setup_level $lab'A' $lab'end' 'H4x0r5_d0nt_N33d_m3t4pHYS1c5' lab08 level_files[@] level_owners[@] level_perms[@] +add_socat_on_start "$LEVELS_DIR/lab08" "timeout 60 $LEVELS_DIR/lab08/lab8A" 8841 $lab'end' + +# Add lab09 (cpp and networked) +lab=lab9 +level_files=($lab'C' $lab'C.cpp' $lab'C.readme') +level_owners=($lab'A:'$lab'C' $lab'C:'$lab'C' $lab'C:'$lab'C') +level_perms=('0550' '0400' '0400') +setup_level $lab'C' $lab'A' '1_th0uGht_th4t_w4rn1ng_wa5_l4m3' lab09 level_files[@] level_owners[@] level_perms[@] +add_socat_on_start "$LEVELS_DIR/lab09" "timeout 60 $LEVELS_DIR/lab09/lab9C" 9943 $lab'A' +level_files=($lab'A' $lab'A.cpp' $lab'A.readme') +level_owners=($lab'end:'$lab'A' $lab'A:'$lab'A' $lab'A:'$lab'A') +level_perms=('0550' '0400' '0400') +setup_level $lab'A' $lab'end' '1_d1dNt_3v3n_n33d_4_Hilti_DD350' lab09 level_files[@] level_owners[@] level_perms[@] +add_socat_on_start "$LEVELS_DIR/lab09" "timeout 300 $LEVELS_DIR/lab09/lab9A" 9941 $lab'end' + +# Add project1 +lab=project1 +level_files=('tw33tchainz' 'README') +level_owners=($lab'_priv:'$lab $lab':'$lab) +level_perms=('4550' '0400') +setup_level $lab $lab'_priv' 'm0_tw33ts_m0_ch4inz_n0_m0n3y' $lab level_files[@] level_owners[@] level_perms[@] + +# Add project2 +lab=project2 +level_files=('rpisec_nuke' 'README' 'GENERAL_CROWELL.key' 'GENERAL_DOOM.key' 'GENERAL_HOTZ.key') +level_owners=($lab'_priv:'$lab $lab':'$lab $lab'_priv:'$lab $lab'_priv:'$lab $lab'_priv:'$lab) +level_perms=('4550' '0400' '0400' '0400' '0400') +setup_level $lab $lab'_priv' 'th3_pr1nt_funct10n_w4s_100_l!n3s_al0ne' $lab level_files[@] level_owners[@] level_perms[@] +add_socat_on_start "$LEVELS_DIR/project2" "timeout 300 $LEVELS_DIR/project2/rpisec_nuke" 31337 $lab'_priv' + +# Add lecture examples +lecuser=lecture +lecpriv=lecture_priv +## Make users +chattr -fR -i /etc/passwd +chattr -fR -i /etc/shadow +useradd -m -s /bin/bash -G gameuser $lecuser +echo $lecuser':'$lecuser | chpasswd +useradd -m -s /bin/bash -G gameuser $lecpriv +passwd -l $lecpriv +chattr -fR +i $(eval echo ~$lecuser) +chattr -fR +i $(eval echo ~$lecpriv) +chattr -fR +i /etc/passwd +chattr -fR +i /etc/shadow +## Set permissions +chattr -fR -i $LEVELS_DIR +find /levels/lecture -type f | xargs -I {} chown $lecpriv:$lecuser {} {} +find /levels/lecture -type f | xargs -I {} chmod 4550 {} {} +find /levels/lecture -type f -name '*.c*' | xargs -I {} chown $lecuser:$lecuser {} {} +find /levels/lecture -type f -name '*.c*' | xargs -I {} chmod 0400 {} {} +chattr -fR +i $LEVELS_DIR + +# This needs to be here +echo 'exit 0' >> /etc/rc.local + +echo '*** DONE! ***' +echo -n 'reboot now? (y/n): ' +read REBOOT +if [ "$REBOOT" == 'y' ]; then + reboot +else + echo 'You must reboot for certain settings to kick in' + echo 'Please reboot soon' +fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..f89eca1 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds all of the level directories +SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR}) +foreach(subdir ${SUBDIRS}) + message(STATUS "Building ${subdir}...") + add_subdirectory(${subdir}) +endforeach() diff --git a/src/lab01/CMakeLists.txt b/src/lab01/CMakeLists.txt new file mode 100644 index 0000000..30ff30f --- /dev/null +++ b/src/lab01/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab1C lab1C.c) + +add_executable(lab1B lab1B.c) +SET_FLAGS(lab1B "-s") + +add_executable(lab1A lab1A.c) +SET_FLAGS(lab1A "-s") + +# These are the files we want to give students +install(TARGETS lab1C lab1B lab1A DESTINATION "${RELEASE_DIR}/lab01") diff --git a/src/lab01/README.md b/src/lab01/README.md new file mode 100644 index 0000000..0fcacb4 --- /dev/null +++ b/src/lab01/README.md @@ -0,0 +1,16 @@ +## Reversing Labs +I tried to base these more or less on Jeremy's labs. If you get the +key correct, you get a shell, so we can structure these the same way +we've been doing the rest of the levels. + +### Lab C +Simple Integer compare, obvious yes/no path. + +### Lab B +XOR'd string, you supply key by getting the difference between your input +and a hardcoded value. "Correct" path is obfuscated so you have to actually xor +stuff together and reason it out (or thats the idea) + +### Lab A +Simple keygen. The serial is calculated by adding to a base checksum and doing +some XOR / modulus stuff. diff --git a/src/lab01/lab1A.c b/src/lab01/lab1A.c new file mode 100644 index 0000000..536cb28 --- /dev/null +++ b/src/lab01/lab1A.c @@ -0,0 +1,86 @@ +/* +Modern Binary Exploitation +Lab 1: Introduction to Reverse Engineering +LabA: Keygen + +gcc -s -m32 ./labA.c +*/ + +#include +#include +#include +#include +#include + +#include "utils.h" +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" + +ENABLE_TIMEOUT(60) + +int auth(char * username, unsigned int serial) { + int i, len; + unsigned int chk; + + username[strcspn(username, "\n")] = 0; + len = strnlen(username, 32); + + deathrays; + if (len < 6) { + return 1; + } + + if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) + { + printf(ANSI_COLOR_GREEN ".---------------------------.\n"); + printf(ANSI_COLOR_RED "| !! TAMPERING DETECTED !! |\n"); + printf(ANSI_COLOR_GREEN "'---------------------------'\n"); + + return 1; + } + + chk = (username[3] ^ 0x1337) + 0x5EEDED; + for(i=0; i 127) { + return 1; + } + chk += (username[i] ^ chk) % 1337; + } + + if (serial != chk) { + return 1; + } + + return 0; +} + +int main(int argc, char ** argv) { + unsigned int serial; + char username[32]; + + deathrays; + printf(".---------------------------.\n"); + printf("|--------- RPISEC --------|\n"); + printf("|+ SECURE LOGIN SYS v. 3.0 +|\n"); + printf("|---------------------------|\n"); + + printf("|~- Enter your Username: ~-|\n"); + printf("'---------------------------'\n"); + fgets(username, 32, stdin); + + printf(".---------------------------.\n"); + printf("| !! NEW ACCOUNT DETECTED !!|\n"); + printf("|---------------------------|\n"); + printf("|~- Input your serial: ~-|\n"); + printf("'---------------------------'\n"); + scanf("%u", &serial); + + if(!auth(username, serial)) { + printf("Authenticated!\n"); + system("/bin/sh"); + return EXIT_SUCCESS; + } + + return EXIT_FAILURE; +} diff --git a/src/lab01/lab1B.c b/src/lab01/lab1B.c new file mode 100644 index 0000000..3232848 --- /dev/null +++ b/src/lab01/lab1B.c @@ -0,0 +1,121 @@ +/* +Modern Binary Exploitation +Lab 1: Introduction to Reverse Engineering +LabB: Harder CrackMe + +gcc -s -m32 ./labB.c +*/ + +#include +#include +#include +#include + +#include "utils.h" + +void decrypt(unsigned int key) { + unsigned int len; + unsigned int i; + char str[] = "Q}|u`sfg~sf{}|a3"; + + deathrays; + len = strlen(str); + + for (i=0; i +#include + +int main(int argc, char ** argv) { + int input; + + printf("-----------------------------\n"); + printf("--- RPISEC - CrackMe v1.0 ---\n"); + printf("-----------------------------\n"); + printf("\nPassword: "); + scanf("%d", &input); + + if (input == 0x149A) { + printf("\nAuthenticated!\n"); + system("/bin/sh"); + } + else { + printf("\nInvalid Password!!!\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/lab02/CMakeLists.txt b/src/lab02/CMakeLists.txt new file mode 100644 index 0000000..0b1a2dc --- /dev/null +++ b/src/lab02/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab2C lab2C.c) +SET_FLAGS(lab2C "-O0 -fno-stack-protector") + +add_executable(lab2B lab2B.c) +SET_FLAGS(lab2B "-O0 -fno-stack-protector") + +add_executable(lab2A lab2A.c) +SET_FLAGS(lab2A "-O0 -fno-stack-protector") + +# These are the files we want to give students +install(TARGETS lab2C lab2B lab2A DESTINATION "${RELEASE_DIR}/lab02") +install(FILES lab2C.c lab2B.c lab2A.c DESTINATION "${RELEASE_DIR}/lab02") diff --git a/src/lab02/lab2A.c b/src/lab02/lab2A.c new file mode 100644 index 0000000..9dd363a --- /dev/null +++ b/src/lab02/lab2A.c @@ -0,0 +1,59 @@ +#include +#include +#include + +/* + * compiled with: + * gcc -O0 -fno-stack-protector lab2A.c -o lab2A + */ + +void shell() +{ + printf("You got it\n"); + system("/bin/sh"); +} + +void concatenate_first_chars() +{ + struct { + char word_buf[12]; + int i; + char* cat_pointer; + char cat_buf[10]; + } locals; + locals.cat_pointer = locals.cat_buf; + + printf("Input 10 words:\n"); + for(locals.i=0; locals.i!=10; locals.i++) + { + // Read from stdin + if(fgets(locals.word_buf, 0x10, stdin) == 0 || locals.word_buf[0] == '\n') + { + printf("Failed to read word\n"); + return; + } + // Copy first char from word to next location in concatenated buffer + *locals.cat_pointer = *locals.word_buf; + locals.cat_pointer++; + } + + // Even if something goes wrong, there's a null byte here + // preventing buffer overflows + locals.cat_buf[10] = '\0'; + printf("Here are the first characters from the 10 words concatenated:\n\ +%s\n", locals.cat_buf); +} + +int main(int argc, char** argv) +{ + if(argc != 1) + { + printf("usage:\n%s\n", argv[0]); + return EXIT_FAILURE; + } + + concatenate_first_chars(); + + printf("Not authenticated\n"); + return EXIT_SUCCESS; +} diff --git a/src/lab02/lab2B.c b/src/lab02/lab2B.c new file mode 100644 index 0000000..426576b --- /dev/null +++ b/src/lab02/lab2B.c @@ -0,0 +1,35 @@ +#include +#include +#include + +/* + * compiled with: + * gcc -O0 -fno-stack-protector lab2B.c -o lab2B + */ + +char* exec_string = "/bin/sh"; + +void shell(char* cmd) +{ + system(cmd); +} + +void print_name(char* input) +{ + char buf[15]; + strcpy(buf, input); + printf("Hello %s\n", buf); +} + +int main(int argc, char** argv) +{ + if(argc != 2) + { + printf("usage:\n%s string\n", argv[0]); + return EXIT_FAILURE; + } + + print_name(argv[1]); + + return EXIT_SUCCESS; +} diff --git a/src/lab02/lab2C.c b/src/lab02/lab2C.c new file mode 100644 index 0000000..e7592ac --- /dev/null +++ b/src/lab02/lab2C.c @@ -0,0 +1,38 @@ +#include +#include +#include + +/* + * compiled with: + * gcc -O0 -fno-stack-protector lab2C.c -o lab2C + */ + +void shell() +{ + printf("You did it.\n"); + system("/bin/sh"); +} + +int main(int argc, char** argv) +{ + if(argc != 2) + { + printf("usage:\n%s string\n", argv[0]); + return EXIT_FAILURE; + } + + int set_me = 0; + char buf[15]; + strcpy(buf, argv[1]); + + if(set_me == 0xdeadbeef) + { + shell(); + } + else + { + printf("Not authenticated.\nset_me was %d\n", set_me); + } + + return EXIT_SUCCESS; +} diff --git a/src/lab03/CMakeLists.txt b/src/lab03/CMakeLists.txt new file mode 100644 index 0000000..061b6e0 --- /dev/null +++ b/src/lab03/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab3C lab3C.c) +SET_FLAGS(lab3C "${NO_MITS_FLAGS}") + +add_executable(lab3B lab3B.c) +SET_FLAGS(lab3B "${NO_MITS_FLAGS}") + +add_executable(lab3A lab3A.c) +SET_FLAGS(lab3A "${NO_MITS_FLAGS}") + +# These are the files we want to give students +install(TARGETS lab3C lab3B lab3A DESTINATION "${RELEASE_DIR}/lab03") +install(FILES lab3C.c lab3B.c lab3A.c DESTINATION "${RELEASE_DIR}/lab03") + diff --git a/src/lab03/lab3A.c b/src/lab03/lab3A.c new file mode 100644 index 0000000..09668ab --- /dev/null +++ b/src/lab03/lab3A.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include "utils.h" + +#define STORAGE_SIZE 100 + +/* gcc -Wall -z execstack -o lab3A lab3A.c */ + +/* get a number from the user and store it */ +int store_number(unsigned int * data) +{ + unsigned int input = 0; + unsigned int index = 0; + + /* get number to store */ + printf(" Number: "); + input = get_unum(); + + /* get index to store at */ + printf(" Index: "); + index = get_unum(); + + /* make sure the slot is not reserved */ + if(index % 3 == 0 || (input >> 24) == 0xb7) + { + printf(" *** ERROR! ***\n"); + printf(" This index is reserved for quend!\n"); + printf(" *** ERROR! ***\n"); + + return 1; + } + + /* save the number to data storage */ + data[index] = input; + + return 0; +} + +/* returns the contents of a specified storage index */ +int read_number(unsigned int * data) +{ + unsigned int index = 0; + + /* get index to read from */ + printf(" Index: "); + index = get_unum(); + + printf(" Number at data[%u] is %u\n", index, data[index]); + + return 0; +} + +int main(int argc, char * argv[], char * envp[]) +{ + int res = 0; + char cmd[20] = {0}; + unsigned int data[STORAGE_SIZE] = {0}; + + /* doom doesn't like enviroment variables */ + clear_argv(argv); + clear_envp(envp); + + printf("----------------------------------------------------\n"\ + " Welcome to quend's crappy number storage service! \n"\ + "----------------------------------------------------\n"\ + " Commands: \n"\ + " store - store a number into the data storage \n"\ + " read - read a number from the data storage \n"\ + " quit - exit the program \n"\ + "----------------------------------------------------\n"\ + " quend has reserved some storage for herself :> \n"\ + "----------------------------------------------------\n"\ + "\n"); + + + /* command handler loop */ + while(1) + { + /* setup for this loop iteration */ + printf("Input command: "); + res = 1; + + /* read user input, trim newline */ + fgets(cmd, sizeof(cmd), stdin); + cmd[strlen(cmd)-1] = '\0'; + + /* select specified user command */ + if(!strncmp(cmd, "store", 5)) + res = store_number(data); + else if(!strncmp(cmd, "read", 4)) + res = read_number(data); + else if(!strncmp(cmd, "quit", 4)) + break; + + /* print the result of our command */ + if(res) + printf(" Failed to do %s command\n", cmd); + else + printf(" Completed %s command successfully\n", cmd); + + memset(cmd, 0, sizeof(cmd)); + } + + return EXIT_SUCCESS; +} diff --git a/src/lab03/lab3B.c b/src/lab03/lab3B.c new file mode 100644 index 0000000..19c4941 --- /dev/null +++ b/src/lab03/lab3B.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" + +ENABLE_TIMEOUT(60) + +/* gcc -z execstack -fno-stack-protector -o lab3B lab3B.c */ + +/* hint: write shellcode that opens and reads the .pass file. + ptrace() is meant to deter you from using /bin/sh shellcode */ + +int main() +{ + pid_t child = fork(); + char buffer[128] = {0}; + int syscall = 0; + int status = 0; + + if(child == 0) + { + prctl(PR_SET_PDEATHSIG, SIGHUP); + ptrace(PTRACE_TRACEME, 0, NULL, NULL); + + /* this is all you need to worry about */ + puts("just give me some shellcode, k"); + gets(buffer); + } + else + { + /* mini exec() sandbox, you can ignore this */ + while(1) + { + wait(&status); + if (WIFEXITED(status) || WIFSIGNALED(status)){ + puts("child is exiting..."); + break; + } + + /* grab the syscall # */ + syscall = ptrace(PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL); + + /* filter out syscall 11, exec */ + if(syscall == 11) + { + printf("no exec() for you\n"); + kill(child, SIGKILL); + break; + } + } + } + + return EXIT_SUCCESS; +} diff --git a/src/lab03/lab3C.c b/src/lab03/lab3C.c new file mode 100644 index 0000000..bf46c71 --- /dev/null +++ b/src/lab03/lab3C.c @@ -0,0 +1,49 @@ +#include +#include +#include + +/* gcc -z execstack -fno-stack-protector -o lab3C lab3C.c */ + +char a_user_name[100]; + +int verify_user_name() +{ + puts("verifying username....\n"); + return strncmp(a_user_name, "rpisec", 6); +} + +int verify_user_pass(char *a_user_pass) +{ + return strncmp(a_user_pass, "admin", 5); +} + +int main() +{ + char a_user_pass[64] = {0}; + int x = 0; + + /* prompt for the username - read 100 byes */ + printf("********* ADMIN LOGIN PROMPT *********\n"); + printf("Enter Username: "); + fgets(a_user_name, 0x100, stdin); + + /* verify input username */ + x = verify_user_name(); + if (x != 0){ + puts("nope, incorrect username...\n"); + return EXIT_FAILURE; + } + + /* prompt for admin password - read 64 bytes */ + printf("Enter Password: \n"); + fgets(a_user_pass, 0x64, stdin); + + /* verify input password */ + x = verify_user_pass(a_user_pass); + if (x == 0 || x != 0){ + puts("nope, incorrect password...\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/lab04/CMakeLists.txt b/src/lab04/CMakeLists.txt new file mode 100644 index 0000000..c46dbe4 --- /dev/null +++ b/src/lab04/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab4C lab4C.c) +SET_FLAGS(lab4C "${NO_MITS_FLAGS}") + +add_executable(lab4B lab4B.c) +SET_FLAGS(lab4B "${NO_MITS_FLAGS}") + +add_executable(lab4A lab4A.c) +SET_FLAGS(lab4A "-z execstack -z relro -z now") + +# These are the files we want to give students +install(TARGETS lab4C lab4B lab4A DESTINATION "${RELEASE_DIR}/lab04") +install(FILES lab4C.c lab4B.c lab4A.c DESTINATION "${RELEASE_DIR}/lab04") + diff --git a/src/lab04/lab4A.c b/src/lab04/lab4A.c new file mode 100644 index 0000000..bc8aca4 --- /dev/null +++ b/src/lab04/lab4A.c @@ -0,0 +1,74 @@ +/* + * Format String Lab - A Problem + * gcc -z execstack -z relro -z now -o lab4A lab4A.c + */ +#include +#include +#include +#include +#include +#include +#include + +#define BACKUP_DIR "./backups/" +#define LOG_FILE "./backups/.log" + +void +log_wrapper(FILE *logf, char *msg, char *filename) +{ + char log_buf[255]; + strcpy(log_buf, msg); + snprintf(log_buf+strlen(log_buf), 255-strlen(log_buf)-1/*NULL*/, filename); + log_buf[strcspn(log_buf, "\n")] = '\0'; + fprintf(logf, "LOG: %s\n", log_buf); +} + +int +main(int argc, char *argv[]) +{ + char ch = EOF; + char dest_buf[100]; + FILE *source, *logf; + int target = -1; + + if (argc != 2) { + printf("Usage: %s filename\n", argv[0]); + } + + // Open log file + logf = fopen(LOG_FILE, "w"); + if (logf == NULL) { + printf("ERROR: Failed to open %s\n", LOG_FILE); + exit(EXIT_FAILURE); + } + + log_wrapper(logf, "Starting back up: ", argv[1]); + + // Open source + source = fopen(argv[1], "r"); + if (source == NULL) { + printf("ERROR: Failed to open %s\n", argv[1]); + exit(EXIT_FAILURE); + } + + // Open dest + strcpy(dest_buf, BACKUP_DIR); + strncat(dest_buf, argv[1], 100-strlen(dest_buf)-1/*NULL*/); + target = open(dest_buf, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); + if (target < 0) { + printf("ERROR: Failed to open %s%s\n", BACKUP_DIR, argv[1]); + exit(EXIT_FAILURE); + } + + // Copy data + while( ( ch = fgetc(source) ) != EOF) + write(target, &ch, 1); + + log_wrapper(logf, "Finished back up ", argv[1]); + + // Clean up + fclose(source); + close(target); + + return EXIT_SUCCESS; +} diff --git a/src/lab04/lab4B.c b/src/lab04/lab4B.c new file mode 100644 index 0000000..28376f7 --- /dev/null +++ b/src/lab04/lab4B.c @@ -0,0 +1,27 @@ +/* + * Format String Lab - B Problem + * gcc -z execstack -z norelro -fno-stack-protector -o lab4B lab4B.c + */ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int i = 0; + char buf[100]; + + /* read user input securely */ + fgets(buf, 100, stdin); + + /* convert string to lowercase */ + for (i = 0; i < strlen(buf); i++) + if (buf[i] >= 'A' && buf[i] <= 'Z') + buf[i] = buf[i] ^ 0x20; + + /* print out our nice and new lowercase string */ + printf(buf); + + exit(EXIT_SUCCESS); + return EXIT_FAILURE; +} diff --git a/src/lab04/lab4C.c b/src/lab04/lab4C.c new file mode 100644 index 0000000..9278d1d --- /dev/null +++ b/src/lab04/lab4C.c @@ -0,0 +1,66 @@ +/* + * Format String Lab - C Problem + * gcc -z execstack -z norelro -fno-stack-protector -o lab4C lab4C.c + */ +#include +#include +#include +#include + +#define PASS_LEN 30 + +int main(int argc, char *argv[]) +{ + char username[100] = {0}; + char real_pass[PASS_LEN] = {0}; + char in_pass[100] = {0}; + FILE *pass_file = NULL; + int rsize = 0; + + /* open the password file */ + pass_file = fopen("/home/lab4B/.pass", "r"); + if (pass_file == NULL) { + fprintf(stderr, "ERROR: failed to open password file\n"); + exit(EXIT_FAILURE); + } + + /* read the contents of the password file */ + rsize = fread(real_pass, 1, PASS_LEN, pass_file); + real_pass[strcspn(real_pass, "\n")] = '\0'; // strip \n + if (rsize != PASS_LEN) { + fprintf(stderr, "ERROR: failed to read password file\n"); + exit(EXIT_FAILURE); + } + + /* close the password file */ + fclose(pass_file); + + puts("===== [ Secure Access System v1.0 ] ====="); + puts("-----------------------------------------"); + puts("- You must login to access this system. -"); + puts("-----------------------------------------"); + + /* read username securely */ + printf("--[ Username: "); + fgets(username, 100, stdin); + username[strcspn(username, "\n")] = '\0'; // strip \n + + /* read input password securely */ + printf("--[ Password: "); + fgets(in_pass, sizeof(in_pass), stdin); + in_pass[strcspn(in_pass, "\n")] = '\0'; // strip \n + + puts("-----------------------------------------"); + + /* log the user in if the password is correct */ + if(!strncmp(real_pass, in_pass, PASS_LEN)){ + printf("Greetings, %s!\n", username); + system("/bin/sh"); + } else { + printf(username); + printf(" does not have access!\n"); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/src/lab05/CMakeLists.txt b/src/lab05/CMakeLists.txt new file mode 100644 index 0000000..3bfe233 --- /dev/null +++ b/src/lab05/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab5C lab5C.c) +SET_FLAGS(lab5C "-fno-stack-protector") + +add_executable(lab5B lab5B.c) +SET_FLAGS(lab5B "--static -fno-stack-protector") + +add_executable(lab5A lab5A.c) +SET_FLAGS(lab5A "--static") + +# These are the files we want to give students +install(TARGETS lab5C lab5B lab5A DESTINATION "${RELEASE_DIR}/lab05") +install(FILES lab5C.c lab5B.c lab5A.c DESTINATION "${RELEASE_DIR}/lab05") + diff --git a/src/lab05/lab5A.c b/src/lab05/lab5A.c new file mode 100644 index 0000000..8857c05 --- /dev/null +++ b/src/lab05/lab5A.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include "utils.h" + +#define STORAGE_SIZE 100 + +/* gcc --static -o lab5A lab5A.c */ + +/* get a number from the user and store it */ +int store_number(unsigned int * data) +{ + unsigned int input = 0; + int index = 0; + + /* get number to store */ + printf(" Number: "); + input = get_unum(); + + /* get index to store at */ + printf(" Index: "); + index = (int)get_unum(); + + /* make sure the slot is not reserved */ + if(index % 3 == 0 || index > STORAGE_SIZE || (input >> 24) == 0xb7) + { + printf(" *** ERROR! ***\n"); + printf(" This index is reserved for doom!\n"); + printf(" *** ERROR! ***\n"); + + return 1; + } + + /* save the number to data storage */ + data[index] = input; + + return 0; +} + +/* returns the contents of a specified storage index */ +int read_number(unsigned int * data) +{ + int index = 0; + + /* get index to read from */ + printf(" Index: "); + index = (int)get_unum(); + + printf(" Number at data[%d] is %u\n", index, data[index]); + + return 0; +} + +int main(int argc, char * argv[], char * envp[]) +{ + int res = 0; + char cmd[20] = {0}; + unsigned int data[STORAGE_SIZE] = {0}; + + /* doom doesn't like enviroment variables */ + clear_argv(argv); + clear_envp(envp); + + printf("----------------------------------------------------\n"\ + " Welcome to doom's crappy number storage service! \n"\ + " Version 2.0 - With more security! \n"\ + "----------------------------------------------------\n"\ + " Commands: \n"\ + " store - store a number into the data storage \n"\ + " read - read a number from the data storage \n"\ + " quit - exit the program \n"\ + "----------------------------------------------------\n"\ + " doom has reserved some storage for himself :> \n"\ + "----------------------------------------------------\n"\ + "\n"); + + + /* command handler loop */ + while(1) + { + /* setup for this loop iteration */ + printf("Input command: "); + res = 1; + + /* read user input, trim newline */ + fgets(cmd, sizeof(cmd), stdin); + cmd[strlen(cmd)-1] = '\0'; + + /* select specified user command */ + if(!strncmp(cmd, "store", 5)) + res = store_number(data); + else if(!strncmp(cmd, "read", 4)) + res = read_number(data); + else if(!strncmp(cmd, "quit", 4)) + break; + + /* print the result of our command */ + if(res) + printf(" Failed to do %s command\n", cmd); + else + printf(" Completed %s command successfully\n", cmd); + + memset(cmd, 0, sizeof(cmd)); + } + + return EXIT_SUCCESS; +} diff --git a/src/lab05/lab5B.c b/src/lab05/lab5B.c new file mode 100644 index 0000000..1f4effa --- /dev/null +++ b/src/lab05/lab5B.c @@ -0,0 +1,15 @@ +#include +#include + +/* gcc -fno-stack-protector --static -o lab5B lab5B.c */ + +int main() +{ + + char buffer[128] = {0}; + + printf("Insert ROP chain here:\n"); + gets(buffer); + + return EXIT_SUCCESS; +} diff --git a/src/lab05/lab5C.c b/src/lab05/lab5C.c new file mode 100644 index 0000000..12a4739 --- /dev/null +++ b/src/lab05/lab5C.c @@ -0,0 +1,26 @@ +#include +#include + +/* gcc -fno-stack-protector -o lab5C lab5C.c */ + +char global_str[128]; + +/* reads a string, copies it to a global */ +void copytoglobal() +{ + char buffer[128] = {0}; + gets(buffer); + memcpy(global_str, buffer, 128); +} + +int main() +{ + char buffer[128] = {0}; + + printf("I included libc for you...\n"\ + "Can you ROP to system()?\n"); + + copytoglobal(); + + return EXIT_SUCCESS; +} diff --git a/src/lab06/CMakeLists.txt b/src/lab06/CMakeLists.txt new file mode 100644 index 0000000..df0c590 --- /dev/null +++ b/src/lab06/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab6C lab6C.c) +SET_FLAGS(lab6C "-pie -fPIE -fno-stack-protector") + +add_executable(lab6B lab6B.c) +SET_FLAGS(lab6B "-z relro -z now -pie -fPIE -fno-stack-protector") + +add_executable(lab6A lab6A.c) +SET_FLAGS(lab6A "-pie -fPIE") + +# These are the files we want to give students +install(TARGETS lab6C lab6B lab6A DESTINATION "${RELEASE_DIR}/lab06") +install(FILES lab6C.c lab6B.c lab6B.readme lab6A.c DESTINATION "${RELEASE_DIR}/lab06") diff --git a/src/lab06/lab6A.c b/src/lab06/lab6A.c new file mode 100644 index 0000000..bfb37a0 --- /dev/null +++ b/src/lab06/lab6A.c @@ -0,0 +1,123 @@ +/* +Exploitation with ASLR enabled +Lab A + +gcc -fpie -pie -o lab6A ./lab6A.c + +Patrick Biernat +*/ + +#include +#include +#include +#include "utils.h" + +struct uinfo { + char name[32]; + char desc[128]; + unsigned int sfunc; +}user; + + +struct item { + char name[32]; + char price[10]; +}aitem; + +struct item ulisting; + +void write_wrap(char ** buf) { + write(1, *buf, 8); +} + +void make_note() { + char note[40]; + printf("Make a Note About your listing...: "); + gets(note); +} + +void print_listing() { + printf( + "Here is the listing you've created: \n"); + if(*ulisting.name == '\x00') { + return; + } + printf("Item: %s\n", ulisting.name); + printf("Price: %s\n",ulisting.price); +} + +void make_listing() { + printf("Enter your item's name: "); + fgets(ulisting.name, 31, stdin); + printf("Enter your item's price: "); + fgets(ulisting.price, 9, stdin); +} + +void setup_account(struct uinfo * user) { + char temp[128]; + memset(temp, 0, 128); + printf("Enter your name: "); + read(0, user->name, sizeof(user->name)); + printf("Enter your description: "); + read(0, temp, sizeof(user->desc)); + strncpy(user->desc, user->name,32); + strcat(user->desc, " is a "); + + memcpy(user->desc + strlen(user->desc), temp, strlen(temp)); +} + +void print_name(struct uinfo * info) { + printf("Username: %s\n", info->name); +} + +int main(int argc, char ** argv) { + disable_buffering(stdout); + struct uinfo merchant; + char choice[4]; + + printf( + ".-------------------------------------------------. \n" \ + "| Welcome to l337-Bay + | \n" + "|-------------------------------------------------| \n" + "|1: Setup Account | \n" + "|2: Make Listing | \n" + "|3: View Info | \n" + "|4: Exit | \n" + "|-------------------------------------------------| \n" ); + + // Initialize user info + memset(merchant.name, 0, 32); + memset(merchant.desc, 0 , 64); + merchant.sfunc = (unsigned int)print_listing; + + //initialize listing + memset(ulisting.name, 0, 32); + memset(ulisting.price, 0, 10); + + while(1) { + memset(choice, 0, 4); + printf("Enter Choice: "); + + if (fgets(choice, 2, stdin) == 0) { + break; + } + getchar(); // Eat the newline + + if (!strncmp(choice, "1",1)) { + setup_account(&merchant); + } + if (!strncmp(choice, "2",1)) { + make_listing(); + } + if (!strncmp(choice, "3",1)) { // ITS LIKE HAVING CLASSES IN C! + ( (void (*) (struct uinfo *) ) merchant.sfunc) (&merchant); + } + if (!strncmp(choice, "4",1)) { + return EXIT_SUCCESS; + } + + } + + + return EXIT_SUCCESS; +} diff --git a/src/lab06/lab6B.c b/src/lab06/lab6B.c new file mode 100644 index 0000000..6af08c0 --- /dev/null +++ b/src/lab06/lab6B.c @@ -0,0 +1,191 @@ +/* doom's +/* compiled with: gcc -z relro -z now -pie -fPIE -fno-stack-protector -o lab6B lab6B.c */ + +#include +#include +#include +#include +#include "utils.h" + +ENABLE_TIMEOUT(300) + +/* log the user in */ +int login() +{ + printf("WELCOME MR. FALK\n"); + + /* you win */ + system("/bin/sh"); + return 0; +} + +/* doom's super secret password mangling scheme */ +void hash_pass(char * password, char * username) +{ + int i = 0; + + /* hash pass with chars of username */ + while(password[i] && username[i]) + { + password[i] ^= username[i]; + i++; + } + + /* hash rest of password with a pad char */ + while(password[i]) + { + password[i] ^= 0x44; + i++; + } + + return; +} + +/* doom's super secure password read function */ +int load_pass(char ** password) +{ + FILE * fd = 0; + int fail = -1; + int psize = 0; + + /* open the password file */ + fd = fopen("/home/lab6A/.pass", "r"); + if(fd == NULL) + { + printf("Could not open secret pass!\n"); + return fail; + } + + /* get the size of the password */ + if(fseek(fd, 0, SEEK_END)) + { + printf("Failed to seek to end of pass!\n"); + return fail; + } + + psize = ftell(fd); + + if(psize == 0 || psize == -1) + { + printf("Could not get pass size!\n"); + return fail; + } + + /* reset stream */ + if(fseek(fd, 0, SEEK_SET)) + { + printf("Failed to see to the start of pass!\n"); + return fail; + } + + /* allocate a buffer for the password */ + *password = (char *)malloc(psize); + if(password == NULL) + { + printf("Could not malloc for pass!\n"); + return fail; + } + + /* make sure we read in the whole password */ + if(fread(*password, sizeof(char), psize, fd) != psize) + { + printf("Could not read secret pass!\n"); + free(*password); + return fail; + } + + fclose(fd); + + /* successfully read in the password */ + return psize; +} + +int login_prompt(int pwsize, char * secretpw) +{ + char password[32]; + char username[32]; + char readbuff[128]; + int attempts = -3; + int result = -1; + + /* login prompt loop */ + while(attempts++) + { + /* clear our buffers to avoid any sort of data re-use */ + memset(password, 0, sizeof(password)); + memset(username, 0, sizeof(username)); + memset(readbuff, 0, sizeof(readbuff)); + + /* safely read username */ + printf("Enter your username: "); + fgets(readbuff, sizeof(readbuff), stdin); + + /* use safe strncpy to copy username from the read buffer */ + strncpy(username, readbuff, sizeof(username)); + + /* safely read password */ + printf("Enter your password: "); + fgets(readbuff, sizeof(readbuff), stdin); + + /* use safe strncpy to copy password from the read buffer */ + strncpy(password, readbuff, sizeof(password)); + + /* hash the input password for this attempt */ + hash_pass(password, username); + + /* check if password is correct */ + if(pwsize > 16 && memcmp(password, secretpw, pwsize) == 0) + { + login(); + result = 0; + break; + } + + printf("Authentication failed for user %s\n", username); + } + + return result; +} + +int main(int argc, char* argv[]) +{ + int pwsize; + char * secretpw; + + disable_buffering(stdout); + + /* load the secret pass */ + pwsize = load_pass(&secretpw); + pwsize = pwsize > 32 ? 32 : pwsize; + + /* failed to load password */ + if(pwsize == 0 || pwsize == -1) + return EXIT_FAILURE; + + /* hash the password we'll be comparing against */ + hash_pass(secretpw, "lab6A"); + printf("----------- FALK OS LOGIN PROMPT -----------\n"); + + /* authorization loop */ + if(login_prompt(pwsize, secretpw)) + { + + /* print the super serious warning to ward off hackers */ + printf("+-------------------------------------------------------+\n"\ + "|WARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNIN|\n"\ + "|GWARNINGWARNI - TOO MANY LOGIN ATTEMPTS - NGWARNINGWARN|\n"\ + "|INGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWAR|\n"\ + "+-------------------------------------------------------+\n"\ + "| We have logged this session and will be |\n"\ + "| sending it to the proper CCDC CTF teams to analyze |\n"\ + "| ----------------------------- |\n"\ + "| The CCDC cyber team dispatched will use their |\n"\ + "| masterful IT and networking skills to trace |\n"\ + "| you down and serve swift american justice |\n"\ + "+-------------------------------------------------------+\n"); + + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/lab06/lab6B.readme b/src/lab06/lab6B.readme new file mode 100644 index 0000000..cf118c5 --- /dev/null +++ b/src/lab06/lab6B.readme @@ -0,0 +1,8 @@ +lab6B is not a suid binary, instead you must pwn the privileged +service running on port 6642 + +Using netcat: + nc wargame.server.example 6642 -vvv + +Your final exploit must work against this service in order to +get the .pass file from the lab6A user. diff --git a/src/lab06/lab6C.c b/src/lab06/lab6C.c new file mode 100644 index 0000000..dfdd3d6 --- /dev/null +++ b/src/lab06/lab6C.c @@ -0,0 +1,94 @@ +/* +Exploitation with ASLR +Lab C + + gcc -pie -fPIE -fno-stack-protector -o lab6C lab6C.c +*/ + +#include +#include +#include + +struct savestate { + char tweet[140]; + char username[40]; + int msglen; +} save; + +void set_tweet(struct savestate *save ); +void set_username(struct savestate * save); + +void handle_tweet() +{ + struct savestate save; + + /* Initialize our save state to sane values. */ + memset(save.username, 0, 40); + save.msglen = 140; + + /* read a username and tweet from the user */ + set_username(&save); + set_tweet(&save); + + printf(">: Tweet sent!\n"); + return; +} + +void set_tweet(struct savestate *save ) +{ + char readbuf[1024]; + memset(readbuf, 0, 1024); + + printf(">: Tweet @Unix-Dude\n"); + printf(">>: "); + + /* read a tweet from the user, safely copy it to struct */ + fgets(readbuf, 1024, stdin); + strncpy(save->tweet, readbuf, save->msglen); + + return; +} + +void set_username(struct savestate * save) +{ + int i; + char readbuf[128]; + memset(readbuf, 0, 128); + + printf(">: Enter your username\n"); + printf(">>: "); + + /* Read and copy the username to our savestate */ + fgets(readbuf, 128, stdin); + for(i = 0; i <= 40 && readbuf[i]; i++) + save->username[i] = readbuf[i]; + + printf(">: Welcome, %s", save->username); + return; +} + +/* debug functionality, not used in production */ +void secret_backdoor() +{ + char cmd[128]; + + /* reads a command and executes it */ + fgets(cmd, 128, stdin); + system(cmd); + + return; +} + +int main(int argc, char * argv[]) +{ + + printf( + "--------------------------------------------\n" \ + "| ~Welcome to l33t-tw33ts ~ v.0.13.37 |\n" \ + "--------------------------------------------\n"); + + /* make some tweets */ + handle_tweet(); + + return EXIT_SUCCESS; +} diff --git a/src/lab07/CMakeLists.txt b/src/lab07/CMakeLists.txt new file mode 100644 index 0000000..12a81a1 --- /dev/null +++ b/src/lab07/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab7C lab7C.c) +SET_FLAGS(lab7C "-z relro -z now -fPIE -pie -fstack-protector-all") + +add_executable(lab7A lab7A.c) +SET_FLAGS(lab7A "-static -z relro -z now -fstack-protector-all") + +# These are the files we want to give students +install(TARGETS lab7C lab7A DESTINATION "${RELEASE_DIR}/lab07") +install(FILES lab7C.c lab7A.c lab7A.readme DESTINATION "${RELEASE_DIR}/lab07") diff --git a/src/lab07/lab7A.c b/src/lab07/lab7A.c new file mode 100644 index 0000000..af0a032 --- /dev/null +++ b/src/lab07/lab7A.c @@ -0,0 +1,273 @@ +/* compiled with: gcc -static -z relro -z now -fstack-protector-all -o lab7A lab7A.c */ + +#include +#include +#include +#include +#include +#include "utils.h" + +ENABLE_TIMEOUT(60) + +#define MAX_MSG 10 +#define MAX_BLOCKS 32 +#define BLOCK_SIZE 4 + +struct msg { + void (* print_msg)(struct msg *); + unsigned int xor_pad[MAX_BLOCKS]; + unsigned int message[MAX_BLOCKS]; + unsigned int msg_len; +}; + +struct msg * messages[MAX_MSG]; + +/* apply one time pad */ +void encdec_message(unsigned int * message, unsigned int * xor_pad) +{ + int i = 0; + for(i = 0; i < MAX_BLOCKS; i++) + message[i] ^= xor_pad[i]; +} + +/* print information about the given message */ +void print_message(struct msg * to_print) +{ + unsigned int i = 0; + char * xor_pad; + char * message; + + xor_pad = (char *)&to_print->xor_pad; + message = (char *)&to_print->message; + + /* print the message's xor pad */ + printf("\nXOR Pad: \n" + "-----------------------------------------\n"); + + for(i = 0; i < BLOCK_SIZE*MAX_BLOCKS; i++) + { + printf("%02x", xor_pad[i] & 0xFF); + if(i % 32 == 31) + puts(""); + } + + /* print encrypted message */ + printf("\nEncrypted Message: \n" + "-----------------------------------------\n"); + + for(i = 0; i < BLOCK_SIZE*MAX_BLOCKS; i++) + { + printf("%02x", message[i] & 0xFF); + if(i % 32 == 31) + puts(""); + } + + puts(""); +} + +/* creates a message */ +int create_message() +{ + int i, j; + struct msg * new_msg = NULL; + + /* find a free message slot */ + for(i = 0; i < MAX_MSG; i++) + if(messages[i] == NULL) + break; + + /* make sure we actually found an empty slot */ + if(messages[i]) + { + printf("-No message slots left!\n"); + return 1; + } + + printf("-Using message slot #%u\n", i); + + /* initialize new message */ + new_msg = malloc(sizeof(struct msg)); + memset(new_msg, 0, sizeof(struct msg)); + new_msg->print_msg = &print_message; + + for(j = 0; j < MAX_BLOCKS; j++) + new_msg->xor_pad[j] = rand(); + + /* get the length of data the user intends to encrypt */ + printf("-Enter data length: "); + + new_msg->msg_len = get_unum(); + + if(new_msg->msg_len == 0) + { + printf("-Message length must be greater than zero!\n"); + free(new_msg); + return 1; + } + + /* make sure the message length is no bigger than the xor pad */ + if((new_msg->msg_len / BLOCK_SIZE) > MAX_BLOCKS) + new_msg->msg_len = BLOCK_SIZE * MAX_BLOCKS; + + /* read in the message to encrypt with the xor pad */ + printf("-Enter data to encrypt: "); + read(0, &new_msg->message, new_msg->msg_len); + + /* encrypt message */ + encdec_message(new_msg->message, new_msg->xor_pad); + + /* save the new message to the global list */ + messages[i] = new_msg; + + return 0; +} + +int edit_message() +{ + char numbuf[32]; + unsigned int i = 0; + + /* get message index to destroy */ + printf("-Input message index to edit: "); + fgets(numbuf, sizeof(numbuf), stdin); + i = strtoul(numbuf, NULL, 10); + + if(i >= MAX_MSG || messages[i] == NULL) + { + printf("-Invalid message index!\n"); + return 1; + } + + printf("-Input new message to encrypt: "); + + /* clear old message, and read in a new one */ + memset(&messages[i]->message, 0, BLOCK_SIZE * MAX_BLOCKS); + read(0, &messages[i]->message, messages[i]->msg_len); + + /* encrypt message */ + encdec_message(messages[i]->message, messages[i]->xor_pad); + + return 0; +} + +/* free a secure message */ +int destroy_message() +{ + char numbuf[32]; + unsigned int i = 0; + + /* get message index to destroy */ + printf("-Input message index to destroy: "); + fgets(numbuf, sizeof(numbuf), stdin); + i = strtoul(numbuf, NULL, 10); + + if(i >= MAX_MSG || messages[i] == NULL) + { + printf("-Invalid message index!\n"); + return 1; + } + + /* destroy message */ + memset(messages[i], 0, sizeof(struct msg)); + free(messages[i]); + messages[i] = NULL; + + return 0; +} + +/* print a message at a select index */ +int print_index() +{ + char numbuf[32]; + unsigned int i = 0; + + /* get message index to print */ + printf("-Input message index to print: "); + fgets(numbuf, sizeof(numbuf), stdin); + i = strtoul(numbuf, NULL, 10); + + if(i >= MAX_MSG || messages[i] == NULL) + { + printf("-Invalid message index!\n"); + return 1; + } + + /* print the message of interest */ + messages[i]->print_msg(messages[i]); + + return 0; +} + +/* the vulnerability is in here */ +void print_menu() +{ + printf("+---------------------------------------+\n" + "| Doom's OTP Service v1.0 |\n" + "+---------------------------------------+\n" + "|------------ Services Menu ------------|\n" + "|---------------------------------------|\n" + "| 1. Create secure message |\n" + "| 2. Edit secure message |\n" + "| 3. Destroy secure message |\n" + "| 4. Print message details |\n" + "| 5. Quit |\n" + "+---------------------------------------+\n"); +} + +int main() +{ + int choice = 0; + srand(time(NULL)); + disable_buffering(stdout); + + while(1) + { + print_menu(); + + /* get menu option */ + printf("Enter Choice: "); + choice = get_unum(); + + printf("-----------------------------------------\n"); + + /* handle menu selection */ + if(choice == 1) + { + if(create_message()) + printf("-Failed to create message!\n"); + else + printf("-Message created successfully!\n"); + } + else if(choice == 2) + { + if(edit_message()) + printf("-Failed to edit message!\n"); + else + printf("-Message has been successfully modified!\n"); + } + else if(choice == 3) + { + if(destroy_message()) + printf("-Failed to destroy message!\n"); + else + printf("-Message destroyed!\n"); + } + else if(choice == 4) + { + if(print_index()) + printf("-Failed to print message!\n"); + } + else if(choice == 5) + { + break; // exit + } + else + printf("-Invalid choice!\n"); + + choice = 0; + puts(""); + } + + printf("See you tomorrow!\n"); + return EXIT_SUCCESS; +} diff --git a/src/lab07/lab7A.readme b/src/lab07/lab7A.readme new file mode 100644 index 0000000..651c6bb --- /dev/null +++ b/src/lab07/lab7A.readme @@ -0,0 +1,3 @@ +lab7A is a remote level much like lab6B. It is running on port 7741. + +nc wargame.server.example 7741 -vvv diff --git a/src/lab07/lab7C.c b/src/lab07/lab7C.c new file mode 100644 index 0000000..80ca684 --- /dev/null +++ b/src/lab07/lab7C.c @@ -0,0 +1,185 @@ +/* compiled with: gcc -z relro -z now -fPIE -pie -fstack-protector-all -o lab7C lab7C.c */ +#include +#include +#include +#include +#include "utils.h" + +#define MAX_STR 6 +#define MAX_NUM 6 + +struct data { + char reserved[8]; + char buffer[20]; + void (* print)(char *); +}; + +struct number { + unsigned int reserved[6]; // implement later + void (* print)(unsigned int); + unsigned int num; +}; + +void small_str(char * a_str) +{ + printf("here's your lame string: %s\n", a_str); +} + +void big_str(char * a_str) +{ + printf("nice big str yo: %s\n", a_str); +} + +void small_num(unsigned int a_num) +{ + printf("not 1337 enough: %u\n", a_num); +} + +void big_num(unsigned int a_num) +{ + printf("tite number dawg: %u\n", a_num); +} + +void print_menu() +{ + printf("-- UAF Playground Menu ----------------------\n" + "1. Make a string\n" + "2. Make a number\n" + "3. Delete a string\n" + "4. Delete a number\n" + "5. Print a string\n" + "6. Print a number\n" + "7. Quit\n" + "---------------------------------------------\n" + "Enter Choice: "); +} + +/* bugs galore... but no memory corruption! */ +int main(int argc, char * argv[]) +{ + struct data * strings[MAX_STR] = {0}; + struct number * numbers[MAX_NUM] = {0}; + struct data * tempstr = NULL; + struct number * tempnum = NULL; + + int strcnt = 0; + int numcnt = 0; + unsigned int choice = 0; + unsigned int index = 0; + + while(1) + { + print_menu(); + + /* get menu option */ + if((choice = get_unum()) == EOF) + break; + + /* make a string */ + if(choice == 1) + { + if(strcnt < MAX_STR) + { + tempstr = malloc(sizeof(struct data)); + + /* no memory corruption this time */ + printf("Input string to store: "); + fgets(tempstr->buffer, 20, stdin); + tempstr->buffer[strcspn(tempstr->buffer, "\n")] = 0; + + /* pick a print function */ + tempstr->print = strlen(tempstr->buffer) > 10 ? big_str : small_str; + + /* store the string to our master list */ + strings[++strcnt] = tempstr; + printf("Created new string!\n"); + } + else + printf("Please delete a string before trying to make another!\n"); + } + + /* make a number */ + else if(choice == 2) + { + if(numcnt < MAX_NUM) + { + tempnum = malloc(sizeof(struct number)); + + printf("Input number to store: "); + tempnum->num = get_unum(); + + /* pick a print function */ + tempnum->print = tempnum->num > 0x31337 ? big_num : small_num; + + /* store the number to our master list */ + numbers[++numcnt] = tempnum; + printf("Created new number!\n"); + } + else + printf("Please delete a number before trying to make another!\n"); + } + + /* delete a string */ + else if(choice == 3) + { + if(strcnt && strings[strcnt]) + { + free(strings[strcnt--]); + printf("Deleted most recent string!\n"); + } + else + printf("There are no strings left to delete!\n"); + } + + /* delete a number */ + else if(choice == 4) + { + if(numcnt && numbers[numcnt]) + { + free(numbers[numcnt--]); + printf("Deleted most recent number!\n"); + } + else + printf("There are no numbers left to delete!\n"); + } + + /* print a string */ + else if(choice == 5) + { + printf("String index to print: "); + index = get_unum(); + + if(index < MAX_STR && strings[index]) + strings[index]->print(strings[index]->buffer); + else + printf("There is no string to print!\n"); + } + + /* print a number */ + else if(choice == 6) + { + printf("Number index to print: "); + index = get_unum(); + + if(index < MAX_NUM && numbers[index]) + numbers[index]->print(numbers[index]->num); + else + printf("There is no number to print!\n"); + } + + /* quit */ + else if(choice == 7) + break; + + /* base case */ + else + printf("Invalid choice!\n"); + + index = 0; + choice = 0; + printf("\n"); + } + + printf("See you tomorrow!\n"); + return EXIT_SUCCESS; +} diff --git a/src/lab08/CMakeLists.txt b/src/lab08/CMakeLists.txt new file mode 100644 index 0000000..c0bffb4 --- /dev/null +++ b/src/lab08/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab8C lab8C.c) +SET_FLAGS(lab8C "-z relro -z now -fPIE -pie -fstack-protector-all") + +add_executable(lab8B lab8B.c) +SET_FLAGS(lab8B "-z relro -z now -fPIE -pie -fstack-protector-all") + +add_executable(lab8A lab8A.c) +SET_FLAGS(lab8A "-static -fstack-protector-all -mpreferred-stack-boundary=2") + +# These are the files we want to give students +install(TARGETS lab8C lab8B lab8A DESTINATION "${RELEASE_DIR}/lab08") +install(FILES lab8C.c lab8B.c lab8A.c lab8A.readme DESTINATION "${RELEASE_DIR}/lab08") diff --git a/src/lab08/lab8A.c b/src/lab08/lab8A.c new file mode 100644 index 0000000..348b9d2 --- /dev/null +++ b/src/lab08/lab8A.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include "utils.h" +#define STDIN 0 + +//gcc -fstack-protector-all -mpreferred-stack-boundary=2 -o lab8A lab8A.c +int *global_addr; +int *global_addr_check; + +// made so you can only read what we let you + +void selectABook() { + /* Our Apologies,the interface is currently under developement */ + char buf_secure[512]; + scanf("%s", buf_secure); + printf(buf_secure); + if(strcmp(buf_secure, "A") == 0){ + readA(); + }else if(strcmp(buf_secure,"F") == 0){ + readB(); + }else if(*buf_secure == '\x00'){ + readC(); + }else if(buf_secure == 1337){ + printf("\nhackers dont have time to read.\n"); + exit(EXIT_FAILURE); + }else{ + printf("\nWhat were you thinking, that isn't a good book."); + selectABook(); + } + return; +} + +void readA(){ + + printf("\n\n*************************************************\n"); + printf("{|} Aristote's Metaphysics 350 B.C. Book VIII {|}\n"); + printf("*************************************************\n\n"); + printf("To return to the difficulty which has been stated with respect both to definitions and to numbers, what is the cause of their unity? In the case of all things which have several parts and in which the totality is not, as it were, a mere heap, but the whole is something beside the parts, there is a cause; for even in bodies contact is the cause of unity in some cases, and in others viscosity or some other such quality. And a definition is a set of words which is one not by being connected together, like the Iliad, but by dealing with one object.-What then, is it that makes man one; why is he one and not many, e.g. animal + biped, especially if there are, as some say, an animal-itself and a biped-itself? Why are not those Forms themselves the man, so that men would exist by participation not in man, nor in-one Form, but in two, animal and biped, and in general man would be not one but more than one thing, animal and biped? \n"); + +} + +void readB(){ + + printf("\n\n*************************************************\n"); + printf("{|} Aristote's Metaphysics 350 B.C. Book IVIZ {|}\n"); + printf("*************************************************\n\n"); + printf( + + "Clearly, then, if people proceed thus in their usual manner of definition and speech, they cannot explain and solve the difficulty. But if, as we say, one element is matter and another is form, and one is potentially and the other actually, the question will no longer be thought a difficulty. For this difficulty is the same as would arise if 'round bronze' were the definition of 'cloak'; for this word would be a sign of the definitory formula, so that the question is, what is the cause of the unity of 'round' and 'bronze'? The difficulty disappears, because the one is matter, the other form. What, then, causes this-that which was potentially to be actually-except, in the case of things which are generated, the agent? For there is no other cause of the potential sphere's becoming actually a sphere, but this was the essence of either. Of matter some is intelligible, some perceptible, and in a formula there is always an element of matter as well as one of actuality; e.g. the circle is 'a plane figure'. But of the things which have no matter, either intelligible or perceptible, each is by its nature essentially a kind of unity, as it is essentially a kind of being-individual substance, quality, or quantity (and so neither 'existent' nor 'one' is present in their definitions), and the essence of each of them is by its very nature a kind of unity as it is a kind of being-and so none of these has any reason outside itself, for being one, nor for being a kind of being; for each is by its nature a kind of being and a kind of unity, not as being in the genus 'being' or 'one' nor in the sense that being and unity can exist apart from particulars. \n"); + +} + +void readC(){ + + printf("\n\n*************************************************\n"); + printf("{|} Aristote's Metaphysics 350 B.C. Book MN9+ {|}\n"); + printf("*************************************************\n\n"); + printf( + "Owing to the difficulty about unity some speak of 'participation', and raise the question, what is the cause of participation and what is it to participate; and others speak of 'communion', as Lycophron says knowledge is a communion of knowing with the soul; and others say life is a 'composition' or 'connexion' of soul with body. Yet the same account applies to all cases; for being healthy, too, will on this showing be either a 'communion' or a 'connexion' or a 'composition' of soul and health, and the fact that the bronze is a triangle will be a 'composition' of bronze and triangle, and the fact that a thing is white will be a 'composition' of surface and whiteness. The reason is that people look for a unifying formula, and a difference, between potency and complete reality. But, as has been said, the proximate matter and the form are one and the same thing, the one potentially, and the other actually. Therefore it is like asking what in general is the cause of unity and of a thing's being one; for each thing is a unity, and the potential and the actual are somehow one. Therefore there is no other cause here unless there is something which caused the movement from potency into actuality. And all things which have no matter are without qualification essentially unities. "); + + +} + +void findSomeWords() { + /* We specialize in words of wisdom */ + char buf[24]; + // to avoid the null + global_addr = (&buf+0x1); + // have to make sure no one is stealing the librarians cookies (they get angry) + global_addr_check = global_addr-0x2; + char lolz[4]; + + printf("\n..I like to read ^_^ <== "); + read(STDIN, buf, 2048); // >> read a lot every day ! + + if(((*( global_addr))^(*(global_addr_check))) != ((*( global_addr))^(0xdeadbeef))){ + printf("\n\nWoah There\n"); + // why are you trying to break my program q-q + exit(EXIT_FAILURE); + } + + // protected by my CUSTOM cookie - so soooo safe now + return; +} + +int main(int argc, char* argv[]) { + + disable_buffering(stdout); + printf("\n\n\n"); + printf("**********************************************\n"\ + "{|} Welcome to QUEND's Beta-Book-Browser {|}\n"\ + "**********************************************\n"\ + "\n" + "\t==> reading is for everyone <==\n"\ + "\t[+] Enter Your Favorite Author's Last Name: "); + selectABook(); + + printf("\n...please turn to page 394...\n"); + findSomeWords(); + + printf("\n\t[===] Whew you made it !\n\n"); + return EXIT_SUCCESS; +} diff --git a/src/lab08/lab8A.readme b/src/lab08/lab8A.readme new file mode 100644 index 0000000..8eb69ab --- /dev/null +++ b/src/lab08/lab8A.readme @@ -0,0 +1,3 @@ +lab8A is a remote level much like lab6B. It is running on port 8841. + +nc wargame.server.example 8841 -vvv diff --git a/src/lab08/lab8B.c b/src/lab08/lab8B.c new file mode 100644 index 0000000..ebd9243 --- /dev/null +++ b/src/lab08/lab8B.c @@ -0,0 +1,251 @@ +/* + * gcc -z relro -z now -fPIE -pie -fstack-protector-all -o lab8B lab8B.c + */ + +#include +#include +#include + +#define MAX_FAVES 10 + +struct vector { + void (*printFunc)(struct vector*); + char a; + short b; + unsigned short c; + int d; + unsigned int e; + long f; + unsigned long g; + long long h; + unsigned long long i; +}; + +struct vector v1; +struct vector v2; +struct vector v3; +struct vector* faves[MAX_FAVES]; + +void printVector(struct vector* v); + +void printMenu() +{ + printf("+------------------------------------------------------------+\n"); + printf("| |\n"); + printf("| 1. Enter data :> |\n"); + printf("| 2. Sum vectors :] |\n"); + printf("| 3. Print vector :3 |\n"); + printf("| 4. Save sum to favorites 8) |\n"); + printf("| 5. Print favorites :O |\n"); + printf("| 6. Load favorite :$ |\n"); + printf("| 9. Get help :D |\n"); + printf("| |\n"); + printf("+------------------------------------------------------------+\n"); + printf("I COMMAND YOU TO ENTER YOUR COMMAND: "); +} + +struct vector* vectorSel() +{ + printf("Which vector? "); + char sel; + while((sel = getchar()) == '\n'); // I love C. + switch(sel) + { + case '1': + return &v1; + case '2': + return &v2; + case '3': + return &v3; + default: + printf("\nBAD VECTOR SELECTION\n"); + exit(EXIT_FAILURE); + } +} + +void enterData() +{ + struct vector* v = vectorSel(); + if(v == &v3) + { + printf("Please don't try to manually enter data into the sum.\n"); + return; + } + printf("Data entry time!\n"); + printf("char a: "); + while((v->a = getchar()) == '\n'); // Still love C. + printf("short b: "); + scanf("%hd", &(v->b)); + printf("unsigned short c: "); + scanf("%hu", &(v->c)); + printf("int d: "); + scanf("%d", &(v->d)); + printf("unsigned int e: "); + scanf("%u", &(v->e)); + printf("long f: "); + scanf("%ld", &(v->f)); + printf("unsigned long g: "); + scanf("%lu", &(v->g)); + printf("long long h: "); + scanf("%lld", &(v->h)); + printf("unsigned long long i: "); + scanf("%llu", &(v->i)); + v->printFunc = printVector; +} + +void sumVectors() +{ + if(v1.a==0 || v2.a==0 || + v1.b==0 || v2.b==0 || + v1.c==0 || v2.c==0 || + v1.d==0 || v2.d==0 || + v1.e==0 || v2.e==0 || + v1.f==0 || v2.f==0 || + v1.g==0 || v2.g==0 || + v1.h==0 || v2.h==0 || + v1.i==0 || v2.i==0) + { + printf("You didn't even set the addends... :(\n"); + return; + } + v3.a = v1.a + v2.a; + v3.b = v1.b + v2.b; + v3.c = v1.c + v2.c; + v3.d = v1.d + v2.d; + v3.e = v1.e + v2.e; + v3.f = v1.f + v2.f; + v3.g = v1.g + v2.g; + v3.h = v1.h + v2.h; + v3.i = v1.i + v2.i; + printf("Summed.\n"); +} + +/* + * Bonus points if you don't use this function. + */ +void thisIsASecret() +{ + system("/bin/sh"); +} + +void printVector(struct vector* v) +{ + printf("Address: %p\n", v); + printf("void printFunc: %p\n", v->printFunc); + printf("char a: %c\n", v->a); + printf("short b: %hd\n", v->b); + printf("unsigned short c: %hu\n", v->c); + printf("int d: %d\n", v->d); + printf("unsigned int e: %u\n", v->e); + printf("long f: %ld\n", v->f); + printf("unsigned long g: %lu\n", v->g); + printf("long long h: %lld\n", v->h); + printf("unsigned long long i: %llu\n", v->i); +} + +void fave() +{ + unsigned int i; + for(i=0; i= MAX_FAVES) + { + printf("Index out of bounds\n"); + return; + } + + struct vector* v = vectorSel(); + if(v == &v3) + { + printf("Please don't try to manually enter data into the sum.\n"); + return; + } + memcpy(v, faves[i], sizeof(v)); +} + +void help() +{ + printf("\ +This program adds two vectors together and stores it in a third vector. You \ +can then add the sum to your list of favorites, or load a favorite back into \ +one of the addends.\n"); +} + +int main(int argc, char** argv) +{ + char sel; + printMenu(); + v1.printFunc = printf; + v2.printFunc = printf; + v3.printFunc = printf; + struct vector* v; + while((sel = getchar()) && (sel == '\n' || getchar())) // Magic ;^) + { + if(sel == '\n') + continue; + + switch(sel) + { + case '0': + printf("OK, bye.\n"); + return EXIT_SUCCESS; + case '1': + enterData(); + break; + case '2': + sumVectors(); + break; + case '3': + v = vectorSel(); + //printf("Calling %p\n", v->printFunc); + v->printFunc(v); + break; + case '4': + fave(); + break; + case '5': + printFaves(); + break; + case '6': + loadFave(); + break; + case '9': + help(); + break; + default: + printf("\nThat was bad input. \ +Just like your futile attempt to pwn this.\n"); + return EXIT_FAILURE; + } + printMenu(); + } + return EXIT_SUCCESS; +} diff --git a/src/lab08/lab8C.c b/src/lab08/lab8C.c new file mode 100644 index 0000000..e8a8791 --- /dev/null +++ b/src/lab08/lab8C.c @@ -0,0 +1,132 @@ +/* + * gcc -z relro -z now -fPIE -pie -fstack-protector-all -o lab8C lab8C.c + */ + +#include +#include +#include +#include +#include +#include +#include + +struct fileComp { + char fileContents1[255]; + char fileContents2[255]; + int cmp; +}; + +char* readfd(int fd) +{ + // Find length of file + int size = lseek(fd, 0, SEEK_END); + if(size >= 255) + { + printf("Your file is too big.\n"); + exit(EXIT_FAILURE); + } + // Reset fd to beginning of file + lseek(fd, 0, SEEK_SET); + // Allocate space for the file and a null byte + char* fileContents = malloc((size+1) & 0xff); + if(!fileContents) + { + printf("Could not allocate space for file contents\n"); + exit(EXIT_FAILURE); + } + // Read the file contents into the buffer + int numRead = read(fd, fileContents, size & 0xff); + return fileContents; +} + +int getfd(char* arg) +{ + if(arg[0] != '-' || arg[1] != 'f' || arg[3] != '=') + { + printf("Invalid formatting in argument \"%s\"\n", arg); + return -1; + } + + int fd; + if(arg[2] == 'n') + { + // O_NOFOLLOW means that it won't follow symlinks. Sorry. + fd = open(arg+4, O_NOFOLLOW | O_RDONLY); + if(fd == -1) + { + printf("File could not be opened\n"); + return -1; + } + } + else if(arg[2] == 'd') + { + errno = 0; + fd = atoi(arg+4); + } + else + { + printf("Invalid formatting in argument \"%s\"\n", arg); + return -1; + } + + return fd; +} + +struct fileComp* comparefds(int fd1, int fd2) +{ + struct fileComp* fc = malloc(sizeof(struct fileComp)); + if(!fc) + { + printf("Could not allocate space for file contents\n"); + exit(EXIT_FAILURE); + } + + strcpy(fc->fileContents1, readfd(fd1)); + strcpy(fc->fileContents2, readfd(fd2)); + fc->cmp = strcmp(fc->fileContents1, fc->fileContents2); + return fc; +} + +char* securityCheck(char* arg, char* s) +{ + if(strstr(arg, ".pass")) + return "<<>>"; + return s; +} + +int main(int argc, char** argv) +{ + if(argc != 3) + { + printf("Hi. This program will do a lexicographical comparison of the \ +contents of two files. It has the bonus functionality of being \ +able to process either filenames or file descriptors.\n"); + printf("Usage: %s {-fn=|-fd=} {-fn=|-fd=}\n", argv[0]); + return EXIT_FAILURE; + } + + int fd1 = getfd(argv[1]); + int fd2 = getfd(argv[2]); + if(fd1 == -1 || fd2 == -1) + { + printf("Usage: %s {-fn=|-fd=} {-fn=|-fd=}\n", argv[0]); + return EXIT_FAILURE; + } + if(fd1 == 0 || fd2 == 0) + { + printf("Invalid fd argument.\n"); + printf("(We're still fixing some bugs with using STDIN.)\n"); + printf("Usage: %s {-fn=|-fd=} {-fn=|-fd=}\n", argv[0]); + return EXIT_FAILURE; + } + + struct fileComp* fc = comparefds(fd1, fd2); + + printf( + "\"%s\" is lexicographically %s \"%s\"\n", + securityCheck(argv[1], fc->fileContents1), + fc->cmp > 0 ? "after" : (fc->cmp < 0 ? "before" : "equivalent to"), + securityCheck(argv[2], fc->fileContents2)); + + return EXIT_SUCCESS; +} diff --git a/src/lab09/CMakeLists.txt b/src/lab09/CMakeLists.txt new file mode 100644 index 0000000..4b05b40 --- /dev/null +++ b/src/lab09/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(lab9C lab9C.cpp) +SET_FLAGS(lab9C "-fstack-protector-all -z relro -z now") + +add_executable(lab9A lab9A.cpp) +SET_FLAGS(lab9C "-fstack-protector-all -z relro -z now -fPIE -pie") + +# These are the files we want to give students +install(TARGETS lab9C lab9A DESTINATION "${RELEASE_DIR}/lab09") +install(FILES lab9C.cpp lab9C.readme lab9A.cpp lab9A.readme DESTINATION "${RELEASE_DIR}/lab09") diff --git a/src/lab09/lab9A.cpp b/src/lab09/lab9A.cpp new file mode 100644 index 0000000..8d47d11 --- /dev/null +++ b/src/lab09/lab9A.cpp @@ -0,0 +1,199 @@ +/* + * compile: g++ -fstack-protector-all -z relro -z now -O1 -fPIE -pie ./lab9A.cpp -g -o lab9A + * clark's improved item storage server! + * Changelog: + * * Using HashSets for insta-access! + * +*/ + +#include +#include +#include +#include +#include "utils.h" + +ENABLE_TIMEOUT(300) + +#define SIZE_HASHSET_VEC 8 + +void +print_menu(void) +{ + printf("+----------- clark's improved item storage -----------+\n" + "| [ -- Now using HashSets for insta-access to items! |\n" + "| 1. Open a lockbox |\n" + "| 2. Add an item to a lockbox |\n" + "| 3. Get an item from a lockbox |\n" + "| 4. Destroy your lockbox and items in it |\n" + "| 5. Exit |\n" + "+-----------------------------------------------------+\n"); +} + +/********* Storage implementation **********/ + +// hash functor +class hash_num { + public: + // I'm no mathematician + unsigned int + operator() (unsigned int const &key) const { + return key; + } +}; + +// Hashset +template +class HashSet { + public: + HashSet(unsigned int size) : m_size(size), set_data(new T[size]) {} + virtual ~HashSet() { delete [] set_data; } + virtual void add(T val); + virtual unsigned int find(T val); + virtual T get(unsigned int); + private: + unsigned int m_size; + HashFunc m_hash; + T *set_data; +}; +typedef HashSet hashset_int; + +template +void +HashSet::add(T val) +{ + int index = this->m_hash(val) % this->m_size; + this->set_data[index] = val; +} + +template +unsigned int +HashSet::find(T val) +{ + return this->m_hash(val) % this->m_size; +} + +template +T +HashSet::get(unsigned int index) +{ + if (index >= m_size) { + std::cout << "Invalid index" << std::endl; + return T(); + } + return set_data[index]; +} + +/********* Storage interface implementation **********/ +void +do_new_set(hashset_int **set_vec) +{ + int bin = -1; + int choice = -1; + std::cout << "Which lockbox do you want?: "; + bin = get_unum(); + if (bin < 0) { + std::cout << "Invalid set ID!" << std::endl; + return; + } else if (bin >= SIZE_HASHSET_VEC) { + std::cout << "No more room!" << std::endl; + return; + } + std::cout << "How many items will you store?: "; + choice = get_unum(); + set_vec[bin] = new hashset_int(choice); +} + +void +do_add_item(hashset_int **set_vec) +{ + int set_id = -1; + int item_val = -1; + + std::cout << "Which lockbox?: "; + set_id = get_unum(); + if (set_id < 0 || set_id >= SIZE_HASHSET_VEC) { + std::cout << "Invalid set ID!" << std::endl; + return; + } + + std::cout << "Item value: "; + item_val = get_unum(); + set_vec[set_id]->add(item_val); +} + +void +do_find_item(hashset_int **set_vec) +{ + int set_id = -1; + int item_val = -1; + int item_index = -1; + + std::cout << "Which lockbox?: "; + set_id = get_unum(); + if (set_id < 0 || set_id >= SIZE_HASHSET_VEC) { + std::cout << "Invalid set ID!" << std::endl; + return; + } + + std::cout << "Item value: "; + item_val = get_unum(); + item_index = set_vec[set_id]->find(item_val); + if (item_index == -1) { + std::cout << "Item not found!" << std::endl; + } else { + std::cout << "Item Found" << std::endl; + printf("lockbox[%d] = %d\n", item_index, set_vec[set_id]->get(item_index)); + } +} + +void +do_del_set(hashset_int **set_vec) +{ + int del_id; + std::cout << "Which set?: "; + del_id = get_unum(); + if (del_id < 0 || del_id >= SIZE_HASHSET_VEC) { + std::cout << "Invalid ID!" << std::endl; + return; + } + delete set_vec[del_id]; +} + +int +main(int argc, char *argv[]) +{ + hashset_int **set_vec = new hashset_int*[SIZE_HASHSET_VEC]; + int choice = -1; + bool done = false; + disable_buffering(stdout); + + while (!done) { + print_menu(); + std::cout << "Enter choice: "; + choice = get_unum(); + switch (choice) { + case 1: + do_new_set(set_vec); + break; + case 2: + do_add_item(set_vec); + break; + case 3: + do_find_item(set_vec); + break; + case 4: + do_del_set(set_vec); + break; + case 5: + done = true; + break; + default: + puts("Invalid option!"); + break; + } + } + + delete [] set_vec; + + return EXIT_SUCCESS; +} diff --git a/src/lab09/lab9A.readme b/src/lab09/lab9A.readme new file mode 100644 index 0000000..7673631 --- /dev/null +++ b/src/lab09/lab9A.readme @@ -0,0 +1 @@ +nc wargame.server.example 9941 diff --git a/src/lab09/lab9C.cpp b/src/lab09/lab9C.cpp new file mode 100644 index 0000000..e08d800 --- /dev/null +++ b/src/lab09/lab9C.cpp @@ -0,0 +1,91 @@ +/* + * compile: g++ -fstack-protector-all -z relro -z now ./lab9C.cpp -o lab9C + * + * DSVector - A basic homwork implementation of std::vector + * This is a wrapper program to test it! + */ + +#include +#include +#include +#include +#include +#include +#include "utils.h" + +ENABLE_TIMEOUT(60) + +void +print_menu(void) +{ + printf("+------- DSVector Test Menu -------+\n" + "| 1. Append item |\n" + "| 2. Read item |\n" + "| 3. Quit |\n" + "+----------------------------------+\n"); +} + +template +class DSVector { + public: + // I don't like indexing from 0, I learned VB.NET first. + DSVector() : len(1), alloc_len(len+256) {} + unsigned int size() { return len; } + void append(T item); + // No info leaks, either! + T get(unsigned int index) { return (index < alloc_len ? vector_data[index] : -1); }; + private: + unsigned int alloc_len; + unsigned int len; + // I was asleep during the dynamic sizing part, at least you can't overflow! + T vector_data[1+256]; +}; + +template +void +DSVector::append(T item) +{ + // No overflow for you! + if (len >= alloc_len) { + std::cout << "Vector is full!" << std::endl; + return; + } + vector_data[this->len++] = item; +} + +int +main(int argc, char *argv[]) +{ + DSVector test1; + unsigned int choice = 0; + bool done = false; + disable_buffering(stdout); + + while (!done) { + print_menu(); + std::cout << "Enter choice: "; + choice = get_unum(); + + /* handle menu selection */ + switch (choice) { + case 1: + std::cout << "Enter a number: "; + choice = get_unum(); + test1.append(choice); + break; + case 2: + std::cout << "Choose an index: "; + choice = get_unum(); + printf("DSVector[%d] = %d\n", choice, test1.get(choice)); + break; + case 3: + done = true; + break; + default: + puts("Invalid choice!"); + break; + } + } + + return EXIT_SUCCESS; +} diff --git a/src/lab09/lab9C.readme b/src/lab09/lab9C.readme new file mode 100644 index 0000000..c11f338 --- /dev/null +++ b/src/lab09/lab9C.readme @@ -0,0 +1 @@ +nc wargame.server.example 9943 diff --git a/src/lab10/CMakeLists.txt b/src/lab10/CMakeLists.txt new file mode 100644 index 0000000..a003474 --- /dev/null +++ b/src/lab10/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +#add_executable(lab10C lab10C.c) +#add_executable(lab10A lab10A.c) + +# These are the files we want to give students +#install(TARGETS lab10C lab10A DESTINATION "${RELEASE_DIR}/lab10") +#install(FILES lab10C.c lab10A.c DESTINATION "${RELEASE_DIR}/lab10") + diff --git a/src/lab10/README b/src/lab10/README new file mode 100644 index 0000000..bd84b42 --- /dev/null +++ b/src/lab10/README @@ -0,0 +1,10 @@ +To start lab C: + +ssh lab10C@warzone-kernel.rpis.ec +password: lab10start + + +Once you pwn the Kernel module to get root, you can read the flag, and the password for lab10A in /root/flag. + + +Good luck! diff --git a/src/lab10/lab10A.c b/src/lab10/lab10A.c new file mode 100644 index 0000000..ecd8e7c --- /dev/null +++ b/src/lab10/lab10A.c @@ -0,0 +1,355 @@ +/* +iptables sux. +*/ + + +#include // included for all kernel modules +#include // included for KERN_INFO +#include // included for __init and __exit macros + +#include // included for filesystem structs +#include // included for device driver stuff : +#include // Because memcpy :) +#include // get_random_bytes() + +// Networking Includes +#include +#include +#include +#include +#include + +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick Biernat"); +MODULE_DESCRIPTION("MBE Lab 10A"); + + +typedef struct disallow_filter { + unsigned int pr_num; + unsigned int port; + unsigned int id; + struct disallow_filter * next; + struct disallow_filter * prev; +}d; + +typedef struct callback_filter { + unsigned int pr_num; + unsigned int id; + + void (*callback)(struct callback_filter *); + struct callback_filter * next; + struct callback_filter * prev; +}c; + +struct disallow_filter * dfilter_head; +struct callback_filter * cfilter_head; +struct nf_hook_ops nfho; + +unsigned int pkt_hook(unsigned int hooknum, struct sk_buff *skb, const struct + net_device * in, const struct net_device * out, + int (*okfn)(struct sk_buff *)) { +/* + This function filters packets as they come into the system. + Callback filters take precedence over disallow filters. +*/ + + struct disallow_filter * walkera; + struct callback_filter * walkerb; + struct iphdr * ip_header; + + printk(KERN_INFO "[uTables] Got a packet!\n"); + + ip_header = (struct iphdr *)skb_network_header(skb); + + walkera = dfilter_head; + walkerb = cfilter_head; + + while(walkerb != 0) { + if(walkerb->pr_num == ip_header->protocol) { + break; + } + walkerb = walkerb->next; + } + if (walkerb) { + walkerb->callback(walkerb); + return NF_ACCEPT; + } + + while(walkera != 0) { + if (walkera->pr_num == ip_header->protocol) { + break; + } + walkera = walkera->next; + } + if (walkera) { + printk(KERN_INFO "[uTables] Caught a disallowed Packet!\n"); + return NF_DROP; + } + + + return NF_ACCEPT; +} + +void emulate_packet(int pnum) { + struct disallow_filter * walkera; + struct callback_filter * walkerb; + printk(KERN_INFO "[uTables] Emulating Protocol: %d\n", pnum); + + + walkera = dfilter_head; + walkerb = cfilter_head; + + while(walkerb != 0) { + if(walkerb->pr_num == pnum) { + break; + } + walkerb = walkerb->next; + } + if (walkerb) { + printk(KERN_INFO "Found callback filter!\n"); + walkerb->callback(walkerb); + return; + } + + while(walkera != 0) { + if (walkera->pr_num == pnum) { + break; + } + walkera = walkera->next; + } + if (walkera) { + printk(KERN_INFO "[uTables] Caught a disallowed Packet!\n"); + return; + } + return; +} + +void default_callback(struct sk_buff * skb) { + printk(KERN_INFO "[uTables] Default Callback Hit!\n"); + return; +} + +static ssize_t pwn_read(struct file* file, char * buf, size_t count, loff_t *ppos) +{ + return len; +} + +int add_cfilter(struct callback_filter * filt) { +/* + Add a callback filter to uTables. +*/ + struct callback_filter * nfilter, *walker; + printk("[uTables] Adding a callback filter\n"); + + nfilter = kmalloc(sizeof(struct callback_filter), GFP_KERNEL); + nfilter->pr_num = filt->pr_num; + nfilter->id = filt->id; + nfilter->callback = default_callback; + nfilter->next = 0; + + walker = cfilter_head; + while(walker->next != 0) { + walker = walker->next; + } + walker->next = nfilter; + nfilter->prev = walker; + + printk(KERN_INFO "New Filter At Address: %p\n", nfilter); + printk(KERN_INFO "New Filter Protocol: %u\n", nfilter->pr_num); + printk(KERN_INFO "New Filter ID: %u\n", nfilter->id); + printk(KERN_INFO "New Filter Callback @: %p\n", nfilter->callback); + printk(KERN_INFO "New Filter NEXT: %p\n", nfilter->next); + printk(KERN_INFO "New Filter PREV: %p\n", nfilter->prev); + + return 0; + +} + +int add_dfilter(struct disallow_filter * filt) { +/* + Add a disallow filter to uTables. +*/ + + struct disallow_filter * nfilter, *walker; + + printk("PR NUM: %d\n", filt->pr_num); + nfilter = kmalloc(sizeof(struct disallow_filter), GFP_KERNEL); + nfilter->pr_num = filt->pr_num; + nfilter->port = filt->port; + nfilter->id = filt->id; + nfilter->next = 0; + + walker = dfilter_head; + while(walker->next != 0) { + walker = walker->next; + } + walker->next = nfilter; + nfilter->prev = walker; + + printk(KERN_INFO "New Filter At Address: %p", nfilter); + printk(KERN_INFO "New Filter Protocol: %u\n", nfilter->pr_num); + printk(KERN_INFO "New Filter Port: %u\n", nfilter->port); + printk(KERN_INFO "New Filter ID: %u\n", nfilter->id); + + return 0; +} + +int remove_defilter(int pr_num) { +/* + Remove a filter for the specified protocol number. +*/ + struct disallow_filter * walker; + + walker = dfilter_head; + while(walker->pr_num != pr_num && walker != NULL){ + walker = walker->next; + } + if(walker) { + printk(KERN_INFO "Removing Filter for %u at %08x\n", walker->pr_num, walker); + walker->prev->next = walker->next; + if(walker->next) { + walker->next->prev = walker->prev; + } + kfree(walker); + return 0; + } + return -1; +} + +int modify_callback(void * data) { +/* + Apart from the default Callback, you may load + additional kernel modules and use their functions + as callback routines from the filtering hook here. +*/ + struct callback_filter * walker; + unsigned int addr; + unsigned int cid; + + memcpy(&cid, data, 4); + memcpy(&addr, data + 4, 4); + printk(KERN_INFO "Addr: %u\n", addr); + printk(KERN_INFO "ID: %u\n", cid); + + if (addr < 0xc0000000) { + printk(KERN_INFO "[ERROR] Userspace Address detected!\n"); + return -1; + } + + walker = cfilter_head; + while (walker != 0) { + if (walker->id == cid) { + break; + } + walker = walker->next; + } + if (walker) { + walker->callback = addr; + printk(KERN_INFO "Updated Filter ID: %u Callback to : %u\n",walker->id, walker->callback); + } + else { + printk(KERN_INFO "Could not find Filter with ID: %u\n",walker->id); + return -1; + } + return 0; +} + +static ssize_t pwn_write(struct file* file, const char * buf, size_t count, loff_t *ppos) +{ // This is how you configure uTables + + if (buf[0] == '\x01') { // Now you know you're talking to this thing :) + printk(KERN_INFO "The flag is in /root/flag\n"); + } + + if (buf[0] == '\x02') { // Add a disallow filter + printk(KERN_INFO "[uTables] Adding new disallow filter\n"); + printk(KERN_INFO "PR: %u", buf[1]); + add_dfilter( (struct disallow_filter *) &(buf[1])); + } + + if (buf[0] == '\x03') { // Add a callback filter + printk(KERN_INFO "[uTables] Adding a new callback filter\n"); + add_cfilter( (struct callback_filter *) &(buf[1])); + } + + if (buf[0] == '\x04') { // Modify a callback function + printk(KERN_INFO "[uTables] Modifying a callback\n"); + modify_callback((void *) &(buf[4])); + } + + if (buf[0] == '\x05') { // Emulate a Packet arriving in the kernel. + printk(KERN_INFO "[uTables] Emulating a packet arriving\n"); + emulate_packet( (int) (buf[1])); + + } + + return count; +} + + +static const struct file_operations pwnops = { + .owner = THIS_MODULE, + .read = pwn_read, + .write = pwn_write, +}; + +static struct miscdevice pwn_dev = { + MISC_DYNAMIC_MINOR, "pwn" , &pwnops +}; + +static int __init mod_init(void) +{ +/* + Initialize data structures and register a device that will be used to + configure uTables. + Also set up our networking hook so we can look at packets coming into the + kernel. +*/ + + int ret; + // Register our device and create heads for our linked lists + ret = misc_register(&pwn_dev); + dfilter_head = kmalloc(sizeof(struct disallow_filter), GFP_KERNEL); + cfilter_head = kmalloc(sizeof(struct callback_filter), GFP_KERNEL); + + // Initialize our linked list heads + dfilter_head->pr_num = -1; + dfilter_head->port = -1; + dfilter_head->next = 0; + dfilter_head->prev = 0; + + cfilter_head->pr_num = -1; + cfilter_head->id = -1; + cfilter_head->callback = default_callback; + cfilter_head->next = 0; + cfilter_head->prev = 0; + + // Set up our basic netfilter hook + nfho.hook = pkt_hook; + nfho.hooknum = 0; + nfho.pf = PF_INET; + nfho.priority = NF_IP_PRI_FIRST; + + // Register our hook + nf_register_hook(&nfho); + + printk(KERN_INFO "Finished Init\n"); + printk(KERN_INFO "Can u get r00t?\n"); + return 0; +} + +static void __exit mod_cleanup(void) +{ + printk(KERN_INFO "Cleaning up module.\n"); + misc_deregister(&pwn_dev); + nf_unregister_hook(&nfho); +} + + +// We're "registering" our module with the rest of the Kernel here. +module_init(mod_init); +module_exit(mod_cleanup); + + diff --git a/src/lab10/lab10C.c b/src/lab10/lab10C.c new file mode 100644 index 0000000..6cd40f1 --- /dev/null +++ b/src/lab10/lab10C.c @@ -0,0 +1,127 @@ +/* +Unix-Dude sux at writing rootkits. + +He forgot the get_r00t code q_q. +*/ + + +#include // included for all kernel modules +#include // included for KERN_INFO +#include // included for __init and __exit macros + +#include // included for filesystem structs +#include // included for device driver stuff : +#include // Because memcpy :) +#include // get_random_bytes() + +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick Biernat"); +MODULE_DESCRIPTION("MBE Lab 10 C"); + +unsigned int secret; + +typedef struct key_material { + char key[1024]; + void (*algo)(char *); + int auth; +}da_keyz; + + +struct key_material * sekret; + +static ssize_t pwn_write(struct file* file, const char * buf, size_t count, loff_t *ppos) +{ // Here we check for the password + + printk(KERN_INFO "%s\n",buf); + if( count == 0x31337) { + if (sekret->auth) { + // Do the root thing here. + printk(KERN_INFO "Nice privs bro.\n"); + } + return 0x31337; + } + + if(buf[0] == '\x01') { + printk("Flag is @ /root/flag"); + } + + if ( ( *(unsigned int *)buf ^ 0xcafebabe) == 0) { + printk(KERN_INFO "Performing Key Authentication now...\n"); + sekret->algo(buf); + } + + return count; +} + + +static const struct file_operations pwnops = { + .owner = THIS_MODULE, + .write = pwn_write, +}; + +static struct miscdevice pwn_dev = { + MISC_DYNAMIC_MINOR, "pwn" , &pwnops +}; + +void algo_xor(char * buf) { +/* + Secure One-Time Pad Authentication Function. +*/ + int i; + int sum; + + sum = 0; + printk(KERN_INFO "Inside algo_xor!\n"); + + for(i=0; i <= 1024; i++) { + sekret->key[i] ^= buf[i]; + } + + for(i=0; i <= 1024; i++) { + sum += sekret->key[i]; + } + + if(sum == 0) { + sekret->auth = 1; + } + else { + printk(KERN_INFO "Authentication Failed!\n"); + memset(sekret, 0 , sizeof(struct key_material)); + get_random_bytes(&(sekret->key),1024); + } + return; +} + +//Think of this as the familiar "main" function +static int __init mod_init(void) +{ + int ret; + // Register Device to /dev + ret = misc_register(&pwn_dev); + + // Allocate Space for the key + sekret = kmalloc(sizeof(struct key_material), GFP_KERNEL); + get_random_bytes(&sekret->key, 1024); + + // Set the algorithm to a sane default + sekret->algo = algo_xor; + + printk(KERN_INFO "Finished Init\n"); + printk(KERN_INFO "Can u get r00t?\n"); + return 0; +} + +static void __exit mod_cleanup(void) +{ + printk(KERN_INFO "Cleaning up module.\n"); + misc_deregister(&pwn_dev); +} + + +//We're "registering" our module with the rest of the Kernel here. +module_init(mod_init); +module_exit(mod_cleanup); + + diff --git a/src/lecture/CMakeLists.txt b/src/lecture/CMakeLists.txt new file mode 100644 index 0000000..10fe7d3 --- /dev/null +++ b/src/lecture/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) + +set(RELEASE_DIR "${RELEASE_DIR}/lecture") + +# Adds all of the level directories +SUBDIRLIST(SUBDIRS ${CMAKE_CURRENT_SOURCE_DIR}) +foreach(subdir ${SUBDIRS}) + message(STATUS "Building lecture:${subdir}...") + add_subdirectory(${subdir}) +endforeach() diff --git a/src/lecture/aslr/CMakeLists.txt b/src/lecture/aslr/CMakeLists.txt new file mode 100644 index 0000000..d5ba866 --- /dev/null +++ b/src/lecture/aslr/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(aslr2 aslr2.c) +SET_FLAGS(aslr2 "-static -z execstack -fno-stack-protector") + +add_executable(aslr_leak1 aslr_leak1.c) +SET_FLAGS(aslr_leak1 "-pie -fPIE -fno-stack-protector") + +add_executable(aslr_leak2 aslr_leak2.c) +SET_FLAGS(aslr_leak2 "-pie -fPIE -fno-stack-protector") + +# These are the files we want to give students +install(TARGETS aslr2 aslr_leak1 aslr_leak2 DESTINATION "${RELEASE_DIR}/aslr") +install(FILES aslr2.c aslr_leak1.c aslr_leak2.c DESTINATION "${RELEASE_DIR}/aslr") diff --git a/src/lecture/aslr/aslr2.c b/src/lecture/aslr/aslr2.c new file mode 100644 index 0000000..62b3ffd --- /dev/null +++ b/src/lecture/aslr/aslr2.c @@ -0,0 +1,25 @@ +/* +Exploitation with ASLR Enabled +Lecture: Example 2 +Modern Binary Exploitation + +Compiled with: +gcc -m32 -fno-stack-protector -z execstack -static ./aslr2.c + +Patrick Biernat +*/ + + +#include +#include + +int main(int argc, char** argv) +{ + char my_string[16]; + char THE_TRICK[2] = "\xFF\xE4"; + + fgets(my_string,40,stdin); + + + return 0; +} diff --git a/src/lecture/aslr/aslr_leak1.c b/src/lecture/aslr/aslr_leak1.c new file mode 100644 index 0000000..854c46a --- /dev/null +++ b/src/lecture/aslr/aslr_leak1.c @@ -0,0 +1,29 @@ +/* +Exploitation with ASLR Enabled +Lecture: Example 1 +Modern Binary Exploitation + +Compiled with: +gcc -pie -fPIE -fno-stack-protector -o aslr_leak1 aslr_leak1.c + +-Patrick Biernat +*/ +#include +#include + +void i_am_rly_leet() +{ + printf("You found me!\nGood job!\n"); + return; +} + +int main(int argc, char** argv) +{ + char my_string[16]; + printf("Win Func @ %p\n",i_am_rly_leet); + fflush(stdout); + fgets(my_string,40,stdin); + + + return 0; +} diff --git a/src/lecture/aslr/aslr_leak2.c b/src/lecture/aslr/aslr_leak2.c new file mode 100644 index 0000000..984abc0 --- /dev/null +++ b/src/lecture/aslr/aslr_leak2.c @@ -0,0 +1,23 @@ +#include +#include + +/* gcc -pie -fPIE -fno-stack-protector -o aslr_leak2 ./aslr_leak2.c */ + +int main(int argc, char * argv[]) +{ + char leaky[16]; + + if(argc < 2) + { + printf("Please provide two arguments.\n"); + return 1; + } + + memcpy(leaky, argv[1], 16); + + printf("Leaky buffer: %s\n", leaky); + printf("another round? : "); + fgets(leaky, 64, stdin); + + return 0; +} diff --git a/src/lecture/cpp/CMakeLists.txt b/src/lecture/cpp/CMakeLists.txt new file mode 100644 index 0000000..c64af5b --- /dev/null +++ b/src/lecture/cpp/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(rect rect.cpp) + +add_executable(cpp_lec01 cpp_lec01.cpp) + +add_executable(cpp_lec02 cpp_lec02.cpp) + +# These are the files we want to give students +install(TARGETS rect cpp_lec01 cpp_lec02 DESTINATION "${RELEASE_DIR}/cpp") +install(FILES rect.cpp cpp_lec01.cpp cpp_lec02.cpp DESTINATION "${RELEASE_DIR}/cpp") diff --git a/src/lecture/cpp/cpp_lec01.cpp b/src/lecture/cpp/cpp_lec01.cpp new file mode 100644 index 0000000..d398bda --- /dev/null +++ b/src/lecture/cpp/cpp_lec01.cpp @@ -0,0 +1,45 @@ +#include +#include +#include + +class Foo { +public: + virtual void greet() { printf("Foo says hi\n"); } + void me() { printf("Foo is best\n"); } +}; + +class Bar : public Foo { +public: + virtual void greet() { printf("Bar says hi\n"); } + virtual void dismiss() { printf("Bar says bye\n"); } + void me() { printf("Bar is best\n"); } +}; + +class Baz : public Bar { +public: + void dismiss() { printf("Baz says bye \n"); } + void me() { printf("Baz is best\n"); } +}; + +int +main(int argc, char *argv[]) +{ + Foo foo; + Bar bar; + Baz baz; + Bar *barbaz = (Bar *)new Baz; + + foo.greet(); + puts("\n"); + + bar.greet(); + bar.me(); + bar.dismiss(); + puts("\n"); + + barbaz->me(); + barbaz->dismiss(); + + return 0; +} + diff --git a/src/lecture/cpp/cpp_lec02.cpp b/src/lecture/cpp/cpp_lec02.cpp new file mode 100644 index 0000000..e8fe8a0 --- /dev/null +++ b/src/lecture/cpp/cpp_lec02.cpp @@ -0,0 +1,70 @@ +/* + * Credit: https://defuse.ca/exploiting-cpp-vtables.htm + */ + +#include +#include +#include + +class CodeTester { + public: + virtual void test(const char*code) + { + int (*ret)() = (int(*)())code; + ret(); + } +}; + +class CommandExecutor { + public: + virtual void execute(const char *command) + { + system(command); + } +}; + +class Greeter { + public: + virtual void sayHello(const char *name) + { + printf("Hello, %s!\n", name); + } +}; + +void greet(Greeter *greeter); +void doNothing(); + +int main(int argc, char **argv) +{ + Greeter g; + char buf[64]; + printf("You must be 18 years or older to use this program. Are you? "); + + doNothing(); + + gets(buf); /* OVERFLOW */ + if (strcmp(buf, "y") == 0) { + greet(&g); + return 0; + } else { + return 1; + } +} + +void greet(Greeter *greeter) +{ + char name[100]; + printf("What is your name? "); + fgets(name, 100, stdin); + name[strlen(name)-1] = '\0'; + greeter->sayHello(name); +} + +/* This exists just so that the compiler/linker needs to include + * CommandExecutor's code, since otherwise it would be unused. */ +void doNothing() +{ + CommandExecutor e; + CodeTester c; +} + diff --git a/src/lecture/cpp/rect.cpp b/src/lecture/cpp/rect.cpp new file mode 100644 index 0000000..38324c5 --- /dev/null +++ b/src/lecture/cpp/rect.cpp @@ -0,0 +1,37 @@ +#include +#include + +class Rect { + public: + Rect() : width(0), height(0) {} + int area() { return width*height; } + void set_vals(int w, int h); + private: + int width; + int height; +}; + +void +Rect::set_vals(int w, int h) +{ + this->width = w; + this->height = h; +} + +int +main(int argc, char *argv[]) +{ + Rect r; + + printf("sizeof(r) = %d\n", sizeof(r)); + + int *vars = (int *)&r; + + printf("width = %d, height = %d\n", vars[0], vars[1]); + + r.set_vals(10, 24); + printf("setvals(10, 24);\n"); + printf("width = %d, height = %d\n", vars[0], vars[1]); + + return 0; +} diff --git a/src/lecture/format_strings/CMakeLists.txt b/src/lecture/format_strings/CMakeLists.txt new file mode 100644 index 0000000..17c420d --- /dev/null +++ b/src/lecture/format_strings/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(fmt_lec01 fmt_lec01.c) +add_executable(fmt_lec02 fmt_lec02.c) +add_executable(fmt_lec03 fmt_lec03.c) +add_executable(fmt_lec04 fmt_lec04.c) + +# These are the files we want to give students +install(TARGETS fmt_lec01 fmt_lec02 fmt_lec03 fmt_lec04 DESTINATION "${RELEASE_DIR}/format_strings") +install(FILES fmt_lec01.c fmt_lec02.c fmt_lec03.c fmt_lec04.c DESTINATION "${RELEASE_DIR}/format_strings") diff --git a/src/lecture/format_strings/fmt_lec01.c b/src/lecture/format_strings/fmt_lec01.c new file mode 100644 index 0000000..b861703 --- /dev/null +++ b/src/lecture/format_strings/fmt_lec01.c @@ -0,0 +1,17 @@ +/* + * Format Strings Example 1 + * + */ +#include +#include + +int +main(int argc, char *argv[]) +{ + char buf[100]; + + fgets(buf, 100, stdin); + printf(buf); + + return EXIT_SUCCESS; +} diff --git a/src/lecture/format_strings/fmt_lec02.c b/src/lecture/format_strings/fmt_lec02.c new file mode 100644 index 0000000..cb0156e --- /dev/null +++ b/src/lecture/format_strings/fmt_lec02.c @@ -0,0 +1,29 @@ +/* + * Format Strings Example 2 + * + */ +#include +#include + +int +main(int argc, char *argv[]) +{ + int unchangeable = 0xcafebabe; + char buf[100]; + + fgets(buf, 100, stdin); + printf(buf); + + //HINT + fprintf(stderr, "unchangeable @ %p\n", &unchangeable); + + //fgets makes it impossible to overflow the buffer, + // but just in case... + if (unchangeable != 0xcafebabe) { + printf("Cookie overwritten!\n"); + printf("unchangeable changed to %#x\n", unchangeable); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/src/lecture/format_strings/fmt_lec03.c b/src/lecture/format_strings/fmt_lec03.c new file mode 100644 index 0000000..b67d7f8 --- /dev/null +++ b/src/lecture/format_strings/fmt_lec03.c @@ -0,0 +1,29 @@ +/* + * Format Strings Example 3 + * + */ +#include +#include + +int +main(int argc, char *argv[]) +{ + int unchangeable = 0xdeadbeef; + char buf[100]; + + fgets(buf, 100, stdin); + printf(buf); + + //HINT + fprintf(stderr, "unchangeable @ %p\n", &unchangeable); + + if (unchangeable == 0xcafebabe) { + printf("Success!\n"); + } else { + printf("Failure!\n"); + printf("unchangeable is %#x", unchangeable); + exit(EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} diff --git a/src/lecture/format_strings/fmt_lec04.c b/src/lecture/format_strings/fmt_lec04.c new file mode 100644 index 0000000..1538272 --- /dev/null +++ b/src/lecture/format_strings/fmt_lec04.c @@ -0,0 +1,15 @@ +#include +#include + +int +main(int argc, char *argv[]) +{ + char buf[100]; + + fgets(buf, 100, stdin); + printf(buf); + fgets(buf, 100, stdin); + printf(buf); + + return EXIT_SUCCESS; +} diff --git a/src/lecture/heap/CMakeLists.txt b/src/lecture/heap/CMakeLists.txt new file mode 100644 index 0000000..f2876c6 --- /dev/null +++ b/src/lecture/heap/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(heap_chunks heap_chunks.c) + +add_executable(heap_smash heap_smash.c) + +add_executable(heap_uaf heap_uaf.c) +SET_FLAGS(heap_uaf "-z relro -z now -fPIE -pie -fstack-protector-all") + +add_executable(sizes sizes.c) + +# These are the files we want to give students +install(TARGETS heap_chunks heap_smash heap_uaf sizes DESTINATION "${RELEASE_DIR}/heap") +install(FILES heap_chunks.c heap_smash.c heap_uaf.c sizes.c DESTINATION "${RELEASE_DIR}/heap") diff --git a/src/lecture/heap/heap_chunks.c b/src/lecture/heap/heap_chunks.c new file mode 100644 index 0000000..6ff83d2 --- /dev/null +++ b/src/lecture/heap/heap_chunks.c @@ -0,0 +1,34 @@ +/* compiled with: gcc -o heap_chunks heap_chunks.c */ +#include +#include +#include + +#define LEN 15 + +void print_chunk(unsigned int * ptr, unsigned int len) +{ + + printf("[ prev - 0x%08x ][ size - 0x%08x ][ data buffer (0x%08x) -------> ... ] - from malloc(%d)\n", \ + *(ptr-2), + *(ptr-1), + (unsigned int)ptr, + len); +} + +int main() +{ + unsigned int * ptr[LEN]; + unsigned int lengths[] = {0, 4, 8, 16, 24, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384}; + int i; + + /* malloc chunks, and them print their fields */ + printf("mallocing...\n"); + + for(i = 0; i < LEN; i++) + ptr[i] = malloc(lengths[i]); + + for(i = 0; i < LEN; i++) + print_chunk(ptr[i], lengths[i]); + + return 0; +} diff --git a/src/lecture/heap/heap_smash.c b/src/lecture/heap/heap_smash.c new file mode 100644 index 0000000..4843e99 --- /dev/null +++ b/src/lecture/heap/heap_smash.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +struct toystr { + void (* message)(char *); + char buffer[20]; +}; + +void print_super(char * who) +{ + printf("%s is superrr cool......\n", who); +} + +void print_cool(char * who) +{ + printf("%s is cool!\n", who); +} + +void print_meh(char * who) +{ + printf("%s is meh...\n", who); +} + +int main(int argc, char * argv[]) +{ + struct toystr * coolguy = NULL; + struct toystr * lameguy = NULL; + + coolguy = malloc(sizeof(struct toystr)); + lameguy = malloc(sizeof(struct toystr)); + + coolguy->message = &print_cool; + lameguy->message = &print_meh; + + printf("Input coolguy's name: "); + fgets(coolguy->buffer, 200, stdin); + coolguy->buffer[strcspn(coolguy->buffer, "\n")] = 0; + + printf("Input lameguy's name: "); + fgets(lameguy->buffer, 20, stdin); + lameguy->buffer[strcspn(lameguy->buffer, "\n")] = 0; + + coolguy->message(coolguy->buffer); + lameguy->message(lameguy->buffer); + + return 0; +} diff --git a/src/lecture/heap/heap_uaf.c b/src/lecture/heap/heap_uaf.c new file mode 100644 index 0000000..24ee8c6 --- /dev/null +++ b/src/lecture/heap/heap_uaf.c @@ -0,0 +1,149 @@ +/* doom doesn't mess around with his gcc protections, everything is on! */ +/* compiled with: gcc -z relro -z now -fPIE -pie -fstack-protector-all -o heap_uaf heap_uaf.c */ + +#include +#include +#include +#include + +struct toystr { + void (* message)(char *); + char buffer[20]; +}; + +struct person { + int favorite_num; + int age; + char name[16]; +}; + +void print_cool(char * who) +{ + printf("%s is cool!\n", who); +} + +void print_meh(char * who) +{ + printf("%s is meh...\n", who); +} + +void secret_shell() +{ + execve("/bin/sh", NULL, NULL); +} + +void print_menu() +{ + printf("-- Menu ----------------------\n" + "1. Make coolguy\n" + "2. Make a_person\n" + "3. Delete coolguy\n" + "4. Delete a_person\n" + "5. Print coolguy message\n" + "6. Print person info\n" + "7. Quit\n" + "Enter Choice: "); +} + +/* bugs galore... but no memory corruption! */ +int main(int argc, char * argv[]) +{ + struct toystr * coolguy = NULL; + struct person * a_person = NULL; + int choice = 0; + + while(1) + { + print_menu(); + + /* get menu option */ + scanf("%u", &choice); + getc(stdin); + + /* perform menu actions */ + if(choice == 1) + { + coolguy = malloc(sizeof(struct toystr)); + printf("New coolguy is at 0x%08x\n", (unsigned int)coolguy); + + /* no memory corruption this time */ + printf("Input coolguy's name: "); + fgets(coolguy->buffer, 20, stdin); + coolguy->buffer[strcspn(coolguy->buffer, "\n")] = 0; + coolguy->message = &print_cool; + + /* yay */ + printf("Created new coolguy!\n"); + } + else if(choice == 2) + { + a_person = malloc(sizeof(struct person)); + printf("New person is at 0x%08x\n", (unsigned int)a_person); + + /* initialize a_person */ + printf("Input a_person's name: "); + fgets(a_person->name, 16, stdin); + a_person->name[strcspn(a_person->name, "\n")] = 0; + + printf("Input a_person's favorite number: "); + scanf("%u", &a_person->favorite_num); + getc(stdin); + + printf("Input a_person's age: "); + scanf("%u", &a_person->age); + getc(stdin); + if(a_person->age > 110 || a_person->age < 0) + printf("Wow your age is pretty crazy yo\n"); + + /* all done here */ + printf("Created a new person!\n"); + } + else if(choice == 3) + { + if(coolguy) + { + free(coolguy); + printf("Deleted coolguy!\n"); + } + else + printf("There is no coolguy to free!\n"); + } + else if(choice == 4) + { + if(a_person) + { + free(a_person); + printf("Deleted person!\n"); + } + else + printf("There is no person to free!\n"); + } + else if(choice == 5) + { + if(coolguy) + coolguy->message(coolguy->buffer); + else + printf("There is no coolguy to print the cool message!\n"); + } + else if(choice == 6) + { + if(a_person) + { + printf("Person's name: %s\n", a_person->name); + printf("Person's age: %d\n", a_person->age); + printf("Persons' favorite number: %u\n", a_person->favorite_num); + } + else + printf("There is no person to print!\n"); + } + else if(choice == 7) + break; + else + printf("Invalid choice!\n"); + + choice = 0; + } + + printf("See you tomorrow!\n"); + return 0; +} diff --git a/src/lecture/heap/print_frees.c b/src/lecture/heap/print_frees.c new file mode 100644 index 0000000..4b3ba9c --- /dev/null +++ b/src/lecture/heap/print_frees.c @@ -0,0 +1,53 @@ +/* compiled with: gcc -o print_frees print_frees.c */ +#include +#include +#include + +#define LEN 15 + +void print_chunk(unsigned int * ptr) +{ + /* LOL MAGIC */ + int is_free = *((*(ptr-1) & ~7)/4 + (ptr-1)) & 1; + + if(is_free) + { + printf("[ prev - 0x%08x ][ size - 0x%08x ][ data buffer (0x%08x) ----> ... ] - Chunk 0x%08x - In use\n", \ + *(ptr-2), + *(ptr-1), + (unsigned int)ptr, + (unsigned int)(ptr-2)); + }else{ + + printf("[ prev - 0x%08x ][ size - 0x%08x ][ fd - 0x%08x ][ bk - 0x%08x ] - Chunk 0x%08x - Freed\n", \ + *(ptr-2), + *(ptr-1), + *ptr, + *(ptr+1), + (unsigned int)(ptr-2)); + } + +} + +int main() +{ + unsigned int * ptr[LEN]; + unsigned int lengths[] = {0, 4, 8, 16, 24, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384}; + int i; + + printf("mallocing...\n"); + for(i = 0; i < LEN; i++) + ptr[i] = malloc(lengths[i]); + + for(i = 0; i < LEN; i++) + print_chunk(ptr[i]); + + printf("\nfreeing every other chunk...\n"); + for(i = 0; i < LEN; i+=2) + free(ptr[i]); + + for(i = 0; i < LEN-1; i++) + print_chunk(ptr[i]); + + return 0; +} diff --git a/src/lecture/heap/sizes.c b/src/lecture/heap/sizes.c new file mode 100644 index 0000000..316e288 --- /dev/null +++ b/src/lecture/heap/sizes.c @@ -0,0 +1,27 @@ +/* compiled with: gcc -o sizes sizes.c */ + +#include +#include +#include + +int main() +{ + + unsigned int lengths[] = {32, 4, 20, 0, 64, 32, 32, 32, 32, 32}; + unsigned int * ptr[10]; + int i; + + /* make arbitrary chunks on the heap */ + for(i = 0; i < 10; i++) + ptr[i] = malloc(lengths[i]); + + /* print distance between chunks, eg size of chunks */ + for(i = 0; i < 9; i++) + printf("malloc(%2d) is at 0x%08x, %3d bytes to the next pointer\n", + lengths[i], + (unsigned int)ptr[i], + (ptr[i+1]-ptr[i])*sizeof(unsigned int)); + + + return 0; +} diff --git a/src/lecture/misc/CMakeLists.txt b/src/lecture/misc/CMakeLists.txt new file mode 100644 index 0000000..565adbd --- /dev/null +++ b/src/lecture/misc/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(canary canary.c) +add_executable(heap heap.c) +add_executable(uninitialized_data uninitialized_data.c) + +# These are the files we want to give students +install(TARGETS canary heap uninitialized_data DESTINATION "${RELEASE_DIR}/misc") +install(FILES canary.c heap.c uninitialized_data.c DESTINATION "${RELEASE_DIR}/misc") diff --git a/src/lecture/misc/canary.c b/src/lecture/misc/canary.c new file mode 100644 index 0000000..562b9db --- /dev/null +++ b/src/lecture/misc/canary.c @@ -0,0 +1,33 @@ +#include +#include +#define STDIN 0 +//gcc -fstack-protector-all -mpreferred-stack-boundary=2 -o canary canary.c + +void contrivedLeak() { + char buf[512]; + scanf("%s", buf); + printf(buf); + return; +} + +void contrivedOverflow() { + printf("\n..I like to read ^_^ <== "); + char buf[24]; + read(STDIN, buf, 48); + char lolz[24]; + strcpy(lolz, buf); + printf(lolz); + return; +} + +int main(int argc, char* argv[]) { + setbuf(stdout, NULL); + printf("What you give, you will get back\n"); + printf("==> white elephants: "); + contrivedLeak(); + printf("\nYou're lucky numbers are 512 and 1024\n"); + contrivedOverflow(); + printf("\n\nWoah There\n"); + return 0; + +} diff --git a/src/lecture/misc/heap.c b/src/lecture/misc/heap.c new file mode 100644 index 0000000..afc1e42 --- /dev/null +++ b/src/lecture/misc/heap.c @@ -0,0 +1,50 @@ +/* + * This level is completed when you see the “you have logged in already!” message + * https://exploit-exercises.com/protostar/heap2/ + */ + +#include +#include +#include +#include +#include + +struct auth { + char name[32]; + int auth; +}; + +struct auth *auth; +char *service; + +int main(int argc, char **argv) +{ + char line[128]; + + while(1) { + printf("[ auth = %p, service = %p ]\n", auth, service); + + if(fgets(line, sizeof(line), stdin) == NULL) break; + + if(strncmp(line, "auth ", 5) == 0) { + auth = malloc(sizeof(auth)); + memset(auth, 0, sizeof(auth)); + if(strlen(line + 5) < 31) { + strcpy(auth->name, line + 5); + } + } + if(strncmp(line, "reset", 5) == 0) { + free(auth); + } + if(strncmp(line, "service", 6) == 0) { + service = strdup(line + 7); + } + if(strncmp(line, "login", 5) == 0) { + if(auth->auth) { + printf("you have logged in already!\n"); + } else { + printf("please enter your password\n"); + } + } + } +} diff --git a/src/lecture/misc/uninitialized_data.c b/src/lecture/misc/uninitialized_data.c new file mode 100644 index 0000000..f689ee4 --- /dev/null +++ b/src/lecture/misc/uninitialized_data.c @@ -0,0 +1,56 @@ +#include +#include +#include +#define MAX_USER 1024 +#define MAX_PASS MAX_USER +#define ERR_CRITIC 0x01 +#define ERR_AUTH 0x02 + +void escape(char* cmd) +{ + system(cmd); +} + +int do_auth(void) +{ + char username[MAX_USER], password[MAX_PASS]; + fprintf(stdout, "Please enter your username: "); + fgets(username, MAX_USER, stdin); + fflush(stdin); + fprintf(stdout, "Please enter your password: "); + fgets(password, MAX_PASS, stdin); +#ifdef DEBUG + fprintf(stderr, "Username is at: 0x%08x (%d)\n", &username, strlen(username)); + fprintf(stderr, "Password is at: 0x%08x (%d)\n", &password, strlen(password)); +#endif + if(!strcmp(username, "user") && !strcmp(password, "washere")) + { + return 0; + } + return -1; +} +int log_error(int farray, char *msg) +{ + char *err, *mesg; + char buffer[24]; +#ifdef DEBUG + fprintf(stderr, "Mesg is at: 0x%08x\n", &mesg); + fprintf(stderr, "Mesg is pointing at: 0x%08x\n", mesg); +#endif + memset(buffer, 0x00, sizeof(buffer)); + sprintf(buffer, "Error: %s", mesg); + fprintf(stdout, "%s\n", buffer); + return 0; +} +int main(void) +{ + switch(do_auth()) + { + case -1: + log_error(ERR_CRITIC | ERR_AUTH, "Unable to login"); + break; + default: + break; + } + return 0; +} diff --git a/src/lecture/misc/uninitialized_data_noaslr.sh b/src/lecture/misc/uninitialized_data_noaslr.sh new file mode 100755 index 0000000..51f88e5 --- /dev/null +++ b/src/lecture/misc/uninitialized_data_noaslr.sh @@ -0,0 +1,3 @@ +#/bin/sh +# Note: This will drop privileges, and so can't be used for exploiting setuid binaries. +setarch $(uname -m) -R /levels/lecture/misc/uninitialized_data diff --git a/src/lecture/rop/CMakeLists.txt b/src/lecture/rop/CMakeLists.txt new file mode 100644 index 0000000..ec5c73f --- /dev/null +++ b/src/lecture/rop/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(rop_exit rop_exit.c) + +add_executable(rop_pivot rop_pivot.c) +SET_FLAGS(rop_pivot "-static") + +# These are the files we want to give students +install(TARGETS rop_exit rop_pivot DESTINATION "${RELEASE_DIR}/rop") +install(FILES rop_exit.c rop_pivot.c DESTINATION "${RELEASE_DIR}/rop") diff --git a/src/lecture/rop/rop_exit.c b/src/lecture/rop/rop_exit.c new file mode 100644 index 0000000..517471b --- /dev/null +++ b/src/lecture/rop/rop_exit.c @@ -0,0 +1,13 @@ +#include + +int main() +{ + char buffer[128] = {0}; + + /* break stuff */ + printf("insert ropchain: "); + gets(buffer); + + /* program always returns 0 */ + return 0; +} diff --git a/src/lecture/rop/rop_pivot.c b/src/lecture/rop/rop_pivot.c new file mode 100644 index 0000000..afa0e24 --- /dev/null +++ b/src/lecture/rop/rop_pivot.c @@ -0,0 +1,29 @@ +#include + +/* gcc -static -o rop_pivot rop_pivot.c */ + +int main(int argc, char * argv[]) +{ + char buffer[128] = {0}; + int overwrite[1] = {0}; + + if(argc < 3) + { + printf("I need two arguments\n"); + printf("Usage: %s [overwrite index] [overwrite address]\n", argv[0]); + return 1; + } + + /* create a pivot scenario */ + printf("Overwriting 0x%08x with 0x%08x\n", \ + overwrite[strtoul(argv[1], NULL, 10)], strtoul(argv[2], NULL, 10)); + overwrite[strtoul(argv[1], NULL, 10)] = strtoul(argv[2], NULL, 10); + + /* read a rop chain */ + printf("insert ropchain: "); + fgets(buffer, 128, stdin); + + /* program always returns 0 */ + return 0; +} + diff --git a/src/lecture/shellcode/CMakeLists.txt b/src/lecture/shellcode/CMakeLists.txt new file mode 100644 index 0000000..1381c76 --- /dev/null +++ b/src/lecture/shellcode/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.8) + +# Adds an executable target +add_executable(inject inject.c) +SET_FLAGS(inject "${NO_MITS_FLAGS}") + +# These are the files we want to give students +install(TARGETS inject DESTINATION "${RELEASE_DIR}/shellcode") +install(FILES inject.c DESTINATION "${RELEASE_DIR}/shellcode") diff --git a/src/lecture/shellcode/inject.c b/src/lecture/shellcode/inject.c new file mode 100644 index 0000000..a5d7f49 --- /dev/null +++ b/src/lecture/shellcode/inject.c @@ -0,0 +1,15 @@ +#include + +/* gcc -z execstack -fno-stack-protector -o inject inject.c */ + +int main() +{ + char buffer[128]; + + puts("where we're going"); + puts("we don't need ... roads."); + gets(buffer); + + return 0; +} + diff --git a/src/project1/CMakeLists.txt b/src/project1/CMakeLists.txt new file mode 100644 index 0000000..b9f29bf --- /dev/null +++ b/src/project1/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.8) + +# These are the files we want to give students +install(FILES tw33tchainz README DESTINATION "${RELEASE_DIR}/project1") diff --git a/src/project1/README b/src/project1/README new file mode 100644 index 0000000..30110da --- /dev/null +++ b/src/project1/README @@ -0,0 +1,10 @@ +Project one is representative of what you might see in the average 200 point +CTF challenge. There is no source provided and you’re expected to do some +reverse engineering with IDA. Through reversing and playing around with the +challenge, you will likely find the issues and vulnerabilities you can leverage +to take control of the challenge. + +The end goal is like any of labs. There’s a secret .pass file in the privileged +project1 account, and we would like you to extract it. + +Good luck. diff --git a/src/project1/tw33tchainz b/src/project1/tw33tchainz new file mode 100755 index 0000000..0d829e7 Binary files /dev/null and b/src/project1/tw33tchainz differ diff --git a/src/project2/CMakeLists.txt b/src/project2/CMakeLists.txt new file mode 100644 index 0000000..2e3630a --- /dev/null +++ b/src/project2/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.8) + +# These are the files we want to give students +install(FILES rpisec_nuke GENERAL_CROWELL.key GENERAL_DOOM.key GENERAL_HOTZ.key README DESTINATION "${RELEASE_DIR}/project2") diff --git a/src/project2/GENERAL_CROWELL.key b/src/project2/GENERAL_CROWELL.key new file mode 100644 index 0000000..0b4d4a8 --- /dev/null +++ b/src/project2/GENERAL_CROWELL.key @@ -0,0 +1 @@ +4E96E75BD2912E31F3234F6828A4A897 diff --git a/src/project2/GENERAL_DOOM.key b/src/project2/GENERAL_DOOM.key new file mode 100644 index 0000000..efa8ea2 --- /dev/null +++ b/src/project2/GENERAL_DOOM.key @@ -0,0 +1 @@ +90357303412EF822CD10E798760491A6 diff --git a/src/project2/GENERAL_HOTZ.key b/src/project2/GENERAL_HOTZ.key new file mode 100644 index 0000000..0fe347d --- /dev/null +++ b/src/project2/GENERAL_HOTZ.key @@ -0,0 +1 @@ +D3E60C90579EEE92EFD46898A911B0AF diff --git a/src/project2/README b/src/project2/README new file mode 100644 index 0000000..19e2d86 --- /dev/null +++ b/src/project2/README @@ -0,0 +1,7 @@ +There are a few different stages to this project. There is no source, so you +will be required to do some reversing. Using IDA is HIGHLY advised. + +Ultimately, this is an exploitation challenge. There is a .pass file, and you +are expected to get a shell as with the labs or last project. + +The service is running on port 31337 diff --git a/src/project2/rpisec_nuke b/src/project2/rpisec_nuke new file mode 100755 index 0000000..e5eb371 Binary files /dev/null and b/src/project2/rpisec_nuke differ