zsteg 0.2.12 → 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b50a98cd405613a299041cc60c497f4f9a73a099e3112f44b27dee3fddf4831d
4
- data.tar.gz: 8c58dd150ce32f42cc381a67592eded9c9c38e7dc0c4026642ec4773081f4bea
3
+ metadata.gz: 05bf462c6bc2696efead731d0ce3bda8cf371435cc9448b100892b7084364c64
4
+ data.tar.gz: c12f610fe42706271d763620100a71572477696c07010d9323c1bb97f7440fbe
5
5
  SHA512:
6
- metadata.gz: 726aa00d6e7cc127072b7dbebe5418d668bc7d62dd119267ab05341b96d63ca71ce23cb2e2cb189e5b59cb8cbd48c09700d736b0d581b32b1feeb30a9ac3b390
7
- data.tar.gz: 22811b2e9c2ffc3e4ce09aa67d3a65c7dd3636d84740b09664e80dca20d02456f5632214a7df8354affac0f9e8ffd7ccaeb466606608f3bd8e1222ca3dec34c9
6
+ metadata.gz: 3340516e94d8248446ddb5df7a64269aed8fb4b09a1bf10057d603581b352e39adc595104ae4b75fa042d8895459532dac21c2304cc49bfe222ffc0df358fa55
7
+ data.tar.gz: d4bd9eaf13356a534eeb3be2807b524c73549dc0d3fbe44f349393930f0f4a31be1430b434d4ef8fb42ea2c2eda42dd13eb013222fc37714ce9801973358ba8e
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "zpng", ">= 0.4.4"
4
- gem "iostruct"
3
+ gem "zpng", ">= 0.4.5"
4
+ gem "iostruct", ">= 0.0.5"
5
5
  gem "prime"
6
6
 
7
7
  group :development do
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- addressable (2.8.0)
5
- public_suffix (>= 2.0.2, < 5.0)
4
+ addressable (2.8.1)
5
+ public_suffix (>= 2.0.2, < 6.0)
6
6
  builder (3.2.4)
7
7
  descendants_tracker (0.0.4)
8
8
  thread_safe (~> 0.3, >= 0.3.1)
9
9
  diff-lcs (1.5.0)
10
- faraday (1.10.0)
10
+ faraday (1.10.3)
11
11
  faraday-em_http (~> 1.0)
12
12
  faraday-em_synchrony (~> 1.0)
13
13
  faraday-excon (~> 1.1)
@@ -31,7 +31,7 @@ GEM
31
31
  faraday-rack (1.0.0)
32
32
  faraday-retry (1.0.3)
33
33
  forwardable (1.3.3)
34
- git (1.13.1)
34
+ git (1.13.2)
35
35
  addressable (~> 2.8)
36
36
  rchardet (~> 1.8)
37
37
  github_api (0.19.0)
@@ -41,8 +41,8 @@ GEM
41
41
  hashie (~> 3.5, >= 3.5.2)
42
42
  oauth2 (~> 1.0)
43
43
  hashie (3.6.0)
44
- highline (2.0.3)
45
- iostruct (0.0.4)
44
+ highline (2.1.0)
45
+ iostruct (0.0.5)
46
46
  juwelier (2.4.9)
47
47
  builder
48
48
  bundler
@@ -55,13 +55,13 @@ GEM
55
55
  rake
56
56
  rdoc
57
57
  semver2
58
- jwt (2.4.1)
58
+ jwt (2.7.0)
59
59
  kamelcase (0.0.2)
60
60
  semver2 (~> 3)
61
61
  mini_portile2 (2.8.1)
62
62
  multi_json (1.15.0)
63
63
  multi_xml (0.6.0)
64
- multipart-post (2.2.3)
64
+ multipart-post (2.3.0)
65
65
  nokogiri (1.14.2)
66
66
  mini_portile2 (~> 2.8.0)
67
67
  racc (~> 1.4)
@@ -74,46 +74,46 @@ GEM
74
74
  prime (0.1.2)
75
75
  forwardable
76
76
  singleton
