http://www.future-software.co.uk/Products/vld/vld.htm - Webpage (vld126.zip) - (1.45Mb)
Welcome once again. In DigiSHOW we have a dongle protection which is poorly implemented to say the least, however it does offer up many learning opportunities and the chance to forever banish the dk47wn32.dll to the proverbial dustbin. On installation the program copies the relevant driver to your System directory, in my case this is dk47wn95.386, note the old 386 extension here, most decent dongles now use vxd's for their evil communications (at least for Windows 95 anyhow).
Disassembling the file dk47wn32.dll seems the way to go, and looking through the exported functions list should raise a smile (FindDk47, DK47ReadRandomNumbers). Obviously looking inside the main program to see where these functions are imported is wise, you might also like to load these exports into SoftICE with the Symbol Loader. Inside vld.exe we have the following.
:00403649 CALL 00408002 <-- DK47wn32.DK47DriverInstalled.
:0040364E CMP EAX, 00000001 <-- Driver Installed sets EAX=1.
:00403651 JNZ 0040369C <-- No_driver_installed_jump.
:00403653 CALL 00407FFC <-- DK47wn32.FindDK47
:00403658 CMP EAX, 00000001 <-- Is dongle connected.
:0040365B JNZ 0040369C <-- Jump_its_not.
:0040365D LEA EAX, DWORD PTR [ESP+04]
:00403661 PUSH 00000806 <-- This looks like the dongle data.
:00403665 PUSH EAX
:00403667 PUSH 0000003B
:00403669 PUSH 00000006 <-- Push a whole load more parameters.
:0040366B PUSH 0000001E
:0040366D CALL 00407FF6 <-- DK47wn32.DK47ReadRandomNumbers
:00403672 MOV EAX, 00000447 <-- EAX initialised to 447h.
:00403677 XOR ECX, ECX <-- Clean ECX.
:00403679 MOV CL, BYTE PTR [ESP+EAX+04] <-- Dongle return data.
:0040367D ADD ESI, ECX <-- Store result in ESI.
:0040367F INC EAX <-- Increment loop.
:00403680 CMP EAX, 00000806 <-- Is loop done.
:00403685 JL 00403677 <-- Get more data.
:00403687 CMP ESI, 0001FECA <-- Good result.
:0040368D JNZ 0040369C <-- Jump_bad.
:0040368F MOV EAX, 00000001 <-- Good guy flag.
:00403695 ADD ESP, 00000808 <-- Big stack correction for all that dongle data.
This code is fairly easy to understand, unfortunately for the programmer all of the bad jumps are of the form JNZ 0040369C, and as we know that the code passes the first "is driver installed check" its obvious how the other 2 should work. FindDK47 first checks the parallel port to see if our dongle is connected, if it is then we return EAX=1, if its not EAX=0. Our objective now is to patch what we can of the dll generically, note that it would be impossible to patch the dll for all applications seeing as the dongle codes are checked usually on the application side.
At 00403679, CL points to values that must have been obtained from the dongle, each time I've examined the code CL has been FF, suggesting an error, its certainly possible on the application side to improve the efficiency of this code by patching the loop, remembering that the value of EAX needs to be adjusted. Looking inside the disassembly listing of dk47wn32.dll our first task is to ensure that FindDK47 always returns true i.e. there is always a dongle connected. The FindDK47 function is controlled using [EBP-04], it seems that the dll checks for the dongles presence using a 1 returned by the actual dongle. The relevant code is this:
:20001343 CALL KERNEL32.ReleaseSemaphore
:20001349 MOV EAX, DWORD PTR [EBP-04] <-- This needs to be 1.
:2000134C AND EAX, 0000FFFF <-- Check register with logic AND.
I recommend you read up on semaphore objects in any decent system class reference, it might also be worth reading about wait functions. Needless to say you could easily replace the AND EAX, 0000FFFF with an XOR EAX,EAX (33C0) and an INC EAX (40) + appropriate (2) NOP's to ensure that your dongle is always connected. To patch the return codes obtained from the dongle we could settle for simply removing the jump at 0040368D, however I prefer to re-write this entire routine and improve the code efficiency at the same time.
:00403672 MOV EAX, 00000806 (B806080000) <-- As if
loop had finished.
:00403677 XOR ECX, ECX <-- Leave ECX as 0, it doesn't matter.
:00403679 MOV ESI, 0001FECA (BECAFE0100) <-- What ESI should be.
:0040367E INC EAX
:0040367F DEC EAX <-- Better looking than 2 NOP's.
Although I showed you earlier how the dll could be patched, it is probably more appropriate to patch everything in 1 place (i.e. the application), I'll leave that as a small exercise. Those of you who dislike unnecessary files might also like to remove the need for the driver file by patching the result of DK47DriverInstalled. Unusually I'm going to credit the author with some intelligence, he has probably realised that his application is so specialist in nature that the average warezer is unlikely to be cheating him out of significant revenues.
The unfortunate reality of this protection is that there is potentially little the author could do with this particular manufacturers' dongle, the security of the calling dongle routines is the weak link and even if checks were peppered throughout the program an average cracker would easily isolate them.