Documentation & Blog

김수키(Kimsuky)의 termsrv.dll 패치 기반 내부 침투 전략 분석

KWAKBUMJUN 2026. 4. 5. 22:55

들어가며: 공격자가 "원격 데스크톱"을 좋아하는 이유

APT 공격자에게 가장 이상적인 원격 접근 수단은 무엇일까? 커스텀 백도어? C2 셸? 의외로 답은 훨씬 평범하다 — RDP(Remote Desktop Protocol)다.

RDP는 Windows에 기본 내장되어 있고, 암호화된 정상 프로토콜이며, 관리자들이 일상적으로 사용한다. 트래픽 자체가 의심스럽지 않다. GUI 기반이라 파일 탐색, 문서 열람, 이메일 확인까지 자유롭다. 공격자 입장에서 RAT(Remote Access Trojan)보다 RDP가 더 편하고, 더 안전하다.

북한 연계 APT 그룹 Kimsuky(김수키)는 이 점을 정확히 간파했다. 그런데 한 가지 문제가 있었다. Windows 데스크톱 에디션은 RDP 동시 세션을 1개만 허용한다. 공격자가 RDP로 접속하는 순간, 피해자의 화면이 잠기고 세션이 끊긴다. 피해자는 즉시 이상을 눈치챈다.

Kimsuky의 해법은 우아할 정도로 단순했다: Windows의 세션 제한을 강제하는 시스템 DLL 자체를 바꿔버리는 것. 그 DLL이 바로 termsrv.dll이다.


1. Kimsuky는 누구인가

Kimsuky(또는 Black Banshee, Thallium, Velvet Chollima)는 2013년부터 활동이 확인된 북한 정찰총국 산하 사이버 공작 그룹이다. 한국, 일본, 미국의 정부 기관, 싱크탱크, 대학 연구자, 언론인을 주요 대상으로 삼는다.

이 그룹의 특징은 "기술적 정교함"보다 "사회공학적 끈기"에 있다. 몇 주에 걸쳐 신뢰를 쌓는 이메일 교신 후 악성 첨부파일을 보내는 식이다. 2024~2025년에는 DMARC 미설정 도메인을 악용한 이메일 스푸핑, GitHub를 C2로 활용한 XenoRAT 배포 등 전술을 지속적으로 진화시키고 있다.

최근 Kimsuky의 원격 접근 수단 변천사:

시기 주요 원격 접근 수단 특징
~2022 AppleSeed, Gold Dragon (커스텀 백도어) 자체 개발, 시그니처 노출 위험
2023 xRAT, TinyNuke + TightVNC (오픈소스 악용) 범용 도구로 귀속 난이도 상승
2023 하반기~ RDP Wrapper + Proxy 악성코드 정상 프로토콜 활용, 네트워크 탐지 우회
2024~ termsrv.dll 직접 패치 + RevClient 시스템 DLL 변조, 가장 은밀한 방식

이 변천사에서 읽을 수 있는 전략적 방향은 명확하다: 커스텀 악성코드에서 정상 인프라 악용으로, 네트워크 기반 탐지가 어려운 방식으로 진화하고 있다.


2. termsrv.dll의 정체: RDP의 심장부

2.1 Windows RDP 아키텍처에서의 위치

Windows의 원격 데스크톱 서비스(Terminal Services)는 svchost.exe 프로세스 내에서 호스팅되는 서비스로 동작한다. 이 서비스의 핵심 로직을 담당하는 라이브러리가 바로 C:\Windows\System32\termsrv.dll이다.

[RDP 클라이언트]
     │
     ▼ (TCP 3389, TLS 암호화)
[RDP 리스너 / 세션 브로커]
     │
     ▼
[svchost.exe -k NetworkService]
     │
     ├── termsrv.dll  ← 세션 관리, 라이선스 검증, 정책 강제
     ├── rdpcorets.dll (RDP 코어 전송)
     └── rdpbase.dll   (기반 라이브러리)
     │
     ▼
[csrss.exe / winlogon.exe / 사용자 세션]

termsrv.dll은 다음을 담당한다:

  • 세션 생성/관리: 새 RDP 세션의 생성, 기존 세션 연결, 세션 간 전환
  • 라이선스 정책 강제: Windows 에디션에 따른 동시 세션 수 제한
  • 인증 처리: NLA(Network Level Authentication) 등 연결 전 인증 절차
  • 세션 격리: 각 세션의 데스크톱 환경 격리 보장

