CPS v1.16 - Tutorial

Install files in C:\CPSWIN32 - check you have urlmon.dll
cps116.zip - (1.09Mb).

Greetings once again and welcome to another requested dongle tutorial. In fact CPS v1.16 fits my site well because its using a Sentinel similar to GeoPath Power CAD/CAM, except its linking the 32-bit scw32.dll instead of scw16.dll. Disassembling the main exe will take a while but its certainly worth the wait, a quick sift through the imported functions will give you some code to start looking at.

Venturing into SoftICE, a bpio -h 378 rw will work well, the first break is inside the dongle dll so disable the breakpoint and start pressing F12 to get back to the application side. You'll gain an entry at this code.

:00419082 CALL 0056859B <-- You'll land just after this (RNBOcplusInitialize).
:00419087 MOV WORD PTR [EBP-1C], AX <-- Store AX.
:0041908B MOV EDX, DWORD PTR [EBP-1C] <-- Now place it in EDX.
:0041908E AND EDX, 0000FFFF <-- Polish it.
:00419094 TEST EDX,EDX <-- Check EDX.
:00419096 JZ 004190C5 <-- Might_not_be_a_bad_jump.

This code might not work as your intuition suggests, the JZ looks as if it ought to be bad, but if you follow the code execution you'll see that this leads us to a very quick RET thus skipping both calls to RNBOcplusRead (which we ought to assume the dongle is accessed). Without looking at the API guide for this older Sentinel we are left guessing what RNBOcplusInitialize actually does, we could just trace it and look for telltale signs (e.g. 378 in a register), that would be indicative of parallel port address getting. Lets assume this is good and continue.

:004190C5 MOV WORD PTR [0075F5F4], 0000 <-- Set this flag 0.
:004190E2 XOR EDX,EDX <-- EDX=0 (unnecessary perhaps?).
:004190E4 MOV DX, WORD PTR [0075F5F4] <-- Move flag to DX.
:004190EB CMP EDX, DWORD PTR [EBP-18] <-- Another flag check.
:004190EE JGE 00419159 <-- Jump_and_prepare_to_read_dongle.

This code is interesting, [EBP-18] is the critical flag and is obviously set somewhere by the dongle dll code, every time I've looked its been flagged as 5, almost certainly this is an API error code meaning "dongle not present" or similar, the only probable good value of [EBP-18] is 0, but take note how a call is made to RNBOcplusRead if this doesn't jump, this is merely just a loop to check the dongles presence yet again. We also know that the XOR EDX,EDX and MOV DX code really just sets EDX=0, but that was already the case from the previous snippet so we can use the address space here to set [EBP-18] to 0 as required.

Patch

:004190E4 MOV WORD PTR [EBP-18], 0000 <-- Set memory flag good. (66, C7, 45, E8, 00, 00, 90).

This patch ensures that our dongle always exists and sets [EBP-18] accordingly just in case it is verified later. We move on to the next code snippet.

:00419159 MOV WORD PTR [0075F5F4], 003F <-- Familiar, amount of dongle data to read.
:00419162 PUSH 0075F1E8 <-- Dongle data area.
:00419167 MOV DX, WORD PTR [0075F5F4] <-- Store 3F in DX.
:00419174 CALL 00568595 <-- RNBOcplusRead.
:00419179 MOV WORD PTR [EBP-1C], AX <-- Use AX again for the return code and store it.
:0041917D MOV WORD PTR [0075F5F4], 0005 <-- Store again.
:00419186 XOR EAX,EAX <-- Clear EAX.
:00419188 MOV AX, WORD PTR [0075F1E8] <-- Return from dongle (is FFFF!).
:0041918E XOR ECX,ECX <-- Clear ECX.
:00419190 MOV CX, WORD PTR [0075F5F4] <-- We know this value.
:00419197 XOR EDX,EDX <-- Clear EDX.
:00419199 MOV DX, WORD PTR [EBP+2*ECX-28] <-- DX = good return value (5460h).
:0041919E CMP EAX,EDX <-- Compare.
:004191A0 JZ 004191CC <-- Good_jump_and_set_good_flag_[EBP-40].

This is the main dongle checking routine, when you trace this and see AX returned as FFFF (-1), the word error ought to immediately enter your mind, the good value 5460h is unfortunately left in DX ready for the compare, obviously there are several ways to patch this, the best option is probably changing 00419188 to MOV AX, 5460h and appropriate fillers/NOP's e.g. (66, B8, 60, 54, 40, 48).

Once again with this type of Sentinel we see an inherent weakness, the API structure means that any reverse engineer with some thought can easily work a path through the code. All decent schemes should really use a dongle response to decrypt portions of the loading code and obviously check for the dongles presence more than once. Although I didn't demonstrate how, it should be possible to patch the dll generically, rather than returning FFFF as an error it should be possible to inject code into the dll to retrieve the good return code.


© 1998 CrackZ. 1st November 1998.