There are a few items that we want to store on disk (basically things that aren't state related).
The Dongle Serial
The Manufacturer Serial
The Vendor ID
The Dongle Password
The 200 byte internal flash memory (of which the last 4 is the algorithm)
In addition, if we're going the rainbow table route, we need a way to store keys for different
algorithms selected. We *MIGHT* want to support changing the algorithm on the fly in a program (I know that if I was using this dongle to protect a program, that's DEFINITELY one thing I would think of ;) ).
As a result, we need a structure to quickly read the keys from a file to memory... a num_keys value is probably in order for that.
Then, some kind of structure that would be like:
Algorithm used (basically copied from the last 4 bytes of the internal flash memory)
DogBytes - number of bytes in the buffer
DogRequest - The unencrypted payload (1-63/4 bytes)
So that will be our format for... let's call it doge.key -a quick little C program can init a file like this for us:
***WOW MUCH SECURITY... VERY MICRODOGE... SUCH HACK***
Anyway, I basically set everything to null - yes, you could just create a 224 byte null file.
[Extending The API]
So, I think that I would just be pleased as punch if the API we wrote (are writing) would support adding rainbow table entries on the fly, in addition to writing the vendor_id, mfg_serial, dog_serial, and maybe printing out this lovely data for us to see.
opcode: 0x539 - 1337 ;)
unsigned long RTAdd()
Reads: DogData, DogBytes, DogPassword
Return Value - 0 if successful, 13371337 if not.
Desc: Basically, this is like DogConvert except we're going to pass what we want the dog response to be as DogPassword. In the driver, we will read the last 4 bytes of the flash memory to determine the algorithm, create a new rainbow table entry, and store it in our dog.key file.
We'll also add 1338:
unsigned long SetDogSerial()
Return Value: 0 if successful, 13381338 if not.
Desc: Sets the Dog_Serial value to the int stored in DogData.
unsigned long SetMgfSerial()
Return Value: 0 if successful, 13391339 if not.
Desc: Sets the Mfg_Serial value to the int stored in DogData.
unsigned long SetVendorID()
Return Value: 0 if successful, 13401340 if not.
Desc: Sets the Dongle VendorID value to the 8 byte buffer stored in DogData.
aaaand 1341 to be safe:
unsigned long ReloadRainbowTable()
Return Value: 0 if successful, 13411341 if not.
Desc: Sends a signal to the emu to reload the rainbow table from disk.
Of course, this means we'll have to also create our own request packet... no big deal :D
In the end, our additions look like this (notice that I'm calling LinuxUsbDriverEntry directly ^^)
Next, we'll focus on refactoring the emulator:
So, there's quite a bit going on here... I'm going to paraphrase what's going on.
Basically, we're still using the hook methodology, but we're made things a little more sophisticated - we're reading in a binary file (doge.key) on initialization to populate a data structure (Dog) in memory with key metadata what would be accessible during any kind of transaction. We then go on to read the binary file - pulling keys out of each subsequent 76 byte sequence containing the algorithm the key was generated under (so we can maintain algorithm switching functionality of the dongle), the response, the size of the response, and the actual request data itself.
The control flow is pretty basic - we hook our dongle call, decrypt the packet, find out what it wants, and construct a response in kind, encrypt it, and write it back to the program.
The switch statement in the function controls every call to the imaginary driver. Running a test program with a simple convert shows that our added keys are indeed working in the new version:
The test application itself is nothing more than an original C program where we test the dongle's functionality (compiled against our extended API, of course )
In the end, it's probably easier to make a python program that can seed an initial dongle and generate the appropriate rainbow table values for you - for the sake of brevity, I'm going to leave that as an exercise to the reader..
It reads something that looks like this:
Basically, all the character prefixes for each line tell the script what data is being loaded.
Next time, we'll interface with a real dongle to pull keys, and perhaps introduce MD4.0 as well :)