# AEGIS

윈도우 취약점 진단 · 자동 조치 콘솔.

실행 파일 하나. 설치 없음. 외부 의존성 없음.
진단 결과를 보여주기만 하는 게 아니라 **되돌릴 수 있게 고친다.**

```
aegis.exe          더블클릭 → 웹 콘솔이 열린다
```

---

## 무엇을 하는가

| | |
|---|---|
| **진단** | 107개 룰로 이 PC 의 설정·계정·서비스·정책을 점검 |
| **CVE 조회** | 설치된 소프트웨어를 NVD · CISA KEV · FIRST EPSS 와 대조 |
| **자동 조치** | 발견한 문제를 적용하고, 언제든 되돌린다 |
| **변화 추적** | 지난 진단 대비 무엇이 새로 생기고 사라졌는지 |
| **위험 수용** | 받아들이기로 한 항목은 사유와 함께 남기고 다음 진단에서 다시 뜨지 않는다 |
| **개선 계획** | 무엇을 고치면 몇 점이 되는지. 다음 등급까지 최소 몇 건인지 |
| **항목 재확인** | 밖에서 직접 고친 항목만 0.3초에 다시 확인 (전체 진단 21초) |
| **취약 드라이버** | 랜섬웨어가 백신을 끄는 데 쓰는 서명된 드라이버(BYOVD) 34종 탐지 |
| **KEV 감시** | 재스캔 없이 "오늘 실제 악용이 확인된" 취약점을 알림 |
| **경량 감시** | 5분마다 포트·방화벽·Defender·관리자 그룹 변화 감시 |
| **예약 진단** | 작업 스케줄러에 등록. 꺼져 있어도 약속한 시각에 실행 |
| **네트워크 스캔** | 대역 포트 스캔 + TLS·인증서 점검 |
| **심층 정찰** | IP·웹 대상의 서비스 버전을 실제 CVE·KEV·EPSS 와 대조 + 보안 헤더 등급 + 노출 점검 |

---

## 설계 원칙

### 되돌릴 수 없는 변경은 만들지 않는다

모든 조치는 다음 순서를 강제한다. 하나라도 실패하면 진행하지 않는다.

```
관리자 권한 확인
  → 조치 직전 값 캡처      ← 실패하면 여기서 중단
  → 적용
  → 검증
  → 롤백 스크립트와 함께 저널에 기록 (append-only, fsync)
```

3번에서 실패하든 4번에서 실패하든, 저널에는 이미 되돌리는 법이 적혀 있다.

### 외부 의존성 0

`go.mod` 에 아무것도 없다. UI 도 트레이 아이콘도 전부 표준 라이브러리와 syscall 로 만들었다.
받아서 실행하면 그걸로 끝이고, 공급망을 통해 들어올 것도 없다.

### 로컬에만 바인딩

`127.0.0.1` 외에는 바인딩을 거부한다. 그 위에:

- 192비트 세션 토큰
- DNS 리바인딩 방지 (Host 헤더 검증)
- CSRF 방지 (Origin 검증 — 부분 문자열이 아니라 파싱해서 호스트 비교)
- 토큰 상수 시간 비교
- CSP `default-src 'self'` — 외부로 나가는 통로 자체가 없다

### 수집은 한 번, 평가는 메모리에서

룰마다 PowerShell 을 부르면 107개에 50초가 걸린다.
그래서 사실을 **한 번에 전부** 긁어오고(13개 수집기 병렬) 룰 평가는 Go 메모리에서 한다.
룰이 200개로 늘어도 평가는 밀리초 단위다.

---

## 사용법

### 웹 콘솔

```
aegis.exe
```

UAC 승인 후 콘솔 창이 열린다. **검은 콘솔 창은 뜨지 않는다.**

UI 는 실행 파일에 embed 된 웹 화면이고, `127.0.0.1` 에만 바인딩된 로컬 서버가 띄운다.
Edge 나 Chrome 의 앱 모드(`--app=`)로 열어 주소창과 탭이 없는 창 하나로 보인다 —
둘 다 없으면 기본 브라우저로 물러선다.

네이티브 GUI 대신 이 방식을 쓴 이유는 **의존성 0** 때문이다.
GUI 프레임워크를 끌어오면 단일 8MB 바이너리와 "공급망으로 들어올 것이 없다"는
전제가 함께 무너진다.
프로그램은 트레이에 상주한다 — 우클릭하면 콘솔 열기 / 지금 진단 / 로그 / 종료.