77
- psych (4.0.4)
77
+ psych (5.1.0)
78
78
  stringio
79
- public_suffix (4.0.7)
79
+ public_suffix (5.0.1)
80
80
  racc (1.6.2)
81
81
  rack (3.0.4.1)
82
82
  rainbow (3.1.1)
83
83
  rake (13.0.6)
84
84
  rchardet (1.8.0)
85
- rdoc (6.4.0)
85
+ rdoc (6.5.0)
86
86
  psych (>= 4.0.0)
87
- rspec (3.11.0)
88
- rspec-core (~> 3.11.0)
89
- rspec-expectations (~> 3.11.0)
90
- rspec-mocks (~> 3.11.0)
91
- rspec-core (3.11.0)
92
- rspec-support (~> 3.11.0)
93
- rspec-expectations (3.11.0)
87
+ rspec (3.12.0)
88
+ rspec-core (~> 3.12.0)
89
+ rspec-expectations (~> 3.12.0)
90
+ rspec-mocks (~> 3.12.0)
91
+ rspec-core (3.12.1)
92
+ rspec-support (~> 3.12.0)
93
+ rspec-expectations (3.12.2)
94
94
  diff-lcs (>= 1.2.0, < 2.0)
95
- rspec-support (~> 3.11.0)
96
- rspec-mocks (3.11.1)
95
+ rspec-support (~> 3.12.0)
96
+ rspec-mocks (3.12.3)
97
97
  diff-lcs (>= 1.2.0, < 2.0)
98
- rspec-support (~> 3.11.0)
99
- rspec-support (3.11.0)
98
+ rspec-support (~> 3.12.0)
99
+ rspec-support (3.12.0)
100
100
  ruby2_keywords (0.0.5)
101
101
  semver2 (3.4.2)
102
102
  singleton (0.1.1)
103
- stringio (3.0.2)
103
+ stringio (3.0.5)
104
104
  thread_safe (0.3.6)
105
- zpng (0.4.4)
105
+ zpng (0.4.5)
106
106
  rainbow (~> 3.1.1)
107
107
 
108
108
  PLATFORMS
109
109
  ruby
110
110
 
111
111
  DEPENDENCIES
112
- iostruct
112
+ iostruct (>= 0.0.5)
113
113
  juwelier
114
114
  prime
115
115
  rspec
116
- zpng (>= 0.4.4)
116
+ zpng (>= 0.4.5)
117
117
 
118
118
  BUNDLED WITH
119
119
  2.3.12
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 BIT comes first
37
- --msb most significant BIT comes first
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
- -a, --all try all known methods
41
- -o, --order X pixel iteration order (default: 'auto')
42
- valid values: ALL,xy,yx,XY,YX,xY,Xy,bY,...
43
- -E, --extract NAME extract specified payload, NAME is like '1b,rgb,lsb'
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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.12
1
+ 0.2.13
data/cmp_png.rb CHANGED
@@ -5,7 +5,7 @@ require 'awesome_print'
5
5
  images = ARGV.map{ |fname| ZPNG::Image.load(fname) }
6
6
  raise "need at least 2 images" if images.size < 2
7
7
 
8
- limit = 20
8
+ limit = 100
9
9
  alpha_used = images.any?(&:alpha_used?)
10
10
  channels = alpha_used ? %w'r g b a' : %w'r g b'
11
11
 
@@ -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
15
+ def valid?
16
+ magic == 0x116b && (1..8).include?(bitloss)
17
+ end
18
+
19
+ def to_s
20
+ super.sub('#<struct ZSteg::Checker::SteganographyPNG::Result', 'SteganographyPNG').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
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
- # catch Kernel#print for easier verbosity handling
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
 
@@ -92,12 +97,26 @@ module ZSteg
92
97
  Array(params[:order]).uniq.each do |order|
93
98
  (params[:prime] == :all ? [false,true] : [params[:prime]]).each do |prime|
94
99
  Array(params[:bits]).uniq.each do |bits|
95
- p1 = @params.merge :bits => bits, :order => order, :prime => prime
96
- if order[/b/i]
97
- # byte iterator does not need channels
98
- check_channels nil, p1
100
+ if params[:pixel_align] == :all
101
+ [false, true].each do |pixel_align|
102
+ # skip cases when output will be identical for pixel_align true/false
103
+ next if pixel_align && (8%bits) == 0
104
+ p1 = @params.merge bits: bits, order: order, prime: prime, pixel_align: pixel_align
105
+ if order[/b/i]
106
+ # byte iterator does not need channels
107
+ check_channels nil, p1
108
+ else
109
+ channels.each{ |c| check_channels c, p1 }
110
+ end
111
+ end
99
112
  else
100
- channels.each{ |c| check_channels c, p1 }
113
+ p1 = @params.merge bits: bits, order: order, prime: prime
114
+ if order[/b/i]
115
+ # byte iterator does not need channels
116
+ check_channels nil, p1
117
+ else
118
+ channels.each{ |c| check_channels c, p1 }
119
+ end
101
120
  end
102
121
  end
103
122
  end
@@ -150,6 +169,13 @@ module ZSteg
150
169
  show_title title, :bright_red
151
170
  process_result data, :special => true, :title => title
152
171
  end
172
+
173
+ if r = SteganographyPNG.check_image(@image, @params)
174
+ @found_anything = true
175
+ title = "image"
176
+ show_title title, :bright_red
177
+ process_result nil, title: title, result: r
178
+ end
153
179
  end
154
180
 
155
181
  def check_metadata
@@ -220,6 +246,8 @@ module ZSteg
220
246
  end
221
247
  end
222
248
 
