들어가며
이 글은 상용 DLP(Data Loss Prevention) 프로그램의 핵심 기능을 분석하고, 윈도우 커널 드라이버 기반으로 직접 구현해보는 시리즈입니다.
지난 글에서는 Minifilter를 확장하여 '민감정보 패턴 검사'와 '파일 첨부 차단' 기능을 구현하는 과정, 그리고 그 과정에서 마주친 Office 파일(.xlsx) 검사의 딜레마를 어떻게 해결했는지 다루어 보았습니다.
이번 글에서는 DLP 시스템의 핵심 기능 중 하나인 파일 암호화 구현 과정을 다룹니다. 파일을 특정 '보안 폴더'에 넣으면 자동으로 AES-256 방식으로 암호화되어 전용 확장자(.siyul)로 저장되고, 더블클릭 시 패스워드를 입력하면 원래 프로그램으로 열리는 명시적 암호화(Explicit Encryption) 구조를 만들어 보겠습니다.
이전글 보러가기
https://imoracle.tistory.com/76
[DLP 개발기] 5. Minifilter 확장: 민감정보 패턴 검사와 파일 첨부 차단
들어가며이 글은 상용 DLP(Data Loss Prevention) 프로그램의 핵심 기능을 분석하고, 윈도우 커널 드라이버 기반으로 직접 구현해보는 시리즈입니다.지난 글에서는 네트워크 필터(WFP)의 한계와 유저모
imoracle.tistory.com
처음부터 보러가기
https://imoracle.tistory.com/72
[DLP 개발기] 1. 커널 드라이버 기반 보안 시스템, OpenGuard 시작하기
들어가며 다양한 기업용 PC 보안 솔루션을 접하다 보면 자연스레 호기심이 생깁니다. "이거 대체 어떻게 구현한 거지?" 사실 오래전, DLP 보안 솔루션 전문 기업에 입사 지원을 했다가 서류에서 탈
imoracle.tistory.com
1. 암호화 방식 선택: 이상과 현실의 타협점
DLP에서 파일을 암호화하는 방식은 크게 두 가지로 나뉩니다.
- 투명 암호화 (Transparent Encryption): 사용자는 암호화 사실을 모른 채 평소처럼 사용하지만, 커널의 Minifilter 단에서 디스크에 읽고 쓸 때 자동으로 암/복호화를 수행하는 방식입니다. (확장자 변경 없음)
- 명시적 암호화 (Explicit Encryption): 원본 파일을 암호화한 뒤 새로운 확장자를 부여하여, 사용자가 시각적으로 암호화된 파일임을 인지하게 하는 방식입니다.
투명 암호화를 포기한 이유
처음에는 기술적 성취를 위해 Minifilter를 이용한 투명 암호화에 도전했습니다. 하지만 구현 과정에서 개인 프로젝트의 범위를 넘어서는 심각한 OS 레벨의 문제들을 마주했습니다.
- Paging I/O 문제: Word나 Excel은 메모리맵 파일 방식을 사용합니다. 이 경우 일반적인 IRP_MJ_READ/WRITE가 아닌 IRP_PAGING_IO 플래그로 요청이 들어오는데, 이를 잘못 건드리면 캐시 매니저와 충돌하여 BSOD(블루스크린)가 발생합니다.
- 비정렬 쓰기 (Unaligned Write) 문제: AES는 16바이트 블록 단위로 동작합니다. 애플리케이션이 13바이트만 쓰기를 요청할 경우 패딩이 추가되어 파일 크기가 변하고, 결국 다음 쓰기 오프셋이 틀어져 복호화가 깨집니다.
- 오프셋 보정의 늪: 파일 앞단에 메타데이터(헤더)를 붙이면 실제 디스크 오프셋과 애플리케이션이 인식하는 오프셋이 달라집니다. 모든 I/O 작업에서 오프셋을 계산 및 보정해야 하며, 파일 크기 검사(IRP_MJ_QUERY_INFORMATION)까지 후킹하여 크기를 속여야 합니다.
- 캐시 매니저 충돌: 윈도우 캐시에는 평문이, 디스크에는 암호문이 저장되며 발생하는 불일치로 인해 파일이 손상될 위험이 큽니다.
이 문제들을 완벽하게 제어하려면 사실상 BitLocker 수준의 볼륨 암호화 드라이버를 개발해야 했습니다.
최종 선택: 유저모드 보안 폴더 감시 방식
상용 제품의 방식을 분석해 보니, 그들 역시 특정 확장자를 사용하는 명시적 암호화 방식을 택하고 있었습니다. 명시적 암호화라면 굳이 복잡하고 위험한 Minifilter를 고집할 필요가 없습니다.
에이전트에서 ReadDirectoryChangesW API로 특정 보안 폴더를 감시하는 유저모드 방식이 훨씬 간단하고 안정적이라는 결론을 내렸습니다.
작동 흐름: 보안 폴더 생성/수정 감지 → UI 팝업(비밀번호 입력) → 원본 파일 암호화(.siyul 생성) → 원본 삭제
이 방식은 Paging I/O나 캐시 충돌 문제가 전혀 없으며, 어떤 포맷의 파일이든 암호화가 가능하고 구현 난이도도 현실적입니다.
2. 고유 파일 포맷 설계: .siyul 헤더 구조
파일을 암호화할 때, 복호화에 필요한 메타데이터를 담을 자체 헤더 포맷을 설계했습니다. 총 128바이트로 구성됩니다.