관리자 권한이 필요한 이유: BitLocker, LSA 설정, 로컬 보안 정책, 감사 정책은
관리자가 아니면 **읽을 수도 없고** 자동 조치는 전부 막힌다.

### 터미널

```
aegis.exe -scan                    호스트 진단 후 결과 출력
aegis.exe -scan -intel             CVE 조회 포함
aegis.exe -net 192.168.0.0/24      네트워크 스캔
aegis.exe -net 10.0.0.1-50 -ports web
aegis.exe -port 8080               웹 콘솔 포트 지정
aegis.exe -data D:\aegis-data      데이터 폴더 지정
```

GUI 서브시스템으로 빌드됐지만 터미널에서 실행하면 그 콘솔에 붙는다.
리다이렉션도 정상 동작한다 — `aegis.exe -scan > result.txt`

---

## 화면

| 화면 | 내용 |
|---|---|
| **대시보드** | 보안 점수, 영역별 위험 분포, 실행 로그, 최우선 조치 대상 |
| **발견 사항** | 전체 목록. 심각도·영역·조치 방식으로 필터 |
| **변화** | 지난 진단 대비 신규 / 악화 / 해소, 점수 추이 |
| **네트워크** | 대역 스캔, IP 탭별 포트 목록, TLS 점검 결과 |
| **인벤토리** | 수집한 사실 전체 (소프트웨어·포트·계정·서비스·패치) |
| **조치 기록** | 적용한 조치와 되돌리기 |
| **설정** | 자동 조치 정책, 예약 진단, KEV 감시, 룰 카탈로그 |

---

## 데이터

기본 위치는 실행 파일 옆 `data/` 다. 쓰기가 막힌 곳에 설치했다면
`%LOCALAPPDATA%\AEGIS\data` 로 물러선다.

```
data/
  inventory.json     마지막 수집 결과
  scans.json         진단 이력
  scans/*.json       진단별 발견 사항
  journal.jsonl      조치 기록 (append-only)
  settings.json      설정
  cache/intel.json   CVE 조회 캐시
  aegis.log          실행 로그
```

전부 이 PC 안에만 있다. 진단 결과가 외부로 나가는 경로는 없다.
바깥으로 나가는 통신은 CVE 조회(NVD · CISA · FIRST) 뿐이고, 그것도 끌 수 있다.

---

## CVE 조회와 캐시

NVD 는 익명 요청을 30초당 5회로 제한한다. 그래서 결과를 제품별로 캐시한다.

| 나이 | 동작 |
|---|---|
| 24시간 내 | 캐시 그대로 — 네트워크를 안 쓴다 |
| 7일 내 | **캐시로 즉시 답하고** 갱신은 진단이 끝난 뒤 백그라운드로 |
| 7일 초과 | 그때만 조회를 기다린다 |

두 번째 진단부터는 기다림이 없다.

**KEV 와 EPSS 는 API 키가 필요 없다.** 가장 중요한 판단 근거
("실제로 악용되고 있는가", "30일 내 악용 확률")는 항상 나온다.

---

## 개선 계획

발견 사항이 76건이면 사람은 목록을 닫는다. 어디부터 손대야 하는지,
손대면 무엇이 달라지는지 알 수 없기 때문이다.

대시보드는 두 가지를 함께 답한다.

- **자동 조치를 누르면 몇 점이 되는가** — 버튼 옆에 `12 → 14 F` 로 붙는다.
  올라가는 폭이 작으면 그것도 사실이다. 설정 하드닝으로는 해결되지 않는
  PC 라는 뜻이고, 그걸 숨기면 버튼만 누르고 끝내게 된다.
- **다음 등급까지 최소 몇 건인가** — `D 까지 45건` 을 누르면 발견 사항이
  정확히 그 45건으로 걸러진다. 위험이 큰 것부터 빼는 것이 최적이므로
  이 개수는 최소값이 보장된다.

위험이 소수 항목에 몰려 있으면 등급 대신 그걸 먼저 말한다 —
`위험의 54%가 4건에 몰려 있다`. 쏠림이 없으면 이 줄은 나오지 않는다.

---

## 항목 재확인

