Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 3개 있습니다.)
한 대의 PC에서 여러 개의 키입력 매크로 프로그램이 가능할까?


저는 SDK 레벨의 개발자입니다. 그래서 때로 DDK 레벨의 개발자들이 부럽습니다. ^^

마침, 이번 마소 3월호의 248 페이지에 "리버싱으로 분석하는 온라인 게임 해킹툴"이라는 재미있는 ^^ 기사를 읽게 되었는데요. 역시 DDK하는 사람들은 리버싱 실력 자체가 다릅니다. 너무 너무 멋있다는! ^^

이야기를 좀 벗어나서.

한때 저도 "모" 게임에 푹 빠졌을 때가 있었다는 사실... 아셨나요? ^^
그 게임에서 구현한 3차원 세계는 정말이지 온라인 게임을 처음 접한 저에게는 신세계와 같았습니다. (결과적으로 지금 생각해 보면, 이때 온라인 게임의 폐해를 알았기에 나중에 WOW가 나왔어도 심드렁할 수 있었던 것 같습니다. ^^;)

제가 그렇게 게임에 빠져있을 때, 나름대로 ^^ 만든 매크로 프로그램을 만들어서 아주 잘 활용했었습니다. 그렇다고 무슨 자동 사냥하는 프로그램은 아니었고, 컴퓨터 2대에서 게임 클라이언트를 각각 실행하고, 한 대에서 제가 게임을 하면서 다른 한대에 실행된 캐릭터를 같이 조정할 수 있는 프로그램이었습니다. 예를 들어, 제 컴퓨터의 "a" 키를 누르면 다른 PC의 캐릭터가 같이 공격해 주고, "h" 키를 누르면 제 캐릭터에 에너지를 보충 할 수 있도록 한 것이었습니다.

"리버싱으로 분석하는 온라인 게임 해킹툴" 기사를 보면서, 그때 제가 만든 그 프로그램이 생각났습니다. 기사에서는 "고전적인 매크로 구현 방법"이라고 하면서 "keybd_event", "mouse_event"를 예로 들었는데 실제로 제가 만든 그 프로그램에서도 "keybd_event" API를 사용해서 구현했었습니다.

기사에서 언급되고 있지만, "keybd_event, mouse_event" API는 게임 보안 솔루션에서 사용을 막았기 때문에 이젠 구식이 되어버린 기술이라고 합니다.

그때 기억도 되새길 겸. 정말로 모 업체의 3-D 게임 하나를 다운로드 받아서 테스트를 해봤습니다. 오호... 정말 안됩니다. ^^; 재미있게도 게임 프로그램이 전면에 뜰 때만 keybd_event 함수가 동작 안하고 다시 다른 응용 프로그램이 전면으로 오면 동작을 합니다. keybd_event 유의 함수가 다른 프로그램에서는 "유용한" 매크로로 쓰인다는 점에 대한 세심한 배려가 돋보입니다.




해보는 김에. 기사에서 언급된 0x64, 0x60 포트를 이용해서 제어를 해보고 싶었습니다. 말씀드린 데로 저는 SDK 개발자이기 때문에 드라이버 개발은 해본적이 없습니다. (사실 Hello World 수준의 dummy 드라이버는 실습해봤지만, 그 이상은 해본 적이 없습니다.)

그래서 검색을 해봤더니. 아하... ^^ 공개된 프로그램이 하나 눈에 띄입니다.

NTPort Library
; http://www.zealsoftstudio.com/ntport/

평가판을 다운로드 할 수 있는데, 그렇다고 기능 제약이 있는 것은 아니고 최초 구동시에 라이선스 알림 대화창이 뜬다는 제약만 있기 때문에 테스트 용으로는 전혀 손색이 없습니다.

그럼. 일단 포트를 읽고 쓰는 드라이버는 구했고. 다음 문제는 어떻게 사용해야 키 입력을 흉내낼 수 있느냐는 것인데.

생각보다, 이 방법을 언급하고 있는 자료를 찾기가 쉽지 않았습니다. 겨우 찾은 방법이 아래 문서의 11페이지에 나온 정도입니다.

Keylogging Analysis
; http://codeengn.com/?module=file&act=procFileDownload&file_srl=233&sid=7f06fd348c558e70720143533138db07

위의 내용을 NTPortLibrary 코드로 다시 쓰면.

