문제 : Name이 CodeEngn일 때 Serial은 무엇인가

3번과 똑같은 문제다 lstrcmpA함수에 브레이크포인트를 걸고 실행한 뒤 Name에 CodeEngn입력하고 Serial에 임의값 입력한다음 함수내부로 들어가면 string2에 임의의 값이 입력되고, string1에 비교할 값이 나온다. String1에 LOD-59919-A0024900이 정답이다.

1

2

문제 : Name이 CodeEngn일 때 Serial은 무엇인가

1

간단한 문제다 lstrcmpA함수에 브레이크 포인트를 걸고 그 직전에 푸쉬 하는 값만 확인해주면 된다. 임의로 시리얼 값을 12345로 설정 한 뒤 실행해보면 3265754874와 비교한다.

2

문제 : 정답은 무엇인가?

1

일단 파일을 실행해보니 그림 4처럼 도스창에 패스워드를 입력 받는다. 아무 값이나 입력하고 엔터를 눌렀더니 자동으로 종료가 되었다. 별다른 패킹은 되있지 않고, C++로 코딩된 프로그램이다. 패스워드 입력함수 직전에 브레이크포인트를 걸고 패스워드엔 임의로 12345를 넣었다.

2

패스워드를 입력 받고 아래 내용처럼 64번반복하며 이런저런 연산을 하는데 처음엔 이부분이 핵심일 꺼라 생각하고 자세히 확인해 봤지만 그림 5 의 내용만 64번 반복해서 넣고 별다른 일은 인행되지 않은 걸로 판단했다.

3

4

계속 진행하다 004013C5 함수를 실행하면 계속 리턴이 되었고, 해당 함수 내부를 확인해 봤다.

5

보면 12345의 아스키 값들이 그림 5처럼 64개가 들어있는데 그 중 한부분의 31(아스키 정수1) 값을 43과 비교하고있다. 43은 영어 대문자 C의 아스키 값이고 CMP결과로 같지 않으면 리턴 하는 부분으로 바로 점프 하게 된다.

6

7

아래로 총 10번을 이런 식으로 비교,점프를 반복하고있고 매번 반복하는 값들은 “CRAAACKED!” 이다. 앞부분의 64번 반복연산 등은 그냥 함정 정도였던 것 같고 결국 문제는 이 함수를 찾아내서 16진수 아스키 값을 확인하는 문제였다.

43 = C 52 = R 41 = A 41 = A 41 = A 43 = C 4b = K 45 = E 44 = D 21 = !

8

프로그램을 실행해서 CRAAACKED! 를 입력하면 처음에 임의의 수를 입력할 때 와 달리 종료되지 않고 WELL DONE!라는 메시지박스가 출력된다.

9

문제 : 이 프로그램은 몇 밀리세컨드 후에 종료 되는가 정답인증은 MD5해쉬값(대문자)변환 후 인증하시오

실행해보니 처음에 PUSHAD가 보여서 PEiD로 확인해보니 UPX로 패킹 되 있는 프로그램이라서, 먼저 UPX툴로 언패킹을 하고 시작했다.

1

실행 시간 값 구하는 문제라서 sleep과 timegettime 함수들에 브레이크포인트를 걸어주고, 실행했더니, 비정상적으로 리턴하고 다시 진행되다가 그림 2같은 에러창이 떴다.

2

함수목록에서 안티 디버깅 함수중 IsDebuggerPresent를 찾아서 TEST EAX,EAX를 CMP EAX,EAX 로 수정했다. 그럼 Z플래그가 1로세팅되서 0040E969에서 에러 메시지 출력하는 분기점으로 넘어가지 않는다.

3

안티디버깅 해제후 진행을 하니 계속 프로그램이 무한루프에 빠진건지 멈춰버리는 일이 발생했다. 해당 함수를 브레이크포인트 걸고 함수내부를 확인하다 또다시 멈추고 이런 반복을통해 0040eaf9, 0040ea13, 0040b218, 0040bcc0, 00444d3a, 0045E05F, 00444db8, 77D46574 총 7번을 들어가보니 WaitForSingleObject 라는 함수를 발견했다. 그전까지는 메시지박스 관련된 함수들만 나왔는데 처음보는 함수라서 구글에 검색해보니 Thread가 특정 signal이 발생할 떄 까지 정지해 있다가, signal (Exit_event) 을 받으면, 작업을 수행할 때 사용하기 위한 api라고한다. 문제랑은 큰 관련이 없다.

