Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Анализ изображений с точки зрения компьютерной криминалистики (Стегоанализ изображений). Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
71
if group_type == GroupType.REGULAR: inv_regulars += 1 elif group_type == GroupType.SINGULAR: inv_singulars += 1
return regulars, singulars, inv_regulars, inv_singulars
def get_groups(channel_array): groups = [] excess = []
ln = channel_array.shape[1] for str in channel_array: for i in [i*PIXELS_IN_GROUP for i in range(ln //
PIXELS_IN_GROUP)]:
group = [] for j in range(PIXELS_IN_GROUP): group.append(str[i + j]) groups.append(group)
for i in range((ln // PIXELS_IN_GROUP) * PIXELS_IN_GROUP,
ln):
excess.append(str[i]) if len(excess) >= PIXELS_IN_GROUP: groups.append(excess[:PIXELS_IN_GROUP]) excess = excess[PIXELS_IN_GROUP:]
return groups
def smooth_func(nums): sum = 0 for i in range(len(nums) - 1): sum += abs(nums[i+1] - nums[i]) return sum
def flip_direct(val): val = int(val) if val & 1: return val - 1 return val + 1
def flip_back(val): val = int(val) if val & 1: return val + 1 return val - 1
def flip_null(val): val = int(val) return val
72
def get_mask_funcs(mask=FLIPPING_MASK): f_mask = [] for e in mask: if e == 1: f_mask.append(flip_direct) elif e == 0: f_mask.append(flip_null) elif e == -1: f_mask.append(flip_back)
return f_mask
def group_flipping(group, mask_funcs): flipped = [] for i in range(PIXELS_IN_GROUP): flipped.append(mask_funcs[i](group[i]))
return flipped
def get_group_type(func, flipped_func): if flipped_func > func: return GroupType.REGULAR if flipped_func < func: return GroupType.SINGULAR if flipped_func == func: return GroupType.UNUSABLE
def invert_mask(mask=FLIPPING_MASK): return [e * -1 for e in mask]
def get_func_values(group, mask_funcs): flipped_group = group_flipping(group, mask_funcs) group_func = smooth_func(group) flipped_group_func = smooth_func(flipped_group)
return group_func, flipped_group_func
def get_p(direct_values, invert_values, log=None): writelog(log, "\t\tRM(p/2): {0}\n\t\tSM(p/2): {1}\n\t\tR-M(p/2):
{2}\n\t\tS-M(p/2): {3}\n"
"\t\tRM(1-p/2): {4}\n\t\tSM(1-p/2): {5}\n\t\tR-M(1-
p/2): {6}\n\t\tS-M(1-p/2): {7}\n\n"
.format(direct_values[0], direct_values[1],
direct_values[2], direct_values[3],
invert_values[0], invert_values[1],
invert_values[2], invert_values[3]))
d0 = direct_values[0] - direct_values[1] d0i = direct_values[2] - direct_values[3]
73
d1 = invert_values[0] - invert_values[1] d1i = invert_values[2] - invert_values[3]
writelog(log, "\t\td0 = {0}; d0i = {1}; d1 = {2}; d1i =
{3}\n".format(d0, d0i, d1, d1i))
a = (d1 + d0) * 2 b = d0i - d1i - d1 - 3 * d0 c = d0 - d0i
D = Decimal(b ** 2 - 4 * a * c)
if D < 0: x1 = x2 = min_x = 0 elif D == 0: x1 = x2 = min_x = - (b / 2 * a) else: x1 = Decimal((-b + Decimal.sqrt(D)) / (2 * a)) x2 = Decimal((-b - Decimal.sqrt(D)) / (2 * a))
if abs(x1) < abs(x2): min_x = x1 else: min_x = x2
p = Decimal(min_x / (min_x - Decimal(0.5)))
writelog(log, "\t\ta = {0}; b = {1}; c = {2}; D = {3}\n".format(a,
b, c, D))
writelog(log, "\t\tx1 = {0:.5}; x2 = {1:.5}; min_x = {2:.5}; p =
{3:.5}\n\n"
.format(float(x1), float(x2), float(min_x), p))
return max(p, 0)
74
ПРИЛОЖЕНИЕ В. Программная реализация стегоанализа скрытия,
произведённого по методу Коха-Жао
from math import fabs from lib.Utils import writelog #, histo
import lib.ImagesWorker as IW from lib.DCT import dct, DctMethod from lib._additions.KochZao import get_block_coeffs,
get_difference_of_modules, get_blocks
DCT_METHOD = DctMethod.SCIPY BLOCK_SIZE = 8 CUT_COEFF = 0.2
def analyze_kza(img_array, log=None): img_array = IW.get_blue(img_array)
seq = {"C1": [], "C2": [], "C3": []} seq_difs = {"C1": 0, "C2": 0, "C3": 0} d = {} blocks = get_blocks(img_array)
for block in blocks: dct_block = dct(block, DCT_METHOD)
seq["C1"].append(get_module_dif(dct_block, ((2, 3), (3,
2))))
seq["C2"].append(get_module_dif(dct_block, ((2, 4), (4,
2))))
seq["C3"].append(get_module_dif(dct_block, ((3, 4), (4,
3))))
# histo(seq["C3"])
for key in seq: il, ir = get_interval(seq[key]) il = il - 1 if il > 0 else il ir = ir + 2 if ir < len(seq[key]) - 2 else ir
seq[key] = seq[key][il:ir] seq_difs[key] = il
d[key] = [seq[key][0]] for i in range(1, len(seq[key])): d[key].append(fabs(seq[key][i] - seq[key][i-1])) d[key].append(seq[key][len(seq[key]) - 1])
# histo(d["C3"])
M0s, inds = [], [] for key in seq: r = find_two_maxs(d[key])
75
r[1] -= 1
if len(r) < 2 or len(seq[key][r[0]:r[1] + 1]) < 8: M0 = 0.0 writelog(log, "[{0}] {1} has not needed
seq\n".format(key, key))
ind = None else: M0 = min(seq[key][r[0]:r[1]]) writelog(log, "[{0}] SEQ = {1}\n".format(key,
seq[key][r[0]:r[1] + 1]))
ind = (seq_difs[key] + r[0], seq_difs[key] + r[1])
M0s.append(M0) inds.append(ind)
writelog(log, "[{0}] SEQ = {1}, bounds: from {2} to {3}. M0
= {4}\n".format(key, str(key), r[0], r[1] - 1, M0))
max_ind = M0s.index(max(M0s)) p, ind = M0s[max_ind], inds[max_ind] p = p - 0.5 if p > 0.5 else p
r = {"threshold": p, "indexes": ind}
return r
def get_module_dif(block, indexes): bc = get_block_coeffs(block, indexes) dif = get_difference_of_modules(bc[0], bc[1]) return fabs(dif)
def get_interval(seq): smax = max(seq) trsh = smax * CUT_COEFF
aseq = seq.copy() for i in range(len(aseq)): if aseq[i] < trsh: aseq[i] = 0.0
sq_inds = [] il, ir = 0, 0 for i in range(len(aseq)): if aseq[i] == 0.0: ir = i if ir - il > 0: sq_inds.append((il, ir - 1)) il = i + 1
if len(sq_inds) > 0: sizes = [j - i + 1 for (i, j) in sq_inds] max_size = max(sizes) il, ir = sq_inds[sizes.index(max_size)]
76
return il, ir
def find_two_maxs(d): m = max(d) il = d.index(m) d[il] = -1 m = max(d) ir = d.index(m)
if il < ir: return [il, ir] else: return [ir, il]
77
ПРИЛОЖЕНИЕ Г. Интерфейс программного комплекса Stegano
Analyzer
Для данного программного комплекса реализованы два вида интерфейса:
консольный (текстовый) и графический. Консольный пользовательский
интерфейс (КПИ) основан на указании так называемых аргументов командной
строки (аргументов запуска или флагов). Обязательным аргументом является
«-i» или «--image», указывающий на имя или путь до анализируемого файла изображения.
Обязательным также является указание методов, при помощи которых
будет производиться анализ. Для этого используются два аргумента: флаг «­am» или «--allmethods», предназначенный для получения результатов анализа всеми тремя реализованными методами, а также «-m» или «--method», позволяющий указать один конкретный метод стегоанализа.
Необязательным является аргумент-флаг «-e» или «--extract»,
устанавливающий необходимость извлечения информации, скрытой по
методу Коха-Жао, при её обнаружении.
Запуск консольного интерфейса может производиться при помощи
любого поддерживаемого операционной системой средства предоставления
интерфейса командной строки (например, CMD или PowerShell в операционной системе (ОС) Windows, эмуляторы терминалов Linux).
Демонстрация вызова разработанного приложения со стандартным
атрибутом «-h» (позволяющим увидеть подсказки по доступным в программе атрибутам запуска), произведённого в консоли Windows Terminal, представлена на рисунке ПГ.1.
78
Рисунок ПГ.1 – Вызов подсказки по использованию консольного интерфейса
Для запуска графической оболочки программы (графического
пользовательского интерфейса – ГПИ), предусмотрен атрибут «-g» или «-­gui».
Графический интерфейс предоставляет окно с четырьмя областями:
загрузки изображения, запуска анализа, миниатюры, результатов.
Область загрузки изображения позволяет выбрать файл поддерживаемого
графического формата. Его копия, масштабированная до необходимого
размера, будет показана в области миниатюры. Область запуска анализа
позволяет выбрать методы и дополнительные параметры (попытку извлечения
при анализе Коха-Жао и визуализацию результата при анализе методом Хи­квадрат).
Область результатов содержит данные о степени заполненности или
реальном размере обнаруженного встроенного сообщения (в зависимости от
метода анализа), а также блок извлечённых текстовых данных, если
соответствующий параметр был включён.
Если параметр, указывающий на необходимость визуализации
заполненности включён, то после проведения анализа в область миниатюры
будет загружено масштабированное изображение, на котором блоки,
79
предположительно соответствующие частям встроенного сообщения, будут
окрашены красным, а «чистые» блоки – зелёным.
Демонстрация главного окна ГПИ программного комплекса, вызванного
при помощи указания атрибута «-g» в консольном интерфейсе программы, представлена на рисунке ПГ.2.
Рисунок ПГ.2 – Вызов графического интерфейса программного комплекса
80
ПРИЛОЖЕНИЕ Д. Инструкция по использованию программного
комплекса Stegano Analyzer
При использовании консольного интерфейса общий вид команды запуска
программного комплекса имеет следующий вид:
SteganoAnalyzer {метод анализа} [необходимость извлечения] {имя файла}
Метод анализа должен быть задан одним из двух следующих флагов
(аргументов):
1) -m <METHOD>: задание одного из трёх доступных методов; вместо
«METHOD» должно быть указано:
chi2: для анализа по методу Хи-квадрат; rs: для анализа RS-методом; kza: для обнаружения скрытия по Коха-Жао.
2) -am: использование всех трёх доступных методов анализа
(игнорирует указание флага «-m»).
Необходимость извлечения задаётся флагом «-e» и может быть использована лишь при анализе скрытия по методу Коха-Жао. В противном случае флаг будет проигнорирован.
Имя файла определяется аргументом «-i <PATH>», где вместо PATH
следует указать имя или полный путь до файла изображения, которое следует
проанализировать.
Примеры использования вышеописанных аргументов запуска для
анализа изображений:
SteganoAnalyzer.exe -m chi2 -i img1.png SteganoAnalyzer.exe -m rs -i C:\data\img2.bmp SteganoAnalyzer.exe -m kza -e -i img3.bmp SteganoAnalyzer.exe -am -i C:\img4.png SteganoAnalyzer.exe -am -e -i img6.png
В качестве анализируемых изображений должны использоваться
графические файлы форматов PNG или BMP.
Запуск программы при помощи вышеописанной команды следует
выполнять в стандартном приложении «Командная строка», официальном
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]