2.2 "한 번에 하나만" — 세션 제한의 기술적 구현

Windows Server는 기본 2개, 라이선스 추가 시 무제한 RDP 세션을 허용한다. 하지만 Windows 10/11 데스크톱 에디션은 단 1개의 세션만 허용한다. 이것은 마이크로소프트의 라이선스 정책이며, 기술적으로는 termsrv.dll 내부의 다음 함수들이 이 제한을 강제한다:

함수 역할
CDefPolicy::Query() 핵심. 현재 세션 정책을 질의하여 추가 세션 허용 여부 결정
CSLQuery::Initialize() 라이선스 서버 초기화 및 라이선스 유효성 검증
CSessionArbitrationHelper::IsSingleSessionPerUserEnabled() 사용자당 단일 세션 제한 플래그 확인

CDefPolicy::Query()의 정상 동작을 의사코드로 표현하면 이렇다:

// 정상 CDefPolicy::Query() 의사코드 (단순화)
HRESULT CDefPolicy::Query(/* ... */) {
    // 현재 라이선스 유형 확인
    DWORD licenseType = this->m_PolicyData[0x3C / sizeof(DWORD)];

    if (licenseType == LICENSE_TYPE_CONCURRENT) {
        // 서버 에디션: 동시 세션 허용
        return S_OK;  // → 세션 생성 진행
    } else {
        // 데스크톱 에디션: 기존 세션 강제 종료 후 새 세션 생성
        return SINGLE_SESSION_ENFORCED;  // → 기존 사용자 로그오프
    }
}

이 함수의 반환 값 하나가 "동시 세션 허용 여부"를 결정한다. 공격자의 관점에서, 이 함수가 항상 "서버 에디션"처럼 동작하게 만들면 제한이 사라진다.

2.3 패치의 실체: 12바이트의 마법

ASEC의 분석에 따르면, Kimsuky가 CDefPolicy::Query() 내부에 적용한 패치는 다음과 같다:

패치 전 (정상 바이너리):

39 81 3C 06 00 00    ; cmp [rcx+0x63C], eax    ← 라이선스 유형 비교
0F 84 E7 43 01 00    ; jz  <single_session>    ← 일치하면 단일 세션 강제로 분기

패치 후 (변조된 바이너리):

B8 00 01 00 00       ; mov eax, 0x100          ← eax에 0x100(성공 코드) 저장
89 81 38 06 00 00    ; mov [rcx+0x638], eax    ← 정책 데이터에 성공 값 강제 기록
90                   ; nop                     ← 나머지 바이트 패딩

이 12바이트 패치가 하는 일을 풀어 설명하면:

  1. 원래 코드는 [rcx+0x63C]에 저장된 라이선스 유형을 eax와 비교(cmp)한다.
  2. 비교 결과가 같으면(jz, jump if zero) 단일 세션 강제 루틴으로 분기한다.
  3. 패치된 코드는 이 비교와 조건 분기를 완전히 제거하고, 대신 성공을 의미하는 값(0x100)을 정책 데이터 구조체에 직접 써넣는다.
  4. 결과적으로 CDefPolicy::Query()항상 "동시 세션 허용" 결과를 반환하게 된다.
[정상 실행 흐름]
CDefPolicy::Query() → 라이선스 확인 → 데스크톱 에디션 → 단일 세션 강제
                                                         ↓
                                              기존 사용자 강제 로그오프

[패치 후 실행 흐름]
CDefPolicy::Query() → (비교 건너뜀) → 항상 다중 세션 허용
                                         ↓
                              공격자와 피해자가 동시에 로그인 상태 유지

3. 전체 공격 흐름: 스피어 피싱에서 은밀한 동거까지

Kimsuky의 termsrv.dll 패치 공격은 독립적으로 수행되지 않는다. 이것은 다단계 침투 작전의 한 파트이며, 최종 목표인 "장기 은밀 접근"을 위한 인프라 구축 단계에 해당한다.

Phase 1: 초기 침투 — 스피어 피싱

[공격자] --→ 사전 조사 (LinkedIn, 학회 발표, 논문 저자)
    │
    ▼
