백신이란 바이러스, 스파이웨어, 랜섬웨어 등 악성 소프트웨어(Malware)를 감시 및 탐지하여, 사용자와 사용자의 데이터가 피해를 입지 않도록 돕는 보안 소프트웨어이다.
현대의 백신은 시그니처 기반 탐지 기법, 휴리스틱 탐지 기법, 행위 기반 탐지 기법 등 다양한 기법을 동원하여 고차원의 보안 기능을 제공한다. 간단히 설명하면 각 기법의 원리는 아래와 같다.
- 시그니처 기반 탐지 : 이전에 사용된 공격 패턴을 수집하여 저장해두고, 패턴에 맞는 입력이 들어왔을 때 이를 감지한다.
- 휴리스틱 기반 탐지 : 악성 프로그램의 코드 구조나 특징을 추론하여 잠재적 위험도를 계산해 악성 여부를 판단한다.
- 행위 기반 탐지 : 파일 암호화 시도, 시스템 레지스트리 무단 변경 등 악의적일 수 있는 프로세스의 행동을 감지한다.
이중에서 가장 전통적인 백신이자 Java의 기본적인 문법과 컬렉션 기능만으로도 만들 수 있는 시그니처 기반 탐지 백신을 간단하게 만들었다.
1. 설계
시그니처 기반 탐지 백신이 어떻게 작동하는지 먼저 생각해보자. 이미 알려진 악성코드의 고유한 패턴을 데이터 베이스(블랙리스트)에 저장해 두고, 입력된 트래픽이나 파일 등이 데이터베이스에 저장된 패턴과 일치하는지를 감지하여 악성 소프트웨어를 잡아낸다.
이 작동 원리를 기능으로 치환하면 아래와 같이 생각해볼 수 있다.
바이러스 패턴을 데이터 베이스에 저장하기 -> 파일을 생성하기 -> 시스템 파일을 스캔하여 파일 내용과 DB를 대조하기(검색하기) -> 파일의 악성 여부를 출력하기 -> 악성 파일 격리하기
여기에 더하여, 잘못 탐지되는 등의 예외 상황을 상정해 '악성파일로 감지되었으나 허용할 목록(화이트리스트)'을 만들어 그 예외를 처리하는 것, 입력된 파일과 그 파일의 악성 여부를 목록으로 출력하는 것, 격리되어있는 파일을 일괄로 삭제하는 것까지 몇 가지의 기능을 더하면 아주 간단한 백신을 만들 수 있다.
여기에서 필요한 객체에 데이터와 기능을 간략하게 나누어본다면,
- 파일 : 파일의 이름, 내용, 생성한 사, 생성 날짜
- 데이터베이스 : 블랙리스트, 화이트리스트, 블랙리스트와 화이트리스 수정
- 백신 : 파일 스캔, 스캔한 내용과 데이터베이스를 대조, 감지 결과 출력
- 파일 관리자 : 격리소 운영, 백신에서 처리한 결과를 토대로 파일을 격리소로 이동, 삭제, 파일에 '안전', '격리', '허용'(원래 격리되어있어야했으나 허용됨) 등 태그를 붙이기
- 메뉴판 : 파일을 생성하기, 파일 수정하기, 파일 목록 불러오기, 예외처리 지정하기, 격리소에 있는 파일 삭제하기
- 실행파일
이렇게 필요할 것 같다.
가장 독립적으로 존재할 수 있는 파일 객체부터, DB, Vaccine, 파일 관리자, 메뉴판, 실행 코드 순서로 만들었다.
2. 코딩
코딩 중 마주한 문제는 크게 두 번 정도 있었다.
public void addBlackList(String pattern) {
if(!blackList.contains(pattern)) {
blackList.add(pattern);
System.out.println("신규 악성 패턴이 등록되었습니다.");
} else {
System.out.println("이미 등록되어있는 패턴입니다.");
}
}
...
public void loadPatternsFromFile() {
try (BufferedReader br = new BufferedReader(new FileReader("blacklist.txt"))) {
String line;
System.out.println("DB를 불러옵니다.");
while ((line = br.readLine()) != null) {
addBlackList(line);
}
} catch (IOException e) {
System.out.println("blacklist.txt이 없습니다. 기본 내장 DB로 실행합니다.");
}
}처음에는 addBlackList를 이렇게 작성하고 filesystem을 활용해야겠다는 생각을 나중에 하는 바람에 뒤늦게 덧붙였다가 생각을 못 해서 신규 패턴이 등록되었다는 문구가 와르르 튀어나왔다...
수정 ->
public void addBlackList(String pattern) {
if(!blackList.contains(pattern)) {
blackList.add(pattern);
System.out.println("신규 악성 패턴이 등록되었습니다.");
savePatternToFile(); //추가
} else {
System.out.println("이미 등록되어있는 패턴입니다.");
}
}
...
public void loadPatternFromFile() {
//파일에서 한 줄씩 읽어오기
try (BufferedReader br = new BufferedReader(new FileReader("blacklist.txt"))) {
String line;
System.out.println("DB를 불러옵니다.");
//파일에 남은 글자가 없을 때까지 반복해서 blacklist 에 담는다.
while ((line = br.readLine()) != null) {
if(!blackList.contains(line)) {
blackList.add(line);
}
}
System.out.println("DB를 불러왔습니다.");
} catch (IOException e) {
System.out.println("blacklist.txt이 없습니다. 기본 내장 DB로 실행합니다.");
}
}또 blacklist.txt 파일의 경로 설정에서 실수가 있어서 블랙리스트 갱신이 안 되는 문제가 있었는데 이건 단순 실수였다보니 쉽게 해결이 됐다.
이것 외에 딱히 코딩에서 어려운 점은 없었다. 함수는 구글링을 하면 구현할 수 있기에 필요한 클래스가 있으면 AI와 구글링을 통해 코드를 채웠고 그 과정은 그렇게 어렵지는 않았다. 기초 문법만 알면 코드는 비교적 짧고 반복되는 문법도 많았기 때문에 괜찮았다. 필요한 기능이 내 생각보다 많았을 뿐 기술적으로 어렵지는 않았다.
다만 file이랑 file 매니저 분리했듯 DB랑 DB 매니저도 분리할걸... 이라는 후회가 남긴 한다.
가장 어려웠던 건 내가 알고있는 백신의 기능을 구현하려다보니 중간중간 더 필요한 메서드는 늘어가는데, 이걸 중간에 넣고 빼고 하다보니까 내가 짠 코드인데도 매서드 하나하나가 잘 기억이 안 나고 헷갈리는 게 많아져서 다시 정리하고 쓰는 시간이 많이 필요했다.
만든 코드는 아래와 같다.
3. 실행화면

