들어가며
지난 1편에서 설계한 아키텍처를 바탕으로, 이번 편에서는 실제로 데이터가 흐르고 동작하는 E2E(End-to-End) 파이프라인을 완성해 보겠습니다.
목표는 심플합니다. "관리자 웹에서 정책을 변경하면, 30초 안에 커널 드라이버까지 도달해 실제 차단이 이루어지게 만든다."
이전편 보러가기
https://imoracle.tistory.com/72
[DLP 개발기] 1. 커널 드라이버 기반 보안 시스템, OpenGuard 시작하기
들어가며 다양한 기업용 PC 보안 솔루션을 접하다 보면 자연스레 호기심이 생깁니다. "이거 대체 어떻게 구현한 거지?" 사실 오래전, DLP 보안 솔루션 전문 기업에 입사 지원을 했다가 서류에서 탈
imoracle.tistory.com
다음편 보러가기
https://imoracle.tistory.com/74
[DLP 개발기] 3. WPF 트레이 앱 통신과 커널 레벨 매체/파일 제어 (USB & Minifilter)
들어가며이 글은 오피스키퍼 등 상용 DLP(Data Loss Prevention) 프로그램의 동작 원리를 분석하고, 윈도우 커널 드라이버 기반의 보안 솔루션을 직접 구현해보는 시리즈입니다.지난 2편에서는 커널 드
imoracle.tistory.com
전체 데이터 흐름 (Data Flow)
시스템은 크게 웹 서버, 유저모드 에이전트, 커널 드라이버 3단계로 동작합니다. 커널 드라이버가 직접 네트워크 통신을 하는 것은 보안상, 안정성상 위험하므로 에이전트가 중간 다리 역할을 수행합니다.

프로젝트 구조 설계
솔루션(OpenGuard.sln)은 역할에 따라 4개의 프로젝트로 깔끔하게 분리했습니다.
- OpenGuard_Driver : KMDF 기반 커널 드라이버 프로젝트
- OpenGuard_Agent : C++ Win32 기반 백그라운드 서비스 (에이전트)
- OpenGuard_Common : 드라이버와 에이전트가 통신 규격을 공유하는 공통 헤더
- OpenGuard_UI : 사용자에게 보여질 UI로 C# WPF 기반 프로젝트
1. 드라이버와 에이전트의 약속 (OpenGuard_Common)
가장 먼저 할 일은 유저모드(에이전트)와 커널모드(드라이버)가 대화할 수 있도록 프로토콜을 정의하는 것입니다.
통신에 사용할 IOCTL 코드와 정책 구조체를 헤더 파일로 분리하여 양쪽 프로젝트에서 모두 참조하도록 했습니다.

2. 커널 드라이버 구현 (.sys)
디바이스 생성 및 정책 수신 (IOCTL)
DriverEntry 에서 디바이스 객체와 심볼릭 링크를 생성한 뒤, DeviceIoControl 핸들러를 연결합니다. 에이전트로부터 새로운 정책이 넘어오면 전역 구조체에 덮어씁니다. 이때 멀티스레드 환경에서 데이터가 꼬이지 않도록 FastMutex 를 사용해 동기화 처리를 해줍니다.

소프트웨어 실행 차단 로직
프로세스 실행을 제어하기 위해 PsSetCreateProcessNotifyRoutineEx 콜백을 등록합니다. 누군가 프로그램을 실행할 때마다 이 콜백이 호출되는데, 실행하려는 프로세스 이름을 추출해 정책의 블랙리스트와 비교합니다.
만약 차단 대상이라면 CreateInfo->CreationStatus 를 STATUS_ACCESS_DENIED 로 설정하여 실행을 원천 차단합니다.

차단 대상인 메모장이 켜지지 않는 모습

로그 큐 (Ring Buffer) 처리
차단 이벤트가 발생하면 즉시 에이전트로 보낼 수 없으니(커널에서 유저로 먼저 말을 걸기 힘드므로), 드라이버 내부에 로그를 잠시 쌓다둡니다. 이를 위해 스핀락(KSPIN_LOCK)으로 보호되는 원형 큐(Ring Buffer)를 구현하여 에이전트가 폴링해 갈 때까지 보관합니다.

3. 유저모드 에이전트 구현 (C++ Win32)
커널 드라이버와의 통신
에이전트는 윈도우 서비스 형태로 동작하며, SCM(Service Control Manager)을 통해 드라이버를 동적으로 로드합니다. 이후 CreateFile 로 드라이버의 핸들을 얻고, DeviceIoControl 을 사용해 정책을 밀어 넣습니다.


서버와 통신 (동적 정책 수신 & 체크인)
에이전트는 주기적으로 동작하며 두 가지 핵심 작업을 수행합니다.

1. 체크인 : PC명, 사용자명, IP정보를 서버에 등록하고 30초마다 last_seen 값을 갱신하여 자신의 생존(온라인 상태)을 알립니다.
2. 정책 폴링 : WinHTTP 라이브러리를 사용해 서버에 정책을 요청합니다. JSON 응답을 파싱하여 OG_POLICY 구조체로 변환한 뒤, 위에서 만든 DeviceIoControl 을 통해 커널 드라이버에 전달합니다.