"○○ 교수님, 최근 논문 관련 문의드립니다" (1~2주간 정상적인 이메일 교신)
    │
    ▼
"참고 자료 보내드립니다" → 문의사항.docx.lnk (이중 확장자 LNK 파일)
                          20241015_56801.docx.lnk
                          CSO_20240524.xlsx.lnk

LNK 파일은 실행 시 PowerShell 또는 Mshta를 통해 공격자의 C2 서버에서 추가 스크립트를 다운로드한다. 최근에는 Google Drive를 경유하는 사례도 확인되었다.

초기 정찰 스크립트 (hwp.bat):

  • WMIC 명령으로 설치된 안티바이러스 제품 확인
  • 시스템 정보 수집 후 C2로 전송
  • 안티바이러스 종류에 따라 후속 페이로드 선택

Phase 2: 거점 확보 — 백도어 & 키로거

구성 요소 파일명 역할
키로거 k.ps1 키보드 입력을 %APPDATA%\k.log에 저장
키로거 런처 OneNote.vbs k.ps1을 주기적으로 실행
로더 pow.ps1 암호화된 인젝터(desktop.r7u)를 복호화
인젝터 desktop.r7u MSBuild.exe에 RAT 인젝션
최종 페이로드 desktop.r3u xRAT 또는 KimJongRAT (암호화 상태)

실행 체인:

hwp.bat → OneNote.vbs + pow.ps1 설치
              │              │
              ▼              ▼
         k.ps1 실행     desktop.r7u 복호화
         (키로거)            │
                             ▼
                    MSBuild.exe에 xRAT 인젝션
                    (정상 프로세스 위장)

최근 변종에서는 PebbleDash 백도어를 활용하는 사례도 확인되었다. PebbleDash는 원래 Lazarus 그룹이 사용하던 도구인데, 2024년부터 Kimsuky가 재활용하기 시작했다. 주목할 점은 실행 방식의 변화다: 기존 regsvr32.exe를 통한 DLL 실행에서 LSA(Local Security Authority) 레지스트리에 DLL을 등록하여 lsass.exe 프로세스가 로드하는 방식으로 전환했다. lsass.exe는 보안상 중요한 시스템 프로세스라 보안 제품이 함부로 종료하거나 검사하기 어렵다는 점을 악용한 것이다.

Phase 3: RDP 인프라 구축 — termsrv.dll 패치

이 단계가 본 보고서의 핵심이다. 공격자는 multiple.exe라는 전용 도구를 사용한다.

multiple.exe의 PDB 경로 (개발 환경 흔적):

Z:\5-program\multiple\multisession_complete\Release\x64\Multisession.pdb
G:\0711_uac_multiple_work\multisession_complete\x64\Release\Multisession.pdb

이 PDB 경로에서 읽을 수 있는 정보:

  • 5-program: 공격자의 도구 분류 체계에서 5번째 카테고리
  • 0711_uac_multiple_work: 7월 11일에 UAC 우회 + 다중 세션 기능을 작업
  • multisession_complete: 다중 세션 패치가 도구의 핵심 목적임을 명시

multiple.exe 동작 순서:

① RDP 서비스 종료
   └── net stop TermService /y

② termsrv.dll 파일 권한 획득
   └── takeown /f C:\Windows\System32\termsrv.dll
   └── icacls C:\Windows\System32\termsrv.dll /grant Everyone:F

③ 원본 파일 백업 (이름 변경)
   └── rename C:\Windows\System32\termsrv.dll → termsrv.pdb

④ 패치된 DLL 복사
   └── copy %APPDATA%\termsrv.dll → C:\Windows\System32\termsrv.dll

⑤ RDP 서비스 재시작
   └── net start TermService

⑥ 은닉 계정 생성
   └── net user IIS_USER [password] /add
   └── net localgroup Administrators IIS_USER /add
   └── reg add "HKLM\...\SpecialAccounts\UserList" /v IIS_USER /t REG_DWORD /d 0

계정 은닉의 핵심: SpecialAccounts\UserList 레지스트리에 값 0으로 등록하면, 해당 계정은 Windows 로그인 화면에 표시되지 않는다. IIS_USER라는 이름은 IIS 웹 서버의 기본 서비스 계정처럼 보이도록 의도한 위장이다.

