발자취
악성코드 탐지 시스템 실습 02 - 별도 파일로 저장된 VirusDB 본문

악성코드 탐지시스템의 구조를 알아보는 실습, 그 두번째 시간이다.
본 실습은 '파이썬으로 배우는 Anti-Virus 구조와 원리' 교재의 4~7, 12장에 해당하는 실습이며, 본 게시물에서는 6장의 내용을 다룬다.
앞선 실습의 탐지 시스템의 문제점을 개선한 구조의 탐지 시스템을 확인할 수 있다.
이전 실습 게시글:
https://haelyn.tistory.com/127
2. 두번째 실습
실습에 필요한 코드는 다음과 같다.
#Written by JWHO for IntrusionDetection Class
import hashlib
import string
import random
import os
NUM_OF_FAKE_VIRUSE_FILES=10
name = "virus.db"
for i in range(NUM_OF_FAKE_VIRUSE_FILES):
k=hashlib.md5()
random.seed(i)
idx = str(i+1)
msg="*fakeVirus"+idx+" for test purpose* signature FV"
num=str((int)(10000000*random.random()))
msg+=num
msg_len=len(msg)
k.update(msg)
digest=k.hexdigest()
output = str(msg_len)+":"+digest+":"+"FakeVirus"+idx+"\n"
fp = open(name, 'ab+')
fp.write(output)
fp.close()
virus_db_gen.py
# -*- coding:utf-8 -*-
import sys
import os
import hashlib
import zlib
import StringIO
VirusDB = [] # 악성코드 패턴은 모두 virus.kmd에 존재함
vdb = [] # 가공된 악성코드 DB가 저장된다.
vsize = [] # 악성코드의 파일 크기만 저장한다.
# KMD 파일을 복호화한다.
def DecodeKMD(fname):
try:
fp = open(fname, 'rb')
buf = fp.read()
fp.close()
buf2 = buf[:-32] # 암호화 내용을 분리한다.
fmd5 = buf[-32:] # MD5를 분리한다.
f = buf2
for i in range(3):
md5 = hashlib.md5()
md5.update(f)
f = md5.hexdigest()
if f != fmd5:
raise SystemError
buf3 = ''
for c in buf2[4:]: # 0xFF로 XOR한다.
buf3 += chr(ord(c) ^ 0xFF)
buf4 = zlib.decompress(buf3) # 압축을 해제한다.
return buf4
except:
pass
return None
# virus.kmd 파일에서 악성코드 패턴을 읽는다.
def LoadVirusDB():
buf = DecodeKMD('virus.kmd')
fp = StringIO.StringIO(buf)
while True:
line = fp.readline()
if not line: break
line = line.strip()
VirusDB.append(line)
fp.close()
# VirusDB를 가공하여 vdb에 저장한다.
def MakeVirusDB():
for pattern in VirusDB:
t = []
v = pattern.split(':')
t.append(v[1])
t.append(v[2])
vdb.append(t)
size = int(v[0])
if vsize.count(size) == 0:
vsize.append(size)
# 악성코드를 검사한다.
def SearchVDB(fmd5):
for t in vdb:
if t[0] == fmd5:
return True, t[1]
return False, ''
if __name__ == '__main__':
LoadVirusDB()
MakeVirusDB()
if len(sys.argv) != 2:
print 'Usage: antivirus.py [file]'
exit(0)
fname = sys.argv[1]
size = os.path.getsize(fname)
if vsize.count(size):
fp = open(fname, 'rb')
buf = fp.read()
fp.close()
m = hashlib.md5()
m.update(buf)
fmd5 = m.hexdigest()
ret, vname = SearchVDB(fmd5)
if ret == True:
print '%s : %s' % (fname, vname)
os.remove(fname)
else:
print '%s : ok' % (fname)
else:
print '%s : ok' % (fname)
6-7.py
# -*- coding:utf-8 -*-
import sys
import zlib
import hashlib
import os
def main():
if len(sys.argv) != 2:
print 'Usage: kmake.py [file]'
return
fname = sys.argv[1]
tname = fname
fp = open(tname, 'rb')
buf = fp.read()
fp.close()
buf2 = zlib.compress(buf) # 대상 파일 내용을 압축한다.
buf3 = ''
for c in buf2:
buf3 += chr(ord(c) ^ 0xFF) # 0xFF로 압축한 내용을 XOR한다.
buf4 = 'KAVM' + buf3
f = buf4
for i in range(3):
md5 = hashlib.md5()
md5.update(f)
f = md5.hexdigest()
buf4 += f
kmd_name = fname.split('.')[0] + '.kmd'
fp = open(kmd_name, 'wb')
fp.write(buf4)
fp.close()
print '%s -> %s' % (fname, kmd_name)
if __name__ == '__main__':
main()
kmake.py
1. 실습 절차
1. ~/Desktop/AVCodes 폴더에 정상 파일인 benign1.txt ... benign10.txt 파일과 악성 파일인 fakeVirus1.txt ... fakeVirus10.txt 파일들을 생성한다.
2. ~/Desktop/AVCodes로 이동한 후, 다음의 명령어를 수행해 virus.db 파일을 생성한다. 이 파일을 ~/Desktop/AVCodes/Ch6 폴더에 복사 붙여넣기 한다.
python .\virus_db_gen.py
여기서 virus.db란?
이전 실습에서 파이썬 코드에 포함되어 있던 VirusDB의 내용을 별도의 db 파일의 형태로 생성해준 것이다.
3. ~/Desktop/AVCodes/Ch6 폴더로 이동 후, 다음의 명령어를 수행해 virus.db에 대한 압축과 인코딩 작업을 한다.
python .\kmake.py virus.db
→ 'Virus.kmd'라는 파일이 새롭게 생성된다. 압축, 인코딩된 Virus.db 파일이다.
4. benign7.txt와 fakeVirus7.txt 파일을 복사하여 ~/Desktop/AVCodes/Ch6 폴더에 붙여넣고 해당 폴더로 이동한 뒤, 다음의 명령어를 수행한다.
python .\6-7.py .\benign7.txt
→ "ok" 문구가 출력된다.
python .\6-7.py .\fakeVirus7.txt
→ "fakeVirus7.txt"가 출력되며 파일이 삭제된다.
2. 코드 파일 분석
1. 6-7.py

