pkunzip.exe psedit.zip w32dsm87.zip tekfct95.zip iwindbg.exe ;if you have downloaded itUnpack everything in this same subdirectory.
** What is your incentive to register? There is now an annoying splash screen that appears when starting the unregistered version as well as the word <unregistered> generously placed throughout the program. We had to add these features since we were getting lots of support calls from people who had not registered. In other words, you get support when you register! **In fact the author of this target is an extremely correct person, and has de facto allowed an unrestricted and time-unlimited use of his software to everybody. This is also the reason I have chosen this target: I don't believe that this will damage him... quite the contrary! This target is extremely useful, extremely powerful and extremely cheap, as anybody using it will realise. Its users base deserves to be expanded and I hope that at least some of you will register and pay for its complete (new) version after having cracked black and blue its shareware (old) version... it is the minimum you should do for the target that will have opened for you the hidden marvellous path to software reverse engineering!
FIRST CODE SNIPPET OF INTERESTThis code snippet actually tells you EVERYTHING you need to know. An average cracker would already know what to do. The two strings revealed by the disassembler are preceded by a compare instruction which is the key of the whole protection scheme. The target has a very simple protection indeed. I'll now explain to you the above code step by step. The first instruction (the first line) will be used to explain the hexadecimal notation (for dummies):
:004805F9 803D1AF34C0000 cmp byte ptr [004CF31A], 00 <A compare followed :00480600 7422 je 00480624 <by a jump, both :00480602 B201 mov dl, 01 <located just before :00480604 8B83C4010000 mov eax, dword ptr [ebx+000001C4] <the red string below!!! :0048060A E84567F9FF call 00416D54 :0048060F BA18074800 mov edx, 00480718 <-- 80718="<unregistered version>" :00480614 8B83E0010000 mov eax, dword ptr [ebx+000001E0] :0048061A E80968F9FF call 00416E28 :0048061F E9C7000000 jmp 004806EB jump here from Address:00480600(C) :00480624 33D2 xor edx, edx :00480626 8B83C4010000 mov eax, dword ptr [ebx+000001C4] :0048062C E82367F9FF call 00416D54 :00480631 BA38074800 mov edx, 00480738 ->"Licensed Version. Do Not Copy!" :00480636 8B83E0010000 mov eax, dword ptr [ebx+000001E0] :0048063C E8E767F9FF call 00416E28
:004805F9 803D1AF34C0000 cmp byte ptr [004CF31A], 00LOOK AT THE FIRST CODE LINE/ This is an INSTRUCTION, situated at location 4805F9. Your target code is represented in hexadecimal notation, and each byte (or series of bytes) has a particular meaning. This is assembly, the so called 'machine language': 80 3D 1A F3 4C 00 00
80 3D 1A F3 4C 00 00this correspond to assembly command cmp byte ptr [004CF31A], 00, whose meaning we'll investigate in a minute, but these same hexadecimal bytes correspond also to the underlying 'real' binary code, here it is... for each hexadecimal a byte each composed of 8 bits (either one or zero):
80 3D 1A F3 4C 00 00 10000000 00111101 00011010 11110011 01001100 00000000 00000000Now, just look at the binary code... look at the number THREE, for instance (inside 3D and inside F3)... you get it? 3 is always 0011, let's have a look at the same code once more, this time divided in 4 bit pieces:
8 0 3 D 1 A F 3 4 C 0 1000 0000 0011 1101 0001 1010 1111 0011 0100 1100 0000...Now everything should be clear and you have your explanation before your eyes: hexadecimal code allows a precise and immediate representation of the UNDERLYING binary code, which as you (should) know is the only code that your computer is capable to understand (power on / power off). Binary is elementarily simple: 0=0000; 1=0001; 2=0010; 3= 0011; 4=0100; 5=0101; 6=0110; 7=0111 and so on. 4 bits give 16 possibilities (0-F: 0000-1111, decimal 0-15); 8 bits (a byte) give 256 possibilities and range from 0 (which is 00000000) to FF (which is 11111111 and corresponds to 255... 0-255 are 256 possibilities).
cmp byte ptr [004CF31A], 00 << ASSEMBLY LANGUAGE 803D1AF34C0000 10000000001111010001101011110011010011000000000000000000This means [compare what is inside the memory location number [004CF31A] with zero]... or, if you prefer, [let's see if a zero has been stored inside that memory location]... Technically, this 'compare' is considered an arithmetic operation, because the source operand (here zero), is subtracted from the destination operand (here the content of location [004CF31A]. The result, however is used for setting the flags and it is not stored anywhere. Flags are single (0/1) bits of a special register, which are VERY important, inter alia, for our cracking purposes... more about flag-bits and register-bytes later.
cmp byte ptr [004CF31A], 00 803D1AF34C0000 << HEXADECIMAL NOTATION 10000000001111010001101011110011010011000000000000000000hexadecimal expression, ... you will probably not yet understand this, yet it should already result somehow more transparent... Let's imagine that you know that 80 (like 3B) means (often enough) compare, i.e.'cmp', and that 803D means specifically 'cmp byte ptr' (that is "compare a memory location I'm pointing you to"), well, in that case you would immediately guess that (after 803D) the following part: 1A34C00, represents a memory location in inverted format, and that the last byte, zero, correspond to the right operand of our instruction.
... 8039E9 cmp byte ptr [ecx], E9 803A20 cmp byte ptr [edx], 20 803B22 cmp byte ptr [ebx], 22 803C0000 cmp byte ptr [eax+eax], 00 803C1826 cmp byte ptr [eax+ebx], 26 803C2400 cmp byte ptr [esp], 00 803D35E04C0000 cmp byte ptr [004CE035], 00 <This is like 'our' instruction above ... 803B22 cmp byte ptr [ebx], 22 807B0122 cmp byte ptr [ebx+01], 22 807B4800 cmp byte ptr [ebx+48], 00 ... 807E4800 cmp byte ptr [esi+48], 00 80BC064C0100001A cmp byte ptr [esi+eax+0000014C], 1A 80F861 cmp al, 61 80F91A cmp cl, 1A 80FA61 cmp dl, 61 80FB20 cmp bl, 20 80FF64 cmp bh, 64Now, if take a couple of minutes out of your patience bag and look hard at the hexadecimal codes of the raster above, you'll make out some easy and clear patterns... Most of the compare instructions above regard the various REGISTERS of your microprocessor: ax (which is divided into al and ah), bx, cx... and so on... more about registers later.
cmp byte ptr [004CF31A], 00 803D1AF34C0000 10000000001111010001101011110011010011000000000000000000 << BINARY NOTATIONThe long row of zero and ones above is a binary expression... you would probably not want to understand what that mean even if somebody would pay you for it. Yet now that you have read the above text you could eventually (slowly) understand that in this awful sequence of 1 and zero there is a compare, and then a memory location in inverted format: 004CF31A, and then a last byte, 00, which is therefore the source operand of the compare... This is the way your microprocessor gets the code from the program. Wouw! Don't worry, you'll (almost) NEVER have to reverse binary notation when you crack :-)
:004805F9 803D1AF34C0000 cmp byte ptr [004CF31A], 00 ;done above :00480600 7422 je 00480624 :00480602 B201 mov dl, 01 :00480604 8B83C4010000 mov eax, dword ptr [ebx+000001C4] :0048060A E84567F9FF call 00416D54 :0048060F BA18074800 mov edx, 00480718 ->"<unregistered version>" :00480614 8B83E0010000 mov eax, dword ptr [ebx+000001E0] :0048061A E80968F9FF call 00416E28 :0048061F E9C7000000 jmp 004806EB jump here from Address:00480600(C) :00480624 33D2 xor edx, edx :00480626 8B83C4010000 mov eax, dword ptr [ebx+000001C4] :0048062C E82367F9FF call 00416D54 :00480631 BA38074800 mov edx, 00480738 ->"Licensed Version. Do Not Copy!" :00480636 8B83E0010000 mov eax, dword ptr [ebx+000001E0] :0048063C E8E767F9FF call 00416E28I will not keep you hours on this. The code above means what my comments say, just try to understand why:
:004805F9 cmp byte ptr [004CF31A], 00 <d'we have a zero in memory location F31A? :00480600 je 00480624 <if so jump to 624... (THIS IS A GOOD JUMP!) :00480602 mov dl, 01 <else bad luck! Load 1 inside register dl :00480604 mov eax, dword ptr [ebx+1C4] <and load in eax the address at ebx+1C4 :0048060A call 00416D54 <and call the subroutine at 16DC4; then then :0048060F mov edx, 00480718 <point to string "<unregistered version>" :00480614 mov eax, dword ptr [ebx+1E0] <and load in eax the address at ebx+1E0 :0048061A call 00416E28 <and call the subroutine at 16E28 :0048061F jmp 004806EB <and jump away WITHOUT executing the following code jump here from Address:00480600(C) :00480624 xor edx, edx <load a zero in dx (this is a GOOD GUY flag) :00480626 mov eax, dword ptr [ebx+1C4] <and load in eax the address at ebx+1C4 :0048062C call 00416D54 <and call the subroutine at 16DC4; then :00480631 mov edx, 00480738 <point to string "Licensed Version. Do Not Copy!" :00480636 mov eax, dword ptr [ebx+1E0] <and load in eax the address at ebx+1E0 :0048063C call 00416E28 <and call the subroutine at 16E28You will notice that this code can EITHER load 'flag' 1 in register dl and then point to "unregistered version"
OK, it's confirmed, we have enough proofs. Every time the target nags us with the 'unregistered' string, there is acheck of memory location CF31A. Let's get ready to crack now!
:004811E6 803D1AF34C0000 cmp byte ptr [004CF31A], 00 :004811ED 742D je 0048121C :004811EF BA44134800 mov edx, 00481344 <"TechFacts 95 Embedded Help "<unregistered>"
:004B9445 803D1AF34C0000 cmp byte ptr [004CF31A], 00 :004B944C 740F je 004B945D :004B944E BA78944B00 mov edx, 004B9478 <"TechFacts 95 "<unregistered>"
:0047BA54 B898BB4700 mov eax, 0047BB98 ;"Registration Key accepted!" :0047BA59 E83EBEFBFF call 0043789C ;call this and that :0047BA5E C6051AF34C0000 mov byte ptr [004CF31A], 00 ;good guy, let's give him zero :0047BA65 EB11 jmp 0047BA78 ;go aheadAnd CODE SNIPPET 2
:004CBB67 E834F7FAFF call 0047B2A0 ;after executing this subroutine :004CBB6C 84C0 test al, al ;check the returned value with AND :004CBB6E 7509 jnz 004CBB79 ;jump good flag if zero flag clear :004CBB70 C6051AF34C0001 mov byte ptr [004CF31A], 01 ;mark the non registered lazy bastard :004CBB77 EB07 jmp 004CBB80 ;beggar off without good flag :004CBB79 C6051AF34C0000 mov byte ptr [004CF31A], 00 ;get good flagSince our memory location is SET only three times inside our target... two times as we like it (to zero, at 47BA5E and 4CBB79) and only once as we do NOT want it to be (to one at 4CBB70), the crack is straightforward... you only need to change ONE SINGLE BYTE of the code and this target will be always registered: You just need to change original code
:004CBB70 C6051AF34C0001 mov byte ptr [004CF31A], 01 ;bad flaginto cracked code
:004CBB70 C6051AF34C0000 mov byte ptr [004CF31A], 00 ;good guyOf course inside the target we will have somewhere a routine that checks if the input numbers of the registration are correct ('fravia' and '12121212') and that sets our triggering call bad or good as a consequence... we COULD NOT CARE LESS.
Go to dos 'ms dos prompt psedit choose tekfct95.exe backup file (one never knows) F8 (search) input string C6051AF34C0001 then move right until you are with the cursor under the 01 type 00 F2 (save)that's all. Run your cracked target (and eventually buy its new version if you like it... you'll notice that tekfct95.exe offers indeed some very useful functions for our endeavours.