Commit eb8204436b7f815e43661e80208af5fc543e6cb7

Authored by Chunk
1 parent c9fdeb00
Exists in master

staged.

msteg/StegBase.py 0 → 100644
@@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
  1 +"""
  2 +This module implements a common base class of the steganographic
  3 +algorithms which embed data into JPEG files.
  4 +In order to run plugins inheriting from this class
  5 +you must build the rw_dct.so library which interfaces with libjpeg.
  6 +To do so, just run
  7 +% python setup.py build
  8 +in stegotool/util and copy the rw_dct.so
  9 +library (which can be found somewhere in the build-directory to
  10 +stegotool/util.
  11 +
  12 +"""
  13 +import numpy as np
  14 +import time
  15 +import os
  16 +import sys
  17 +import random
  18 +import re
  19 +
  20 +import mjsteg
  21 +import jpegObj
  22 +from common import *
  23 +
  24 +
  25 +class StegBase(object):
  26 + """
  27 + This is the base class for some of the JPEG-algorithms that behave
  28 + similarly such as JSteg, OutGuess and F3.
  29 + """
  30 +
  31 + def __init__(self):
  32 + """
  33 + Constructor of the JPEGSteg class.
  34 + """
  35 + self.t0 = None
  36 + self.cov_jpeg = None
  37 + self.cov_data = None
  38 + self.hid_data = None
  39 +
  40 + def _get_cov_data(self, img_path):
  41 + """
  42 + Returns DCT coefficients of the cover image.
  43 + """
  44 + self.cov_jpeg = jpegObj.Jpeg(img_path)
  45 + self.cov_data = self.cov_jpeg.getCoefBlocks()
  46 + return self.cov_data
  47 +
  48 +
  49 + def _get_hid_data(self, src_hidden):
  50 + """
  51 + Returnsthe secret data as byte sequence.
  52 + """
  53 + raw = [0, 0, 0, 0] + np.fromfile(src_hidden, np.uint8).tolist()
  54 + raw_size = len(raw)
  55 + for i in xrange(4):
  56 + raw[i] = raw_size % 256
  57 + raw_size /= 256
  58 + self.hid_data = np.array(raw)
  59 +
  60 + if np.size(self.hid_data) * 8 > np.size(self.cov_data):
  61 + raise Exception("Cover image is too small to embed data.Cannot fit %d bits in %d DCT coefficients" % (
  62 + np.size(self.hid_data) * 8, np.size(self.cov_data)))
  63 + return self.hid_data
  64 +
  65 +
  66 + def _post_embed_actions(self, src_cover, src_hidden, tgt_stego):
  67 + """
  68 + This function isn't named very accurately. It actually calls the
  69 + _raw_embed function in inherited classes.
  70 + """
  71 + try:
  72 + cov_data = self._get_cov_data(src_cover)
  73 + hid_data = self._get_hid_data(src_hidden)
  74 + cov_data = self._raw_embed(cov_data, hid_data)
  75 +
  76 + self.cov_jpeg.setCoefBlocks(cov_data)
  77 + self.cov_jpeg.Jwrite(tgt_stego)
  78 +
  79 + size = os.path.getsize(tgt_stego)
  80 + size_embedded = np.size(hid_data)
  81 +
  82 + self._display_stats("embedded", size, size_embedded,
  83 + time.time() - self.t0)
  84 +
  85 + except TypeError as e:
  86 + raise e
  87 + except Exception:
  88 + raise Exception(
  89 + 'DCT coefficients exhausted. This usually means there are not enough DCT coefficients in the image in which algorithm can actually embed data. You should choose a larger image.')
  90 +
  91 + def _post_extract_actions(self, src_steg, tgt_hidden):
  92 + """
  93 + This function isn't named very accurately. It actually calls the
  94 + _raw_extract function in inherited classes.
  95 + """
  96 + try:
  97 + steg_data = self._get_cov_data(src_steg)
  98 + emb_size = os.path.getsize(src_steg)
  99 +
  100 + # recovering file size
  101 + header_size = 4 * 8
  102 + size_data = self._raw_extract(steg_data, header_size)
  103 + size_data = bits2bytes(size_data)
  104 + size_hd = 0
  105 + for i in xrange(4):
  106 + size_hd += size_data[i] * 256 ** i
  107 +
  108 + raw_size = size_hd * 8
  109 +
  110 + if raw_size > np.size(steg_data):
  111 + raise Exception("Supposed secret data too large for stego image.")
  112 +
  113 + hid_data = self._raw_extract(steg_data, raw_size)
  114 + hid_data = bits2bytes(hid_data)
  115 + hid_data[4:].tofile(tgt_hidden)
  116 +
  117 + self._display_stats("extracted", emb_size,
  118 + np.size(hid_data),
  119 + time.time() - self.t0)
  120 + except:
  121 + raise Exception('DCT coefficients exhausted.The stego image is probably corrupted.')
  122 +
  123 +
  124 + def _looks_like_jpeg(self, path):
  125 + try:
  126 + with open(path, 'r') as f:
  127 + return f.read(2) == '\xff\xd8'
  128 + except IOError:
  129 + return False
  130 +
  131 + def _display_stats(self, verb, cov_size, emb_size, duration):
  132 + print(
  133 + "%dB %s in %.2fs (%.2f kBps), embedding ratio: %.4f" %
  134 + (emb_size, verb, duration, (emb_size / duration) / 1000.,
  135 + float(emb_size) / cov_size))
  136 +
  137 + # dummy functions to please pylint
  138 + def _raw_embed(self, cov_data, hid_data, status_begin=0):
  139 + pass
  140 +
  141 + def _raw_extract(self, steg_data, num_bits):
  142 + pass
  143 +
  144 + def _dummy_embed_hook(self, cov_data, hid_data):
  145 + pass
  146 +
  147 + def _dummy_extract_hook(self, steg_data, num_bits):
  148 + pass
