giovedì 20 dicembre 2018

Emulazione di tastiera ITALIANA per arduino - episodio 1 - Lo Scriptomane



(per i processori ATMEL che supportano USB nativamente)


Buongiorno a tutti!
Questo è il mio primo post su Arduino, spero vi sia utile.
Oggi vedremo come sia possibile emulare una tastiera con Arduino. Inoltre, con un po' di nazionalismo, vedremo come "rientrare" nelle tastiere supportate dalla libreria, dato che la keyboard language localization della libreria integrata nell'arduino IDE è SOLO AMERICANA.

Arduino è grande e mitico

Per prima cosa bisogna dire che Arduino, il progetto open hardware tutto italiano che ha avuto un successo mondiale, permette di prototipare rapidamente progetti di elettronica e costruire… …beh praticamente qualsiasi cosa vogliate (se avete tempo e budget infiniti, ovvio).
Essendo io appassionato di informatica, ovviamente ho cominciato subito a pensare ad interfacciarlo con il PC e dopo un bel po’ ecco la prima applicazione pratica (nel campo della cybersecurity e, nello specifico, nel penetration testing).

La USB Rubber Ducky

Un'altra premessa da fare: la rubber ducky è un famoso (nel campo della cybersecurity) strumento dell’altrettanto famoso (nel medesimo campo) show di YouTube: Hak5.
In sostanza si tratta di un piccolo dispositivo per Keystroke Injection Attacks (debuttati in grande proprio con la sua invenzione): emula una tastiera e comincia a lanciare comandi "alla massima velocità".
L’emulazione di tastiera e/o di altri dispositivi di input “HID” (Human Interface Device) apre le porte a tutta una serie di possibilità circa gli attacchi fisici perpetrabili in regime di penetration testing “red team”.
Come può un computer ritenere dannosi i comandi che il suo stesso utente inserisce dalla tastiera?...

Insomma: un tool spaziale, in particolar modo per chi, come me, si intende di scripting.
VOLEVO AVERLO.

Se non altro per "evangelizzare" i miei utenti e conoscenti circa la buona pratica di bloccare il pc prima di allontanarsene... ... quando si è in ufficio o in un luogo a cui hanno accesso altre persone, ovviamente... Quando siamo a casa in pantofole e andiamo a farci il caffè NON SERVE!

Non siamo paranoici; solo "quasi paranoici". :-)

Ecco, però, c'erano dei “piccoli problemi”:

1 – il costo: la USB Rubber Ducky cost 45 dollari (senza contare l’iva e le tasse doganali di farsi spedire qualcosa dall’america, questione che io ho sperimentato sulla mia pelle, nel 2006 circa, facendomi inviare dei gadget Microsoft riservati ai Microsoft Certified Professionals)

2 – la distanza: al tempo in cui avevo guardato io, nemmeno la spedivano in Italia.



La soluzione

Ho quindi cominciato a pensare come fosse possibile COSTRUIRNE una partendo dal “mio amico” Arduino (e magari molto più economica).
Cercando su internet ho subito cominciato a trovare molto materiale ed ho scoperto di “non essere solo”. Tuttavia mi sono subito scontrato con la prima difficoltà: gli Arduino che avevo in casa non potevano emulare la tastiera.

Con QUALE Arduino è possibile farlo

Eh, si, perché NON TUTTI GLI ARDUINO SONO UGUALI…. Infatti, nelle sue versioni + vendute (UNO e NANO, ad esempio) montano una MCU (la CPU dei microcontrollori) a 8 bit di tipo ATMega 328 che NON SUPPORTA il protocollo USB.
Se vi state domandando come fa Arduino a connettersi con la USB beh, la risposta è davvero semplice: montano, embedded sulla scheda, un convertitore USB/Seriale standard. Questo CHIP permette di tradurre il linguaggio USB per parlare (in seriale) con Arduino.
Alcune MCU della ATMEL (che sono le MCU che “danno vita” ad Arduino), tuttavia, supportano nativamente il protocollo USB ed è quindi possibile programmarle per emulare un dispositivo non appena vengono connesse.

