Log in

View Full Version : Sentinel spro dongle protection


ComanderKeen
June 13th, 2002, 09:14
There is local software named KardiLab that is protected by sentinel spro dongle. It has two versions, KardiLab 8 and 10. I dumped both dongles memories with sprodump and found that contents of the memories of two dongles exactly same except the serials (Cell 00). But its not possible to run one of them with the others dongle. Anybody knows any protection API uses the serial of a sentinel dongle or it’s some kind of new trick. Anyway I’ll appreciate if someone shares his opinions with me about this subject.

Greetings to CrackZ, Goatass and CyberHeg ( I learned everything from you)…and reversers all around the world.

P.S: Sorry for my un-advanced EnglishJ

cyberheg
June 13th, 2002, 16:29
You can do lots of tricks with the serial. If you read the manual I am sure it says somewhere that if a developer orders a series of dongles the serial number will be incremented one by one for each dongle. In past I bought a developer SDK where the dongle had the serial number 0x0001. The dongle then broke after some time and the serial of the new dongle became 0x0002. Knowing this fact is useful because it can allow developers to "mark" dongles for a specific program or version. Lets say the developers of your target ordered 1000 dongles for the first version and then later again 1000 new ones for the 2nd version. It's easy then to do a check if your dongle is in the first or the 2nd range.

Of other types of checks it's possible ofcourse to tie the serial to a real serial number which must be inputted by the user.

Also you can use it as a dongle specific encryption. I only saw that once though (it was with a Hasp dongle though) where the program used the dongle serial as a decryption key for the dongle memory.

A specific dongle can ofcourse also be blacklisted easily because if it's serial aswell.

Regarding your target I can't say more unless you post more details.

CrackZ
June 14th, 2002, 00:53
Hiya,

Check if both dumps have the same Developer ID (cell 1), if they do then you should safely be able to unplug 1 of them (might save you some confusion).

The only way a developer can read the dongle s/n (if that is the basis of the protection) is via one of the spro(Read) API's (2 of them), find those, and breakpoint them, then just follow back the s/n and see how its used.

I have to confess I think it really unlikely any developer would just distinguish by just dongle s/n, however, if they have Cyberheg's theory sounds pretty likely, probably just a range of s/n's per version.

Regards (let me know if you can make available the target and/or dumps) and I'll probably be able to help more.

CrackZ.

VoxQuietis
June 20th, 2002, 09:12
Hi Crackz,

I think you never saw an actual Superpro based hostid implemenation of Flexlm. They are doing exactly that: they have a DevId (or a small range of it, dont know) and they use the DevId and the dongles serial as Flexid=7-xxxxxxxx.

I even think, that this is quite OK, since Flexlm's biggest advantage is its flexibility and not the security. I.e. You never would start patching the Flexlm-stuff to overcome the dongle based hostid (You'd rather go ahead with Hostid=Any .

On the other hand, I saw an (expensive) VHDL-synthesis tool, which uses Flexlm and incorporates a small query table into its licensing mechanism. While the standard Flexlm implementation had been successfully attacked by a group called SLT, the dongle based portion of the protections doesn't seem to be compromised for the public (leeching) audience. (but be shure, that it's hacked, anyway :-P )

Regards,
- Vox.

ComanderKeen
June 20th, 2002, 09:26
Since the time I sent about the post to the forum I had the chance to check the contents of two new dongles, which belongs two other versions (version 9 and 12). I checked the Dev. ID’s (Cell 01) and they are exactly same with preceding dongles. And serials of dongles seem from the same serie.(4004 /4B04 /4A04/3504). I opened the .exe file with IDA and applied Killer_3K’s flirt signature. Dev. ID isn’t pushed directly (which something new for me) and check the calls for sproRead and sproQuerry APIs, found something interesting. Is it something I thought? A call for the Cell 00 (serial number of the dongle)?


00C6AFD0 sub esp, 4
00C6AFD3 test byte ptr ds:dword_C6891C, 70h
00C6AFDA mov [esp+4+var_2], 0
00C6AFE1 jz short loc_C6B017
00C6AFE3 lea eax, [esp+4+var_2]
00C6AFE7 push eax ; store address?
00C6AFE8 push 0 : cell to read?
00C6AFEA push 0C5FCC8h acket record?
00C6AFEF call sproRead
00C6AFF4 test ax, ax
00C6AFF7 jnz loc_C6B0E7
00C6AFFD mov cx, ds:word_C600D0
00C6B004 cmp [esp+4+var_2], cx
00C6B009 jz loc_C6B0E7
00C6B00F mov ax, 3
00C6B013 add esp, 4
00C6B016 retn

