Powershell a cette capacité de ne lancer que des scripts signés. Mais comment ca marche, et peut t’on valider cela sur un linux. Oui c’est pas le plus simple…
Mais pourquoi pas ! Faisons l’exercice sur le script de test AMSI https://microsoft.github.io/CSS-Exchange/Admin/Test-AMSI/
La signature d’un PS1 est situé a la fin du fichier, et elle est taggée par un # SIG # Begin
A priori le base 64 est un bete format PKCS7 En gros c’est un SAC a trucs.
Etape 1 avec le one liner, on peut extraire les certificats inclus dans ce blob.
$ cat Test-AMSI.ps1 | grep “# Begin signature” -A50000 | grep -v signature | cut -b 3- | dos2unix | base64 -d | openssl pkcs7 -inform der -print_certs > certificates.pem
Etape 2, toujours avec un one liner, on peut extraire la signature du document et on la convertit en fichier certificat standard dans un format PEM (base 64 simple).
On cherche le SHA256 du document… On regarde l’offset , hl header len et l = len et on prend l’octet string de l’object .. ici un SHA256 ( ABCF…. )
$ cat Test-AMSI.ps1 | grep “# Begin signature” -A50000 | grep -v signature | cut -b 3- | dos2unix | base64 -d | openssl pkcs7 -in – -inform der -noout -print | less
Pour simplier notre vie on va découper la signature dans un fichier .. ca nous évitera les oneliner trop long… Sortons cette signature en format binaire dans un fichier sig.bin
$ cat Test-AMSI.ps1 | grep “# Begin signature” -A50000 | grep -v signature | cut -b 3- | dos2unix | base64 -d > sig.bin
Parsons la signature avec asn1parse pour savoir ou extraire le SHA qui nous intéresse. cette vue n’est pas structurée.
$ openssl asn1parse -inform der -in sig.bin | less
Ce qu’on cherche c’est le champ rsaEncryption, aka step 3
On va extraire ce “champ” rsaencryption, On vois qu’il est a l’offset 4021 et qu’il a un entete de 4 bytes et une longeur de 256 bytes. DD fera le taff.
$ dd if=sig.bin of=sig_sha.bin bs=1 skip=$[ 4021 + 4 ] count=256
Ce champ “rsaencryption” est chiffré avec une clef privée qui évidemment n’est pas dans le certificat, mais la clef qui permet sont déchiffrement c’est la clef publique .. et elle , elle est bien dans le certificat.
$ openssl x509 -inform pem -in certificates.pem -noout -text | less
Donc, step 4, du certificat nous allons extraire la clef publique dans un fichier pubkey.pem
$openssl x509 -inform pem -in certificates.pem -noout -pubkey > pubkey.pem
Step 5: Désormais on peut déchiffrer notre blob rsaencryption avec la dite “clef”. Et on sort ca dans un fichier sha_verified.bin
$ openssl rsautl -verify -pubin -inkey pubkey.pem < sig_sha.bin > sha_verified.bin
On peut alors voir la valeur du SHA256 qu’on est supposé obtenir.
$openssl asn1parse -inform der -in sha_verified.bin
Victoire, Et voila c’est finis.. le SHA256 attendu du document est supposé être 027F3C516AEAF1E9B5868265A22F3C07E9D6D8B59B71C894D1E066AE8550BDE5
Et c’est là que ca coince, impossible de génerer ce hash a partir du document….
Si je vire tout les lignes SIG j’obtient 557dd2be05086c4e5e25c316fe9f8a17f2f4816b39963039521872169d9f0fbb
Si quelqu’un sait, pingez moi !… Sinon il va falloir sortir le debugger pour savoir comment le hash du fichier est calculé.