원문 캡처 · github.com
원문 캡처 · github.com

Zero Breach는 AdFection/Candiru 스파이웨어 캠페인의 흔적을 컴퓨터에서 찾는 로컬 전용 읽기 전용 검사 도구다. Windows, macOS, Linux에서 테스트됐으며 Python 3.8 이상이 필요하다. 검사 결과는 발견한 항목과 증거의 강도뿐 아니라 확인하지 못한 항목도 함께 보여준다.

검사 대상은 브라우저 기록·쿠키·캐시·연결 기록, 파일 지문, 자동 시작 등록 정보, 알려진 악성코드 파일 경로, DNS 확인자 캐시 등이다. 쿠키는 호스트 이름과 시각 정보만 조회하고 값을 읽거나 브라우저 자격 증명을 복호화하지 않는다. 다만 잠긴 데이터베이스를 조회하기 위한 임시 스냅샷에는 데이터베이스 전체 바이트가 복사된다.

검사 결과가 깨끗하다고 기기가 안전하다는 뜻은 아니다. 이런 수준의 스파이웨어는 검사 자체를 피하도록 만들어졌고, 흔적 대부분은 몇 주 안에 사라질 수 있다. Windows는 DNS 기록 기능을 사용자가 켜지 않으면 과거 DNS 이력을 남기지 않는다. 실제 표적이 됐다고 믿을 만한 이유가 있다면 스크립트에 의존하지 말고 Access Now 디지털 보안 헬프라인이나 Amnesty International Security Lab에 전문가의 도움을 요청하라고 프로젝트는 안내한다.

배경과 검사 범위

The Citizen Lab은 2026년 10월 보고서에서 광고 기술 회사 Discover-Tech가 Controlium 플랫폼으로 광고가 표시되는 순간 기기를 식별하고 감염시켜, 클릭 없이 Candiru 스파이웨어를 전달했다고 밝혔다. 2024~2025년 알자지라 기기 최소 45대가 표적이 됐다. Zero Breach의 지표는 해당 보고서와 Recorded Future의 같은 인프라에 대한 독립 추적 자료에서 가져왔다.

도구는 Chrome, Edge, Brave, Chromium, Firefox의 지원 위치에서 발견된 프로필을 대상으로 기록과 쿠키, 파비콘, HTTP 캐시, 로컬·세션 저장소, 서비스 워커 캐시, HSTS 및 연결 기록을 확인한다. 파일 검사에서는 스파이웨어가 떨어뜨리는 사용자 쓰기 가능 위치의 후보 파일에 대해 SHA-256을 알려진 샘플 해시와 비교한다. 악용된 적이 있는 정상 서명 드라이버의 해시는 별도로 표시하며, 감염 증거가 아니라 조사 단서로 취급한다.

Windows에서는 사용자별 COM 등록 정보, DNS 확인자 캐시, DNS 기록 기능의 활성화 여부, hosts 파일, HW.sys 취약 드라이버와 같은 알려진 고정 경로 파일을 확인한다. 항목은 종류에 따라 증거 수준을 구분한다. 캐시된 페이지에 도메인이 등장한 경우는 저장된 참조일 수 있으며 접속 증거와 구별한다. 쿠키 메타데이터나 저장된 연결 기록도 감염 여부나 기록이 남은 경위를 입증하지는 않는다.

설치와 실행

관리자 권한이나 제3자 패키지는 필요하지 않다. 가장 간단한 방법은 zero-breach.py 다운로드 후 릴리스 체크섬으로 파일을 확인하는 것이다. 다운로드한 폴더에서 터미널을 연다. Windows에서는 python을, macOS와 Linux에서는 python 대신 python3을 사용한다.

python -X utf8 zero-breach.py # full scan python -X utf8 zero-breach.py --quick # faster; skips file fingerprinting python -X utf8 zero-breach.py --json report.json

소스에서 실행할 때는 다음 명령을 사용한다.

python -X utf8 scan/adint-scan.py

검사는 시스템 설정을 바꾸지 않고 의도적인 네트워크 요청이나 지표 조회도 하지 않는다. 원격·리디렉션 경로는 건너뛰며, 온라인 인증서 확인은 비활성화돼 있다. 잠긴 데이터베이스의 스냅샷은 임시 파일이며 사용 후 삭제를 시도한다. 삭제에 실패하면 남은 위치를 보고한다. --json은 요청한 보고서를 파일로 쓴다. 종료 코드는 0이 발견 항목 없음, 2가 지표 일치, 1이 잘못된 지표 파일 등 검사 준비 실패를 뜻한다.

다운로드 파일은 공식 저장소에서 받아 실행 전에 확인해야 한다. 릴리스 v0.1.1에는 검사기와 체크섬 목록의 분리된 GPG 서명이 포함돼 있다. 프로젝트의 서명 안내를 따라 서명을 확인하고, 전체 키 지문을 ArchiveGenocide 확인 페이지와 대조할 수 있다. ArchiveGenocide 다운로드 확인 페이지에는 해당 버전의 체크섬도 별도로 공개돼 있다.

