발자취

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

3-2/악성코드

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

해린 2024. 1. 18. 06:57

 

악성코드 탐지시스템의 구조를 알아보는 실습, 그 두번째 시간이다.

본 실습은 '파이썬으로 배우는 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가 별도의 파일로 나뉜 탐지 시스템 유형을 살펴보았다.

다음 시간엔 좀 더 효율적인 탐지 시스템을 살펴볼 것이다.