'crack'에 해당되는 글 1건

  1. 2007.04.30 PxxxxCxx 크랙 (1)

PxxxxCxx 크랙

2007.04.30 16:59

PxxxxCxx 크랙




난는 원래 크랙 같은걸 별로 좋아하지 않는다.
걍 업무상 디스어셈블링 된 코드를 보고 있을 뿐인데 회사에서 하루종일 그것만 보고 있다가
집에 와서까지 보려고 하니 머리에 쥐가 나서 :p

그런데 이번에는 어쩌다가 저걸 크랙을 해야 해서 한번 해봤다.
크래킹에 도전을 해보신분들은 알겠지만, 이바닥은 어렵고 난해한 고난이도의 지식으로
삽질하며 정정당당히 승부를 할 필요가 없다.

최대한 간단하게, 그리고 최소한의 바이너리만 이용해서 골을 넣어야 하는게 진미~!
그래서 난 크랙을 단순코드의 미학이라고 생각한다 (Alternative Rock이랑 같은가 :p )

그럼 시작해볼까,

먼저 일반적인 상황에서 실행하면 다음과 같은 에러 등록권유 메시지 박스를 보여준다.

사용자 삽입 이미지

30일 평가기간 중에 -13633일이 남았다고 나오는데 ;; 내가 작업을 한 후 원래대로 다시 되돌리지
못해서 그렇게 표시되는 것 뿐이다, 보통은 1~30사이의 숫자가 나오겠지.. 암튼 그렇다고 쳐라
Try를 누르면 30일동안은 꽁짜로 쓸 수 있다.

만약 30일이 지나면 다음과 같은 메시지 박스를 뿌리면서 이제 트라이얼로 쓸 수도 없다. 사든지
Close하든지 결정하라는 메시지.

사용자 삽입 이미지


그럼 이걸 한번 무력화 해 볼까,

이런거 무력화하는 방법에는 여러가지 접근방법이 있다. 몇가지만 추려봐야겟다.

1) 시간 계산 루틴을 무력화하는 방법 - 30일이 지났는지 계산할테니 그걸 바보만드는 법
2) 시리얼을 입력후, 맞는 시리얼로 점프할때 그리로 강제 점프시키는 법
3) 시리얼 계산 루틴을 분석하여 직접 등록 넘버를 만드는 법

3번이 젤 해커답긴 하지만, 시간이 젤 많이 걸리는 작업이다. 난 귀찮은 작업은 싫어한다.
(근데 의외로 3번이 제일 쉽게 풀리는 경우도 있다. 연산 루틴 뻔히 보히고 최종적으로
EDI나 ESI 등에서 문자열 비교를 할때 같은) 머 어쨌든 하나씩 가볼까.

어떤 크래커는 모든 부분을 분석하는건 미련하기 짝이 없는 짓이라고 하는데, 남이 짜놓은
코드를 뜯어보며 얘는 여기를 왜 이렇게 해놓았을까 하며 상념에 젖는것도 나름 보람되는 일이다.
초기화 코드를 구성하는것이 개발자마다 천차만별인데, 난 그 차이를 비교하는것을 좋아한다.
그런의미에서 첨부터 한번 더듬어가보겠다.

일단 패킹부터 살펴보자.

사용자 삽입 이미지

Nothing Found * 라고 나오네. 무슨 희안한 프로텍터로 되어 있기에 나띵파운드냐 라고 몇초간
생각을 했지만, PEView에 넣어보니 Import Table에 정보가 다 보인다. 난 패킹이다. 이런 맛있는
밥이. 이정도면 우리에겐 거의 소스나 다름없다.

00407BE8   .  50            push eax                                 ; /pBufSize
00407BE9   .  8D8D E4FEFFFF lea ecx, dword ptr ss:[ebp-11C]          ; |
00407BEF   .  51            push ecx                                 ; |Buffer
00407BF0   .  8D95 DCFEFFFF lea edx, dword ptr ss:[ebp-124]          ; |
00407BF6   .  52            push edx                                 ; |pValueType
00407BF7   .  6A 00         push 0                                   ; |Reserved = NULL
00407BF9   .  68 D05D4200   push a.00425DD0                          ; |ValueName = "Name"
00407BFE   .  56            push esi                                 ; |hKey
00407BFF   .  C785 E0FEFFFF>mov dword ptr ss:[ebp-120], 0C8          ; |
00407C09   .  C685 E4FEFFFF>mov byte ptr ss:[ebp-11C], 0             ; |
00407C10   .  FFD7          call near edi                            ; \RegQueryValueExA
00407C12   .  33C0          xor eax, eax
00407C14   .  EB 0A         jmp short a.00407C20
00407C16   .  8DA424 000000>lea esp, dword ptr ss:[esp]
00407C1D   .  8D49 00       lea ecx, dword ptr ds:[ecx]
00407C20   >  8A8C05 E4FEFF>mov cl, byte ptr ss:[ebp+eax-11C]
00407C27   .  8888 E00C4300 mov byte ptr ds:[eax+430CE0], cl
00407C2D   .  83C0 01       add eax, 1
00407C30   .  84C9          test cl, cl
00407C32   .^ 75 EC         jnz short a.00407C20
00407C34   .  8D85 E0FEFFFF lea eax, dword ptr ss:[ebp-120]
00407C3A   .  50            push eax
00407C3B   .  884D AC       mov byte ptr ss:[ebp-54], cl
00407C3E   .  8D4D AC       lea ecx, dword ptr ss:[ebp-54]
00407C41   .  51            push ecx
00407C42   .  8D95 DCFEFFFF lea edx, dword ptr ss:[ebp-124]
00407C48   .  52            push edx
00407C49   .  6A 00         push 0
00407C4B   .  68 C85D4200   push a.00425DC8                          ;  ASCII "Serial"
00407C50   .  56            push esi
00407C51   .  C785 E0FEFFFF>mov dword ptr ss:[ebp-120], 50
00407C5B   .  FFD7          call near edi
00407C5D   .  56            push esi                                 ; /hKey

먼저 RegQueryValueExA 로 Name과 Serial을 찾는다. 레지스트리에 등록 인포메이션을
기록해 놓는구나 하고 감이 빡 온다.

00407B03  |.  68 D85D4200   push a.00425DD8                          ;  ASCII "ExpDate"

ExpDate까지 있다. 사용제한 날짜라는 것이네 정말 정직한 프로그래머가 개발했다.


0041492E  /$  55            push ebp
0041492F  |.  8BEC          mov ebp, esp
00414931  |.  51            push ecx
00414932  |.  51            push ecx
00414933  |.  8D45 F8       lea eax, [local.2]
00414936  |.  50            push eax                                 ; /pFileTime
00414937  |.  FF15 F0504200 call near dword ptr ds:[<&KERNEL32.GetSy>; \GetSystemTimeAsFileTime
0041493D  |.  8B45 F8       mov eax, [local.2]
00414940  |.  8B4D FC       mov ecx, [local.1]
00414943  |.  6A 00         push 0
00414945  |.  05 0080C12A   add eax, 2AC18000
0041494A  |.  68 80969800   push 989680
0041494F  |.  81D1 214E62FE adc ecx, FE624E21
00414955  |.  51            push ecx
00414956  |.  50            push eax
00414957  |.  E8 242A0000   call a.00417380
0041495C  |.  8B4D 08       mov ecx, [arg.1]
0041495F  |.  85C9          test ecx, ecx
00414961  |.  74 05         je short a.00414968
00414963  |.  8901          mov dword ptr ds:[ecx], eax
00414965  |.  8951 04       mov dword ptr ds:[ecx+4], edx
00414968  |>  C9            leave
00414969  \.  C3            retn

시간 계산 루틴이다. 다 계산해서 레지스트리에 때려박는데, 오 그래도 암호화는 해서 넣어둔다.
(적어도 20세기에 만들어진 것은 아니라는 얘기다)


00407B08  |.  56            push esi
00407B09  |.  C745 FC 08000>mov [local.1], 8
00407B10  |.  FFD7          call near edi
00407B12  |>  837D FC 08    cmp [local.1], 8
00407B16  |.  0F85 8F000000 jnz a.00407BAB
00407B1C  |.  8D45 F0       lea eax, [local.4]
00407B1F  |.  50            push eax                                 ; /Arg2
00407B20  |.  68 085E4200   push a.00425E08                          ; |Arg1 = 00425E08 ASCII "iopjfr^p)kiss)ee"
00407B25  |.  E8 269A0000   call a.00411550                          ; \a.00411550

요기 암호화 키 값이 보인다. 간단한 대칭키 암호화 알고리즘이다.


00411550  /$  55            push ebp
00411551  |.  8BEC          mov ebp, esp
00411553  |.  81EC F4000000 sub esp, 0F4
00411559  |.  A1 D8F84200   mov eax, dword ptr ds:[42F8D8]
0041155E  |.  33C5          xor eax, ebp
00411560  |.  8945 FC       mov [local.1], eax
00411563  |.  8B45 08       mov eax, [arg.1]
00411566  |.  56            push esi
00411567  |.  8B75 0C       mov esi, [arg.2]
0041156A  |.  6A 10         push 10
0041156C  |.  50            push eax
0041156D  |.  8D45 DC       lea eax, [local.9]
00411570  |.  50            push eax
00411571  |.  E8 1A2F0000   call a.00414490
00411576  |.  8D8D 74FFFFFF lea ecx, [local.35]
0041157C  |.  51            push ecx
0041157D  |.  8D55 DC       lea edx, [local.9]
00411580  |.  52            push edx
00411581  |.  E8 5AFCFFFF   call a.004111E0
00411586  |.  8D85 0CFFFFFF lea eax, [local.61]
0041158C  |.  50            push eax
0041158D  |.  8D8D 74FFFFFF lea ecx, [local.35]
00411593  |.  51            push ecx
00411594  |.  E8 07FDFFFF   call a.004112A0
00411599  |.  6A 08         push 8
0041159B  |.  8D55 F4       lea edx, [local.3]
0041159E  |.  56            push esi
0041159F  |.  52            push edx
004115A0  |.  E8 EB2E0000   call a.00414490
004115A5  |.  8D85 0CFFFFFF lea eax, [local.61]
004115AB  |.  50            push eax
004115AC  |.  8D4D EC       lea ecx, [local.5]
004115AF  |.  51            push ecx
004115B0  |.  8D55 F4       lea edx, [local.3]
004115B3  |.  52            push edx
004115B4  |.  E8 07FEFFFF   call a.004113C0
004115B9  |.  6A 08         push 8
004115BB  |.  8D45 EC       lea eax, [local.5]
004115BE  |.  50            push eax
004115BF  |.  56            push esi
004115C0  |.  E8 CB2E0000   call a.00414490
004115C5  |.  8B4D FC       mov ecx, [local.1]
004115C8  |.  83C4 40       add esp, 40
004115CB  |.  33CD          xor ecx, ebp
004115CD  |.  5E            pop esi
004115CE  |.  E8 342E0000   call a.00414407
004115D3  |.  8BE5          mov esp, ebp
004115D5  |.  5D            pop ebp
004115D6  \.  C3            retn

여기가 연산 함수다. 대략 bool Decrypt(char *szTime, char *szKey) 형식인듯. 안의 보이는
콜문이 주요 서브함수가 된다.

아 이짓을 다 하려니 끝이 없다. 대략적인 구조를 걍 써보자면,
1) 레지스트리를 검사해서 name Serial ExpDate 등을 찾는다. 없으면 만든다.
2) 시간 계산하여 ExpDate에 8Byte로 암호화를 시켜서 박아넣는다.
3) 현재 시간 구하여 ExpDate를 복호화 한 후 비교한다.
4) 30일이 지나기 전이면 (위 이미지의)첫번째 메시지 박스, 지난 후면 두번째 메시지 박스를 뿌려준다.

