|
|
|
|
|
|
|
|
|
|
||
|
||
|
|
|
|
The program saves an encrypted license key in our registry file in this entry:
HKEY_LOCAL_MACHINE \SOFTWARE\Raxco\PerfectDisk\3.0\License Key
The license key has an 18h value stored in there
now so that you can run Demo mode. Note what it is because we will be seeing it again
real soon.
After some searching around it looks like the file PDCommon.dll is where the real protection is.
Disassemble it with W32dasm and you will see all kinds of exciting names like:
EncryptLicense
When you click on Help/View License using RegMon you will see that the reg key with the
license key is called so we can fire up SoftIce and start there. We can work our way through the
code to figure out a simple patch to the program so that it accepts the license key that the
Author gave us. We can then dive a little deeper into the code and use our brain to figure
out how to create encrypted license keys that the program will accept.
This program will allow you to see an encryption and
decryption function in action if you have not dealt with them before. Lets go have a closer
look at this protection routine and have some fun.
Exported fn(): ?LoadLicenseRegistryVer@CLicense@@QAEXXZ - Ord:017Bh
DecryptLicense
VerifyChkSumLicense
SetLicenseRegistry
SaveLicense
One way to crack the program is to find where the
important registered owner vs bad guy decisions are made. This will determine where the
patches must be made to make the program function as if you were a registered
owner. The software Author was nice enough to provide well named functions that we can
go directly to. The easiest way to get to the well named functions as shown below and as
found in W32Dasm is to start the program, click on help. In SoftIce, set "bpx
RegQueryValueExa". Press F5 (or CTRL-D), then click on View License. After SI pops up,
press F11 to return to PDCommon.dll. Then "bd 0" (disable the first breakpoint) and set
"bpx 1000F78D". Press F5 (or CTRL-D) and when SoftIce pops up you are at the below code.
:1000F781 55
push ebp
:1000F782 8BEC
mov ebp, esp
:1000F784 83EC08
sub esp, 00000008
:1000F787 894DFC
mov dword ptr [ebp-04], ecx
:1000F78A 8B4DFC
mov ecx, dword ptr [ebp-04]
* Reference To: PDCommon.?Load@CLicense@@QAEHXZ
:1000F78D E8F7010000
call 1000F989
<--Land here.
:1000F792 85C0
test eax, eax
<-- eax=0? (Is license not loaded?)
:1000F794 0F8418010000
je 1000F8B2
<-- jmp to bad place if license not loaded?
:1000F79A 8B45FC
mov eax, dword ptr [ebp-04]
:1000F79D 83C018
add eax, 00000018
:1000F7A0 50
push eax
<-- Second dword of license key
:1000F7A1 8B4DFC
mov ecx, dword ptr [ebp-04]
:1000F7A4 83C114
add ecx, 00000014
:1000F7A7 51
push ecx
<-- First dword of License key
:1000F7A8 8B4DFC
mov ecx, dword ptr [ebp-04]
* Reference To: PDCommon.?Decrypt@CLicense@@AAEXAAK0@Z
:1000F7AB E8E7070000
call 1000FF97
<-- Decrypt first 2 dwords of License key
:1000F7B0 8B55FC
mov edx, dword ptr [ebp-04]
:1000F7B3 83C228
add edx, 00000028
:1000F7B6 52
push edx
<-- Sixth dword of License key
:1000F7B7 8B45FC
mov eax, dword ptr [ebp-04]
:1000F7BA 83C024
add eax, 00000024
:1000F7BD 50
push eax
<-- Fifth dword of License key
:1000F7BE 8B4DFC
mov ecx, dword ptr [ebp-04]
* Reference To: PDCommon.?Decrypt@CLicense@@AAEXAAK0@Z
:1000F7C1 E8D1070000
call 1000FF97
<-- Decrypt last two dwords of License key
:1000F7C6 8B4DFC
mov ecx, dword ptr [ebp-04]
:1000F7C9 83C120
add ecx, 00000020
:1000F7CC 51
push ecx
<-- Fourth dword of License key
:1000F7CD 8B55FC
mov edx, dword ptr [ebp-04]
:1000F7D0 83C21C
add edx, 0000001C
:1000F7D3 52
push edx
<-- Third dword of License key
:1000F7D4 8B4DFC
mov ecx, dword ptr [ebp-04]
* Reference To: PDCommon.?Decrypt@CLicense@@AAEXAAK0@Z
:1000F7D7 E8BB070000
call 1000FF97
<-- Decrypt middle two dwords of License key
:1000F7DC 8B4DFC
mov ecx, dword ptr [ebp-04]
* Reference To: PDCommon.?VerifyChkSum@CLicense@@AAEHXZ
:1000F7DF E8DB080000
call 100100BF
<-- Check chksum of License key
:1000F7E4 85C0
test eax, eax
<-- eax=0? (Chksum is bad?)
:1000F7E6 7536
jne 1000F81E
<-- jmp to good place if chksum is not bad
--------- snip snip --------
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000F7E6(C)
:1000F81E 8B4DFC
mov ecx, dword ptr [ebp-04]
:1000F821 8B5114
mov edx, dword ptr [ecx+14]
<-- edx must be between 08-0F
:1000F824 83E208
and edx, 00000008
<-- for edx^08 to not be zero
:1000F827 85D2
test edx, edx
<-- edx=0?
:1000F829 740C
je 1000F837
<-- jmp to trial time ck if edx=0
:1000F82B 8B45FC
mov eax, dword ptr [ebp-04]
:1000F82E C7401408000000
mov [eax+14], 00000008
<-- mov good flag to [eax+14]
:1000F835 EB7B
jmp 1000F8B2
<-- jmp to registered owner
--------- snip snip --------
If the above code is changed:
FROM:  :1000F7E6 7536
jne 1000F81E
<-- jmp to good place if chksum is not bad
TO: :1000F7E6 EB36
jmp 1000F81E
<-- jmp to good place ALL of the time
then the License checksum will always seem good.
If the above code is changed:
FROM:  :1000F829 740C
je 1000F837
<-- jmp to bad place if edx=0
TO: :1000F829 9090
NOP NOP
<-- ALWAYS pass thru to good place
then the comparison with the decrypted 1st byte ANDed with
08 will always seem good.
Now the software Author was also nice enough to provide
functions to generate our own license key and install the new license key directly into our
registry. What more could we ask for? Why don't we try making our own encrypted license
key. Rather than put all the detail (because this is taking longer than I thought it would),
I can outline the theory and provide some detail. First, we need to figure out what makes
a good license key. There are three things in the case of this license key. The license key
length must be 18h (24d) bytes. The 18h decrypted bytes
of the license key must add up to xFF. This is determined by
tracing into the chksum function located at :1000F7DF CALL 100100BF. The decrypted
license key that the Author provides us with is seen in [eax+14] at 100100CB. We know
that the chksum function needs to return a non-zero value (from above detail). Look at
the last few lines in the chksum function code below:
:10010164 81E2FF000000
and edx, 000000FF
<-- edx=sum license key decrypted bytes
:1001016A 33C0
xor eax, eax
<-- eax=0, this is initial return value
:1001016C 81FAFF000000
cmp edx, 000000FF
<-- is edx=FF? (good guy?)
:10010172 0F94C0
sete al
<-- set al=1 if good guy
:10010175 8BE5
mov esp, ebp
<-- stack maintenance
:10010177 5D
pop ebp
:10010178 C3
ret
If we want EDX to equal FF after EDX is AND with FF, then
EDX needs to be xFF. The third criteria that the license key must meet is that the
first byte of the license key must be a value between 08 and 0F (if it is 01,then demo, 02 is
extended demo, 04 is expired demo). We know this from lines that we
saw before above. That means one of the simpliest license keys could be:
08 00 00 F7 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
The above license key meets the three criteria of being 18h
bytes long, the sum of the bytes is xFF (F7+8+0), and the first byte value is between 08 and 0F.
We have enough information to now encrypt this legal license key. The encryption funtion
is located at 1000FEF1 and is called three times, same as the decryption funtion. Now
we just have to start the program, break in, ensure the stack won't scream bloody murder,
and set up our new license key in memory at the correct location and then run the program.
It will be like falling off a log.
Use the same technique as earlier to break into
PDCommon.dll. Then clear all breakpoints and set "bpx 1000F787", press CTRL-D. Clear the
View License screen, then click View License again. When
Softice breaks, go to the EIP register and type in "1000F8BA", press F10 once. Now this is
the start of the encyption function that is only used during installation, but since we want
to take advantage of this function, SoftIce allows us to setup program execution there.
Press F10 once more to stop on the InsertChkSumToFlags
function. Type "d ecx+14" to show the start of the 18h byte decrypted license key.
To use the simple license key above, insert 08 in memory location 00A6F7BC and
F7 at memory location 00A6F7BF (or any one of the other 17h bytes in the license key).
The other 16h bytes should be zeroed out, but if they are not, go in and zero them.
If you want to see what that key looks like after it is encrypted, set "bpx
1000F910 do "d ecx+14". Otherwise, press CTLR-D and your new license key will be written
to the registry. It should look like the 18h bytes below.
66 F0 C0 58 6A 34 F9 FB
CD 45 72 D7 E7 E0 35 CF
CD 45 72 D7 E7 E0 35 CF
The next exercise would be to rip the encryption and
registry loading code out and use it for a key gen. I will leave that for you.
(Clarification: It is actually the 4th byte that gets
checked for being between 08-0F, not the first byte. The 4th byte gets moved to the first
byte position when it gets checked in the VerifyChkSum@License function after decryption.
I thought that
it might be too confusing to explain all this when generating the encrypted key using the
instructions above because the first and 4th bytes get switched at the InsertChkSumToFlags@License
function just before encryption. Now that you are totally confused ....)
|
|
If you have any comments or questions, start a thread at
The Sandman's site and I will probably see it.
My thanks to The Sandman for his fantastic site, to all the people their who provide help, and to The Snake for providing this html template that I shamelessly used without his consent.