bool is_buffer_empty(void)
{
    int timeout;
    
    for(timeout = 200; timeout && (Inport(0x64) & 0x02); timeout--) 
    {
      Sleep(1);
    }

    retrn timeout != 0;
}

if (is_buffer_empty() == false)
{
    return;
}
Outport(0x64, 0xD2);

if (is_buffer_empty() == false)
{
    return;
}
Outport(0x60, scanCode);

위의 코드에서 scanCode 값은 아래 문서의 16페이지에서 찾아볼 수 있습니다.

Keyboard Scan Code Specification
; http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc

keyboard_port_io_scancode_1.png

즉, scanCode 값에 10을 넣으면 키보드로 "9" 숫자키를 입력한 것과 동일한 효과를 발생합니다.

자, 이 정도 하고 다시 게임 프로그램을 실행시키고 테스트 해봅니다. 우와~~~ 이번에는 정상적으로 문자가 전달됩니다. ^^ 아직 여기까지는 보안 프로그램이 막지 않았나 봅니다. (이 프로그램에 쓰인 보안 프로그램만 이것을 막지 않은 것인지, 아니면 이것을 원천적으로 막을 수 없는 것인지는 잘 모르겠습니다.)




그런데. 재미있는 방법이 하나 더 있습니다.
"Remote Desktop" 아시죠? mstsc.exe 프로그램으로 원격 접속하는.

예전에는 RDS 환경이 그다지 좋지 않아서 RDS 세션 환경에서는 3-D 프로그램이 실행되지 않았었는데, 어느새 시간은 흘러 ^^ 그것도 이젠 옛날 이야기가 되어버렸습니다. 그러니까, Windows Server 2008 R2에서 제공되는 RDS 환경에서는 3-D 프로그램도 정상적으로 실행이 됩니다. (제가 테스트 해본 바에 의하면 Vista 원격 접속 지원에서도 3-D 프로그램이 실행되었기 때문에 아마도 Windows Server 2008에서도 되지 않을까... 예상합니다.)

그렇다면 RDS 환경에서 게임 프로그램을 실행한 경우에는 키 입력을 위한 매크로 프로그램이 어떻게 작동할 수 있을까요? 우선, RDS 환경 내에서 포트 제어를 통한 키입력 방법은 효과가 없습니다. 짐작으로는, RDP 클라이언트 측에서 마우스/키 입력이 RDS 세션으로 전달되어 처리되는 방식이기 때문에 물리적인 하드웨어의 포트를 제어하는 방식으로는 RDS 세션 내의 프로그램에 영향을 주지는 않는 것 같습니다.

또한, "keybd_event, mouse_event" API도 RDP 환경 내에서 동작은 하지만 여전히 보안 프로그램이 설치된 게임 클라이언트에는 동작하지 않습니다.

그런데! ... 이쯤 되면 눈치채신 분도 계시겠지만.

어차피 게임 클라이언트는 그것이 실행된 윈도우 세션 내에서의 "keybd_event, mouse_event"에 대해서만 막을 수 있기 때문에, "RDP 클라이언트가 실행된 환경"에서 "keybd_event, mouse_event" API를 실행시켜 전달하는 것은 가능하다는 것입니다. 말로 설명하는 것보다 아래의 화면을 보면 이해가 되시겠죠. ^^

keyboard_port_io_scancode_2.png

위의 그림에서는 Windows 7 운영체제에 키 입력을 keybd_event 함수를 이용해서 발생시키는 "MainWindow"라는 제목을 가진 프로그램과 mstsc.exe 프로그램이 실행되어 있습니다. 보는 것처럼, MainWindow 프로그램에서 발생하는 keybd_event에 의해서 mstsc.exe에 숫자 키 "9"가 전달되는 것을 확인할 수 있습니다. 일단 메모장을 실행시켜서 테스트하고 있지만 게임 클라이언트라고 하더라도 정상적으로 키 입력을 "받아들일 수밖에" 없습니다. 왜냐하면 그 입력이 keybd_event에 의한 것인지 사용자에 의한 것인지 "RDS 세션에서 작동 중인 게임 프로그램에 설치된 보안 프로그램 입장"에서는 구별할 수 있는 방법이 없기 때문입니다.

그렇다면!
손쉬운 자동 사냥 프로그램을 못하게 하려고 keybd_event 함수를 막았던 보안 업체는, 위와 같은 방식의 자동 사냥 프로그램은 어떻게 막을 수 있을까요? 아마도, 아예 RDS 환경에서는 게임이 실행되지 못하도록 만들어야 하지 않을까 싶은데요. 정말... 그렇게 막아버리게 될까요? ^^