각 릴리스는 zero-breach.py의 SHA-256을 제공한다. Windows PowerShell에서는 Get-FileHash zero-breach.py -Algorithm SHA256, macOS와 Linux에서는 shasum -a 256 zero-breach.py로 확인한다. 저장소에서 직접 재빌드할 수도 있다.

git clone https://github.com/interplains/zero-breach.git cd zero-breach git checkout v0.1.1 python build/build.py # writes dist/zero-breach.py and prints its SHA-256

이 명령은 v0.1.1을 재현한다. 다른 릴리스에서는 해당 태그를 사용한다. macOS와 Linux에서는 빌드 명령에 python3을 쓴다. 개발 브랜치에는 이후 변경 사항이 있을 수 있어 이전 릴리스와 일치하지 않는다.

일부 백신 제품은 브라우저 데이터베이스를 읽는 스크립트를 인포스틸러와 비슷한 동작으로 판단해 경고할 수 있다. Zero Breach는 쿠키 값이 아닌 호스트 이름과 시각만 SQL로 조회하며 자격 증명을 복호화하지 않는다. 다만 잠긴 데이터베이스를 스냅샷으로 만들 때 데이터베이스 바이트 전체가 복사된다. 프로젝트는 백신이 경고할 경우 소스를 읽고 해시를 확인한 뒤 판단하라고 안내한다.

결과 해석과 한계

보고서는 평이한 요약으로 발견 내용, 심각도, 권고 조치, 검사하지 못한 항목을 설명한다. 주요 결과 유형은 다음과 같다.

  • on-disk: 파일이 공개된 지문과 일치한다. 스파이웨어 샘플 해시 일치는 해당 샘플을 식별하지만, vuln-driver 일치는 악용된 것으로 알려진 정상 소프트웨어를 가리킬 뿐 감염 증거는 아니다.
  • persistence: 이름이 자동 실행되도록 등록됐다. 심각한 항목이다.
  • contacted: 연결 기록이다. 광고 전달과 명령·제어 서버처럼 지표의 역할에 따라 의미가 달라진다.
  • dns-record: 이름이나 주소가 로컬 DNS 데이터에 있다. 조회가 실패했을 수도 있으며, 이름 확인만으로 서버 접속이 입증되지는 않는다.
  • configured: 로컬 설정에서 이름이 실제 주소에 연결돼 있다.
  • referenced: 방문하지 않은 북마크나 브라우저 저장소 등 저장된 콘텐츠에 이름이 나온다. 접속을 입증하지 않는다.

다음 조치는 증거와 지표의 역할에 따라 달라진다. 광고 관련 흔적이나 정상 드라이버 일치는 저장된 맥락부터 확인하며, 자동으로 스파이웨어 헬프라인에 연결할 사유가 되지는 않는다. 우려되는 인프라 흔적은 전문가의 해석이 필요하다. 알려진 스파이웨어 파일 일치와 지속성 항목은 증거를 보존하고 신속히 전문가에게 검토받아야 한다. 신빙성 있는 표적 우려가 있다면 검사 결과와 관계없이 직접 도움을 요청해야 한다. 약한 일치가 여러 개 나왔다고 강한 증거가 되는 것도 아니다.

도구는 증거 위치를 전체 경로로 표시하고, 도메인과 IP 주소는 보고서를 전달받은 메일 시스템이 지표에 접속하지 않도록 example[.]com처럼 변형해 출력한다. 차단용 주소를 가리키는 DNS 캐시 항목은 접속 시도가 아니라 보호 설정으로 표시한다. hosts 파일이 조회 없이 해당 주소를 미리 설정할 수 있기 때문이다. SQLite 스냅샷을 더 일관되게 만들려면 검사 전에 브라우저를 닫아야 한다. 로컬 경로 검사는 운영체제 수준의 격리 기능이 아니다. 엄격한 오프라인 실행이 필요하면 POSIX 네트워크 마운트와 검사 중 파일시스템 변경을 고려해 별도의 격리 경계를 마련해야 한다.

지표 데이터와 추가 활용

현재 소스 지표 목록에는 도메인 292개, IP 주소 111개, 스파이웨어 해시 1개, 정상 취약 드라이버 해시 1개 등 총 405개 지표가 있다. 목록은 iocs/adfection_iocs.txt에 있으며 각 줄에 등급, 신뢰도, 출처가 기록돼 있다. 서명된 v0.1.1 릴리스에는 지표 338개가 포함돼 있고, 이후 소스·피드 업데이트는 서명된 릴리스 파일을 바꾸지 않는다.

