banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thủ thuật reverse engineering Zart's Keygenme [phân tích và keygen]  XML
  [Article]   Zart's Keygenme [phân tích và keygen] 21/01/2008 06:26:59 (+0700) | #1 | 111299
[Avatar]
kienmanowar
HVA Friend

Joined: 13/07/2004 05:57:34
Messages: 483
Offline
[Profile] [PM] [WWW]
///////////////////////////////////////////////////////////////////////////////////
Program : Zart's Keygenme
Download : http://www.crackmes.de/users/zart/mishka_tribute/download
Description : make a keygen, do whatever you need to for this, just submit solution and keygen.
Tools : IDA, OllyDbg
Difficult : Easy
Packer/Protector/Compiler : N/A
Objective : Keygen
Cracker : kienmanowar{REATEAM}
///////////////////////////////////////////////////////////////////////////////////

Trước tiên phải nói bản thân cái keygenme này nó có Bug dẫn đến keygen ko thỏa hết các trường hợp và cũng rất khó chịu

1. Chạy keygenme, hehe tác giả cho nghe một bài tune. Nhập Name và Serial vào và nhấn Enter, blah biến mất luôn không để lại em Nag nào!!

2. Load thử vào Olly trước, tìm tất cả các Ref strings nhưng ko có em nào thú vi cả. Bật IDA lên và load keygenme vào, chờ analyse xong thì nhấn Shift+F12 đẻ mở cửa số Strings.Dạo một lượt ta tìm được Good Boy

Code:
.data:00407028 szSerialcheckedout-nowrightakeygen_ db 0Ah ; DATA XREF: _main+15Ao_main
.data:00407028                 db 'Serial checked out - now right a keygen.',0Ah,0


3. Nhấn đúp chuột vào _main+15Ao sẽ trở lai asm code :

Code:
.text:00401246                 push    offset szSerialcheckedout-nowrightakeygen_ ; "\nSerial checked out - now right a keyge"...
.text:0040124B                 jmp     short loc_401252 ; Jump
.text:0040124B
.text:0040124D ; ---------------------------------------------------------------------------
.text:0040124D
.text:0040124D loc_40124D:                             ; CODE XREF: _main+158j
.text:0040124D                 push    offset szSerialfailedcheck ; "\nSerial failed check!\n"
.text:0040124D

4. Giờ thì reload lại keygenme trong Olly và nhấn Ctrl+G, nhập vào địa chỉ 0x00401246. Cuộn lên trên đầu và đặt một BP tại điểm bắt đầu của thủ tục này :

Code:
004010EC >/$  B8 69414000                 MOV     EAX, <keygenme.loc_404169> ;  _main <== set BP here
004010F1  |.  E8 DA2E0000                 CALL    <keygenme.__EH_prolog>
004010F6  |.  83EC 24                     SUB     ESP, 24
004010F9  |.  53                          PUSH    EBX


5. Nhấn F9 để rụn, dừng lại tại BP. Trace down cho tới khi tới đoạn asm code nhận UserName và Serial. Trong đoạn code này ta sẽ thấy nó lấy từng kí tự một và so sánh xem có phải kí tự có mã 0xD (Phím enter), còn không nó sẽ chuẩn bị một vùng Buffer để thực hiện việc nối chuỗi.Cụ thể đoạn code như sau, anh em đọc sẽ hiểu :