AEGIS 밖에서 직접 고치는 일이 많다. 포트를 닫고, 프로그램을 지우고, 설정을 바꾼다.
그때마다 전체 진단(21초)을 돌리라고 하면 아무도 안 한다.
그 21초는 수집기 하나가 거의 다 쓰는 것이라 일부만 돌려도 줄지 않는다.

그래서 상세 화면의 **다시 확인** 은 그 룰이 보던 값 하나만 다시 읽는다. 0.3초다.
해소됐으면 상태가 바뀌고 점수가 즉시 따라온다.

다시 읽을 방법이 정의된 항목만 가능하다 — 검증 스크립트가 있는 룰, 포트, 드라이버.
나머지는 "전체 진단이 필요하다" 고 정직하게 답한다.
확인할 수 없는데 확인했다고 하면 고쳐진 줄 알고 넘어가게 되므로, 못 하는 것보다 나쁘다.

---

## 취약 드라이버 (BYOVD)

하드닝 룰을 다 지켜도 커널로 올라오는 길이 하나 남는다.

공격자는 취약점을 찾는 대신 **정품 서명이 붙은 취약 드라이버**를 가져와 설치한다.
서명이 유효하므로 드라이버 서명 강제를 통과하고, 그 드라이버의 임의 메모리 쓰기
기능으로 커널에 올라가 백신과 EDR 을 꺼 버린다.
랜섬웨어가 암호화를 시작하기 직전에 하는 일이 정확히 이것이다.

AEGIS 는 실제 사고에서 반복 등장한 34종을 이름으로 찾는다.
해시가 아니라 이름으로 찾는 이유가 있다 — 이 파일들은 악성코드가 아니다.
MSI Afterburner 를 정상 설치해도 `RTCore64.sys` 는 그대로 들어오고,
어느 경로로 들어왔든 똑같이 취약하다. 공격자는 이미 이 PC 에 있는 것을 쓰면 그만이다.

찾은 파일의 SHA256 을 함께 싣는다. loldrivers.io 나 VirusTotal 에서 바로 대조하라고.

---

## 위험 수용

고칠 수 없거나 고치지 않기로 한 항목이 있다. 재택근무용으로 열어 둔 3389 같은 것들이다.
그런 항목을 매 진단마다 다시 보게 두면 목록 전체를 안 보게 된다.

발견 사항 상세에서 **위험 수용** 을 누르면 사유와 함께 기록되고 점수에서 빠진다.

수용은 발견 사항이 아니라 **룰 + 대상** 에 걸린다. 발견 사항 ID 에는 스캔 ID 가
들어 있어서, ID 에 걸면 다음 진단에서 새 ID 가 생겨 수용이 통째로 풀린다.
대상까지 키에 넣기 때문에 이 PC 의 3389 를 받아들여도 네트워크 스캔이 찾은
다른 장비의 3389 는 그대로 뜬다.

받아들인 항목은 **설정 → 받아들인 위험** 에 전부 나열된다. 점수에서 빠지는 항목이
보이지 않으면 그 자체가 구멍이기 때문이다. 되돌리면 즉시 다시 열린다.

---

## 자동 조치

기본은 **꺼져 있다.** 켜려면 룰을 하나씩 명시해야 한다.

세 조건을 모두 만족해야 후보가 된다:

1. 카탈로그가 `auto` 등급으로 판정한 것 (부작용 가능은 `guard` 등급으로 분리돼 있다)
2. 롤백 가능 — 캡처와 복원 스크립트가 정의된 것
3. 화이트리스트에 룰 ID 가 명시된 것

카테고리나 심각도 단위 허용은 **없다.** 다음에 룰이 추가될 때
무엇이 적용될지 아무도 모르게 되기 때문이다.

한 회차 상한은 10건이다. 정책이 잘못 걸렸을 때 되돌릴 양을 예측 가능하게 가둔다.

**드라이런을 먼저 쓸 것.** 며칠 동안 "무엇이 적용됐을지" 를 확인한 뒤 실제 적용으로 바꾼다.

---

## 심층 정찰 (원격 취약점 스캔)

포트 스캔이 "3306 이 열려 있다"까지 안다면, 심층 정찰은 "그 MySQL 이 지금 악용되는
CVE 3건에 노출돼 있다"까지 간다. 네트워크 스캔 화면에서 **심층 정찰**을 켜면 세 계층이
포트·배너·TLS 위에 얹힌다.