Salt와 IV를 파일마다 랜덤으로 생성하는 이유
같은 패스워드로 동일한 내용을 암호화하더라도 결과물이 매번 다르게 나오도록 하여, Rainbow Table 공격이나 IV 재사용으로 인한 암호학적 취약점을 방지하기 위함입니다.

3. 암호화 코어 구현 (PBKDF2 & AES-256)
PBKDF2를 이용한 안전한 키 파생
사용자의 패스워드를 그대로 AES 키로 사용하는 것은 매우 위험합니다. PBKDF2(Password-Based Key Derivation Function 2)를 적용해 브루트포스 공격을 방어합니다.

AES-256-CBC 암호화 적용
Windows 내장 BCrypt API를 사용하여 AES-256-CBC 모드로 암호화를 수행합니다. CTR 모드에 비해 구현이 직관적이며, 파일 전체를 한 번에 처리하므로 랜덤 접근 문제를 고려하지 않아도 됩니다. PKCS7 패딩은 API에서 자동 처리하도록 설정했습니다.


4. 보안 폴더 감시 로직 (ReadDirectoryChangesW)
핵심 동작을 수행하는 백그라운드 스레드입니다. 지정된 보안 폴더(예: C:\SecureFolder\)의 변경 사항을 실시간으로 감시합니다.

5. WPF UI 연동과 사용자 경험(UX) 최적화
C++로 작성된 백그라운드 에이전트와 패스워드 입력을 받을 WPF 기반 UI 프로세스 간의 통신은 Named Pipe를 활용했습니다. 에이전트가 파일 생성을 감지하면 파이프를 통해 UI에 패스워드 팝업을 띄우라고 명령하는 구조입니다.
가장 신경 쓴 부분은 사용자 경험(UX) 입니다. 사용자가 암호화된 파일을 열람할 때의 이질감을 최소화하기 위해 레지스트리 작업을 추가했습니다.
- 확장자 등록: 에이전트 실행 시 .siyul 확장자를 OpenGuard.EncFile로 레지스트리에 등록합니다.
- 아이콘 적용: 자물쇠 모양의 전용 아이콘(siyul.ico)을 매핑합니다.
- 실행 연결: 더블클릭 시 OpenGuard 에이전트가 두 번째 인스턴스로 실행되도록 연결(ShellExecute)합니다.
더블클릭 시 열람 시나리오

