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
정성태

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13607정성태4/25/2024187닷넷: 2248.C# - 인터페이스 타입의 다중 포인터를 인자로 갖는 C/C++ 함수 연동
13606정성태4/24/2024202닷넷: 2247. C# - tensorflow 연동 (MNIST 예제)파일 다운로드1
13605정성태4/23/2024377닷넷: 2246. C# - Python.NET을 이용한 파이썬 소스코드 연동파일 다운로드1
13604정성태4/22/2024421오류 유형: 901. Visual Studio - Unable to set the next statement. Set next statement cannot be used in '[Exception]' call stack frames.
13603정성태4/21/2024705닷넷: 2245. C# - IronPython을 이용한 파이썬 소스코드 연동파일 다운로드1
13602정성태4/20/2024801닷넷: 2244. C# - PCM 오디오 데이터를 연속(Streaming) 재생 (Windows Multimedia)파일 다운로드1
13601정성태4/19/2024851닷넷: 2243. C# - PCM 사운드 재생(NAudio)파일 다운로드1
13600정성태4/18/2024881닷넷: 2242. C# - 관리 스레드와 비관리 스레드
13599정성태4/17/2024869닷넷: 2241. C# - WAV 파일의 PCM 사운드 재생(Windows Multimedia)파일 다운로드1
13598정성태4/16/2024892닷넷: 2240. C# - WAV 파일 포맷 + LIST 헤더파일 다운로드2
13597정성태4/15/2024880닷넷: 2239. C# - WAV 파일의 PCM 데이터 생성 및 출력파일 다운로드1
13596정성태4/14/20241069닷넷: 2238. C# - WAV 기본 파일 포맷파일 다운로드1
13595정성태4/13/20241052닷넷: 2237. C# - Audio 장치 열기 (Windows Multimedia, NAudio)파일 다운로드1
13594정성태4/12/20241069닷넷: 2236. C# - Audio 장치 열람 (Windows Multimedia, NAudio)파일 다운로드1
13593정성태4/8/20241084닷넷: 2235. MSBuild - AccelerateBuildsInVisualStudio 옵션
13592정성태4/2/20241219C/C++: 165. CLion으로 만든 Rust Win32 DLL을 C#과 연동
13591정성태4/2/20241199닷넷: 2234. C# - WPF 응용 프로그램에 Blazor App 통합파일 다운로드1
13590정성태3/31/20241079Linux: 70. Python - uwsgi 응용 프로그램이 k8s 환경에서 OOM 발생하는 문제
13589정성태3/29/20241154닷넷: 2233. C# - 프로세스 CPU 사용량을 나타내는 성능 카운터와 Win32 API파일 다운로드1
13588정성태3/28/20241268닷넷: 2232. C# - Unity + 닷넷 App(WinForms/WPF) 간의 Named Pipe 통신 [2]파일 다운로드1
13587정성태3/27/20241170오류 유형: 900. Windows Update 오류 - 8024402C, 80070643
13586정성태3/27/20241337Windows: 263. Windows - 복구 파티션(Recovery Partition) 용량을 늘리는 방법
13585정성태3/26/20241132Windows: 262. PerformanceCounter의 InstanceName에 pid를 추가한 "Process V2"
13584정성태3/26/20241250개발 환경 구성: 708. Unity3D - C# Windows Forms / WPF Application에 통합하는 방법파일 다운로드1
13583정성태3/25/20241472Windows: 261. CPU Utilization이 100% 넘는 경우를 성능 카운터로 확인하는 방법
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...