내 휴가를 WSC 리버스 엔지니어링으로 망친 이야기
(blog.es3n1n.eu)- Windows Security Center(WSC) 서비스 API를 직접 활용하여 Windows Defender를 비활성화하는 도구인 defendnot 개발 과정에 대한 경험 공유임
- 프로젝트는 이전 no-defender 프로젝트의 기술적 한계와 법적 문제를 극복하는 과정에서 시작됨
- 특수 환경(맥북 arm64, 원격 디버깅, 높은 지연) 등 여러 가지 장애물 속에서 리버스 엔지니어링과 디버깅을 진행함
- Defender 등록 우회 및 프로세스 검증 메커니즘 분석, 여러 실패와 시도 끝에 안정적으로 동작하도록 개선함
- 최종적으로 자동 실행 기능까지 구현 완료함과 동시에, 프로젝트 과정을 돌아보며 힘들었던 점을 고백함
소개
- Windows Defender를 비활성화하는 defendnot 도구의 구현 여정 경험 공유임
- 주요 기술적 세부 사항 설명 대신, 실제 환경에서 겪은 문제와 삽질 경험 중심으로 정리됨
- 정식 문서화 및 기술적 설명은 이후 별도로 공개될 예정임
1년 전 회상
- 약 1년 전에 no-defender라는 프로젝트를 공개하여, WSC API를 통해 Windows Defender가 비활성화되는 구조를 활용함
- 이 프로젝트는 안티바이러스 공급 업체의 서드파티 코드를 참조함으로써, 시스템에 다른 안티바이러스가 등록된 것처럼 속임
- 출시 후 큰 관심을 받으며 약 1,500개의 Star를 얻었으나, 관련 안티바이러스 업체의 DMCA 삭제 요청으로 인해 소스 삭제 및 프로젝트 종료를 결정함
프로젝트 시작 계기
- 현재 글 작성 당시 서울에서 airbnb에 체류 중임
- 주요 개발 환경은 M4Pro MacBook이며, 필수적인 x86 리버스 엔지니어링용 기기를 따로 챙기지 않음
- CTF 대회 및 여행 일정으로 인해 x86 디바이스 없이 작업을 진행해야 하는 상황 발생
- no-defender 프로젝트의 "정상적인" 구현 가능성 검토와 함께, AV 무관 단독 구현이 가능한지 탐색 시작임
초기 조사 (1일차)
- 친구의 도움으로 wsc 바이너리를 제공받아, 이전 프로젝트와 유사한 구조로 WSC 등록 재구현 시도임
- WSC의 COM API 활용해 구현했으나, Access Denied 오류 발생함
- 오류 원인을 WSC가 API 호출 프로세스의 서명 검증 및 인증 과정에서 찾음
- AV 프로세스에 모듈을 인젝션하여 등록을 시도했을 때 성공적으로 AV가 등록됨
AV 바이너리 대체 및 추가 실험 (1일차)
- 서명된 시스템 프로세스(cmd.exe 등)를 통해 도구 실행 시도, PPL(Protected Process Light) 검증에서 실패 경험함
- 분석을 위해 자세한 디스어셈블 및 추적을 기약하고 일시 중단함
환경 구축 (2일차)
- arm64 MacBook 환경의 한계로 x86 Windows 디버깅이 매우 어려운 상황임
- 미국에 사는 친구의 PC를 원격(Parasec, Anydesk 등)으로 이용하여, 고지연 환경 하에서 디버깅 및 실험 진행함
- 코드 빌드와 VM 디버깅이 복잡하게 교차되는 과정에서 속도 저하와 혼란 경험함
WSC 서비스 디버깅 (2일차)
- WSC 서비스가 svchost에 의해 실행되는 DLL 구조임을 확인함
- PPL 보호 해제를 위해 특수 드라이버로 우회 적용, 디버거로 함수 진입 확인함
- 서비스 내부에서 WinDefend SID 토큰 확인이 실행되고 있음을 파악함
- WinDefend SID를 가진 프로세스 모방 시도를 통해 인증 절차를 우회하려는 이론 수립함
WinDefend SID 모방 (2일차)
- Windows의 토큰 구조와 동작 원리에 대한 추가 학습 수행함
- WinDefend SID 모방 코드 구현 및 실행 후, 모든 COM 호출에서 SUCCESS 리턴되지만 실제로 AV 등록이 이루어지지 않는 정황 확인함
검증 알고리듬 재구성 (3일차)
- AV 바이너리에서 SID 체크가 정말 통과되는지 신중히 재분석함
- SID 체크 미통과시, 서비스가 권한 상승 상태, 바이너리 서명, PE의 DllCharacteristics 플래그(ForceIntegrity) 등을 추가 확인함
- 해당 구조 수행 함수 재현, 시스템 내 core 바이너리에 적용해 실험 진행함
Taskmgr 프로세스 활용 (3일차)
- Taskmgr.exe를 대상 프로세스 삼아 재실험했으나, 이름 전달 과정 오류 및 IPC 버그로 인해 WSC가 요청을 거부하는 문제 겪음
- 파일 경로 추론 및 AV 이름 전달 방식 개선 후 정상 동작 확인함
코드 정리 (3일차)
- 기능 정리 및 자동 실행(autorun) 기능 구현 시도함
- 자동 실행 관리에서 간헐적 실패를 겪고, 원인 규명을 위해 코드와 환경 점검 반복함
자동 실행 구현 (4일차)
- 작업 스케줄러(Task Scheduler) 옵션 중, 노트북이 AC 전원에 연결되지 않았을 때 작업이 실행되지 않도록 체크박스가 설정된 것이 원인임을 확인함
- 해당 설정 해제 후 자동 실행이 정상적으로 동작함
- 마무리로 코드 클린업 및 테스트 수행함
결론
- 제한적이고 불편한 환경에서의 리버스 엔지니어링 작업이 심리적/물리적으로 매우 힘든 경험이었음
- 차후 더 상세한 WSC 구현 문서는 별도로 공개될 예정임
감사 인사
- Pindos: PC를 야간에 제공해 디버깅을 돕고 방을 데워준 친구임
- MrBruh: 프로젝트 탐구를 시작하도록 자극 및 아이디어 피드백을 제공한 동료임
- 프로젝트 기간 함께 연락하며 힘이 되어준 지인들임
- 김치를 사랑함을 고백함
- 우리의 벽에 그래피티를 남긴 예술가에게도 감사함
Hacker News 의견
- Defender를 비활성화하는 가장 강력하지만 침습적인 방법으로는 라이브 Linux USB로 부팅해 "C:\ProgramData\Microsoft\Windows Defender" 폴더 이름을 바꾼 후 그 자리에 빈 파일을 만드는 방법임
- 그룹 정책이 너무 잘 작동하기 때문에 homelab에 컨트롤러를 두고 모든 사용자에 대해 Defender 정책을 자동으로 바꾸는 로컬 도메인 환경을 구성함
- Windows가 그런 변조를 탐지하는 서명된 매니페스트가 없다는 게 이상함
- 인기 있는 제품도 사실상 그렇게 하며, 인터넷 전체의 약 25%를 다운시킨 적도 있음
- 프로젝트가 많이 화제가 되고 약 1.5k 스타도 받았는데, 그 후 내가 사용하던 백신 개발자가 DMCA 요청을 보냄. "내가 사용하던 백신"이 무엇인지, 왜 이 사람이 DMCA를 보내는지 이해가 안 감. 아마 작성자가 다른 백신을 리버스 엔지니어링해서 오픈소스에 넣었거나, 최소한 WinDefend를 흉내낸 것과 관련된 듯함. 저작권 문제가 있었던 것 같음
- 내 이해로는 다른 백신 툴의 껍데기를 이용해 시그니처 요구사항을 우회한 것으로 보임. 변형적이라 합리적일 수 있지만 (법 관련 전문가는 아님) 회색지대임
- 예, 기존 백신 프로그램의 일부를 복사해 저작권법을 어긴 것임. 인용한 바로 위 문단에서도 프로젝트가 기존 백신의 서드파티 코드를 써서 AV를 WSC에 등록하도록 만들었다고 설명함
- 참고로, WSC는 Windows Security Center의 약자임
- 도움에 감사함. 처음 약어가 등장할 때 설명이 없으면 정말 답답함
- 이건 정말 기괴함: https://github.com/es3n1n/defendnot/…
궁금하다면 실제로 무슨 일이 일어나는지 이 곳을 참고: https://github.com/es3n1n/defendnot/…
- CPP 마법을 잘 설명할 수 있는 사람이 왜 이 코드가 기괴한지 설명해 줄 수 있는지 궁금함
- 이게 뭐가 이상한지 모르겠음. 나는 이 패턴을 코드 여러 군데에 잘 씀. 호출부에선 시그니처가 다르긴 하지만(개인 취향임). 참고로 D 언어는 scope 종료 시 트리거되는 문법이 내장돼 있음
- 시간 부족으로 모든 COM 요소에 대해 직접 RAII 패턴을 구현하긴 귀찮았음. 다음 업데이트에서 바꿀 예정임
- "코드는 동료를 대하는 방법과 같다" - Michael Feather 요약하면, AI가 아님 코드는 어떤 객체의 스코프가 종료될 때 함수 호출을 지연시키는 역할임. C 매크로를 활용해 복잡한 C 람다/익명 함수 정의와 고유 변수명 생성을 간단하게 함. 단, 매크로를 대문자로 표기하지 않고 함수 호출처럼 보여서 익숙하지 않은 사람은 헷갈릴 수 있음. 몇몇 사람들에게 이 패턴은 충분히 유용해서 관용적이라는 인식임. 기술적 설명은 다른 댓글 링크에서 볼 수 있음
- 나는 작년에 Windows의 가상 데스크탑을 리버스 엔지니어링하면서 휴가를 크게 즐김이 멋진 추억임. 리버스 엔지니어링이 정말 재밌음. 재밌는 점을 많이 배웠는데, 예를 들면 Windows RPC 내부에 문서화되지 않은 메시지 통신 방식이 있다는 점임: https://csandker.io/2022/05/24/Offensive-Windows-IPC-3-ALPC.html
- 최근에 https://nostarch.com/windows-security-internals 를 읽었는데, 이 글을 더욱 공감가게 만듦. Windows에선 백엔드가 어떻게 동작하는지 어느 정도 알았지만, 그 책의 마지막 챕터가 토큰과 SID에 대해 저자가 다룬 것만큼 자세하게 설명함
- 왜 WSC를 비활성화하고 싶어하는지 궁금함
- 성능이나, 악성코드 개발, 해킹 등의 이유가 있을 법함
- 위협 행위자라면 다른 EDR(엔드포인트 탐지 및 대응) 제품이 설치되어 있지 않아 운이 좋을 수도 있음. 하지만 있다면 거의 확실히 차단당할 것임. EDR 벤더라면 이건 Windows 방화를벽을 비활성화하기 위한 난독화된 API 호출로 쓸 수 있음. CrowdStrike 같은 제품도 자체 방화벽을 쓰거나 Windows 방화벽을 대체할 수 있음
- 모든 백신 소프트웨어는 적어도 powervirus임. netcat.exe 쓰면 안 된다는 식으로 누가 감시하는 게 싫음
- 내 하드웨어니까 내가 원하는 대로 쓸 것임. 단순한 이유임
- 굳이 자기 시스템에 rootkit을 심고 싶어하는 이유가 의문임
- 내게 더 나쁜 점은 Check Point Harmony가 Defender를 위해 만들어진 인터페이스를 전혀 활용하지 않고, 지식 베이스 문서로 Defender를 직접 비활성화하라고 사용자에게 안내하는 점임
- 혹시 궁금하다면: WSC는 Windows Security Center의 약자임. 나도 찾아봐야 했음
- "이 모든 걸 관리하는 것은 Windows Security Center-WSC이다"라는 표현이 기사에 포함되어 있음
- "내가 arm64 macbook에서 작업중이라 현재 arm macbook에서 x86 Windows를 에뮬레이션할 수 있는 제대로 된 방법이 없다"는 글에 대해, UTM은 어떤지 물어보고 Parallels가 최근 Intel VM 지원을 시작했다고 언급함
- UTM 을 써봤는데 x86 Windows에서는 쓸 수 없을 정도였음. 커맨드라인 Linux 정도는 수용 가능한 속도로 느릴 수 있지만, GUI 환경에선 불가능함. arm64 Windows는 잘 돌아가는데, 이건 x86 Windows가 아니니 x86 시스템 컴포넌트 리버스 엔지니어링엔 쓸모 없음
- QEMU의 다이나믹 리컴파일(dynamic recompilation) 시스템이 Windows나 macOS(Rosetta 2)의 네이티브 시스템만큼 효율적이지 않음. UTM에서 x86 Windows는 실행되긴 하지만 성능이 매우 안 좋음. 실제로는 ARM Windows VM에서 Windows의 다이나믹 리컴파일러로 x86 앱을 돌리거나, 네이티브 코드 기반 하위시스템을 쓰는 WINE이 더 낫다고 느낌. 간단히 급히 작업할 때는 괜찮을 수 있음. OP가 말한 "제대로 된" 상태에 퍼포먼스가 포함되어 있다면 그 입장이 이해됨
- 내가 잘못 알고 있으면 정정해달라지만, MMU가 있는 CPU의 에뮬레이션은 근본적으로 느릴 수밖에 없고 최적화가 어렵다는 게 맞는 것 같음. Apple의 Rosetta와 Microsoft의 해당 기술은 사용자 영역 코드만 실행하니까 빨리 돌아가는 거임. 시스템 전체 MMU 에뮬레이션은 피함