Anyone who spent a bit of time archiving software distributed on floppies probably knows this situation: There’s only one disk set of a given software release known to exist, and it’s not clean. That is, it’s been previously used to install the software and the installer scribbled something on the floppies, like the user’s name or a serial number.
Restoring the disks to a virgin state is desirable, but that’s easier said than done. There are easy cases like the OS/2 installation boot floppy: The installer creates a file named INSTALL.LOG and writes a couple of things to it, but does not modify any existing files. Such behavior is relatively harmless because the additional file can be simply ignored, or all traces of it can be thoroughly erased.
LAN Manager 2.1 and 2.2 is in a different category. The setup program “burns in” the user name, modifying a file on one of the installation disks. That is far more difficult to undo because an existing file’s timestamp is changed and the contents modified. Restoring original content is rather difficult because it’s not at all obvious what it had originally been. Although having just one “clean” set of LAN Manager disks helps.
LAN Manager 2.1 Licensing
In LAN Manager 2.1, Microsoft implemented a new licensing scheme which relied on overwriting a special block of data in the file called SERVICES\NETSVINI.EXE. This is the “root” service without which LAN Manager can not run. The data block serves two purposes: Copy protection and license management.
The copy protection is very lightweight and only consists of “burning in” the user name and installation date into the executable. Licensing is much stricter and limits the number of connections to a server. Microsoft sold 10-user license packs ($995) which increased the server’s capacity; these could be purchased and installed multiple times through the ADDPAK utility. Microsoft also sold unlimited upgrades ($5,495) which removed the connection limit entirely, or rather set it to 1,000 users.
I primarily focused on the user registration in my analysis. When the LAN Manager setup is first run, it asks for the user name and writes it to the NETSVINI.EXE file on the OS/2 Workstation disk. This file is copied to all installed machines. On a subsequent install, setup no longer asks for the user name and just uses the existing information.
The user name is scrambled such that it cannot be easily found in the NETSVINI.EXE file. Modifying it is naturally even harder.
Analyzing the LAN Manager setup utility revealed that Microsoft pulled out the big gun for this—DES encryption. Note that LAN Manager 2.0 already used DES for calculating password hashes and optionally encrypting traffic.
On the OS/2-based server and workstations, DES encryption/decryption API was implemented in a kernel component and accessed through an IOCTL in order to make snooping more difficult. This was of course not available to the setup utility, therefore LAN Manager’s SETUP.EXE has its own DES implementation.
From a modern perspective, the use of DES for encrypting the user name is a waste of time. Why? Because LAN Manager uses a single hardcoded key for it. The use of DES serves only to obfuscate, something which could be achieved through much simpler means. Once you fish out the key out of the SETUP.EXE executable, the user registration data has nowhere to hide.
Well, almost. Even after I had the encrypted data and the key, it still took me quite a while to decrypt it using a standard DES implementation. Although DES is outdated, it is real crypto… which means that if you get a single bit of the key wrong, the result will be complete garbage.
The troublemaker turned out to be the format of the DES key. The standard DES algorithm uses 56-bit keys, but these are usually supplied as a 64-bit key where the low bit of each byte is ignored.
Given how LAN Manager turns passwords more or less directly into DES keys, Microsoft did not want to toss out the low bit of each byte, so that “PasswdB” would not be equivalent to “PasswdC”. Instead, Microsoft packed the DES key into 7 bytes (56 bits); before feeding the key to the DES algorithm, LAN Manager inserts one dummy bit for each 7 bits of the input, thus obtaining a 64-bit key for DES.
What this means is that when the DES key hardcoded in the LAN Manager setup is used with a standard DES implementation, it will produce garbage. It has to be first spaced out and have dummy parity bits inserted. Once that’s done, a standard DES implementation (e.g. the one in the Python Crypto module) works just fine.
Data Structure Details
The above mentioned data structure is stored in NETSVINI.EXE. It has a header with a ‘LMPI’ signature—perhaps that stands for LAN Manager Product Information? The format is roughly as follows:
|74||2||Number of additional licenses|
This structure has at least three users: The SETUP.EXE utility, the ADDPAK.EXE utility, and NETSVINI.EXE itself. As far as I can tell, SETUP only touches the user name and timestamp. ADDPAK updates the additional licenses. NETSVINI uses the product/serial and additional licenses to calculate the licensed connection limit.
The field I named “product/serial” looks about like this: ‘096-045v210-xxxxxxxx’; that is literally ‘xxxxxxxx’. I suspect the original idea was to put the LAN Manager serial number in there, but Microsoft appears to have decided against it and left a sequence of ‘x’ characters in place of the serial number. The middle part (‘045v210’) is significant because it determines the LAN Manager version and the maximum user limit.
If additional licenses are installed through the ADDPAK utility, those will be stored after the encrypted user name and timestamp. The additional licenses do include a complete serial number. That was an inevitable requirement, because otherwise users could install additional 10-user licenses several times. The serial number was a way of preventing that.
Lies and Half-Truths
Microsoft published KB article Q77358 which describes the how Additional User Paks are installed. As far as I can tell, the description might perhaps fit LAN Manager 2.0. It definitely does not apply to LAN Manager 2.1/2.2. I have one LAN Manager 2.1 unlimited user AddPak and it most certainly does not create ADDPAK.SER, but rather installs the additional license into NETSVINI.EXE, as described above.
While I cannot test it, I am almost certain that additional 10-user licenses are installed in exactly the same manner on LAN Manager 2.1/2.2, by modifying NETSVINI.EXE, rather than creating or modifying a separate ADDPAK.SER file.
As an aside, LAN Manager 2.1/2.2 can also be installed as a peer server/workstation. In that case, NETSVINI.EXE is not used, and a separate NETPSINI.EXE (PS for Peer Server) is used instead. NETPSINI.EXE does not include the ‘LMPI’ data block, the installer does not ask for user name, and the connection limit cannot be changed.
Examining Registration Data
I slapped together a simple Python utility which lets one view the registration information in LAN Manager. It looks for the LMPI header and can be used on NETSVINI.EXE or on a (raw) floppy image containing NETSVINI.EXE (which, unlike other files on the installation disks, is not compressed for obvious reasons).
The utility requires the Crypto module. If not already in place, this can be typically installed with ‘pip install pycryptodome’ or equivalent, depending on the host OS.
Here’s an example output from running lmcrypt.py against NETSVINI.EXE from LAN Manager 2.1 and upgraded to unlimited connection through ADDPAK:
LMPI signature found at file offset 0xbef6 Product ID: 096-045v210-xxxxxxxx Registered to: OS/2 Museum Timestamp: 1638040400 (2021-11-27 19:13:20) Number of AddPaks: 1 AddPak serial: 096-244v210-72201277
See the Python source code for details. Note that the implementation is based on guesswork and may be inaccurate. Modifying the registration data is intentionally left as an exercise to the reader.