249
+ bits_tag << "p" if params[:pixel_align]
250
+
223
251
  title = [
224
252
  bits_tag,
225
253
  channels,
@@ -268,21 +296,26 @@ module ZSteg
268
296
  def process_result data, params
269
297
  verbose = params[:special] ? [@verbose,1.5].max : @verbose
270
298
 
271
- if @cache[data]
272
- if verbose > 1
273
- puts "[same as #{@cache[data].inspect}]".gray
274
- return true
275
- else
276
- # silent return
277
- return false
299
+ result = nil
300
+ if data
301
+ if @cache[data]
302
+ if verbose > 1
303
+ puts "[same as #{@cache[data].inspect}]".gray
304
+ return true
305
+ else
306
+ # silent return
307
+ return false
308
+ end
278
309
  end
279
- end
280
310
 
281
- # TODO: store hash of data for large datas
282
- @cache[data] = params[:title]
311
+ # TODO: store hash of data for large datas
312
+ @cache[data] = params[:title]
283
313
 
284
- if result = data2result(data, params)
285
- @results << result
314
+ if result = data2result(data, params)
315
+ @results << result
316
+ end
317
+ elsif !(result = params[:result])
318
+ raise "[?] No data nor result"
286
319
  end
287
320
 
288
321
  case verbose
@@ -309,7 +342,7 @@ module ZSteg
309
342
  else
310
343
  show_result result, params
311
344
  end
312
- if data.size > 0 && !result.is_a?(Result::OneChar) && !result.is_a?(Result::WholeText)
345
+ if data && data.size > 0 && !result.is_a?(Result::OneChar) && !result.is_a?(Result::WholeText)
313
346
  # newline if no results and want hexdump
314
347
  puts if !result || result == []
315
348
  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
- :verbose => 0,
15
- :limit => Checker::DEFAULT_LIMIT,
16
- :order => Checker::DEFAULT_ORDER
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 BIT comes first" do
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 BIT comes first" do
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
- # opts.on "--pixel-align", "pixel-align hidden data (EasyBMP)" do
70
- # @options[:pixel_align] = true
71
- # end
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 "-a", "--all", "try all known methods" do
74
- @options[:prime] = :all
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
- opts.on("-o", "--order X", /all|auto|[bxy,]+/i,
82
- "pixel iteration order (default: '#{@options[:order]}')",
83
- "valid values: ALL,xy,yx,XY,YX,xY,Xy,bY,...",
84
- ){ |x| @options[:order] = x.split(',') }
99
+ #################################################################################
100
+ opts.separator "\nAnalysis params:"
101
+ #################################################################################
85
102
 
86
- opts.on "-E", "--extract NAME", "extract specified payload, NAME is like '1b,rgb,lsb'" do |x|
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
@@ -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
- #pixel_align = params[:pixel_align]
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
- #puts a.join
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
- #a.clear if pixel_align
66
+ a.clear if pixel_align && a.size < 8
67
67
  end
68
68
  end
69
69
  end
data/lib/zsteg.rb CHANGED
@@ -9,10 +9,6 @@ require 'zsteg/checker'
9
9
  require 'zsteg/result'
10
10
  require 'zsteg/file_cmd'
11
11
 
12
- require 'zsteg/checker/wbstego'
13
- require 'zsteg/checker/scanline_checker'
14
- require 'zsteg/checker/zlib'
15
-
16
12
  require 'zsteg/masker'
17
13
 
18
14
  require 'zsteg/analyzer'
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/spec_helper.rb CHANGED
@@ -40,6 +40,7 @@ def cli *args
40
40
  else
41
41
  ZSteg::CLI
42
42
  end
43
+ args << "-qqq"
43
44
  args << "--no-color" unless args.any?{|x| x['color']}
44
45
  orig_stdout, out = $stdout, ""
45
46
  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.12 ruby lib
5
+ # stub: zsteg 0.2.13 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "zsteg".freeze
9
- s.version = "0.2.12"
9
+ s.version = "0.2.13"
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 = "2023-02-14"
14
+ s.date = "2023-02-19"
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",
@@ -63,6 +64,7 @@ Gem::Specification.new do |s|
63
64
  "spec/r3g2b3_spec.rb",
64
65
  "spec/simple_spec.rb",
65
66
  "spec/spec_helper.rb",
67
+ "spec/steganography_png_spec.rb",
66
68
  "spec/wbstego_spec.rb",
67
69
  "spec/wechall_spec.rb",
68
70
  "spec/zlib_spec.rb",
@@ -81,14 +83,14 @@ Gem::Specification.new do |s|
81
83
  end
82
84
 
83
85
  if s.respond_to? :add_runtime_dependency then
84
- s.add_runtime_dependency(%q<zpng>.freeze, [">= 0.4.4"])
85
- s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0"])
86
+ s.add_runtime_dependency(%q<zpng>.freeze, [">= 0.4.5"])
87
+ s.add_runtime_dependency(%q<iostruct>.freeze, [">= 0.0.5"])
86
88
  s.add_runtime_dependency(%q<prime>.freeze, [">= 0"])
87
89
  s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
88
90
  s.add_development_dependency(%q<juwelier>.freeze, [">= 0"])
89
91
  else
90
- s.add_dependency(%q<zpng>.freeze, [">= 0.4.4"])
91
- s.add_dependency(%q<iostruct>.freeze, [">= 0"])
92
+ s.add_dependency(%q<zpng>.freeze, [">= 0.4.5"])
93
+ s.add_dependency(%q<iostruct>.freeze, [">= 0.0.5"])
92
94
  s.add_dependency(%q<prime>.freeze, [">= 0"])
93
95
  s.add_dependency(%q<rspec>.freeze, [">= 0"])
94
96
  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.12
4
+ version: 0.2.13
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: 2023-02-14 00:00:00.000000000 Z
11
+ date: 2023-02-19 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.4
19
+ version: 0.4.5
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.4
26
+ version: 0.4.5
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: '0'
33
+ version: 0.0.5
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: '0'
40
+ version: 0.0.5
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
@@ -135,6 +136,7 @@ files:
135
136
  - spec/r3g2b3_spec.rb
136
137
  - spec/simple_spec.rb
137
138
  - spec/spec_helper.rb
139
+ - spec/steganography_png_spec.rb
138
140
  - spec/wbstego_spec.rb
139
141
  - spec/wechall_spec.rb
140
142
  - spec/zlib_spec.rb