преобразовать файл в изображение в градациях серого - PullRequest
1 голос
/ 12 февраля 2020

Я пытаюсь преобразовать файлы (любой файл как exe, apk) в изображение в оттенках серого. Я подготовил двоичные биты файла, используя код ниже. Тем не менее, я застрял в группировке 8 бит, чтобы представить пиксель в моем изображении, так что каждый пиксель от 0 до 255. Литература показала, что вредоносное ПО можно классифицировать, преобразовав его в серое изображение и применив модель CNN для классификации

import cv2
import numpy
import os
import binascii

filePath = "240387329dee4f03f98a89a2feff9bf30dcba61fcf614cdac24129da54442762"
file = open(filePath, "rb")
with file:
    byte = file.read()
    hexadecimal = binascii.hexlify(byte)
    decimal = int(hexadecimal, 16)
    binary = bin(decimal)[2:].zfill(8)
    print("hex: %s, decimal: %s, binary: %s" % (hexadecimal, decimal, binary))

Редактировать:

Я написал ниже, где я установил ширину изображения. Есть отзывы?

import cv2
import numpy
import os
import binascii
import array
import scipy.misc
#print (format(5,"b"))

filename='240387329dee4f03f98a89a2feff9bf30dcba61fcf614cdac24129da54442762';
f=open(filename,'rb');
ln = os.path.getsize(filename);
width = 500;
rem = ln%width;
a=array.array("B");
a.fromfile(f,ln-rem);
f.close;
g=numpy.reshape(a,(len(a)/width,width));
g= numpy.uint8(g);
scipy.misc.imsave('Malware.png',g);

1 Ответ

2 голосов
/ 12 февраля 2020

Вам не нужно преобразовывать данные в шестнадцатеричные или двоичные, все, что вам нужно сделать, это преобразовать двоичные данные (последовательность байтов) в 2D-массив.

Проблема в том, что ни один 1D-массив не может быть преобразован в 2D-массив.
В случае, если число байтов является простым числом = N, например, вы получите изображение 1xN (уродливая одиночная строка или изображение столбца).

В следующем примере предполагается, что размеры изображения должны быть квадратными, и для заполнения необходимого количества байтов используется заполнение:

import numpy as np
from math import sqrt, ceil
import cv2

#Input file name (random file I found in my folder).
input_file_name = 'test_cython.cp36-win_amd64.pyd';

#Read the whole file to data
with open(input_file_name, 'rb') as binary_file:        
    data = binary_file.read()

# Data length in bytes
data_len = len(data)

# d is a verctor of data_len bytes
d = np.frombuffer(data, dtype=np.uint8)

# Assume image shape should be close to square
sqrt_len = int(ceil(sqrt(data_len)))  # Compute square toot and round up

# Requiered length in bytes.
new_len = sqrt_len*sqrt_len

# Number of bytes to pad (need to add zeros to the end of d)
pad_len = new_len - data_len

# Pad d with zeros at the end.
# padded_d = np.pad(d, (0, pad_len))
padded_d = np.hstack((d, np.zeros(pad_len, np.uint8)))

# Reshape 1D array into 2D array with sqrt_len pad_len x sqrt_len (im is going to be a Grayscale image).
im = np.reshape(padded_d, (sqrt_len, sqrt_len))

# Save image
cv2.imwrite('im.png', im)

# Display image
cv2.imshow('im' ,im)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:
enter image description here


Создание изображения, которое можно использовать для восстановления исходного файла:

Если вы хотите получить изображение и восстановить исходный файл (равный байт, без заполнения) Вам необходимо восстановить исходную длину данных в изображении.
(Вы также можете восстановить длину отступа).

В следующей реализации сохраняется исходная длина данных в первых 8 пикселях.

После прочтения изображения можно удалить отступы и сохраненную длину, а также восстановить исходный файл.

Вот пример «кодирования» и «декодирования»:

import numpy as np
from math import sqrt, ceil
import cv2
import struct

#Input file name
input_file_name = 'test_cython.cp36-win_amd64.pyd';

#Read the whole file to data
with open(input_file_name, 'rb') as binary_file:        
    data = binary_file.read()

# Data length in bytes
data_len = len(data)

# d is a verctor of data_len bytes
d = np.frombuffer(data, dtype=np.uint8)

data_len_as_bytes = np.frombuffer(struct.pack("Q", data_len), dtype=np.uint8) # Convert data_len to 8 bytes

data_len = data_len + len(data_len_as_bytes) #Update length to include the 8 bytes

# Set data_len as first 8 bytes of d
d = np.hstack((data_len_as_bytes, d))

# Assume image shape should be close to square
sqrt_len = int(ceil(sqrt(data_len)))  # Compute square toot and round up

# Requiered length in bytes.
new_len = sqrt_len*sqrt_len

# Number of bytes to pad (need to add zeros to the end of d)
pad_len = new_len - data_len

# Pad d with zeros at the end.
# padded_d = np.pad(d, (0, pad_len))
padded_d = np.hstack((d, np.zeros(pad_len, np.uint8)))

# Reshape 1D array into 2D array with sqrt_len pad_len x sqrt_len (im is going to be a Grayscale image).
im = np.reshape(padded_d, (sqrt_len, sqrt_len))

# Save image
cv2.imwrite('im.png', im)

# Display image
#cv2.imshow('im' ,im)
#cv2.waitKey(0)
#cv2.destroyAllWindows()


# Restore original data:
##################################
input_file_name = 'test.bin';  #Output file name

im = cv2.imread('im.png', cv2.IMREAD_GRAYSCALE)

# Convert 2D to 1D
padded_d = im.flatten()

# Get original length
data_len_as_bytes = padded_d[0:8]

orig_data_len = struct.unpack("Q", data_len_as_bytes.tobytes())

# Crop the original data bytes (without the padding).
data = padded_d[8:8+orig_data_len[0]]

#Write d whole file to binary file
with open(input_file_name, 'wb') as binary_file:
    binary_file.write(data)

Теперь вы можете загрузить любой (маленький) файл в Переполнение стека как изображение, и пусть кто-то другой восстановит ваш файл ,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...