Windows OS에서 특정 윈도우의 클립보드 값을 얻어오고 변경해보는 소스코드를 분석해보았습니다.

OS 내부적으로 클립보드를 어떻게 처리하는지 대충이라고 알고 싶어서 시작해보았습니다.



위는 테스트 한 소스코드입니다. "test1234" 를 클립보드에 넣어둔 상태에서 저 프로그램을 실행하면 결과는 다음과 같습니다.


test1234

Ezbeat ^-^


가 됩니다.

이제 한줄 한줄 분석해보겠습니다. ( 써놓고 보니 자세히는 아닌... ㅠ )

( 모든 분석은 Windows 7 x86 에서 진행되었고 reactOS 소스코드를 참고하면서 진행하였습니다. )


1. OpenClipboard(NULL)

MSDN 설명을 보니 

클립보드를 열고 다른 어플리케이션이 클립보드 수정하는 것을 막아준다고합니다.

인자가 NULL이 들어가면 현재 작업과 관계되어 있는 클립보드를 연다고 되어 있습니다.

무슨 말인지 모르겠지만 내부를 분석해보도록 하겠습니다.


OpenClipboard를 호출하면 내부적으로

ntdll.dll에선 ZwUserOpenClipboard 를 호출하고 kernel에선 win32k ! NtUserOpenClipboard 를 호출하게 됩니다.


NtUserOpenClipboard에선 주요하게 호출되는 함수는 총 3개입니다.

 - win32k ! UserEnterUserCritSec

구글에도 정보가 거의 없네요. 그래도 변수명과 함수명으로 유추를 해보면 

리소스를 사용하는데 있어서 독점하기 위해 준비하는 작업같네요. 크리티컬 섹션은 보통 같은 프로세스내에서 전역변수 같이 공유하는 변수의 동기화를 위해 사용됩니다. 이와 비슷한 작업 같습니다. 딱봐도 그런거같죠?

갈길이 바쁘니 그냥 고고..


win32k!UserEnterUserCritSec: 어셈코드

push    dword ptr [win32k!gpresUser]

call    dword ptr [win32k!_imp__ExEnterPriorityRegionAndAcquireResourceExclusive]

mov     dword ptr [win32k!gptiCurrent],eax

mov     byte ptr [win32k!gbValidateHandleForIL],1

ret


 - win32k ! _OpenClipboard

이 함수가 주요 함수겠지요.

내부적으로 윈도우 스테이션을 사용하는데요.

현재 스레드에 맞는 윈도우 스테이션을 가져와 현재 스레드의 클립보드 락이 걸려 있는지 확인하고(ptiClipLock확인)

안걸려 있다면 ptiClipLock 에 현재 스레드의 Win32Thread 값을 넣습니다.


 - win32k ! UserSessionSwitchLeaveCrit

위 UserEnterUserCritSec 함수와 대응되는 함수입니다. 리소스에 락을 걸어줬으니 다시 풀어줘야겠지요.


내부적으로도 쫌 복잡하지만 대충 코드보고 말로만 적어봤습니다.

결국 OpenClipboard가 하는 역할은 클립보드를 사용하기 위해 현재 윈도우 스테이션의 ptiClipLock 인자에 값을 셋팅하면서 락을 걸어주는 것입니다. 저번 포스팅에서 설명한적이 있지만 기본적으로 윈도우는 현재 로그인된 세션에서 입출력을 위한 WinSta0 스테이션을 하나 갖는다고 하였습니다. 이 스테이션 내부적으로 사용자의 입출력을 담당하는 디폴트 데스크탑, winlogon 데스크탑 등등이 있죠. 하지만 저 스테이션을 관리하는 커널 오브젝트 내부의 클립보드 관련 멤버변수가 락이 걸렸습니다. 그러므로 특정 데스크탑 혹은 프로세스에서 클립보드를 사용하려고 OpenClipboard를 사용해도 성공하지 못할 것입니다.

실제로 특정 프로세스에서 OpenClipboard를 호출하고나서 프로그램을 멈춘상태로 놔두고 다른 프로세스에서 복사 붙혀넣기 기능을 사용하려고해도 안되더군요. 실제로 해보세요 :D


찾아보니 누가 글 써놓은게 있군요.

http://hi.baidu.com/warptencq/item/6228accd8a8c5a0b0bd93a67


winsta0,session,desktop,winlogon,default..txt


첫 문장에 딱 나와있습니다. 약간의 발번역을 하겠습니다..

윈도우 스테이션은 클립보드, global atom 집합, 데스크톱 오브젝트 그룹을 포함합니다. 각 세션마다 하나씩 있는 윈도우 스테이션은 유저와 상호작용을 할 수 있도록 합니다. 윈도우 스테이션 이름은 "Winsta0" 입니다. ... 쭉쭉..

아무튼 윈도우 스테이션은 클립보드를 포함한다는 것! 그리고 코드에도 실제 저렇게 나온다는 것!

단순히 생각했는데 윈도우 스테이션에 들어가 있다니.. 뭔가 분석이 복잡해 질 것 같습니다 ㅠㅠ


OpenClipboard 하나만 해도 쫌 기네요. 짧게 해보려고 했는데 어쩔수 없습니다.


시간 날 때마다 조금씩 봐봐야겠네요. 최종 목적은 클립보드를 이용해 어떠한 재미난 일을 할 수 있을지 알아보는 것입니다. 안되면 말구요;;ㅠㅠ


다음 번엔 GetClipboardData 함수를 알아보겠습니다. 옵션은 CF_TEXT만...

Posted by Ezbeat