msteg/steganalysis/ChiSquare.py 0 → 100644
@@ -0,0 +1,165 @@ @@ -0,0 +1,165 @@
  1 +"""
  2 +<p>
  3 +This module implements an algorithm described by Andreas Westfeld in [1,2],
  4 +which detects if there was data embedded into an image using JSteg.
  5 +It uses the property that JSteg generates pairs of values in the
  6 +DCT-coefficients histogram, which can be detected by a \chi^2 test.
  7 +</p>
  8 +
  9 +<pre>
  10 +[1]: Andreas Westfeld, F5 - A Steganographic Algorithm High Capacity Despite
  11 +Better Steganalysis
  12 +[2]: Andreas Westfeld, Angriffe auf steganographische Systeme
  13 +</pre>
  14 +"""
  15 +
  16 +from collections import defaultdict
  17 +import os
  18 +
  19 +import Image
  20 +import numpy
  21 +from scipy.stats import chisquare
  22 +import matplotlib.pyplot as plt
  23 +import itertools as it
  24 +
  25 +from stegotool.util.plugins import describe_and_annotate
  26 +from stegotool.util.plugins import ImagePath, NewFilePath
  27 +from stegotool.util.JPEGSteg import JPEGSteg
  28 +from stegotool.util import rw_dct
  29 +
  30 +class ChiSquare(JPEGSteg):
  31 + """
  32 + The module contains only one method, <b>detect</b>.
  33 + """
  34 +
  35 + def __init__(self, ui, core):
  36 + self.ui = ui
  37 + self.core = core
  38 +
  39 + @describe_and_annotate((None, None),
  40 + ("Source image", ImagePath),
  41 + ("Target image", NewFilePath),
  42 + ("2nd Target image", NewFilePath))
  43 + def detect(self, src, tgt, tgt2):
  44 + """
  45 + <p>
  46 + Detect if there was data embedded in the <i>source image</i> image with
  47 + JSteg algorithm.
  48 + </p>
  49 +
  50 + <p>
  51 + Parameters:
  52 + <ol>
  53 + <li><pre>Source image</pre> Image which should be tested</li>
  54 + <li><pre>Target image</pre> Image which displays a graphic with the
  55 + embedding probability</li>
  56 + <li><pre>2nd Target image</pre> Image which displays the embedding
  57 + positions in the image</li>
  58 + </ol>
  59 + </p>
  60 + """
  61 + # --------------------------- Input -----------------------------------
  62 + # If src is from the image pool, test whether the image exists encoded
  63 + # on the file system. Otherwise we can not read DCT-coefficients.
  64 + if self.core.media_manager.is_media_key(src):
  65 + src = self.core.media_manager.get_file(src)
  66 + if hasattr(src, 'tmp_file'):
  67 + src = src.tmp_file
  68 + self.ui.display_error('Trying file: %s' % src)
  69 + else:
  70 + self.ui.display_error('Can not detect anything from \
  71 + decoded images.')
  72 + return
  73 + # Test whether the file exists.
  74 + if not os.path.isfile(src):
  75 + self.ui.display_error('No such file.')
  76 + return
  77 + # Test if it is a JPEG file.
  78 + if not self._looks_like_jpeg(src):
  79 + self.ui.display_error('Input is probably not a JPEG file.')
  80 + return
  81 +
  82 + # ---------------------------- Algorithm ------------------------------
  83 + # Build DCT-histogram in steps of \approx 1% of all coefficients and
  84 + # calculate the p-value at each step.
  85 + dct_data = rw_dct.read_dct_coefficients(src)
  86 + hist = defaultdict(int)
  87 + cnt = 0
  88 + l = len(dct_data)
  89 + one_p = l / 100
  90 + result = []
  91 + for block in dct_data:
  92 + # update the histogram with one block of 64 coefficients
  93 + for c in block:
  94 + hist[c] += 1
  95 +
  96 + cnt += 1
  97 + if not cnt % one_p:
  98 + # calculate p-value
  99 + self.ui.set_progress(cnt * 100 / l)
  100 +
  101 + # ignore the pair (0, 1), since JSteg does not embed data there
  102 + hl = [hist[i] for i in range(-2048, 2049) if not i in (0, 1)]
  103 + k = len(hl) / 2
  104 + observed = []
  105 + expected = []
  106 + # calculate observed and expected distribution
  107 + for i in range(k):
  108 + t = hl[2 * i] + hl[2 * i + 1]
  109 + if t > 3:
  110 + observed.append(hl[2 * i])
  111 + expected.append(t / 2)
  112 + # calculate (\chi^2, p)
  113 + p = chisquare(numpy.array(observed), numpy.array(expected))[1]
  114 + result.append(p)
  115 +
  116 + # ----------------------------- Output --------------------------------
  117 + # Graph displaying the embedding probabilities in relation to the
  118 + # sample size.
  119 + figure = plt.figure()
  120 + plot = figure.add_subplot(111)
  121 + plot.grid(True)
  122 + plot.plot(result, color='r', linewidth=2.0)
  123 + plt.axis([0, 100, 0, 1.1])
  124 + plt.title('Embedding probability for different percentages \
  125 +of the file capacity.')
  126 + plt.xlabel('% of file capacity')
  127 + plt.ylabel('Embedding probability')
  128 +
  129 + if self.core.media_manager.is_media_key(tgt):
  130 + img = figure_to_pil(figure)
  131 + self.core.media_manager.put_media(tgt, img)
  132 + else:
  133 + plt.savefig(tgt)
  134 +
  135 + # Image displaying the length and position of the embedded data
  136 + # within the image
  137 + img2 = Image.open(src)
  138 + img2.convert("RGB")
  139 + width, height = img2.size
  140 +
  141 + for i in range(100):
  142 + result[i] = max(result[i:])
  143 +
  144 + cnt2 = 0
  145 + for (top, left) in it.product(range(0, height, 8), range(0, width, 8)):
  146 + if not cnt2 % one_p:
  147 + r = result[cnt2 / one_p]
  148 + if r >= 0.5:
  149 + color = (255, int((1 - r) * 2 * 255), 0)
  150 + else:
  151 + color = (int(r * 2 * 255), 255, 0)
  152 + cnt2 += 1
  153 + img2.paste(color, (left, top, min(left + 8, width),
  154 + min(top + 8, height)))
  155 + self.core.media_manager.put_media(tgt2, img2)
  156 +
  157 + def __str__(self):
  158 + return 'Chi-Square-Test'
  159 +
  160 +
  161 +def figure_to_pil(figure):
  162 + figure.canvas.draw()
  163 + return Image.fromstring('RGB',
  164 + figure.canvas.get_width_height(),
  165 + figure.canvas.tostring_rgb())