Code:
0040119A >|> /FF15 9C604000               /CALL    NEAR DWORD PTR DS:[<&MSVCRT._kbhit>]                       ; [loc_40119A
004011A0  |. |85C0                        |TEST    EAX, EAX
004011A2  |.^ 74 F6                       |JE      SHORT <keygenme.loc_40119A>
004011A4  |. |FF15 98604000               |CALL    NEAR DWORD PTR DS:[<&MSVCRT._getch>]                       ; [_getch
004011AA  |. |837D E4 00                  |CMP     DWORD PTR SS:[EBP-1C], 0
004011AE  |. |8845 E8                     |MOV     BYTE PTR SS:[EBP-18], AL
004011B1  |. |75 5E                       |JNZ     SHORT <keygenme.loc_401211>
004011B3  |. |3C 0D                       |CMP     AL, 0D
004011B5  |. |75 33                       |JNZ     SHORT <keygenme.loc_4011EA>
004011B7  |. |837D EC 00                  |CMP     DWORD PTR SS:[EBP-14], 0
004011BB  |. |75 0F                       |JNZ     SHORT <keygenme.loc_4011CC>
004011BD  |. |8B0D 10604000               |MOV     ECX, DWORD PTR DS:[<&MSVCIRT.cout>]                        ;  MSVCIRT.cout
004011C3  |. |68 60704000                 |PUSH    keygenme.00407060                                          ;  ASCII 0A,"You must enter a name!\n Name: "
004011C8  |. |FFD6                        |CALL    NEAR ESI
004011CA  |.^ EB CE                       |JMP     SHORT <keygenme.loc_40119A>
004011CC >|> |8B0D 10604000               |MOV     ECX, DWORD PTR DS:[<&MSVCIRT.cout>]                        ;  loc_4011CC
004011D2  |. |68 54704000                 |PUSH    keygenme.00407054                                          ;  ASCII "Serial: "
004011D7  |. |C745 E4 01000000            |MOV     DWORD PTR SS:[EBP-1C], 1
004011DE  |. |FFD6                        |CALL    NEAR ESI
004011E0  |. |50                          |PUSH    EAX
004011E1  |. |FF15 18604000               |CALL    NEAR DWORD PTR DS:[<&MSVCIRT.flush>]                       ;  MSVCIRT.flush
004011E7  |. |59                          |POP     ECX
004011E8  |.^ EB B0                       |JMP     SHORT <keygenme.loc_40119A>
004011EA >|> |FF75 E8                     |PUSH    DWORD PTR SS:[EBP-18]                                      ;  loc_4011EA
004011ED  |. |8B0D 10604000               |MOV     ECX, DWORD PTR DS:[<&MSVCIRT.cout>]                        ;  MSVCIRT.cout
004011F3  |. |FFD7                        |CALL    NEAR EDI
004011F5  |. |50                          |PUSH    EAX
004011F6  |. |FF15 18604000               |CALL    NEAR DWORD PTR DS:[<&MSVCIRT.flush>]                       ;  MSVCIRT.flush
004011FC  |. |59                          |POP     ECX
004011FD  |. |FF75 E8                     |PUSH    DWORD PTR SS:[EBP-18]
00401200  |. |8D4D D0                     |LEA     ECX, DWORD PTR SS:[EBP-30]
00401203  |. |FF75 EC                     |PUSH    DWORD PTR SS:[EBP-14]
00401206  |. |FF15 24604000               |CALL    NEAR DWORD PTR DS:[<&MSVCP60.std::basic_string<char,std::c>;  MSVCP60.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::append
0040120C  |. |FF45 EC                     |INC     DWORD PTR SS:[EBP-14]
0040120F  |.^ EB 89                       |JMP     SHORT <keygenme.loc_40119A>
00401211 >|> |3C 0D                       |CMP     AL, 0D                                                     ;  loc_401211
00401213  |. |74 23                       |JE      SHORT <keygenme.loc_401238>
00401215  |. |FF75 E8                     |PUSH    DWORD PTR SS:[EBP-18]
00401218  |. |8B0D 10604000               |MOV     ECX, DWORD PTR DS:[<&MSVCIRT.cout>]                        ;  MSVCIRT.cout
0040121E  |. |FFD7                        |CALL    NEAR EDI
00401220  |. |50                          |PUSH    EAX
00401221  |. |FF15 18604000               |CALL    NEAR DWORD PTR DS:[<&MSVCIRT.flush>]                       ;  MSVCIRT.flush
00401227  |. |59                          |POP     ECX
00401228  |. |8D049B                      |LEA     EAX, DWORD PTR DS:[EBX+EBX*4]
0040122B  |. |0FBE4D E8                   |MOVSX   ECX, BYTE PTR SS:[EBP-18]
0040122F  |. |8D5C41 D0                   |LEA     EBX, DWORD PTR DS:[ECX+EAX*2-30]
00401233  |.^\E9 62FFFFFF                 \JMP     <keygenme.loc_40119A>


Dùng IDA dựng mã giả của đoạn trên :

Code:
while ( TRUE )
  {
    while ( TRUE )
    {
      while ( !kbhit() )
        ;
      iKeyInput = getch();
      LOBYTE(iTempChar) = iKeyInput;
      if ( v18 )
        break;
      if ( iKeyInput == Enter_key )
      {
        if ( iSize )
        {
          v18 = 1;
          szStr = ostream__operator__(cout, "\nSerial: ");
          flush(szStr);
        }
        else
        {
          ostream__operator__(cout, "\nYou must enter a name!\nName: ");
        }
      }
      else
      {
        v11 = ostream__operator__(cout, iTempChar);
        flush(v11);
        std__basic_string_char_std__char_traits_char__std__allocator_char____append(&szStrBuffer, iSize++, iTempChar); //Append String
      }
    }
    if ( iKeyInput == Enter_key )
      break;
    v12 = ostream__operator__(cout, iTempChar);
    flush(v12);
    szSerial = (char)iTempChar + 10 * szSerial - 48;
  }


6. Ok sau khi có được mảng buffer chứa chuỗi vừa tính toán, ta trace tiếp tới đoạn code sau :

Code:
00401238 >|> \8D45 D0                     LEA     EAX, DWORD PTR SS:[EBP-30]                                  ;  loc_401238
0040123B  |.  50                          PUSH    EAX                                                         ; 
0040123C  |.  E8 BFFDFFFF                 CALL    <keygenme.sub_calculate_serial()>                           ;  <== Trace Into


7. Trace into sub_calculate_serial() :

Code:
00401005  |.  33C0                        XOR     EAX, EAX                                                    ;  <== eax = 0
00401007  |.  33F6                        XOR     ESI, ESI                                                    ;  <== esi = 0
00401009  |.  8B51 08                     MOV     EDX, DWORD PTR DS:[ECX+8]                                   ;  <== Length(szTempString)
0040100C  |.  57                          PUSH    EDI
0040100D  |.  85D2                        TEST    EDX, EDX
0040100F  |.  BF BA430000                 MOV     EDI, 43BA                                                   ;  <== edi = 0x43BA
00401014  |.  76 25                       JBE     SHORT <keygenme.loc_40103B>
00401016  |.  53                          PUSH    EBX
00401017  |.  8B59 04                     MOV     EBX, DWORD PTR DS:[ECX+4]                                   ;  <== ebx : szTempString[]
0040101A >|>  8B0D 2C604000               /MOV     ECX, DWORD PTR DS:[<&MSVCP60.`std::basic_string<char,std::>;  loc_40101A
00401020  |.  85DB                        |TEST    EBX, EBX
00401022  |.  74 03                       |JE      SHORT <keygenme.loc_401027>
00401024  |.  8D0C33                      |LEA     ECX, DWORD PTR DS:[EBX+ESI]
00401027 >|>  0FBE09                      |MOVSX   ECX, BYTE PTR DS:[ECX]                                     ;  <== ecx = szTempString[i]
0040102A  |.  0FAFC7                      |IMUL    EAX, EDI                                                   ;  <== eax = eax * edi
0040102D  |.  03C1                        |ADD     EAX, ECX                                                   ;  <== eax = eax + ecx
0040102F  |.  69FF FAE60600               |IMUL    EDI, EDI, 6E6FA
00401035  |.  46                          |INC     ESI                                                        ;  <== esi++
00401036  |.  3BF2                        |CMP     ESI, EDX                                                   ;  <== while esi < Length(szTempString)
00401038  |.^ 72 E0                       \JB      SHORT <keygenme.loc_40101A>                                ;  <== Then continue


Sử dụng IDA để dựng mã giả :

Code:
int iReaKey; // eax@1
  unsigned int iLenszStrBuffer; // edx@1
  unsigned int iInit; // edi@1
  unsigned int iIndex; // esi@1
  int v5; // ebx@2
  void *szChar; // ecx@3

  iReaKey = 0;
  iIndex = 0;
  iLenszStrBuffer = *(_DWORD *)(a1 + 8);                        // Length of szStrBuffer
  iInit = 0x43BAu;
  if ( iLenszStrBuffer )
  {
    v5 = *(_DWORD *)(a1 + 4);                                   // Point to szStrBuffer
    do
    {
      szChar = _C;
      if ( v5 )
        szChar = (void *)(v5 + iIndex);                         // Get char for szStrBuffer
      iReaKey = *(_BYTE *)szChar + iInit * iReaKey;
      iInit *= 0x6E6FAu;
      ++iIndex;
    }
    while ( iIndex < iLenszStrBuffer );
  }
  return iReaKey;


Dòm vào đoạn mã giả trên, ta thấy mảng Buffer sẽ được sử dụng để tính toán, kết quả iRealKey cuối cùng sẽ được lưu trọng thanh ghi EAX.

8. Đây là đoạn check key sau khi tính toán và key ta nhập vào, đúng thì show Good Boy :

Code:
00401241  |.  3BC3                        CMP     EAX, EBX <== Compare iReal Key with szSerial
00401243  |.  59                          POP     ECX
00401244  |.  75 07                       JNZ     SHORT <keygenme.loc_40124D>
00401246  |.  68 28704000                 PUSH    keygenme.00407028                                           ;  ASCII 0A,"Serial che"
0040124B  |.  EB 05                       JMP     SHORT <keygenme.loc_401252>
0040124D >|>  68 10704000                 PUSH    keygenme.00407010                                           ;  loc_40124D
00401252 >|>  8B0D 10604000               MOV     ECX, DWORD PTR DS:[<&MSVCIRT.cout>]                         ;  loc_401252
00401258  |.  FFD6                        CALL    NEAR ESI
0040125A  |.  FF75 E0                     PUSH    DWORD PTR SS:[EBP-20]
0040125D  |.  E8 35040000                 CALL    <keygenme.sub_401697>
00401262  |.  59                          POP     ECX
00401263  |.  E8 59010000                 CALL    <keygenme.sub_4013C1>
00401268  |.  834D FC FF                  OR      DWORD PTR SS:[EBP-4], FFFFFFFF
0040126C  |.  6A 01                       PUSH    1
0040126E  |.  8D4D D0                     LEA     ECX, DWORD PTR SS:[EBP-30]
00401271  |.  FF15 30604000               CALL    NEAR DWORD PTR DS:[<&MSVCP60.std::basic_string<char,std::ch>;  MSVCP60.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy
00401277  |.  5F                          POP     EDI
00401278  |.  33C0                        XOR     EAX, EAX
0040127A  |.  5E                          POP     ESI
0040127B >|>  8B4D F4                     MOV     ECX, DWORD PTR SS:[EBP-C]                                   ;  loc_40127B
0040127E  |.  5B                          POP     EBX
0040127F  |.  64:890D 00000000            MOV     DWORD PTR FS:[0], ECX
00401286  |.  C9                          LEAVE
00401287  \.  C3                          RETN


Tổng kết là toàn bộ source của keygenme(hehe sẽ có bug không tránh khỏi nhé ):

Code:
char szName[64]={0};
char szSerial[64]={0};
char szTempString[128]={0};
char szTemp[64]={0};
int i=0,j=0,LenUser=0,iRealKey=0,iValue=0;

LenUser=GetDlgItemText(IDC_Name,szName,70);
    if (LenUser < 1 || LenUser > 14)
    {
        MessageBox("----------===== Your name atleast 1 chart ====---------- \n\n   ----------===== But not over 14 charts ====---------- ","Hey !! Please input your name again !! ");
    }
    else
    {
        i = 0;
        while (i < LenUser)
        {
            i++;
            for (j=i;j>0;j--)
            {
                szTemp[j-1] = szName[i];           
            }
            strncat(szTempString,szTemp,i);
        }

        LenUser = strlen(szTempString);
        i = 0;
        _asm
            {
                xor eax,eax
                xor esi,esi
                xor edx,edx
                mov edi,0x43BA
            }   
        while (i < LenUser)
        {
            _asm
            {
                mov eax, iRealKey
                lea ecx, dword ptr[szTempString]
                movsx ecx,byte ptr[ecx+esi]
                imul eax, edi
                add eax, ecx
                imul edi, edi, 0x6E6FA
                inc esi
                mov iRealKey,eax
            }
            i++;   
        }
        wsprintf(szSerial,"%d",iRealKey);
    }

    SetDlgItemText(IDC_Serial,szSerial);


That's all. Thanx for reading my tutor.

--++--==[ Greatz Thanks To ]==--++--
My family, Computer_Angel, Moonbaby , Zombie_Deathman, Littleboy, Benina, QHQCrker,
the_Lighthouse, Merc, Hoadongnoi, Nini ... all REA‘s members, TQN, HacNho, RongChauA,
Deux, tlandn, light.phoenix aka mfeng, dqtln, ARTEAM .... all my friend, and YOU.

--++--==[ Thanks To ]==--++--
iamidiot, WhyNotBar, trickyboy, dzungltvn, takada, hurt_heart, haule_nth, hytkl, moth, XIANUA, nhc1987 v..v..
[Up] [Print Copy]
  [Question]   Re: Zart's Keygenme [phân tích và keygen] 20/12/2008 01:33:48 (+0700) | #2 | 163216
shinichi_zz
Member

[Minus]    0    [Plus]
Joined: 23/02/2007 16:19:13
Messages: 14
Offline
[Profile] [PM]
Biết cái này để làm gì nhưng tiếc là mình chưa đủ trình để hiểu dc nó.
[Up] [Print Copy]
  [Question]   Re: Zart's Keygenme [phân tích và keygen] 20/12/2008 01:42:02 (+0700) | #3 | 163217
[Avatar]
kienmanowar
HVA Friend

Joined: 13/07/2004 05:57:34
Messages: 483
Offline
[Profile] [PM] [WWW]
Uh biết cái này chỉ để giải trí cho vui những lúc rảnh rỗi thôi, chẳng để làm gì cả smilie. Oh` tôi nghiên cứu cũng một thời gian dài nhưng cảm thấy mình cũng chưa đủ trình để hiểu hết về nó smilie
[Up] [Print Copy]
  [Question]   Re: Zart's Keygenme [phân tích và keygen] 20/12/2008 09:30:45 (+0700) | #4 | 163277
TQN
Elite Member

[Minus]    0    [Plus]
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
[Profile] [PM] [WWW] [Yahoo!]
Cái này hồi xưa mà chưa có HexRays thì khóc tiếng Mán luôn. Tui phải ngồi lì trên máy 1 ngày, cúp điện thoại em út gọi thì mặc may mới mò ra.
[Up] [Print Copy]
  [Question]   Re: Zart's Keygenme [phân tích và keygen] 20/12/2008 10:07:55 (+0700) | #5 | 163282
[Avatar]
kienmanowar
HVA Friend

Joined: 13/07/2004 05:57:34
Messages: 483
Offline
[Profile] [PM] [WWW]

TQN wrote:
Cái này hồi xưa mà chưa có HexRays thì khóc tiếng Mán luôn. Tui phải ngồi lì trên máy 1 ngày, cúp điện thoại em út gọi thì mặc may mới mò ra. 


hì anh TQN, cái cảm giác đêm ngồi lọ mọ, mở Olly F8/F7 trace code chay và đọc hiểu nó thú vị làm sao smilie

Rg
[Up] [Print Copy]
  [Question]   Re: Zart's Keygenme [phân tích và keygen] 21/12/2008 01:29:57 (+0700) | #6 | 163363
xude
Member

[Minus]    0    [Plus]
Joined: 14/12/2008 01:34:17
Messages: 2
Offline
[Profile] [PM]
Olly còn sướng chán , Softice+windows 98 vừa trace vừa niệm thần chú để nó khỏi crash hehe
[Up] [Print Copy]
  [Question]   Re: Zart's Keygenme [phân tích và keygen] 07/04/2009 08:17:47 (+0700) | #7 | 175995
tuanbca
Member

[Minus]    0    [Plus]
Joined: 31/03/2009 16:53:56
Messages: 5
Offline
[Profile] [PM]

xude wrote:
Olly còn sướng chán , Softice+windows 98 vừa trace vừa niệm thần chú để nó khỏi crash hehe 

Hehe giống mình thế, mình lọ mọ làm quen mấy cái này từ hồi rất lâu rồi nhưng cứ động đến softice thì win nó cũng ice luôn ice nhiều đâm chán nên đến giờ vẫn ngu smilie
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 Users currently in here 
1 Anonymous

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|