#!/usr/bin/ruby ## docxtract v0.1 : Extract files from docx document ## Copyright (C) 2009 Franck GUENICHOT ## franck {dot} guenichot {at} orange {dot} fr ## ## This program is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License ## as published by the Free Software Foundation; either version 3 ## of the License, or any later version. ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . ## Written for the Network Forensic Puzzle #2 ## http://forensicscontest.com require 'rubygems' require 'zip/zip' require 'zip/zipfilesystem' require 'digest/md5' require 'optparse' $VERSION = "0.1" # USeful funcs. def md5sum(file) #Calculate md5sum of a file digest = Digest::MD5.hexdigest(File.read(file)) digest end ################################################################################################# # handle command line args options = {} opts = OptionParser.new do|opts| opts.banner = " docxtract version #{$VERSION} Copyright (C) 2009 Franck GUENICHOT docxtract comes with ABSOLUTELY NO WARRANTY; This is free software, and you are welcome to redistribute it under certain conditions. (GPL v3) Usage: docxtract -x [-i] [-d ] " options[:xtract] = false opts.on( '-x', '--xtract', 'xtract files (by default to current dir)' ) do options[:xtract] = true end options[:img_only] = false opts.on( '-i', '--img_only', '(extract) images only' ) do options[:img_only] = true end options[:md5sum] = false opts.on( '-m', '--md5', 'Display extracted file MD5 Hash' ) do options[:md5sum] = true end options[:destdir] = nil opts.on( '-d', '--destdir DIR', 'define destination DIR' ) do|dir| options[:destdir] = dir end opts.on( '-h', '--help', 'Display this screen' ) do puts opts exit end end #parse command line args opts.parse! $filename = ARGV[ARGV.length-1] # if no file in input => display help and exit if $filename == nil puts opts exit(0) end unless File.exist?($filename) puts "File: #{$filename} does not exist." exit(0) end begin if options[:xtract] then # open docx file Zip::ZipFile.open($filename) do |zipfile| zipfile.each {|file| if options[:destdir] then destpath = File.join(options[:destdir],file.name) else destpath = file.name.gsub('word/media/',"") end if options[:img_only] then if file.name =~ /word\/media\/.*$/ then puts "Extracting: #{file.name.gsub('word/media/',"")} (#{file.size} bytes)" FileUtils.mkpath(File.dirname(destpath.gsub('word/media/',""))) file.extract(destpath.gsub('word/media/',""),&proc{true}) if options[:md5sum] then md5 = md5sum(destpath) puts "MD5: #{md5}" end end else puts "Extracting: #{file.name} (#{file.size} bytes)" #create dir FileUtils.mkpath(File.dirname(destpath)) zipfile.extract(file,destpath) if options[:md5sum] then md5 = md5sum(destpath) puts "MD5: #{md5}" end end } end else puts opts end rescue => exception puts "An error occurred" puts exception end ################################################################################################# # END of docxtract # #################################################################################################