zsteg 0.2.12 → 0.2.14
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 +4 -4
- data/Gemfile +2 -2
- data/Gemfile.lock +88 -44
- data/README.md +14 -25
- data/TODO +2 -0
- data/VERSION +1 -1
- data/cmp_png.rb +1 -1
- data/lib/zsteg/checker/steganography_png.rb +36 -0
- data/lib/zsteg/checker/wbstego.rb +1 -2
- data/lib/zsteg/checker/zlib.rb +1 -0
- data/lib/zsteg/checker.rb +76 -32
- data/lib/zsteg/cli/cli.rb +57 -33
- data/lib/zsteg/extractor/byte_extractor.rb +5 -2
- data/lib/zsteg/extractor/color_extractor.rb +5 -5
- data/lib/zsteg/result.rb +4 -3
- data/lib/zsteg.rb +0 -4
- data/spec/checker_spec.rb +3 -3
- data/spec/plte_spec.rb +17 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/steganography_png_spec.rb +13 -0
- data/zsteg.gemspec +11 -8
- metadata +10 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 517af804bb6892894d053fe80139d31ca23746c02c42f33dd5574bf25e41f8c2
|
|
4
|
+
data.tar.gz: 399a3f35dc307eb44d1b3e4cb776e32887428d25f311b42a8facb33ecb8ba7f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cf416358da42bab09505d7f54d3e5df0b9e26cc4b29e3b6e0aa73bb13900c7367d5e941298917bb6286a6e8b5f430eca36547a4f66efd4d06b3c2a8316b17ffd
|
|
7
|
+
data.tar.gz: 49f2ac63384acc20790882c5542375b655c4462a6099d0ba999fe300ca91766c9d65ec08f2288f9e628c6c11b552f91490ae24be55c6ffbd96b0c94998a64002
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
remote: http://rubygems.org/
|
|
3
3
|
specs:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
activesupport (7.1.6)
|
|
5
|
+
base64
|
|
6
|
+
benchmark (>= 0.3)
|
|
7
|
+
bigdecimal
|
|
8
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
9
|
+
connection_pool (>= 2.2.5)
|
|
10
|
+
drb
|
|
11
|
+
i18n (>= 1.6, < 2)
|
|
12
|
+
logger (>= 1.4.2)
|
|
13
|
+
minitest (>= 5.1)
|
|
14
|
+
mutex_m
|
|
15
|
+
securerandom (>= 0.3)
|
|
16
|
+
tzinfo (~> 2.0)
|
|
17
|
+
addressable (2.8.8)
|
|
18
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
19
|
+
base64 (0.3.0)
|
|
20
|
+
benchmark (0.5.0)
|
|
21
|
+
bigdecimal (4.0.1)
|
|
22
|
+
builder (3.3.0)
|
|
23
|
+
cgi (0.5.1)
|
|
24
|
+
concurrent-ruby (1.3.6)
|
|
25
|
+
connection_pool (2.5.5)
|
|
26
|
+
date (3.5.1)
|
|
7
27
|
descendants_tracker (0.0.4)
|
|
8
28
|
thread_safe (~> 0.3, >= 0.3.1)
|
|
9
|
-
diff-lcs (1.
|
|
10
|
-
|
|
29
|
+
diff-lcs (1.6.2)
|
|
30
|
+
drb (2.2.3)
|
|
31
|
+
erb (4.0.4)
|
|
32
|
+
cgi (>= 0.3.3)
|
|
33
|
+
faraday (1.10.4)
|
|
11
34
|
faraday-em_http (~> 1.0)
|
|
12
35
|
faraday-em_synchrony (~> 1.0)
|
|
13
36
|
faraday-excon (~> 1.1)
|
|
@@ -20,19 +43,21 @@ GEM
|
|
|
20
43
|
faraday-retry (~> 1.0)
|
|
21
44
|
ruby2_keywords (>= 0.0.4)
|
|
22
45
|
faraday-em_http (1.0.0)
|
|
23
|
-
faraday-em_synchrony (1.0.
|
|
46
|
+
faraday-em_synchrony (1.0.1)
|
|
24
47
|
faraday-excon (1.1.0)
|
|
25
48
|
faraday-httpclient (1.0.1)
|
|
26
|
-
faraday-multipart (1.0
|
|
27
|
-
multipart-post (~> 2)
|
|
28
|
-
faraday-net_http (1.0.
|
|
49
|
+
faraday-multipart (1.2.0)
|
|
50
|
+
multipart-post (~> 2.0)
|
|
51
|
+
faraday-net_http (1.0.2)
|
|
29
52
|
faraday-net_http_persistent (1.2.0)
|
|
30
53
|
faraday-patron (1.0.0)
|
|
31
54
|
faraday-rack (1.0.0)
|
|
32
55
|
faraday-retry (1.0.3)
|
|
33
|
-
forwardable (1.
|
|
34
|
-
git (
|
|
56
|
+
forwardable (1.4.0)
|
|
57
|
+
git (2.3.3)
|
|
58
|
+
activesupport (>= 5.0)
|
|
35
59
|
addressable (~> 2.8)
|
|
60
|
+
process_executer (~> 1.1)
|
|
36
61
|
rchardet (~> 1.8)
|
|
37
62
|
github_api (0.19.0)
|
|
38
63
|
addressable (~> 2.4)
|
|
@@ -41,8 +66,12 @@ GEM
|
|
|
41
66
|
hashie (~> 3.5, >= 3.5.2)
|
|
42
67
|
oauth2 (~> 1.0)
|
|
43
68
|
hashie (3.6.0)
|
|
44
|
-
highline (
|
|
45
|
-
|
|
69
|
+
highline (3.1.2)
|
|
70
|
+
reline
|
|
71
|
+
i18n (1.14.8)
|
|
72
|
+
concurrent-ruby (~> 1.0)
|
|
73
|
+
io-console (0.8.2)
|
|
74
|
+
iostruct (0.7.0)
|
|
46
75
|
juwelier (2.4.9)
|
|
47
76
|
builder
|
|
48
77
|
bundler
|
|
@@ -55,15 +84,19 @@ GEM
|
|
|
55
84
|
rake
|
|
56
85
|
rdoc
|
|
57
86
|
semver2
|
|
58
|
-
jwt (2.
|
|
87
|
+
jwt (2.10.2)
|
|
88
|
+
base64
|
|
59
89
|
kamelcase (0.0.2)
|
|
60
90
|
semver2 (~> 3)
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
logger (1.7.0)
|
|
92
|
+
mini_portile2 (2.8.9)
|
|
93
|
+
minitest (5.26.1)
|
|
94
|
+
multi_json (1.19.1)
|
|
63
95
|
multi_xml (0.6.0)
|
|
64
|
-
multipart-post (2.
|
|
65
|
-
|
|
66
|
-
|
|
96
|
+
multipart-post (2.4.1)
|
|
97
|
+
mutex_m (0.3.0)
|
|
98
|
+
nokogiri (1.17.2)
|
|
99
|
+
mini_portile2 (~> 2.8.2)
|
|
67
100
|
racc (~> 1.4)
|
|
68
101
|
oauth2 (1.4.11)
|
|
69
102
|
faraday (>= 0.17.3, < 3.0)
|
|
@@ -71,49 +104,60 @@ GEM
|
|
|
71
104
|
multi_json (~> 1.3)
|
|
72
105
|
multi_xml (~> 0.5)
|
|
73
106
|
rack (>= 1.2, < 4)
|
|
74
|
-
prime (0.1.
|
|
107
|
+
prime (0.1.4)
|
|
75
108
|
forwardable
|
|
76
109
|
singleton
|
|
77
|
-
|
|
110
|
+
process_executer (1.1.2)
|
|
111
|
+
psych (5.3.1)
|
|
112
|
+
date
|
|
78
113
|
stringio
|
|
79
|
-
public_suffix (
|
|
80
|
-
racc (1.
|
|
81
|
-
rack (3.
|
|
114
|
+
public_suffix (6.0.2)
|
|
115
|
+
racc (1.8.1)
|
|
116
|
+
rack (3.2.4)
|
|
82
117
|
rainbow (3.1.1)
|
|
83
|
-
rake (13.
|
|
84
|
-
rchardet (1.
|
|
85
|
-
rdoc (
|
|
118
|
+
rake (13.3.1)
|
|
119
|
+
rchardet (1.10.0)
|
|
120
|
+
rdoc (7.1.0)
|
|
121
|
+
erb
|
|
86
122
|
psych (>= 4.0.0)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
rspec-
|
|
93
|
-
|
|
123
|
+
tsort
|
|
124
|
+
reline (0.6.3)
|
|
125
|
+
io-console (~> 0.5)
|
|
126
|
+
rspec (3.13.2)
|
|
127
|
+
rspec-core (~> 3.13.0)
|
|
128
|
+
rspec-expectations (~> 3.13.0)
|
|
129
|
+
rspec-mocks (~> 3.13.0)
|
|
130
|
+
rspec-core (3.13.6)
|
|
131
|
+
rspec-support (~> 3.13.0)
|
|
132
|
+
rspec-expectations (3.13.5)
|
|
94
133
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
95
|
-
rspec-support (~> 3.
|
|
96
|
-
rspec-mocks (3.
|
|
134
|
+
rspec-support (~> 3.13.0)
|
|
135
|
+
rspec-mocks (3.13.7)
|
|
97
136
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
98
|
-
rspec-support (~> 3.
|
|
99
|
-
rspec-support (3.
|
|
137
|
+
rspec-support (~> 3.13.0)
|
|
138
|
+
rspec-support (3.13.6)
|
|
100
139
|
ruby2_keywords (0.0.5)
|
|
140
|
+
securerandom (0.3.2)
|
|
101
141
|
semver2 (3.4.2)
|
|
102
|
-
singleton (0.
|
|
103
|
-
stringio (3.0
|
|
142
|
+
singleton (0.3.0)
|
|
143
|
+
stringio (3.2.0)
|
|
104
144
|
thread_safe (0.3.6)
|
|
105
|
-
|
|
145
|
+
tsort (0.2.0)
|
|
146
|
+
tzinfo (2.0.6)
|
|
147
|
+
concurrent-ruby (~> 1.0)
|
|
148
|
+
zpng (0.4.6)
|
|
149
|
+
iostruct (>= 0.7.0)
|
|
106
150
|
rainbow (~> 3.1.1)
|
|
107
151
|
|
|
108
152
|
PLATFORMS
|
|
109
153
|
ruby
|
|
110
154
|
|
|
111
155
|
DEPENDENCIES
|
|
112
|
-
iostruct
|
|
156
|
+
iostruct (>= 0.7.0)
|
|
113
157
|
juwelier
|
|
114
158
|
prime
|
|
115
159
|
rspec
|
|
116
|
-
zpng (>= 0.4.
|
|
160
|
+
zpng (>= 0.4.6)
|
|
117
161
|
|
|
118
162
|
BUNDLED WITH
|
|
119
|
-
2.
|
|
163
|
+
2.4.22
|
data/README.md
CHANGED
|
@@ -28,26 +28,32 @@ Usage
|
|
|
28
28
|
|
|
29
29
|
Usage: zsteg [options] filename.png [param_string]
|
|
30
30
|
|
|
31
|
+
-a, --all try all known methods
|
|
32
|
+
-E, --extract NAME extract specified payload, NAME is like '1b,rgb,lsb'
|
|
33
|
+
|
|
34
|
+
Iteration/extraction params:
|
|
35
|
+
-o, --order X pixel iteration order (default: 'auto')
|
|
36
|
+
valid values: ALL,xy,yx,XY,YX,xY,Xy,bY,...
|
|
31
37
|
-c, --channels X channels (R/G/B/A) or any combination, comma separated
|
|
32
38
|
valid values: r,g,b,a,rg,bgr,rgba,r3g2b3,...
|
|
33
|
-
-l, --limit N limit bytes checked, 0 = no limit (default: 256)
|
|
34
39
|
-b, --bits N number of bits, single int value or '1,3,5' or range '1-8'
|
|
35
40
|
advanced: specify individual bits like '00001110' or '0x88'
|
|
36
|
-
--lsb least significant
|
|
37
|
-
--msb most significant
|
|
41
|
+
--lsb least significant bit comes first
|
|
42
|
+
--msb most significant bit comes first
|
|
38
43
|
-P, --prime analyze/extract only prime bytes/pixels
|
|
44
|
+
--shift N prepend N zero bits
|
|
45
|
+
--step N step
|
|
39
46
|
--invert invert bits (XOR 0xff)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
-
|
|
47
|
+
--pixel-align pixel-align hidden data
|
|
48
|
+
|
|
49
|
+
Analysis params:
|
|
50
|
+
-l, --limit N limit bytes checked, 0 = no limit (default: 256)
|
|
44
51
|
|
|
45
52
|
--[no-]file use 'file' command to detect data type (default: YES)
|
|
46
53
|
--no-strings disable ASCII strings finding (default: enabled)
|
|
47
54
|
-s, --strings X ASCII strings find mode: first, all, longest, none
|
|
48
55
|
(default: first)
|
|
49
56
|
-n, --min-str-len X minimum string length (default: 8)
|
|
50
|
-
--shift N prepend N zero bits
|
|
51
57
|
|
|
52
58
|
-v, --verbose Run verbosely (can be used multiple times)
|
|
53
59
|
-q, --quiet Silent any warnings (can be used multiple times)
|
|
@@ -85,23 +91,6 @@ Examples
|
|
|
85
91
|
|
|
86
92
|
# zsteg wbstego/wbsteg_noenc_even.bmp 1b,lsb,bY -v
|
|
87
93
|
|
|
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
94
|
b1,lsb,bY .. <wbStego size=22, data="xtSuperSecretMessage\n", even=true, mix=true, controlbyte="t">
|
|
106
95
|
00000000: 51 00 00 16 00 00 74 0d b5 78 1e a1 39 74 e8 38 |Q.....t..x..9t.8|
|
|
107
96
|
00000010: 53 c6 56 94 75 d1 a5 70 84 c8 27 65 fe 08 72 35 |S.V.u..p..'e..r5|
|
data/TODO
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.14
|
data/cmp_png.rb
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# coding: binary
|
|
2
|
+
module ZSteg
|
|
3
|
+
class Checker
|
|
4
|
+
module SteganographyPNG
|
|
5
|
+
|
|
6
|
+
URL = "https://github.com/pedrooaugusto/steganography-png"
|
|
7
|
+
|
|
8
|
+
# https://github.com/pedrooaugusto/steganography-png/blob/2a0e038c135e41438b4c2c93821227a2289b4203/scanlines/scanlines.go#L234
|
|
9
|
+
#
|
|
10
|
+
# The secret metadata is stored in the last bytes of the last scanline in the form of:
|
|
11
|
+
# 17 107 [bitloss] [secret size - 4 bytes] [secret type] [secret type length]
|
|
12
|
+
# 17 107 1 4096 "text/plain" 10
|
|
13
|
+
|
|
14
|
+
class Result < IOStruct.new("nCNa*", :magic, :bitloss, :secret_size, :secret_type, struct_name: 'SteganographyPNG')
|
|
15
|
+
def valid?
|
|
16
|
+
magic == 0x116b && (1..8).include?(bitloss)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
super.sub(/>$/,'').bright_red
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.check_image image, _params = {}
|
|
25
|
+
ls = image.scanlines.last
|
|
26
|
+
data = ls.decoded_bytes
|
|
27
|
+
secret_type_length = data[-1].ord
|
|
28
|
+
return nil if secret_type_length > data.size - 8
|
|
29
|
+
data = data[ -secret_type_length-8 .. -2 ]
|
|
30
|
+
# data.size to prevent "want 8 bytes, got 7" IOStruct warning when secret_type_length == 0
|
|
31
|
+
r = Result.read(data, data.size)
|
|
32
|
+
r.valid? && [r, URL]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -11,7 +11,7 @@ module ZSteg
|
|
|
11
11
|
"Rijndael", # 4
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
-
class Result < IOStruct.new
|
|
14
|
+
class Result < IOStruct.new("a3a3a*", :size, :ext, :data, :even, :hdr, :enc, :mix, :controlbyte, struct_name: 'wbStego')
|
|
15
15
|
attr_accessor :color
|
|
16
16
|
|
|
17
17
|
def initialize *args
|
|
@@ -39,7 +39,6 @@ module ZSteg
|
|
|
39
39
|
|
|
40
40
|
def to_s
|
|
41
41
|
s = inspect.
|
|
42
|
-
sub("#<struct #{self.class.to_s}", "<wbStego").
|
|
43
42
|
gsub(/, \w+=nil/,'')
|
|
44
43
|
|
|
45
44
|
color = @color
|
data/lib/zsteg/checker/zlib.rb
CHANGED
|
@@ -21,6 +21,7 @@ module ZSteg
|
|
|
21
21
|
# http://blog.w3challs.com/index.php?post/2012/03/25/NDH2k12-Prequals-We-are-looking-for-a-real-hacker-Wallpaper-image
|
|
22
22
|
# http://blog.w3challs.com/public/ndh2k12_prequalls/sp113.bmp
|
|
23
23
|
def self.check_data data
|
|
24
|
+
data = data.force_encoding('ASCII-8BIT')
|
|
24
25
|
return unless idx = data.index(/\x78[\x9c\xda\x01]/n)
|
|
25
26
|
|
|
26
27
|
zi = ::Zlib::Inflate.new
|
data/lib/zsteg/checker.rb
CHANGED
|
@@ -3,6 +3,11 @@ require 'stringio'
|
|
|
3
3
|
require 'zlib'
|
|
4
4
|
require 'set'
|
|
5
5
|
|
|
6
|
+
require 'zsteg/checker/scanline_checker'
|
|
7
|
+
require 'zsteg/checker/steganography_png'
|
|
8
|
+
require 'zsteg/checker/wbstego'
|
|
9
|
+
require 'zsteg/checker/zlib'
|
|
10
|
+
|
|
6
11
|
module ZSteg
|
|
7
12
|
class Checker
|
|
8
13
|
attr_accessor :params, :channels, :verbose, :results
|
|
@@ -46,20 +51,20 @@ module ZSteg
|
|
|
46
51
|
|
|
47
52
|
private
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
def print *args
|
|
51
|
-
Kernel.print(*args) if @verbose >= 0
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# catch Kernel#printf for easier verbosity handling
|
|
55
|
-
def printf *args
|
|
56
|
-
Kernel.printf(*args) if @verbose >= 0
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# catch Kernel#puts for easier verbosity handling
|
|
60
|
-
def puts *args
|
|
61
|
-
Kernel.puts(*args) if @verbose >= 0
|
|
62
|
-
end
|
|
54
|
+
# # catch Kernel#print for easier verbosity handling
|
|
55
|
+
# def print *args
|
|
56
|
+
# Kernel.print(*args) if @verbose >= 0
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# # catch Kernel#printf for easier verbosity handling
|
|
60
|
+
# def printf *args
|
|
61
|
+
# Kernel.printf(*args) if @verbose >= 0
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# # catch Kernel#puts for easier verbosity handling
|
|
65
|
+
# def puts *args
|
|
66
|
+
# Kernel.puts(*args) if @verbose >= 0
|
|
67
|
+
# end
|
|
63
68
|
|
|
64
69
|
public
|
|
65
70
|
|
|
@@ -71,6 +76,7 @@ module ZSteg
|
|
|
71
76
|
check_extradata
|
|
72
77
|
check_metadata
|
|
73
78
|
check_imagedata
|
|
79
|
+
check_chunks
|
|
74
80
|
end
|
|
75
81
|
|
|
76
82
|
if @image.format == :bmp
|
|
@@ -92,12 +98,26 @@ module ZSteg
|
|
|
92
98
|
Array(params[:order]).uniq.each do |order|
|
|
93
99
|
(params[:prime] == :all ? [false,true] : [params[:prime]]).each do |prime|
|
|
94
100
|
Array(params[:bits]).uniq.each do |bits|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
if params[:pixel_align] == :all
|
|
102
|
+
[false, true].each do |pixel_align|
|
|
103
|
+
# skip cases when output will be identical for pixel_align true/false
|
|
104
|
+
next if pixel_align && (8%bits) == 0
|
|
105
|
+
p1 = @params.merge bits: bits, order: order, prime: prime, pixel_align: pixel_align
|
|
106
|
+
if order[/b/i]
|
|
107
|
+
# byte iterator does not need channels
|
|
108
|
+
check_channels nil, p1
|
|
109
|
+
else
|
|
110
|
+
channels.each{ |c| check_channels c, p1 }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
99
113
|
else
|
|
100
|
-
|
|
114
|
+
p1 = @params.merge bits: bits, order: order, prime: prime
|
|
115
|
+
if order[/b/i]
|
|
116
|
+
# byte iterator does not need channels
|
|
117
|
+
check_channels nil, p1
|
|
118
|
+
else
|
|
119
|
+
channels.each{ |c| check_channels c, p1 }
|
|
120
|
+
end
|
|
101
121
|
end
|
|
102
122
|
end
|
|
103
123
|
end
|
|
@@ -124,6 +144,16 @@ module ZSteg
|
|
|
124
144
|
process_result @image.imagedata, h
|
|
125
145
|
end
|
|
126
146
|
|
|
147
|
+
def check_chunks
|
|
148
|
+
@image.chunks.each_with_index do |chunk, idx|
|
|
149
|
+
next unless chunk.respond_to?(:size) && chunk.respond_to?(:data)
|
|
150
|
+
next unless chunk.size && chunk.data
|
|
151
|
+
next if chunk.size < 5 || chunk.is_a?(ZPNG::TextChunk) || chunk.is_a?(ZPNG::Chunk::IDAT)
|
|
152
|
+
h = { :title => "chunk:#{idx}:#{chunk.type}", :show_title => true }
|
|
153
|
+
process_result chunk.data, h
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
127
157
|
def check_extradata
|
|
128
158
|
# accessing imagedata implicitly unpacks zlib stream
|
|
129
159
|
# zlib stream may contain extradata
|
|
@@ -150,6 +180,13 @@ module ZSteg
|
|
|
150
180
|
show_title title, :bright_red
|
|
151
181
|
process_result data, :special => true, :title => title
|
|
152
182
|
end
|
|
183
|
+
|
|
184
|
+
if r = SteganographyPNG.check_image(@image, @params)
|
|
185
|
+
@found_anything = true
|
|
186
|
+
title = "image"
|
|
187
|
+
show_title title, :bright_red
|
|
188
|
+
process_result nil, title: title, result: r
|
|
189
|
+
end
|
|
153
190
|
end
|
|
154
191
|
|
|
155
192
|
def check_metadata
|
|
@@ -220,6 +257,8 @@ module ZSteg
|
|
|
220
257
|
end
|
|
221
258
|
end
|
|
222
259
|
|
|
260
|
+
bits_tag << "p" if params[:pixel_align]
|
|
261
|
+
|
|
223
262
|
title = [
|
|
224
263
|
bits_tag,
|
|
225
264
|
channels,
|
|
@@ -268,21 +307,26 @@ module ZSteg
|
|
|
268
307
|
def process_result data, params
|
|
269
308
|
verbose = params[:special] ? [@verbose,1.5].max : @verbose
|
|
270
309
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
310
|
+
result = nil
|
|
311
|
+
if data
|
|
312
|
+
if @cache[data]
|
|
313
|
+
if verbose > 1
|
|
314
|
+
puts "[same as #{@cache[data].inspect}]".gray
|
|
315
|
+
return true
|
|
316
|
+
else
|
|
317
|
+
# silent return
|
|
318
|
+
return false
|
|
319
|
+
end
|
|
278
320
|
end
|
|
279
|
-
end
|
|
280
321
|
|
|
281
|
-
|
|
282
|
-
|
|
322
|
+
# TODO: store hash of data for large datas
|
|
323
|
+
@cache[data] = params[:title]
|
|
283
324
|
|
|
284
|
-
|
|
285
|
-
|
|
325
|
+
if result = data2result(data, params)
|
|
326
|
+
@results << result
|
|
327
|
+
end
|
|
328
|
+
elsif !(result = params[:result])
|
|
329
|
+
raise "[?] No data nor result"
|
|
286
330
|
end
|
|
287
331
|
|
|
288
332
|
case verbose
|
|
@@ -309,7 +353,7 @@ module ZSteg
|
|
|
309
353
|
else
|
|
310
354
|
show_result result, params
|
|
311
355
|
end
|
|
312
|
-
if data.size > 0 && !result.is_a?(Result::OneChar) && !result.is_a?(Result::WholeText)
|
|
356
|
+
if data && data.size > 0 && !result.is_a?(Result::OneChar) && !result.is_a?(Result::WholeText)
|
|
313
357
|
# newline if no results and want hexdump
|
|
314
358
|
puts if !result || result == []
|
|
315
359
|
limit = (params[:limit] || @params[:limit]).to_i
|
data/lib/zsteg/cli/cli.rb
CHANGED
|
@@ -11,14 +11,39 @@ module ZSteg
|
|
|
11
11
|
def run
|
|
12
12
|
@actions = []
|
|
13
13
|
@options = {
|
|
14
|
-
:
|
|
15
|
-
:
|
|
16
|
-
:
|
|
14
|
+
verbose: 0,
|
|
15
|
+
limit: Checker::DEFAULT_LIMIT,
|
|
16
|
+
order: Checker::DEFAULT_ORDER,
|
|
17
|
+
step: 1,
|
|
18
|
+
ystep: 1,
|
|
17
19
|
}
|
|
18
20
|
optparser = OptionParser.new do |opts|
|
|
19
21
|
opts.banner = "Usage: zsteg [options] filename.png [param_string]"
|
|
20
22
|
opts.separator ""
|
|
21
23
|
|
|
24
|
+
opts.on "-a", "--all", "try all known methods" do
|
|
25
|
+
@options[:prime] = :all
|
|
26
|
+
@options[:order] = :all
|
|
27
|
+
@options[:pixel_align] = :all
|
|
28
|
+
@options[:bits] = (1..8).to_a
|
|
29
|
+
# specifying --all on command line explicitly enables extra checks
|
|
30
|
+
@options[:extra_checks] = true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
opts.on "-E", "--extract NAME", "extract specified payload, NAME is like '1b,rgb,lsb'" do |x|
|
|
34
|
+
@options[:verbose] = -2 # silent ZPNG warnings
|
|
35
|
+
@actions << [:extract, x]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#################################################################################
|
|
39
|
+
opts.separator "\nIteration/extraction params:"
|
|
40
|
+
#################################################################################
|
|
41
|
+
|
|
42
|
+
opts.on("-o", "--order X", /all|auto|[bxy,]+/i,
|
|
43
|
+
"pixel iteration order (default: '#{@options[:order]}')",
|
|
44
|
+
"valid values: ALL,xy,yx,XY,YX,xY,Xy,bY,...",
|
|
45
|
+
){ |x| @options[:order] = x.split(',') }
|
|
46
|
+
|
|
22
47
|
opts.on("-c", "--channels X", /[rgba,1-8]+/,
|
|
23
48
|
"channels (R/G/B/A) or any combination, comma separated",
|
|
24
49
|
"valid values: r,g,b,a,rg,bgr,rgba,r3g2b3,..."
|
|
@@ -28,14 +53,14 @@ module ZSteg
|
|
|
28
53
|
@options[:extra_checks] = false
|
|
29
54
|
end
|
|
30
55
|
|
|
31
|
-
opts.on("-l", "--limit N", Integer,
|
|
32
|
-
"limit bytes checked, 0 = no limit (default: #{@options[:limit]})"
|
|
33
|
-
){ |n| @options[:limit] = n }
|
|
34
|
-
|
|
35
56
|
opts.on("-b", "--bits N", "number of bits, single int value or '1,3,5' or range '1-8'",
|
|
36
57
|
"advanced: specify individual bits like '00001110' or '0x88'"
|
|
37
58
|
) do |x|
|
|
38
59
|
a = []
|
|
60
|
+
if x[-1] == 'p'
|
|
61
|
+
@options[:pixel_align] = true
|
|
62
|
+
x = x[0..-2]
|
|
63
|
+
end
|
|
39
64
|
x = '1-8' if x == 'all'
|
|
40
65
|
x.split(',').each do |x1|
|
|
41
66
|
if x1['-']
|
|
@@ -50,10 +75,10 @@ module ZSteg
|
|
|
50
75
|
@options[:extra_checks] = false
|
|
51
76
|
end
|
|
52
77
|
|
|
53
|
-
opts.on "--lsb", "least significant
|
|
78
|
+
opts.on "--lsb", "least significant bit comes first" do
|
|
54
79
|
@options[:bit_order] = :lsb
|
|
55
80
|
end
|
|
56
|
-
opts.on "--msb", "most significant
|
|
81
|
+
opts.on "--msb", "most significant bit comes first" do
|
|
57
82
|
@options[:bit_order] = :msb
|
|
58
83
|
end
|
|
59
84
|
|
|
@@ -62,31 +87,20 @@ module ZSteg
|
|
|
62
87
|
# specifying prime on command line disables extra checks
|
|
63
88
|
@options[:extra_checks] = false
|
|
64
89
|
end
|
|
65
|
-
opts.on "--invert", "invert bits (XOR 0xff)" do
|
|
66
|
-
@options[:invert] = true
|
|
67
|
-
end
|
|
68
90
|
|
|
69
|
-
|
|
70
|
-
#
|
|
71
|
-
|
|
91
|
+
opts.on("--shift N", Integer, "prepend N zero bits"){ |x| @options[:shift] = x }
|
|
92
|
+
#opts.on("--step N", Integer, "step") { |x| @options[:step] = x }
|
|
93
|
+
opts.on("--invert", "invert bits (XOR 0xff)") { @options[:invert] = true }
|
|
72
94
|
|
|
73
|
-
opts.on "-
|
|
74
|
-
@options[:
|
|
75
|
-
@options[:order] = :all
|
|
76
|
-
@options[:bits] = (1..8).to_a
|
|
77
|
-
# specifying --all on command line explicitly enables extra checks
|
|
78
|
-
@options[:extra_checks] = true
|
|
95
|
+
opts.on "--pixel-align", "pixel-align hidden data" do
|
|
96
|
+
@options[:pixel_align] = true
|
|
79
97
|
end
|
|
80
98
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
){ |x| @options[:order] = x.split(',') }
|
|
99
|
+
#################################################################################
|
|
100
|
+
opts.separator "\nAnalysis params:"
|
|
101
|
+
#################################################################################
|
|
85
102
|
|
|
86
|
-
opts.on
|
|
87
|
-
@options[:verbose] = -2 # silent ZPNG warnings
|
|
88
|
-
@actions << [:extract, x]
|
|
89
|
-
end
|
|
103
|
+
opts.on("-l", "--limit N", Integer, "limit bytes checked, 0 = no limit (default: #{@options[:limit]})"){ |n| @options[:limit] = n }
|
|
90
104
|
|
|
91
105
|
opts.separator ""
|
|
92
106
|
|
|
@@ -112,10 +126,6 @@ module ZSteg
|
|
|
112
126
|
@options[:min_str_len] = x
|
|
113
127
|
end
|
|
114
128
|
|
|
115
|
-
opts.on "--shift N", Integer, "prepend N zero bits" do |x|
|
|
116
|
-
@options[:shift] = x
|
|
117
|
-
end
|
|
118
|
-
|
|
119
129
|
opts.separator ""
|
|
120
130
|
opts.on "-v", "--verbose", "Run verbosely (can be used multiple times)" do |v|
|
|
121
131
|
@options[:verbose] += 1
|
|
@@ -203,6 +213,9 @@ module ZSteg
|
|
|
203
213
|
h[:bit_order] = :msb
|
|
204
214
|
when /^(\d)b$/, /^b(\d+)$/
|
|
205
215
|
h[:bits] = parse_bits($1)
|
|
216
|
+
when /^(\d)bp$/, /^b(\d+)p$/
|
|
217
|
+
h[:bits] = parse_bits($1)
|
|
218
|
+
h[:pixel_align] = true
|
|
206
219
|
when /\A[rgba]+\Z/
|
|
207
220
|
h[:channels] = [x]
|
|
208
221
|
when /\Axy|yx|yb|by\Z/i
|
|
@@ -231,6 +244,17 @@ module ZSteg
|
|
|
231
244
|
@img.extradata[$1.to_i]
|
|
232
245
|
when /imagedata/
|
|
233
246
|
@img.imagedata
|
|
247
|
+
when /\Achunk:(\d+):(.+)\Z/
|
|
248
|
+
# chunk with type check
|
|
249
|
+
idx, type = $1.to_i, $2
|
|
250
|
+
chunk = @img.chunks[idx]
|
|
251
|
+
raise "chunk ##{idx}: expected #{type} type, but got #{chunk.type}" if chunk.type != type
|
|
252
|
+
chunk.data
|
|
253
|
+
when /\Achunk:(\d+)\Z/
|
|
254
|
+
# chunk without type check
|
|
255
|
+
idx, type = $1.to_i, $2
|
|
256
|
+
chunk = @img.chunks[idx]
|
|
257
|
+
chunk.data
|
|
234
258
|
else
|
|
235
259
|
h = decode_param_string name
|
|
236
260
|
h[:limit] = @options[:limit] if @options[:limit] != Checker::DEFAULT_LIMIT
|
|
@@ -32,8 +32,8 @@ module ZSteg
|
|
|
32
32
|
else
|
|
33
33
|
8.times{ |i| byte |= (a.shift<<(7-i))}
|
|
34
34
|
end
|
|
35
|
-
#printf "[d] %02x %08b\n", byte, byte
|
|
36
35
|
data << byte.chr
|
|
36
|
+
#a = []
|
|
37
37
|
if data.size >= @limit
|
|
38
38
|
print "[limit #@limit]".gray if @verbose > 1
|
|
39
39
|
break
|
|
@@ -77,12 +77,15 @@ module ZSteg
|
|
|
77
77
|
[@image.height-1, 0, -1]
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
xstep *= params[:step] if params[:step]
|
|
81
|
+
ystep *= params[:ystep] if params[:ystep]
|
|
82
|
+
|
|
80
83
|
# cannot join these lines from ByteExtractor and ColorExtractor into
|
|
81
84
|
# one method for performance reason:
|
|
82
85
|
# it will require additional yield() for EACH BYTE iterated
|
|
83
86
|
|
|
84
87
|
if type[0,1].downcase == 'b'
|
|
85
|
-
# ROW iterator
|
|
88
|
+
# ROW iterator (natural)
|
|
86
89
|
if params[:prime]
|
|
87
90
|
idx = 0
|
|
88
91
|
y0.step(y1,ystep){ |y| x0.step(x1,xstep){ |x|
|
|
@@ -6,7 +6,7 @@ module ZSteg
|
|
|
6
6
|
|
|
7
7
|
def color_extract params = {}
|
|
8
8
|
channels = Array(params[:channels])
|
|
9
|
-
|
|
9
|
+
pixel_align = params[:pixel_align]
|
|
10
10
|
|
|
11
11
|
ch_masks = []
|
|
12
12
|
case channels.first.size
|
|
@@ -42,28 +42,28 @@ module ZSteg
|
|
|
42
42
|
color = @image[x,y]
|
|
43
43
|
|
|
44
44
|
ch_masks.each do |c,bidxs|
|
|
45
|
+
bidxs = bidxs[a.size-8..] if pixel_align && a.size + bidxs.size > 8
|
|
45
46
|
value = color.send(c)
|
|
46
47
|
bidxs.each do |bidx|
|
|
47
48
|
a << value[bidx]
|
|
48
49
|
end
|
|
49
50
|
end
|
|
50
|
-
#p [x,y,a.size,a]
|
|
51
51
|
|
|
52
52
|
while a.size >= 8
|
|
53
53
|
byte = 0
|
|
54
|
-
#
|
|
54
|
+
# a0 = a.dup
|
|
55
55
|
if params[:bit_order] == :msb
|
|
56
56
|
8.times{ |i| byte |= (a.shift<<i)}
|
|
57
57
|
else
|
|
58
58
|
8.times{ |i| byte |= (a.shift<<(7-i))}
|
|
59
59
|
end
|
|
60
|
-
#printf "[d] %02x %08b\n", byte, byte
|
|
60
|
+
# printf "[d] %-10s -> %-10s : %s %02x %08b x=%d y=%d\n", a0.join, a.join, byte.chr.inspect, byte, byte, x, y
|
|
61
61
|
data << byte.chr
|
|
62
62
|
if data.size >= @limit
|
|
63
63
|
print "[limit #@limit]".gray if @verbose > 1
|
|
64
64
|
throw :limit
|
|
65
65
|
end
|
|
66
|
-
|
|
66
|
+
a.clear if pixel_align && a.size < 8
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
end
|
data/lib/zsteg/result.rb
CHANGED
|
@@ -8,8 +8,9 @@ module ZSteg
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
class OpenStego < IOStruct.new
|
|
12
|
-
|
|
11
|
+
class OpenStego < IOStruct.new("CVCCCC",
|
|
12
|
+
:version, :data_len, :channel_bits, :fname_len, :compress, :encrypt, :fname,
|
|
13
|
+
struct_name: 'OpenStego')
|
|
13
14
|
|
|
14
15
|
def self.read io
|
|
15
16
|
super.tap do |r|
|
|
@@ -18,7 +19,7 @@ module ZSteg
|
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
def to_s
|
|
21
|
-
super.sub(
|
|
22
|
+
super.sub(/>$/,'').bright_red
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
|
data/lib/zsteg.rb
CHANGED
data/spec/checker_spec.rb
CHANGED
|
@@ -17,9 +17,9 @@ describe Checker do
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
it "should be quiet by default" do
|
|
21
|
-
@out.should == ""
|
|
22
|
-
end
|
|
20
|
+
# it "should be quiet by default" do
|
|
21
|
+
# @out.should == ""
|
|
22
|
+
# end
|
|
23
23
|
|
|
24
24
|
it "returned results should be equal to #results" do
|
|
25
25
|
@results.should == @checker.results
|
data/spec/plte_spec.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "samples/plte1.png" do
|
|
4
|
+
subject{ cli(sample("plte1.png")) }
|
|
5
|
+
it { should include("Zip archive data") }
|
|
6
|
+
|
|
7
|
+
describe "--extract" do
|
|
8
|
+
it "should extract zip file from PLTE with type check" do
|
|
9
|
+
r = cli(sample("plte1.png"), "--extract", "chunk:1:PLTE")
|
|
10
|
+
md5(r).should == 'e125f0f322fd1e99050dba688968385c'
|
|
11
|
+
end
|
|
12
|
+
it "should extract zip file from PLTE without type check" do
|
|
13
|
+
r = cli(sample("plte1.png"), "--extract", "chunk:1")
|
|
14
|
+
md5(r).should == 'e125f0f322fd1e99050dba688968385c'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
#coding: binary
|
|
2
2
|
$:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
|
|
3
3
|
require 'zsteg'
|
|
4
|
+
require 'digest/md5'
|
|
4
5
|
|
|
5
6
|
SAMPLES_DIR = File.expand_path("../samples", File.dirname(__FILE__))
|
|
6
7
|
|
|
8
|
+
def md5 data
|
|
9
|
+
Digest::MD5.hexdigest(data)
|
|
10
|
+
end
|
|
11
|
+
|
|
7
12
|
def each_sample glob="*.png"
|
|
8
13
|
Dir[File.join(SAMPLES_DIR, glob)].each do |fname|
|
|
9
14
|
yield fname.sub(Dir.pwd+'/','')
|
|
@@ -40,6 +45,7 @@ def cli *args
|
|
|
40
45
|
else
|
|
41
46
|
ZSteg::CLI
|
|
42
47
|
end
|
|
48
|
+
args << "-qqq"
|
|
43
49
|
args << "--no-color" unless args.any?{|x| x['color']}
|
|
44
50
|
orig_stdout, out = $stdout, ""
|
|
45
51
|
begin
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# https://github.com/pedrooaugusto/steganography-png
|
|
4
|
+
each_sample("steganography-png/*.png") do |fname|
|
|
5
|
+
describe fname do
|
|
6
|
+
it "should reveal secret message" do
|
|
7
|
+
r = cli fname, "--limit", "64", "-a", "--no-file"
|
|
8
|
+
r.should include("SteganographyPNG")
|
|
9
|
+
r.should include(ZSteg::Checker::SteganographyPNG::URL)
|
|
10
|
+
r.should_not include("ZSteg::Checker::SteganographyPNG")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/zsteg.gemspec
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: zsteg 0.2.
|
|
5
|
+
# stub: zsteg 0.2.14 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "zsteg".freeze
|
|
9
|
-
s.version = "0.2.
|
|
9
|
+
s.version = "0.2.14"
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib".freeze]
|
|
13
13
|
s.authors = ["Andrey \"Zed\" Zaikin".freeze]
|
|
14
|
-
s.date = "
|
|
14
|
+
s.date = "2026-01-28"
|
|
15
15
|
s.email = "zed.0xff@gmail.com".freeze
|
|
16
16
|
s.executables = ["zsteg".freeze, "zsteg-mask".freeze, "zsteg-reflow".freeze]
|
|
17
17
|
s.extra_rdoc_files = [
|
|
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
|
|
|
36
36
|
"lib/zsteg/analyzer.rb",
|
|
37
37
|
"lib/zsteg/checker.rb",
|
|
38
38
|
"lib/zsteg/checker/scanline_checker.rb",
|
|
39
|
+
"lib/zsteg/checker/steganography_png.rb",
|
|
39
40
|
"lib/zsteg/checker/wbstego.rb",
|
|
40
41
|
"lib/zsteg/checker/zlib.rb",
|
|
41
42
|
"lib/zsteg/cli/cli.rb",
|
|
@@ -58,11 +59,13 @@ Gem::Specification.new do |s|
|
|
|
58
59
|
"spec/mask_spec.rb",
|
|
59
60
|
"spec/newbiecontest_spec.rb",
|
|
60
61
|
"spec/openstego_spec.rb",
|
|
62
|
+
"spec/plte_spec.rb",
|
|
61
63
|
"spec/polictf2012_spec.rb",
|
|
62
64
|
"spec/prime_spec.rb",
|
|
63
65
|
"spec/r3g2b3_spec.rb",
|
|
64
66
|
"spec/simple_spec.rb",
|
|
65
67
|
"spec/spec_helper.rb",
|
|
68
|
+
"spec/steganography_png_spec.rb",
|
|
66
69
|
"spec/wbstego_spec.rb",
|
|
67
70
|
"spec/wechall_spec.rb",
|
|
68
71
|
"spec/zlib_spec.rb",
|
|
@@ -73,7 +76,7 @@ Gem::Specification.new do |s|
|
|
|
73
76
|
]
|
|
74
77
|
s.homepage = "http://github.com/zed-0xff/zsteg".freeze
|
|
75
78
|
s.licenses = ["MIT".freeze]
|
|
76
|
-
s.rubygems_version = "3.
|
|
79
|
+
s.rubygems_version = "3.2.33".freeze
|
|
77
80
|
s.summary = "Detect stegano-hidden data in PNG & BMP files.".freeze
|
|
78
81
|
|
|
79
82
|
if s.respond_to? :specification_version then
|
|
@@ -81,14 +84,14 @@ Gem::Specification.new do |s|
|
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
if s.respond_to? :add_runtime_dependency then
|
|
84
|
-
s.add_runtime_dependency(%q<zpng>.freeze, [">= 0.4.
|
|
85
|
-
s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0"])
|
|
87
|
+
s.add_runtime_dependency(%q<zpng>.freeze, [">= 0.4.6"])
|
|
88
|
+
s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0.7.0"])
|
|
86
89
|
s.add_runtime_dependency(%q<prime>.freeze, [">= 0"])
|
|
87
90
|
s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
|
|
88
91
|
s.add_development_dependency(%q<juwelier>.freeze, [">= 0"])
|
|
89
92
|
else
|
|
90
|
-
s.add_dependency(%q<zpng>.freeze, [">= 0.4.
|
|
91
|
-
s.add_dependency(%q<iostruct>.freeze, [">= 0"])
|
|
93
|
+
s.add_dependency(%q<zpng>.freeze, [">= 0.4.6"])
|
|
94
|
+
s.add_dependency(%q<iostruct>.freeze, [">= 0.7.0"])
|
|
92
95
|
s.add_dependency(%q<prime>.freeze, [">= 0"])
|
|
93
96
|
s.add_dependency(%q<rspec>.freeze, [">= 0"])
|
|
94
97
|
s.add_dependency(%q<juwelier>.freeze, [">= 0"])
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zsteg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrey "Zed" Zaikin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: zpng
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.4.
|
|
19
|
+
version: 0.4.6
|
|
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.4.
|
|
26
|
+
version: 0.4.6
|
|
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
|
-
version:
|
|
33
|
+
version: 0.7.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
|
-
version:
|
|
40
|
+
version: 0.7.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: prime
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +108,7 @@ files:
|
|
|
108
108
|
- lib/zsteg/analyzer.rb
|
|
109
109
|
- lib/zsteg/checker.rb
|
|
110
110
|
- lib/zsteg/checker/scanline_checker.rb
|
|
111
|
+
- lib/zsteg/checker/steganography_png.rb
|
|
111
112
|
- lib/zsteg/checker/wbstego.rb
|
|
112
113
|
- lib/zsteg/checker/zlib.rb
|
|
113
114
|
- lib/zsteg/cli/cli.rb
|
|
@@ -130,11 +131,13 @@ files:
|
|
|
130
131
|
- spec/mask_spec.rb
|
|
131
132
|
- spec/newbiecontest_spec.rb
|
|
132
133
|
- spec/openstego_spec.rb
|
|
134
|
+
- spec/plte_spec.rb
|
|
133
135
|
- spec/polictf2012_spec.rb
|
|
134
136
|
- spec/prime_spec.rb
|
|
135
137
|
- spec/r3g2b3_spec.rb
|
|
136
138
|
- spec/simple_spec.rb
|
|
137
139
|
- spec/spec_helper.rb
|
|
140
|
+
- spec/steganography_png_spec.rb
|
|
138
141
|
- spec/wbstego_spec.rb
|
|
139
142
|
- spec/wechall_spec.rb
|
|
140
143
|
- spec/zlib_spec.rb
|
|
@@ -161,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
161
164
|
- !ruby/object:Gem::Version
|
|
162
165
|
version: '0'
|
|
163
166
|
requirements: []
|
|
164
|
-
rubygems_version: 3.
|
|
167
|
+
rubygems_version: 3.2.33
|
|
165
168
|
signing_key:
|
|
166
169
|
specification_version: 4
|
|
167
170
|
summary: Detect stegano-hidden data in PNG & BMP files.
|