All the scripts needed to build and extract Linux flags

This commit is contained in:
wchen-r7 2017-07-07 11:58:46 -05:00
parent e8f4bb24a7
commit 61c8130244
30 changed files with 421 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

View File

@ -0,0 +1,37 @@
# -*- coding: binary -*-
#!/usr/bin/env ruby
require 'zlib'
def load_wav(fname)
File.read(fname)
end
def find_data_chunk_offset(wav)
wav.index('data') + 1
end
def get_data_chunk_size(wav)
data_chunk_offset = find_data_chunk_offset(wav)
wav[data_chunk_offset, 4].unpack('N').first
end
def extract_data_chunk(wav)
chunk_offset = find_data_chunk_offset(wav)
chunk_size = get_data_chunk_size(wav)
wav[chunk_offset + 4 + 3, chunk_size]
end
wav_fname = ARGV.shift
output = ARGV.shift
wav = load_wav(wav_fname)
data_chunk = extract_data_chunk(wav)
data_chunk = Zlib::Inflate.inflate(data_chunk)
File.open(output, 'wb') do |f|
f.write(data_chunk)
end
puts "#{output} written"

View File

@ -0,0 +1,88 @@
# -*- coding: binary -*-
#!/usr/bin/env ruby
require 'zlib'
def load_image(fname)
data = File.read(fname)
Zlib::Deflate.deflate(data)
end
# http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html
def make_wav(data_chunk)
# 47202 test size
size = 216 + data_chunk.length
wav = ''
# WAV RIFF Header
wav << 'RIFF' # groupID
wav << [ size ].pack('V') # WAV Size
wav << 'WAVE' # Riff Type
# FORMAT CHUNK
wav << 'fmt ' # Chunk ID
wav << [ 18 ].pack('V') # Chunk Size
wav << [ 0x06 ].pack('v') # Format tag
wav << [ 0x02 ].pack('v') # Channels
wav << [ 0x1f40].pack('V') # Sample per sec
wav << [ 0x3e80 ].pack('V') # Average Bytes per sec
wav << [ 0x02 ].pack('v') # Block align
wav << [ 0x08 ].pack('v') # Bits per sample
wav << [ 0x00 ].pack('v')
# Fact Chunk
wav << 'fact' # Chunk ID
wav << [ 0x04 ].pack('V') # Chunk size
wav << [ 0x5bc5 ].pack('V') # uncompressed size
# Data chunk
wav << 'data' # Chunk ID
wav << [ data_chunk.length ].pack('V') # Chunk size
wav << data_chunk
# afsp Chunk
wav << 'afsp' # Chunk ID
wav << [ 73 ].pack('V') # Chunk size
wav << 'AFspdate: 2003-01-30 03:28:44 UTC'
wav << "\x00"
wav << 'user: kabal@CAPELLA'
wav << "\x00"
wav << 'program: CopyAudio'
wav << [ 0x00 ].pack('v')
# List chunk
wav << 'LIST' # Chunk ID
wav << [ 76 ].pack('V') # Chunk size
wav << 'INFO'
# Sub chunk: ICRD
wav << 'ICRD' # Chunk ID
wav << [ 0x18 ].pack('V') # Chunk size
wav << '2003-01-30 03:28:44 UTC' # Timestamp
wav << "\x00"
# Sub Chunk: ISFT
wav << 'ISFT' # Chunk ID
wav << [ 0x0a ].pack('V') # Chunk Size
wav << 'CopyAudio' # Value
wav << "\x00"
# Sub chunk: ICMT
wav << 'ICMT' # Chunk ID
wav << [ 0x0e ].pack('V') # Chunk Size
wav << 'kabal@CAPELLA' # Value
wav << "\x00"
wav
end
# 'jack_of_clubs.PNG'
image_fname = ARGV.shift
output = ARGV.shift
zip_image = load_image(image_fname)
wav = make_wav(zip_image)
File.open(output, 'wb') do |f|
f.write(wav)
end
puts "Imaged zipped in a wav file."
puts "Wav file written to #{output}"

View File

