zsteg 0.1.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +4 -4
- data/Gemfile.lock +69 -52
- data/README.md +43 -10
- data/README.md.tpl +5 -0
- data/VERSION +1 -1
- data/lib/zsteg/checker.rb +3 -1
- data/lib/zsteg/checker/scanline_checker.rb +1 -0
- data/lib/zsteg/checker/wbstego.rb +1 -0
- data/lib/zsteg/cli/cli.rb +22 -2
- data/lib/zsteg/cli/mask.rb +5 -1
- data/lib/zsteg/cli/reflow.rb +55 -33
- data/lib/zsteg/extractor/byte_extractor.rb +2 -1
- data/lib/zsteg/extractor/color_extractor.rb +2 -2
- data/lib/zsteg/file_cmd.rb +1 -1
- data/lib/zsteg/result.rb +1 -0
- data/spec/cats_spec.rb +3 -1
- data/spec/newbiecontest_spec.rb +2 -1
- data/spec/polictf2012_spec.rb +26 -12
- data/spec/spec_helper.rb +4 -2
- data/spec/zlib_spec.rb +19 -3
- data/zsteg.gemspec +25 -31
- metadata +27 -28
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 03b8c9494bd4dfb5953973438b62cd909abb1a0d6fc46363928e9a3773e1e47a
|
|
4
|
+
data.tar.gz: a46faa826bc3781860881b4c15d9e6c04fb86da6dedfd5df2487f62fa09fcbf1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f4243a62114c5098d56c59d273deaff5addf89b334377ba0d63032a6aee9759720ff3772805ae6a445179d3487a40b436024cc1c431f9a723e8de5140e2f683
|
|
7
|
+
data.tar.gz: 86eed1938f6c92812ab461f25b8647a25034e06b1b8c23b81187c253ef987de84d49a5e6d1521874fc480cf9cbe136559d921ab91ea8d2501383a13688dcb49d
|
data/Gemfile
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
source "http://rubygems.org"
|
|
2
2
|
|
|
3
|
-
gem 'zpng', ">= 0.
|
|
3
|
+
gem 'zpng', ">= 0.3.1"
|
|
4
4
|
gem "iostruct"
|
|
5
5
|
|
|
6
6
|
group :development do
|
|
7
|
-
gem "rspec", "
|
|
8
|
-
gem "bundler", "
|
|
9
|
-
gem "jeweler", "~>
|
|
7
|
+
gem "rspec", "~> 3.9.0"
|
|
8
|
+
gem "bundler", "~> 2.2.3"
|
|
9
|
+
gem "jeweler", "~> 2.3.9"
|
|
10
10
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,68 +1,85 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
remote: http://rubygems.org/
|
|
3
3
|
specs:
|
|
4
|
-
addressable (2.
|
|
5
|
-
builder (3.2.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
4
|
+
addressable (2.4.0)
|
|
5
|
+
builder (3.2.4)
|
|
6
|
+
descendants_tracker (0.0.4)
|
|
7
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
8
|
+
diff-lcs (1.4.4)
|
|
9
|
+
faraday (0.9.2)
|
|
10
|
+
multipart-post (>= 1.2, < 3)
|
|
11
|
+
git (1.8.1)
|
|
12
|
+
rchardet (~> 1.8)
|
|
13
|
+
github_api (0.16.0)
|
|
14
|
+
addressable (~> 2.4.0)
|
|
15
|
+
descendants_tracker (~> 0.0.4)
|
|
16
|
+
faraday (~> 0.8, < 0.10)
|
|
17
|
+
hashie (>= 3.4)
|
|
18
|
+
mime-types (>= 1.16, < 3.0)
|
|
19
|
+
oauth2 (~> 1.0)
|
|
20
|
+
hashie (4.1.0)
|
|
21
|
+
highline (2.0.3)
|
|
22
|
+
iostruct (0.0.4)
|
|
23
|
+
jeweler (2.3.9)
|
|
22
24
|
builder
|
|
23
|
-
bundler
|
|
25
|
+
bundler
|
|
24
26
|
git (>= 1.2.5)
|
|
25
|
-
github_api (
|
|
27
|
+
github_api (~> 0.16.0)
|
|
26
28
|
highline (>= 1.6.15)
|
|
27
|
-
nokogiri (
|
|
29
|
+
nokogiri (>= 1.5.10)
|
|
30
|
+
psych
|
|
28
31
|
rake
|
|
29
32
|
rdoc
|
|
30
|
-
|
|
31
|
-
jwt (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
semver2
|
|
34
|
+
jwt (2.2.2)
|
|
35
|
+
mime-types (2.99.3)
|
|
36
|
+
mini_portile2 (2.5.0)
|
|
37
|
+
multi_json (1.15.0)
|
|
38
|
+
multi_xml (0.6.0)
|
|
39
|
+
multipart-post (2.1.1)
|
|
40
|
+
nokogiri (1.11.1)
|
|
41
|
+
mini_portile2 (~> 2.5.0)
|
|
42
|
+
racc (~> 1.4)
|
|
43
|
+
oauth2 (1.4.4)
|
|
44
|
+
faraday (>= 0.8, < 2.0)
|
|
45
|
+
jwt (>= 1.0, < 3.0)
|
|
46
|
+
multi_json (~> 1.3)
|
|
42
47
|
multi_xml (~> 0.5)
|
|
43
|
-
rack (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
rspec-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
rack (>= 1.2, < 3)
|
|
49
|
+
psych (3.3.0)
|
|
50
|
+
racc (1.5.2)
|
|
51
|
+
rack (2.2.3)
|
|
52
|
+
rainbow (3.0.0)
|
|
53
|
+
rake (13.0.3)
|
|
54
|
+
rchardet (1.8.0)
|
|
55
|
+
rdoc (6.3.0)
|
|
56
|
+
rspec (3.9.0)
|
|
57
|
+
rspec-core (~> 3.9.0)
|
|
58
|
+
rspec-expectations (~> 3.9.0)
|
|
59
|
+
rspec-mocks (~> 3.9.0)
|
|
60
|
+
rspec-core (3.9.3)
|
|
61
|
+
rspec-support (~> 3.9.3)
|
|
62
|
+
rspec-expectations (3.9.4)
|
|
63
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
64
|
+
rspec-support (~> 3.9.0)
|
|
65
|
+
rspec-mocks (3.9.1)
|
|
66
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
67
|
+
rspec-support (~> 3.9.0)
|
|
68
|
+
rspec-support (3.9.4)
|
|
69
|
+
semver2 (3.4.2)
|
|
70
|
+
thread_safe (0.3.6)
|
|
71
|
+
zpng (0.3.2)
|
|
58
72
|
rainbow
|
|
59
73
|
|
|
60
74
|
PLATFORMS
|
|
61
75
|
ruby
|
|
62
76
|
|
|
63
77
|
DEPENDENCIES
|
|
64
|
-
bundler (
|
|
78
|
+
bundler (~> 2.2.3)
|
|
65
79
|
iostruct
|
|
66
|
-
jeweler (~>
|
|
67
|
-
rspec (
|
|
68
|
-
zpng (>= 0.
|
|
80
|
+
jeweler (~> 2.3.9)
|
|
81
|
+
rspec (~> 3.9.0)
|
|
82
|
+
zpng (>= 0.3.1)
|
|
83
|
+
|
|
84
|
+
BUNDLED WITH
|
|
85
|
+
2.2.3
|
data/README.md
CHANGED
|
@@ -29,17 +29,26 @@ Usage
|
|
|
29
29
|
Usage: zsteg [options] filename.png [param_string]
|
|
30
30
|
|
|
31
31
|
-c, --channels X channels (R/G/B/A) or any combination, comma separated
|
|
32
|
-
valid values: r,g,b,a,rg,
|
|
32
|
+
valid values: r,g,b,a,rg,bgr,rgba,r3g2b3,...
|
|
33
33
|
-l, --limit N limit bytes checked, 0 = no limit (default: 256)
|
|
34
|
-
-b, --bits N number of bits
|
|
34
|
+
-b, --bits N number of bits, single int value or '1,3,5' or range '1-8'
|
|
35
|
+
advanced: specify individual bits like '00001110' or '0x88'
|
|
35
36
|
--lsb least significant BIT comes first
|
|
36
37
|
--msb most significant BIT comes first
|
|
37
38
|
-P, --prime analyze/extract only prime bytes/pixels
|
|
39
|
+
--invert invert bits (XOR 0xff)
|
|
38
40
|
-a, --all try all known methods
|
|
39
41
|
-o, --order X pixel iteration order (default: 'auto')
|
|
40
42
|
valid values: ALL,xy,yx,XY,YX,xY,Xy,bY,...
|
|
41
43
|
-E, --extract NAME extract specified payload, NAME is like '1b,rgb,lsb'
|
|
42
44
|
|
|
45
|
+
--[no-]file use 'file' command to detect data type (default: YES)
|
|
46
|
+
--no-strings disable ASCII strings finding (default: enabled)
|
|
47
|
+
-s, --strings X ASCII strings find mode: first, all, longest, none
|
|
48
|
+
(default: first)
|
|
49
|
+
-n, --min-str-len X minimum string length (default: 8)
|
|
50
|
+
--shift N prepend N zero bits
|
|
51
|
+
|
|
43
52
|
-v, --verbose Run verbosely (can be used multiple times)
|
|
44
53
|
-q, --quiet Silent any warnings (can be used multiple times)
|
|
45
54
|
-C, --[no-]color Force (or disable) color output (default: auto)
|
|
@@ -54,7 +63,8 @@ Examples
|
|
|
54
63
|
|
|
55
64
|
# zsteg flower_rgb3.png
|
|
56
65
|
|
|
57
|
-
|
|
66
|
+
imagedata .. file: 370 XA sysV pure executable not stripped - version 768
|
|
67
|
+
b3,rgb,lsb,xy .. text: "SuperSecretMessage"
|
|
58
68
|
|
|
59
69
|
### Multi-result file
|
|
60
70
|
|
|
@@ -65,16 +75,34 @@ Examples
|
|
|
65
75
|
meta A .. [same as "meta F"]
|
|
66
76
|
meta date:create .. text: "2012-03-15T23:32:46+07:00"
|
|
67
77
|
meta date:modify .. text: "2012-03-15T23:32:14+07:00"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
imagedata .. file: 68K BCS executable
|
|
79
|
+
b1,r,lsb,xy .. text: "Second cat is Marussia"
|
|
80
|
+
b1,g,lsb,xy .. text: "Good, but look a bit deeper..."
|
|
81
|
+
b1,bgr,lsb,xy .. text: "MF_WIhf>"
|
|
82
|
+
b2,g,lsb,xy .. text: "VHello, third kitten is Bessy"
|
|
72
83
|
|
|
73
84
|
### wbStego even distributed
|
|
74
85
|
|
|
75
86
|
# zsteg wbstego/wbsteg_noenc_even.bmp 1b,lsb,bY -v
|
|
76
87
|
|
|
77
|
-
|
|
88
|
+
imagedata .. file: FoxPro FPT, blocks size 1, next free block index 65537
|
|
89
|
+
00000000: 00 01 00 01 00 00 00 01 00 00 00 00 00 00 00 00 |................|
|
|
90
|
+
00000010: 00 00 00 00 00 00 00 00 00 00 00 01 00 01 01 00 |................|
|
|
91
|
+
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
92
|
+
00000030: 00 01 01 01 00 01 00 00 00 00 00 00 01 01 00 01 |................|
|
|
93
|
+
00000040: 01 00 01 01 00 01 00 01 00 01 01 01 01 00 00 00 |................|
|
|
94
|
+
00000050: 00 00 00 01 01 01 01 00 01 00 01 00 00 00 00 01 |................|
|
|
95
|
+
00000060: 00 00 01 01 01 00 00 01 00 01 01 01 00 01 00 00 |................|
|
|
96
|
+
00000070: 01 01 01 00 01 00 00 00 00 00 01 01 01 00 00 00 |................|
|
|
97
|
+
00000080: 00 01 00 01 00 00 01 01 01 01 00 00 00 01 01 00 |................|
|
|
98
|
+
00000090: 00 01 00 01 00 01 01 00 01 00 00 01 00 01 00 00 |................|
|
|
99
|
+
000000a0: 00 01 01 01 00 01 00 01 01 01 00 01 00 00 00 01 |................|
|
|
100
|
+
000000b0: 01 00 01 00 00 01 00 01 00 01 01 01 00 00 00 00 |................|
|
|
101
|
+
000000c0: 01 00 00 00 00 01 00 00 01 01 00 00 01 00 00 00 |................|
|
|
102
|
+
000000d0: 00 00 01 00 00 01 01 01 00 01 01 00 00 01 00 01 |................|
|
|
103
|
+
000000e0: 01 01 01 01 01 01 01 00 00 00 00 00 01 00 00 00 |................|
|
|
104
|
+
000000f0: 00 01 01 01 00 00 01 00 00 00 01 01 00 01 00 01 |................|
|
|
105
|
+
b1,lsb,bY .. <wbStego size=22, data="xtSuperSecretMessage\n", even=true, mix=true, controlbyte="t">
|
|
78
106
|
00000000: 51 00 00 16 00 00 74 0d b5 78 1e a1 39 74 e8 38 |Q.....t..x..9t.8|
|
|
79
107
|
00000010: 53 c6 56 94 75 d1 a5 70 84 c8 27 65 fe 08 72 35 |S.V.u..p..'e..r5|
|
|
80
108
|
00000020: 1f 3e 53 5d a7 65 8b 6e 3b 63 6b 1d bf 72 ee 27 |.>S].e.n;ck..r.'|
|
|
@@ -86,7 +114,7 @@ Examples
|
|
|
86
114
|
|
|
87
115
|
# zsteg wbstego/wbsteg_blowfish_pass_1.bmp 1b,lsb,bY -v
|
|
88
116
|
|
|
89
|
-
|
|
117
|
+
b1,lsb,bY .. <wbStego size=26, data="\rC\xF5\xBF#\xFF[6\e\xB3"..., even=false, hdr="\x01", enc="Blowfish">
|
|
90
118
|
00000000: 1a 00 00 00 ff 01 01 0d 43 f5 bf 23 ff 5b 36 1b |........C..#.[6.|
|
|
91
119
|
00000010: b3 17 42 4a 3f ba eb c7 ee 9c d7 7a 2b |..BJ?......z+ |
|
|
92
120
|
|
|
@@ -94,7 +122,7 @@ Examples
|
|
|
94
122
|
|
|
95
123
|
# zsteg ndh2k12_sp113.bmp -b 1 -o yx -v
|
|
96
124
|
|
|
97
|
-
|
|
125
|
+
b1,rgb,lsb,yx .. zlib: data="%PDF-1.4\n%\xC3\xA4\xC3\xBC\xC3\xB6\xC3\x9F\n2 0 obj\n<</Length 3 0 R/Filter/FlateDecode>>\nstream\nx\x9C\x8DT\xC9n\xDB@\f\xBD\xCFW\xF0\x1C \x13\x92\xB3\x03\x86\x80\xC8K\xD1\xDE\\\b\xE8\xA1...", offset=4, size=186
|
|
98
126
|
00000000: 00 02 eb 9b 78 9c d4 b9 65 54 24 cc 92 36 58 b8 |....x...eT$..6X.|
|
|
99
127
|
00000010: d3 68 e3 ee ee 4e e3 ee ee 0e 85 bb 3b dd 68 23 |.h...N......;.h#|
|
|
100
128
|
00000020: 8d bb bb bb 3b 8d bb bb 3b 34 ee 6e 1f ef 7b ef |....;...;4.n..{.|
|
|
@@ -112,6 +140,11 @@ Examples
|
|
|
112
140
|
000000e0: fd bb 13 a9 e6 3a c9 da 19 34 ae f0 43 bb 90 90 |.....:...4..C...|
|
|
113
141
|
000000f0: 58 88 de 46 ce 91 6f aa 8d d9 7d b8 d6 88 a6 65 |X..F..o...}....e|
|
|
114
142
|
|
|
143
|
+
See also
|
|
144
|
+
--------
|
|
145
|
+
1. https://29a.ch/photo-forensics/
|
|
146
|
+
2. https://holloway.nz/steg/
|
|
147
|
+
|
|
115
148
|
License
|
|
116
149
|
-------
|
|
117
150
|
Released under the MIT License. See the [LICENSE](https://github.com/zed-0xff/zsteg/blob/master/LICENSE.txt) file for further details.
|
data/README.md.tpl
CHANGED
|
@@ -49,6 +49,11 @@ Examples
|
|
|
49
49
|
|
|
50
50
|
% zsteg ndh2k12_sp113.bmp -b 1 -o yx -v
|
|
51
51
|
|
|
52
|
+
See also
|
|
53
|
+
--------
|
|
54
|
+
1. https://29a.ch/photo-forensics/
|
|
55
|
+
2. https://holloway.nz/steg/
|
|
56
|
+
|
|
52
57
|
License
|
|
53
58
|
-------
|
|
54
59
|
Released under the MIT License. See the [LICENSE](https://github.com/zed-0xff/zsteg/blob/master/LICENSE.txt) file for further details.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.3
|
data/lib/zsteg/checker.rb
CHANGED
|
@@ -310,6 +310,8 @@ module ZSteg
|
|
|
310
310
|
show_result result, params
|
|
311
311
|
end
|
|
312
312
|
if data.size > 0 && !result.is_a?(Result::OneChar) && !result.is_a?(Result::WholeText)
|
|
313
|
+
# newline if no results and want hexdump
|
|
314
|
+
puts if !result || result == []
|
|
313
315
|
limit = (params[:limit] || @params[:limit]).to_i
|
|
314
316
|
t = limit > 0 ? data[0,limit] : data
|
|
315
317
|
print ZPNG::Hexdump.dump(t){ |x| x.prepend(" "*4) }
|
|
@@ -383,7 +385,7 @@ module ZSteg
|
|
|
383
385
|
# t = data.
|
|
384
386
|
# encode('UTF-16', 'UTF-8', :invalid => :replace, :replace => '').
|
|
385
387
|
# encode!('UTF-8', 'UTF-16')
|
|
386
|
-
# r = t.scan(/\p{Word}{#{
|
|
388
|
+
# r = t.scan(/\p{Word}{#{DEFAULT_MIN_STR_LEN},}/)
|
|
387
389
|
# r if r.any?
|
|
388
390
|
# rescue
|
|
389
391
|
# end
|
data/lib/zsteg/cli/cli.rb
CHANGED
|
@@ -112,6 +112,10 @@ module ZSteg
|
|
|
112
112
|
@options[:min_str_len] = x
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
+
opts.on "--shift N", Integer, "prepend N zero bits" do |x|
|
|
116
|
+
@options[:shift] = x
|
|
117
|
+
end
|
|
118
|
+
|
|
115
119
|
opts.separator ""
|
|
116
120
|
opts.on "-v", "--verbose", "Run verbosely (can be used multiple times)" do |v|
|
|
117
121
|
@options[:verbose] += 1
|
|
@@ -120,7 +124,11 @@ module ZSteg
|
|
|
120
124
|
@options[:verbose] -= 1
|
|
121
125
|
end
|
|
122
126
|
opts.on "-C", "--[no-]color", "Force (or disable) color output (default: auto)" do |x|
|
|
123
|
-
|
|
127
|
+
if defined?(Rainbow) && Rainbow.respond_to?(:enabled=)
|
|
128
|
+
Rainbow.enabled = x
|
|
129
|
+
else
|
|
130
|
+
Sickill::Rainbow.enabled = x
|
|
131
|
+
end
|
|
124
132
|
end
|
|
125
133
|
opts.separator "\nPARAMS SHORTCUT\n"+
|
|
126
134
|
"\tzsteg fname.png 2b,b,lsb,xy ==> --bits 2 --channel b --lsb --order xy"
|
|
@@ -201,6 +209,8 @@ module ZSteg
|
|
|
201
209
|
h[:order] = x
|
|
202
210
|
when 'prime'
|
|
203
211
|
h[:prime] = true
|
|
212
|
+
when 'zlib'
|
|
213
|
+
h[:zlib] = true
|
|
204
214
|
else
|
|
205
215
|
raise "uknown param #{x.inspect}"
|
|
206
216
|
end
|
|
@@ -219,6 +229,8 @@ module ZSteg
|
|
|
219
229
|
# zlib stream may contain extradata
|
|
220
230
|
@img.imagedata
|
|
221
231
|
@img.extradata[$1.to_i]
|
|
232
|
+
when /imagedata/
|
|
233
|
+
@img.imagedata
|
|
222
234
|
else
|
|
223
235
|
h = decode_param_string name
|
|
224
236
|
h[:limit] = @options[:limit] if @options[:limit] != Checker::DEFAULT_LIMIT
|
|
@@ -234,7 +246,15 @@ module ZSteg
|
|
|
234
246
|
end
|
|
235
247
|
|
|
236
248
|
def extract name
|
|
237
|
-
|
|
249
|
+
data = _extract_data(name)
|
|
250
|
+
if name['zlib']
|
|
251
|
+
if r = Checker::Zlib.check_data(data)
|
|
252
|
+
data = r.data
|
|
253
|
+
else
|
|
254
|
+
raise "cannot decompress with zlib"
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
print data
|
|
238
258
|
end
|
|
239
259
|
|
|
240
260
|
end
|
data/lib/zsteg/cli/mask.rb
CHANGED
|
@@ -77,7 +77,11 @@ module ZSteg
|
|
|
77
77
|
@options[:verbose] -= 1
|
|
78
78
|
end
|
|
79
79
|
opts.on "-C", "--[no-]color", "Force (or disable) color output (default: auto)" do |x|
|
|
80
|
-
|
|
80
|
+
if defined?(Rainbow) && Rainbow.respond_to?(:enabled=)
|
|
81
|
+
Rainbow.enabled = x
|
|
82
|
+
else
|
|
83
|
+
Sickill::Rainbow.enabled = x
|
|
84
|
+
end
|
|
81
85
|
end
|
|
82
86
|
end
|
|
83
87
|
|
data/lib/zsteg/cli/reflow.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#coding: binary
|
|
1
2
|
require 'optparse'
|
|
2
3
|
require 'stringio'
|
|
3
4
|
require 'set'
|
|
@@ -42,10 +43,14 @@ module ZSteg
|
|
|
42
43
|
|
|
43
44
|
opts.separator ""
|
|
44
45
|
|
|
45
|
-
opts.on "-a", "--all", "try all possible sizes
|
|
46
|
+
opts.on "-a", "--all", "try all possible sizes" do
|
|
46
47
|
@options[:try_all] = true
|
|
47
48
|
end
|
|
48
49
|
|
|
50
|
+
opts.on "-r", "--rewrite", "just rewrite the header, keeping imagedata as-is" do
|
|
51
|
+
@options[:rewrite] = true
|
|
52
|
+
end
|
|
53
|
+
|
|
49
54
|
opts.separator ""
|
|
50
55
|
|
|
51
56
|
opts.on "-O", "--outfile FILENAME", "output single result to specified file" do |x|
|
|
@@ -64,7 +69,11 @@ module ZSteg
|
|
|
64
69
|
@options[:verbose] -= 1
|
|
65
70
|
end
|
|
66
71
|
opts.on "-C", "--[no-]color", "Force (or disable) color output (default: auto)" do |x|
|
|
67
|
-
|
|
72
|
+
if defined?(Rainbow) && Rainbow.respond_to?(:enabled=)
|
|
73
|
+
Rainbow.enabled = x
|
|
74
|
+
else
|
|
75
|
+
Sickill::Rainbow.enabled = x
|
|
76
|
+
end
|
|
68
77
|
end
|
|
69
78
|
end
|
|
70
79
|
|
|
@@ -150,12 +159,21 @@ module ZSteg
|
|
|
150
159
|
h = @image.width*@image.height/w
|
|
151
160
|
_reflow w,h
|
|
152
161
|
end
|
|
153
|
-
|
|
162
|
+
elsif @options[:try_all]
|
|
154
163
|
# enum all
|
|
155
164
|
2.upto(@image.width*@image.height/2) do |w|
|
|
156
165
|
h = @image.width*@image.height/w
|
|
157
166
|
_reflow w,h
|
|
158
167
|
end
|
|
168
|
+
else
|
|
169
|
+
# smart all
|
|
170
|
+
w = 4
|
|
171
|
+
loop do
|
|
172
|
+
h = @image.width*@image.height/w
|
|
173
|
+
break if h < 4
|
|
174
|
+
_reflow w,h
|
|
175
|
+
w += 1
|
|
176
|
+
end
|
|
159
177
|
end
|
|
160
178
|
end
|
|
161
179
|
|
|
@@ -202,37 +220,41 @@ module ZSteg
|
|
|
202
220
|
data = fi.read(4+4+4)
|
|
203
221
|
fo.write(data[0,4] + [w,h].pack("V2")) # write new size
|
|
204
222
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
imagedata
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
223
|
+
if @options[:rewrite]
|
|
224
|
+
IO.copy_stream fi, fo
|
|
225
|
+
else
|
|
226
|
+
# copy remaining header bytes
|
|
227
|
+
fo.write fi.read(imagedata_offset-fi.tell)
|
|
228
|
+
|
|
229
|
+
# FIXME: if scanline sizes differ in BITS, not bytes...
|
|
230
|
+
|
|
231
|
+
# scanline padding needs to be respected...
|
|
232
|
+
imagedata = StringIO.new
|
|
233
|
+
@image.height.times do
|
|
234
|
+
data = fi.read @old_total_sl_bytes
|
|
235
|
+
imagedata << data[0, @old_significant_sl_bytes]
|
|
236
|
+
#p data[@old_significant_sl_bytes..-1]
|
|
237
|
+
end
|
|
238
|
+
imagedata << fi.read # read extradata, if any
|
|
239
|
+
|
|
240
|
+
imagedata.rewind
|
|
241
|
+
imagedata_start = fo.tell
|
|
242
|
+
h.times do
|
|
243
|
+
fo << imagedata.read(new_significant_sl_bytes)
|
|
244
|
+
fo << padding
|
|
245
|
+
end
|
|
246
|
+
file_size = fo.tell
|
|
247
|
+
imagedata_size = fo.tell - imagedata_start
|
|
248
|
+
fo << imagedata.read # write extradata, if any
|
|
249
|
+
|
|
250
|
+
# write new BITMAPFILEHEADER.bfSize
|
|
251
|
+
fo.seek 2
|
|
252
|
+
fo.write [file_size].pack('V')
|
|
253
|
+
|
|
254
|
+
# write new BITMAPINFOHEADER.biSizeImage
|
|
255
|
+
fo.seek 14+20 # BITMAPFILEHEADER::SIZE + 20
|
|
256
|
+
fo.write [imagedata_size].pack('V')
|
|
224
257
|
end
|
|
225
|
-
file_size = fo.tell
|
|
226
|
-
imagedata_size = fo.tell - imagedata_start
|
|
227
|
-
fo << imagedata.read # write extradata, if any
|
|
228
|
-
|
|
229
|
-
# write new BITMAPFILEHEADER.bfSize
|
|
230
|
-
fo.seek 2
|
|
231
|
-
fo.write [file_size].pack('V')
|
|
232
|
-
|
|
233
|
-
# write new BITMAPINFOHEADER.biSizeImage
|
|
234
|
-
fo.seek 14+20 # BITMAPFILEHEADER::SIZE + 20
|
|
235
|
-
fo.write [imagedata_size].pack('V')
|
|
236
258
|
end
|
|
237
259
|
end
|
|
238
260
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#coding: binary
|
|
1
2
|
module ZSteg
|
|
2
3
|
class Extractor
|
|
3
4
|
# ByteExtractor extracts bits from each scanline bytes
|
|
@@ -15,7 +16,7 @@ module ZSteg
|
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
data = ''.force_encoding('binary')
|
|
18
|
-
a = []
|
|
19
|
+
a = [0]*params[:shift].to_i # prepend :shift zero bits
|
|
19
20
|
byte_iterator(params) do |x,y|
|
|
20
21
|
sl = @image.scanlines[y]
|
|
21
22
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#coding: binary
|
|
1
2
|
module ZSteg
|
|
2
3
|
class Extractor
|
|
3
4
|
# ColorExtractor extracts bits from each pixel's color
|
|
@@ -35,8 +36,7 @@ module ZSteg
|
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
data = ''.force_encoding('binary')
|
|
38
|
-
a = []
|
|
39
|
-
#puts
|
|
39
|
+
a = [0]*params[:shift].to_i # prepend :shift zero bits
|
|
40
40
|
catch :limit do
|
|
41
41
|
coord_iterator(params) do |x,y|
|
|
42
42
|
color = @image[x,y]
|
data/lib/zsteg/file_cmd.rb
CHANGED
data/lib/zsteg/result.rb
CHANGED
data/spec/cats_spec.rb
CHANGED
data/spec/newbiecontest_spec.rb
CHANGED
|
@@ -5,7 +5,8 @@ sample("newbiecontest/alph1-surprise.bmp") do |fname|
|
|
|
5
5
|
describe fname do
|
|
6
6
|
subject{ cli(fname) }
|
|
7
7
|
|
|
8
|
-
it { should include "PE32 executable
|
|
8
|
+
it { should include "PE32 executable" }
|
|
9
|
+
it { should include "MS Windows" }
|
|
9
10
|
it { should include "is program canno" }
|
|
10
11
|
|
|
11
12
|
describe "--extract" do
|
data/spec/polictf2012_spec.rb
CHANGED
|
@@ -7,37 +7,51 @@ sample('polictf2012_f200.bmp') do |fname|
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
describe "hidden BMP #1" do
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
before(:all) do
|
|
11
|
+
@data = cli(fname, "--extract", "4b,lsb,bY")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should be 416816 bytes" do
|
|
15
|
+
@data.size.should == 416816
|
|
16
|
+
end
|
|
12
17
|
|
|
13
18
|
it "should have BMP header" do
|
|
14
|
-
data[0,2].should == "BM"
|
|
19
|
+
@data[0,2].should == "BM"
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
it "should have 7zip after BMP" do
|
|
18
|
-
data.index("7z").should == 2005
|
|
23
|
+
@data.index("7z").should == 2005
|
|
19
24
|
end
|
|
20
25
|
|
|
21
26
|
describe "deeper" do
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
before(:all) do
|
|
28
|
+
@tname = File.join("tmp", File.basename(fname) + ".bmp")
|
|
29
|
+
File.open(@tname, "wb"){ |f| f<<@data }
|
|
30
|
+
end
|
|
24
31
|
|
|
25
32
|
it "should detect 7z & BMP" do
|
|
26
|
-
out = cli(tname)
|
|
33
|
+
out = cli(@tname)
|
|
27
34
|
out.should include('7-zip archive')
|
|
28
35
|
out.should include('PC bitmap, Windows 3.x format, 100 x 55 x 24')
|
|
29
36
|
end
|
|
30
37
|
|
|
31
38
|
describe "hidden BMP #2" do
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
before(:all) do
|
|
40
|
+
@data2 = cli(@tname, "--extract", "2b,lsb,bY")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should be 103875 bytes" do
|
|
44
|
+
@data2.size.should == 103875
|
|
45
|
+
end
|
|
34
46
|
|
|
35
47
|
describe "deeper" do
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
before(:all) do
|
|
49
|
+
@tname2 = File.join("tmp", File.basename(@tname) + ".bmp")
|
|
50
|
+
File.open(@tname2, "wb"){ |f| f<<@data2 }
|
|
51
|
+
end
|
|
38
52
|
|
|
39
53
|
it "should detect text" do
|
|
40
|
-
out = cli(tname2)
|
|
54
|
+
out = cli(@tname2)
|
|
41
55
|
out.should include('sticazziantanieancoraunavoltacomesefossestato')
|
|
42
56
|
end
|
|
43
57
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#coding: binary
|
|
1
2
|
$:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
|
|
2
3
|
require 'zsteg'
|
|
3
4
|
|
|
@@ -19,7 +20,7 @@ def sample fname
|
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
def cli *args
|
|
22
|
-
|
|
23
|
+
@cli_cache ||= {}
|
|
23
24
|
args.map! do |arg|
|
|
24
25
|
if arg.is_a?(String) && arg[' ']
|
|
25
26
|
# split strings with spaces into arrays
|
|
@@ -29,7 +30,7 @@ def cli *args
|
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
args.flatten!
|
|
32
|
-
|
|
33
|
+
@cli_cache[args.inspect] ||=
|
|
33
34
|
begin
|
|
34
35
|
klass =
|
|
35
36
|
if args.first.is_a?(Symbol)
|
|
@@ -52,6 +53,7 @@ def cli *args
|
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
RSpec.configure do |config|
|
|
56
|
+
config.expect_with(:rspec) { |c| c.syntax = :should }
|
|
55
57
|
config.before :suite do
|
|
56
58
|
Dir[File.join(SAMPLES_DIR, "**", "*.7z")].each do |fname|
|
|
57
59
|
next if File.exist?(fname.sub(/\.7z$/,''))
|
data/spec/zlib_spec.rb
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
sample("ndh2k12_sp113.bmp") do |fname|
|
|
4
|
+
describe fname do
|
|
5
|
+
subject{ cli(fname, "-o", "all") }
|
|
6
|
+
it { should include("%PDF-1.4") }
|
|
7
|
+
|
|
8
|
+
describe "--extract" do
|
|
9
|
+
subject{ cli(fname, "--extract b1,rgb,lsb,yx") }
|
|
10
|
+
|
|
11
|
+
it { should_not include "%PDF-1.4" }
|
|
12
|
+
it { subject.size.should == 546750 }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "--extract zlib" do
|
|
16
|
+
subject{ cli(fname, "--extract b1,rgb,lsb,yx,zlib") }
|
|
17
|
+
|
|
18
|
+
it { should include "%PDF-1.4" }
|
|
19
|
+
it { subject.size.should == 202383 }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
6
22
|
end
|
data/zsteg.gemspec
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: zsteg 0.
|
|
5
|
+
# stub: zsteg 0.2.3 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
|
-
s.name = "zsteg"
|
|
9
|
-
s.version = "0.
|
|
8
|
+
s.name = "zsteg".freeze
|
|
9
|
+
s.version = "0.2.3"
|
|
10
10
|
|
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
12
|
-
s.
|
|
13
|
-
s.
|
|
14
|
-
s.
|
|
15
|
-
s.
|
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
|
+
s.require_paths = ["lib".freeze]
|
|
13
|
+
s.authors = ["Andrey \"Zed\" Zaikin".freeze]
|
|
14
|
+
s.date = "2021-02-18"
|
|
15
|
+
s.email = "zed.0xff@gmail.com".freeze
|
|
16
|
+
s.executables = ["zsteg".freeze, "zsteg-mask".freeze, "zsteg-reflow".freeze]
|
|
16
17
|
s.extra_rdoc_files = [
|
|
17
18
|
"README.md",
|
|
18
19
|
"README.md.tpl",
|
|
@@ -100,34 +101,27 @@ Gem::Specification.new do |s|
|
|
|
100
101
|
"writers/zlib_append.rb",
|
|
101
102
|
"zsteg.gemspec"
|
|
102
103
|
]
|
|
103
|
-
s.homepage = "http://github.com/zed-0xff/zsteg"
|
|
104
|
-
s.licenses = ["MIT"]
|
|
105
|
-
s.
|
|
106
|
-
s.
|
|
107
|
-
s.summary = "Detect stegano-hidden data in PNG & BMP files."
|
|
104
|
+
s.homepage = "http://github.com/zed-0xff/zsteg".freeze
|
|
105
|
+
s.licenses = ["MIT".freeze]
|
|
106
|
+
s.rubygems_version = "3.2.3".freeze
|
|
107
|
+
s.summary = "Detect stegano-hidden data in PNG & BMP files.".freeze
|
|
108
108
|
|
|
109
109
|
if s.respond_to? :specification_version then
|
|
110
110
|
s.specification_version = 4
|
|
111
|
+
end
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
else
|
|
119
|
-
s.add_dependency(%q<zpng>, [">= 0.2.3"])
|
|
120
|
-
s.add_dependency(%q<iostruct>, [">= 0"])
|
|
121
|
-
s.add_dependency(%q<rspec>, [">= 2.8.0"])
|
|
122
|
-
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
|
123
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
|
124
|
-
end
|
|
113
|
+
if s.respond_to? :add_runtime_dependency then
|
|
114
|
+
s.add_runtime_dependency(%q<zpng>.freeze, [">= 0.3.1"])
|
|
115
|
+
s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0"])
|
|
116
|
+
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.9.0"])
|
|
117
|
+
s.add_development_dependency(%q<bundler>.freeze, ["~> 2.2.3"])
|
|
118
|
+
s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
|
125
119
|
else
|
|
126
|
-
s.add_dependency(%q<zpng
|
|
127
|
-
s.add_dependency(%q<iostruct
|
|
128
|
-
s.add_dependency(%q<rspec
|
|
129
|
-
s.add_dependency(%q<bundler
|
|
130
|
-
s.add_dependency(%q<jeweler
|
|
120
|
+
s.add_dependency(%q<zpng>.freeze, [">= 0.3.1"])
|
|
121
|
+
s.add_dependency(%q<iostruct>.freeze, [">= 0"])
|
|
122
|
+
s.add_dependency(%q<rspec>.freeze, ["~> 3.9.0"])
|
|
123
|
+
s.add_dependency(%q<bundler>.freeze, ["~> 2.2.3"])
|
|
124
|
+
s.add_dependency(%q<jeweler>.freeze, ["~> 2.3.9"])
|
|
131
125
|
end
|
|
132
126
|
end
|
|
133
127
|
|
metadata
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zsteg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrey "Zed" Zaikin
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: zpng
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.3.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.3.1
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: iostruct
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- -
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '0'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- -
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rspec
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- -
|
|
45
|
+
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version:
|
|
47
|
+
version: 3.9.0
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- -
|
|
52
|
+
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version:
|
|
54
|
+
version: 3.9.0
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: bundler
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- -
|
|
59
|
+
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
61
|
+
version: 2.2.3
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- -
|
|
66
|
+
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
68
|
+
version: 2.2.3
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: jeweler
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- - ~>
|
|
73
|
+
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
75
|
+
version: 2.3.9
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- - ~>
|
|
80
|
+
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
83
|
-
description:
|
|
82
|
+
version: 2.3.9
|
|
83
|
+
description:
|
|
84
84
|
email: zed.0xff@gmail.com
|
|
85
85
|
executables:
|
|
86
86
|
- zsteg
|
|
@@ -176,24 +176,23 @@ homepage: http://github.com/zed-0xff/zsteg
|
|
|
176
176
|
licenses:
|
|
177
177
|
- MIT
|
|
178
178
|
metadata: {}
|
|
179
|
-
post_install_message:
|
|
179
|
+
post_install_message:
|
|
180
180
|
rdoc_options: []
|
|
181
181
|
require_paths:
|
|
182
182
|
- lib
|
|
183
183
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
184
|
requirements:
|
|
185
|
-
- -
|
|
185
|
+
- - ">="
|
|
186
186
|
- !ruby/object:Gem::Version
|
|
187
187
|
version: '0'
|
|
188
188
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
189
|
requirements:
|
|
190
|
-
- -
|
|
190
|
+
- - ">="
|
|
191
191
|
- !ruby/object:Gem::Version
|
|
192
192
|
version: '0'
|
|
193
193
|
requirements: []
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
signing_key:
|
|
194
|
+
rubygems_version: 3.2.3
|
|
195
|
+
signing_key:
|
|
197
196
|
specification_version: 4
|
|
198
197
|
summary: Detect stegano-hidden data in PNG & BMP files.
|
|
199
198
|
test_files: []
|