티스토리 뷰
이번 글 에서는 MFC기반의 프로그램인..
내다이어리를 크렉하는 방법을 알아 보겠습니다.
먼저 대상 프로그램인 내다이어리를 실행하여 봅시다.
내다이어리를 실행하면 정식 사용자 등록창 부터 나오는군요.
돈이 많이 궁한 모양입니다.
자 우리는 "등록 번호 입력" 버튼을 눌러 봅시다.
등록 번호 입력 창이 뜨는데 등록번호 창에는
아무키나 입력 하고 "등록" 버튼을 눌러 봅시다.
우리들이 사랑하는 에러 메시지가 역시 나와주는군요
이 메시지를 잘 기억해 두시고, 이제 분석을 시작하죠
먼저 W32Dasm으로 내다이러리 파일을 역어셈블 해옵시다.
역어셈블이 완료 됬으면 이제 String Ref에서 아까 보았던
에러 메시지[등록 번호가 올바르지 않습니다.]를 찾아 봅시다.
찾았으면 이제 더블클릭해서 이 스트링을 참조하는곳으로 가보죠.
커헉! 오긴 왔지만 MFC 원형으로 도배가 되있군요.
이래선 뭐가 무슨 함순지 알수가 없습니다.
현재 주소 0x440BB2 를 잘 기억 하시고 이제
대상 파일을 IDA로 역어셈블 하여 옵시다.
역어셈블이 완료되어서 IDA에 자료가 표시되면
"G" 버튼을 눌러서 Jump to address 창을 띄워 봅시다.
창이뜨면 Jump address 란에 아까 기억해둔 주소인
0x440BB2를 적고 OK 버튼을 눌릅시다.
W32Dasm으로 역어셈블 했을때는 MFC 원형의
도배 였지만 지금 IDA로 역어셈블 하니....
무슨 함수 인지 잘 보이는군요.
0x440B68 부터 중요한 부분을 해석해 가며 보죠
:00440B68 E8951D0B00 Call GetDlgItem ;핸들을 구해온다.
:00440B6D 8BC8 mov ecx, eax ;결과를 ecx에 넣는다.
:00440B6F E8761A0B00 Call GetWindowTextA ;텍스트를 구해온다.
:00440B74 8D4C2404 lea ecx, dword ptr [esp+04] ;ecx의 값을 [esp+0x4]의 값으로
:00440B78 Call TrimLeft ;뭘까? EAX의 값이 우리가 입력한값이됨
:00440B7D lea ecx, [esp+4] ;ecx의 값을 [esp+0x4]의 값으로
:00440B81 Call TrimRight EAX와 ECX가 우리가 입력한 값이됨
:00440B8F 51 push ecx ;우리가 입력한값을 스택에 넣음
---------------------------------------------------------------------------------
0x440B78 ~ 0x440B8A 까지는 입력된 키를 대문자로 만듬.
---------------------------------------------------------------------------------
:00440B8F 51 push ecx ;대문자화된 값을 스택에 넣는다.
:00440BA2 E859000000 Call 0x00440C00 ;키 체크 루틴 <======================중요
:00440BA7 85C0 test eax, eax ;eax 를 테스트 하여 본다.
:00440BA9 6A00 push 00000000 ;스택에 0을 넣는다.
:00440BAB 68FC605300 push 005360FC ;다이얼로그의 제목
:00440BB0 750E jne 0x00440BC0 ;테스트 결과가..(Zero 플래그가 0이 아니면) 점프
:00440BB2 68DC605300 push 005360DC ;스택에 "등록 번호가 올바르지 않습니다." 넣음
:00440BB9 E8561D0B00 Call MessageBoxA ;메시지창 띄움
:00440BBE EB13 jmp 0x00440BD3 ;점프
-----------------------------------------------------------------------------------
자 우리는 윗부분에서 0x440BA2 에서 키 체크 루틴을 콜 하는것을 볼수 있습니다.
그럼 이제 키 체크 루틴인 0x440C00 부분을 분석하여 보죠
-----------------------------------------------------------------------------------
:00440C31 83F91B cmp ecx, 0000001B ;우리가 입력한 값이27자인가?
:00440C34 0F85E5010000 jne 00440E1F ;아니라면 점프
:00440C3A 8A4809 mov cl, byte ptr [eax+09] ;10번쨰 글자가 가져와서 CL에 넣는다.
:00440C3D 80F92D cmp cl, 2D ;10번쨰 글자가 하이푼(-) 인가?
:00440C40 0F85D9010000 jne 00440E1F ;하이푼이 아니라면 점프
:00440C46 8078122D cmp byte ptr [eax+12], 2D ;19번쨰 글자가 하이푼(-) 인가?
:00440C4A 0F85CF010000 jne 00440E1F ;아니라면 점프
-------------------------------------------------------------------------------------
:00440C67 8A10 mov dl, byte ptr [eax] ;eax의[우리가입력한] 첫번쨰 글자를 dl에 넣는다.
:00440C69 8A1E mov bl, byte ptr [esi] ;esi의 첫번쨰 글자를 bl 에 넣는다.
:00440C6B 8ACA mov cl, dl ;dl(첫번쨰 글자)를 cl에 복사해둔다.
:00440C6D 3AD3 cmp dl, bl ;dl과 bl 비교
:00440C6F 751E jne 00440C8F ;같지 않다면 점프
:00440C71 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0인가?
:00440C73 7416 je 00440C8B ;그렇다면 점프
------------------------------------------------------------------------------------
:00440C75 8A5001 mov dl, byte ptr [eax+01] ;eax의[우리가입력한] 두번쨰 글자를 dl에 넣는다.
:00440C78 8A5E01 mov bl, byte ptr [esi+01] ;esi의 두번쨰 글자를 bl 에 넣는다.
:00440C7B 8ACA mov cl, dl ;dl(두번쨰 글자)를 cl에 복사해둔다.
:00440C7D 3AD3 cmp dl, bl ;dl과 bl 비교
:00440C7F 750E jne 00440C8F ;같지 않다면 점프
:00440C81 83C002 add eax, 00000002 ;eax의 앞에 2글자를 지움[바꿈]
:00440C84 83C602 add esi, 00000002 ;esi의 앞에 2글자를 지움[바꿈]
:00440C87 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0 인가?
:00440C89 75DC jne 00440C67 ;아니라면 0x440C67로 다시 돌아감
------------------------------------------------------------------------------------
:00440C8B 33C0 xor eax, eax ;eax를 0으로 초기화
:00440C8D EB05 jmp 00440C94 ;0x440C94로 점프
------------------------------------------------------------------------------------
:00440C94 3BC7 cmp eax, edi ;eax와 edi를 비교한다. [둘다 0 이다.]
------------------------------------------------------------------------------------
:00440CA2 84DB test bl, bl ;bl을 테스트 한다.
:00440CA4 0F8575010000 jnz 00440E1F ;0이 아니면 점프
------------------------------------------------------------------------------------
:00440D68 8A5C3410 mov bl, byte ptr [esp+esi+10] ;bl에 esp+esi+10의 값을 가져온다.
:00440D6C 8D4C2414 lea ecx, dword ptr [esp+14] ;ecx에 값을 esp+14으로 만든다.
:00440D70 8AC3 mov al, bl ;bl의 값을 al에 복사해둔다.
:00440D72 C0E804 shr al, 04 ;al을 4로 나눈다.
:00440D75 0444 add al, 44 ;al에 44를 더한다.
:00440D77 50 push eax ;eax의 값을 스택에 집어넣는다.
:00440D78 E8C5170B00 Call YCString ;아이돈노
:00440D7D 81E3FF000000 and ebx, 000000FF ;ebx를 FF와 and 연산
:00440D83 81E30F000080 and ebx, 8000000F ;ebx를 8000000F와 and 연산
:00440D89 7905 jns 00440D90 ;싸인 플레그가 셋되지 않았으면 점프
:00440D8B 4B dec ebx ;ebx값 1 감소
:00440D8C 83CBF0 or ebx, FFFFFFF0 ;ebx를 FFFFFFF0와 or 연산
:00440D8F 43 inc ebx ;ebx를 1 증가 시킴
:00440D90 80C344 add bl, 44 ;bl의 값을 44증가 시킴
:00440D93 8D4C2414 lea ecx, dword ptr [esp+14] ;ecx에 값을 esp+14으로 만든다.
:00440D97 53 push ebx ;ebx의 값을 스택에 집어넣는다.
:00440D98 E8A5170B00 Call YCString ;아이돈노
:00440D9D 46 inc esi ;esi의 값을 1 증가 시킴
:00440D9E 83FE04 cmp esi, 00000004 ;esi를 4와 비교한다.
:00440DA1 7CC5 jl 00440D68 ;작다면 0x440D68로 다시 돌아감
------------------------------------------------------------------------------------
:00440DAA 8A10 mov dl, byte ptr [eax] ;dl에 eax[우리가입력한키]의 첫번쨰 글자를 넣는다.
:00440DAC 8A1E mov bl, byte ptr [esi] ;bl에 esi의 첫번쨰 글자를 넣는다.
:00440DAE 8ACA mov cl, dl ;dl(첫번째 글자)를 cl에 복사해둔다.
:00440DB0 3AD3 cmp dl, bl ;dl 과 bl 비교
:00440DB2 751E jne 00440DD2 ;같지 않으면 점프
:00440DB4 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0 인가?
:00440DB6 7416 je 00440DCE ;0 이면 점프???
------------------------------------------------------------------------------------
:00440DB8 8A5001 mov dl, byte ptr [eax+01] ;dl에 eax의 두번쨰 글자를 넣는다.
:00440DBB 8A5E01 mov bl, byte ptr [esi+01] ;bl에 esi의 두번쨰 글자를 넣는다.
:00440DBE 8ACA mov cl, dl ;dl(첫번째 글자)를 cl에 복사해둔다.
:00440DC0 3AD3 cmp dl, bl ;dl 과 bl 비교
:00440DC2 750E jne 00440DD2 ;같지 않으면 점프
:00440DC4 83C002 add eax, 00000002 ;eax의 앞에 2글자를 지움[바꿈]
:00440DC7 83C602 add esi, 00000002 ;esi의 앞에 2글자를 지움[바꿈]
:00440DCA 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0 인가?
:00440DCC 75DC jne 00440DAA ;아니라면 0x440DAA로 다시 돌아감
------------------------------------------------------------------------------------
우리는 키체크루틴의 분석을 완료 했으니 우리는
우리의 등록번호를 뽑아낼수 있습니다.
음 과연 어디서 등록번호를 얻을수 있을까요?
위의 코드 분석을 잘 보시면 알수 있습니다.
저는 밑의 코드들이 실질적인 등록번호 체크 루틴
일껏이라고 짐작(?) 하여 봅니다.
---------------------------------------------------------------------------------
:00440C31 83F91B cmp ecx, 0000001B ;우리가 입력한 값이27자인가?
:00440C34 0F85E5010000 jne 00440E1F ;아니라면 점프
:00440C3A 8A4809 mov cl, byte ptr [eax+09] ;10번쨰 글자가 가져와서 CL에 넣는다.
:00440C3D 80F92D cmp cl, 2D ;10번쨰 글자가 하이푼(-) 인가?
:00440C40 0F85D9010000 jne 00440E1F ;하이푼이 아니라면 점프
:00440C46 8078122D cmp byte ptr [eax+12], 2D ;19번쨰 글자가 하이푼(-) 인가?
:00440C4A 0F85CF010000 jne 00440E1F ;아니라면 점프
-------------------------------------------------------------------------------------
:00440C67 8A10 mov dl, byte ptr [eax] ;eax의[우리가입력한] 첫번쨰 글자를 dl에 넣는다.
:00440C69 8A1E mov bl, byte ptr [esi] ;esi의 첫번쨰 글자를 bl 에 넣는다.
:00440C6B 8ACA mov cl, dl ;dl(첫번쨰 글자)를 cl에 복사해둔다.
:00440C6D 3AD3 cmp dl, bl ;dl과 bl 비교
:00440C6F 751E jne 00440C8F ;같지 않다면 점프
:00440C71 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0인가?
:00440C73 7416 je 00440C8B ;그렇다면 점프
------------------------------------------------------------------------------------
:00440C75 8A5001 mov dl, byte ptr [eax+01] ;eax의[우리가입력한] 두번쨰 글자를 dl에 넣는다.
:00440C78 8A5E01 mov bl, byte ptr [esi+01] ;esi의 두번쨰 글자를 bl 에 넣는다.
:00440C7B 8ACA mov cl, dl ;dl(두번쨰 글자)를 cl에 복사해둔다.
:00440C7D 3AD3 cmp dl, bl ;dl과 bl 비교
:00440C7F 750E jne 00440C8F ;같지 않다면 점프
:00440C81 83C002 add eax, 00000002 ;eax의 앞에 2글자를 지움[바꿈]
:00440C84 83C602 add esi, 00000002 ;esi의 앞에 2글자를 지움[바꿈]
:00440C87 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0 인가?
:00440C89 75DC jne 00440C67 ;아니라면 0x440C67로 다시 돌아감
------------------------------------------------------------------------------------
:00440DAA 8A10 mov dl, byte ptr [eax] ;dl에 eax[우리가입력한키]의 첫번쨰 글자를 넣는다.
:00440DAC 8A1E mov bl, byte ptr [esi] ;bl에 esi의 첫번쨰 글자를 넣는다.
:00440DAE 8ACA mov cl, dl ;dl(첫번째 글자)를 cl에 복사해둔다.
:00440DB0 3AD3 cmp dl, bl ;dl 과 bl 비교
:00440DB2 751E jne 00440DD2 ;같지 않으면 점프
:00440DB4 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0 인가?
:00440DB6 7416 je 00440DCE ;0 이면 점프???
------------------------------------------------------------------------------------
:00440DB8 8A5001 mov dl, byte ptr [eax+01] ;dl에 eax의 두번쨰 글자를 넣는다.
:00440DBB 8A5E01 mov bl, byte ptr [esi+01] ;bl에 esi의 두번쨰 글자를 넣는다.
:00440DBE 8ACA mov cl, dl ;dl(첫번째 글자)를 cl에 복사해둔다.
:00440DC0 3AD3 cmp dl, bl ;dl 과 bl 비교
:00440DC2 750E jne 00440DD2 ;같지 않으면 점프
:00440DC4 83C002 add eax, 00000002 ;eax의 앞에 2글자를 지움[바꿈]
:00440DC7 83C602 add esi, 00000002 ;esi의 앞에 2글자를 지움[바꿈]
:00440DCA 84C9 test cl, cl ;cl(dl을 복사해둔값)이 0 인가?
:00440DCC 75DC jne 00440DAA ;아니라면 0x440DAA로 다시 돌아감
---------------------------------------------------------------------------------
그렇다면 어떡해 해야 등록번호를 얻을수 있을까요?
:00440C31 ~ :00440C4A 까지 문자열의 길이라던가
하이푼(-) 여부를 체크 함으로 우리가 등록번호란에
"NDIARYKEY-XXXXXXXX-XXXXXXXX" 이라고
입력해주어야 합니다. 위와 같이 입력 해주면
440C31 ~ 440C4A 까지는 통과 할수 있습니다.
그다음 문제는 바로 00440C67 ~ 00440C89 인데
첫번쨰 하이푼 앞의 글자가 NDIARYKEY 인지 아닌지
체크 하는 부분임으로 이부분역시 통과 될것입니다.
이제 남은 문제는 두번쨰 하이푼과 세번쨰 하이푼
앞의 입력값을 체크 하는 부분인데 제작자가 게을러서 인지
체크루틴이 하나군요. [게으른놈~]
00440DAA ~ 00440DCC 까지 인데........
00440DA3에 디버거를 이용하여 브레이크 포인트를 걸어 둔후
이 지점에 브레이크가 걸리고 나서 이 줄을 실행 시키면
ESI에 올바른 등록번호가 나타나는것을 보실수 있습니다.
두번쨰 하이푼 앞의 번호와 세번쨰 하이푼 앞의 번호를
전부 여기서 체크 함으로 브레이크 포인트는 두번 걸리게 됩니다.
첫번쨰 걸릴때의 ESI에 값이 두번쨰 하이푼 앞의 값이고
두번쨰 걸릴떄의 ESI에 값이 세번쨰 하이푼 앞의 값입니다.
저는 설치 번호 : "NDIARY20-FF154530-2F0331CA" 에 대한...
등록 번호 : "NDIARYKEY-FSJRKQQK-HSFQIPPG"를 얻을수 있었습니다.
각자의 키를 잘 알아 내보시기 바랍니다.
금방 뽑아내실수 있을 겁니다. 그럼 이번글은 여기서 마치죠
'Reverse Engineering' 카테고리의 다른 글
Tutorial 7 - abex's Crack Me 솔루션 (0) | 2008.01.11 |
---|---|
Tutorial 6 - Dede를 이용한 Icon Grabber 2.1v 크랙하기 (0) | 2008.01.11 |
Tutorial 4 - StringReference를 이용한 010 Editor 1.3v 크랙하기 (2) | 2008.01.11 |
Tutorial 3 - W32Dasm 살펴보기 (0) | 2008.01.11 |
Tutorial 2 - 리버스 엔지니어링을 위한 기초 지식 (2) | 2008.01.11 |
- Total
- Today
- Yesterday
- svn
- c언어
- 멀티스레드
- TDD
- ruby
- EzShortcut
- 좋은 프로그래머
- 게임개발포에버
- 루비 온 레일즈
- ftp
- CppSQLite
- SDL
- Ruby on Rails
- 조엘 온 소프트웨어
- 루비
- 디자인 패턴
- RoR
- SQLite Spy
- 게임데브포에버
- 임백준
- TraceRoute
- MS-SQL
- 바로가기 프로그램
- 디버깅
- Rails
- NDC2013
- EasyExec
- perfmon
- 리버스 엔지니어링
- 엘키
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |