CodeEngn Reversing Basic_Level04

문제 요구사항은 디버거를 탐지하는 함수를 찾으라는 것이다.

일단 그냥 실행해 보자.

정상이라는 문자열이 찍힌다.

올리디버거로 돌리기 전에 간단히 PEiD로 확인해 보았다. [Debug]가 신경쓰이지만, 딱히 패킹은 안 되어있는 듯 하다.

올리디버거로 돌려보자.

디버거로 돌렸을 때의 실행 창이다. 정상 대신 디버깅 당함이라는 문자열이 찍힌다.

우선 “디버깅 당함”과 “정상” 문자열을 찾아봐야겠다는 생각이 든다. 그런데 아무리 봐도 없는 것 같다. 한국어라서 그런가, 무언가 다른 점이 있나? 일단 첫 번째 방법이 잘 안 되었으므로 차선책을 택했다. 메인문을 찾아보자.

콘솔창에 글씨가 뜨는 순간의 함수 call 지점을 F8과 F7을 이용하여 찾는다.

첫 번째로 걸린 Call 여기 breakpoint를 걸고 다시 실행한다. 이 함수에 F7을 이용하여 들어가본다.

방금 함수에 들어가 보니 jmp와 이어져 있다. 그리고 그 jmp를 따라가니 함수 프롤로그가 보인다.

함수를 자세히 들여다 보자. 일단 진행시켜 보았더니, 커서가 멈춰있는 바로 위 줄이 호출되면 “디버깅 당함”문자열이 출력된다. 함수에 push하는 인자를 메모리 덤프에서 찾아보았다.

디버깅 당함 문자열을 찾았다. 저 call이 문자열을 출력하는 함수임이 명백하다.

바로 아래에도 같은 call이 있고, 밑을 침범하지 않도록 jmp가 있는 것을 보아 위쪽에 이 두 상황을 분기하는 점프가 있을거라 예상된다.

위로 올라가 보니 분기문이 있다.

바로 위 test eax, eax를 통해 flag register를 세팅하고, 그 결과에 따라 분기한다. test eax, eax는 eax가 0일 때 zf가 1로 세팅된다.

test 위 수상한 call과 test에 breakpoint를 걸고 다시 한 번 돌려보았다.

F8로 진행시킨 결과 test 위 call은 eax를 변경하지 않는다. 즉 분기에 영향을 끼치지 않는다. 또한 함수 내에 들어가 살펴보니 프로그램 오류를 처리하기 위한 코드로 보인다.

그 위 Call에서 멈춰보았다. 우리는 EAX를 어디서 얻나를 알고싶다.

IsDebugPresent 함수에서 반환값으로 EAX에 1을 넣는다. 우리가 찾는 함수는 바로 이 함수이다. 사실 이 함수는 유명한 함수이며 Anti-Reversing 기법에서 가장 기초적인 기법이다.

그래서 배경지식이 있다면 search for all intermodular calls를 이용하여 바로 찾아낼 수 있다.

위는 MSDN 에 나와있는 IsDebuggerPresent 함수에 대한 설명이다. 디버거에서 도는 것이 아니면 0을, 디버거에서 도는 것이면 0이 아닌 수를 반환한다.

점프를 바꾸거나 없어도 될 것 같은 CMP ESI와 ESP + Call 04.00408210에 적당히 EAX의 값을 0으로 바꾸는 코드를 넣으면 디버깅을 하고 있으면서도 “정상”을 출력할 수 있다.


tags: writeup, reversing, pe file, windows, anti reversing, x86asm