Wireshark가 Windows에서 프로세스별로 필터링할 수 없는 이유와 해결 방법
요약
Windows 환경에서 Wireshark는 구조적으로 프로세스별 패킷 필터링이 어렵습니다. 이를 해결하기 위해 `pktmon`이라는 내장 도구를 사용하여 캡처 시점에 PID를 ETL 파일에 기록하고, 이후 tshark로 해당 PID를 기준으로 필터링할 수 있습니다. 이 방법은 출처 추적 문제를 해결하지만, HTTPS 암호화 내용 자체는 여전히 접근할 수 없습니다.
핵심 포인트
- Wireshark의 구조적 한계: 패킷에는 프로세스 정보가 기본적으로 포함되지 않음.
- `pktmon` 사용 권장: 캡처 시점에 PID를 커널 레벨에서 기록하여 출처 추적 가능.
- 필터링과 내용 분석 분리: `pktmon`은 출처(PID)만 알려줄 뿐, HTTPS 암호문 내용은 해결 불가.
- SSL Pinning 및 프록시 우회 문제: 금융/게임 앱의 보안 메커니즘으로 인해 추가적인 후킹 기법이 필요함.
Windows 환경에서 Wireshark는 소켓 계층(socket layer) 아래에서 패킷을 캡처합니다. 이 과정에서 생성되는 패킷에는 어떤 프로세스 정보도 담겨 있지 않습니다. 즉, TCP/IP 헤더에 "이것은 WeChat.exe에서 온 것이다"라고 명시하는 필드가 없습니다. 따라서 30초 동안 캡처하여 60개의 다른 연결로부터 40,000개의 패킷을 얻었다고 해도, 실제로 관심 있는 앱의 패킷이 어떤 포트 번호에 속하는지 추측할 수밖에 없습니다.
이는 Wireshark의 버그가 아닙니다. 이는 캡처가 이루어지는 구조적인 특성 때문입니다. Wireshark에는 _ws.process.id 필드가 존재하지만, 이 값은 libpcap에서 오는 것이 아니라 ETW 메타데이터(NDIS 계층)로부터 채워집니다. 만약 Wireshark GUI에서 직접 캡처를 시작하면, 이 필드는 비어 있게 됩니다.
해결 방법: pktmon
Windows 10 1809 버전 이상에는 pktmon이라는 내장 캡처 도구가 포함되어 있으며, 이 도구는 캡처 시점에 PID(프로세스 ID)를 ETL 파일에 기록합니다. 이것이 핵심적인 차이점입니다. 프로세스 식별자가 나중에 재구성되는 것이 아니라 커널에 의해 캡처 중에 기록되기 때문입니다.
관리자 터미널에서 다음과 같이 실행합니다:
pktmon start --capture --pkt-size 4096 --file-name cap.etl
:: 대상 앱을 실행하는 작업 수행
pktmon stop
...
그다음 tshark를 사용하여 PID로 필터링합니다 (PID는 작업 관리자 또는 tasklist | findstr appname에서 가져올 수 있습니다):
tshark -r cap.pcapng -Y "_ws.process.id == 12345" -w filtered.pcap
이렇게 생성된 filtered.pcap 파일을 Wireshark로 열면, 대상 프로세스의 패킷만 포함되어 있습니다. '통계(Statistics)' → '대화(Conversations)'를 확인하면, 기기 전체의 모든 연결 목록 대신 깔끔하게 정리된 연결 목록을 얻을 수 있습니다.
이것이 해결하는 것과 그렇지 않은 것
이 방법은 출처 추적(attribution) 문제를 해결합니다. 즉, 어떤 패킷이 어느 프로세스에 속하는지를 알려줍니다. 하지만 내용(content) 문제는 해결하지 못합니다. HTTPS는 여전히 암호문입니다. 평문 데이터를 얻으려면 MITM 프록시(mitmproxy, Charles, Fiddler)가 필요하며, 대상 장치가 이 프록시를 통해 라우팅되어야 하고, 해당 프록시에 대한 신뢰할 수 있는 CA(Certificate Authority)가 있어야 합니다.
필터링 문제는 프록시 계층에서 다른 형태로 재발합니다: mitmproxy는 브라우저와 그 외 모든 것을 포함하여 프록시를 통과하는 모든 흐름을 기록합니다. 작동하는 요령은 각 흐름의 클라이언트 소스 포트를 가져와 psutil.net_connections()에서 조회한 다음, 대상 프로세스와 일치하는 PID를 가진 흐름만 유지하는 것입니다.
두 가지 문제가 발생할 수 있습니다:
- SSL Pinning. 금융, 트레이딩, 일부 게임 등 많은 클라이언트는 서버 인증서 지문을 하드코딩합니다. mitmproxy CA를 설치해도 아무 효과가 없습니다. 핸드셰이크가 실패하기 때문입니다. 이것은 패킷 캡처가 아니라 인증서 검증 함수에 대한 Frida 후킹(hook)이 필요합니다.
- 프록시 우회 (Proxy bypass). 데스크톱 애플리케이션은 시스템 프록시를 안정적으로 읽지 못합니다. 일부는 실행 전에
HTTP_PROXY/HTTPS_PROXY가 설정되어야 하며, 일부는 직접 연결로 하드코딩됩니다. QUIC과 원시 UDP는 프록시를 완전히 우회하지만, L3/L4 레벨에서는 여전히 이를 감지할 수 있습니다.
도구 (The tool)
저는 이 전체 흐름을 proc-sniffer에 담았습니다. 즉, PID 필터링이 적용된 pktmon 캡처와, 소스 포트 → PID를 매핑하는 선택적 mitmproxy L7 계층입니다. 이를 통해 요청한 프로세스의 평문 데이터만 얻을 수 있습니다.
이는 CLI(Command Line Interface)와 MCP 서버 형태로 모두 제공되므로, 에이전트가 하나의 대화 내에서 캡처를 시작하고 중지하며 결과를 내보낼 수 있습니다.
process name --psutil--> PID / local ports
L3/L4: pktmon (PID로 캡처) --> ETL --etl2pcapng--> pcapng --filter by PID--> filtered.pcap
L7 : mitmproxy (프록시, 소스 포트 → PID로 필터링) --> http_traffic.jsonl
...
# L3/L4 + L7,
Wireshark가 설치되어 있지 않으면 tshark가 없으므로 `_ws.process.id` 필터링을 사용할 수 없습니다. 대체 방식은 캡처 중 대상의 로컬 포트를 초당 한 번 샘플링하고 포트별로 필터링합니다. 짧게 지속되는 연결은 놓칠 수 있습니다.
## 개발 과정에서 마주친 문제점들
- **PID 드리프트(PID drift).** 프로세스가 재시작되면, 자식 프로세스가 새로운 PID로 실행됩니다. 정확한 PID와 일치시키는 것보다 이름/실행 파일명/명령줄을 기준으로 매칭하는 것이 더 안정적입니다.
- **관리자 권한 필수.** 패킷 캡처와 모든 프로세스의 연결 읽기 모두 높은 수준의 권한(elevation)이 필요합니다.
- **etl2pcapng vs pktmon etl2pcap.** 내장 변환기가 작동하지만, Microsoft의 독립 실행형 `etl2pcapng.exe`가 약간 더 깔끔한 출력을 생성합니다. 이 도구는 발견하는 것을 사용합니다.
- **macOS와 Linux에는 이런 문제가 없습니다.** `lsof -i`에 `tcpdump`, 또는 `ss -tp`를 사용하면 프로세스 이름을 직접 얻을 수 있습니다. Windows에서 우회 경로가 존재하는 이유는 NDIS 계층이 프로세스 의미론(process semantics)을 담고 있지 않기 때문입니다.
## 범위
이 도구는 사용자 자신의 기기에서 실행되는 소프트웨어의 트래픽을 캡처합니다. 이 도구를 소유하거나 분석 권한이 있는 소프트웨어에 사용하십시오 — 상호 운용성, 디버깅, 보안 연구 또는 학습 목적입니다. 다른 사람의 트래픽이나 검사할 권리가 없는 서비스의 트래픽을 캡처하는 것은 관할권 내에서 법률 및 서비스 약관을 위반할 수 있습니다. 이것은 면책 조항 단락이 아니라, 이 도구가 실제로 사용되는 경계 범위입니다.
MIT 라이선스.
**저장소(Repo):** [https://github.com/xiao77mwq/proc-sniffer](https://github.com/xiao77mwq/proc-sniffer)
만약 캡처할 수 없는 사례를 만났다면, 어떤 애플리케이션인지와 무엇을 보려고 했는지에 대한 이슈(issue)를 열어주세요 — 제가 읽겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기