갑자기 파일에 대한 앤트로피를 계산해야 할일이 생겨 찾아보닌 섀넌의 앤트로피를 가장 많이 사용한다고 한다.

 

코드로 직접 구현하는 방법도 있지만 파이썬에서는 Scipy를 비롯해 많은 라이브러리에서 앤트로피 함수를 지원하고 있다.

 

내가 구현해야할 내용은 파일의 바이트코드를 읽어와서 앤트로피를 구하는 것이다.

 

섀넌의 앤트로피에 대한 논문은 1948년에 발표된

Shannon, Claude E. (July–October 1948). “A Mathematical Theory of Communication”

이라는 논문에서 다뤄졌다.

 

상세한 내용은

 

* 한글위키

 

https://ko.wikipedia.org/wiki/%EC%A0%95%EB%B3%B4_%EC%97%94%ED%8A%B8%EB%A1%9C%ED%94%BC

 

정보 엔트로피 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 2 섀넌의 엔트로피: 2 개의 공정한 동전을 던질 때 정보 엔트로피는 발생 가능한 모든 결과의 개수에 밑이 2 인 로그를 취한 것과 같다. 2 개의 동전을 던지면 4

ko.wikipedia.org

 

* 영문위키

 

https://en.wikipedia.org/wiki/Entropy_(information_theory)

 

대부분이 그렇듯이 영문위키가 좀더 내용이 많다.

 

기본적인 알고리즘을 이해하기 위해 참조한 코드는 아래의 두개 블로그이고 첫번째 블로그에 공개된 코드를 기반으로 디렉토리 서치와 대용량 바이너리 코드에 대한 엔트로피 계산이 가능하도록 변경하였다.

 

파일에 대한 앤트로피를 구하면 해당파일이 압축이나 암호화된 것인지 일반 파일인지 구분하는 것이 가능하다.

압축되거나 암호화된 파일은 앤트로피가 높아지는 경향을 보인다.

 

자세한 것은 아래 링크로 첨부한 미국해군대학원의 논문을 참조하기 바랍니다.

 

# -*- coding: utf-8 -*-
"""
Created on Thu Mar 25 17:11:59 2021

@author: test
"""

import math, string, sys, fileinput, os

# 새로 작성한 파일 앤트로피 함수
def file_entropy(fn):
	# 바이트값 카운트를 위한 딕셔너리 초기화
    dict_byte = { 0 : 0 }
    for x in range(1, 256):
        dict_byte[x] = 0
    #print(dict_byte)
    try :
    	# 바이트배열로 읽으면 메모리 부담이 있어서 속도는 느리지만 한바이트씩 읽어서 연산한다.
        f = open(fn, 'rb')
        running = True
        fcnt = 0
        entropy = 0
        while running :
            s = f.read(1)
            # 널 바이트가 읽히면 종료한다.
            if s == b'' : 
                print(fcnt)
                running = False
                break
            fcnt += 1
            idx = int.from_bytes(s, 'little')
            # 바이트 값에 해당하는 딕셔너리 값을 증가시킨다.
            v = dict_byte.get(idx) + 1
            dict_byte[idx] = v
            # if fcnt % 1000000 == 0 :
            #     print(fcnt, idx, v)
        f.close()
        
        # 카운트 된 바이트 값을 읽어서 파일 사이즈를 기준으로 앤트로피를 계산한다.
        for key, value in dict_byte.items() :
            p_x = float(value)/fcnt
            if p_x > 0:
                entropy += - p_x*math.log(p_x, 2)
        return entropy
            
    except IOError:
        print(sys.stderr)

# 디렉토리 탐색해서 파일일 경우만 앤트로피를 구한다.
def search(dirname):
    filenames = os.listdir(dirname)
    for filename in filenames:
        full_filename = os.path.join(dirname, filename)
        if os.path.isdir(full_filename) :
            pass
        print (full_filename)
        print(file_entropy(full_filename))

# 아큐먼트를 입력받는다.
file_path = sys.argv[1]
#file_path = "C:/Work"

if len(sys.argv) != 2:
    print("Insufficient arguments")
    print(len(sys.argv))
    sys.exit()

print("### start ###")
print(file_path)

# 디렉토리일경우 해당 디렉토리의 파일들을 탐색
if os.path.isdir(file_path) :
    search(file_path)
# 파일일 경우 파일앤트로피 함수를 바로 호출하여 앤트로피 계산
elif os.path.isfile(file_path) :
    print(file_entropy(file_path))
#print(file_entropy(file_path))
#search(file_path)

print('end')

 

<미해군대학원의 논문에 나온 내용을 참고>

 

* 논문 초록

 

calhoun.nps.edu/handle/10945/55513

 

Entropy-based file type identification and partitioning

Abstract The need for file identification and partitioning in the digital forensic, reverse engineering, and security analyst fields cannot be overstated. In this research, we investigate the use of the Shannon entropy profile derived from the file express

calhoun.nps.edu

* 실제 논문 PDF

 

apps.dtic.mil/sti/pdfs/AD1046497.pdf

 

 

<참조한 링크>

 

http://pythonfiddle.com/shannon-entropy-calculation/

 

Shannon entropy calculation | Python Fiddle

 

pythonfiddle.com

 

https://kennethghartman.com/calculate-file-entropy/

 

Calculate File Entropy – Kenneth G. Hartman, CISSP

Calculate File Entropy Entropy is the measurement of the randomness.  The concept originated in the study of thermodynamics, but Claude E. Shannon in applied the concept to digital communications his 1948 paper, “A Mathematical Theory of Communication.

kennethghartman.com

 

 

 

Posted by 휘프노스
,