00C6B0A7 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
00C6B0A7
00C6B0A7 loc_C6B0A7: ; CODE XREF: sub_C6AFD0+69 j
00C6B0A7 push 4
00C6B0A9 mov ds:dword_C5FC60, eax
00C6B0AE mov ds:dword_C5FC64, 0
00C6B0B8 push 0
00C6B0BA push 0C5FC64h
00C6B0BF push 0C5FC60h
00C6B0C4 push 0 ; Algorithm starting point?
00C6B0C6 push 0C5FCC8h : packet record?
00C6B0CB call sproQuery
00C6B0D0 test ax, ax
00C6B0D3 jnz short loc_C6B0E7
00C6B0D5 mov ecx, ds:dword_C5FC64
00C6B0DB cmp ecx, ds:dword_C6891C
00C6B0E1 jz short loc_C6B0E7
00C6B0E3 mov ax, 3
00C6B0E7
00C6B0E7 loc_C6B0E7: ; CODE XREF: sub_C6AFD0+27 j
00C6B0E7 ; sub_C6AFD0+39 j ...
00C6B0E7 add esp, 4
00C6B0EA retn
00C6B0EA sub_C6AFD0 endp
00C6B0EA

and I have another question about sproRead, you can see that the cell to read is pushed in eax at line 00C6B962, two lines before the byte from offset 00C5E00C moved (movzx) to eax. If the content of offset 00C5E00C is;

00C5E00C byte_C5E00C db 0A2h ; DATA XREF: _

which byte does it move into the eax? Is eax 0002 or 000A? Same trick is used in pushing the Dev ID before sproFindFirstUnit.

00C6B94C cmp ds:byte_C5E00C, 0FFh
00C6B953 jz short loc_C6B982
00C6B955 movzx ax, ds:byte_C5E00C
00C6B95D push 0C600CCh
00C6B962 push eax ;Cell to read?
00C6B963 push 0C5FCC8h
00C6B968 call sproRead
00C6B96D test ax, ax
00C6B970 jnz loc_C6BA39
00C6B976 xor eax, eax
00C6B978 mov ax, ds:word_C600CC
00C6B97E mov [esp+24h], eax


I thank everybody for being patient while reading my post. Special thanks to CrackZ and CyberHeg for useful advices.

cyberheg
June 20th, 2002, 10:53
About your movzx query I see a problem here.
The line you specified:

movzx ax, ds:byte_C5E00C

is actually the same as:

mov ax, 0 ; clear only 16 lower bits of eax
mov al, 0a2h

So from what you wrote eax will contain: ????00a2

Now the problem is that the cell to read is out of range but maybe thats how it should be? Maybe it's intended to be a fake check to make the dongle return values other then "good". This would actually be a simple but effective way to clear away non thinking crackers who allways believe dongles should be working in one way.

Another thing is your query. You notice that the cell to query on is 0. This is another fake check where you need to use the manual. From the manual it says that only userwritable cells can be used for queries. These start from +8 so 0 is ofcourse a restricted cell. I can't remember if the following was specified in the manual or it was because of my own tests but in sentinel shell (automatic protector) I wrote in a essay once about the same thing since it also uses this kind of check.
A query algorithm is 2 cells hence a DWORD long. These cells will in this case be 0 (serial) and 1 (developer id). If you do a query on these you get the same response back as you sent to the dongle as your query string. Now it should be easy to emulate since you just need to copy the query string to the response position.

Are you sure this is not sentinel shell btw? Both checks read on cell 0 and query on shell 0 were/are used by this protector.

Hopefully this helps.

goatass
June 20th, 2002, 14:26
After the sproRead call you see this:

00C6AFFD mov cx, ds:word_C600D0
00C6B004 cmp [esp+4+var_2], cx
00C6B009 jz loc_C6B0E7

what is it comparing the return value to?

Similarly with the sproQuery:

00C6B0D5 mov ecx, ds:dword_C5FC64
00C6B0DB cmp ecx, ds:dword_C6891C
00C6B0E1 jz short loc_C6B0E7

maybe can give you a better idea as to what you should expect in the return value.

goatass