diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/FKAttend User's Manual.pdf b/content/posts/2024/04/reverse-engineering-an-attendance-reader/FKAttend User's Manual.pdf new file mode 100644 index 0000000..9824247 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/FKAttend User's Manual.pdf differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/featured-background.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/featured-background.jpg new file mode 100644 index 0000000..816780f Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/featured-background.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/01-r701.png b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/01-r701.png new file mode 100644 index 0000000..f88453a Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/01-r701.png differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/02-old-clock.png b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/02-old-clock.png new file mode 100644 index 0000000..febd24d Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/02-old-clock.png differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/1.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/1.jpg new file mode 100644 index 0000000..095ada6 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/1.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/2.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/2.jpg new file mode 100644 index 0000000..a57d391 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/2.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/3.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/3.jpg new file mode 100644 index 0000000..ae24b5f Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/3.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/4.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/4.jpg new file mode 100644 index 0000000..422bb5b Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/4.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/5.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/5.jpg new file mode 100644 index 0000000..d8aa235 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/5.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/6.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/6.jpg new file mode 100644 index 0000000..74bf3b2 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/6.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/7.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/7.jpg new file mode 100644 index 0000000..1b02d78 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/7.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/8.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/8.jpg new file mode 100644 index 0000000..29658b5 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/8.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/9.jpg b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/9.jpg new file mode 100644 index 0000000..8ef36ea Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/03-official-client-installation/9.jpg differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/04-codemerx-decompile.png b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/04-codemerx-decompile.png new file mode 100644 index 0000000..6f56a70 Binary files /dev/null and b/content/posts/2024/04/reverse-engineering-an-attendance-reader/images/04-codemerx-decompile.png differ diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/index.it.md b/content/posts/2024/04/reverse-engineering-an-attendance-reader/index.it.md new file mode 100644 index 0000000..4d4fdb6 --- /dev/null +++ b/content/posts/2024/04/reverse-engineering-an-attendance-reader/index.it.md @@ -0,0 +1,164 @@ ++++ +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 +DDL](), +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. diff --git a/content/posts/2024/04/reverse-engineering-an-attendance-reader/index.md b/content/posts/2024/04/reverse-engineering-an-attendance-reader/index.md new file mode 100644 index 0000000..ba3f22d --- /dev/null +++ b/content/posts/2024/04/reverse-engineering-an-attendance-reader/index.md @@ -0,0 +1,158 @@ ++++ +title = "Reverse Engineering of an Attendance Reader" +summary = "Step 1: Beginning to understand how everything works" +date = "2024-04-28" + +tags = ["Reverse Engineering", "Attendance Reader", "Decompilation", "Codemerx"] +categories = ["Projects"] +series = ["Attendance Reader"] +series_order = 1 ++++ + +One of the reasons I created this blog is to share my experiences with other +enthusiastic geeks who love this kind of niche content like me. + +In this series of articles, I will explain to you how I reverse-engineered the +communication protocol used between an attendance reader and its (Windows-only) +client, and we will create an alternative client with +[Rust](https://rust-lang.org/) and [Tauri](https://tauri.app/) to replace the +proprietary one. + +![I.P.S. Informatica's R701](images/01-r701.png "Here's the attendance reader +we're going to reverse-engineer") + +## A bit of background + +My dad wanted to update the old attendance reader for his small business, so he +went straight on Amazon and bought the +[R701](https://ipsattendant.it/rilevatore-presenze-r701/) from [I.P.S. +Informatica](https://ipsinformatica.info/). + +Unlike the old reader, with this one employees can record their presence via +PIN, fingerprint, or RFID badge, then the records can be downloaded through the +official Windows client or via a USB stick. + +![The old attendance reader](images/02-old-clock.png "The old attendance reader +looked something like this") + +The problem is that the client, besides being installable only on Windows and +requiring an account to perform even offline actions, doesn't meet my dad's +requirements. + +It would be appreciated if a report was generated every month for each +employee, with a table showing the hours worked each day. Instead, the official +software only allows you to download a list of presences, without any kind of +division by month or employee, and it doesn't allow exporting everything to a +`.ods` file. + +So, in pure "[Stallman when the new Xerox printer +jams](https://oreilly.com/openbook/freedom/ch01.html)" mode, I decided that the +best solution was to rewrite everything in an open-source way. + +## Dumping the records via USB + +To begin, I tried to download the records using a USB stick, as this method +doesn't require a Windows PC. I formatted a USB stick in FAT32, and after +creating a test user and making a few records, I downloaded the data to my +laptop. + +Once I opened the contents of the USB stick, I noticed that the reader had +created two files: + +* `~tmp.tmp`: which contains the string `usb test!!` repeated 384 times; +* `AGLog_001.txt`: which contains the records. + +I believe that the `~tmp.tmp` file is used by the reader only to check if the +USB stick is writable, so we can ignore it. + +Opening the `AGLog_001.txt` file, we can start to look at the various fields +that the reader stores in memory: + +```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` is the record ID +* `Mchn` is the reader ID +* `EnNo` is the employee ID who made the record (**En**ployee **No**mber?) +* `Name` is the employee's name +* `Mode` is the method by which the employee recorded their presence: + * `33` is via fingerprint + * `34` is using a PIN + * `35` is with the badge +* `IOMd` is the field containing the employee entrance or exit (**I**n/**O**ut + **M**o**d**e ?) + * `0` is the first entrance + * `1` is the first exit + * `2` is the second entrancance + * `3` is the second exit +* `Datetime` is the date and time of the record + +Considering that I recorded the test records by passing through all the +entrance and exit modes in order, using the PIN the first time, the fingerprint +the second time, and the badge the last two times, we can be satisfied with the +result. + +We could even write a Python program using the +[csv](https://docs.python.org/3/library/csv.html) library to extract the data +we need from this file. + +But this wouldn't be interesting enough to be a blog post. I don't want to +enter the device's admin menu, press the `2`, `1`, and `2` keys in order to +make a dump, then take the resulting file and filter it with a Python script +without a graphical interface. + +I want to create a program that runs natively on Windows and Linux and allows +me to download all the data I care about with a single click, in the format I +need. + +Before pulling out [Wireshark](https://wireshark.org/) and trying to sniff some +packets, I want to try another technique... + +## Decompiling the closed-source client + +As [a wise man](https://twitter.com/DebugPrivilege/status/1531661046238388226) +once said, "All source code is open source if you can read Assembly". + +Since the company that wrote the code is Italian and the client only works on +Windows, there's a high chance the code is written in C# on the .NET platform. + +If this is the case, it should be pretty straightforward to get the source code +through a decompiler like +[CodemerxDecompile](https://decompiler.codemerx.com/). + +So I created a virtual machine with [Windows 10 +AME](https://archive.org/details/windows10-ame-21h1-2021-08-09/) and installed +the official client at [version +04.03.02](https://ipsattendant.it/download-programmi-e-manuali/). + +{{< carousel images="images/03-official-client-installation/*" +aspectRatio="16-9" interval="1000" >}} + +Once I installed the official client, I copied the `C:\Program Files +(x86)\ipsAttendant` directory onto my Linux machine and opened it with +CodemerxDecompile. + +As I expected, the code is written in C#, so it's easily readable. + +![CodemerxDecompile](images/04-codemerx-decompile.png "The executable code +opened with CodemerxDecompile") + +Searching here and there, I found out the bitter truth: inside the +`Dichiarazioni.cs` file, there are many interesting methods, such as +`FK_ConnectNet()`. However, these methods are all imports from a library called +`FKAttend.dll`. + +Searching the web, it seems this library has been around for many years, and I +highly doubt the company that made the reader wrote it themselves. I also found +the [official DDL +documentation](), +but nothing else. + +Since decompiling a library that even the creator didn't bother to implement +themselves is not something I'm willing to do, in the next article, we will try +to reverse-engineer the communication between the client and the device.