4. 관리자 웹 콘솔 (PHP + MariaDB)
정책을 지시하고 로그를 보여줄 중앙 통제실입니다. Ubuntu Server에 NGINX 를 구축한 서버가 존재합니다만 이번 프로젝트에는
Dothome 의 무료 웹 호스팅에서 지원해주는 PHP 8과 MariaDB로 가볍게 구성했으며, 주요 PHP 구성 및 테이블 구조는 다음과 같습니다.
PHP 구성
/openguard/
ㄴ config.php < DB정보
ㄴ agent_checkin.php < 에이전트 등록/체크인
ㄴ send_logs.php < 로그 수신
ㄴ get_policy.php < 정책 반환
ㄴ admin/
ㄴ index.php < 대시보드
ㄴ agents.php < 에이전트 현황
ㄴ logs.php < 로그 조회
ㄴ policy.php < 정책 설정
DB 구조

- og_agents : 연결된 에이전트 정보 및 마지막 접속 시간 관리
- og_logs : 차단 내역 등 에이전트가 올려보낸 이벤트 로그 저장
- og_policies : 버전별 제어 정책 데이터
관리자가 웹 대시보드에서 메모장(notepad.exe) 차단을 설정하고 저장하면 정책 버전이 올라갑니다. 그러면 최대 30초 안에 각 PC의 에이전트가 이를 감지하여 새 정책을 다운로드하고, 커널 드라이버에 밀어 넣어 즉각적인 차단이 시작됩니다.
실행
웹 로그인 화면

웹 대시보드

웹 로그 조회 화면

웹 정책 설정 화면

웹 에이전트 관리 화면

개발 중 마주친 이슈들 (삽질 노트)
드라이버 개발이 늘 그렇듯, 한 번에 켜지는 법이 없죠. 이번 단계에서 겪은 주요 트러블슈팅 메모입니다.
- PsSetCreateProcessNotifyRoutineEx 등록 실패 (에러코드 : 0xC0000022)
- 원인/해결 : 프로세스 콜백을 사용하려면 드라이버 파일이 서명되어 있거나, 서명 확인을 강제하는 링커 옵션이 필요합니다. 프로젝트 속성 링커 옵션에 /integritycheck 를 반드시 추가해야 합니다. (없으면 드라이버 구동 시 ACCESS_DENIED 가 발생 합니다.) 저번 ObRegisterCallbacks 구현 때도 이래서 알고 있었습니다만 링커탭 명령줄에 추가를 안하고 다른탭에 추가를 해버리는 바람에 애먹었습니다. 분명 추가했다고 생각했는데 링커탭인지 제대로 확인도 안하고 추가해버리는 바람에 일어난 불상사였습니다.
- GUID_DEVICE_INTERFACE_ARRIVAL 링크 오류
- 원인/해결 : 헤더 파일의 Include 순서가 문제였습니다. 윈도우 커널 헤더는 순서를 많이 탑니다. 일반 적인 유저모드 개발과 다르게 말이죠, ntddk.h > initguid.h > wdm.h > wdmguid.h 순서로 맞춰주어 해결했습니다.
- 디버그 로그(KdPrint)가 안 찍히는 현상
- 원인/해결 : Release 모드에서는 매크로 특성상 출력이 비활성화됩니다. Debug 모드로 빌드해야 DebugView 등에서 로그를 확인할 수 있습니다.
다음 편 예고
이제 인프라와 파이프라인이 뚫렸습니다! 서버에서 명령을 내리면 커널이 통제하는 것까지 완성되었네요.
다음 3편에서는 USB차단을 커널 PnP 콜백(IoRegisterPlugPlayNotification)으로 구현하고, 이후 사용자에게 "보안 프로그램이 작동 중입니다"라고 알려줄 WPF 기반의 트레이(Tray) 앱(OpenGuard_UI)을 만들고, 에이전트와 Named Pipe로 통신하는 과정을 다루겠습니다. 더불어, 안티치트 개발 등에서 자주 쓰이는 ObRegisterCallbacks를 응용하여 유저가 에이전트 및 UI 프로세스를 강제로 끄지 못하도록 막는 자기 보호(Self-Defense) 기능도 적용해 보려 생각중입니다만 자기 보호기능은 프로젝트의 순서 맨 끝으로 미뤄도 되지않나 고민중입니다.
긴 글 읽어주셔서 감사합니다.
다음 편 보러가기
https://imoracle.tistory.com/74
[DLP 개발기] 3. WPF 트레이 앱 통신과 커널 레벨 매체/파일 제어 (USB & Minifilter)
들어가며이 글은 오피스키퍼 등 상용 DLP(Data Loss Prevention) 프로그램의 동작 원리를 분석하고, 윈도우 커널 드라이버 기반의 보안 솔루션을 직접 구현해보는 시리즈입니다.지난 2편에서는 커널 드
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 개발기] 1. 커널 드라이버 기반 보안 시스템, OpenGuard 시작하기 (0) | 2026.04.29 |