Cracking Security Administrator For Windows 95/98 v1.3 by douby^dread First of all, I'd like to say that I really like Tornado's approach of helping newbies with increasing their cracking skills. That's why I decided to help him with this project of his ;-) When you run Secagent, the first thing you'll notice is the a window asking you for the serial number.. It doesn't ask for a name or company or something. So the serial is probably hardcoded or sumphing like that... Let's enter a wrong serial... What you get is a messagebox whining about a wrong registration code.. Now what ? We could do a couple of things first of all we could do lil'bit of fooling around in soft- ice, setting some breakpoints and stuff or we could load the program in w32dasm and take a look at the dead listing first... The latter is the approach I usually prefer.. So guess what I did first eh ? Yeah dudez, you got it right, I disassembled the program in w32dasm and took a look at the string table.. And boy, there were a couple of nice fish swimming around in there ;-) "Sorry this registration code", "Registration has successfully".. Double clicking on one of these babes will get you here: :00471C64 8B55FC mov edx, dword ptr [ebp-04] :00471C67 8BC3 mov eax, ebx :00471C69 E842B0FFFF call 0046CCB0 :00471C6E 84C0 test al, al :00471C70 7438 je 00471CAA ;if al == 0 wrong serial :00471C72 8B4DFC mov ecx, dword ptr [ebp-04] * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00471C0E(C) | :00471C75 BAEC1C4700 mov edx, 00471CEC :00471C7A A1B4584700 mov eax, dword ptr [004758B4] :00471C7F E8E07FFFFF call 00469C64 :00471C84 B201 mov dl, 01 :00471C86 A1B4584700 mov eax, dword ptr [004758B4] :00471C8B E8B87FFFFF call 00469C48 :00471C90 6A40 push 00000040 * Possible StringData Ref from Code Obj ->"Information" | :00471C92 B9F01C4700 mov ecx, 00471CF0 * Possible StringData Ref from Code Obj ->"Registration has successfully " ->"completed!" | :00471C97 BAFC1C4700 mov edx, 00471CFC :00471C9C A1C0404700 mov eax, dword ptr [004740C0] :00471CA1 8B00 mov eax, dword ptr [eax] :00471CA3 E85C50FDFF call 00446D04 :00471CA8 EB18 jmp 00471CC2 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00471C70(C) | :00471CAA 6A10 push 00000010 * Possible StringData Ref from Code Obj ->"Error" | :00471CAC B9281D4700 mov ecx, 00471D28 * Possible StringData Ref from Code Obj ->"Sorry, this registration code " ->"is invalid!" | :00471CB1 BA301D4700 mov edx, 00471D30 :00471CB6 A1C0404700 mov eax, dword ptr [004740C0] :00471CBB 8B00 mov eax, dword ptr [eax] :00471CBD E84250FDFF call 00446D04 * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00471CA8(U) | :00471CC2 33C0 xor eax, eax :00471CC4 5A pop edx :00471CC5 59 pop ecx :00471CC6 59 pop ecx :00471CC7 648910 mov dword ptr fs:[eax], edx As you can see, the routine containing the serial check is probably located at :0046CCB0... So let's take a look over there ;-) :0046CCB0 55 push ebp :0046CCB1 8BEC mov ebp, esp :0046CCB3 51 push ecx :0046CCB4 53 push ebx :0046CCB5 56 push esi :0046CCB6 8955FC mov dword ptr [ebp-04], edx :0046CCB9 8BF0 mov esi, eax :0046CCBB 8B45FC mov eax, dword ptr [ebp-04] :0046CCBE E81171F9FF call 00403DD4 :0046CCC3 33C0 xor eax, eax :0046CCC5 55 push ebp :0046CCC6 68A4CD4600 push 0046CDA4 :0046CCCB 64FF30 push dword ptr fs:[eax] :0046CCCE 648920 mov dword ptr fs:[eax], esp :0046CCD1 33DB xor ebx, ebx :0046CCD3 C605B858470000 mov byte ptr [004758B8], 00 :0046CCDA B8BC584700 mov eax, 004758BC :0046CCDF E8C06CF9FF call 004039A4 :0046CCE4 8B45FC mov eax, dword ptr [ebp-04] :0046CCE7 E8346FF9FF call 00403C20 :0046CCEC 83F80C cmp eax, 0000000C :0046CCEF 0F8599000000 jne 0046CD8E :0046CCF5 8B45FC mov eax, dword ptr [ebp-04] :0046CCF8 803838 cmp byte ptr [eax], 38 :0046CCFB 0F858D000000 jne 0046CD8E :0046CD01 8B45FC mov eax, dword ptr [ebp-04] :0046CD04 80780233 cmp byte ptr [eax+02], 33 :0046CD08 0F8580000000 jne 0046CD8E :0046CD0E 8B45FC mov eax, dword ptr [ebp-04] :0046CD11 80780331 cmp byte ptr [eax+03], 31 :0046CD15 7577 jne 0046CD8E :0046CD17 8B45FC mov eax, dword ptr [ebp-04] :0046CD1A 80780439 cmp byte ptr [eax+04], 39 :0046CD1E 756E jne 0046CD8E :0046CD20 8B45FC mov eax, dword ptr [ebp-04] :0046CD23 80780830 cmp byte ptr [eax+08], 30 :0046CD27 7565 jne 0046CD8E :0046CD29 8B45FC mov eax, dword ptr [ebp-04] :0046CD2C 80780935 cmp byte ptr [eax+09], 35 :0046CD30 755C jne 0046CD8E :0046CD32 8B45FC mov eax, dword ptr [ebp-04] :0046CD35 80780A53 cmp byte ptr [eax+0A], 53 :0046CD39 7553 jne 0046CD8E :0046CD3B 8B45FC mov eax, dword ptr [ebp-04] :0046CD3E 80780B45 cmp byte ptr [eax+0B], 45 :0046CD42 754A jne 0046CD8E :0046CD44 B8BC584700 mov eax, 004758BC :0046CD49 8B55FC mov edx, dword ptr [ebp-04] :0046CD4C E8A76CF9FF call 004039F8 :0046CD51 C605B858470001 mov byte ptr [004758B8], 01 :0046CD58 B301 mov bl, 01 :0046CD5A 33D2 xor edx, edx :0046CD5C 8B8600050000 mov eax, dword ptr [esi+00000500] :0046CD62 E86DCEFCFF call 00439BD4 :0046CD67 33D2 xor edx, edx :0046CD69 8B8614050000 mov eax, dword ptr [esi+00000514] :0046CD6F E8B8D9FBFF call 0042A72C :0046CD74 33D2 xor edx, edx :0046CD76 8B8610030000 mov eax, dword ptr [esi+00000310] :0046CD7C E853CEFCFF call 00439BD4 :0046CD81 33D2 xor edx, edx :0046CD83 8B860C030000 mov eax, dword ptr [esi+0000030C] :0046CD89 E846CEFCFF call 00439BD4 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses: |:0046CCEF(C), :0046CCFB(C), :0046CD08(C), :0046CD15(C), :0046CD1E(C) |:0046CD27(C), :0046CD30(C), :0046CD39(C), :0046CD42(C) | :0046CD8E 33C0 xor eax, eax :0046CD90 5A pop edx :0046CD91 59 pop ecx :0046CD92 59 pop ecx :0046CD93 648910 mov dword ptr fs:[eax], edx :0046CD96 68ABCD4600 push 0046CDAB * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0046CDA9(U) | :0046CD9B 8D45FC lea eax, dword ptr [ebp-04] :0046CD9E E8016CF9FF call 004039A4 :0046CDA3 C3 ret A lot of jumps to 0046CD8E eh? Prolly not a nice place to jump to eh ;-) And what do you think about all those cmp byte ptr [eax + X], XX eh? Prrrretty suspicious if you ask me... What could that cmp eax, 0000000C mean ? A length check ? Well I'm usually a very lazy person, so this is what I did... I just wrote down the decimal numbers and the letters corresponding to the ascii numbers behind all the eax compares... So: cmp byte ptr [eax], 38 -> 8 cmp byte ptr [eax+02], 33 -> 3 cmp byte ptr [eax+03], 31 -> 1 cmp byte ptr [eax+04], 39 -> 9 cmp byte ptr [eax+08], 30 -> 0 cmp byte ptr [eax+09], 35 -> 5 cmp byte ptr [eax+0A], 53 -> S cmp byte ptr [eax+0B], 45 -> E Eh, but what about the spaces the program doesn't check, like [eax+01] ? Well, it could be the program checks them later in another routine, but like I said, I'm lazy, so for now, put some nice X's in the empty spaces... This is what we'll get: 8X319XXX05SE Okiz, let's enter this number in the "enter registration code"-textfield... And.. Bingo! It works ;-) Well that's all folks.. Greets go out to: all dread members, all faith members, all revolution members and all ecolove members, yosh, carpathia, bjanes, hutch, sortof, josephCo and prolly some other dudes I forgot ;-)