7žgMMMMM[1111A4uuُx1 '=*gM`Beta Notes: 10/17/91 The following bold entries constitute a tentative outline for topics to dicuss in detail. Some of these topics will require a fair amount of research on my part - in particular, the Eve and Encryption sections will take some time. After this section come the live cracks. These represent an attempt to take a novice cracker through every step of the cracking process detailing choices and decisions that I would make as I go and why I would make them. Any feedback would be greatly appreciated - especially from any novice crackers who find parts of this document incomprehensible. Note that this is a rough draft - there are bound to be errors although hopefully no logical ones (just syntactical and/or spelling). Determining where to start looking 1) Types of protection a) Serial number schemes b) Registration codes c) Network serial checks [AppleTalk driver stuff] d) Hardware plugs - see below e) Encryption - see below f) Time stamps g) Key disk How to break into programs 1) Trap interrupts a) Dialog/Alert traps b) MenuSelect c) InitFonts etc. 2) Manual entrance of TMON [Good luck] 3) Automatic TMON entrance via code modification [_Debugger trap insertion] a) Determining an address with Nosy b) Determining an address from the Jump Table c) Using TMON, Nosy, and ResEdit together 1) Determining address offsets 2) Nosy vs TMON a) Why Nosy "feels better" b) Why TMON is virtually omniscient TMON Tricks 1) TMON tricks with register values, flags, and instruction modification 2) One step ModalDialog hassles [Serial number schemes] 3) TMON Pro shortcuts Determining the type of crack to apply 1) Bypasses vs cracks 2) Finding the key code 3) Branch switching a) Mention something about branch op-codes - 2 and 4 byte instructions and offsets 4) Flag/variable modification 5) Code modification Everything you always wanted to know about the CODE 0 Jump Table. 1) What it is and how it works 2) Locating an entry point 3) Modifications Hardware plugs 1) General tips [Device Manager stuff] 2) Eve bullshit Encrypted Code Unless you are one hell of a genius at cryptology and have lots of time to kill, the encrypted CODE resources will have to be de-crypted and written back to the program. Here is why: to decrypt itself, a program will usually either take a known seed number and use it on each encrypted byte of the code or else it will start with some byte in the code and do a forward decrypt, i.e. the first byte decrypts the second byte, the new second byte decrypts the third byte, and so on. A simple method might be to have some code that looks like this: MOVE #1000,D0 LEA encryptedshit,A0 LEA encryptedshit-1,A1 loop1 EOR.L (A1)+,(A0)+ DBRA D0,loop1 encryptedshit Here is where the encrypted gibberish begins. This is a simple example, but note how it functions. D0 gets the number of longwords to decrypt, A0 is the destination (where the decrypted stuff will go - which is right back over the encrypted stuff) and A1 gets the decrypting key which is the long word that was previously decrypted. Then the code simply loops D0 times writing over the encrypted code with the decrypted code. After this code has finished, the program continues execution right where the encrypted (and now decrypted) code begins. Now cosider: somewhere in the encrypted stuff is the error check that you have to modify. This will be simple enough to locate assuming that you can run the decryption routine and then immediately regain control in TMON. The problem is that when you go to modify the error check so that it always passes, the modification screws up the decryption routine. This is because the decryption routine requires the exact original values to run properly since these values are the keys that the code uses. So a crack using traditional methods requires that you not only change the error branch, but that you also change every other encrypted value such that the decryption routine still runs properly - no small feat! A much more feasable method would be to decrypt the code, make the necessary modifications to the error routine, and then disable the decryption routine (just branching around it would do) and writing the whole mess (un-encrypted) back to the original code resource. So much for the theory, now if I could just crack one of these suckers... Live Cracks MultiClip 2.0 This program uses a network checking algorithm to determine whether multiple copies with the same serial number are currently running - if you don't use this program on a network, you will never see the error. Step 1: Where to start looking. There are actually several good places to begin looking for the protection (especially if you have already cracked it - but I will assume that you have not). First of all, since the program scans the network, it is probably using the _Open Trap somewhere early in its code to to access the Appletalk driver. Second, it displays an error dialog (or alert) so we could open it up in Resedit, find the error dialog (and note its ID # for later use) and then Nosy it and look at procedures that call ModalDialog or one of the Alert traps to try and find the one that displays the dialog with the proper ID #. Third, we could have TMON trap either 1) ModalDialog if it is a dialog or 2) StopAlert, CautionAlert or NoteAlert if it is an Alert and begin tracing from that point backwords. Fourth, we could just Nosy it and start from the top (the slow way). Whenever a program displays an error dialog (not a serial number dialog which seems to be in vogue these days) I almost always find the ID # of the dialog or alert and begin looking at procs in Nosy, so let's start there. In Resedit, we note that it is Dialog (and not Alert) #128 that is the problem. On to Nosy. After Nosy analyzes the INIT resource, open up the Trap Refs List under the Display menu and scroll down to GetNewDialog. Here you will find two listings: ASKNAME and PUTREGISTERDLOG. Since there are only two we can quickly check them both out (if there were a bunch, I would probably try a different method). First let us look at ASKNAME - here is the listing down to the GetNewDialog: 42BA: QUAL ASKNAME ; b# =184 s#1 =proc54 vdu_1 VEQU -26 vdu_2 VEQU -18 vdu_3 VEQU -12 vdu_4 VEQU -10 vdu_5 VEQU -8 param1 VEQU 8 funRslt VEQU 12 42BA: VEND ;-refs - com_43 MYFILTERFORNAME 42BA: 4E56 FFE6 'NV..' ASKNAME LINK A6,#-$1A 42BE: 48E7 0318 'H...' MOVEM.L D6-D7/A3-A4,-(A7) 42C2: 2C2E 0008 2000008 MOVE.L param1(A6),D6 42C6: 42A7 'B.' CLR.L -(A7) 42C8: 4EBA E642 100290C JSR proc19 42CC: 285F '(_' POP.L A4 42CE: 486E FFF8 200FFF8 PEA vdu_5(A6) 42D2: A874 '.t' _GetPort ; (VAR port:GrafPtr) 42D4: 42A7 'B.' CLR.L -(A7) 42D6: 302C 001E '0,..' MOVE 30(A4),D0 42DA: D07C 0014 '.|..' ADD #20,D0 42DE: 3F00 '?.' PUSH D0 42E0: 42A7 'B.' CLR.L -(A7) 42E2: 70FF 'p.' MOVEQ #-1,D0 42E4: 2F00 '/.' PUSH.L D0 42E6: A97C '.|' _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr; behind:WindowPtr):DialogPtr The first thing to do is to locate the _GetNewDialog and determine its associated parameters: actually all we care about is the first parameter, the ID #. Tracing backwords, we see that -1 is the third parm, 0 is the second parm, and 30(A4) + #20 (from the ADD #20,D0) is the first parm. Well, we have a problem here. Instead of a nice plain ID # being passed to GetNewDialog, the ID # is hidden on the stack frame somewhere. At this point it is best to mark this proc as indeterminite and go on to the next one. If we must come back to this one then we will have to figure out if ID #128 is valid for this proc and go from there. So let us look at PUTREGISTERDLOG 33AC: QUAL PUTREGISTERDLOG ; b# =141 s#1 =proc35 vdb_1 VEQU -286 vdb_2 VEQU -278 vdb_3 VEQU -276 vdb_4 VEQU -274 vdb_5 VEQU -272 vdb_6 VEQU -270 vdb_7 VEQU -268 vdb_8 VEQU -264 vdb_9 VEQU -262 vdb_10 VEQU -256 param1 VEQU 8 33AC: VEND ;-refs - INIT1 PUTREGISTERDLOG 33AC: 4E56 FEE2 'NV..' LINK A6,#-$11E 33B0: 2F0C '/.' PUSH.L A4 33B2: 206E 0008 2000008 MOVEA.L param1(A6),A0 33B6: 43EE FF00 200FF00 LEA vdb_10(A6),A1 33BA: 703F 'p?' MOVEQ #63,D0 33BC: 22D8 '".' ldb_1 MOVE.L (A0)+,(A1)+ 33BE: 51C8 FFFC 10033BC DBRA D0,ldb_1 33C2: 42A7 'B.' CLR.L -(A7) 33C4: 3F3C 0080 '?<..' PUSH #128 33C8: 42A7 'B.' CLR.L -(A7) 33CA: 70FF 'p.' MOVEQ #-1,D0 33CC: 2F00 '/.' PUSH.L D0 33CE: A97C '.|' _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr; behind:WindowPtr):DialogPtr Once again, find the GetNewDialog and determine the parms. Here we have -1 for the third, 0 for the second, and lo and behold, 128 for the first. This is definately our procedure. Note that this is an extremely easy example as no attempt has been made to disguise the ID # - it is clearly 128, the value we have been looking for all along. Determining how to implement the crack. The obvious place to start looking is just before the error dialog has been loaded. Here is that section of code from the above procedure: LINK A6,#-$11E PUSH.L A4 MOVEA.L param1(A6),A0 LEA vdb_10(A6),A1 MOVEQ #63,D0 ldb 1 MOVE.L (A0)+,(A1)+ DBRA D0,ldb_1 Next comes the code we just looked at CLR.L -(A7) PUSH #128 CLR.L -(A7) MOVEQ #-1,D0 PUSH.L D0 _GetNewDialog As we look at this code, keep in mind what it is that we are looking for. We know that the program is capable of loading without this error, so somewhere it has to be checking the network and then either branching to the error code (if it detects a copy of itself) or else branching around the error code. So we need to find the branch that is causing this segment of code to execute. A quick scan of the code that precedes the error dialog code should reveal nothing of interest. A Link followed by a 63 word Move Loop - no branches of any consequence whatsoever. If you are wondering why we can immediately eliminate the DBRA D0,ldb1 (after all, it is a branch) then ask yourself this: 1st, where does the branch go? Answer: to the line above the branch instruction. 2nd, what (if any) conditions is it checking? Answer: it checks to see if D0 (an obvious loop counter in this case) is equal to zero. If the branch does not either 1) branch directly to the error code (in this case it would have to be branching to the CLR.L -(A7) ) or 2) branch around the error code (somewhere after the GetNewDialog and the ensuing ModalDialog and probably even an ensuing DisposeDialog) then the branch is almost certainly a bad candidate. You particulaly should be able to immediately eliminate loop terminator branches like the one above. Well, since we have eliminated the only branch in this procedure above the GetNewDialog, we will have to look elsewhere. The next obvious place to look is in the procedure that called this one. Again Nosy makes this a snap. Take a look at the line right above the code listing that read refs - INIT1. The refs line tells you every procedure that calls the one you are currently looking at. Luckily, there is only one, so let us look at it next. Since this is a long procedure, I am only listing the section that surrounds the JSR PUTREGISTERDLOG line. I should also mention that I am writing this with a copy that I cracked a while ago and in un-cracking it for this document, could not remember exactly what the changed code was. I will show you where your code listing might differ from mine below: 196: 4268 0004 'Bh..' CLR 4(A0) 19A: 4228 0006 'B(..' CLR.B 6(A0) 19E: 4228 0007 'B(..' CLR.B 7(A0) 1A2: 43FA 036E 1000512 LEA data2,A1 ; len= 1 1A6: 45E8 0009 'E...' LEA 9(A0),A2 1AA: 4EBA 0392 100053E JSR proc2 1AE: 43FA 03A2 1000552 LEA data4,A1 ; 'Multi' 1B2: 4EBA 038A 100053E JSR proc2 1B6: 43FA 03AC 1000564 LEA data7,A1 ; len= 2 1BA: 4EBA 0382 100053E JSR proc2 1BE: 4A6E FFEC 200FFEC TST vab_2(A6) 1C2: 6756 100021A BEQ.S lab_13 1C4: 4FEF FFFE 'O...' LEA -2(A7),A7 1C8: 2F2E FFEE 200FFEE PUSH.L vab_3(A6) 1CC: 4EBA 2C88 1002E56 JSR proc29 1D0: 301F '0.' POP D0 1D2: 6646 100021A BNE.S lab_13 1D4: 4FEF FFCE 'O...' LEA -50(A7),A7 1D8: 204F ' O' MOVEA.L A7,A0 1DA: 317C FFF6 0018 '1|....' MOVE #$FFF6,ioCRefNum(A0) 1E0: 216E FFEE 001E 200FFEE MOVE.L vab_3(A6),ioSEBlkPtr(A0) 1E6: 317C 00FC 001A '1|....' MOVE #252,CSCode(A0) 1EC: A004 '..' _Control ; (A0|IOPB:ParamBlockRec):D0\OSErr 1EE: 4FEF 0032 'O..2' LEA 50(A7),A7 1F2: 206E FFEE 200FFEE MOVEA.L vab_3(A6),A0 1F6: A01F '..' _DisposPtr ; (A0/p:Ptr) 1F8: 486D FFFC -4 PEA glob1(A5) 1FC: A86E '.n' _InitGraf ; (globalPtr:Ptr) 1FE: A8FE '..' _InitFonts 200: A912 '..' _InitWindows 202: A9CC '..' _TeInit 204: 42A7 'B.' CLR.L -(A7) 206: A97B '.{' _InitDialogs ; (resumeProc:ProcPtr) 208: A850 '.P' _InitCursor 20A: 42B8 0A6C $A6C CLR.L DeskHook 20E: 487A 0302 1000512 PEA data2 ; len= 1 212: 4EBA 3198 10033AC JSR PUTREGISTERDLOG 216: 4EFA 0316 100052E JMP com_2 21A: 4227 'B'' lab_13 CLR.B -(A7) 21C: A99B '..' _SetResLoad ; (AutoLoad:BOOLEAN) 21E: 42A7 'B.' CLR.L -(A7) 220: 2F3C 4452 5652 '/AAAAABLLM@MbUUUVVVVVVVVYabb+bKbbbee'e]efDqqqqsE|CaCKefvw !%cstž/  $>U&5Ho<=\l<RSz{/DE   + , Q R a w   '` p '` p '` p '` '` '` '` P+, !xy=>/d23wx7obD|_`!""X"Y"""#)#]###$-$a$$$$$%'%a%%&&G&&&''']''(:(;(<)))'` '` '` '` '` '` '` '` '` '` Q))*J*K*]*h*~****++++-+8+F+G0033344P4455J555656l6677J777878899O99::L:::; ;m;;.>a>>AAAAAAAAABBER '` '` '` '` '` '` '` '` '` '` PERESGGLLLLM?M@MaMbOOQQS*S+UUUUUVVVVVVVVVWW W:W_W~WWWWXX)XHXmXXXXXYY__aaaabb+bbbbcc4cNcec~ccccddջ'` '` '` '` '` '` '` '` '`  '` '` '` Jdd=dTdlddddde(eCeeeeeff,fDfEmmqqqqqqqqsDsEswsstt<tnttu$uSuuvvUvvvwwTwwxxGxyxxy y=yyyz*z]zz{ {^{{||t|||CD '` '` '` '` '` '` '` '` '` '` ODJK\fw "# 6m3 ?q1c1c.`HYAq$%bct '` '` '` '` '` '` '` '` T[\ D~J*_ E-d%] Bw,j'x \H*eRN GQR*`B H?v'` '` '` _v0liA0NR-t-zKS=x5jž'` '` '` 3CodeList  + l*G;!JVc=q~Sq]<@U |  <  >JCžbc)ERdDvždefghijk!"HH(FG(HH(d'@=/R@H -:LaserWriter (KV