Fantastico!

Sul sito della Microchip (che ha recentemente comprato ATMel), è possibile scaricare una scheda specifiche che consente di capire quali MCU solitamente montate su Arduino supportano USB nativamente.
Se non avete voglia di leggere o non siete curiosi, vi basta sapere che ATMega 32u4 (montato su Arduino Pro Micro) lo supporta.

Un altro problema: la libreria standard è solo US (americana)

Ecco quindi, dopo l’arrivo del tanto atteso pacchetto da Amazon con l’arduino PRO MICRO (che, nella mia versione, monta un ATMega 32u4), che mi sono messo al lavoro per testare per benino la libreria Keyboard.h di Arduino per scoprire… … con sommo orrore che la tastiera emulata è SOLO Americana e che non è supportata ufficialmente la localizzazione.

Il problema di ALT-GR

Fin qui, non ero ancora scoraggiato, perché aprendo il codice sorgente della libreria ho visto che esistevano definizioni di costanti e array di mappatura che potevano essere modificate, quindi… … mi sono messo al lavoro, soprattutto per capire se qualcuno lo avesse già fatto… purtroppo le mie prime ricerche non mi hanno portato lontano ed ho incontrato anche il problema dell’ALT-GR.
Infatti, in Italia, alcuni caratteri speciali ESSENZIALI per gli script (come ad es. le parentesi graffe {} o “curly braces”) richiedono la pressione di più di un tasto modificatore (es ALT-GR + SHIFT + è = “{“ ) e questo non solo non è supportato dalla libreria (e potrete trovare anche un sacco di post e thread in giro che ne parlano e lo asseriscono come se fosse un problema inevitabile), ma NON E’ PROPRIO CONTEMPLATO!
Ero abbattuto, ma non volevo rinunciare… stavo pensando di “sniffare” la USB della mia tastiera per capire la bitmap del segnale che passava mentre premevo alt-gr e altri modificatori, per poi applicare le operazioni BITWISE con le costanti a mano all’interno della libreria…
… ed ecco che il mio amico PAK mi ha tirato fuori dal cilindro la soluzione: NON SOLO qualcuno aveva già fatto il lavoro, ma lo aveva fatto per QUASI TUTTE LE LINGUE! (e a me interessa solo l’italiano… :-) ).

La soluzione ALT-GR e il link dove scaricare tutte le asciimaps

Su Github, quel BENEFATTORE dell’umanità che ha nickname Nurrl, ha persino creato un GENERATORE di librerie modificate per la propria localizzazione di tastiera!
Ora, io non sono un fan delle sovrastrutture, quindi ho aperto il js, ho visto cosa faceva e, in sostanza, ho preso il file della localizzazione ed ho effettuato le stesse operazioni a mano, ricavando la libreria modificata.
Inoltre, dato che avevo ricevuto dal cielo il lavoro più grosso già fatto, mi sono anche preso la briga di modificare il nome ed i metadati della libreria, creandone di fatto una copia che ho chiamato KeyboardIT (senza cambiare il nome delle classi, anche per mantenere impossibile inizializzare 2 lib keyboard nello stesso progetto).

Ed ecco, la allego al post, così che la possiate scaricare ed usare direttamente (va messa la cartella dentro “libraries” nelle sottocartelle del programma Arduino IDE)


Un programma per testare la nostra nuova tastiera

Ecco qui un piccolo programmino che testa i caratteri speciali che si possono fare ed elenca quelli che invece sono, ahimè, per ora, proibiti. Dico per ora perchè magari troverò delle altre soluzioni mirabolanti da "fondere" con questa.. 


