+++ title = "Reverse engineering di un lettore di presenze" summary = "Step 1: incominciare a capire come funziona il tutto" date = "2024-04-28" tags = ["Reverse Engineering", "Lettore di Presenze", "Decompilazione", "Codemerx"] categories = ["Progetti"] series = ["Lettore di presenze"] series_order = 1 +++ Uno dei motivi per cui ho creato questo blog è per condividere le mie esperienze con altri pazzi entusiasti che adorano questo tipo di contenuti di nicchia come me. In questa serie di articoli andrò a spiegare come ho eseguito il reverse engineering del protocollo di comunicazione usato tra un lettore di presenze ed il suo client (ovviamente creato solo per Windows) ed andremo a creare un client alternativo con [Rust](https://rust-lang.org/) e [Tauri](https://tauri.app/) per rimpiazzare quello proprietario. ![L'R701 di I.P.S. Informatica](images/01-r701.png "Ecco il lettore di presenze che andremo a reverse-enginerizzare") ## Un po' di background Mio padre ha voluto aggiornare il vecchio lettore di presenze per la sua attività: è volato su Amazon e ha comprato l'[R701](https://ipsattendant.it/rilevatore-presenze-r701/) di [I.P.S. Informatica](https://ipsinformatica.info/). A differenza del vecchio lettore, con questo i dipendenti possono registrare la loro presenza tramite PIN, impronta digitale o tramite un badge RFID, poi le registrazioni possono essere scaricate tramite il client ufficiale per Windows o tramite una chiavetta USB. ![Il vecchio lettore di presenze](images/02-old-clock.png "Il vecchio lettore di presenze assomigliava a questo") Il problema è che il client, oltre ad essere installabile solo su Windows e richiedere un'account per eseguire azioni offline, non risponde ai requisiti dell'azienda. Sarebbe gradito che ogni mese venisse fatto un report per ogni dipendente, con una tabella che permetta di vedere le ore lavorate ogni giorno. Invece il software ufficiale permette di scaricare solo una lista di presenze, senza alcun tipo di divisione per mese o per dipendente, e non permette di esportare il tutto in un file `.ods`. Così, in pura modalità "[Stallman quando la nuova stampante Xerox si inceppa](https://oreilly.com/openbook/freedom/ch01.html)", ho deciso che la soluzione migliore è riscrivere il tutto in modo *open-source*. ## Dump delle registrazioni tramite USB Come prima cosa ho provato a scaricare le registrazioni tramite una chiavetta USB, dato che questo metodo non necessita di un PC Windows. Così ho formattato una chiavetta in FAT32 e, dopo aver creato un utente di test e aver creato qualche registrazione, ho scaricato i dati sul mio laptop. Una volta aperto il contenuto della chiavetta ho notato che il lettore ha creato due file: * `~tmp.tmp`: che contiene la stringa `usb test!!` ripetuta 384 volte; * `AGLog_001.txt`: che contiene le registrazioni. Credo che il file `~tmp.tmp` venga usato dal registratore solo per vedere se la chiavetta USB è scrivibile, quindi possoiamo ignorarlo. Aprendo il file `AGLog_001.txt` possiamo andare ad intuire i vari campi che il lettore si salva in memoria: ```csv No Mchn EnNo Name Mode IOMd DateTime 000001 1 000000001 test 34 0 2024/04/28 16:04:23 000002 1 000000001 test 33 1 2024/04/28 16:05:28 000003 1 000000001 test 35 2 2024/04/28 16:08:49 000004 1 000000001 test 35 3 2024/04/28 16:09:01 ``` * `No` è l'ID della registrazione * `Mchn` è l'ID del registratore * `EnNo` è l'ID del dipendente che ha effettuato la registrazione (**En**ployee**No**mber ?) * `Name` è il nome del dipendente * `Mode` è la modalità con coi il dipendente ha registrato la presenza: * `33` è tramite l'impronta digitale * `34` è usando il PIN * `35` è con il badge * `IOMd` è il campo che simboleggia l'ingresso o l'uscita del dipendente (**I**n/**O**ut **M**o**d**e ?): * `0` è il primo ingresso * `1` è la prima uscita * `2` è il secondo ingresso * `3` è la seconda uscita * `Datetime` è la data e l'ora della registrazione Considerando che ho registrato le presenze passando per tutte le modalità di ingresso e di uscita in ordine e che ho usato il PIN la prima volta, l'impronta digitale la seconda ed il badge le ultime due, possiamo ritenerci soddisfatti del risultato. Potremmo addirittura scrivere un programma in Python che usi la libreria [csv](https://docs.python.org/3/library/csv.html) per estrarre i dati che ci servono da questo file. Ma questo non sarebbe così interessante da essere un post sul mio blog. Non voglio entrare nel menù di amministrazione del dispositivo per poi premere in ordine i tasti `2`, `1` e `2` per fare il dump, poi prendere il file risultante e filtrarlo con uno script Python senza interfaccia grafica. Voglio creare un programma che funzioni nativamente su Windows e Linux e che mi permetta di scaricare tutti i dati che mi interessano con un singolo click, già formattati correttamente. Prima di tirare fuori [Wireshark](https://wireshark.org/) e provare a sniffare dei pacchetti però, voglio provare un'altra tecnica... ## Decompilare il client closed-source Come disse una volta [un saggio](https://twitter.com/DebugPrivilege/status/1531661046238388226): "Tutto il codice è *open-source* se sai leggere Assembly". Dato che la compagnia che ha scritto il codice è italiana e che il client funziona solo su Windows, c'è un alta probabilità che il codice sia stato scritto in C# su piattaforma .NET. Se questo è il caso, dovrebbe essere abbastanza semplice ottenere il codice sorgente tramite un decompilatore come [CodemerxDecompile](https://decompiler.codemerx.com/). Quindi ho creato una macchina virtuale con [Windows 10 AME](https://archive.org/details/windows10-ame-21h1-2021-08-09/) e ho installato il client ufficiale alla [versione 04.03.02](https://ipsattendant.it/download-programmi-e-manuali/). {{< carousel images="images/03-official-client-installation/*" aspectRatio="16-9" interval="1000" >}} Una volta installato il client ufficiale ho copiato la directory `C:\Program Files (x86)\ipsAttendant` sulla mia macchina Linux e l'ho aperta con CodemerxDecompile. Come avevo previsto il codice è scritto in C#, quindi è facilmente leggibile. ![CodemerxDecompile](images/04-codemerx-decompile.png "Il codice dell'eseguibile aperto con CodemerxDecompile") Cercando di qua e di là ho scoperto l'amara verità: dentro al file `Dichiarazioni.cs` sono presenti molti metodi interessanti, come `FK_ConnectNet()`. Questi metodi però sono tutti import da una libreria chiamata `FKAttend.dll`. Cercando sul web, sembra che questa libreria sia in giro da molti anni e dubito altamente che l'abbia scritta la compagnia del lettore. Ho trovato anche [la documentazione ufficiale del DLL](), ma nient'altro. Dato che decompilare una libreria che manco il creatore ha avuto voglia di implementare da se non è una cosa che sono disposto a fare, nel prossimo articolo proveremo a fare il reverse engineering della comunicazione che avviene tra client e dispositivo.