Results 1 to 9 of 9

Thread: Project # 3 TASKS 1 & 2

  1. #1
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Blog Entries

    Project # 3 TASKS 1 & 2

    TASK 1 - Set your system clock ahead to trigger an expiration nag.
    a) Figure out how to change the install date info so the program still functions normally (at least for the next 30 days or so) WITHOUT patching the program.
    b) Now patch the program so it will continue to operate (unregistered) indefinitely.

    There are many API breakpoints that might, or might not, be successful with time checks. You could just try them all, or maybe use an API monitor to tell you which one(s) are being used. If not, you'll need another way to get to the relevant code. Filemon/Regmon should tell you where the install date info is kept, so you may need to use the corresponding breakpoints (i.e. CreateFileA / ReadFile for files and RegOpenKeyExA / RegQueryValueExA for the registry)


    TASK 2 -
    a) Determine where/how the program keeps its registration info.

    Trace through the registration routine and register the program by
    b) patching a jump or
    c) determining a valid serial.
    The 1st two projects have given the general techniques sufficient to do this.

    d) After you've done b) or c) above, what happens? Trace through the code (F10) and determine what API calls are used and what they are doing.

  2. #2
    Hi all,

    I though I may as well get the ball rolling. here is some preliminary stuff and task 1.

    Preliminary stuff
    I installed the program with INCTRL 4 which monitors the installation and generates a report showing all files, registry keys and values added or changed during the installation. Useful for making sure you get rid of all of the program when you delete it and damn useful for this sort of work The following created in the registry is probably fishy considering we are looking at a time check:

    HKEY_CURRENT_USER\Software\HappyIcon\startdate=01C0546F (29381503)

    Note: the startdate value is created from your system clock when you install the program and will be different for each person. The value 29381503 is just the decimal conversion of 01C0546F.

    SIDENOTE: If someone could show me how to convert this into a time and date eg 3rd Nov 2000 I would be grateful.

    OK, I ran the program to find out what it did. Selecting "about" from the "Help" menu gives the following information:

    Licence: Unregistered
    Granted to: Unregistered

    Selecting "register" from the same menu provides you with a dialog to enter:


    If you set the system clock forward so that the expiration nag is displayed and then set the clock back to the correct time, you can use the program normally once again. This suggests that there is just a direct comparison with the date it was installed and the current date and nothing else is set.

    Task 1
    As was mentioned in the task list, set the system time so that the expiration nag appears. Time to look at the program.

    Kayaker discussed a couple of the ways you could determine the right breakpoint to use. There is another simple method he did not mention. Get yourself a PE header browser (I use PEBrowse), open the program with it and check out the program's imports. There is only one API function that the program uses that will retrieve the system time; GetSytemTimeAsFileTime. If you set a breakpoint on that API function you will land here:

    * Reference To: KERNEL32.GetSystemTimeAsFileTime, Ord:0176h
    :00414C5A FF15E8004200 Call dword ptr [004200E8]
    :00414C60 8B4C241C mov ecx, dword ptr [esp+1C] ;current filetime
    :00414C64 8B542404 mov edx, dword ptr [esp+04] ;installed filetime
    :00414C68 2BCA sub ecx, edx
    :00414C6A 81F993170000 cmp ecx, 00001793
    :00414C70 720A jb 00414C7C

    If you note the values in ecx and edx after the MOV instructions you will see that one of them corresponds to the the startdate value we saw in the registry earlier, the other is the current system time/date. If you take the value in ecx and use this to replace the startdate value in the registry (Use regedit in the windoze directory, get to the key shown above, rightclick on the value and select modify, type in your new value) you can now use the program for the next 30 days or so.

    To make the patch permanent so it will continue to run unregistered, it is a simple matter of changing

    :00414C70 720A jb 00414C7C


    :00414C70 EB0A jmp 00414C7C

    which will cause the program to make the right jump regardless of what the result from the comparison is.

    I promise that I have read the FAQ and tried to use the Search to answer my question.

  3. #3
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Blog Entries
    Nice work Mersenne and thanks for a detailed response.

    I don't think you can convert GetSystemTimeAsFileTime results as a regular date and time. According to its definition it returns information as Coordinated Universal Time (UTC) format in a FILETIME structure. The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601. Don't know where the hell they come up with that one

    If you trace into the Kernel32 call you can see system date info being PUSHed in certain registers (i.e. 7D0=2000, 0B=11=Nov), but they're only being used internally to calculate the UTC.

    typedef struct _FILETIME { // ft
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;

    dwLowDateTime- Specifies the low-order 32 bits of the file time.
    dwHighDateTime-Specifies the high-order 32 bits of the file time.

    If you display the FILETIME structure address pointed to in the GetSystemTimeAsFileTime parameter you see the 2 DWORDS listed. It appears that the HighDateTime is the date and the LowDateTime is the time. The HighDateTime is the [esp+1C] value used in the CMP.

    * Reference To: KERNEL32.GetSystemTimeAsFileTime, Ord:0176h
    :00414C5A FF15E8004200 Call dword ptr [004200E8]
    :00414C60 8B4C241C mov ecx, dword ptr [esp+1C]
    :00414C64 8B542404 mov edx, dword ptr [esp+04]
    :00414C68 2BCA sub ecx, edx
    :00414C6A 81F993170000 cmp ecx, 00001793
    :00414C70 720A jb 00414C7C

    Just for fun here's a few other ways you could patch to force the cmp to be valid:

    :00414C64 8B542404 mov edx, dword ptr [esp+04]
    :00414C64 8B4C241C mov edx, dword ptr [esp+1C]

    :00414C68 2BCA sub ecx, edx
    :00414C68 2BC9 sub ecx, ecx

    :00414C68 2BCA sub ecx, edx
    :00414C68 33C9 xor ecx, ecx


  4. #4
    mhmm...Alright, just finished task 1, same general idea as what mersenne posted. As far as task 2 goes, however I did both B and C....Using a very simple breakpoint (GetDlgItemTextA), I was able to locate and patch *the* conditional jump, and i was registered (actually crazy as it is, I didnt even ahve to patch lol I Just did 'r fl z' in sice and i was registered for good, lol), as well as *fish* out a correct serial within just a few lines of this critical jump.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  5. #5

    Project # 3 TASKS 1 & 2 (Part 1)

    Please ignore all the ' marks, I had to try and stop those emoticons from being posted everywhere. Also if someone knows how to format the code stuff better, PLEASE let me know. The pre and fixed tags don't work so well.

    Here we go with task 2

    Considering that everytime you try to register the program you have to re-enter all the details, suggests that the program is not keeping any information entered (at this stage). There is nothing written to the registry or file.

    To patch a jump or determine a valid serial, we first need to break into the code to figure out what the program is doing. The program needs to get the information we enter into the registration dialog so lets begin there. There are a number of API functions which the program can use to do this. Looking at the list of imports again you will see that it is most likely GetDlgItemTextA. Set this breakpoint and then enter the information requested in the registration dialog. For the purposes of this project I entered the following:

    Name: copy
    First name: pirate
    Key: 12344321

    Hit the OK button and you will break at this function. The program actually calls this function three times in a row to get the name, followed by the first name and then the key so if you are using Softice you can press ctrl D after the first and second calls to get you to the third one. Press F11 and you will be in the program code. Alternatively you can trace through the code after you break the first time. After the final call you will end up here:
    * Reference To: USER32.wsprintfA, Ord:02B3h
    :00414079 8B1DF4024200            mov ebx, dword ptr [004202F4]
    :0041407F 8D542414                lea edx, dword ptr [esp+14]     ;address of name in edx
    :00414083 52                      push edx                        ;'push "copy"
    :00414084 8D44246C                lea eax, dword ptr [esp+6C]     ;address of first name in eax
    * Possible StringData Ref from Data Obj ->"HappyIcon"
    :00414088 6878214200              push 00422178                   ;'push "HappyIcon"
    :0041408D 50                      push eax                        ;'push "pirate"
    :0041408E 8D8C24A0050000          lea ecx, dword ptr [esp+000005A0];'destination address
    * Possible StringData Ref from Data Obj ->"%s%s%s"
    :00414095 68B4484200              push 004248B4                   ;format string
    :0041409A 51                      push ecx                        ;'push destination address
    :0041409B FFD3                    call ebx                        ;call wsprintfA
    This bit of code takes our name, first name and the string "HappyIcon" and concatenates (links) them. The result is that at the destination address you will see "pirateHappyIconcopy" for this example. For imformation about the format string used check out the API reference.

    :0041409D 8DBC24A8050000          lea edi, dword ptr [esp+000005A8];address of our new string
    :004140A4 83C9FF                  or ecx, FFFFFFFF
    :004140A7 33C0                    xor eax, eax
    :004140A9 83C414                  add esp, 00000014
    :004140AC F2                      repnz
    :004140AD AE                      scasb
    :004140AE F7D1                    not ecx                         ;length of string including 00 
                                                                      ;termination byte now in ecx
    The program now calculates the length of this string. During this time edi is incremented so that after the scasb instruction edi will point to the end of the string. The following corrects edi so that it points to the beginning of the string once more.

    see part 2................
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  6. #6

    Project # 3 TASKS 1 & 2 (part 2)

    :004140B0 2BF9                    sub edi, ecx
    :004140B2 8D942490010000          lea edx, dword ptr [esp+00000190];new address for string
    :004140B9 8BC1                    mov eax, ecx
    :004140BB 8BF7                    mov esi, edi
    :004140BD 8BFA                    mov edi, edx
    :004140BF C1E902                  shr ecx, 02                     ;converts length to dwords
    :004140C2 F3                      repz
    :004140C3 A5                      movsd                           ;move the string
    :004140C4 8BC8                    mov ecx, eax                    ;string length back into ecx
    :004140C6 8D842490010000          lea eax, dword ptr [esp+00000190] ;address of string
    :004140CD 83E103                  and ecx, 00000003			
    :004140D0 F3                      repz
    :004140D1 A4                      movsb
    :004140D2 8A8C2490010000          mov cl, byte ptr [esp+00000190] ;first character of our string
    :004140D9 84C9                    test cl, cl                     ;Is it zero?
    :004140DB 741F                    je 004140FC                     ;if yes, jump
    The string gets moved to a different address and now the fun begins
    * Referenced by a (U)nconditional or (C)onditional Jump at Address:
    :004140DD 80385F                  cmp byte ptr [eax], 5F	
    :004140E0 7503                    jne 004140E5				
    :004140E2 C60020                  mov byte ptr [eax], 20	 
    * Referenced by a (U)nconditional or (C)onditional Jump at Address:
    :004140E5 0FBE08                  movsx ecx, byte ptr [eax]       ;move character into ecx
    :004140E8 334C2410                xor ecx, dword ptr [esp+10]     ;xor with value in [esp+10]
    :004140EC 81F1CE9A5713            xor ecx, 13579ACE               ;xor with 13579ACE
    :004140F2 40                      inc eax	                        ;move pointer to next char
    :004140F3 894C2410                mov dword ptr [esp+10], ecx     ;'put new value in [esp+10]
    :004140F7 803800                  cmp byte ptr [eax], 00          ;is our next char=0?
    :004140FA 75E1                    jne 004140DD                    ;if no, jump up
    This is the major loop of our serial calculating routine. It cycles through the string one character at a time, checks to see if the character is 5F ("_") and if yes, replaces it with 20h (space character). The charcter is then XORed with what is at address [ESP+10]. The starting value in [ESP+10] is FFFFFFFF. This value is then XORed by 13579ACE and stored back in [ESP+10]. The pointer to our string is moved to the next character which is checked to see if it is zero (the end of the string). If it is not zero the loop repeats.

    * Referenced by a (U)nconditional or (C)onditional Jump at Address:
    :004140FC 8D9424BC000000          lea edx, dword ptr [esp+000000BC] ;the key we entered
    :00414103 52                      push edx
    :00414104 E873220000              call 0041637C                   ;the key converted to hex
    :00414109 8B4C2414                mov ecx, dword ptr [esp+14]     ;our calculated value
    :0041410D 83C404                  add esp, 00000004
    :00414110 81F1F0BD6824            xor ecx, 2468BDF0               ;xor with 2468BDF0
    :00414116 3BC1                    cmp eax, ecx                    ;compare the values
    :00414118 742E                    je 00414148                     ;if the same, please continue
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  7. #7

    Project # 3 TASKS 1 & 2 (Part 3)

    The key we entered is converted to hex. The value from the loop above is then XORed with 2468BDF0. Note that after this instruction, ecx contains our correct serial IN HEXIDECIMAL for the name we entered. For pirate copy it is C8C0D8A4. To get the correct key to enter in the registration screen all we need do is covert it back to decimal viz -926885724. The jmp directly after the compare is where the program decides who gets registered and who get the "Invalid registration" message. If we wish we could change

    :00414118 742E je 00414148


    :00414118 EB2E jmp 00414148

    to permanently patch the program. There are also other ways to patch this, as Kayaker mentioned in a post above.

    After the program is successfully registered, the file HappyIcon.lic is created in the same directory that Happy Icon is installed in. The unregistered string disappears from the main window title and the about menu item now has the registration information entered as does the register menu item but now all the edit boxes have been greyed.

    I promise that I have read the FAQ and tried to use the Search to answer my question.

  8. #8

    Remind me not to use code tags either, they take up too many characters! Found out a little too late.

    Sorry about the split posts

    I promise that I have read the FAQ and tried to use the Search to answer my question.

  9. #9
    Well I haven't seen anything here yet about the happyicon.lic file so I will mention it. After the prog decides the user typed in a valid reg number, it creates the .lic file with your registration info. Most programs will check the reg info every time on start up to make sure it is valid but not in this case. If you pass the original check you are reged for life it seams. There is a checksum number in the *.lic file. I haven't traced through the CRC routine but if I have time I will look at it.
    Thanks for the interesting project. The target is damn easy to crack but untill now I never bothered to follow all the api calls and see what was going on in a program. Normaly I was just interested in getting it reged. This is a bit more interesting.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

Similar Threads

  1. RSA Mini Project
    By Bengaly in forum Mini Project Area
    Replies: 11
    Last Post: October 10th, 2002, 08:12
  2. A New Project?
    By CoDe_InSiDe in forum Mini Project Area
    Replies: 51
    Last Post: May 20th, 2001, 21:06
  3. Ideas For A New Project ???
    By Clandestiny in forum Mini Project Area
    Replies: 15
    Last Post: February 8th, 2001, 15:36
  4. Project # 3 TASKS 3 & 4
    By Kayaker in forum Mini Project Area
    Replies: 20
    Last Post: December 11th, 2000, 21:03
  5. Project # 3
    By Kayaker in forum Mini Project Area
    Replies: 8
    Last Post: December 2nd, 2000, 21:04


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts