Keine
Ausgangssituation ist wie in P4 ein simples hackbares Programm via Buffer-Overflow:
#include <stdio.h>
void hack(void);
void read(void);
int main(void){
read();
return 0;
}
void hack(void) { printf("Hacked!\n\r"); }
void read(void){
int test = CAN;
char hackme[2];
printf("IN: ");
gets(hackme);
printf("%s\n\r", hackme);
}
Das Programm kann nun mit dem üblichen Aktionen disassembled werden und "gehackt" werden.
$ echo -e "123456789012345678901234\xad\x05\x40\x00\x00\x00\x00\x00" | ./a.out
Hacked!
Als erstes fügen wir im Daten/Text-Segment eine konstante/globale variable hinzu, die unseren Canary-Wert repräsentiert.
In unserem Fall haben wir die über ein define
die die Variable CAN
mit dem Wert 0x41424344
definiert. (0x41424344
, da es einfach in gdb zu sehen ist).
#include <stdio.h>
#define CAN 0x41424344 // 1094861636
void hack(void);
void read(void);
int main(void){ read(); return 0; }
void hack(void) { printf("Hacked!\n\r"); }
void read(void){
int test = CAN;
char hackme[2];
printf("test %p hackme %p\n", &test, &hackme);
printf("IN: ");
gets(hackme);
printf("%s\n\r", hackme);
}
Als nächstes wird nun direkt vor einem return der Funktion die Überprüfung des Canaries durchgeführt. Für den Fall das der Canary nicht mehr übereinstimmt wird eine entsprechende Fehlermeldung ausgegeben und das Programm sicherheitshalber beendet.
#include <stdio.h>
#define CAN 0x41424344
void hack(void);
void read(void);
int main(void){ read(); return 0; }
void hack(void) { printf("Hacked!\n\r"); }
void read(void){
int test = CAN;
char hackme[2];
printf("test %p hackme %p\n", &test, &hackme);
printf("IN: ");
gets(hackme);
printf("%s\n\r", hackme);
if(test != CAN ){
printf("NO, HACKING PLEASE!\n\r");
exit(0);
}
}
Die Besonderheit hierbei ist, dass nun beim Aufruf des Programmes zusätzlich zu dem Overflow noch der Canary mit überschrieben werden muss, daher ist die Anzahl der übergebenen Parameter länger.
# Getestet kann der Canary-Schutz werden mit Hilfe dieses Aufrufes
$ echo -e "12345678901234567890123\x00\x00\xad\x05\x40\x00\x00\x00\x00\x00" | ./a.out
No, HACKING PLEASE!
# Der Canary kann umgangen werden indem im Buffer-Overflow der entsprechende Canary-Wert wieder gesetzt wird (0x41424344 entspricht DCBA)
$ echo -e "123456781234DCBAxxxxxxxx\xfd\x05\x40\x00\x00\x00\x00\x00" | ./a.out
Das Final Programm befindet sich im Anhang