msteg/steganography/StegBase.py
@@ -1,148 +0,0 @@ @@ -1,148 +0,0 @@
1 -"""  
2 -This module implements a common base class of the steganographic  
3 -algorithms which embed data into JPEG files.  
4 -In order to run plugins inheriting from this class  
5 -you must build the rw_dct.so library which interfaces with libjpeg.  
6 -To do so, just run  
7 -% python setup.py build  
8 -in stegotool/util and copy the rw_dct.so  
9 -library (which can be found somewhere in the build-directory to  
10 -stegotool/util.  
11 -  
12 -"""  
13 -import numpy as np  
14 -import time  
15 -import os  
16 -import sys  
17 -import random  
18 -import re  
19 -  
20 -import mjsteg  
21 -import jpegObj  
22 -from common import *  
23 -  
24 -  
25 -class StegBase(object):  
26 - """  
27 - This is the base class for some of the JPEG-algorithms that behave  
28 - similarly such as JSteg, OutGuess and F3.  
29 - """  
30 -  
31 - def __init__(self):  
32 - """  
33 - Constructor of the JPEGSteg class.  
34 - """  
35 - self.t0 = None  
36 - self.cov_jpeg = None  
37 - self.cov_data = None  
38 - self.hid_data = None  
39 -  
40 - def _get_cov_data(self, img_path):  
41 - """  
42 - Returns DCT coefficients of the cover image.  
43 - """  
44 - self.cov_jpeg = jpegObj.Jpeg(img_path)  
45 - self.cov_data = self.cov_jpeg.getCoefBlocks()  
46 - return self.cov_data  
47 -  
48 -  
49 - def _get_hid_data(self, src_hidden):  
50 - """  
51 - Returnsthe secret data as byte sequence.  
52 - """  
53 - raw = [0, 0, 0, 0] + np.fromfile(src_hidden, np.uint8).tolist()  
54 - raw_size = len(raw)  
55 - for i in xrange(4):  
56 - raw[i] = raw_size % 256  
57 - raw_size /= 256  
58 - self.hid_data = np.array(raw)  
59 -  
60 - if np.size(self.hid_data) * 8 > np.size(self.cov_data):  
61 - raise Exception("Cover image is too small to embed data.Cannot fit %d bits in %d DCT coefficients" % (  
62 - np.size(self.hid_data) * 8, np.size(self.cov_data)))  
63 - return self.hid_data  
64 -  
65 -  
66 - def _post_embed_actions(self, src_cover, src_hidden, tgt_stego):  
67 - """  
68 - This function isn't named very accurately. It actually calls the  
69 - _raw_embed function in inherited classes.  
70 - """  
71 - try:  
72 - cov_data = self._get_cov_data(src_cover)  
73 - hid_data = self._get_hid_data(src_hidden)  
74 - cov_data = self._raw_embed(cov_data, hid_data)  
75 -  
76 - self.cov_jpeg.setCoefBlocks(cov_data)  
77 - self.cov_jpeg.Jwrite(tgt_stego)  
78 -  
79 - size = os.path.getsize(tgt_stego)  
80 - size_embedded = np.size(hid_data)  
81 -  
82 - self._display_stats("embedded", size, size_embedded,  
83 - time.time() - self.t0)  
84 -  
85 - except TypeError as e:  
86 - raise e  
87 - except Exception:  
88 - raise Exception(  
89 - 'DCT coefficients exhausted. This usually means there are not enough DCT coefficients in the image in which algorithm can actually embed data. You should choose a larger image.')  
90 -  
91 - def _post_extract_actions(self, src_steg, tgt_hidden):  
92 - """  
93 - This function isn't named very accurately. It actually calls the  
94 - _raw_extract function in inherited classes.  
95 - """  
96 - try:  
97 - steg_data = self._get_cov_data(src_steg)  
98 - emb_size = os.path.getsize(src_steg)  
99 -  
100 - # recovering file size  
101 - header_size = 4 * 8  
102 - size_data = self._raw_extract(steg_data, header_size)  
103 - size_data = bits2bytes(size_data)  
104 - size_hd = 0  
105 - for i in xrange(4):  
106 - size_hd += size_data[i] * 256 ** i  
107 -  
108 - raw_size = size_hd * 8  
109 -  
110 - if raw_size > np.size(steg_data):  
111 - raise Exception("Supposed secret data too large for stego image.")  
112 -  
113 - hid_data = self._raw_extract(steg_data, raw_size)  
114 - hid_data = bits2bytes(hid_data)  
115 - hid_data[4:].tofile(tgt_hidden)  
116 -  
117 - self._display_stats("extracted", emb_size,  
118 - np.size(hid_data),  
119 - time.time() - self.t0)  
120 - except:  
121 - raise Exception('DCT coefficients exhausted.The stego image is probably corrupted.')  
122 -  
123 -  
124 - def _looks_like_jpeg(self, path):  
125 - try:  
126 - with open(path, 'r') as f:  
127 - return f.read(2) == '\xff\xd8'  
128 - except IOError:  
129 - return False  
130 -  
131 - def _display_stats(self, verb, cov_size, emb_size, duration):  
132 - print(  
133 - "%dB %s in %.2fs (%.2f kBps), embedding ratio: %.4f" %  
134 - (emb_size, verb, duration, (emb_size / duration) / 1000.,  
135 - float(emb_size) / cov_size))  
136 -  
137 - # dummy functions to please pylint  
138 - def _raw_embed(self, cov_data, hid_data, status_begin=0):  
139 - pass  
140 -  
141 - def _raw_extract(self, steg_data, num_bits):  
142 - pass  
143 -  
144 - def _dummy_embed_hook(self, cov_data, hid_data):  
145 - pass  
146 -  
147 - def _dummy_extract_hook(self, steg_data, num_bits):  
148 - pass  
1 this is to be embeded. 1 this is to be embeded.
  2 +//0216
  3 +vim of clang - https://github.com/JBakamovic/yavide
  4 +# Usage overview
  5 +Category | Shortcut | Description
  6 +--------------------------------- | --------------------------------- | ---------------------------------
  7 +**Project management** | |
  8 + | `<Ctrl-s>n` | Create new project
  9 + | `<Ctrl-s>i` | Import project with already existing code base
  10 + | `<Ctrl-s>o` | Open project
  11 + | `<Ctrl-s>c` | Close project
  12 + | `<Ctrl-s>s` | Save project
  13 + | `<Ctrl-s>d` | Delete project
  14 +**Buffer management** | |
  15 + | `<Ctrl-c>` | Close current buffer
  16 + | `<Ctrl-s>` | Save current buffer
  17 + | `<Ctrl-Tab>` | Go to next buffer
  18 + | `<Ctrl-Shift-Tab>` | Go to previous buffer
  19 + | `<Ctrl-Down>` | Scroll buffer by one line (down)
  20 + | `<Ctrl-Up>` | Scroll buffer by one line (up)
  21 +**Buffer modes** | |
  22 + | `<ESC>` | Enter the `normal` mode
  23 + | `<a>` | Enter the `insert` mode (append after cursor)
  24 + | `<i>` | Enter the `insert` mode (insert before cursor)
  25 + | `<Shift-v>` | Enter the `visual` mode (line mode)
  26 + | `<v>` | Enter the `visual` mode (character mode)
  27 +**Buffer editing** | |
  28 + | `<Ctrl-a>` | Select all
  29 + | `<Ctrl-x>` | Cut
  30 + | `<Ctrl-c>` | Copy
  31 + | `<Ctrl-v>` | Paste
  32 + | `<Ctrl-z>` | Undo
  33 + | `<Ctrl-r>` | Redo
  34 + | `<Shift-s>` | Delete the whole line
1 Binary files a/res/extracted and b/res/extracted differ 1 Binary files a/res/extracted and b/res/extracted differ
res/steged.jpg

50.3 KB | W: | H:

43.7 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin