How to crack M$-Money trial versions 1.00p, 3.00p & 5.0

( by Heres )

- This is my contribution to the 1998 Hcu Strainer -
[You should use Courier New 8 in order to view and print correctly this essay]

M$-Money v1.00p Working Model

Well, as +ORC says, history is important, so let start from version 1.00p of Microsoft Money; I quickly found it on the net. The file to crack is MNYDEMO.EXE (501.664 bytes - 01/jun/1993). Launch the target and notice that the system date must be 1992 in order to run the program. So we want to crack this check routine first. +ORC teaches me to use the dead listing, finding the dialog, but I wait and I think... Maybe there is a quicker way to crack this... The dialog pops up with a beep, a strange beep. Ok... Try to investigate about function user!messagebeep. Fire SoftICE, bpx user!messagebeep and run the target. SoftICE breaks the code before the beep, so strike F12 and you are in MNYDEMO routine. Look before the call, you see 2 conditional jumps (JZ) until previous RETF, but they both jump in the same routine. So take a look to stack. Last 3 entries are: CS-70 : 04FA CS-70 : 2956 CS : 2B80 So bpx CS:2B80 and re-run the target. The call goes directly to previous routine, so look before, but as you can see, no conditional jumps are present. So bpx CS-70h:2956 and re-run... Mmmmh... Good stack fishing! * Referenced by a CALL at Addresses: |:0024.04FA, :0024.0C6D | :0024.2912 1E push ds :0024.2913 58 pop ax :0024.2914 90 nop :0024.2915 45 inc bp :0024.2916 55 push bp :0024.2917 8BEC mov bp, sp :0024.2919 1E push ds :0024.291A 8ED8 mov ds, ax :0024.291C 83EC0A sub sp, 000A :0024.291F 8A267747 mov ah, [4777] :0024.2923 2500FE and ax, FE00 :0024.2926 3D0058 cmp ax, 5800 :0024.2929 7405 je 2930 ; go to Jump A :0024.292B 3D005A cmp ax, 5A00 :0024.292E 7506 jne 2936 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0024.2929(C) | :0024.2930 A17647 mov ax, [4776] :0024.2933 EB3F jmp 2974 ; Jump A :0024.2935 90 nop * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0024.292E(C) | :0024.2936 8D46FA lea ax, [bp-06] :0024.2939 50 push ax :0024.293A 9ADA040000 call 0039.04A6h :0024.293F 8BD8 mov bx, ax :0024.2941 8B07 mov ax, [bx] :0024.2943 8946FC mov [bp-04], ax :0024.2946 8946F8 mov [bp-08], ax :0024.2949 8A46F9 mov al , [bp-07] :0024.294C 24FE and al, FE :0024.294E 3C58 cmp al, 58 :0024.2950 740E je 2960 ; Jump B ***** :0024.2952 B84408 mov ax, 0844 :0024.2955 50 push ax :0024.2956 9A92280000 call 0031.2B62h ; Here the bpx :0024.295B 2BC0 sub ax, ax :0024.295D EB1D jmp 297C Jump A & Jump B are interesting jumps after the call... Try to make work the first... bpx CS:2929 and re-run. Then write e cs:eip and change 74 to EB in the data window. F5 to go on.(Notice that no .ini or .mny files are initially present in Money1 directory). Ok! It seems to work, but take a look at the About item, in Help menu... The expiration date is very strange (01/01/48)... Re-run the program... Mmmmh, a 60days limit message pops up when the data file (.mny) is present... Not a good crack! So try to invert the second jump (Jump B): e cs:eip (from 74 to EB), so strike F5... It works... The expiration date is costantly updated and no nag screens... Start the phase 2 now, re-enable the only bpx at messagebeep and clear other breakpoints. Enter into Future Transaction and insert a date after the 60days period: I tryed with year 2005. SoftICE pops up into messagebeep routine, so strike F12 and watch the stack. See last 3 entries: CS : 2CEC CS+33D0 : 2980 CS : 1AD0 As before, using bpx, you can easily find the conditional jumps and reach the code: * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0058.292C(C) | :0058.2931 837EC600 cmp word ptr [bp-3A], 0000 :0058.2935 7403 je 293A :0058.2937 E96606 jmp 2FA0 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0058.2935(C) | :0058.293A 8B5EC0 mov bx, [bp-40] :0058.293D 8A07 mov al , [bx] :0058.293F 2AE4 sub ah, ah :0058.2941 2BD2 sub dx, dx :0058.2943 52 push dx :0058.2944 50 push ax :0058.2945 9AFFFF0000 call USER.ANSIUPPER :0058.294A A2BC2F mov [2FBC], al :0058.294D E95006 jmp 2FA0 :0058.2950 837E0800 cmp word ptr [bp+08], 0000 :0058.2954 7452 je 29A8 ; Working Jump+ ***** :0058.2956 833E304FFF cmp word ptr [4F30], FFFF :0058.295B 7513 jne 2970 :0058.295D B84708 mov ax, 0847 :0058.2960 50 push ax :0058.2961 9A4D2B0000 call 0031.2B62h * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0058.2988(C), :0058.29A6(U) | :0058.2966 FF760C push word ptr [bp+0C] * Possible Ref to Menu: MAINMENU, Item: "Account Book" | :0058.2969 B80100 mov ax, 0001 :0058.296C E96108 jmp 31D0 :0058.296F 90 nop * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0058.295B(C) | :0058.2970 A1304F mov ax, [4F30] :0058.2973 39067647 cmp [4776], ax :0058.2977 772F ja 29A8 ; Working Jump :0058.2979 B84308 mov ax, 0843 :0058.297C 50 push ax :0058.297D 2BC0 sub ax, ax :0058.297F 50 push ax :0058.2980 9AFFFF0000 call 0031.2CCCh ; Here the bpx You easily can find that the only working jumps are at CS:2954 and at CS:2977, but what is the difference ??? I think it is at CS:2961... Set a bpx at CS:2954 and try, assigning to DS:[4F30] the value of FFFF... Mmmmmh... An interesting message: Only the full product version accepts transactions without dates. Oh,oh... Why do not use this useful feature? ;-D Ok... So the correct crack is at CS:2954, changing 7452 to EB52 (jump always).

M$-Money v3.00p Evaluation version

Start without .mny files nor msmoney.ini file, so follow the previous method, breakpointing the user!messagebeep function. The stack is now: CS+5E8 : 0889 CS+5E8 : 1510 CS : AD3E Searching the conditional jumps, you reach the code: * Referenced by a CALL at Addresses: |:0008.0889, :0008.16D6, :0008.172B | :0008.14BC C8060000 enter 0006, 00 :0008.14C0 837E0400 cmp word ptr [bp+04], 0000 :0008.14C4 741E je 14E4 :0008.14C6 8A26D764 mov ah, [64D7] :0008.14CA 2500FE and ax, FE00 :0008.14CD 8946FA mov [bp-06], ax :0008.14D0 3D005C cmp ax, 5C00 :0008.14D3 740A je 14DF :0008.14D5 3D005E cmp ax, 5E00 :0008.14D8 7405 je 14DF :0008.14DA 3D0060 cmp ax, 6000 :0008.14DD 7505 jne 14E4 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0008.14D3(C), :0008.14D8(C) | :0008.14DF A1D664 mov ax, [64D6] :0008.14E2 EB4B jmp 152F ; Not working jump * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0008.14C4(C), :0008.14DD(C) | :0008.14E4 8D46FC lea ax, [bp-04] :0008.14E7 50 push ax :0008.14E8 9A52052815 call 0081.0552 :0008.14ED 8BD8 mov bx, ax :0008.14EF 368B07 mov ax, ss:[bx] :0008.14F2 8946FE mov [bp-02], ax :0008.14F5 8A66FF mov ah, [bp-01] :0008.14F8 80E4FE and ah, FE :0008.14FB 80FC5C cmp ah, 5C :0008.14FE 741C je 151C :0008.1500 8A66FF mov ah, [bp-01] :0008.1503 80E4FE and ah, FE :0008.1506 80FC5E cmp ah, 5E :0008.1509 7411 je 151C ; Working Jump ***** :0008.150B 681709 push 0917 :0008.150E 6A00 push 0000 :0008.1510 9A1AADBB0E call 0064.AD1A ; Here the bpx :0008.1515 33C0 xor ax, ax :0008.1517 C9 leave :0008.1518 C20400 ret 0004 We found same situations as before. So switch to phase 2: Future transactions. Here the first difference with version 1.00p. The stack is: CS+148 : 223A CS+C8 : 360F CS : AF7E But near the second address, no conditional jumps are present and breakpointing the first you get a Protection Fault... We have a chance, make a backtrace buffer. So breakpoint the only CS+C8:360F and re-enter your date. You have to establish the buffer range, so type: bpr cs:0000 cs:360F T and re-enter the date. With the SHOW command of SoftICE, you can see: ... 000007 CS:2B6A ... JB 2B6F ; Interesting !!! 000006 CS:2B6C ... JMP 3606 000005 CS:3606 ... PUSH 0916 000004 CS:3609 ... PUSH 00 000003 CS:360B ... PUSH 00 000002 CS:360D ... PUSH 00 000001 CS:360F ... CALL XXXX:AF58 So bpx CS:2B6A and re-enter your date. You can find the code: * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0014.2B30(C) | :0014.2B35 8A04 mov al , [si] :0014.2B37 8B5EF4 mov bx, [bp-0C] :0014.2B3A 884710 mov [bx+10], al :0014.2B3D E90D0A jmp 354D :0014.2B40 8B5EF8 mov bx, [bp-08] :0014.2B43 F6470C06 test byte ptr [bx+0C], 06 :0014.2B47 7403 je 2B4C :0014.2B49 E9010A jmp 354D ; Not working jump * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0014.2B47(C) | :0014.2B4C 837E0800 cmp word ptr [bp+08], 0000 :0014.2B50 741D je 2B6F ; Working Jump+ ***** :0014.2B52 F606AC1701 test byte ptr [17AC], 01 :0014.2B57 7516 jne 2B6F ; Working Jump+ ***** :0014.2B59 833ED870FF cmp word ptr [70D8], FFFF :0014.2B5E 7503 jne 2B63 :0014.2B60 E9950A jmp 35F8 ; Not working jump * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0014.2B5E(C) | :0014.2B63 A1D664 mov ax, [64D6] :0014.2B66 3906D870 cmp [70D8], ax :0014.2B6A 7203 jb 2B6F ; Working Jump :0014.2B6C E9970A jmp 3606 As previous releases, if you want to enable all features of full version, the crack must be at CS:2B50 or at CS:2B57, converting conditional jumps, to always jumps (JMPS)

M$-Money v5.0 Trial version

Ouch... No beep inside... We have to follow another way to crack our babe. But we are familiar with the check routines code now. Try to use the getlocaltime calls (bpx getlocaltime), as +ORC says. I deleted first the sample.mny file, so I can work as before. Start with bpx getlocaltime, so strike F5 and go on until you can create a NEW file (open file --> new file): at the new dialog enter the name (es: heres.mny). After pressing the OK button, you can see some calls to getlocaltime function, before the notice of expiration. At fisrt call watch the stack... Last 3 entries are: CS : 004785BD CS : 00476D42 CS : 00478730 So Bpx the last one, disable the break at getlocaltime, and strike F5. Confirm the expiration and you are at CS:00478730, so set a bpx at the call point CS:0047872B (call 0046F000) and go to recreate the file. When SoftICE pops up, strike F8 and trace the code until the call to getlocaltime in MSMONEY code. After the call there are 2 jumps, but they seems not work, so return to the caller (stepping with F8). Mmmmh... I have already seen this piece of code !!! * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:00470648(C), :00470664(C) | :0047067C E84F83FFFF call 004689D0 :00470681 6689442402 mov [esp + 02], ax ; Return point :00470686 662500FE and ax, FE00 :0047068A 663D0060 cmp ax, 6000 :0047068E 7428 je 004706B8 ; The JUMP ***** :00470690 663D0062 cmp ax, 6200 :00470694 7422 je 004706B8 :00470696 6A00 push 00000000 :00470698 A1F03F6100 mov eax, [00613FF0] :0047069D 6A00 push 00000000 :0047069F 50 push eax :004706A0 6810F54C00 push 004CF510 :004706A5 68DC2F0000 push 00002FDC :004706AA E861B8FFFF call 0046BF10 :004706AF 83C414 add esp, 00000014 :004706B2 33C0 xor eax, eax :004706B4 83C404 add esp, 00000004 :004706B7 C3 ret As you can try, the CALL at CS:004706AA go directly to the Notice of Expiration display routine, so our working jump is probably at CS:0047068E. Ok... It works ! The expiration date is correct (see About item in Help menu). Now the phase 2, with the Payment Calendar. Enter a new payment and then your date (I change the year every time), with the only getlocaltime breakpoint active. SoftICE pops up and you can strike F5. The screen reappairs and then go back to the debugger moving the mouse... F5 again and you are at the last call to getlocaltime, before the advertisement (you can verify this with F5). So you can return to MSMONEY with F12 and go on over the code using F10. I recommend to set a bpx after some ret instructions, in order to disable the tedious getlocaltime bpx (doit !). Again with F10 but do not care about the code, the advertisement pops up very soon... Oh,oh... I found one call at CS:00558BC2... Bpx here, F5 and retry... Ok... I reached this last bpx, so strike F8 and go on with F10, as before. Ok... Another call at CS:005B6839... Bpx here, F5 and retry... F5,F8 and F10 until I reach another call at CS:005B6234, but this one calls only the first advertisement dialog, I think that the check is near this point... Set a bpx to this last call and prepare your backtrace buffer with: BPR CS:005B0000 CS:005B6234 T So F5 and re-enter your wrong date. Strike F5 until reaching the last bpx at CS:005B6234, so use the great SHOW command... 000005 CS:005B551E ... CMP [00619244],AX 000004 CS:005B5525 ... JBE 005B622D ; Good 000003 CS:005B622D ... PUSH 00 000002 CS:005B622F ... PUSH 0000090B 000001 CS:005B6234 ... CALL 00474BA0 The routine I found is: * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:005B54B3(U), :005B54B8(U) | :005B54C3 56 push esi :005B54C4 8B4DEC mov ecx, [ebp-14] :005B54C7 E8E4DAFFFF call 005B2FB0 :005B54CC 56 push esi :005B54CD E85E7AFFFF call 005ACF30 :005B54D2 83C404 add esp, 00000004 :005B54D5 8B4508 mov eax, [ebp+08] :005B54D8 6683780C01 cmp [eax+0C], 0001 :005B54DD 0F85FF0C0000 jne 005B61E2 :005B54E3 8A06 mov al , [esi] :005B54E5 8B4D0C mov ecx, [ebp+0C] :005B54E8 884110 mov [ecx+10], al :005B54EB E9F20C0000 jmp 005B61E2 :005B54F0 8B4DEC mov ecx, [ebp-14] :005B54F3 51 push ecx :005B54F4 E827DBFFFF call 005B3020 :005B54F9 83C404 add esp, 00000004 :005B54FC 85C0 test eax, eax :005B54FE 0F85DE0C0000 jne 005B61E2 :005B5504 837D3000 cmp [ebp+30], 00000000 :005B5508 7421 je 005B552B ; The Jump+ ***** :005B550A 8B4D3C mov ecx, [ebp+3C] :005B550D 668B81A9010000 mov ax, [ecx+000001A9] :005B5514 663DFFFF cmp ax, FFFF :005B5518 0F84F60C0000 je 005B6214 ; Not working jump :005B551E 66390544926100 cmp [00619244], ax :005B5525 0F86020D0000 jbe 005B622D ; Another jump Bpx at CS:005B5508, disabling others, and retry. You can find the same situation as before: the jump at CS:005B5518, when AX = FFFF, introduces the date missing limitation, so enable this great function with the crack CS:005B5508 = 74 21 --> EB 21 Note: Compare the cracks M$-Money v1.00p Working Model FileName : MNYDEMO.EXE Length : 501.664 bytes 1st byte crack : Offset 033ED0 = 74 --> EB 2nd byte crack : Offset 066C74 = 74 --> EB M$-Money v3.00p Evaluation version (french edition) FileName : MNYDEMO.EXE Length : 1.205.888 bytes 1st byte crack : Offset 011669 = 74 --> EB 2nd byte crack : Offset 02DCF0 = 74 --> EB M$-Money v5.0 Trial version FileName : MSMONEY.EXE Length : 4.929.536 bytes 1st byte crack : Offset 06FA8E = 74 --> EB 2nd byte crack : Offset 1B4908 = 74 --> EB Ok... That's all about M$-Money...

M$-Project 95: The quick Crack by + ORC

Take a look to the protection code... :05167F6A E808CFEBFF call 05024E77 :05167F6F 66817DF4C007 cmp [ebp-0C], 07C0 :05167F75 722F jb 05167FA6 :05167F77 66817DF40108 cmp [ebp-0C], 0801 :05167F7D 7727 ja 05167FA6 :05167F7F FF75F4 push [ebp-0C] :05167F82 660FB645F7 movzx byte ptr ax, [ebp-09] :05167F87 660FB64DF6 movzx byte ptr cx, [ebp-0A] :05167F8C 50 push eax :05167F8D 51 push ecx :05167F8E E84EC10B00 call 052240E1 :05167F93 663B45E4 cmp ax, [ebp-1C] :05167F97 7D0D jge 05167FA6 ; My Crack (-> EB7E) :05167F99 668B4DE4 mov cx, [ebp-1C] :05167F9D 662BC8 sub cx, ax :05167FA0 66894DF2 mov [ebp-0E], cx :05167FA4 EB06 jmp 05167FAC * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:05167E13(C), :05167ED7(C), :05167F1B(C), :05167F64(C), :05167F75(C), |:05167F7D(C), :05167F97(C) | :05167FA6 66C745FE0100 mov [ebp-02], 0001 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:05167E9F(C), :05167FA4(U) | :05167FAC FF75DC push [ebp-24] * Reference To: ADVAPI32.RegCloseKey, Ord:00C2h | :05167FAF FF151C5C3C05 Call dword ptr [053C5C1C] :05167FB5 EB25 jmp 05167FDC * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:05167DE5(C) | :05167FB7 66C745EC0000 mov [ebp-14], 0000 :05167FBD 8D45F4 lea eax, [ebp-0C] :05167FC0 50 push eax :05167FC1 E8B1CEEBFF call 05024E77 :05167FC6 66817DF4C007 cmp [ebp-0C], 07C0 :05167FCC 7208 jb 05167FD6 :05167FCE 66817DF40108 cmp [ebp-0C], 0801 :05167FD4 7606 jbe 05167FDC * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:05167FCC(C) | :05167FD6 66C745FE0100 mov [ebp-02], 0001 ; Crack A (Inverting the flag) * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:05167DBB(U), :05167FB5(U), :05167FD4(C) | :05167FDC 66837DFE00 cmp [ebp-02], 0000 :05167FE1 755F jne 05168042 :05167FE3 66837DF000 cmp [ebp-10], 0000 :05167FE8 750E jne 05167FF8 :05167FEA 66837DEC00 cmp [ebp-14], 0000 :05167FEF 7451 je 05168042 :05167FF1 66837DF000 cmp [ebp-10], 0000 :05167FF6 7407 je 05167FFF * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:05167FE8(C) | :05167FF8 66837DEC00 cmp [ebp-14], 0000 :05167FFD 7543 jne 05168042 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:05167FF6(C) | :05167FFF 0FBF4DF2 movsx word ptr ecx, [ebp-0E] :05168003 66833D58192C0501 cmp dword ptr [052C1958], 0001 :0516800B 1BC0 sbb eax, eax :0516800D 83E05A and eax, 0000005A :05168010 83C05A add eax, 0000005A :05168013 3BC1 cmp eax, ecx :05168015 7C2B jl 05168042 ; Crack B (Nooping) :05168017 66837DF21E cmp [ebp-0E], 001E :0516801C 7F4A jg 05168068 :0516801E 8D45F4 lea eax, [ebp-0C] Ok. Crack B doesn't work because, AFTER your expiration date, with the flag at 0001, the line at CS:05167FE1 jumps to the bad routine and the Crack B line is never reached. If you set the date BEFORE your installation date, the line at CS:05167F97 doesn't jump and you reaches the Crack B line with the correct flag (0000), so only in this case the Crack B will work. One solution could be to change the line: :05167F97 = 7D0D jge 05167FA6 --> EB7E jmps 0516817 (Offset: 167397) Ok... That's all... Now I can feel M$-protections...

I found a great text editor, faster than +ORC recommended M$-WW2... Try J-Write
for Windows (32-bit version) and open a file of 50Mb... I have a common P133...
Heres, August 25th 1997
 (c) Heres 1997. All rights reserved