Phase 4: 은밀한 접근 경로 확보 — RevClient

termsrv.dll 패치로 다중 세션이 가능해졌지만, 외부에서 피해자 네트워크의 RDP 포트(3389)에 직접 접근하는 것은 방화벽에 막힐 수 있다. Kimsuky는 이를 해결하기 위해 RevClient라는 자체 제작 포트 포워딩 도구를 배포한다.

RevClient v1.0 설정 정보:

버전: 1.0
뮤텍스: ZhengReversePC
C2: 5.61.59[.]53:2086
로컬 RDP: 127.0.0.2:3389

동작 원리 — 리버스 터널링:

[공격자 PC]                    [C2 서버]                    [감염 시스템]
     │                      5.61.59.53:2086                     │
     │                            │                             │
     │    RDP 클라이언트 연결 ──→ │ ←── RevClient 역방향 연결    │
     │                            │         (감염 시스템이 먼저  │
     │    ◀──── 터널링 ────▶      │          C2에 연결)          │
     │                            │              │               │
     └────── RDP 세션 ──────────────────── 127.0.0.2:3389 ──────┘

RevClient는 리버스 커넥션 방식을 사용한다. 감염 시스템이 먼저 C2 서버에 연결하고, 이 연결을 통해 공격자의 RDP 트래픽을 감염 시스템의 로컬 RDP 포트로 중계한다. 감염 시스템이 아웃바운드 연결을 하는 것이므로, 인바운드 3389를 차단하는 방화벽을 우회한다.

RevClient C2 명령 체계:

명령 코드 기능 전략적 의미
100 포트 포워딩 시작 RDP 접근 경로 개통
200 사용자 계정 삭제 흔적 제거 (작전 종료 시)
300 사용자 계정 추가 + 은닉 새 접근 계정 생성 (기존 계정 노출 시)
400 포트 포워딩 종료 + 포트 초기화 일시 중단 (탐지 회피)
500 포트 포워딩 종료 접근 경로 차단

주목할 점은 계정 생성/삭제를 C2 명령으로 동적 제어한다는 것이다. 사고 대응팀이 계정을 발견하여 삭제해도, 공격자는 명령 하나로 새 계정을 즉시 생성할 수 있다.

Phase 5: 장기 운영 — 정보 수집

RDP 인프라가 구축되면, 공격자는 GUI 환경에서 자유롭게 활동한다:

  • 문서 탐색 및 탈취
  • 이메일 클라이언트 접근
  • 내부 네트워크 추가 정찰
  • 추가 도구 설치 (키로거, 화면 캡처, 웹캠 접근)

4. 공격자의 선택에 담긴 전략적 의도

4.1 "왜 미미카츠의 메모리 패치가 아니라 파일 교체인가?"

Mimikatz의 ts::multirdp 명령은 실행 중인 TermService 프로세스의 메모리에서 termsrv.dll의 특정 패턴을 찾아 실시간으로 패치한다. 이 방식은 재부팅하면 원래대로 돌아간다.

Kimsuky가 파일 교체를 선택한 이유는 지속성(Persistence) 때문이다:

비교 항목 메모리 패치 (Mimikatz) 파일 교체 (Kimsuky)
재부팅 후 패치 소멸, 재실행 필요 패치 유지
탐지 난이도 메모리 포렌식으로 탐지 파일 해시 비교로 탐지 가능하나, 무결성 모니터링 미운영 시 미탐지
의존성 Mimikatz 실행 필요 (탐지 위험 높음) 한 번 교체 후 도구 삭제 가능
안정성 OS 업데이트 시 패치 깨질 수 있음 파일 자체가 교체되어 업데이트 전까지 안정
추가 도구 Mimikatz 바이너리가 디스크에 존재해야 함 multiple.exe 실행 후 삭제 가능

Kimsuky의 선택은 명확하다: "한 번 패치하고 도구를 지우면, 시스템이 재부팅되어도 다중 세션이 유지되고, 패치 도구의 흔적은 남지 않는다."

4.2 "왜 RDP Wrapper가 아니라 DLL 직접 교체인가?"

Kimsuky는 이전 공격에서 오픈소스 도구인 RDP Wrapper를 사용한 이력이 있다. RDP Wrapper는 termsrv.dll을 수정하지 않고, SCM(Service Control Manager)과 TermService 사이에 래퍼 레이어를 삽입하는 방식이다.

