A few months ago, the OS/2 Museum obtained a seemingly complete and error-free set of floppies with SFT NetWare 286 Level II version 2.0a. And just recently, a disk set of Advanced NetWare 86 2.0a turned up, though sadly incomplete.
Both releases are from 1986 and share one rather unpleasant feature: The NetWare OS won’t run without a hardware key card:
All or most old NetWare versions sold before circa 1988 needed a custom hardware key which had to match the serial number that was burned into the NetWare disks. I’m not sure what the exact history was, but it is known that the NetWare serial number could be provided by Novell’s DCB, or Disk Coprocessor Board:
I don’t quite understand what was the point of selling a custom disk controller and requiring a serial number match. But NetWare 2.0a could also run on off the shelf hardware using standard AT disk controllers and drives. For those machines, Novell provided a simple key card:
I’m not entirely sure if Novell was more worried about piracy by end users or by unscrupulous resellers. In any case, in 1986, during the era of NetWare 2.0a, a hardware key was required by NetWare.
Needless to say, if you are incredibly lucky and find a complete NetWare 2.0a disk set, and the disks are actually readable, the chances of also having the matching hardware key are close to nil. And even if you did have one, that does not at all help when trying to run NetWare 2.0a in an emulator. So, what do we do?
There are two obvious approaches. Either emulating the key card hardware, or patching the software to not need a key card.
Emulating a NetWare Key Card
First let’s examine the overall logic. NetWare 2.0a uses a 6-byte serial number which is different on every disk. It’s written into an object file NET$OS.OBJ, from where it propagates into the final NetWare executable, NET$OS.EXE.
The first four bytes are the serial number proper, stored in BCD format (eight digits). The first two digits tend to be zeros and may be left out on serial number stickers and such. The last two bytes are an “Application Number” which possibly controls NetWare capabilities such as the number of users supported.
When NetWare starts up, it reads six bytes of data from the key card. These six bytes have to match the serial and application number stored in NET$OS.OBJ.
The key card hardware is quite simple. It responds to I/O port reads in a fixed range from 23Ah to 23Fh. For reasons that may be lost to history, the serial number is stored in a strange format–possibly obfuscated, possibly somewhat scrambled for technical reasons.
Ports 23Ch to 23Fh return the serial number proper, while ports 23Ah and 23Bh provide the application number. Looking at the key card photo, it is possible that Novell had prototype boards where part of the serial number and/or application number could be set using jumpers.
This is how the serial number nibbles are returned by the key card. Note that all values must be bit-flipped after they are read from the card:
port 23Ch: [ S2L : S1L ] port 23Dh: [ S0H : S3L ] port 23Eh: [ S0L : S3H ] port 23Fh: [ S1H : S2H ] port 23Ah: [ S5H : S4H ] port 23Bh: [ S5L : S4L ] S0 to S5: Six bytes of serial number H = high nibble, L = low nibble All values bitwise complemented
There is really not much to it, and emulating such hardware is trivial. But it is still almost as annoying as the real key card: You must actually have the emulation, and it can unlock only a single copy of NetWare. That is quite annoying when experimenting, such as trying to figure out whether NetWare 86 2.0a 86 and NetWare 286 2.0a SFT II understand the same on-disk format (they don’t).
The only real advantage an emulated key card has is that it can run unmodified NetWare.
Fixing the Software
The other approach is to forget about the key card hardware entirely and patching out the hardware key checks instead.
I decided to go with a somewhat complicated but safe approach. Rather than patching out the serial number checks, I replaced the routine which reads the serial number from the key card. The replacement copies the serial number to the same location where the original routine placed it. That way, if NetWare in any way depended on the contents of the bytes holding the hardware serial number, it would still work fine (though I suspect it doesn’t care).
As it turns out, it’s not hard to find the serial number burned into NET$OS.OBJ / NET$OS.EXE, because it’s prefixed by a convenient ‘S/N=’ string. The existing serial number is read and copied to the end of the replacement routine, which moves it exactly where the routine reading the key card is expected to place it. Fortunately the replacement code is much smaller than the original, because it doesn’t have to bother bit-flipping and swapping all the nibbles around.
The patching logic is implemented in a Python script. This script requires Python 3. Everything is in there, including comments.
The patcher can be run against the NET$OS.EXE file. But not only that. There is a high likelihood that it can patch NET$OS.OBJ as well—as long as the original serial number and key card reading routines are each stored in a single LEDATA record, which is somewhere between highly likely and guaranteed.
Obviously if NET$OS.OBJ is patched, then a newly generated NET$OS.EXE won’t need any further treatment. The patching logic even makes sure that the checksum of the modified LEDATA record still matches, although the Novell linker does not appear to be at all concerned if it does not.
Rather conveniently, the patcher can also be used directly on raw floppy images containing NET$OS.OBJ or NET$OS.EXE. There is a slight chance that the patching might fail if the files were fragmented (i.e. if the crucial byte sequences were stored in non-consecutive sectors). This is extremely unlikely to happen with the original NetWare disks.
Applying the patch to the GENOS-3 disk of SFT NetWare 286 II 2.0a, which holds the generated NET$OS.EXE, we end up with the following:

From 1986 to 2024, NetWare 2.0a lives!
The patching script has obviously not received a lot of testing because there just aren’t that many copies of NetWare 2.0a available.
For reference, the above screenshot shows the System Configuration (SYSCON) utility running on a client system. It is a convenient method of displaying the server’s serial number as well as the application number.
Reinventing the Wheel
Needless to say, this has been done before. And not only has it been done—in the mid-1980s, a company called NetWork Business Systems out of Houston, Texas was proudly selling a tool called KeyCard Eliminator for $99. That was not cheap, but it was a lot cheaper than NetWare licenses, which cost more than a thousand dollars.
But finding these old cracking tools isn’t any easier than finding NetWare 2.0a… so I wrote my own. Problem solved.

