한 가지 더 재미있는 사실이 있습니다.

그동안, "전면에 띄워진 윈도우"에만 키 입력이 전달되었기 때문에 "하나의 PC"에서 하나의 매크로 프로그램만을 동작시킬 수 있었지만 RDS 세션을 활용하게 되면 "하나의 PC"에서 다중 RDS 세션을 열어서 여러 개의 매크로 프로그램을 돌리는 것이 가능합니다.

이런 거 보면, 정말이지 ^^ 컴퓨터는 다양한 기술의 조합에 따른 운영의 묘미가 있는 것 같습니다.

이게 끝일까요? ... 알 수 없습니다. 언제나 기술은 변화하기 때문에.
2003년 PDC에서 언급된 "Multiple Input Queues"가 구현된다면... 위와 같이 다중 세션을 열어놓을 필요도 없을 테니까요.




마지막으로 한 가지 더 재미있는 사실.
Windows Server 2008 R2의 RDS 연결 제한은 기본적으로 "Administration" 모드로 제공되는 라이선스로 인해 2개이고, 라이선스 서버를 제공하는 경우에만 2개의 제한을 없앨 수가 있습니다.

그런데, 예전에 제가 Windows 7의 RDP 연결에서 1개의 연결 제한을 해제하는 (정식이 아닌) 패치를 알려드렸었지요.

Windows 7 - 다중 원격 접속(Remote Desktop) 허용
; https://www.sysnet.pe.kr/2/0/782

재미있게도 그 패치를 적용하면 RDP 연결 수에 제한이 없습니다.

이번 글을 쓰면서, VPC에 설치해 둔 Windows Server 2008 R2에도 해당 termsrv.dll을 테스트해 보았습니다. 오호... 2개의 연결 제한을 갖는 "Administration Mode"가 해제되었다는!




첨부한 파일은 본문에서 설명한 2개의 문서와 소스 코드입니다.

polling.pdf: 위에서 설명한 Keylogging Analysis PPT 문서
scancode.doc: 위에서 설명한 Keyboard Scan Code Specification 문서
Console.zip: NTPortLibrary를 이용한 키입력 테스트 프로젝트 (VS2010)



[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/10/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2010-12-16 12시22분
The AT keyboard controller
; http://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html

Hardware Manipulation (Keyboard LED)
; http://ezbeat.tistory.com/294
정성태
2011-02-10 11시03분
[지나가다] 포트를 이용한 키입력 전달을 보안 프로그램에서 막고 있다고 하셨는데요. 키보드 후킹 후 SendMessage는
상관 없을런지..? 이와 관련해서는 말씀이 없으셔서 관련 주제라 한번 댓글을 달아봅니다. ^^;

스크립트를 지원하는 매크로 프로그램에서 키입력 전달 스크립트를 만들어서 사용하면 키입력이 전달되더군요.
(보안 프로그램이 해당 매크로 프로그램을 막지는 않았음. 막힐경우 불탐으로 클라이언트 종료.)

해당 매크로는 키보드 후킹 후 SendMessage를 하는것 같던데, 해당 매크로의 특정 키워드를 사용하는 거라서
내부에서 어떤 식으로 키입력을 게임(활성창)에 전달하는지 자세히 모르겠네요.

매크로의 원본 C소스까지 공개되어 있던데.. 저는 뭐 소스 분석할 실력이 아니라서^^
[guest]
2011-02-10 11시43분
DirectX 게임 유는 직접 키보드 하드웨어로부터 입력을 받아들이기 때문에 SendMessage 같은 윈도우 메시지 API 전달 함수로는 키 입력을 할 수 없습니다. 말씀하신 스크립트 지원 매크로 프로그램이 뭔지는 모르겠지만, 정확히 SendMessage를 사용하는 것이 맞나요? 맞다면, 그리고 그것으로 DirectX 게임 유에 테스트 하신 건가요?
정성태
2011-02-10 03시24분
[지나가다] 글을 삭제하려고 했는데 댓글을 주셨네요. 감사드립니다. :-)

매크로 프로그램의 소스를 자세히 확인해 보니 SetWindowsHookEx()로 후킹 후 활성화된 윈도우에 keybd_event()를 사용하는 형태 였습니다.
그리고 위의 방식 말고, 직접적으로 SendMessage()를 지원했지만 제가 테스트 해볼 당시에는 작동하지 않았던것으로 기억합니다.

