zsteg 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/Gemfile +2 -7
  2. data/Gemfile.lock +2 -4
  3. data/README.md +72 -1
  4. data/README.md.tpl +23 -0
  5. data/Rakefile +5 -3
  6. data/TODO +5 -2
  7. data/VERSION +1 -1
  8. data/bin/zsteg-mask +7 -0
  9. data/lib/zsteg/checker/wbstego.rb +69 -14
  10. data/lib/zsteg/checker.rb +137 -34
  11. data/lib/zsteg/cli.rb +92 -35
  12. data/lib/zsteg/extractor/byte_extractor.rb +36 -21
  13. data/lib/zsteg/extractor/color_extractor.rb +68 -34
  14. data/lib/zsteg/extractor.rb +36 -1
  15. data/lib/zsteg/file_cmd.rb +64 -1
  16. data/lib/zsteg/mask_cli.rb +268 -0
  17. data/lib/zsteg/masker.rb +52 -0
  18. data/lib/zsteg/result.rb +27 -32
  19. data/lib/zsteg.rb +2 -0
  20. data/samples/hackquest/crypt.bmp +0 -0
  21. data/samples/hackquest/square.bmp +0 -0
  22. data/samples/wbstego/wbsteg_blowfish_pass_1.bmp +0 -0
  23. data/samples/wbstego/wbsteg_cast128_pass_1.bmp +0 -0
  24. data/samples/wbstego/wbsteg_enc_pass_pass.bmp +0 -0
  25. data/samples/wbstego/wbsteg_enc_pass_pass_even.bmp +0 -0
  26. data/samples/wbstego/wbsteg_mix_pass_1.bmp +0 -0
  27. data/samples/wbstego/wbsteg_mix_pass_1_even.bmp +0 -0
  28. data/samples/wbstego/wbsteg_mix_pass_foobar.bmp +0 -0
  29. data/samples/wbstego/wbsteg_mix_pass_pass.bmp +0 -0
  30. data/samples/wbstego/wbsteg_mixenc_pass_pass_even.bmp +0 -0
  31. data/samples/{wbsteg_noenc.bmp → wbstego/wbsteg_noenc.bmp} +0 -0
  32. data/samples/wbstego/wbsteg_noenc.png +0 -0
  33. data/samples/wbstego/wbsteg_noenc_.bmp +0 -0
  34. data/samples/{wbsteg_noenc_17.bmp → wbstego/wbsteg_noenc_17.bmp} +0 -0
  35. data/samples/wbstego/wbsteg_noenc__.bmp +0 -0
  36. data/samples/{wbsteg_noenc_even.bmp → wbstego/wbsteg_noenc_even.bmp} +0 -0
  37. data/samples/wbstego/wbsteg_noenc_even2.bmp +0 -0
  38. data/samples/{wbsteg_noenc_even_17.bmp → wbstego/wbsteg_noenc_even_17.bmp} +0 -0
  39. data/samples/wbstego/wbsteg_noenc_even_17_.bmp +0 -0
  40. data/samples/wbstego/wbsteg_noenc_ext_ABC.bmp +0 -0
  41. data/samples/wbstego/wbsteg_rijndael_pass_1.bmp +0 -0
  42. data/samples/wbstego/wbsteg_rijndael_pass_pass.bmp +0 -0
  43. data/samples/wbstego/wbsteg_rijndael_pass_pass_even.bmp +0 -0
  44. data/samples/wbstego/wbsteg_twofish_pass_1.bmp +0 -0
  45. data/samples/wechall/5ZMGcCLxpcpsru03.g00000010.png +0 -0
  46. data/samples/wechall/5ZMGcCLxpcpsru03.png +0 -0
  47. data/samples/wechall/stegano1.bmp +0 -0
  48. data/spec/checker_spec.rb +47 -0
  49. data/spec/easybmp_spec.rb +9 -0
  50. data/spec/hackquest_spec.rb +18 -0
  51. data/spec/mask_spec.rb +14 -0
  52. data/spec/polictf2012_spec.rb +48 -0
  53. data/spec/prime_spec.rb +9 -0
  54. data/spec/r3g2b3_spec.rb +9 -0
  55. data/spec/spec_helper.rb +21 -4
  56. data/spec/wbstego_spec.rb +21 -3
  57. data/spec/wechall_spec.rb +26 -0
  58. data/tmp/.keep +0 -0
  59. data/zsteg.gemspec +121 -0
  60. metadata +47 -43
  61. data/samples/06_enc.png +0 -0
  62. data/samples/Code.png +0 -0
  63. data/samples/README +0 -4
  64. data/samples/camouflage-password.png +0 -0
  65. data/samples/camouflage.png +0 -0
  66. data/samples/cats.png +0 -0
  67. data/samples/flower.png +0 -0
  68. data/samples/flower_rgb1.png +0 -0
  69. data/samples/flower_rgb2.png +0 -0
  70. data/samples/flower_rgb3.png +0 -0
  71. data/samples/flower_rgb4.png +0 -0
  72. data/samples/flower_rgb5.png +0 -0
  73. data/samples/flower_rgb6.png +0 -0
  74. data/samples/montenach-enc.png +0 -0
  75. data/samples/ndh2k12_sp113.bmp.7z +0 -0
  76. data/samples/openstego_q2.png +0 -0
  77. data/samples/openstego_send.png +0 -0
  78. data/samples/stg300.png +0 -0
