CrackMe® Practices for Newbies
PROJECT 8: Conquer by MisterE

Re: Joseph's Thread Battle Two Conquered
Saturday, 20-Mar-99 04:54:08

    Greetings everybody,

    Here I am again with the last Battle conquered and the enemy in Battle two is completely vanquished. It took me a while to do it because the smoke screen, which I mistook for some nice fug, was very thick. But thanks to a hint from MisterE himself, who stated that this Battle is not what it seems to be, and a more direct hint from ytc_ who identified the right button to click, I was able to in on the heart of this Battle.

    Earlier when I was working on Battle one I located a function Call named CreateFileA and placed a break point on it and watched attempt to open a file named 1.123 and concluded then that must be a key file, so I went ahead and created a file and stuffed it with some bytes and saved it as 1.123 in the same directory where Conquer. Exe resides. Did not seem to make any difference and noticed that the only time the program went there was when I was quitting. This really fooled me and lead me to mistaken believe that this was another trick. This situation was aggravated by the fact by the time I reached there my eyes were bulging out of there sockets because the amount of staring at code in various library modules, and too tiered to think. Finally early in the morning yesterday, I spotted the hint about which button to klick in one of ytc_ posts and the rest became history.

    With a fresh start I fired Conquer and clicked the Battle Two Button and went to battle. I provided a username and a fake serial number and set a break point at function call CreateFile the clicked on the right Button, the Exit Button. Sure enough and true to form the program stopped at lactation 00401B0A and that is where the fun begins:

    * Reference To: KERNEL32.CreateFileA, Ord:0032h

    :00401B0A E8A1030000 Call 00401EB0
    :00401B0F 6A14 push 00000014
    :00401B11 6834364000 push 00403634
    :00401B16 50 push eax

    * Reference To: KERNEL32._lread, Ord:02D0h
    |
    :00401B17 E8AC030000 Call 00401EC8
    :00401B1C 83F814 cmp eax, 00000014
    :00401B1F 0F85B2000000 jne 00401BD7
    :00401B25 33C9 xor ecx, ecx
    :00401B27 33D2 xor edx, edx
    :00401B29 33DB xor ebx, ebx
    :00401B2B EB21 jmp 00401B4E

    What is happening here is that: At first, the call at 00401EB0 opens the file 1.123 and the second call at 00401EC8 reads from the file. The push 00000014 is for the number of bytes to be read and the second push 00403634 is the address for the buffer where the 20 bytes will be stored. There is a cmp eax 00000014 immediately after the second call at 00401B1C followed by a jne 00401BD7. This is the bad cracker jump and it is made if the program fails to read 20 bytes from the key file 1.123. If the read was good a jump is made to 00401B4E. Since nothing very significant for our purposes takes place until a little further, let us skip a few instructions and go to lactation 00401B8B and look at the following code:

    :00401B81 6834364000 push 00403634
    :00401B86 6835384000 push 00403835

    * Reference To: KERNEL32.lstrcmpA, Ord:02D6h
    |
    :00401B8B E83E030000 Call 00401ECE
    :00401B90 33C0 xor eax, eax
    :00401B92 33DB xor ebx, ebx
    :00401B94 33D2 xor edx, edx
    :00401B96 EB19 jmp 00401BB1
    :

    The first thing to notice here is the call 00401ECE at 00401B8B. This call is a string compare
    and it will compare your fake serial with whatever was read from the 1.123 file. The first push before the call puts the memory address of the code from 1.123 file on the stack and the second push places the memory address for your fake serial on the stack and goes comparing them. Remember? Things are not what they seem in this crackme and this compare is only to fool us. So don't rush and take what appears to be the real serial number and use it as your own. It will not work. This is not the only trick, indeed the final and greatest one is the way the serial number is generate, so let us consider that:

    00401B2D 038834364000 add ecx, dword ptr [eax+00403634]
    :00401B33 029834364000 add bl, byte ptr [eax+00403634]
    :00401B39 D1E3 shl ebx, 1
    :00401B3B 03CB add ecx, ebx
    :00401B3D D1C1 rol ecx, 1
    :00401B3F 83E804 sub eax, 00000004
    :00401B42 81C145724D00 add ecx, 004D7245
    :00401B48 81C1293B0000 add ecx, 00003B29
    :00401B4E 0BC0 or eax, eax
    00401B50 75DB jne 00401B2D
    :

    In the few lines of code above a number is generate from the code number in the 1.123 file and it involved a good amount of manipulation: This is a loop that goes for five times and each time a four byte number is brought from the buffer where the code number is stored and added to the ecx register and the first byte of the same four bytes is added to the bl register. Since your code number is less than twenty, the first couple of rounds will be nulls and nothing will be added to these registers at this stage. Then ebx is multiplied by 2 d added to ecx which is also multiplied by 2 , after this the numbers 4D7245H and 3B29H are also added to ecx. By the time the loop is over, you end up with an 8 byte number. This is the first number and it is generate from a hard coded numbers, 4D7245H and 3B29H in combination with the last part of the code number in the 1.123 key file. The first 4 numbers in the key file don't enter into the process. The second number is generate from the serial number the user provide, and here is where and how it is done:

    :00401B98 8A9A35384000 mov bl, byte ptr [edx+00403835]
    :00401B9E 42 inc edx
    :00401B9F 80FB2F cmp bl, 2F
    :00401BA2 760D jbe 00401BB1
    :00401BA4 80FB3A cmp bl, 3A
    :00401BA7 7308 jnb 00401BB1
    :00401BA9 6BC00A imul eax, 0000000A
    :00401BAC 80EB30 sub bl, 30
    :00401BAF 03C3 add eax, ebx
    :00401BB1 80BA3538400000 cmp byte ptr [edx+00403835], 00
    :00401BB8 75DE jne 00401B98

    This is another loop and it keeps going until it goes through every byte in the serial number. First the program checks if the character is a number between 0 and 9 and ignores it if it is not a number, but if it is it first converts it from its ACII representation to the binary representation. In this way the byte 33 representing the number "3" is reduced to half a byte containing binary 3. This number is then added to register eax which is multiplied by 10 every loop. Note the multiplication of eax takes place before the addition of the last number. This process generates a second number based exclusively on the serial number you entered. This number will be compared with the previously generate number and if you have used a good serial number you will be victorious.
    :00401BBA 59 pop ecx
    :00401BBB 3BC1 cmp eax, ecx
    :00401BBD 7518 jne 00401BD7

    Now the second number generate is held in eax register and the first number is pupped to the ecx register and the two are compared at 00401BBB cmp eax, ecx and if the two do not match you are sent to the bad cracker land. However to make the story complete I included the jump which you may patch and forget about serial number. It is staring at you at address 00401BBD. Nop it will give you the victory message.

    Best regards,

    Joseph

    Joseph


Message thread:

Joseph's Thread Task1 finishe (Joseph) (17-Mar-99 06:14:49)

Back to main board