@ -0,0 +1,84 @@
#!/usr/bin/env ruby
require 'rqrcode'
require 'fileutils'
# Installing rmagick is weird.
# Do:
# brew install imagemagick
# brew unlink imagemagick
# brew install imagemagick@6 && brew link imagemagick@6 --force
# gem install rmagick
#
# https://stackoverflow.com/questions/39494672/rmagick-installation-cant-find-magickwand-h
require 'Rmagick'
include Magick
class SevenOfDiamonds
TEMPPATH = File.expand_path(File.join(__FILE__, '..', '.temp'))
def initialize
make_temp_folder
end
def make_temp_folder
Dir.mkdir(TEMPPATH) unless Dir.exists?(TEMPPATH)
end
def clear
FileUtils.rm_rf(TEMPPATH) if Dir.exists?(TEMPPATH)
end
def make_flag(source_image_path, out_path)
bin = File.read(source_image_path)
h = get_hex(bin)
generate_qr_codes(h)
make_gif(out_path)
end
def print_status(msg='')
puts "[*] #{msg}"
end
def get_hex(bin)
h = bin.unpack('H*').first
print_status("Hex string size: #{h.length}")
h
end
def generate_qr_codes(text)
str_length = 50
max_fname_length = (text.length / str_length).round.to_s.length
counter = 0
(0..text.length).step(str_length) do |i|
s = text[i, str_length]
if !s.nil? && !s.empty?
counter += 1
qr = RQRCode::QRCode.new(s)
File.open(File.join(TEMPPATH, "#{counter.to_s.rjust(max_fname_length, '0')}.png"), 'wb') { |f| f.write(png = qr.as_png) }
print_status("QR ##{counter} generated: #{s}")
end
end
end
def make_gif(out_path)
gif = ImageList.new(*Dir[".temp/*.png"])
gif.delay = 10
gif.write(out_path)
print_status("GIF written as: #{out_path}")
end
end
if __FILE__ == $PROGRAM_NAME
source_image_path = 'hint.png'
out_image_path = 'hint.gif'
card = SevenOfDiamonds.new
begin
card.make_flag(source_image_path, out_image_path)
ensure
card.clear
end
end

View File

@ -0,0 +1,77 @@
#!/usr/bin/env ruby
# gem install zxing
require 'zxing'
require 'fileutils'
# Installing rmagick is weird.
# Do:
# brew install imagemagick
# brew unlink imagemagick
# brew install imagemagick@6 && brew link imagemagick@6 --force
# gem install rmagick
#
# https://stackoverflow.com/questions/39494672/rmagick-installation-cant-find-magickwand-h
require 'Rmagick'
include Magick
class CardExtractor
TEMPPATH = File.expand_path(File.join(__FILE__, '..', '.temp'))
def initialize(gif_path)
make_temp_folder
@frames = Image.read(gif_path)
end
def print_status(msg='')
puts "[*] #{msg}"
end
def make_temp_folder
Dir.mkdir(TEMPPATH) unless Dir.exists?(TEMPPATH)
end
def clear
FileUtils.rm_rf(TEMPPATH) if Dir.exists?(TEMPPATH)
end
def extract
s = ''
print_status("Extracting #{@frames.length} frames...")
count = 0
@frames.each do |frame|
count += 1
path = File.join(TEMPPATH, "qr#{count}.png")
frame.write(path)
qr = convert_qr_to_text(path).strip
print_status("Decoded #{File.basename(path)}: #{qr}")
s << qr if qr && !qr.empty?
end
File.open('your_zip_hint.png', 'wb') { |f| f.write([s].pack('H*')) }
end
def convert_qr_to_text(path)
ZXing.decode(path)
end
end
def main
gif_path = ARGV.shift
if gif_path.nil? || gif_path.empty?
puts "[x] Please specify a source GIF file"
return
end
ext = CardExtractor.new(gif_path)
begin
ext.extract
ensure
ext.clear
end
end
if __FILE__ == $PROGRAM_NAME
main
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

View File