**서비스 → CVE 대조.** 배너에서 읽은 제품·버전(nginx 1.18.0, OpenSSH 8.2 …)을
호스트 진단이 쓰는 것과 **같은 NVD·KEV·EPSS 엔진**에 물린다. 로컬 소프트웨어 진단을
위해 이미 만든 엔진이라, 원격 대상에도 KEV(실제 악용)·EPSS(악용 확률) 우선순위가
그대로 붙는다. 대부분의 오픈소스 포트 스캐너에 없는 부분이다.

**HTTP 딥 스캔.** 열린 웹 포트에 요청을 한 번 보내 보안 헤더를 A+~F 로 채점하고
(CSP·HSTS·X-Frame·COOP …), Server·X-Powered-By·generator 메타·쿠키로 기술 스택을
식별해 다시 CVE 엔진으로 보낸다. 세션 쿠키의 Secure·HttpOnly·SameSite 도 본다.

**노출 점검.** nuclei 방식이되 네이티브·안전하다. `.git`·`.env`·백업 파일 노출,
디렉터리 리스팅, server-status·phpinfo, 관리 패널 노출을 **탐지만** 한다 —
익스플로잇도, 비밀번호 시도도 없다. 점검은 선언형 Go 구조체라 표에 한 줄 더 넣어
늘린다. YAML 엔진을 끌어오지 않아 단일 바이너리·의존성 0 을 지킨다.

서비스 배너는 텍스트뿐 아니라 MySQL·MariaDB·Redis 같은 바이너리 핸드셰이크에서도
버전을 뽑는다. 포트를 힌트로 프로토콜별 해석을 한 번 더 시도한다.

발견은 전부 호스트 진단과 같은 model.Finding 이라, 같은 드로어·리포트·위험 점수·
변화 추적을 그대로 재사용한다.

### nuclei 연동 (선택)

nuclei 를 번들하지 않는다 — 단일 바이너리·의존성 0 이 무너지기 때문이다. 대신
`nuclei` 가 PATH 에 설치돼 있으면 감지해서 심층 정찰에 함께 태운다. 결과는 같은
발견 모델로 흡수된다. 없으면 조용히 네이티브 계층만 돈다. 12,000개 넘는 템플릿을
쓰고 싶은 사람은 nuclei 만 따로 설치하면 되고, 나머지 사람은 아무것도 안 해도 된다.

### 안전하게

심층 정찰은 대상에 실제 HTTP 요청을 보낸다. 그래서 시작 전 **스코프 확인**을 켜야 한다 —
본인 소유이거나 명시적 허가를 받은 대상임을 명시하는 것이다. 모든 점검은 비침투적이고
(익스플로잇·무차별 대입·서비스 거부 없음), 대상 로그에 요청 기록이 남는다는 사실도 그대로 알린다.

---

## 네트워크 스캔에 대하여

본인 소유이거나 **명시적 허가를 받은** 대상에만 사용해야 한다.
무단 포트 스캔은 정보통신망법 위반이며, 대상 시스템의 로그에 기록된다.

이 프로그램은 그 판단을 대신해 주지 않는다.

---

## 빌드

```
go build -ldflags="-H=windowsgui -s -w" -o aegis.exe .
```

`-H=windowsgui` 로 콘솔 창을 없앤다. 이때 반드시 자식 프로세스에
`CREATE_NO_WINDOW` 를 걸어야 한다 — 안 그러면 부모 콘솔이 없어지는 순간
PowerShell 자식들이 각자 창을 띄운다. 수집기가 13개 병렬이라 진단 한 번에
검은 창이 13번 깜빡인다. (`hide_windows.go` 참고)

아이콘·버전 정보·UAC 매니페스트는 `rsrc_windows_amd64.syso` 에 들어 있다.
다시 만들려면:

```
windres -c 65001 -i aegis.rc -O coff -o rsrc_windows_amd64.syso
```

### 테스트

```
go test ./...
```

핵심 판단은 전부 테스트로 고정돼 있다 — 변화 비교 키, KEV 첫 실행 억제,
자동 조치 안전 조건, Origin 검증, 리포트 XSS 이스케이프, 예약 등록 왕복.

---

## 요구 사항

- Windows 10 / 11
- 관리자 권한 (진단 항목의 상당수와 모든 자동 조치에 필요)
- PowerShell 5.1 이상 (윈도우 기본 포함)
- CVE 조회에만 인터넷 — 없어도 설정 점검은 전부 동작한다
