Signature / Path — 서명과 경로 위생
Authenticode 서명과 파일이 놓인 경로는 신뢰의 첫 필터다. 유효하지 않거나 없는 서명과 사용자가 쓸 수 있는 경로를 함께 읽는다. 서명은 신원·무결성을 주장하고, 경로는 위치 기대치를 주장한다.
왜 중요한가
서명 상태는 Signed / NotSigned / HashMismatch(위조·변조 징후)로 나눠 본다. Authenticode가 말해 주는 것은 "서명자의 신원"과 "서명 이후 해시가 바뀌지 않았다"까지이고, 파일의 무해함은 말해 주지 않는다.
경로 위생은 반대 방향의 필터다. Downloads·Temp·AppData 같은 사용자가 쓸 수 있는 경로, 시스템을 가장한 이름(svch0st.exe, AppData 아래의 System32 비슷한 폴더)이 대표 리드(판정 전 재검증이 필요한 단서, 용어집)다. 서명과 경로는 이 축의 두 면이고, 둘 다 단독 판정이 아니라 교차 근거로 쓴다.
무엇인가
| 항목 | 설명 |
|---|---|
| 서명 상태 | Authenticode 세 상태: Signed(유효 서명) / NotSigned(서명 없음) / HashMismatch(서명은 있으나 해시 불일치·위조 징후) |
| 확인 도구 | 파일 속성 → 디지털 서명 탭, PowerShell Get-AuthenticodeSignature, Sysinternals sigcheck |
| 카탈로그 서명 | 서명은 파일 안에 넣거나(임베디드) 별도 카탈로그 파일(.cat)에 둔다. Windows 기본 파일 중에는 카탈로그로만 서명된 것이 있고, 빌드에 따라 이런 파일은 속성 창에 디지털 서명 탭이 없다. sigcheck -i(카탈로그 이름과 서명 체인 표시)나 카탈로그 서명도 읽는 Get-AuthenticodeSignature로 확인한다 |
| 대표 확인 명령 | sigcheck -a -h -accepteula <파일> (의심 파일을 하나씩 확인. -accepteula 필수) |
| 파일 출처 | 브라우저는 내려받은 파일에 Zone.Identifier 스트림을 붙인다. ZoneId(보안 영역, 3은 인터넷), ReferrerUrl(내려받기로 연결한 페이지), HostUrl(파일을 받은 주소)가 들어 있다. 탐색기로 압축을 풀면 풀린 파일에도 붙고 ReferrerUrl이 원래 압축 파일을 가리킨다. URL 항목은 브라우저와 버전에 따라 없을 수 있다. 조회는 Get-Content <파일> -Stream Zone.Identifier |
| 경로 위생 | 사용자 쓰기 가능 경로: Downloads·Temp·AppData·OneDrive·ProgramData·Performance·임의명 폴더·바탕화면 / 기대 경로: System32·정식 설치 디렉터리 / 동기화 폴더(클라우드) |
| 한계 | 서명됨 = 무해가 아니고, 서명 없음 = 치트가 아니다. 정상 프리웨어·자체 빌드도 서명이 없고, 서명된 로더도 존재한다 |
서명을 볼 때는 서명 상태(Status)뿐 아니라 서명자가 누구인지, 인증서 체인이 유효한지, 서명 시각(카운터서명 타임스탬프)이 합리적인지까지 본다. 서명자 이름과 파일 목적이 어긋나면 리드다.
SS에서 어떻게 쓰나
- T+25에 스캐너 히트·Prefetch·USN·BAM이 가리키는 실행 파일의 서명 상태를 확인한다.
- 파일이 존재하면 디지털 서명 탭 또는
Get-AuthenticodeSignature로 확인한다. 여러 개를 한 번에 볼 때는 sigcheck를 쓴다. 서명 탭이 없는 Windows 기본 파일은sigcheck -i로 카탈로그 서명을 확인한다. - 파일이 존재하면
Zone.Identifier로 내려받은 출처를 본다.HostUrl·ReferrerUrl의 도메인은 해시·문자열과 별개로 파일 정체를 보여 주는 근거다. 스트림은 편집할 수 있는 텍스트이고Unblock-File이 지우기도 하므로 단독으로 쓰지 않는다. - 경로를 기록한다. 사용자가 쓸 수 있는 경로, 무작위·일회성 폴더명, 클라우드 싱크 폴더를 표시한다.
- 시스템을 가장한 이름을 확인한다.
svch0st.exe처럼 한 글자 비틀기, 또는explorer.exe·svchost.exe가 AppData·Temp에 있는 경우는 즉시 리드다. - 파일이 삭제된 경우 경로와 "서명 불가(대상 없음)"를 기록한다. 이 결과도 증거다.
- 해시(SHA256)는 필요할 때 기록한다. 단일 파일만 조회하고, 대량 VT 업로드는 생략 가능하다.
우회 기법과 남는 흔적
| 기법 | 공격자가 하는 일 | 남는 흔적 |
|---|---|---|
| 확장자·이름 위장 | 실행 파일을 .txt·.jpg 등으로 바꾸거나 무해해 보이는 이름을 쓴다 | LNK의 대상 경로와 확장자, USN의 실제 파일명·RENAME 체인, 실행 이벤트(4688 계열)가 실체를 드러낸다. 프로세스는 원래 이름과 무관하게 실행 경로를 남긴다 |
| 시스템 이름 가장 | svchost.exe·explorer.exe 같은 시스템 이름으로 AppData·Temp에 둔다 | 경로가 기대치(System32)와 어긋난다. 서명 없음 또는 낯선 서명자, USN CREATE 기록 |
| 읽기 전용·권한 은닉 | 파일에 read-only와 권한 제한을 설정해 삭제·탐지를 막고 폴더를 숨긴다 | 폴더 권한 상속 비활성, 변경 권한 제한, 숨김 속성. dir /ah로 숨김 확인, 상속 비활성 버튼으로 ACL 조작 확인 |
| 유효 서명 남용 | 합법 서명자나 탈취·테스트 인증서로 치트에 서명해 "Signed"를 띄운다 | 서명자 이름과 파일 목적·배포 경로가 어긋난다. "서명됨"만으로 Clean 불가. 서명자 신원·시간·경로를 함께 본다. 다른 축(PF·BAM·USN)의 실행 정황이 남는다 |
| 배포 직후 삭제·교체 | 실행 후 파일을 지우거나 같은 이름의 정상 파일로 교체한다 | 서명 검사 자체가 불가능해진다. "대상 없음" 자체를 기록하고 PF·BAM·USN·깨진 LNK로 넘어간다 |
| 실행 이름 후킹 (IFEO) | Image File Execution Options(실행 파일 이름 단위로 대체 실행을 거는 레지스트리 키, 용어집)에 치트 exe 이름으로 Debugger 값을 건다. 검사자가 그 파일을 열면 정상 프로그램이 대신 뜬다 | IFEO 키는 레지스트리에 그대로 남아 전수 열거가 가능하다. 치트 이름의 exe에 Debugger가 걸린 것 자체가 시그니처다. "연 것"과 "실제 파일"을 실행 경로·서명으로 대조한다 |
| 경로 스왑 | 실행 후 치트를 다른 폴더로 옮기고, 기록된 원래 경로에 같은 이름의 정상 파일을 둔다 | 로그된 경로의 파일은 정상이지만 해시·크기·생성시각이 PF·BAM의 실행 시각과 불일치한다. USN의 move+create 연쇄가 스왑을 드러낸다 |
| 대체 데이터 스트림 숨김 | 실행 파일을 다른 파일의 ADS(NTFS 대체 데이터 스트림, 파일 뒤에 붙는 보조 영역, 용어집)에 넣는다. Zone.Identifier 같은 스트림 이름을 쓴다 | dir /r로 열거되는 스트림 목록, 정상 출처 표시치고 비정상적으로 큰 Zone.Identifier, USN의 스트림 생성 기록 |
| 이미지 이어붙이기 | 이미지 파일 뒤에 실행 파일을 이어붙여 확장자·미리보기 검사를 통과하게 한다 | 이미지 내용 대비 지나치게 큰 파일 크기, 파일 끝부분의 PE 헤더. 확장자가 .png여도 끝에 MZ·PE 구조가 있으면 리드다 |
| 바이너리 통째 교체 | 두 파일의 내용을 통째로 바꿔 이름·아이콘 기반 식별을 속인다 | 파일 크기·해시가 정품과 불일치하고 서명이 깨진다(HashMismatch 또는 무서명). 이름은 정상인데 내용이 다른 파일이다 |
| 유니코드 파일명 | 작은 대문자·공백류 글리프 같은 비ASCII 문자로 파일명을 지어 육안·검색을 회피한다 | 비ASCII 코드포인트 자체가 시그니처다. 파일 목록·파서 출력에서 이상 문자로 드러난다 |
| DLL 사이드로딩 | 서명된 정상 exe가 로드할 DLL을 같은 이름의 비정상 DLL로 교체하거나, exe 옆 검색 우선 폴더에 둔다. 정상 exe가 악성 DLL을 대신 로드한다 | 서명된 exe·정상 경로인데 로드된 DLL이 다르다. 모듈 목록에서 기대 위치(System32·설치 폴더)가 아닌 동명 DLL, 서명 없는 동명 DLL, 교체된 DLL의 USN rename·write 체인 |
| 자동시작 + 이름 위장 | startup 폴더에 두고 explorer.exe 같은 시스템 이름을 써서 프로세스 목록과 수동 기동 확인을 속인다 | 사용자 startup 폴더의 "explorer.exe"는 명백한 이상이다. startup 내용물은 전수 열거되고, 프로세스 이름과 실제 파일 경로·서명의 불일치가 드러난다 |
| 출처 표시 지우기 | Unblock-File이나 스트림 삭제로 Zone.Identifier를 없애 다운로드 출처를 감춘다 | 명명 스트림의 추가·삭제는 USN에 STREAM_CHANGE로 남는다. 출처 스트림이 없다는 사실만으로 로컬에서 만든 파일로 단정하지 않고, 같은 파일의 USN 레코드와 브라우저 다운로드 기록을 대조한다 |
이 기법들이 공통으로 노리는 것은 검증의 앞단이다. 경로가 기대치와 맞고, 이름이 정상이고, 서명이 있어도 그 파일이 그 파일이 아닐 수 있다. 서명·경로 축의 마지막 확인은 "이 파일이 원래 그 파일인가"다. 해시·크기·생성시각이 실행 기록의 시각과 맞는지, 로드된 모듈이 기대 위치에서 온 것인지까지 봐야 서명·경로 정합이 의미를 갖는다.
정상 vs 이상
| 구분 | 정상 | 이상 |
|---|---|---|
| 서명 | 알려진 벤더의 유효 서명 | 서명 없음, HashMismatch, 목적과 무관한 서명자 |
| 경로 | System32·정식 설치·게임 폴더 | Temp·Downloads·AppData·무작위 폴더 |
| 이름 | 고유 이름 | 시스템을 가장한 이름(svch0st, scvhost), 한 글자 비틀기 |
| 조합 | 서명+경로 모두 정합 | 경로 이상 + 서명 없음 조합 |
| 파일 정체성 | 경로의 파일이 기대 파일과 해시·시각이 맞는다 | 동명·동경로인데 생성시각·해시가 실행 시각과 불일치(스왑 의심), 스트림·이어붙이기 흔적 |
| 다운로드 출처 | 공식 배포처·게임 런처·패키지 저장소에서 받은 파일 | 치트 배포처 도메인을 가리키는 HostUrl·ReferrerUrl, 실행 파일의 출처 스트림을 지운 흔적(USN STREAM_CHANGE) |
오탐
- 서명 없는 정상 프리웨어·자체 빌드·소규모 도구는 흔하다.
- 커뮤니티 게임 모드나 모드 설치 과정에서 서명 없는 파일이 생긴다.
- 배포된 지 얼마 안 된 정식 파일은 알려진 서명 DB에 아직 올라오지 않았을 수 있다.
- 테스트·사내 인증서로 서명된 정상 도구가 있다.
- 오래된 정상 소프트웨어의 만료 서명: 타임스탬프 없이 서명된 파일은 서명 인증서가 만료되면 Windows가 무서명으로 취급한다. SHA-1로만 서명된 옛 파일도 Windows 10 이후 점차 신뢰받지 못한다.
- 직접 빌드한 오픈소스: 사용자가 소스에서 빌드한 도구는 서명 단계를 거치지 않으므로 무서명이 정상이다.
- 인터넷에서 받은 정상 파일에도
Zone.Identifier가 붙는다. 스트림이 있다는 것만으로는 의심 근거가 되지 않는다.
교차 검증
| 교차 카드 | 확인 내용 |
|---|---|
| R3-SCAN | 스캐너가 지목한 경로 |
| R3-PF·R3-BAM | 같은 경로의 실행 기록 |
| R3-USN | 경로의 파일 생성·이름변경·삭제 기록 |
| R3-PROC | 로드된 모듈의 서명·경로 |
서명·경로 단독으로는 Confirmed 불가다. 두 번째 독립 축이 받쳐야 한다.
증거 캡처
- 서명 탭 또는
Get-AuthenticodeSignature/ sigcheck 출력(상태 + 서명자 + 시간) - 경로·파일명·해시 기록
- 경로 위장 캡처(시스템 이름이 AppData에 있는 경우 등)
- 대상이 삭제돼 서명 불가인 경우 그 사실과 경로
Zone.Identifier출력(ZoneId·ReferrerUrl·HostUrl)- 서명 탭이 없는 파일의
sigcheck -i출력(카탈로그 이름·서명 체인)
모두 11-signature/에 둔다.
흔한 실수
- "서명 없음"만으로 Confirmed를 내린다. 절대 금지다.
- 서명됨을 "무해"로 읽는다. 서명은 신원과 무결성의 주장이다.
- 경로만 보고 "Temp에 있으니 치트"로 단정한다.
- VirusTotal 대량 업로드를 의무처럼 한다. 단일 파일만 조회하고, 해시는 필요시 기록한다.
Community. 현장 SS 플레이북은 히트 하나로 치트 사용을 확정하지 말고 다른 흔적과 맞춰 보라고 강조한다. 정상 exe 옆에 놓인 DLL이 의심스러우면 서명 여부 하나로 결론 내지 말고, DIE·문자열·해시 조회로 그 DLL이 벤더 라이브러리와 다르다는 것부터 입증하라고 안내한다.
Zone.Identifier도 인터넷에서 받은 파일에 정상으로 붙는 스트림이라 그것만으로는 치트로 보지 않는다.
Sources
- 서명 검증 모델: MS Authenticode
- 확인 도구: Sigcheck · Get-AuthenticodeSignature
- MS: 실행 파일 서명의 이해(카탈로그 서명과 임베디드 서명)
- Didier Stevens: 디지털 서명 탭이 없는 파일(카탈로그 서명)
- MS: Authenticode 서명의 타임스탬프(인증서 만료 뒤 유효성, SHA-1)
- Digital Detective: Zone.Identifier 스트림 분석 · TrustedSec Sysmon Community Guide: ZoneId·ReferrerUrl·HostUrl 정의
- MS Get-Content: -Stream 매개변수 · MS Unblock-File: Zone.Identifier 제거 · MS USN_RECORD_V2: STREAM_CHANGE 사유
- Schwarzahn: SS Playbook(현장 SS 도구 문서)
- MITRE: T1546.012 IFEO · T1564.004 NTFS ADS · T1574.002 DLL 사이드로딩
Next
- 프로세스·모듈 → Process / Module
- 삭제·은닉 대응 → 안티포렌식 패스
