풀이 내용이 문제점이나 개선점이 있다면 댓글 부탁드립니다 .

 

그럼 오늘은 Reversing.kr 의 Easy KeygenMe 문제를 풀어 보겠다 .

 

전형적인 키젠문제 답게 이름과 시리얼을 입력 받고

유효한 시리얼인지 확인하는 프로그램이다 .

 

 

그럼 PEiD 를 통해 패킹이 되어있는지 확인을 먼저 해보겠다.

 

 

위 그림을 보면

비쥬얼 스튜디오 C++ 6.0 으로 컴파일 된 걸 확인했다 .

이미지 베이스와 EP 의 위치 또한 확인 할 수 있다 .

 

 

좀더 자세한 정보를 위해 PE View 를 통해 확인을 해보겠다 .

 

섹션의 개수는 3개이며 각각 text , rdata , data 섹션으로 구성되어 있다 .

Import 테이블에선 임포트 된 함수들이 보인다 .

 

그럼 OllyDBG 로 확인해보겠다 .

 

프로그램의 EP 부분이다 .

밑 부분을 보면 역시나 이 프로그램 또한 작다 보니 성공 실패 문자열이 바로 보인다 .

그럼 이 문자열이 쓰인 곳을 확인 해보자 .

 

위 그림을 보면 네모친 부분에서 EAX 를 확인하고 EAX 가 0이 아니면

실패루틴으로 들어가게 된다.

우린 크랙이 아닌 키젠을 만들어야 하기 때문에

저 부분을 고쳐봐야 키젠은 만들지 못한다 .

그럼 우린 천천히 프로그램을 분석하면서 어떠한 연산을 통해

시리얼을 확인하는지 알아보자 .

 

 

처음 Input Name: 을 푸시하고 Printf 함수를 콜하는 구문 밑부터 보면

ESP+10 ( 12FE58 ) 의 주소를 EAX 에 담고, EAX 를 푸시하는게 보인다 .

그 후 %s 를 푸시한 다음 scanf 를 호출하는 모습이다 .

Scanf("%s", 12FE58)

12FE58 의 주소에 우리가 입력한 이름 문자열을 담는다는 것이다 .

 

또, 표시를 안했지만 401038 부분을 보게되면

BYTE 단위로 10,20,30 의 순서로 값을 집어넣는걸 볼 수 있다.

 

그 다음 부분은 문자열의 길이를 세는 부분이다 .

REPNE 의 경우 0이 아닐 때 계속 무한 반복하게 된다 .

EDI 의 주소의 값이 0이 아니라면 ECX 를 줄여가며 반복하게 되는데

( 트레이싱 도중 F7 버튼을 통해 이동하는걸 확인 할 수 있다 .)

FFFFFFFF 로 세팅 후 REPNE 를 통해 감소된 ECX 값을 보수를 취한 뒤 1을 뺀다 .

그럼 NULL 문자를 제외한 문자열의 길이를 알 수 있다 .

그 다음 문자열의 길이가 0이라면 바로 밑 부분의 반복문을 넘어가 시리얼 입력 부분으로 점프하게 된다.

 

 

우린 저 부분을 건너 뛰기 위한 조건들을 찾아보도록 하겠다 .

 

첫번째로는 바로 위의 그림 처럼

Name 의 입력값이 0이 아닌경우 특정 연산을 건너뛰는걸 확인 할 수 있다.

시리얼 생성의 경우 대부분 입력값에 특정 연산 후 시리얼을 비교하게 되는데,

이 경우 연산을 건너뛰기 때문에 주의해서 보도록 한다.

 

위 그림은 전 그림의 바로 밑의 연산과정을 보여준다 .

이 반복문에서는 EBP 가 반복문의 카운터 역할로 사용되며,

내가 입력한 문자와 10.20.30 중 한 숫자와 XOR 연산을 한 후,

그 밑에 sprintf 함수의 호출로 문자열로 기록 되게 된다 .

2번 스탬프 위치를 보면 sprintf 함수의 인자를 확인할 수 있다.

 

마지막 그림이 좀 크다..

굳이 덤프창을 따로 띄울 필욘 없었는데

막상 찍을 땐 그러한 생각을 하지 못했다..

잡설은 그만하고, 마지막 시리얼 체크 부분의 루틴이다 .

결론 먼저 쓰자면

빨간색으로 칠해진 점프구문들을 전부 뛰어야 한다.

그 후 성공 점프로 넘어가거나, 반복점프를 안뛰거나 해야한다 .

왜 그러한가 보면 먼저 지금 커서가 위치한 401115 위치를 보면

TEST EAX, EAX 이다.

그 후 JNZ 로 점프하면 Wrong 부분으로 점프를 하게 된다.

빨간색으로 네모 쳐진 점프구문 다음 구문을 보면

SBB 가 나오는데 이건 SUB 와 비슷한 명령어이다.

SUB와 다른건 케리 플러그를 더해서 사용하느냐 안하느냐 차이이다.

SBB EAX, EAX

SBB EAX, -1

즉 케리 플래그가 0이던 1이던

FFFFFFFF or FFFFFFFE 가 나오게 된다 .

그런고로 마지막 점프구문에서 Wrong 으로 점프하게 된다.

 

그럼 파란색으로 쳐진 점프를 보면

XOR EAX,EAX 로 레지스터를 0으로 초기화 한 후

POP EDI 부분인 40110E 로 점프하게 된다.

그 후 우리가 원하는 Correct ! 의 메시지를 출력 할 수 있게 된다.

 

 

 

자 그럼, 우린 시리얼에 대한 연산루틴 과정을 전부 알아 내었으니,

이름 -> 시리얼에 대한 문제는 해결 해내었다.

하지만, 이 문제에서 원하는 답은

5B134977135E7D13 의 이름이 누구인가? 를 찾는 문제이다.

간단하게만 보자면 XOR 연산은 특정값을 다시 연산하면

원본 값이 나오게 된다 .

이게 무슨 소리인고? 하니 간단한 예제를 보도록 하겠다 .

 

0x10 ^ 0x20 = 0x30

( 여기서 ^ 는 XOR 를 의미한다. )

 

그럼 여기서 특정 키값을 다시 연산하면 다른 키 값이 나오게 된다.

0x30 ^ 0x10 = 0x20

0x30 ^ 0x20 = 0x10

 

이제 감이 좀 오는가?

그럼 우린 XOR 부분에 어떠한 값을 가지고 연산하는지 알고 있기 떄문에

해당 값을 알아낼 수 있다 .

0x5B ^ 0x10 = 0x4B

0x13 ^ 0x20 = 0x33

. . . .

이 경우 하나하나 역연산을 통해 시리얼을 알아낼 수 있지만,

좀 더 복잡한 루틴의 경우 일일이 계산해가며 하기가 힘들기 때문에..

( 불가능하다곤 하지 않겠다 …)

간단한 프로그램을 만들어 해당 시리얼의 이름을 알아내보자.

내 허접한 소스라도 공개하도록 하겠다.

풀이를 보고 이 문제를 접했다면 프로그램 정도는 혼자 구현해보도록 하자


예제 소스 보기




'WarGame > Reversing' 카테고리의 다른 글

Reversing.kr – MusicPlayer 풀이  (1) 2015.11.01
Reversing.kr – Easy CrackMe 풀이  (0) 2015.10.29

+ Recent posts