FindWindow() API는 특정 윈도우 이름이나 클래스 이름을 찾아주는 함수이며, 보통 특정 프로그램이 실행 중인지를 확인 할 때 많이 사용된다.
간혹, 윈도우 이름으로 찾을 때에 특정 프로그램의 윈도우 이름이 Null로 되어 있는 경우가 있기 때문에 윈도우 이름으로 찾는 것보단 클래스 이름으로 찾는 것이 좋다.
MSDN에서는 Findwindow함수를 다음과 같이 구조체를 정의하고 있다.
( http://msdn.microsoft.com/en-us/library/ms633499(VS.85).aspx )
다음은 FindWindow 함수로 클래스 이름 중에 'OLLYDBG'가 있으면, 디버깅 중임을 나타내는 소스이다.
#define _WIND32_WINNT 0x0601 #include <iostream> #include <stdio.h> #include <windows.h>
int check() { char DBG[10] = "OLLYDBG"; int retval; _asm { push 0 lea eax, DBG push eax call dword ptr FindWindowA mov retval, eax } return retval; }
void main() { for (;;) { Sleep(1000);
if ( check() != 0 ) printf("디버깅 당함\n"); else printf("정상\n"); } } |
컴파일 후 실행하면 "정상" 이라는 구분을 확인할 수 있고, OllyDBG에 Attach를 하게 되면 "디버깅 당함"이라는 문구를 확인할 수 있다.
'Search for' -> 'All intermodular calls' 에서 FindWindowA를 찾아보면, 예제 코드에서 작성한 asm 코드 부분을 확인할 수 있다.
아래 보이는 부분은 check() 함수의 전체 부분이며, 중간의 빨간 박스 부분이 바로 asm 코드를 작성한 부분이다.
오른쪽 하단의 박스 부분은 스택에 쌓인 인자 값이 NULL과 OLLYDBG 가 들어가 있는 것을 확인할 수 있다.
FindWindowA 함수는 두 개의 인자 값( ClassName과 WindowName )을 받는다. CALL FindWindowA 함수 호출 전 인자 값을 정의하기 때문에 PUSH 0은 WindowName이 되겠고, LEA EAX, DWORD PTF SS:[EBP-14], PUSH EAX 부분은 ClassName 이다.
이를 우회하는 방법은 OllyDBG의 ClassName을 변경하는 방법이 있지만, 여기에서는 Stack에 들어가는 값을 변경하여 우회하도록 하겠다.
LEA EAX, DWORD PTR SS:[EBP-14], PUSH EAX 의 값을 PUSH 1, NOP, NOP 으로 변경하여 OllyDBG 값을 스택에 넣지 못하도록 한다.
"정상"이라는 구문을 확인 할 수 있다.