대부분의 내용이 첫번째 실습에서 사용했던 4-5.py, 5-9.py와 비슷하기 때문에 달라진 부분 위주로만 분석하겠다.
[85] LoadVirusDB(): VirusDB를 가져온다. 이전 실습에서는 파이썬 파일 내에 DB가 포함되어 있었으나, 본 실습에서는 별도의 db 파일의 형태로 존재하기 때문에 이 db 파일을 가져와줘야 한다.

[47] Virus.kmd(압축된 DB)를 가져와서
[48] 압축, 인코딩을 해제한다.
나머지는 앞선 예제와 거의 비슷하다.
3. 생각해보기
1. 바이러스 탐지 관점에서 6-7.py 프로그램은 5-9.py(이전 실습 파일) 프로그램을 어떤 방식으로 개선하였는가?
1. VirusDB를 별도의 db 파일로 저장하여 따로 관리할 수 있도록 만들었다.
코드 안에 DB 리스트 내용이 포함되면 새로운 바이러스가 추가될 때마다 코드를 계속 수정해줘야 하기 때문에 이 방식은 비효율적이다. 따라서 DB를 별도의 파일로 분리시켜 새로운 바이러스가 추가되면 db 파일만 업데이트 해줘도 되도록 개선했다.
2. DB 파일을 압축, 인코딩하여 많은 양의 바이러스가 있어도 빠르게 처리할 수 있도록 만들어줬다.

이번 시간에는 DB가 별도의 파일로 나뉜 탐지 시스템 유형을 살펴보았다.
다음 시간엔 좀 더 효율적인 탐지 시스템을 살펴볼 것이다.
'3-2 > 악성코드' 카테고리의 다른 글
| 악성코드 탐지 시스템 04 - 암호화와 복호화 (0) | 2024.01.18 |
|---|---|
| 악성코드 탐지 시스템 실습 03 - 문자열 시그니처의 추가 (0) | 2024.01.18 |
| 악성코드 탐지 시스템 실습 01 - 해시값 하드코딩, 파이썬 파일에 포함된 DB (0) | 2024.01.18 |
| 악성코드 Pre-Lab6. 스텔스 프로세스 (0) | 2024.01.17 |
| 악성코드 Pre-Lab5. 계산기 후킹 (0) | 2024.01.09 |