사용자가 .siyul 더블클릭 → 에이전트 실행 → 파이프라인을 통해 패스워드 UI 호출 → 복호화된 데이터를 %TEMP% 경로에 원본 확장자로 임시 저장 → ShellExecuteW로 원본 연결 프로그램(Word, 뷰어 등) 실행 → 3초 후 임시 파일 완전 삭제.
이 흐름 덕분에 사용자는 마치 암호화된 알집 파일을 열어보는 것과 같이 자연스러운 경험을 할 수 있습니다.

6. 트러블슈팅
개발 과정에서 마주친 주요 이슈와 해결 방법입니다.
| 문제 | 원인 | 해결 |
| Minifilter 투명 암호화 BSOD 및 데이터 깨짐 | Paging I/O, 비정렬 쓰기, 캐시 매니저 충돌 | 커널 레벨 투명 암호화를 포기하고 유저모드 보안 폴더(명시적 암호화) 방식으로 아키텍처 전면 전환 |
| 패스워드 입력 팝업이 뜨지 않음 | Named Pipe 권한을 단방향(PIPE_ACCESS_OUTBOUND)으로 설정하여 응답 수신 불가 | 양방향(PIPE_ACCESS_DUPLEX)으로 변경하고 Password 전용 Pipe 채널 분리 |
| C 컴파일 빌드 오류 (goto 구문 관련) | goto 레이블 뒤에서 변수를 초기화하여 스코프 문제 발생 | 변수 선언 및 초기화를 goto 호출부 이전으로 모두 이동 |
| 더블클릭 실행 시 인자(argc) 누락 | WinMain에서 커맨드라인 파싱 누락 | GetCommandLineW() + CommandLineToArgvW 조합으로 파일 경로 파싱 로직 추가 |
| 로그 서버 전송 시 한글 파일명 깨짐 | 에이전트(C++)와 웹 콘솔(PHP) | PHP의 json_encode에 JSON_UNESCAPED_UNICODE 옵션 추가 |
Windows DLP 프로그램 만들기 - 잠정 중단을 알리며
OpenGuard DLP 시리즈를 읽어주신 분들께 감사드립니다. 이번 글은 다음 편 예고가 아닌, 시리즈의 잠정적 중단을 알리는 글입니다.
지금까지 만든 것들
처음에는 오피스키퍼 같은 상용 DLP 프로그램이 대체 어떻게 동작하는지 궁금해서 시작했습니다. 커널 드라이버 한 줄 없이 시작해서, 결국 이 정도까지 왔습니다.
커널 드라이버 (KMDF) + IOCTL 통신
소프트웨어 실행 차단 (PsSetCreateProcessNotifyRoutineEx)
USB 차단 (PnP 콜백)
Minifilter 파일 확장자 차단
Minifilter 민감정보 패턴 검사 (주민번호, 카드번호, 전화번호)
파일 첨부 차단 (브라우저/메일 프로세스 감지)
WFP DNS 쿼리 감지
클립보드 차단
보안 폴더 AES-256 파일 암호화 (.siyul)
WPF 트레이 UI + Named Pipe 통신
PHP/MariaDB 관리자 웹 콘솔
에이전트 체크인 + 정책 폴링
로그 수집 및 서버 전송
처음 목표였던 "상용 DLP의 동작 원리 이해" 는 충분히 달성했다고 생각합니다.
배운 것들
코드보다 더 값진 것들을 배웠습니다.
왜 상용 DLP가 무겁고 복잡한지
투명 암호화를 시도하다가 Paging I/O, 비정렬 쓰기, 캐시 매니저 충돌 문제를 직접 겪고 나서야 이해했습니다. 명시적 확장자를 쓰는지, 상용 제품들이 왜 그렇게 많은 예외 처리를 하는지 — 직접 부딪혀보지 않으면 절대 알 수 없는 것들이었습니다.
WFP의 한계
DNS 쿼리 감지까지는 성공했지만 실제 차단에서 Windows DNS Client 서비스의 캐시 구조 때문에 막혔습니다. 단순해 보이는 "웹사이트 차단" 하나도 NDIS 드라이버 레벨이나 SSL Inspection 없이는 완전히 구현하기 어렵다는 걸 배웠습니다.
커널 개발의 현실
INF 파일 변수 치환 버그, EPROCESS 오프셋 버전 차이, initguid.h 순서 문제, Paging I/O와 캐시 충돌... 문서에 없는 것들을 직접 트러블슈팅하면서 커널 개발이 왜 어렵다고 하는지 몸으로 느꼈습니다.
남은 것들
시리즈를 마무리하면서 아직 구현하지 못한 것들이 있습니다.
자기 보호 (ObRegisterCallbacks) < 이전 커널안티치트의 보호원리와 우회기법 포스팅에서 이미 다루어 보았습니다
xlsx 민감정보 검사 (ZIP 해제 + XML 파싱)
출력물 워터마크 (GDI 후킹) < 포스팅 하지는 않았으나 개별적으로 해당 기능만 구현했던 적이 있어 넘겼습니다
완전한 웹사이트 차단 (NDIS 레벨)
승인 요청 시스템
.siyul 파일 더블클릭 복호화 안정화
이것들을 구현하지 못한 게 아쉽지 않다면 거짓말이지만, 지금 당장 이 프로젝트를 계속 이어갈 여유가 없을 뿐더러 구현 해보고자 한 기능들은 구현하였습니다, 다른 공부해야 할 것들도 쌓여 있고, 블로그 글 정리하는 것도 체력이 필요한 일이라서요.
마치며
이 시리즈를 쓰면서 가장 많이 들었던 생각은 "이걸 만드는 사람들은 대단하다" 였습니다.
화면에 보이는 건 트레이 아이콘 하나지만, 그 뒤에는 커널 드라이버, Minifilter, WFP, Named Pipe, 암호화 라이브러리, 관리자 웹 콘솔이 전부 맞물려 돌아가고 있습니다. 상용 제품들이 수십 명의 개발자와 수년의 시간을 들이는 게 이유가 있다는 걸, 혼자 따라 만들어보면서 실감했습니다.
코드는 여전히 불완전하고, 실제 배포하기엔 멀었습니다. 하지만 그게 목적이 아니었으니까요.
궁금한 게 있으시면 댓글로 남겨주세요. 언젠가 다시 이어갈 수 있으면 좋겠습니다.
감사합니다
이전글 보러가기
https://imoracle.tistory.com/76
[DLP 개발기] 5. Minifilter 확장: 민감정보 패턴 검사와 파일 첨부 차단
들어가며이 글은 상용 DLP(Data Loss Prevention) 프로그램의 핵심 기능을 분석하고, 윈도우 커널 드라이버 기반으로 직접 구현해보는 시리즈입니다.지난 글에서는 네트워크 필터(WFP)의 한계와 유저모
imoracle.tistory.com
처음부터 보러가기
https://imoracle.tistory.com/72
[DLP 개발기] 1. 커널 드라이버 기반 보안 시스템, OpenGuard 시작하기
들어가며 다양한 기업용 PC 보안 솔루션을 접하다 보면 자연스레 호기심이 생깁니다. "이거 대체 어떻게 구현한 거지?" 사실 오래전, DLP 보안 솔루션 전문 기업에 입사 지원을 했다가 서류에서 탈
imoracle.tistory.com
'Project > [DLP] OpenGuard' 카테고리의 다른 글
| [DLP 개발기] 5. Minifilter 확장: 민감정보 패턴 검사와 파일 첨부 차단 (0) | 2026.05.08 |
|---|---|
| [DLP 개발기] 4. WFP DNS 차단의 한계와 유저모드 클립보드 제어 (0) | 2026.05.06 |
| [DLP 개발기] 3. WPF 트레이 앱 통신과 커널 레벨 매체/파일 제어 (USB & Minifilter) (0) | 2026.05.06 |
| [DLP 개발기] 2. 커널 드라이버와 IOCTL, 그리고 E2E 파이프라인 구축 (0) | 2026.04.29 |
| [DLP 개발기] 1. 커널 드라이버 기반 보안 시스템, OpenGuard 시작하기 (0) | 2026.04.29 |