#include
void typeKey(int key)
{
  Keyboard.press(key);
  delay(50);
  Keyboard.release(key);
}
/* Init function */
void setup()
{
  // Begining the Keyboard stream
  Keyboard.begin();
  delay(1500);
  Keyboard.press(KEY_LEFT_GUI);
  Keyboard.press('r');
  Keyboard.releaseAll();
  delay(200);
  Keyboard.print("notepad");
  delay(500);
  typeKey(KEY_RETURN);
  delay(750);
  Keyboard.print("SpecialChars");
  typeKey(KEY_RETURN);
  delay(200);
  //Keyboard.print("ALL SPECIAL - {}|\\!\"$%&/()=?'^[]+-_.:,;"); //FUNZIONA CON LA LIBRERIA MODIFICATA
  //èéòçà°ù§ì£5€`~ sono PROIBITI, secondo la libreria
  // £ apre EDGE sulla guida di windows (F1?) e Si disconnette la seriale di Arduino con uno dei caratteri speciali che seguono (RISCHIOSO?). stringa iniziale {}|\\!\"£$%&/()=?'ì^[]+ùàò-_.:,;
  // ` è il CAPS LOCK...
  // ho tolto i caratteri proibiti adesso
  Keyboard.print("ALL SPECIAL - {}|\\!\"$%&/()=?'^[]+-_.:,;"); //OK, SONO TUTTI OK, QUESTI
  typeKey(KEY_RETURN);
  delay(200);
  // Ending stream
  Keyboard.end();
}
/* ######################################################  Keyboard Layouts #########################################
 * http://ascii-table.com/keyboard.php/103P-1  <- inglese="" o:p="" us="">
 * http://ascii-table.com/keyboard.php/142   <- italiana="" o:p="">
*/
/* */
void loop() {}



Conclusioni

Ecco, finalmente anche noi italiani siamo in grado di emulare la tastiera con il nostro arduino.

Happy Scripting e Merry Christmas a tutti!

mercoledì 19 dicembre 2018

Script Batch con parametri nominali

Buongiorno a tutti, eccoci oggi a parlare di un altro argomento di scripting ultra-classico:
i parametri con nome. Pronti?

Vuoi sapere come usare gli slash per assegnare i parametri di un file .bat?


Vuoi sapere come passare parametri/variabili ad uno script senza bisogno di rispettare un ordine preciso?


Vuoi che i tuoi script batch risultino professionali a chi li usa?


Ecco lo script che fa per te. Vediamo insieme:

Come usare i parametri nominali con batch.

In sostanza qui si tratta di permettere di inserire parametri così:

ilmioscript.bat /nomeDir:cartella1 /numFiles:25

invece che così:

ilmioscript.bat cartella1 25

Ma quanto fa più "figo" richiamare uno script nel primo modo? 

E inoltre NON CI SI DEVE RICORDARE LA POSIZIONE DEI PARAMETRI!

