
원격 PowerShell 세션용 실시간 모니터링 도구로, ETW를 사용하여 WinRM/PSRP 프로토콜을 캡처하고 디코딩하며, 보안 분석을 위한 명령 실행 추적 및 로깅을 제공합니다.
RemotePSpy는 원격 PowerShell 세션의 실시간 모니터링을 제공하며, 포괄적인 로깅 기능이 내장되어 있지 않은 구형(5.0 이전) PowerShell 버전에서 특히 유용합니다.
이 도구는 ETW(Event Tracing for Windows)를 사용하여 원격 PowerShell의 전송 계층으로 사용되는 WinRM 프로토콜에서 메시지 데이터를 수집하고, 다양한 프로토콜 계층을 디코딩하여 실행된 스크립트 명령과 그 입력/출력의 추적을 제공합니다.
현재 이 도구는 초기 연구용 프로토타입이므로 PowerShell 원격 프로토콜(PSRP)의 모든 측면을 지원하지는 않습니다. 그럼에도 원격 PowerShell 세션에서 발생하는 작업에 대한 유용한 통찰력을 제공할 수 있습니다.
가장 쉬운 설치 방법은 pip를 사용하는 것입니다:
pip install remotepspy
pip를 통해 설치할 때 종속성은 자동으로 설치되어야 하지만, 소스에서 설치하려는 경우 아래에 나열되어 있습니다:
libwim-15.dll은 데이터 소스로 (권장되는 기본값인) Microsoft-Windows-WinRM ETW 공급자를 사용하는 경우에만 필요합니다. 이 DLL은 PSRP 메시지 조각을 포함하는 WinRM/WSMan 프로토콜의 특정 스트림 개체를 압축 해제하는 데 사용됩니다. 기본 Python 스크립트와 같은 디렉터리에 넣기만 하면 됩니다.
모니터링 및 로깅을 시작하려면 RemotePSpy를 실행하고, 완료되면 Return 키를 누르십시오. 로그는 현재 작업 디렉터리에 RemotePSpy.log라는 이름으로 기록됩니다.
이 도구는 또한 원격 PowerShell 사용자가 화면에서 보는 내용의 대략적인 복제본을 로그 파일의 더 상세한 정보와 함께 stdout에 출력합니다. 더 복잡한 로깅도 가능하며, 아래의 "로깅" 섹션을 참조하십시오.
Python을 PATH에 설치한 경우 RemotePSpy 실행 스크립트도 PATH에 포함됩니다. 그렇지 않은 경우 Python site-packages 디렉터리에서 찾아야 할 수 있습니다.
기본 RemotePSpy는 (권장되는) WinRM ETW 공급자를 데이터 소스로 사용합니다. 대신 PowerShell ETW 공급자를 사용하려면 RemotePSpy_powershell_prov를 실행할 수 있습니다.
이 버전은 특정 ETW 공급자에서 데이터가 제공되는 방식에 따라 특정 상태를 추적하는 복잡성이 추가되어 불필요한 경고가 발생할 수 있습니다.
코드는 프로토콜 스택의 다양한 계층에서 입력을 받을 수 있는 상당히 모듈화된 여러 클래스로 구성됩니다. 이를 통해 데이터를 얻는 위치와 형식에 따라 클래스를 약간 다른 방식으로 연결할 수 있습니다. 대부분의 클래스는 콜백 함수를 허용하며, 이를 사용하여 생성된 결과를 스택의 다음 계층에 전달합니다.
사용되는 주요 클래스에 대한 설명은 아래에 나와 있으며, 그 다음에는 다양한 시나리오에서 어떤 클래스가 어떤 클래스로 연결되는지 보여주는 몇 가지 처리 흐름이 이어집니다.
ETWWinRM – WinRM 공급자에서 ETW 이벤트를 수집합니다.
ETWPowerShell – PowerShell 공급자에서 ETW 이벤트를 수집합니다.
PowerShellETWParser – PowerShell ETW 이벤트에 대한 Shell 컨텍스트를 식별하고, 조각 데이터를 PSRPDefragmenter에 전달합니다. 또한 스레드 동기화를 제공합니다.
SoapDefragmenter – WinRM ETW 이벤트에서 전체 WSMan SOAP 메시지를 재조립하고, 완전한 SOAP를 WSManPS에 전달합니다.
WSManPS – PowerShell과 관련 없는 WinRM을 필터링하고, Shell 컨텍스트를 추적하며, WSMan SOAP에서 PSRP 조각 데이터를 파싱하고, 조각 데이터를 PSRPDefragmenter에 전달합니다.
PSRPDefragmenter – PSRP 조각을 완전한 PSRP 메시지로 재조립합니다. 조각은 ObjectID별로 조립되며, ObjectID의 고유성은 Shell 컨텍스트를 고려하여 보장됩니다. 최종 PSRP 메시지를 PSRPParser에 전달합니다.
PSRPParser – 원시 바이너리 PSRP 메시지를 디코딩하여 RPID, Pipeline ID, MessageType과 같은 헤더 세부 정보를 추출합니다. 디코딩된 메시지를 SimpleCommandTracer에 전달합니다.
SimpleCommandTracer – MessageType을 사용하여 PSRP 메시지를 해석하고, 명령, 인수 및 해당 출력을 추출하여 출력/로그에 기록합니다. 직렬화된 PowerShell 개체의 부분 디코딩을 포함합니다. 가능한 모든 기능의 완전한 구현은 아니지만, 실행 추적을 위해 대부분의 일반적인 경우를 다루려고 시도합니다.
Microsoft-Windows-WinRM ETW 공급자를 사용할 때의 처리 흐름:
ETWWinRM -> SoapDefragmenter -> WSManPS -> PSRPDefragmenter -> PSRPParser -> SimpleCommandTracer
Microsoft-Windows-PowerShell ETW 공급자를 사용할 때의 처리 흐름:
ETWPowerShell -> PowerShellETWParser -> PSRPDefragmenter -> PSRPParser -> SimpleCommandTracer
프로토콜 스택의 각 계층에 포괄적인 로깅이 있습니다. 이를 통해 다양한 수준에서 디버깅이 가능하며, 개발 중에 특히 유용했습니다. 또한 모든 주요 계층에서 프로토콜의 전체 추적을 얻을 수 있으므로 원격 PowerShell의 작동 방식을 조사하려는 모든 사람에게도 유용할 수 있기를 바랍니다.
현재 로깅을 변경하려면 로거가 구성된 스크립트 끝부분의 소스 코드를 편집해야 합니다. 향후 릴리스에서는 이러한 구성을 위한 더 나은 방법을 제공할 수 있기를 바랍니다.
각 로거 이름은 이를 사용하는 클래스의 상수 LOGGER_NAME으로 정의됩니다. 모든 로거는 "RemotePSpy"의 하위 항목으로 정의됩니다(예: RemotePSpy.etw). 프로그래밍 방식으로는 적절한 로그 이름과 함께 logging.getLogger()를 사용하여 로거를 구성할 수 있습니다.
빠른 참조를 위해 다음 로거와 수준은 프로토콜의 다양한 계층에서 프로토콜 추적을 제공합니다:
SimpleCommandTracer는 stdout에도 추적을 출력하며, 이는 원격 PowerShell 사용자가 보는 화면을 어느 정도 복제하려고 시도합니다. 이는 각 명령, 파이프라인 메서드 호출 및 파이프라인 출력을 RPID 및 Pipeline ID와 같은 추가 컨텍스트를 포함하여 더 정확한 방식으로 기록하는 명령 추적 로그와는 다릅니다.
각 로그에 어떤 수준에서 무엇이 나타나는지에 대한 더 자세한 요약은 아래에 나와 있습니다:
ERROR:
WARNING:
INFO:
DEBUG:
DEBUG:
ERROR:
WARNING:
INFO:
DEBUG:
ERROR:
WARNING:
INFO:
DEBUG:
INFO:
DEBUG:
DEBUG:
ERROR:
DEBUG:
INFO:
| 주요 로그 데이터 | 로거 이름 상수 | 수준 |
|---|
| 명령 추적 | SimpleCommandTracer.LOGGER_NAME | INFO |
| 전체 ETW 이벤트 추적 | ETWWinRM.LOGGER_NAME | DEBUG |
| 전체 WSMan SOAP 메시지 추적 | SoapDefragmenter.LOGGER_NAME | INFO |
| 각 PSRP 조각의 전체 추적 | PSRPDefragmenter.LOGGER_NAME | DEBUG |
| 전체 PSRP 메시지 추적 | PSRPParser.LOGGER_NAME | DEBUG |