WaitForSingleObject function -Waits until the specified object is in the signaled state or the time-out interval elapses. (출처 MSDN)

timeGetTime함수전체에 브레이크 포인트를 걸고 F9로 실행해버리면 계속 무한루프에 빠저서 천천히 관련 없는 함수를 넘기고 직접 timeGetTime함수가 있는 곳까지 하나하나 진행했다. Basic19에서 밀리세컨즈 구하는 문제랑 비슷하게 timeGetTime함수가 실행된후 ESI값과 EAX값을 비교하고 같지 않으면 EAX에 ESI를 빼고 그 값을 EBX+4 스택에 저장된 값과 비교를한다. Basic에서 푼 문제와 거의 완전히 유사한데 중간중간 프로그램이 멈춰버리는 부분들이 많다.

4

00444c44에서 리턴된 EAX를 ESI에 넣고 00444c59에서sleep후 00444c5f에서 timeGetTime를 실행해서 리턴된 값을 ESI(위에서 리턴된 timeGetTime 값)와 비교해서 00444D38로 점프한다.

5

점프해보면 00444D38에서 기록된 시간값(timeGetTime함수 리턴값) 둘을 빼서 걸린 시간을 연산하고 그후에 EBX+4 스택에 있는 값과 비교를 한다.

00444C44에서 루틴에 들어온 시간을 리턴하고, 00444C59에서 Sleep실행 후 다시 00444C5F를 실행할 때 까지의 시간을 리턴 한 뒤 서로 빼서 걸린 시간을 계산하는 문제다.

6

따라서 EBX+4에 저장된 값 337B 십진수로 바꾸면 “13179” MD5 해쉬값 으로 암호화하면 정답은 “DB59260CCE0B871C7B2BB780EEE305DB” 다

문제 : 이 프로그램은 몇 밀리세컨드 후에 종료 되는가

디버거로 실행시키면 PUSHAD가 보인다. 패킹 된 프로그램 같다. PEiD로 확인해본 결과 그림 21에서 보이듯이 UPX로 패킹 되어 있다.

19-1

19-2

직접 OEP를 찾아서 dump해도 되지만, 덤프따기 귀찮기 때문에 UPX를 이용해서 언패킹을 실행했다.

19-3

일단 프로그램을 실행시키면 그림 창이뜨고 확인을 누르거나 가만히 기다리면 혼자 종료한다. 일단 Exit가 들어가는 함수들과 문제가 몇 밀리세컨드 후에 종료 되는지 물었기에 sleep 함수를 확인했다. ExitWindowsEx는 윈도우 종료관련 API라서 무시했다.

19-4

19-5

일단 Exitprocess 함수 부분을 찾아서 브레이크포인트를 걸고 실행해봤더니,그림 25 같은 에러창이 떠서 안티디버깅 API가 있는지 확인했다.

19-6

함수목록에서 IsDebuggerPresent 를 확인했고 해당부분에 브레이크 포인트를 걸고 실행했다. 그리고 0040E969에서 에러 메시지박스 호출하는 함수로 가는 분기점에 TEST EAX,EAX를 CMP EAX,EAX 로 수정해서 Z플레그가 1이되게 저장했다.

19-7

그리고 다시 실행해보니 Exitprocess는 메시지창이 출력된 후에 확인을 누른후 종료하는 루틴으로 판단되고 sleep도 전부 브레이크포인트를 걸어봤지만, 별다른게 없어서 timeGetTime에 전부 브레이크포인트를 걸어봤다. 그후 실행시키고 브레이크포인트부터 진행하면 2번반복후 0041621E에서 계속 멈추고 재 시작하는 순간 메시지박스가 생기고 사라진다. 반복문 안에서 진행 시간이 어딘가 기록된다 판단하고 그 부분을 찾아봤다.

19-8

반복문이 두 번 실행하는데 그림 27을 보면 00444D3A에서 BTX+4값은 2B70 으로 고정되고 EAX값은 실행시키고 00444D3A까지 내려오는 시간이 기록된다. 그리고 진행하면 99444D4E에서 다시 위로 점프하고 두번째는 00444D3D에서 점프를 실행한 뒤 00444D54에서 끝나는 루틴으로 진행한다.

19-9

실행 하는 동안의 시간 값인 EAX가 EBX+4와 비교되는 것을 봤을 때 해당 값을 정답이라 판단했다. 2B70을 10진수로 바꾸면 11120 코드엔진에 확인한결과 정답이다.

19-10