前不久看到了幾個二進位制檔案視覺化的專案,做了一些瞭解,通過視覺化可以看出加殼或者加密檔案,在紋理結構上和正常檔案還是有較大區別。
而且視覺化對檔案格式不敏感,任何檔案都可以檢視其視覺化結果。
視覺化資料來源可分為以下兩類:
二進位制檔案視覺化
二進位制熵視覺化
對繪圖的方式有幾種方法:
這兩種方法其實都是空間填充曲線的子類,有興趣可以瞭解。
對繪圖的色彩也可分為以下
灰度圖,直接生成就是灰度圖
彩色圖,不同區域設定不同顏色,如portex【1】中的分了以下五種色類
# 分別對應不同的顏色
0xff, 0x00, 可見ASCII碼, 不可及ascii碼,非ascii碼
彩色圖,直接使用多通道,即每三個連續的位元組作為一個通道的值,源自【2】
分別將原始二進位制檔案視覺化,熵視覺化,這裡使用了最簡單的視覺化方法。
def bin2image(content, resize=True):
"""
binary to gray image
"""
width = imagesize(len(content))
fh = np.frombuffer(content, dtype=np.uint8)
rn = len(fh)/width
fh = np.reshape(fh[:int(rn)*width],(int(rn),width))
im = Image.fromarray(fh)
if resize:
im = im.resize((244,244))
return im
def H(data):
''' Calculate the entropy of a given data block '''
c = np.bincount(data, minlength=256)
p = c.astype(np.float32) / len(data)
wh = np.where(c)[0]
H = np.sum(-p[wh] * np.log2(
p[wh]))
return H
def block_entropy(data, window=1024, step=256):
Hbins = []
if data.shape[0] < window:
Hbin = H(data)
Hbins.append(Hbin)
else:
shape = data.shape[:-1] + (data.shape[-1] - window + 1, window)
strides = data.strides + (data.strides[-1],)
blocks = np.lib.stride_tricks.as_strided(data, shape=shape, strides=strides)[::step, :]
for block in blocks:
Hbin = H(block)
Hbins.append(Hbin)
return Hbins
def bin2entropy(content, block_size=1024, step=256, resize=True):
"""
following resources: https://github.com/gcmartinelli/entroPy/blob/master/entropy.py
but fatser 6x time
"""
data = np.frombuffer(content, dtype=np.uint8)
entropy_list = block_entropy(data, block_size, step)
width = imagesize(len(entropy_list))*2
rn = len(entropy_list)/width
matrix = np.reshape(entropy_list[:int(rn)*width],(int(rn),width))
im = Image.fromarray(matrix * 255/8)
if resize:
im = im.resize((244,244))
return im
結果如下圖所示。視覺化之後就可以作進一步分析了,比如對比加殼和正常檔案;使用視覺化圖進行惡意識別。
另外,此處的二進位制熵視覺化主要參考【3】,但是進行了改進,比【3】中原始的方法計算熵圖快了6倍以上。
原始碼見 github: https://github.com/Aida-yy/binai/blob/main/binai/feature_extraction/image.py
【1】https://github.com/struppigel/PortEx
【3】https://github.com/gcmartinelli/entroPy