@ -0,0 +1,26 @@
#!/usr/bin/env ruby
# gem install rubyzip
require 'zip'
SOURCEPNG = 'source.png'
CARDNAME = '7_of_diamonds.png'
ZIP_NAME = '7_of_diamonds.zip'
password = ARGV.shift
if password.nil? || password.empty?
puts "[x] Please set a password for the zip file you're trying to create"
exit
end
data = File.read(SOURCEPNG)
zip = Zip::OutputStream.write_buffer(::StringIO.new(''), Zip::TraditionalEncrypter.new(password)) do |o|
o.put_next_entry(CARDNAME)
o.write data
end
File.open(ZIP_NAME, 'wb') do |f|
f.write(zip.string)
end
puts "[*] #{ZIP_NAME} created with password: #{password}"

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

View File

@ -0,0 +1,26 @@
#!/usr/bin/env ruby
# gem install rubyzip
require 'zip'
SOURCEPNG = 'source.png'
CARDNAME = '8_of_hearts.png'
ZIP_NAME = '8_of_hearts.zip'
password = ARGV.shift
if password.nil? || password.empty?
puts "[x] Please set a password for the zip file you're trying to create"
exit
end
data = File.read(SOURCEPNG)
zip = Zip::OutputStream.write_buffer(::StringIO.new(''), Zip::TraditionalEncrypter.new(password)) do |o|
o.put_next_entry(CARDNAME)
o.write data
end
File.open(ZIP_NAME, 'wb') do |f|
f.write(zip.string)
end
puts "[*] #{ZIP_NAME} created with password: #{password}"

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

View File

@ -0,0 +1,25 @@
require 'chunky_png'
include ChunkyPNG::Color
# https://gist.github.com/jeffkreeftmeijer/923084
module ChunkyPNG::Color
def invert(value)
rgb(MAX - r(value), MAX - g(value), MAX - b(value))
end
end
source = ARGV.shift
dest = ARGV.shift
# joker-black.png
img = ChunkyPNG::Image.from_file(source)
img.pixels.map! do |p|
if ChunkyPNG::Color.fully_transparent?(p)
p
else
ChunkyPNG::Color.invert(p)
end
end
img.save(dest)

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

View File

@ -0,0 +1 @@
5c70e13495405b781e6f231d827a565a

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 KiB

View File

@ -0,0 +1,6 @@
#!/bin/bash
zip king_of_spades.zip king_of_spades.png
cat fake.png king_of_spades.zip > card.png
rm king_of_spades.zip
echo "Done"

View File

@ -0,0 +1,18 @@
#!/usr/bin/env ruby
require 'chunky_png'
require 'base64'
img_fname = ARGV.shift
if img_fname.nil? || img_fname.empty?
puts "[*] Please provide a PNG file"
exit
end
puts "[*] Extracting Q of Hearts from #{img_fname}..."
img = ChunkyPNG::Image.from_file(img_fname)
q_of_hearts = Base64::strict_decode64(img.metadata['q_of_hearts'])
File.open('real_q_of_hearts.png', 'wb') { |f| f.write(q_of_hearts) }
puts "[*] Done."

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,17 @@
#!/usr/bin/env ruby
require 'chunky_png'
require 'base64'
FAKEPNG = 'fake.png'
SOURCEPNG = 'source.png'
OUTPNG = 'q_of_hearts.png'
puts "[*] Injecting Q of Hearts data into #{FAKEPNG}..."
source = File.read(SOURCEPNG)
b64 = Base64.strict_encode64(source)
img = ChunkyPNG::Image.from_file(FAKEPNG)
img.metadata['q_of_hearts'] = b64
img.save(OUTPNG)
puts "Done"

View File

@ -0,0 +1,15 @@
#!/usr/bin/env ruby
require 'chunky_png'
require 'base64'
FAKEPNG = 'fake.png'
SOURCEPNG = 'source.png'
OUTPNG = 'q_of_hearts.png'
puts "[*] Injecting Q of Hearts data into #{FAKEPNG}..."
source = File.read(SOURCEPNG)
b64 = Base64.strict_encode64(source)
img = ChunkyPNG::Image.from_file(FAKEPNG)
img.metadata['q_of_hearts'] = b64
img.save(OUTPNG)

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB