CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/telephony/modem.rb
Views: 11766
1
module Telephony
2
3
class Modem
4
attr_accessor :serialport, :sp, :sock
5
attr_accessor :baud, :data_bits, :parity, :stop_bits
6
attr_accessor :flowcontrol
7
attr_accessor :display
8
attr_reader :commandstate
9
10
NONE = SerialPort::NONE
11
HARD = SerialPort::HARD
12
SOFT = SerialPort::SOFT
13
SPACE = SerialPort::SPACE
14
MARK = SerialPort::MARK
15
EVEN = SerialPort::EVEN
16
ODD = SerialPort::ODD
17
18
def initialize(serialport = '/dev/ttyS0')
19
@serialport = serialport || '/dev/ttyS0'
20
@sp = nil
21
@baud = 2400
22
@data_bits = 8
23
@parity = NONE
24
@stop_bits = 1
25
@flowcontrol = NONE
26
@commandstate = true
27
@display = true
28
29
# Connect to and init modem
30
begin
31
#print("Opening Serial Port #{@serialport} (#{@baud} #{@data_bits}#{@parity}#{@stop_bits})\r\n")
32
@sp = SerialPort.create(serialport)
33
@sp.modem_params = {'baud' => @baud, 'data_bits' => @data_bits, 'parity' => @parity, 'stop_bits' => @stop_bits}
34
@sp.read_timeout = -1
35
@sp.rts = 1
36
@sp.dtr = 1 if sp.respond_to?:dtr= # unsupported in windows ):
37
@sock = @sp
38
@sock.extend(Rex::IO::Stream)
39
@sock.extend(Rex::IO::StreamAbstraction::Ext)
40
rescue ::Interrupt
41
raise $!
42
rescue ::Exception => e
43
print("Error opening serial port #{@serialport} : #{e.class} #{e} #{e.backtrace}\r\n")
44
return true
45
end
46
end
47
48
# This provides pass-through method support for the SerialPort object
49
def method_missing(meth, *args); self.sp.send(meth, *args); end
50
51
def put_command(command, timeout)
52
switchback = false
53
if ! @commandstate
54
commandstate
55
switchback = true
56
end
57
58
begin
59
self.flush # TODO: This doesn't work in exploits for some reason but it does in aux modules
60
@sp.puts command + "\r\n"
61
echo = get_response(timeout) # read back the echoed command (not really a response)
62
63
rescue ::Interrupt
64
raise $!
65
rescue ::Exception => e
66
print("Error sending command to modem: #{e.class} #{e} #{e.backtrace}\r\n")
67
return
68
end
69
70
result = get_response(timeout)
71
72
datastate if switchback == true
73
74
return result
75
end
76
77
def get_response(timeout)
78
time = Time.now
79
80
@sp.read_timeout = -1
81
result = ''
82
while Time.now <= time + timeout
83
# get a char from the modem
84
begin
85
c = @sp.getc
86
if c
87
c = c.chr
88
result += c
89
if c == "\n"
90
result = result.chomp
91
break if result.length > 0
92
end
93
end
94
rescue ::Interrupt
95
raise $!
96
rescue ::Exception => e
97
print("Error reading from modem: #{e.class} #{e} #{e.backtrace}\r\n")
98
return
99
end
100
end
101
102
if result.length > 0
103
print "[m] #{result}\r\n" if @display
104
else
105
result = 'TIMEOUT'
106
end
107
108
return result
109
end
110
111
def commandstate
112
if ! @commandstate
113
@sp.break 10 # tenths of a second
114
@sp.puts '+++'
115
@sp.break 10 # tenths of a second
116
result = get_response(3)
117
if result != 'OK'
118
print( "Error switching to command state: FAILED\r\n" )
119
return false
120
else
121
@commandstate = true
122
end
123
end
124
125
return true
126
end
127
128
def datastate
129
if @commandstate
130
result = put_command('ATO0', 3)
131
if result =~ /CONNECT/i
132
@commandstate = false
133
else
134
print( "Error switching to data state: FAILED\r\n" )
135
return false
136
end
137
end
138
139
return true
140
end
141
142
def hangup
143
flush
144
if @commandstate == true
145
#print( "Hanging up... (commandstate ATH0)\r\n" )
146
result = put_command('ATH0', 3)
147
return true if result == 'OK' or result == 'NO CARRIER'
148
else
149
if @sp.respond_to?:dtr= # unsupported in windows ):
150
#print( "Hanging up... (DTR = 0)\r\n" )
151
@sp.dtr = 0
152
sleep 0.75
153
@sp.dtr = 1
154
result = get_response(3)
155
@commandstate = true if result == 'NO CARRIER'
156
return true
157
else
158
#print( "Hanging up... (datastate ATH0)\r\n" )
159
commandstate
160
result = put_command('ATH0', 3)
161
return true if result == 'OK'
162
end
163
end
164
165
return false
166
end
167
168
# flush any stale data in the read buffer
169
def flush
170
@sp.read_timeout = -1
171
while @sp.getc; end
172
end
173
174
# TODO: convert all calls to Modem.params to Modem.modem_params and remove this def
175
def params=(params)
176
@sp.modem_params = params
177
end
178
179
end
180
181
end
182
183