Added an article
All checks were successful
Build and Publish / build (push) Successful in 1m31s

This commit is contained in:
Nicola Belluti 2024-04-28 20:58:13 +02:00
parent 8e0fb09492
commit a1ab1c3c6d
16 changed files with 322 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

View File

@ -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](</posts/2024/04/reverse-engineering-an-attendance-clock-part-1/FKAttend User's Manual.pdf>),
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.

View File

@ -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](</posts/2024/04/reverse-engineering-an-attendance-clock-part-1/FKAttend User's Manual.pdf>),
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.