La cosa è molto molto semplice in realtà e non so davvero perchè nessuno lo faccia, in giro per il mondo...
.. basta parsare il parametro "%*", che contiene TUTTI I PARAMETRI passati allo script nella command line e quindi "splittare" per slash (" / ") e per due punti (" : "), usando il trick delle variabili con nome dinamico (spiegate in quest'altro mio POST).


Ma bando alle ciance, vediamo come si fa:


@echo off
setlocal enabledelayedExpansion

FOR %%x IN (%*) DO (
    set riga=%%x
    FOR /F "delims=/: tokens=1,2,*" %%a IN ("!riga!") DO (
        set %%a=%%b
        REM echo %%a e' Uguale a %%b ?
    )
)
echo nick=!nick!
echo nome=!nome!
echo cognome=!cognome!
echo.







Come avete visto, passando tutti i parametri (separati da spazio, comportamento di default del ciclo FOR) in %* e poi "splittandoli" con il metodo del "nested for" (come già visto per altro nel mio mitico POST: Come prendere l'output di un comando e impostarlo come variabile), definendo qindi tutto ciò che sta prima dei " : " come NOME della variabile e tutto ciò che sta dopo come VALORE... ecco raggiunto il nostro scopo con pochissimo sforzo...

Da oggi, se dovete parametrizzare qualcosa in batch sono convintissimo che userete questo metodo: è troppo più comodo e bello!


Happy Scripting a tutti e Buone Feste!

martedì 18 dicembre 2018

Variabili con nome dinamico e ARRAY in batch

Buongiorno a tutti, oggi vediamo come utilizzare un trick molto speciale con il nostro amico batch...

... vediamo come "usare variabili con nome variabile" nei nostri script .bat

In inglese si potrebbe ricercare "Dynamic Variable Names in Batch"
ossia "Nomi di variabile dinamici in batch"


Con un po' di impegno vedremo anche come utilizzare una pseudo ARRAY (matrice).
Dico "pseudo" perchè le array non esistono davvero in batch: si tratta di usare un nome particolare di variabile per farlo "sembrare" una array (es: %a[0]%, che si ottiene con: set a[0]=xxx) ed utilizzarlo come tale.


Ci sono almeno un milione di casi in cui questo è utile, ma ne cito qui solo un paio:

  • memorizzare in variabile le risultanze di un comando in un For loop, salvandole in una variabile diversa e indicizzata per numero di ciclo (%a[123]% contiene la risultanza del 123esimo ciclo).
  • richiamare una variabile diversa in base al risultato di un comando o di una operazione, che da come risultato il nome di quella variabile (lo so: sono contorto ma, fidatevi, mi è capitato).



Ma ecco, vediamo come fare, in questo script con alcuni esempi.

@echo off
REM è NECESSARIO usare la DelayedExpansion, sia perchè così possiamo usare sia il punto esclamativo che il percentuale come
REM delimitatori, sia perchè solitamente le variabili con nome dinamico sono all'interno di un loop.
setlocal EnableDelayedExpansion


REM settiamo %a% = alla stringa pippo e poi settiamo la variabile %pippo%
set "a=pippo"
set "pippo=ciao, questo e' un messaggio che verrà richiamato solo se sai il mio nome variabile"

REM quindi, per mezzo di questa bellissima DOPPIA NOTAZIONE con il ! e il %, richiamiamo la variabile %pippo%
echo !%a%!

REM ######################## ESEMPIO 2: ARRAY e FOR LOOP con Dynamic Variable name.

for /L %%c in (1,1,50) DO (
    set array[%%c]=siamo nel ciclo %%c
)
echo !array[25]!
REM come vedete becchiamo ESATTAMENTE la variabile 25.


BENE! spero di avervi solleticato abbastanza con questo tema.
Buone Feste a tutti e, come sempre, Happy Scripting!

lunedì 1 ottobre 2018

Creare utenti in più server VMWare ESXi con uno script Powershell e VMWare PowerCLI

Buongiorno a tutti.
Oggi vi mostrerò come è possibile scriptare la creazione di utenti sugli host ESXi di VMWare utilizzando Powershell e PowerCLI: un modulo molto potente per amministrare la nostra infrastruttura virtuale con Powershell.


Per prima cosa è necessario aver installato la PowerCLI nella nostra powershell… altrimenti questi comandi non funzioneranno…
Vedete quindi l’articolo “Come installare la VMWare PowerCLI in Powershell” e poi tornate qui…

Una volta installata, quando lanciamo la nostra powershell, importiamo il modulo di VMWare PowerCLI:

import-module VMware.PowerCLI


E cominciamo a SCRIPTARE…

$a = "hypervisor1.mydomain.local", "hypervisor2.mydomain.local", "hypervisor3.mydomain.local"
$userN="infranagios"
$strPW="bWtw#N--yERHGy8o"
$strDescr="a simple admin user"
$HOSTCredentials = Get-Credential -Credential root
$a | foreach {
$ESXhost =$_
Connect-VIServer $ESXhost -Credential $HOSTCredentials
New-VMHostAccount -Id $userN -Password $strPW -Description $strDescr -UserAccount -Server $ESXhost
$AuthMgr = Get-View (Get-View ServiceInstance).Content.AuthorizationManager
$Entity = Get-Folder ha-folder-root | Get-View
$Perm = New-Object VMware.Vim.Permission
$Perm.entity = $Entity.MoRef
$Perm.group = $false
$Perm.principal = $userN
$Perm.propagate = $true
$Perm.roleId = "-1"
$AuthMgr.SetEntityPermissions($Entity.MoRef,$Perm)
Disconnect-VIServer $ESXhost
}



Note importanti:

In questa dimostrazione ho deciso di copiare e incollare i comandi direttamente dentro una powershell, tuttavia nulla vi vieta di crearvi un file .ps1 e modificarlo come credete.

Come vedete qui ho fatto la scelta di definire username e password in variabile prima, ma nulla vi vieta di ciclare su un file excel e di creare tutti gli utenti su tutti i server, oppure determinati utenti su determinati server... "fate vobis"... 

Ho anche fatto un video (ho scritto in inglese, per fare un esperimento) che mostra il funzionamento dello script... ve lo "embeddo" !

Ora comentiamo insieme il codice:

1- definisco i parametri validi per tutti i servers:
$a è un elenco di server, separato da virgola, su cui vogliamo creare l’utente.
$userN è lo username che vogliamo creare
$strPW è la password che verrà assegnata all’utente.
$strDescr è la descrizione che comparirà per l’utente.

2 - A questo punto richiedo le credenziali in modo sicuro con get-credentials e le memorizzo in una variabile.

3 - Quindi comincio a ciclare su tutti i servers in elenco e, per ognuno
  • Mi connetto usando le credenziali
  • Creo l’utente con il comando New-VMHostAccount (per ora è un utente senza ruolo)
  • Ottengo l’istanza del servizio di AuthorizationManager
  • Ottengo l'istanza della "Entity" del server (o root folder)
  • Creo un nuovo oggetto permissions e gli assegno il ruolo “-1” (che è quello dell’amministratore), la associo all'utente ed alla entity del server (la root folder).
  • Salvo quindi la permission dentro l’istanza del servizio AuthorizationManager
  • mi disconnetto dal server.
Quest'ultimo passaggio (la disconnessione) è molto importante, altrimenti PowerCLI cercherà di attuare i comandi impartiti su tutti i servers connessi... Tuttavia lo script così come è non potrebbe funzionare, avendo necessità di istanziare determinati oggetti del server che vogliamo gestire. 

Uno alla volta quindi!

Happy Scripting a tutti!


domenica 30 settembre 2018

Come leggere il serial number del computer direttamente da windows

Buongiorno a tutti,
 eccoci qui di nuovo a parlare di scripting e di automazione windows.


Oggi vediamo come sia possibile ottenere il Serial Number, il produttore, il produttore della BIOS, ed altre interessanti informazioni direttamente da windows con un piccolo script, che interpella le proprietà della BIOS con vbscript.

Ecco qui lo script.
const ForWriting = 2

set Dic = createObject("Scripting.dictionary")
Set objFSO = createObject("Scripting.FilesystemObject")
Set oShell = CreateObject("Wscript.Shell")
Set varAmbientali = oShell.Environment("PROCESS")
nomecomputer = varAmbientali("COMPUTERNAME")
fileLog = nomecomputer & "_info.txt"
Set objFileLog = objFSO.OpenTextFile(fileLog, ForWriting, True)

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colBIOS = objWMIService.ExecQuery _
    ("Select * from Win32_BIOS")

   
Set objB = objWMIService.Get("Win32_BIOS").Spawninstance_
   
for each objProp in objB.Properties_
    dim objProp
    Dic.Add objProp.Name, ""
    REM wscript.echo objProp.Name & ": " & " - tipo: " & TypeName(objProp) & "- Array : " & objProp.value
   
   
    REM for each objPP in objProp
        REM For i = 0 to Ubound(objBIOS.BIOSVersion)
            REM wscript.echo ObjB.Properties_(objProp.Name)(i)
        REM next
    REM next
next



REM for each strPName in Dic.Keys
    REM wscript.echo strPName & ": " & objB.Properties_(strPName).Value
REM next
   
For each objBIOS in colBIOS
    for each strPName in Dic.Keys
        REM wscript.echo strPName
        REM strCodeT = "wscript.echo strPName & "" - "" & typeName(objBIOS." & strPName & ")"
        REM execute strCodeT
        strCode = "t = typeName(objBIOS." & strPName & ")"
        executeGlobal strCode
        select case t
            Case "String"
                strCode1 = "objFileLog.WriteLine strPName & "": "" & objBIOS." & strPName
            Case "Boolean"
                strCode1 = "objFileLog.WriteLine strPName & "": "" & objBIOS." & strPName
            Case "Date"
                strCode1 = "objFileLog.WriteLine strPName & "": "" & objBIOS." & strPName
            Case "Int"
                strCode1 = "objFileLog.WriteLine strPName & "": "" & objBIOS." & strPName
            Case "Long"
                strCode1 = "objFileLog.WriteLine strPName & "": "" & objBIOS." & strPName
            Case "Variant()"
                strCode1 = "For i = 0 to Ubound(objBIOS." & strPName & ")" & vbCrLf & "objFileLog.WriteLine strPName & "": "" & objBIOS." & strPName & "(i)" & vbCrLf & "Next"
            Case Else
                strCode1 = "objFileLog.WriteLine strPName & "": "" "
        end select
        executeGlobal strCode1
        REM wscript.echo strPName & ": " & objBIOS.
    next
   
    REM objFileLog.WriteLine "Caption: " & objBIOS.Caption
    REM objFileLog.WriteLine "Build Number: " & objBIOS.BuildNumber
    REM objFileLog.WriteLine "Current Language: " & objBIOS.CurrentLanguage
    REM objFileLog.WriteLine "Installable Languages: " & objBIOS.InstallableLanguages
    REM objFileLog.WriteLine "Manufacturer: " & objBIOS.Manufacturer
    REM objFileLog.WriteLine "Name: " & objBIOS.Name
    REM objFileLog.WriteLine "Caption: " & objBIOS.Caption
    REM objFileLog.WriteLine "Description: " & objBIOS.Description
    REM objFileLog.WriteLine "IdentificationCode: " & objBIOS.IdentificationCode
    REM objFileLog.WriteLine "InstallableLanguages: " & objBIOS.InstallableLanguages
    REM objFileLog.WriteLine "InstallDate: " & objBIOS.InstallDate
    REM objFileLog.WriteLine "Primary BIOS: " & objBIOS.PrimaryBIOS
    REM objFileLog.WriteLine "Release Date: " & objBIOS.ReleaseDate
    REM objFileLog.WriteLine "Serial Number: " & objBIOS.SerialNumber
    REM objFileLog.WriteLine "SMBIOS Version: " & objBIOS.SMBIOSBIOSVersion
    REM objFileLog.WriteLine "SMBIOS Major Version: " & objBIOS.SMBIOSMajorVersion
    REM objFileLog.WriteLine "SMBIOS Minor Version: " & objBIOS.SMBIOSMinorVersion
    REM objFileLog.WriteLine "SMBIOS Present: " & objBIOS.SMBIOSPresent
    REM objFileLog.WriteLine "Status: " & objBIOS.Status
    REM objFileLog.WriteLine "Version: " & objBIOS.Version
    REM For i = 0 to Ubound(objBIOS.BIOSVersion)
        REM objFileLog.WriteLine "BIOS Version: " & _
            REM objBIOS.BIOSVersion(i)
    REM Next
    REM For i = 0 to Ubound(objBIOS.BiosCharacteristics)
        REM objFileLog.WriteLine "BIOS Characteristics: " & _
            REM objBIOS.BiosCharacteristics(i)
    REM Next
   
   
   

Next







In pratica, utilizzando WMI (Windows Management Instrumentation), leggiamo le proprietà possibili della BIOS in un dictionary object e quindi le interroghiamo poi per ogni istanza di BIOS trovata nel sistema (solitamente solo 1 :-) ), a questo punto "componiamo" delle stringhe comando, in base alle casistiche in cui ci troviamo, per rendere leggibile il tutto e poi scriviamo in un file che ha nome del computer.


Happy Scripting!