발자취

악성코드 탐지 시스템 실습 03 - 문자열 시그니처의 추가 본문

3-2/악성코드

악성코드 탐지 시스템 실습 03 - 문자열 시그니처의 추가

해린 2024. 1. 18. 07:25

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

본 실습은 '파이썬으로 배우는 Anti-Virus 구조와 원리' 교재의 4~7, 12장에 해당하는 실습이며, 본 게시물에서는 7장의 내용을 다룬다.

앞선 실습의 탐지 시스템의 문제점을 개선한 구조의 탐지 시스템을 확인할 수 있다.

 

이전 실습 게시글:

https://haelyn.tistory.com/127

https://haelyn.tistory.com/128

 


3. 세번째 실습

실습에 필요한 코드는 다음과 같다.

 

#Written by JWHO for IntrusionDetection Class

import hashlib
import string 
import random
import os

NUM_OF_FAKE_VIRUSE_FILES=10
name = "virus_str.db"
for i in range(NUM_OF_FAKE_VIRUSE_FILES):
   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)
   
   
   if i < (int)(NUM_OF_FAKE_VIRUSE_FILES/2):
    k=hashlib.md5()
    k.update(msg)
    digest=k.hexdigest()
    output = "ScanMD5:CureDelete:"+str(msg_len)+":"+digest+":"+"FakeVirus"+idx+"\n"
   else:
    str_starting_pos=str(len("*fakeVirus"+idx+" for test purpose* ")) 
    output = "ScanStr:CureDelete:"+str_starting_pos+":"+"signature FV"+num+":"+"FakeVirus"+idx+"\n"
    
   fp = open(name, 'ab+')
   fp.write(output)
   fp.close()

virus_str_db_gen.py

 

# -*- coding:utf-8 -*-
import sys
import os
import hashlib
import zlib
import StringIO

import scanmod
import curemod

VirusDB = []    
vdb = []        
sdb = []        
vsize = []      



def DecodeKMD(fname):
    try:
        fp = open(fname, 'rb')
        buf = fp.read()
        fp.close()

        buf2 = buf[:-32]
        fmd5 = buf[-32:]

        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:]:  
            buf3 += chr(ord(c) ^ 0xFF)

        buf4 = zlib.decompress(buf3)
        return buf4

    except:
        pass

    return None



def LoadVirusDB():
# Original DecodeKMD function 
#   buf = DecodeKMD('virus.kmd')
    
# Modified DecodeKMD function for IntrusionDetection Class
    buf = DecodeKMD('virus_str.kmd')  
    fp = StringIO.StringIO(buf)

    while True:
        line = fp.readline()
        if not line: break

        line = line.strip()
        VirusDB.append(line)    

    fp.close()

        

def MakeVirusDB():
    for pattern in VirusDB:
        t = []
        v = pattern.split(':')
        
        scan_func = v[0]
        cure_func = v[1]
        
        if scan_func == 'ScanMD5':
            t.append(v[3])
            t.append(v[4])
            vdb.append(t)

            size = int(v[2])
            if vsize.count(size) == 0:
                vsize.append(size)

        elif scan_func == 'ScanStr':
            t.append(int(v[2]))
            t.append(v[3])
            t.append(v[4])
            sdb.append(t)


if __name__ == '__main__':
    LoadVirusDB()
    MakeVirusDB()

    if len(sys.argv) != 2:
        print 'Usage: antivirus.py [file]'
        exit(0)

    fname = sys.argv[1]

    ret, vname = scanmod.ScanVirus(vdb, vsize, sdb, fname)
    if ret == True:
        print '%s : %s' % (fname, vname)
        curemod.CureDelete(fname)    
    else:
        print '%s : ok' % (fname)

antivirus.py

 

그리고 앞 실습에서 사용했던 kmake.py가 필요하다

 

1. 실습 절차

1. ~/Desktop/AVCodes 폴더에 정상 파일인 benign1.txt ... benign10.txt 파일과 악성 파일인 fakeVirus1.txt ... fakeVirus10.txt 파일들을 생성한다.

 

 

2. ~/Desktop/AVCodes로 이동한 후, 다음의 명령어를 수행해 virus_str.db 파일을 생성한다. 이 파일을 ~/Desktop/AVCodes/Ch7 폴더에 복사 붙여넣기 한다.

python .\virus_str_db_gen.py

*여기서 virus_str.db란?

새로운 형식의 DB이다. 바이러스 스캔방식(ScanMD5)는 이전 실습에서 했던 해시 방식이고, 문자열 기반의 ScanStr가 새롭게 추가된 것이다. 이는 시그니처를 구현한 방식이 해시 방식인지, 우리가 읽을 수 있는 문자열 방식인지에 따라 달라지는 것이다. (표현 방식의 차이)

 

3. ~/Desktop/AVCodes/Ch7 폴더로 이동 후, 다음의 명령어를 수행해 virus.db에 대한 압축과 인코딩 작업을 한다.

python .\kmake.py virus_str.db

→ 'Virus_str.kmd'라는 파일이 새롭게 생성된다. 압축, 인코딩된 Virus_str.db 파일이다.

 

 

4. benign3.txt와 fakeVirus3.txt, fakeVirus8.txt 파일을 복사하여 ~/Desktop/AVCodes/Ch7 폴더에 붙여넣고 해당 폴더로 이동한 뒤, 다음의 명령어를 수행한다.

python .\antivirus.py .\benign3.txt

→ "ok" 문구가 출력된다.

 

python .\antivirus.py .\fakeVirus3.txt

→ "fakeVirus3.txt"가 출력되며 파일이 삭제된다.

 

python .\antivirus.py .\fakeVirus8.txt

→ "fakeVirus8.txt"가 출력되며 파일이 삭제된다.

 

 

2. 코드 분석

1. antivirus.py

이전 실습에서 사용했던 코드(6-7.py)와 비교하여 달라진 점에 대해서만 분석할 것이다.

 

makeVirusDB()가 달라졌다. 이전까지는 해시값만 처리했으나 다른 처리 방식(문자열 처리 방식)을 추가해줬다.

 

[77], [86] ScanMD5, ScanStr 두 가지 방식이 다 있다.

 

[37] ScanStr... 사이즈에 맞게 문자열을 비교한다.

 

 

3. 생각해보기

1. 바이러스 탐지 관점에서 antivirus.py 프로그램은 6-7.py 프로그램을 어떠한 방식으로 개선하는가?

원래는 해시값만 시그니처로 뒀으나, 본 실습에서는 문자열 시그니처도 처리할 수 있도록 기존 프로그램을 확장시켰다.

스캔해주는 부분(scanmod.pyc)과 탐지 후에 처리하는 부분(curemod.pyc)이 다 분리되었다. 서로 간섭하지 않기 때문에 따로 임포트하여 사용할 수 있다. 모듈화하여 좀 더 효율적으로 동작하도록 만든 것이다.

 


이번 시간에는 시그니처의 개념을 좀 더 확장시킨 탐지 시스템 유형을 살펴보았다.

탐지 시스템의 문제점을 해결하여 점점 개선시켜 나가는 것이 즐겁다. :)