지표는 The Citizen Lab의 AdFection(2026), Hooking Candiru(2021), CatalanGate(2022), Confiant ADINT(2026), Recorded Future(2025), Microsoft DevilsTongue(2021), ESET(2021), Avast(2022), Google TAG(2021), Amnesty Security Lab의 인도네시아 조사(2024) 자료를 포함한다. 각 자료에서 Candiru와 관련된 지표만 넣었으며, 내보낸 항목에는 실제 출처가 유지된다.

dist 디렉터리에는 STIX 2.1과 MISP 형식이 있어 MISP, SIEM, Amnesty International의 Mobile Verification Toolkit에서 사용할 수 있다. MVT 명령은 mvt-ios check-backup --iocs dist/adfection.stix.json <backup>이다. DNS·광고 차단 목록은 hosts, Adblock/uBlock/AdGuard, dnsmasq, 일반 도메인 목록 형식으로 제공되며 휴대전화나 라우터의 DNS 필터, Pi-hole, AdGuard Home에 쓸 수 있다. 현재 목록에는 검토된 도메인·호스트 이름 291개가 있다. 공유 클라우드 IP와 호스팅 상위 도메인은 제외했다. adtimizer.co 자체는 검사 증거로 남지만 차단 목록에서는 제외하고, 구체적으로 문서화된 운영 호스트는 포함했다. 과거의 귀속 정보만으로 현재 소유자나 활동을 확정할 수 없다. --no-historical로 다시 생성하면 과거 등급 지표를 제외하지만 Recorded Future가 별도로 귀속한 2025년 인프라는 포함한다. hosts 파일은 정확히 일치하는 이름을 차단하고 Adblock 및 dnsmasq 규칙은 하위 도메인도 다룬다.

내보내기 파일은 python build/emit_stix.py, build/emit_misp.py, build/emit_denylist.py로 다시 생성한다. 기존 STIX 이용자를 위한 정정도 있다. 정상 드라이버 해시 6a4875ae86131a594019dec4abd46ac6ba47e57a88287b814d07d929858fe3e5는 활성 STIX 지표에서 제외됐다. 이전 피드를 가져왔다면 STIX 철회를 지원하는 도구에서 dist/adfection.withdrawals.stix.json을 처리하거나 기존 드라이버 규칙과 관계를 직접 제거해야 한다. 철회 파일은 이전 객체를 삭제하기 위한 것이며 탐지나 MVT 피드가 아니다. 검사에는 dist/adfection.stix.json을 계속 사용한다. 검사기와 MISP에서는 드라이버를 조사 단서로 명확히 표시하며, 이 해시만으로 스파이웨어 감염을 입증하지 않는다.

지표 목록은 오래될 수 있어 새 인프라와 만료된 도메인을 반영하려면 별도 업데이트 스크립트를 직접 실행해야 한다. 검사기 자체는 의도적인 네트워크 요청을 하지 않는다.

python scan/update-iocs.py # fetch, verify, show what changed (dry run) python scan/update-iocs.py --apply # also replace the local list

업데이트 스크립트는 HTTPS로 파일을 내려받고 공개된 SHA-256과 대조한 뒤, 파싱 가능한지 확인하고 변경 사항을 먼저 보여준다. 신뢰 모델과 한계는 스크립트 상단에 설명돼 있다. GPG 서명은 자동으로 확인하지 않는다. 서명된 릴리스 매니페스트는 v0.1.1에 포함된 IOC 파일을 인증하며 이후 개발 브랜치의 업데이트를 인증하지 않는다. 자세한 내용은 SIGNING.md를 참고할 수 있다.

설계 원칙은 지표에 접속하지 않기, 검사하지 못한 항목을 정상으로 처리하지 않기, 근거 없는 경보보다 정확성을 우선하기, 필요한 메타데이터만 조회하기, 읽기 전용·관리자 권한 불필요·텔레메트리 없음·의존성 없음이다. 네트워크 호출을 막는 Python 소켓 보호 장치는 운영체제 수준의 네트워크 샌드박스가 아니므로 엄격한 오프라인 경계가 필요하면 운영체제 격리를 사용해야 한다. 테스트는 네트워크 보호, 증거 등급, 경계 일치, 로더 실패, 쿠키 값 제외 여부와 브라우저 마스터 키를 읽지 않는 동작 등을 다룬다. 테스트 명령은 cd scan && python -m unittest discover -s tests 이다.

소프트웨어는 Apache License 2.0으로 제공된다. iocs/와 dist/의 지표 데이터는 CC0 1.0에 따라 공개돼 제한 없이 차단 목록, MISP, STIX 및 다른 도구에 복사할 수 있다. 이 프로젝트는 지표 출처이자 전문가 지원 기관으로 언급된 The Citizen Lab, Confiant, Recorded Future, Amnesty International, Access Now와 제휴하거나 이들의 승인을 받은 프로젝트가 아니다.

관련 자료: The Citizen Lab, Exposing AdFection (2026-10-15), Recorded Future / Insikt Group, Tracking Candiru's DevilsTongue Spyware (CTA-2025-0805). 보안 문제는 SECURITY.md에서 신고할 수 있다.