하지만 RDP Wrapper는 파일이 디스크에 남고, rdpwrap.dll이라는 알려진 파일명이 시그니처 탐지에 걸리기 쉽다. termsrv.dll 직접 교체는:

  • 추가 DLL 파일 없음 (rdpwrap.dll 불필요)
  • 서비스 구성 변경 없음 (SCM 레이어 수정 불필요)
  • 시스템 DLL 자체가 "정상적으로 동작" — 단지 내용이 다를 뿐

4.3 "왜 계정 이름이 IIS_USER인가?"

무작위 문자열이나 "admin2" 같은 이름 대신, IIS_USER를 선택한 것은 의도적 위장이다. IIS(Internet Information Services)는 Windows 서버에서 흔히 사용하는 웹 서버이며, IUSR, IIS_IUSRS 같은 서비스 계정이 존재하는 것이 정상이다. 관리자가 계정 목록을 훑어보더라도 "IIS 관련 서비스 계정이겠지"라고 넘길 가능성이 높다.


5. 탐지가 어려운 이유: 방어자의 사각지대

5.1 "정상과 비정상의 경계가 없다"

이 공격의 가장 교활한 점은 개별 행위만 보면 모두 "있을 수 있는 일"이라는 것이다:

행위 정상 시나리오 공격 시나리오
termsrv.dll 교체 Windows 업데이트 Kimsuky 패치
관리자 계정 추가 IT 부서 작업 공격자 백도어 계정
RDP 서비스 재시작 유지보수 패치 적용을 위한 재시작
아웃바운드 TCP 연결 정상 서비스 통신 RevClient C2 통신
RDP 세션 접속 관리자 원격 접속 공격자 은밀 접근

5.2 네트워크 탐지의 한계

RevClient의 리버스 터널링을 통해 중계된 RDP 트래픽은, 네트워크 관점에서 볼 때 감염 시스템이 외부 IP에 TCP 연결을 하는 것에 불과하다. RDP 프로토콜 자체는 터널 내부에 캡슐화되어 있으므로, DPI(Deep Packet Inspection) 없이는 식별이 어렵다. 포트 번호도 3389가 아닌 C2 포트(예: 2086)를 사용한다.

5.3 파일 무결성 검증의 부재

대부분의 엔드포인트 보안 제품은 termsrv.dll지속적으로 모니터링하지 않는다. 이 파일은 시스템 보호(Windows File Protection/WRP) 대상이지만, 공격자가 takeownicacls로 권한을 가져간 후 교체하면 WRP가 즉시 감지하지 못하는 경우가 있다. 특히 TermService가 중지된 상태에서 교체가 이루어지면 파일 잠금도 없다.

5.4 계정 은닉의 효과

SpecialAccounts\UserList에 등록된 계정은:

  • Windows 로그인 화면에 표시되지 않음
  • net user 명령의 일반 출력에도 누락될 수 있음
  • 이벤트 로그에 로그인 기록은 남지만, 능동적으로 검색하지 않으면 발견하기 어려움

6. 방어 전략: 다층적 대응

6.1 즉시 적용 — 탐지 규칙

termsrv.dll 무결성 모니터링 (최우선):

# termsrv.dll 해시를 기준값과 비교하는 스케줄 작업
$baseline = "저장된_정상_해시값"
$current = (Get-FileHash C:\Windows\System32\termsrv.dll -Algorithm SHA256).Hash
if ($current -ne $baseline) {
    # 알림 발생: termsrv.dll 변조 감지
    Write-EventLog -LogName Security -Source "FileIntegrity" -EventId 9999 -Message "termsrv.dll modified!"
}

SpecialAccounts 레지스트리 감시:

모니터링 경로: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList
트리거: 새 값 생성 시 즉시 알림

Sysmon 탐지 규칙:

Event ID 탐지 대상 규칙
11 (FileCreate) termsrv.dll 파일 변경 TargetFilename contains termsrv.dll
13 (RegistryEvent) 은닉 계정 등록 TargetObject contains SpecialAccounts\UserList
1 (ProcessCreate) TermService 비정상 조작 CommandLine contains net stop TermService
1 (ProcessCreate) 파일 권한 탈취 CommandLine contains takeown AND termsrv
3 (NetworkConnect) RevClient C2 통신 DestinationPort = 비표준 포트 + 지속적 연결

