# -*- coding: binary -*- module Msf module Exploit::Remote::Dialup def initialize(info = {}) super register_options( [ OptInt.new( 'BAUDRATE', [true, 'Baud Rate', 19200]), OptEnum.new( 'DATABITS', [true, 'Data Bits (4 is Windows Only)', '8', ['4', '5', '6', '7', '8'], '8']), OptString.new('DIALPREFIX', [true, 'Dial Prefix', 'ATDT *67, *70,']), OptString.new('DIALSUFFIX', [false, 'Dial Suffix', nil]), OptInt.new( 'DIALTIMEOUT', [true, 'Dial Timeout in seconds', 60]), OptBool.new( 'DISPLAYMODEM', [true, 'Displays modem commands and responses on the console', false]), OptEnum.new( 'FLOWCONTROL', [true, 'Flow Control', 'None', ['None', 'Hardware', 'Software', 'Both'], 'None']), OptString.new('INITSTRING', [true, 'Initialization String', 'AT X6 S11=80']), OptString.new('NUMBER', [true, 'Number to Dial (e.g. 1.800.950.9955, (202) 358-1234, 358.1234 etc.)', nil]), OptEnum.new( 'PARITY', [true, 'Parity (Mark & Space are Windows Only)', 'None', ['None', 'Even', 'Odd', 'Mark', 'Space'], 'None']), OptString.new('SERIALPORT', [true, 'Serial Port (e.g. 0 (COM1), 1 (COM2), /dev/ttyS0, etc.)', '/dev/ttyS0']), OptEnum.new( 'STOPBITS', [true, 'Stop Bits', '1', ['1', '2'], '1']), ], self.class) deregister_options('RHOST') begin require 'telephony' @telephony_loaded = true rescue ::Exception => e @telephony_loaded = false @telephony_error = e end end # Opens the modem connection def connect_dialup(global = true, opts={}) if (not @telephony_loaded) print_status("The serialport module is not available: #{telephony_error}") raise RuntimeError, "Telephony not available" end serialport = datastore['SERIALPORT'] baud = datastore['BAUDRATE'].to_i data_bits = datastore['DATABITS'].to_i stop_bits = datastore['STOPBITS'].to_i parity = case datastore['PARITY'] when 'Even' ; Telephony::Modem::EVEN when 'Odd' ; Telephony::Modem::ODD when 'Mark' ; Telephony::Modem::MARK when 'Space'; Telephony::Modem::SPACE else Telephony::Modem::NONE end flowcontrol = case datastore['FLOWCONTROL'] when 'Hardware' ; Telephony::Modem::HARD when 'Software' ; Telephony::Modem::SOFT when 'Both' ; Telephony::Modem::HARD | Telephony::Modem::SOFT else Telephony::Modem::NONE end initstring = datastore['INITSTRING'] dialprefix = datastore['DIALPREFIX'] dialsuffix = datastore['DIALSUFFIX'] dialtimeout = datastore['DIALTIMEOUT'].to_i number = datastore['NUMBER'].tr(' ', '') modem = Telephony::Modem.new(serialport) modem.params = { 'baud' => baud, 'data_bits' => data_bits, 'parity' => parity, 'stop_bits' => stop_bits } modem.flow_control = flowcontrol modem.display = datastore['DISPLAYMODEM'] print_status("Initializing Modem") result = modem.put_command('ATZ', 3) if result != 'OK' print_error("Error resetting modem") return end result = modem.put_command(initstring, 3) if result != 'OK' print_error("Error initializing modem") return end print_status("Dialing: #{number} (#{dialtimeout} sec. timeout)") dialstring = dialprefix + ' ' + number dialstring += (' ' + dialsuffix) if dialsuffix time = Time.now result = modem.put_command(dialstring, dialtimeout) while result =~ /RINGING/i result = modem.get_response(dialtimeout-(Time.now-time)) end case result when /CONNECT/i print_status("Carrier: #{result}" ) self.modem = modem if global return modem else print_error("No Carrier") disconnect_dialup(modem) return nil end end # Closes the modem connection def disconnect_dialup(nmodem = self.modem) if(nmodem) nmodem.flush nmodem.hangup nmodem.close end end # Reads until timeout looking for regexp def dialup_expect(regexp, timeout) res = { :match => false, :buffer => nil, } return res if ! self.modem res[:buffer] = '' time = Time.now while Time.now < time + timeout c = self.modem.getc res[:buffer] += c.chr if c if res[:buffer].match(regexp) != nil res[:match] = true while c c = self.modem.getc res[:buffer] += c.chr if c end return res end end return res end def dialup_getc return false if ! self.modem return self.modem.getc end def dialup_gets return false if ! self.modem buffer = '' c = self.modem.getc while c != 0x0a buffer += c c = self.modem.getc end buffer += c return buffer end def dialup_putc(c) return false if ! self.modem return self.modem.putc(c) end def dialup_puts(string) return false if ! self.modem return self.modem.puts(string) end def handler(nmodem = self.modem) # If the handler claims the modem, then we don't want it to get closed # during cleanup if ((rv = super) == Handler::Claimed) if (nmodem == self.modem) self.modem = nil end end return rv end attr_accessor :modem end end