data/lib/zsteg.rb CHANGED
@@ -10,3 +10,5 @@ require 'zsteg/result'
10
10
  require 'zsteg/file_cmd'
11
11
 
12
12
  require 'zsteg/checker/wbstego'
13
+
14
+ require 'zsteg/masker'
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ include ZSteg
4
+
5
+ describe Checker do
6
+ each_sample do |fname|
7
+ describe fname do
8
+ describe "#check" do
9
+ before :all do
10
+ @checker = Checker.new(fname)
11
+ orig_stdout, @out = $stdout, ""
12
+ begin
13
+ $stdout = StringIO.new(@out)
14
+ @results = @checker.check
15
+ ensure
16
+ $stdout = orig_stdout
17
+ end
18
+ end
19
+
20
+ it "should be quiet by default" do
21
+ @out.should == ""
22
+ end
23
+
24
+ it "returned results should be equal to #results" do
25
+ @results.should == @checker.results
26
+ end
27
+
28
+ it "should return array of results" do
29
+ @results.should be_instance_of(Array)
30
+ end
31
+
32
+ describe "results" do
33
+ it "should not have text results shorter than #{Checker::MIN_TEXT_LENGTH}" do
34
+ @results.each do |result|
35
+ case result
36
+ when Result::WholeText
37
+ result.text.size.should(be >= Checker::MIN_WHOLETEXT_LENGTH, result.inspect)
38
+ when Result::Text
39
+ result.text.size.should(be >= Checker::MIN_TEXT_LENGTH, result.inspect)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ sample("EasyBMP.bmp") do |fname|
4
+ describe fname do
5
+ it "contains hidden message" do
6
+ cli(fname, "-o","xy").should include("EasyBMPstego")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ sample("hackquest/square.bmp") do |fname|
4
+ describe fname do
5
+ subject{ cli(fname, "-b 10") }
6
+
7
+ it { should include "thesecretpasswordis:jedimaster" }
8
+ end
9
+ end
10
+
11
+ sample("hackquest/crypt.bmp") do |fname|
12
+ describe fname do
13
+ subject{ cli(fname, "-b 10") }
14
+
15
+ it { should include "111Hello" }
16
+ end
17
+ end
18
+
data/spec/mask_spec.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ sample("Steganography_original.png") do |fname|
4
+ describe fname do
5
+ it "extracts hidden image" do
6
+ tname = "tmp/mask.tmp.png"
7
+ File.unlink(tname) if File.exist?(tname)
8
+ cli(ZSteg::MaskCLI, fname, "-m 00000011 -O #{tname}")
9
+ img1 = ZPNG::Image.load tname
10
+ img2 = ZPNG::Image.load fname.sub(/\.png$/,".00000011.png")
11
+ img1.should == img2
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ sample('polictf2012_f200.bmp') do |fname|
4
+ describe fname do
5
+ it "should detect hidden BMP" do
6
+ cli(fname).should include("PC bitmap, Windows 3.x format, 500 x 277 x 24")
7
+ end
8
+
9
+ describe "hidden BMP #1" do
10
+ subject(:data){ cli(fname, "--extract", "4b,lsb,bY") }
11
+ its(:size){ should == 416816 }
12
+
13
+ it "should have BMP header" do
14
+ data[0,2].should == "BM"
15
+ end
16
+
17
+ it "should have 7zip after BMP" do
18
+ data.index("7z").should == 2005
19
+ end
20
+
21
+ describe "deeper" do
22
+ let(:tname){ File.join("tmp", File.basename(fname) + ".bmp") }
23
+ before(:all){ File.open(tname, "wb"){ |f| f<<data } }
24
+
25
+ it "should detect 7z & BMP" do
26
+ out = cli(tname)
27
+ out.should include('7-zip archive')
28
+ out.should include('PC bitmap, Windows 3.x format, 100 x 55 x 24')
29
+ end
30
+
31
+ describe "hidden BMP #2" do
32
+ subject(:data2){ cli(tname, "--extract", "2b,lsb,bY") }
33
+ its(:size){ should == 103875 }
34
+
35
+ describe "deeper" do
36
+ let(:tname2){ File.join("tmp", File.basename(tname) + ".bmp") }
37
+ before(:all){ File.open(tname2, "wb"){ |f| f<<data2 } }
38
+
39
+ it "should detect text" do
40
+ out = cli(tname2)
41
+ out.should include('sticazziantanieancoraunavoltacomesefossestato')
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ sample("prime.png") do |fname|
4
+ describe fname do
5
+ it "contains prime-encoded message" do
6
+ cli(fname, "--prime").should include("48300:TG9yZW0gaXBzdW")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ sample("r3g2b3.png") do |fname|
4
+ describe fname do
5
+ it "contains hidden message" do
6
+ cli(fname, "-c","r3g2b3").should include("astley.3gp")
7
+ end
8
+ end
9
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  $:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
2
2
  require 'zsteg'
3
3
  require 'zsteg/cli'
4
+ require 'zsteg/mask_cli'
4
5
 
5
6
  SAMPLES_DIR = File.expand_path("../samples", File.dirname(__FILE__))
6
7
 
@@ -11,21 +12,37 @@ def each_sample glob="*.png"
11
12
  end
12
13
 
13
14
  def sample fname
14
- File.join(SAMPLES_DIR, fname)
15
+ fname = File.join(SAMPLES_DIR, fname)
16
+ if block_given?
17
+ yield fname.sub(Dir.pwd+'/','')
18
+ end
19
+
20
+ fname
15
21
  end
16
22
 
17
23
  def cli *args
18
24
  @@cli_cache ||= {}
19
- @@cli_cache[args] ||=
25
+ args.map! do |arg|
26
+ if arg.is_a?(String) && arg[' ']
27
+ # split strings with spaces into arrays
28
+ arg.split(' ')
29
+ else
30
+ arg
31
+ end
32
+ end
33
+ args.flatten!
34
+ @@cli_cache[args.inspect] ||=
20
35
  begin
36
+ klass = args.first.is_a?(Class) ? args.shift : ZSteg::CLI
37
+ args << "--no-color" unless args.any?{|x| x['color']}
21
38
  orig_stdout, out = $stdout, ""
22
39
  begin
23
40
  $stdout = StringIO.new(out)
24
- ZSteg::CLI.new(args).run
41
+ klass.new(args).run
25
42
  ensure
26
43
  $stdout = orig_stdout
27
44
  end
28
- out
45
+ out.strip
29
46
  end
30
47
  end
31
48
 
data/spec/wbstego_spec.rb CHANGED
@@ -1,10 +1,28 @@
1
1
  require 'spec_helper'
2
2
 
3
- each_sample("wbsteg*.bmp") do |fname|
3
+ each_sample("wbstego/*") do |fname|
4
4
  describe fname do
5
- subject{ cli(fname) }
5
+ subject{
6
+ if fname['.png']
7
+ cli(fname, "1b,lsb", "-o", "all")
8
+ else
9
+ cli(fname, "1b,lsb")
10
+ end
11
+ }
6
12
 
7
13
  it { should include("wbStego") }
8
- it { should include("SuperSecretMessage") }
14
+ it { should include("SuperSecretMessage") } if fname['noenc']
15
+ if fname['even']
16
+ it { should include("even=true") }
17
+ else
18
+ it { should include("even=false") }
19
+ end
20
+
21
+ %w'blowfish twofish cast128 rijndael'.each do |enc|
22
+ it { should match(/#{enc}/i) } if fname[enc]
23
+ end
24
+
25
+ it { should include("mix=true") } if fname['mix']
26
+ it { should include("enc=\"wbSteg") } if fname['enc'] && !fname['noenc']
9
27
  end
10
28
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ WECHALL = {
4
+ 'stegano1.bmp' => "Look what the hex-edit revealed: passwd:steganoI"
5
+ }
6
+
7
+ each_sample("wechall/*.bmp") do |fname|
8
+ describe fname do
9
+ subject{ cli(fname) }
10
+
11
+ it { should include WECHALL[File.basename(fname)] }
12
+ end
13
+ end
14
+
15
+ sample("wechall/5ZMGcCLxpcpsru03.png") do |fname|
16
+ describe fname do
17
+ it "extracts hidden image" do
18
+ tname = "tmp/wechall.tmp.png"
19
+ File.unlink(tname) if File.exist?(tname)
20
+ cli(ZSteg::MaskCLI, fname, "--green 00000010 -O #{tname}")
21
+ img1 = ZPNG::Image.load tname
22
+ img2 = ZPNG::Image.load fname.sub(/\.png$/,".g00000010.png")
23
+ img1.should == img2
24
+ end
25
+ end
26
+ end
data/tmp/.keep ADDED
File without changes
data/zsteg.gemspec ADDED
@@ -0,0 +1,121 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "zsteg"
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Andrey \"Zed\" Zaikin"]
12
+ s.date = "2013-01-15"
13
+ s.email = "zed.0xff@gmail.com"
14
+ s.executables = ["zsteg", "zsteg-mask"]
15
+ s.extra_rdoc_files = [
16
+ "README.md",
17
+ "README.md.tpl",
18
+ "TODO"
19
+ ]
20
+ s.files = [
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "README.md",
24
+ "README.md.tpl",
25
+ "Rakefile",
26
+ "TODO",
27
+ "VERSION",
28
+ "bin/zsteg",
29
+ "bin/zsteg-mask",
30
+ "cmp_bmp.rb",
31
+ "cmp_png.rb",
32
+ "lib/zsteg.rb",
33
+ "lib/zsteg/checker.rb",
34
+ "lib/zsteg/checker/wbstego.rb",
35
+ "lib/zsteg/cli.rb",
36
+ "lib/zsteg/extractor.rb",
37
+ "lib/zsteg/extractor/byte_extractor.rb",
38
+ "lib/zsteg/extractor/color_extractor.rb",
39
+ "lib/zsteg/file_cmd.rb",
40
+ "lib/zsteg/mask_cli.rb",
41
+ "lib/zsteg/masker.rb",
42
+ "lib/zsteg/result.rb",
43
+ "pngsteg.gemspec",
44
+ "samples/hackquest/crypt.bmp",
45
+ "samples/hackquest/square.bmp",
46
+ "samples/wbstego/wbsteg_blowfish_pass_1.bmp",
47
+ "samples/wbstego/wbsteg_cast128_pass_1.bmp",
48
+ "samples/wbstego/wbsteg_enc_pass_pass.bmp",
49
+ "samples/wbstego/wbsteg_enc_pass_pass_even.bmp",
50
+ "samples/wbstego/wbsteg_mix_pass_1.bmp",
51
+ "samples/wbstego/wbsteg_mix_pass_1_even.bmp",
52
+ "samples/wbstego/wbsteg_mix_pass_foobar.bmp",
53
+ "samples/wbstego/wbsteg_mix_pass_pass.bmp",
54
+ "samples/wbstego/wbsteg_mixenc_pass_pass_even.bmp",
55
+ "samples/wbstego/wbsteg_noenc.bmp",
56
+ "samples/wbstego/wbsteg_noenc.png",
57
+ "samples/wbstego/wbsteg_noenc_.bmp",
58
+ "samples/wbstego/wbsteg_noenc_17.bmp",
59
+ "samples/wbstego/wbsteg_noenc__.bmp",
60
+ "samples/wbstego/wbsteg_noenc_even.bmp",
61
+ "samples/wbstego/wbsteg_noenc_even2.bmp",
62
+ "samples/wbstego/wbsteg_noenc_even_17.bmp",
63
+ "samples/wbstego/wbsteg_noenc_even_17_.bmp",
64
+ "samples/wbstego/wbsteg_noenc_ext_ABC.bmp",
65
+ "samples/wbstego/wbsteg_rijndael_pass_1.bmp",
66
+ "samples/wbstego/wbsteg_rijndael_pass_pass.bmp",
67
+ "samples/wbstego/wbsteg_rijndael_pass_pass_even.bmp",
68
+ "samples/wbstego/wbsteg_twofish_pass_1.bmp",
69
+ "samples/wechall/5ZMGcCLxpcpsru03.g00000010.png",
70
+ "samples/wechall/5ZMGcCLxpcpsru03.png",
71
+ "samples/wechall/stegano1.bmp",
72
+ "spec/camouflage_spec.rb",
73
+ "spec/cats_spec.rb",
74
+ "spec/checker_spec.rb",
75
+ "spec/easybmp_spec.rb",
76
+ "spec/flowers_spec.rb",
77
+ "spec/hackquest_spec.rb",
78
+ "spec/mask_spec.rb",
79
+ "spec/openstego_spec.rb",
80
+ "spec/polictf2012_spec.rb",
81
+ "spec/prime_spec.rb",
82
+ "spec/r3g2b3_spec.rb",
83
+ "spec/simple_spec.rb",
84
+ "spec/spec_helper.rb",
85
+ "spec/wbstego_spec.rb",
86
+ "spec/wechall_spec.rb",
87
+ "spec/zlib_spec.rb",
88
+ "tmp/.keep",
89
+ "zsteg.gemspec"
90
+ ]
91
+ s.homepage = "http://github.com/zed-0xff/zsteg"
92
+ s.licenses = ["MIT"]
93
+ s.require_paths = ["lib"]
94
+ s.rubygems_version = "1.8.24"
95
+ s.summary = "Detect stegano-hidden data in PNG & BMP files."
96
+
97
+ if s.respond_to? :specification_version then
98
+ s.specification_version = 3
99
+
100
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
101
+ s.add_runtime_dependency(%q<zpng>, [">= 0.2.2"])
102
+ s.add_runtime_dependency(%q<iostruct>, [">= 0"])
103
+ s.add_development_dependency(%q<rspec>, [">= 2.8.0"])
104
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
105
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
106
+ else
107
+ s.add_dependency(%q<zpng>, [">= 0.2.2"])
108
+ s.add_dependency(%q<iostruct>, [">= 0"])
109
+ s.add_dependency(%q<rspec>, [">= 2.8.0"])
110
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
111
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
112
+ end
113
+ else
114
+ s.add_dependency(%q<zpng>, [">= 0.2.2"])
115
+ s.add_dependency(%q<iostruct>, [">= 0"])
116
+ s.add_dependency(%q<rspec>, [">= 2.8.0"])
117
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
118
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
119
+ end
120
+ end
121
+