6.2 예방 조치

RDP 접근 제한:

  • RDP 접근을 VPN 경유로만 허용
  • NLA(Network Level Authentication) 강제 활성화
  • 특정 IP/서브넷에서만 RDP 접속 허용 (GPO)

시스템 파일 보호 강화:

  • Windows Defender Credential Guard 활성화 (VBS 기반 보호)
  • HVCI(Hypervisor-Protected Code Integrity) 활성화 — 커널 및 시스템 DLL 무결성 보장
  • AppLocker 또는 WDAC 정책으로 takeown.exe, icacls.exe의 비인가 실행 차단

계정 보안:

  • 정기적 계정 감사 (SpecialAccounts 포함)
  • 관리자 그룹 변경 시 즉시 알림 설정
  • 강력한 비밀번호 정책 + MFA 적용

6.3 사고 대응 체크리스트

감염이 의심될 경우 확인할 항목:

□ C:\Windows\System32\termsrv.dll 해시를 동일 OS 버전의 정상 해시와 비교
□ C:\Windows\System32\termsrv.pdb 파일 존재 여부 확인 (원본 백업 흔적)
□ %APPDATA% 경로에 termsrv.dll 사본 존재 여부 확인
□ SpecialAccounts\UserList 레지스트리에 비인가 계정 등록 여부
□ 관리자 그룹에 알 수 없는 계정 존재 여부 (net localgroup Administrators)
□ TermService 비정상 재시작 이력 (이벤트 로그 7036)
□ %APPDATA%\k.log 파일 존재 여부 (키로거 로그)
□ 외부 비표준 포트로의 지속적 아웃바운드 연결 확인
□ MSBuild.exe의 비정상 네트워크 연결 또는 자식 프로세스

6.4 IOC (Indicators of Compromise)

파일 해시 (MD5):

02804d632675b2a3711e19ef217a2877
0d6717c3fa713c5f5f5cb0539b94b84f
0d691673af913dc0942e55548f6e2e4e
116a71365b83cc38211ccfc8059b363e
2dbe8e89310b42e295bfdf3aad955ba9

C2 인프라:

5.61.59[.]53:2086 (RevClient C2)
103.5.144[.]26, 159.100.13[.]216, 206.206.127[.]152 (관련 인프라)

악성 도메인:

onessearth[.]online
powsecme[.]co

주요 파일 경로:

%APPDATA%\termsrv.dll (사전 패치된 DLL)
%APPDATA%\k.log (키로거 출력)
%APPDATA%\Microsoft\desktop.r7u (암호화된 인젝터)

7. 맺으며: 12바이트가 만드는 전략적 우위

Kimsuky의 termsrv.dll 패치는 기술적으로 단순하다. 12바이트를 바꾸는 것이 전부다. 하지만 이 단순함 속에 정교한 전략이 숨어 있다:

12바이트 패치가 공격자에게 주는 것:

  • 피해자 모르게 동시 접속할 수 있는 은밀성
  • 시스템 재부팅에도 살아남는 지속성
  • 패치 도구를 삭제해도 효과가 유지되는 독립성
  • 정상 프로토콜(RDP)을 사용하는 정당성

방어자에게 요구하는 것:

  • 시스템 DLL의 지속적 무결성 모니터링
  • 숨겨진 계정을 찾아내는 능동적 감사
  • 정상 트래픽 속 비정상을 식별하는 행위 분석
  • "있을 수 있는 일"과 "있어서는 안 되는 일"을 구분하는 맥락적 판단

결국 이 공격이 어려운 이유는 기술적 복잡성이 아니라, 정상과 비정상의 경계가 모호하다는 것이다. termsrv.dll이 교체된 것은 Windows 업데이트일 수도, 공격일 수도 있다. IIS_USER 계정은 웹 서버 서비스 계정일 수도, 백도어일 수도 있다. RDP 세션은 관리자의 정상 접속일 수도, 공격자의 은밀한 침투일 수도 있다.

이 모호함을 해소할 수 있는 유일한 방법은 "정상 상태를 정의하고, 그로부터의 이탈을 지속적으로 감시하는 것"이다. 베이스라인 없이는 이상을 탐지할 수 없다.


참고 자료