본문 바로가기

My Study/Programming&Theory

BlockInput Function

BlockInput이라는 함수가 있다. 
msdn의 친절한 설명을 봐보면..

Blocks keyboard and mouse input events from reaching applications. 
그냥 키보드와 마우스의 입력 이벤트를 막는다고 되어 있다.

하지만 유일하는 먹히는 키 조합.. Ctrl + Alt + Del 키를 누르면 풀린다.
음.. 그래도 저 키조합도 막을 수 있는 방법을 구글에 찾아보면 소스코드도 포함된 글이 많다~

해당 함수는 인자로 BOOL 값을 하나 받는데.. 1이면 block하는 것이고 0이면 unblock하는 것이다.
Anti Reversing 기법으로 사용되는 함수이기도 하는데 밥 먹고 소화겸 어떻게 작동하는지 분석을 해보았다.


아 참고로.. 위 테스트 환경은 Windows XP SP3 이다.

user에서 BlockInput 함수를 호출하면 커널에서는 NtUserBlockInput 함수를 호출하게 된다.
딱 봐도 중요한 함수는 _BlockInput 함수 같다. 앞뒤로 있는 EnterCrit, LeaveCrit 함수는 저 부분을 감싸고 있는 걸로봐선 임계영역을 위한 함수들 같다. 함수 명만봐도..ㅋ

일단 _BlockInput 함수를 봐보자.

그렇게 길지도 않다.

일단 빨간색 네모 친 부분을 잘 보면 된다.

파란색 네모 친 부분에서는 gptiBlockInput 변수가 0인지 체크를 한다. 즉 현재 블록 상태인지 아닌지를 체크한다.
0이 라면 블록 상태가 아니라는 뜻이므로 보라색 명령어가 실행이되면서 esi에 있는 값이 들어간다.
그 값은 (0xe1df1008) 값이다. 하지만 저 값이 항상 일정하지는 않는 듯 싶다. 여러번 해보니 값이 바뀌는 것 같다.

아무튼 무슨 값이 gptiBlockInput 변수로 들어간다는 것이다.

하지만 gptiBlockInput 값이 0이 아니라면 분홍색 네모 친 부분이 실행된다. 먼저 esi와 비교를 하는데 같으면 그 아래 있는 분홍색 명령어를 실행함으로써 gptiBlockInput 변수 값을 0으로 만든다. 다를 경우에는 그냥 종료를 하게된다. 무슨 뜻이냐면 이미 블록이 풀려버렸다는 뜻이다. 왜..? Ctrl + Alt + Del 키를 눌러서 미리 풀어버린 경우에 저렇게 된다.

일단 gptiBlockInput 변수에 들어가는 값에 따라 블록이 되고 안되고가 결정이 된다.
그러면 그냥 커널에서 저 값을 강제로 바꿔보면??..


-_-;;;;;;;;; 바꾸려고 봤더니 변수가 사라졌다... 또한 NtUserBlockInput 함수도 메모리에 존재하지 않는다.

이유는 윈도우에는 nt함수를 위한 user 함수를 위한 각각의 ServiceTable이 있는데
nt함수들은 KiServiceTable에 있고 user함수들은 W32pServiceTable에 있다.

아래는 각 모듈 정보 

kd> !address kiServiceTable
  804d9000 - 001f9000                           
          Usage       KernelSpaceUsageImage
          ImageName   ntkrnlpa.exe

kd> !address W32pServiceTable
  bf800000 - 001c3000                           
          Usage       KernelSpaceUsageImage
          ImageName   \SystemRoot\System32\win32k.sys


또한 분석을 해보면 KiServiceTable은 항상 메모리에 올라와 있지만 W32pServiceTable는 W32pServiceTable 내부 함수가 호출될 경우에만 메모리에 올라온다.
 

이와 같이..;;

그래서 W32pServiceTable 가 메모리에 올라왔을 경우 gptiBlockInput 변수에 접근할 수 있는데 그 때 값을 바꿔주니
BlockInput 함수를 호출하지 않아도 똑같은 동작은 내 맘대로 제어할 수 있었다.

그러면 커널에서는 저 값을 어디서 사용하는 것일까? 당연히 키보드와 마우스의 이벤트를 막는 역할을 할 것이다.
한번 하드웨어 브포를 걸어놓고 살펴보자.

WinDbg에서
ba r4 gptiBlockInput
이와 같이 하면 해당 변수에 4Byte read 시 BP가 걸리게 된다.

어디서 멈췄을까요? 
win32k!ProcessMouseInput 함수에서 멈췄습니다. 처음 부분을 봐보죠.


gptiBlockInput 변수가 0인지 비교를 하고 0이 아니라면 0xbf886745 로 점프를 하게 됩니다.
 

가보면 그냥 함수 에필로그 부분인 것을 알 수 있습니다.

즉, 처음에 블록 상태를 나타내는 변수를 검사 후 0이 아닌 값이 있으면 그냥 이벤트 수행 루틴을 건너 뛰어버리는 것 입니다.
참 변수를 직관적으로 잘 사용하고 있군요.

키보드 같은 경우도 봐보겠습니다.

xxxKeyEvent 함수에서 해당 변수에 접근을 하고 있고 저 부분에서 0인지 아닌지 검사를 하게 됩니다.
0이라면 test 명령어이기 때문에 and 연산 후 값이 0이므로 점프하지 않습니다. 0 이 아닌 경우 점프를 하게 되겠죠.
점프 했을 경우엔... 뭐 위와 비슷하게 처리루틴이 아닌 다른 루틴으로 가겠지요..;

결론.................. BlockInput 함수.. 이렇게 작동합니다. .ㅎㅎ 허무..; 

'My Study > Programming&Theory' 카테고리의 다른 글

Windows rand() 랜덤 비율  (2) 2012.02.14
ARM 명령어 공부  (6) 2012.01.27
My BSOD  (2) 2012.01.08
SwapContext를 이용한 프로세스 찾기  (7) 2012.01.04
Remote Library Injection  (4) 2011.12.29