159 lines
6.4 KiB
Markdown
159 lines
6.4 KiB
Markdown
|
+++
|
||
|
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.
|
||
|
|
||
|

|
||
|
|
||
|
## 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 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.
|
||
|
|
||
|

|
||
|
|
||
|
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.
|