Results 1 to 9 of 9

Thread: odd behavior in a keygen crackme

  1. #1

    odd behavior in a keygen crackme

    So, I (hopefully!) successfully reversed using OllyDbg this crackme that asks for a name and then calculates the serial from the name. Here's what I discerned to be the algorithm:

    Code:
    004012BA  /$ 53              PUSH EBX                                 ;  0
    004012BB  |. 56              PUSH ESI                                 ;  our serial
    004012BC  |. 57              PUSH EDI                                 ;  our name
    004012BD  |. BF 88304000     MOV EDI,keygen_#.00403088
    004012C2  |. 33C0            XOR EAX,EAX
    004012C4  |. 33DB            XOR EBX,EBX
    004012C6  |. 33C9            XOR ECX,ECX                              ;  zero out our counter register
    004012C8  |> 8A1C39          /MOV BL,BYTE PTR DS:[ECX+EDI]            ;  this will move into BL the letters of the name individually, depending on ecx our counter
    004012CB  |. 84DB            |TEST BL,BL                              ;  test to see if we have a letter
    004012CD  |. 74 08           |JE SHORT keygen_#.004012D7              ;  jump if there are no more letters
    004012CF  |. 03C3            |ADD EAX,EBX                             ;  add ebx to the value of eax
    004012D1  |. 83C0 10         |ADD EAX,10                              ;  increase the letter val by 10.  i.e. 74 becomes 84
    004012D4  |. 41              |INC ECX                                 ;  increment our counter
    004012D5  |.^EB F1           \JMP SHORT keygen_#.004012C8
    004012D7  |> 50              PUSH EAX                                 ; /push final serial to stack
    004012D8  |. 68 76304000     PUSH keygen_#.00403076                   ; |Format = "%X"
    004012DD  |. 68 D0304000     PUSH keygen_#.004030D0                   ; |s = keygen_#.004030D0
    004012E2  |. E8 1F000000     CALL <JMP.&user32.wsprintfA>             ; \call wsprintf, storing final serial in keygen_#.004030D0
    004012E7  |. 83C4 0C         ADD ESP,0C                               ;  clean up stack
    004012EA  |. 5F              POP EDI
    004012EB  |. 5E              POP ESI
    004012EC  |. 5B              POP EBX
    004012ED  \. C3              RETN
    With comments that I made to the side. So, I run the application in OllyDbg and try the string "tyler" as the name, and "280" as the serial, and lo and behold, it works! However, if I run the program from windows and try the same name/serial combination, it does not work.

    (Also odd is that my keygen which I wrote in Perl generates the serial number "280" for the name "tyler", which apparently is correct, but when I try other generated serials, they don't work through OllyDbg OR Windows! Is it legal for me to post my Perl here, too, and have someone go over that?)

    So you see, I've done my stuff...I found the algorithm (or what I believe to be it) and I made the keygen. In other words...don't go ballistic calling me a newbie and such ;-). I did what I think is right, and now I just have some questions.

    Thanks!
    When the going gets tough...the tough get going.

    Roar.

  2. #2
    son of Bungo & Belladonna bilbo's Avatar
    Join Date
    Mar 2004
    Location
    Rivendell
    Posts
    310
    Hi, tdennist,

    Tyler? I love her... She is one of my best friends... She is our Elf princess!

    The algorithm is ok: tyler->0x280

    In C language (with a printf at every step, to see better the serial building process):
    Code:
    #include <windows.h>
    #include <stdio.h>
    
    void
    main(void)
    {
        DWORD ret=0;
        char *name = "tyler";
    
        while (*name) {
            ret += *name++ + 0x10;
            printf("%x\n", ret);
            }
    }
    Anyway, I suspect you are facing two problems here...

    First problem:
    So, I run the application in OllyDbg and try the string "tyler" as the name, and "280" as the serial, and lo and behold, it works! However, if I run the program from windows and try the same name/serial combination, it does not work.
    There must be some other name manipulation outside of this routine, which you are not aware of using a debugger... Try using an "hide debugger plugin"...

    Second problem:
    When I try other generated serials, they don't work through OllyDbg OR Windows!
    Are you sure you are building up your Perl result in a longword? Maybe Perl is wrapping inside a 16bit word, but the check is performed on 32bits? Just a speculation...

    Best regards, bilbo
    Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt.[Seneca, Epistulae Morales 104, 26]

  3. #3
    Red wine, not vodka! ZaiRoN's Avatar
    Join Date
    Oct 2001
    Location
    Italy
    Posts
    922
    Blog Entries
    17
    Hi tdennist,
    if you want you can share your crackme with us. We'll try to figure out the problem...

    Regards,
    ZaiRoN

  4. #4
    My gosh...you can't imagine how frustrated that makes me that you were able to bang out that utterly simple keygen, when I went around and around first with C, then with C++, then finally with Perl, all with no luck. While I admit I am verrry very far from proficient in C/C++ (in fact, as it is I greatly prefer programming in ASM than either C or C++...they're just so RESTRICTING...), I like to consider myself at the very least proficient in Perl. Maybe I'll try my next one in Java....

    But anyhoo.

    As far as getting a "hide debugger plugin" is concerned...I have absolutely no idea where one would go to get one o' those, nor how one would go about using one. So...any suggestions?

    I am indeed not sure what is wrong with my Perl. I'll post it here and anybody else who knows Perl mayhap can tell me what's wrong:

    Code:
    #!/usr/bin/perl
    #keygen for keygen #1.exe
    
    print "Name: ";
    chomp($name=<STDIN>);
    
    $serial = 0;
    $ascletter = 0x0;
    
    @letters = split(//,$name);
    
    #doing all arithmetic in base 10, then at the end converting to base 16
    foreach $letter (@letters) {
            $ascletter = ord($letter);
            $serial += $ascletter;
            $serial += 16;         # 16 = 0x10
    }
    
    printf("Serial! -> %x\n", $serial);
    And as far as ZaiRoN's suggestion goes...I've attached it! Feel free to scan it for virii and such, but I'm fairly certain it's free of 'em.

    Thanks for your time and help!
    Attached Files Attached Files
    When the going gets tough...the tough get going.

    Roar.

  5. #5
    You are right, bilbo !
    The keygen uses IsDebugPresent to detect debugger.
    Code:
    .text:0040100C                 call    IsDebuggerPresent
    .text:00401011                 cmp     eax, 1
    .text:00401014                 jnz     short ShowDlg
    .text:00401016                 push    eax
    .text:00401017                 pop     bDebuggerPresent
    And at 004011C8, the keygen call one of two check function, according to bDebuggerPresent flag:
    Code:
    .text:004011C8 HaveNameAndSerial:                      ; CODE XREF: DoCheck+17j
    .text:004011C8                 mov     eax, bDebuggerPresent
    .text:004011CD                 cmp     eax, 1
    .text:004011D0                 jnz     short loc_4011D9
    .text:004011D2                 call    GenerateFakeSerial
    .text:004011D7                 jmp     short CompareSerial
    .text:004011D9 ; ---------------------------------------------------------------------------
    .text:004011D9
    .text:004011D9 loc_4011D9:                             ; CODE XREF: DoCheck+37j
    .text:004011D9                 call    GenerateRealSerial
    .text:004011DE CompareSerial:
    So the real generating serial code at 0040123C.
    Code:
    .text:0040123C GenerateRealSerial proc near            ; CODE XREF: DoCheck:loc_4011D9p
    .text:0040123C                 push    ebx
    .text:0040123D                 push    esi
    .text:0040123E                 push    edi
    .text:0040123F                 push    155h
    .text:00401244                 push    offset DoCheck
    .text:00401249                 call    CheckCRC32
    .text:0040124E                 cmp     eax, crc32ofDoCheck
    .text:00401254                 jz      short Start
    .text:00401256                 call    GenerateFakeSerial
    .text:0040125B                 jmp     short Done
    .text:0040125D ; ---------------------------------------------------------------------------
    .text:0040125D
    .text:0040125D Start:                                  ; CODE XREF: GenerateRealSerial+18j
    .text:0040125D                 mov     edi, offset nameBuf
    .text:00401262                 xor     eax, eax        ; eax = 0
    .text:00401264                 xor     ebx, ebx        ; ebx = 0
    .text:00401266                 xor     ecx, ecx        ; ecx = 0
    .text:00401268                 xor     edx, edx        ; edx = 0
    .text:0040126A
    .text:0040126A Loop:                                   ; CODE XREF: GenerateRealSerial+49j
    .text:0040126A                 mov     bl, [ecx+edi]   ; bl = nameBuf[ecx]
    .text:0040126D                 test    bl, bl          ; bl == 0 ?
    .text:0040126F                 jz      short Check
    .text:00401271                 add     edx, ebx        ; edx += nameBuf[ecx]
    .text:00401273                 or      eax, edx        ; eax |= edx
    .text:00401275                 inc     eax             ; eax++
    .text:00401276                 rol     edx, cl         ; edx <<= cl
    .text:00401278                 not     eax             ; eax = !eax
    .text:0040127A                 mov     esi, offset realSerialBuf
    .text:0040127F                 add     al, [esi+4]
    .text:00401282                 inc     ecx             ; ecx++
    .text:00401283                 add     eax, edx        ; eax += edx
    .text:00401285                 jmp     short Loop
    .text:00401287 ; ---------------------------------------------------------------------------
    .text:00401287
    .text:00401287 Check:                                  ; CODE XREF: GenerateRealSerial+33j
    .text:00401287                 push    edx
    .text:00401288                 push    155h
    .text:0040128D                 push    offset DoCheck
    .text:00401292                 call    CheckCRC32
    .text:00401297                 pop     edx
    .text:00401298                 cmp     eax, crc32ofDoCheck
    .text:0040129E                 jz      short Right
    .text:004012A0
    .text:004012A0 Wrong:
    .text:004012A0                 push    eax
    .text:004012A1                 jmp     short Format
    .text:004012A3 ; ---------------------------------------------------------------------------
    .text:004012A3
    .text:004012A3 Right:                                  ; CODE XREF: GenerateRealSerial+62j
    .text:004012A3                 push    edx
    .text:004012A4
    .text:004012A4 Format:                                 ; CODE XREF: GenerateRealSerial+65j
    .text:004012A4                 push    offset asc_403076 ; "%X"
    .text:004012A9                 push    offset realSerialBuf
    .text:004012AE                 call    wsprintfA
    .text:004012B3                 add     esp, 0Ch
    .text:004012B6
    .text:004012B6 Done:                                   ; CODE XREF: GenerateRealSerial+1Fj
    .text:004012B6                 pop     edi
    .text:004012B7                 pop     esi
    .text:004012B8                 pop     ebx
    .text:004012B9                 retn
    .text:004012B9 GenerateRealSerial endp
    The source of keygen:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char szName[36] = { 0 };
        int serial = 0;
    
        printf("Input user name: ");
        scanf("%32s", szName);
    
        for (int i = 0, len = strlen(szName); i < len; i++)
        {
            serial += szName[i];
            serial <<= i;
        }
    
        printf("Serial = %X\n", serial);
    
        return serial;
    }
    Serial for "tyler" is "4C5A0"
    Regards,
    TQN
    Last edited by TQN; March 23rd, 2005 at 00:49.

  6. #6
    son of Bungo & Belladonna bilbo's Avatar
    Join Date
    Mar 2004
    Location
    Rivendell
    Posts
    310
    tdennist,
    please allow me to write down just 3 remarks, without any malicious intent:

    (1)
    I greatly prefer programming in ASM than either C or C++...they're just so RESTRICTING...
    everything is RESTRICTING when you cannot fully dominate it... also Windows is so RESTRICTING, isn't it? Why? Because it comes without sources...

    (2) I quoted "hide debugger plugin" just for an easy cut and paste of the three words into Google (without quotes): try it, it will make no harm to you!

    (3) Have you already read the two solutions submitted on www.crackmes.de? But yes, TQN's one is better: TQN, why don't you submit it?

    Best regards, bilbo
    Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt.[Seneca, Epistulae Morales 104, 26]

  7. #7
    Hi bilbo !
    I am very afraid when writting English because my bad English skill, and a solution for crackmes.de need a long description, and I am always open aside a Vietnam-English dictionary when writting English.
    Best regards,
    TQN

  8. #8
    son of Bungo & Belladonna bilbo's Avatar
    Join Date
    Mar 2004
    Location
    Rivendell
    Posts
    310

    Again off topic...

    TQN,
    why you do not write an English<->Vietnamese dictionary for Babylon?
    They will reward you for this...
    http://www.babylon.com/display.php?id=55

    By the way, a nice project would be to reverse engineer the Babylon dictionary format (.BGL) - compressed and/or encrypted - in order to revert back to its source format (.GLS)

    Best regards, bilbo
    Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt.[Seneca, Epistulae Morales 104, 26]

  9. #9
    Thank for your idea, bilbo !
    I will take a look at it.

Similar Threads

  1. Control an application behavior
    By Zuk in forum Advanced Reversing and Programming
    Replies: 5
    Last Post: August 15th, 2008, 11:07
  2. strange behavior of unpacked exe (upx)
    By koyaan in forum The Newbie Forum
    Replies: 9
    Last Post: October 5th, 2004, 19:41
  3. Run Trace: stangest behavior
    By Anonymous in forum OllyDbg Support Forums
    Replies: 1
    Last Post: August 13th, 2003, 08:34

Bookmarks

Posting Permissions

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