말씀하신 내용이 맞는듯.. 해당 게임은, 유명 온라인 게임으로 DirectX 류가 맞는것 같습니다. 엉뚱한 내용으로 귀찮게 해드려서 죄송합니다. ^^;;
[guest]
2017-06-02 12시59분
첨부 파일 - Operating Systems Development Series.mht

Operating Systems Development - Scan Codes
; http://www.brokenthorn.com/Resources/OSDevScanCodes.html
정성태

... 151  152  153  154  155  156  [157]  158  159  160  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1121정성태9/12/201127569Java: 5. WTP 내에서 서블릿을 실행하는 환경
1120정성태9/11/201127484.NET Framework: 239. IHttpHandler.IsReusable 속성 이야기파일 다운로드1
1119정성태9/11/201126612Java: 4. 이클립스에 WTP SDK가 설치되지 않는다면? [2]
1118정성태9/11/201138253Java: 3. 이클립스에서 서블릿 디버깅하는 방법 [4]
1117정성태9/9/201125547제니퍼 .NET: 17. 제니퍼 닷넷 적용 사례 (2) - 웹 애플리케이션 hang의 원인을 알려주다.
1116정성태9/8/201156626Java: 2. 자바에서 "Microsoft SQL Server JDBC Driver" 사용하는 방법
1115정성태9/4/201130103Java: 1. 닷넷 개발자가 처음 실습해 본 서블릿
1114정성태9/4/201134613Math: 2. "Zhang Suen 알고리즘(세선화, Thinning/Skeletonization)"의 C# 버전 [4]파일 다운로드1
1113정성태9/2/201134201개발 환경 구성: 129. Hyper-V에 CentOS 설치하기
1112정성태9/2/201150932Linux: 1. 리눅스 <-> 윈도우 원격 접속 프로그램 사용 [3]
1111정성태8/29/201125396제니퍼 .NET: 16. 적용 사례 (1) - DB Connection Pooling을 사용하지 않았을 때의 성능 저하를 알려주다. [1]
1110정성태8/26/201126727오류 유형: 136. RDP 접속이 불연속적으로 끊기는 문제
1109정성태8/26/201129581오류 유형: 135. 어느 순간 Active Directory 접속이 안되는 문제
1108정성태8/22/201131169오류 유형: 134. OLE/COM Object Viewer - DllRegisterServer in IVIEWERS.DLL failed. [1]
1107정성태8/21/201128880디버깅 기술: 43. Windows Form의 Load 이벤트에서 발생하는 예외가 Visual Studio에서 잡히지 않는 문제
1106정성태8/20/201127208웹: 26. FailedRequestTracing 설정으로 인한 iisexpress.exe 비정상 종료 문제
1105정성태8/19/201127138.NET Framework: 238. Web Site Model 프로젝트에서 Trace.WriteLine 출력이 dbgview.exe에서 확인이 안 되는 문제파일 다운로드1
1104정성태8/19/201127292웹: 25. WebDev보다 IIS Express가 더 나은 점 - 다중 가상 디렉터리 매핑 [1]
1103정성태8/19/201133186오류 유형: 133. WCF 포트 바인딩 실패 오류 - TCP error(10013) [1]
1102정성태8/19/201130960Math: 1. 방탈출3 - Room 10의 '중복가능한 조합' 문제를 위한 C# 프로그래밍 [2]파일 다운로드1
1101정성태8/19/201129629.NET Framework: 237. WCF AJAX 서비스와 JavaScript 간의 DateTime 연동 [1]파일 다운로드1
1100정성태8/17/201128733.NET Framework: 236. SqlDbType - DateTime, DateTime2, DateTimeOffset의 차이점파일 다운로드1
1099정성태8/15/201128156오류 유형: 132. 어느 순간 갑자기 접속이 안 되는 TFS 서버
1098정성태8/15/201150169웹: 24. 네이버는 어떻게 로그인 처리를 할까요? [2]
1097정성태8/15/201121473.NET Framework: 235. 메서드의 메타 데이터 토큰 값으로 클래스를 찾아내는 방법
1096정성태8/15/201125632디버깅 기술: 42. Watson Bucket 정보를 이용한 CLR 응용 프로그램 예외 분석 - (2)
... 151  152  153  154  155  156  [157]  158  159  160  161  162  163  164  165  ...