실행하면 이렇게 10개의 메뉴가 먼저 뜬다. 그 중 2를 선택해 미리 준비해둔 파일 리스트 3개를 확인했다.


그 다음 4를 눌러 악성 코드 패턴이 들어있는 파일을 검색한다. 그러면 악성 패턴을 넣어둔 danger.exe 파일이 격리되었다고 나온다. 악성 패턴이 들어있지만, 사용자가 화이트리스트에 넣어둔 my_project.java는 허용으로 나온다.


5번을 눌러 격리 조치 후, 6번을 입력하면 격리소에 들어간 danger.exe 파일이 보인다.
다음으로는 새 파일을 입력해보았다.

새로 추가한 unknown에는 backdoor라는 패턴이 있다. 이 backdoor는 설정상 '신규 악성 패턴'이다. 지금의 데이터베이스에는 없지만, blacklist.txt라는 텍스트 파일에 입력되어 [업데이트할 신규 패턴 목록]에는 있다. 이를 넣어보자.

이렇게 하고, 다시 4를 눌러 파일을 스캔해보면,

이렇게, 격리된다. 하지만 저 unkown에는 의심 패턴이 있지만 나에게 필요한 파일이라면? 이를 화이트리스트로 빼보는 작업도 가능하다. 일단 5번을 선택해 격리소로 이동시키고, 이를 확인한 뒤에 작업해보자.

이후, 격리소를 살펴보면,

unkown은 빠졌다. 이제 여기엔 정말 위험한 파일만 있으니 삭제하자.


그리고 다시 파일 목록을 확인하면,


이렇게, 백신 시뮬레이터를 사용해보았다.
'P&E Question' 카테고리의 다른 글
| HTML/CSS/JS - 웹페이지 제작 과제 : 요트다이스 (1) | 2026.07.08 |
|---|