|
#----------------------------------------------------------------# |
|
# HideMage - Write some Infos into an Image |
|
# by Roman Pramberger |
|
# |
|
# Ruby converts text to Ascii int values up to 126 |
|
# We use a numbersystem of 6. Because we just change the last |
|
# number of an 257 RGB value. |
|
# For example "x" in Ascii is 320 |
|
# Lets guess the Pixel comes as: red[144], green[178], blue[214] |
|
# So we take the 320 and do: red[143], green[172], blue[210] |
|
# And we put 1 Char into 1 Pixel! |
|
#----------------------------------------------------------------# |
|
|
|
require 'optparse' |
|
begin |
|
require 'RMagick' |
|
include Magick |
|
rescue |
|
puts "RMagick not deteced! Do you want to install? (y/n)" |
|
answer = gets.chomp() |
|
if answer == "y" |
|
system("sudo gem install rmagick") |
|
end |
|
exit |
|
end |
|
|
|
options = {} |
|
|
|
optparse = OptionParser.new do|opts| |
|
opts.banner = "Usage: ruby hidemage.rb [options] IMG-FILE.png" |
|
|
|
options[:debug] = false |
|
opts.on( '-d', '--debug', "Output MUCH information\n\n" ) do |
|
options[:debug] = true |
|
end |
|
|
|
options[:write] = false |
|
opts.on( '-w', '--write', 'Write to Image' ) do |string| |
|
options[:write] = true |
|
end |
|
|
|
options[:string] = nil |
|
opts.on( '-s', '--string "STRING"', '* String to hide' ) do |string| |
|
options[:string] = string |
|
end |
|
|
|
options[:file] = nil |
|
opts.on( '-f', '--file FILE', "* Read String from file\n\n" ) do|file| |
|
options[:file] = file |
|
end |
|
|
|
|
|
options[:read] = nil |
|
opts.on( '-r', '--read', "Read from Image\n\n" ) do|file| |
|
options[:read] = file |
|
end |
|
|
|
options[:install] = false |
|
opts.on( '-i', '--install', 'Copy this Script to /usr/bin' ) do|file| |
|
options[:install] = true |
|
end |
|
|
|
opts.on( '-h', '--help', 'Display this screen' ) do |
|
puts opts |
|
exit |
|
end |
|
end |
|
|
|
optparse.parse! |
|
|
|
if ARGV[0].nil? or ARGV[0] == "" or (options[:write] and (options[:file].nil? and options[:string].nil?)) |
|
puts "ERROR: No image given..." if ARGV[0].nil? or ARGV[0] == "" |
|
puts "try: ruby hidemage.rb -h" |
|
exit |
|
end |
|
|
|
if !File.exist?(ARGV[0]) |
|
puts "ERROR: Image not found..." |
|
exit |
|
end |
|
|
|
if !options[:file].nil? |
|
if File.exist?(options[:file]) |
|
string = File.open(options[:file]).read |
|
end |
|
end |
|
|
|
if !options[:string].nil? |
|
puts "!! If you define a file and a string. It will just use the string... " if !options[:file].nil? |
|
string = options[:string] |
|
end |
|
|
|
DEBUG = options[:debug] |
|
@escape = ["1","3","5","1","3","5","1","3","5"] |
|
|
|
puts " |
|
#################################### |
|
# < HideMage > # |
|
# Hide Secret Messages in Images # |
|
#################################### |
|
|
|
" |
|
|
|
if options[:write] |
|
print ":: Reading image to rmagick... " |
|
#img = ImageList.new(ARGV[0]) |
|
img = Magick::Image.read(ARGV[0]).first |
|
#pixels = inimg.dispatch(0,0,inimg.columns, inimg.rows, "RGB") |
|
#img = Magick::Image.constitute(inimg.columns, inimg.rows, "RGB", pixels) |
|
puts "done" |
|
puts img.inspect if DEBUG |
|
|
|
## get Ascii values |
|
print ":: Cutting String into Ascii values... " |
|
$chars = Array.new |
|
string.each_byte do |c| |
|
if c.to_s.split("").size == 2 |
|
puts "Char is only 2 big. expand to 3" if DEBUG |
|
$chars << "0" |
|
elsif c.to_s.split("").size == 1 |
|
puts "Char is only 1 big. expand to 3" if DEBUG |
|
$chars << "0" |
|
$chars << "0" |
|
end |
|
c.to_s.each_char do |c2| |
|
$chars << c2 |
|
end |
|
end |
|
puts "done" |
|
print "#{$chars}\n" if DEBUG |
|
$chars += @escape # add escape sequence "135135135" |
|
|
|
puts ":: Created #{$chars.size} numbers" |
|
|
|
def getNewColorValue(color) |
|
if color.to_i < 250 and color.to_i > 9 |
|
print "Left Values: #{$chars}\n" if DEBUG |
|
color = color.to_i |
|
color -= color.to_s.split("").last.to_i |
|
color += $chars.first.to_i |
|
$chars.delete_at(0) |
|
end |
|
return color |
|
end |
|
|
|
print ":: Write to Image..." |
|
puts "" if DEBUG # just some cosmetic :3 |
|
img.each_pixel { |p,c,r| |
|
if $chars.size > 0 |
|
red = getNewColorValue(p.red/257) |
|
green = getNewColorValue(p.green/257) |
|
blue = getNewColorValue(p.blue/257) |
|
color = "rgb(#{red},#{green},#{blue}) #{c}/#{r}" |
|
#color = "##{red.to_s(16)}#{green.to_s(16)}#{blue.to_s(16)}" |
|
#puts color |
|
img.pixel_color(c,r,color) |
|
img.store_pixels(c,r,1,1,[Pixel.new(red*257, green*257, blue*257, 0)]) |
|
else |
|
break |
|
end |
|
|
|
#rgb(r,g,b) |
|
} |
|
puts "done" |
|
print ":: Saving image..." |
|
img.write(ARGV[0]) |
|
puts " done" |
|
img = nil |
|
end |
|
sleep 0.4 |
|
if options[:read] |
|
print ":: Reading image to rmagick... " |
|
img = ImageList.new(ARGV[0]) |
|
puts "done" |
|
puts img.inspect if DEBUG |
|
|
|
def checkWork() |
|
if @work.size == 3 |
|
@out << @work.join("") |
|
print @work if DEBUG |
|
@work.clear |
|
end |
|
end |
|
def genColor(color) |
|
if color.to_i < 250 and color.to_i > 9 |
|
yut = color.to_s.split("").last.to_i |
|
yut = 9 if yut == -1 |
|
@work << yut |
|
checkWork() |
|
end |
|
end |
|
print ":: Reading Image... " |
|
@work = Array.new |
|
@out = Array.new |
|
img.each_pixel { |p,c,r| |
|
genColor(p.red/257) |
|
genColor(p.green/257) |
|
genColor(p.blue/257) |
|
break if @out[@out.size-1] == "135" and @out[@out.size-2] == "135" and @out[@out.size-3] == "135" |
|
break if @out.size == 20 |
|
} |
|
puts "done" |
|
|
|
puts "<-----[Hidden Message]----->" |
|
@out.each do |o| |
|
begin |
|
print o.to_i.chr if o.to_i != 135 |
|
rescue |
|
end |
|
end |
|
puts "\r\n\r\n" |
|
img = nil |
|
end |