Pufferüberlaufangriff
-
27-10-2019 - |
Frage
Ich versuche, einen sehr einfachen Pufferüberlaufangriff auszuführen. Ich bin so ziemlich ein Neuling. Also, wenn diese Frage dumm ist, entschuldigen Sie mich bitte :-)
Der Code:
#include<stdio.h>
#include<stdlib.h>
int i, n;
void confused(int i)
{
printf("**Who called me? Why am I here?? *** %x\n ", i);
}
void shell_call(char *c)
{
printf(" ***Now calling \"%s\" shell command *** \n", c);
system(c);
}
void victim_func()
{
int a[4];
printf("Enter n: "); scanf("%d",&n);
printf("~~~~~~~~~~~~~ values and address of n locations ~~~~~~~~~~");
for (i = 0;i <n ;i++)
printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]);
printf("\nEnter %d HEX Values \n", n);
// Buffer Overflow vulnerability HERE!
for (i=0;i<n;i++) scanf("%x",&a[i]);
printf("Done reading junk numbers\n");
}
int main()
{
victim_func();
printf(“\n done”);
return 0;
}
Wenn ich Objdump verwende, um die Funktionadressen zu erhalten, habe ich Folgendes:
main(): 0x804854d
Address of main() where printf() is called: 0x8048563
victim_func(): 0x8048455
confused(): 0x8048414
Ich möchte nun, dass ich zu der Funktion 'Confused ()' von Opfer_func () springen soll, indem ich den Puffer dort überfließt und die Rückgabeadresse an die Adresse von Constused () überschreibt. Und ich möchte von Constrused () zur printf () -Anweisung in Main zurückkehren und normal beenden. Also stelle ich die folgende Eingabe zur Verfügung
Enter n: 7
Enter 7 HEX values:
1
2
3
4
5
8048414 (This is to jump to confused)
8048563 (this is to jump to printf() in main)
Obwohl das Programm aus dieser Printf -Anweisung "erledigt" druckt, springt es zurück zu Opfer_Func () und druckt "Enter n:" zurück.
Was mache ich falsch? Jede Hilfe wäre sehr geschätzt!
PS: Ich bin mir nicht sicher, ob ich die Frage richtig gestellt habe. Bitte lassen Sie es mich wissen, wenn weitere Informationen benötigt werden.
Lösung
Ein Pufferüberlaufangriff ist viel komplexer als dieser. Zunächst müssen Sie Assembler verstehen, um dies auszuführen. Nachdem Sie das Programm und die Funktion, auf die Sie abzielen möchten, abgebaut haben, müssen Sie das Stack -Layout bei der Ausführung dieser Funktion bestimmen. Hier ist ein Beispiel eines Pufferüberlaufs, der Visual Studio verwendet, aber das Prinzip ist das gleiche.
#include "stdafx.h"
#include <math.h>
volatile double test;
double function3()
{
test++;
return exp(test);
}
double function2()
{
return log(test);
}
double function1()
{
int a[5] = {0};
a[7] = (int)&function3;
return exp(function2());
}
int _tmain(int argc, _TCHAR* argv[])
{
double a = function1();
test = a;
return a;
}
Dank der Demontage wissen wir, dass A in Function1 vor dem Speichern der Funktion den Stapelrahmenzeiger zugewiesen wird. Der Wert danach ist die Rückgabeadresse, an die Funktion1 gehen sollte, wenn sie fertig ist.
00401090 55 push ebp <- we save the stack pointer
00401091 8B EC mov ebp,esp
00401093 83 EC 1C sub esp,1Ch <- save space to allocate a[5]
00401096 B8 CC CC CC CC mov eax,0CCCCCCCCh
0040109B 89 45 E4 mov dword ptr [ebp-1Ch],eax <- crt debug init a[5]
0040109E 89 45 E8 mov dword ptr [ebp-18h],eax
004010A1 89 45 EC mov dword ptr [ebp-14h],eax
004010A4 89 45 F0 mov dword ptr [ebp-10h],eax
004010A7 89 45 F4 mov dword ptr [ebp-0Ch],eax
004010AA 89 45 F8 mov dword ptr [ebp-8],eax
004010AD 89 45 FC mov dword ptr [ebp-4],eax
Daraus können wir zu dem Schluss kommen, wenn wir A [7] mit einer anderen Adresse überschreiben, wird die Funktion nicht zu Main zurückkehren, sondern mit jeder Adresse, die wir in einem [7] geschrieben haben.
Hoffe das hilft.
Andere Tipps
Nun, ich möchte nun auf die Funktion 'Confused ()' von Opfer_func () springen, indem ich den Puffer dort überfließt und die Rückgabeadresse an die Adresse von Constused () ...
Auf modernen Linux -Plattformen müssen Sie auch sicherstellen, dass zwei Sicherheitsfunktionen zum Testen ausgeschaltet werden. Erstens in NX-Stacks, und zweitens sind Stack Protectors.
Um NX-Stacks auszuschalten, verwenden Sie -Wl,z,execstack
(im Gegensatz zu -Wl,z,noexecstack
). Um Stapelschutz auszuschalten, verwenden Sie -fno-stack-protector
(im Gegensatz zu -fstack-protector
oder -fstack-protector-all
).
Es gibt einen dritten Schutz, den Sie möglicherweise ausschalten müssen. Dieser Schutz ist Fortify_Source. Fortify_Source verwendet "sicherere" Varianten mit hohen Risikofunktionen wie memcpy
und strcpy
. Der Compiler verwendet die sichereren Varianten, wenn die Zielpuffergröße abgeleitet wird. Wenn die Kopie die Zielpuffergröße überschreiten würde, ruft das Programm auf abort()
. Zum Deaktivieren von Fortify_Source das Programm mit zusammenstellen -U_FORTIFY_SOURCE
oder -D_FORTIFY_SOURCE=0
.
Die Sicherheitsfunktionen werden standardmäßig aktiviert, da in der Vergangenheit so viele Probleme gegeben wurden. Im Allgemeinen ist es eine gute Sache, weil es viele Probleme stoppt (wie die, mit denen Sie experimentieren).
Zunächst scheint es mir, dass Sie die Nummer 5 in Ihrer Beispieleingabe nicht eingeben sollten. Ihr Array wird für einen [4] deklariert. Daher hat Elemente 0-3 indexiert - daher scheint Ihr Angriffeingang für mich falsch zu sein.
Es scheint mir auch, dass Ihr Programm einige Dinge über die Architektur übernimmt:
- Sizof (int) == sizeof (Speicheradresse)
- Die Richtung des Wachstums und des Mechanismus der Umgebungsstapel -Implementierung
Wenn eine dieser Annahmen falsch ist, wird sie nie funktionieren.
Dies scheint eine sehr harte Arbeitsaufgabe zu sein.
Es gibt einfachere Beispiele für Pufferüberlaufangriffe als das Ändern des Steuerflusses des Codes. Zum Beispiel können Sie möglicherweise ein anderes Datenstück überschreiben, das vor dem Benutzer geschützt sein soll (z. B. eine Sicherheitseinstellung)
Sie haben uns nicht die Ausgabe des Programms mit den Adressen eines [i] gezeigt. Ich vermute, dass der Compiler so etwas wie die Ausrichtung der Daten auf dem Stapel auf 16 macht. Es könnte viel weiter bis zur Rückgabeadresse sein, als Sie erwarten.