이번에는 PEiD 가 아닌 exeinfope 라는 툴로 살펴보겠습니다.
http://www.exeinfo.xn.pl/ 사이트인데 접속이 안되네요. 아래에 파일 올려놓았습니다.
Autoit으로 프로그래밍했고 upx 패킹이 되어있네요. Autoit은 스크립트언어의 일종입니다. 배우기 쉽데요. ㅋ
참고로 autoit 은 자체적으로 upx 패킹을 지원합니다. 올리디버거로 직접 언패킹을 하려 했지만 지식과 경험의 부족으로
툴을 사용하였습니다. 어떤 분이 autoit으로 upx 툴을 만드셨더라구요. http://blog.naver.com/seongwk/70122005613 여기서 받으실 수 있습니다. 못 받으시는 분들은...역시 아래에 파일을 올렸습니다.
이제 문제 풀이에 들어가겠습니다. 먼저 언패킹을 해주세요.
언패킹이 끝나면 이제 올리디버거를 이용해 문제를 풉니다. 올리디버거로 열어 실행을 해보면 에러가 뜹니다.
이 오류가 뜨는 이유는 안티 디버깅이 설정되어 있기 때문입니다. 사용하는 함수는 IsDebuggerPresent 입니다.
이는 올리디버거의 플러그인 중에 Olly Advanced 에서 우회가 가능합니다.
이 함수의 코드를 보고 싶은 분은 코드창 -> 마우스 우클릭 -> Search for -> All intermodular calls 혹은 Name (label) in current module(Ctrl + N) 을 클릭합니다. 그 후에 IsDebuggerPresent를 입력하여 해당 함수를 찾습니다. BreakPoint를 설정하고 실행하면 IsDebuggerPresent에서 멈추는 데 안으로 들어가서 JMP로 분기를 하고나면 다음과 같은 코드가 보입니다.
PE구조에 대해서는 자세히 모르지만 구글신과 네이년의 도움으로 찾은 내용을 말씀드리자면
- FS 레지스터에서 오프셋 0x18 에 있는 TIB(Thread Information Block) 의 주소를 EAX에 저장합니다.
- TIB 에서 오프셋 0x30에 있는 PEB(Process Environment Block)의 주소를 EAX에 저장합니다.
- PEB 에서 오프셋 0x2 에 있는 BeingDebugged 의 값을 EAX 에 저장합니다.
- 이 값이 1인 경우 디버거를 사용 중이라는 뜻입니다.
- 아래는 올리디버거로 해당 값을 확인한 모습입니다.
계속해서 문제를 풀어보겠습니다. 위와 같은 방법으로 창을 열어 timegettime 함수를 찾습니다.
Name (label) in current module 창
All intermodular calls 창
Timegettime 함수는 http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629%28v=vs.85%29.aspx 여기서 확인하실 수 있습니다.(한글페이지가 없어서 영어로 뜨네요….)
간단히 설명하면 시스템의 시간을 milliseconds로 가져오는 함수입니다. 위에서 처럼 BreakPoint를 지정한 후 실행을 하면 CALL EDI 부분에서 멈추는 걸 볼 수 있습니다.
차례대로 분석해나가시면 timegettime 함수의 주소를 EDI 에 저장한 후
CALL EDI 를 통해 함수를 호출하고 있습니다. 제일 처음의 결과는 ESI 레지스터에 옮겨놓은 후 다시 호출하여 비교한 후
JNB(Jump if Not Below, CF가 0인 경우 분기)를 통해 분기할지 결정합니다. 즉, 나중에 받은 값이 크거나 같으면 분기하는 군요. 분기한 곳으로 이동해서 계속 분석합니다.(JNB에서 Enter만 치면 됩니다.)
분기한 곳의 코드들입니다. EAX와 ESI의 차를 구한 후 [EBX+4]에 저장된 4byte의 값과 비교한 후 JNB를 이용하여 분기를 결정하고 있습니다. 아래에 있는 JNZ에서 분기를 하면 다시 시간을 받아오는 군요. 즉 EBX+4의 값이 우리가 원하는 시간임을 유추할 수 있습니다. CMP EAX, DWORD PTR DS:[EBX+4] 에 BreakPoint를 걸고 실행합니다.
이 값으로 인증을 하면 문제는 풀립니다.