대략 저런 구조인데 레지스트리에 각종 중요한 정보를 기록해두는 개발자의 교과서적인
코딩 습관은 그래도 암호화를 해둠으로써 나름 완전 취약한 상태까지는 아니었다. 하지만
이 플그램은 정말 어이없는 취약점이 있다. 점프 코드를 바꿀 필요도, 등록 시리얼 넘버
연산을 긁어서 키젠을 만들 필요도 없었다.

전.역.변.수 하나만 셋팅해주면 땡~

00407300  /$  33C0          xor eax, eax
00407302  |.  833D A80D4300>cmp dword ptr ds:[430DA8], 1
00407309  |.  0F94C0        sete al
0040730C  \.  C3            retn
0040730D      CC            int3
0040730E      CC            int3
0040730F      CC            int3
00407310  /$  C705 A80D4300>mov dword ptr ds:[430DA8], 2
0040731A  \.  C3            retn
0040731B      CC            int3
0040731C      CC            int3
0040731D      CC            int3
0040731E      CC            int3
0040731F      CC            int3
00407320  /$  C705 A80D4300>mov dword ptr ds:[430DA8], 1
0040732A  \.  C3            retn

여기가 바로 그 핵심 루틴이다. 0이면 초기 사용자, 1이면 30일은 지나지 않은 사용자,
그리고 2면 정식 등록자인 것이다 -.-
대략 아래와 같이 짜놓았을 것으로 생각된다.

#define REGISTRATION     2
#define STILL_REGI          1
#define TRIAL                  0

static DWORD dwUser = 0;

if (dwUser == REGISTRATION)
{
    // 정식 등록자처럼 실행해준다
} else if (dwUser == STILL_REGI)
{
   // 30일 어치만 실행해준다
}
else
{
   // 등록하든지 종료하던지 하는 메시지 창 보여준다.
}

이 DWORD 전역변수는 0x430DA8번지에 저장된다. 강 그 번지에 강제로 2를 넣고 실행해보자.

사용자 삽입 이미지


아주 잘 실행될 것이다 :D

(명목상 실행된 화면 캡쳐는 생략 하였습니다)


2007년 5월.




신고
Posted by window31


댓글을 달아주세요

  1. PxxxxCxx 크랙 제목
    2009.05.20 11:50 신고
    댓글 주소 수정/삭제 댓글
    PxxxxCxx 크랙 프로그램 이름 좀 가르쳐주세요-new1soo@naver.com/

BLOG main image
by window31

카테고리

분류 전체보기 (285)
Reverse Engineering (22)
C, C++ (20)
Kernel (8)
Guitar (19)
잡담 (79)
etc (8)
who am i (8)
보안 이야기 (89)
Tools (3)
월간 마이크로소프트웨어/그.. (28)

글 보관함