IEC104 Client Utility - Metasploit


This page contains detailed information about how to use the auxiliary/client/iec104/iec104 metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.

Module Overview


Name: IEC104 Client Utility
Module: auxiliary/client/iec104/iec104
Source code: modules/auxiliary/client/iec104/iec104.rb
Disclosure date: -
Last modification time: 2020-05-12 22:15:21 +0000
Supported architecture(s): -
Supported platform(s): -
Target service / protocol: -
Target network port(s): 2404
List of CVEs: -

This module allows sending 104 commands.

Module Ranking and Traits


Module Ranking:

  • normal: The exploit is otherwise reliable, but depends on a specific version and can't (or doesn't) reliably autodetect. More information about ranking can be found here.

Basic Usage


msf > use auxiliary/client/iec104/iec104
msf auxiliary(iec104) > show targets
    ... a list of targets ...
msf auxiliary(iec104) > set TARGET target-id
msf auxiliary(iec104) > show options
    ... show and set options ...
msf auxiliary(iec104) > exploit

Required Options


  • RHOSTS: The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'

Knowledge Base


IEC104 Client for Metasploit


Definition


IEC 60870 part 5 is one of the IEC 60870 set of standards which define systems used for telecontrol (supervisory control and data acquisition) in electrical engineering and power system automation applications. Part 5 provides a communication profile for sending basic telecontrol messages between two systems, which uses permanent directly connected data circuits between the systems. The IEC Technical Committee 57 (Working Group 03) have developed a protocol standard for telecontrol, teleprotection, and associated telecommunications for electric power systems. The result of this work is IEC 60870-5. Five documents specify the base IEC 60870-5:

IEC 60870-5-104 (IEC 104) protocol is an extension of IEC 101 protocol with the changes in transport, network, link & physical layer services to suit the complete network access. The standard uses an open TCP/IP interface to network to have connectivity to the LAN (Local Area Network) and routers with different facility (ISDN, X.25, Frame relay etc.) can be used to connect to the WAN (Wide Area Network). Application layer of IEC 104 is preserved same as that of IEC 101 with some of the data types and facilities not used. There are two separate link layers defined in the standard, which is suitable for data transfer over Ethernet & serial line (PPP - Point-to-Point Protocol). The control field data of IEC104 contains various types of mechanisms for effective handling of network data synchronization.

Install


Create a new folder for the IEC104 module, place script in new folder

mkdir -p $HOME/.msf4/modules/auxiliary/client/iec104
cp iec104.rb $HOME/.msf4/modules/auxiliary/client/iec104/

Usage


Selection of module in msfconsole

msf > use auxiliary/client/iec104/iec104

Show module options

msf auxiliary(client/iec104/iec104) > show options

Module options (auxiliary/client/iec104/iec104):

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   ASDU_ADDRESS        1                yes       Common Address of ASDU
   COMMAND_ADDRESS     0                yes       Command Address / IOA Address
   COMMAND_TYPE        100              yes       Command Type
   COMMAND_VALUE       20               yes       Command Value
   ORIGINATOR_ADDRESS  0                yes       Originator Address
   RHOST                                yes       The target address
   RPORT               2404             yes       The target port (TCP)


Auxiliary action:

   Name          Description
   ----          -----------
   SEND_COMMAND  Send command to device

Usage Examples

Example of sending IEC104 general interrogation command This is using thde default setting for command type, address and value, this is connecting to an local IEC104 server simulator for demo purposes
msf auxiliary(client/iec104/iec104) > set rhost 127.0.0.1 rhost => 127.0.0.1 msf auxiliary(client/iec104/iec104) > run

[+] 127.0.0.1:2404 - Received STARTDT_ACT [] 127.0.0.1:2404 - Sending 104 command [+] 127.0.0.1:2404 - Parsing response: Interrogation command (C_IC_NA_1) [+] 127.0.0.1:2404 - TX: 0002 RX: 0000 [+] 127.0.0.1:2404 - CauseTx: 07 (Activation Confirmation) [+] 127.0.0.1:2404 - Parsing response: Single point information (M_SP_NA_1) [+] 127.0.0.1:2404 - TX: 0002 RX: 0002 [+] 127.0.0.1:2404 - CauseTx: 14 (Inrogen) [+] 127.0.0.1:2404 - IOA: 1 SIQ: 0x00 [+] 127.0.0.1:2404 - IOA: 2 SIQ: 0x00 [+] 127.0.0.1:2404 - IOA: 3 SIQ: 0x01 [+] 127.0.0.1:2404 - IOA: 4 SIQ: 0x00 [+] 127.0.0.1:2404 - Parsing response: Single point information (M_SP_NA_1) [+] 127.0.0.1:2404 - TX: 0002 RX: 0004 [+] 127.0.0.1:2404 - CauseTx: 14 (Inrogen) [+] 127.0.0.1:2404 - IOA: 7 SIQ: 0x00 [+] 127.0.0.1:2404 - Parsing response: Double point information (M_DP_NA_1) [+] 127.0.0.1:2404 - TX: 0002 RX: 0006 [+] 127.0.0.1:2404 - CauseTx: 14 (Inrogen) [+] 127.0.0.1:2404 - IOA: 6 SIQ: 0x02 [+] 127.0.0.1:2404 - Parsing response: Interrogation command (C_IC_NA_1) [+] 127.0.0.1:2404 - TX: 0002 RX: 0008 [+] 127.0.0.1:2404 - CauseTx: 0a (Termination Activation) [] 127.0.0.1:2404 - operation ended [] 127.0.0.1:2404 - Terminating Connection [+] 127.0.0.1:2404 - Received STOPDT_ACT [] Auxiliary module execution completed msf auxiliary(client/iec104/iec104) >

Example sending switching command IOA address to be switched is "5", the command type is a double command "46", command is for switching off without time value "5" Using local IEC 104 server simulator

msf auxiliary(client/iec104/iec104) > set rhost 127.0.0.1
rhost => 127.0.0.1
msf auxiliary(client/iec104/iec104) > set command_address 5
command_address => 5
msf auxiliary(client/iec104/iec104) > set command_type 46
command_type => 46
msf auxiliary(client/iec104/iec104) > set command_value 5
command_value => 5
msf auxiliary(client/iec104/iec104) > run

[+] 127.0.0.1:2404 - Received STARTDT_ACT
[*] 127.0.0.1:2404 - Sending 104 command
[+] 127.0.0.1:2404 -   Parsing response: Double command (C_DC_NA_1)
[+] 127.0.0.1:2404 -     TX: 0002 RX: 0000
[+] 127.0.0.1:2404 -     CauseTx: 07 (Activation Confirmation)
[+] 127.0.0.1:2404 -     IOA: 5 DCO: 0x05
[+] 127.0.0.1:2404 -   Parsing response: Single point information with time (M_SP_TB_1)
[+] 127.0.0.1:2404 -     TX: 0002 RX: 0002
[+] 127.0.0.1:2404 -     CauseTx: 03 (Spontaneous)
[+] 127.0.0.1:2404 -     IOA: 3 SIQ: 0x00
[+] 127.0.0.1:2404 -     Timestamp: 2018-03-30 21:39:52.930
[+] 127.0.0.1:2404 -   Parsing response: Double command (C_DC_NA_1)
[+] 127.0.0.1:2404 -     TX: 0002 RX: 0004
[+] 127.0.0.1:2404 -     CauseTx: 0a (Termination Activation)
[+] 127.0.0.1:2404 -     IOA: 5 DCO: 0x05
[*] 127.0.0.1:2404 - operation ended
[*] 127.0.0.1:2404 - Terminating Connection
[+] 127.0.0.1:2404 - Received STOPDT_ACT
[*] Auxiliary module execution completed
msf auxiliary(client/iec104/iec104) >

Go back to menu.

Msfconsole Usage


Here is how the client/iec104/iec104 auxiliary module looks in the msfconsole:

msf6 > use auxiliary/client/iec104/iec104

msf6 auxiliary(client/iec104/iec104) > show info

       Name: IEC104 Client Utility
     Module: auxiliary/client/iec104/iec104
    License: Metasploit Framework License (BSD)
       Rank: Normal

Provided by:
  Michael John <[email protected]>

Available actions:
  Name          Description
  ----          -----------
  SEND_COMMAND  Send command to device

Check supported:
  No

Basic options:
  Name                Current Setting  Required  Description
  ----                ---------------  --------  -----------
  ASDU_ADDRESS        1                yes       Common Address of ASDU
  COMMAND_ADDRESS     0                yes       Command Address / IOA Address
  COMMAND_TYPE        100              yes       Command Type
  COMMAND_VALUE       20               yes       Command Value
  ORIGINATOR_ADDRESS  0                yes       Originator Address
  RHOSTS                               yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
  RPORT               2404             yes       The target port (TCP)

Description:
  This module allows sending 104 commands.

Module Options


This is a complete list of options available in the client/iec104/iec104 auxiliary module:

msf6 auxiliary(client/iec104/iec104) > show options

Module options (auxiliary/client/iec104/iec104):

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   ASDU_ADDRESS        1                yes       Common Address of ASDU
   COMMAND_ADDRESS     0                yes       Command Address / IOA Address
   COMMAND_TYPE        100              yes       Command Type
   COMMAND_VALUE       20               yes       Command Value
   ORIGINATOR_ADDRESS  0                yes       Originator Address
   RHOSTS                               yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT               2404             yes       The target port (TCP)

Auxiliary action:

   Name          Description
   ----          -----------
   SEND_COMMAND  Send command to device

Advanced Options


Here is a complete list of advanced options supported by the client/iec104/iec104 auxiliary module:

msf6 auxiliary(client/iec104/iec104) > show advanced

Module advanced options (auxiliary/client/iec104/iec104):

   Name            Current Setting  Required  Description
   ----            ---------------  --------  -----------
   CHOST                            no        The local client address
   CPORT                            no        The local client port
   ConnectTimeout  10               yes       Maximum number of seconds to establish a TCP connection
   Proxies                          no        A proxy chain of format type:host:port[,type:host:port][...]
   SSL             false            no        Negotiate SSL/TLS for outgoing connections
   SSLCipher                        no        String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"
   SSLVerifyMode   PEER             no        SSL verification method (Accepted: CLIENT_ONCE, FAIL_IF_NO_PEER_CERT, NONE, PEER)
   SSLVersion      Auto             yes       Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate) (Accepted: Auto, TLS, SSL23, SSL3, TLS1, TLS1.1, TLS1.2)
   VERBOSE         false            no        Enable detailed status messages
   WORKSPACE                        no        Specify the workspace for this module

Auxiliary Actions


This is a list of all auxiliary actions that the client/iec104/iec104 module can do:

msf6 auxiliary(client/iec104/iec104) > show actions

Auxiliary actions:

   Name          Description
   ----          -----------
   SEND_COMMAND  Send command to device

Evasion Options


Here is the full list of possible evasion options supported by the client/iec104/iec104 auxiliary module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):

msf6 auxiliary(client/iec104/iec104) > show evasion

Module evasion options:

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   TCP::max_send_size  0                no        Maxiumum tcp segment size.  (0 = disable)
   TCP::send_delay     0                no        Delays inserted before every send.  (0 = disable)

Go back to menu.

Error Messages


This module may fail with the following error messages:

Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.

Error


Here is a relevant code snippet related to the "Error" error message:

44:	  def send_frame(data)
45:	    begin
46:	      sock.put(data)
47:	      sock.get(-1, sock.def_read_timeout)
48:	    rescue StandardError => e
49:	      print_error("Error:" + e.message)
50:	    end
51:	  end
52:	
53:	  # ACPI formats:
54:	  # TESTFR_CON = '\x83\x00\x00\x00'

(Type Identification Unknown)


Here is a relevant code snippet related to the "(Type Identification Unknown)" error message:

116:	    elsif response_data[7].eql?("\x06")
117:	      print_good("    CauseTx: " + response_data[7].unpack('H*').first + " (Activiation)")
118:	
119:	    # 104 error messages
120:	    elsif response_data[7].eql?("\x2c")
121:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (Type Identification Unknown)")
122:	    elsif response_data[7].eql?("\x2d")
123:	      print_error("   CauseTx: " + response_data[7].unpack('H*').first + " (Cause Unknown)")
124:	    elsif response_data[7].eql?("\x2e")
125:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (ASDU Address Unknown)")
126:	    elsif response_data[7].eql?("\x2f")

(Cause Unknown)


Here is a relevant code snippet related to the "(Cause Unknown)" error message:

118:	
119:	    # 104 error messages
120:	    elsif response_data[7].eql?("\x2c")
121:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (Type Identification Unknown)")
122:	    elsif response_data[7].eql?("\x2d")
123:	      print_error("   CauseTx: " + response_data[7].unpack('H*').first + " (Cause Unknown)")
124:	    elsif response_data[7].eql?("\x2e")
125:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (ASDU Address Unknown)")
126:	    elsif response_data[7].eql?("\x2f")
127:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (IOA Address Unknown)")
128:	    elsif response_data[7].eql?("\x6e")

(ASDU Address Unknown)


Here is a relevant code snippet related to the "(ASDU Address Unknown)" error message:

120:	    elsif response_data[7].eql?("\x2c")
121:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (Type Identification Unknown)")
122:	    elsif response_data[7].eql?("\x2d")
123:	      print_error("   CauseTx: " + response_data[7].unpack('H*').first + " (Cause Unknown)")
124:	    elsif response_data[7].eql?("\x2e")
125:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (ASDU Address Unknown)")
126:	    elsif response_data[7].eql?("\x2f")
127:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (IOA Address Unknown)")
128:	    elsif response_data[7].eql?("\x6e")
129:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (Unknown Comm Address ASDU)")
130:	    end

(IOA Address Unknown)


Here is a relevant code snippet related to the "(IOA Address Unknown)" error message:

122:	    elsif response_data[7].eql?("\x2d")
123:	      print_error("   CauseTx: " + response_data[7].unpack('H*').first + " (Cause Unknown)")
124:	    elsif response_data[7].eql?("\x2e")
125:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (ASDU Address Unknown)")
126:	    elsif response_data[7].eql?("\x2f")
127:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (IOA Address Unknown)")
128:	    elsif response_data[7].eql?("\x6e")
129:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (Unknown Comm Address ASDU)")
130:	    end
131:	  end
132:	

(Unknown Comm Address ASDU)


Here is a relevant code snippet related to the "(Unknown Comm Address ASDU)" error message:

124:	    elsif response_data[7].eql?("\x2e")
125:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (ASDU Address Unknown)")
126:	    elsif response_data[7].eql?("\x2f")
127:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (IOA Address Unknown)")
128:	    elsif response_data[7].eql?("\x6e")
129:	      print_error("    CauseTx: " + response_data[7].unpack('H*').first + " (Unknown Comm Address ASDU)")
130:	    end
131:	  end
132:	
133:	  ##############################################################################################################
134:	  # following functions parse different 104 ASDU messages and prints it content, not all messages of the standard are currently implemented

No answer


Here is a relevant code snippet related to the "No answer" error message:

541:	    # Uncomment for debugging
542:	    # print_status("Sending: " + make_apci(asdu).unpack('H*').first)
543:	    response = send_frame(make_apci(asdu))
544:	
545:	    if response.nil?
546:	      print_error("No answer")
547:	    else
548:	      parse_response(response)
549:	    end
550:	    print_status("operation ended")
551:	  end

Error


Here is a relevant code snippet related to the "Error" error message:

554:	    $rx = 0
555:	    $tx = 0
556:	    begin
557:	      connect
558:	    rescue StandardError => e
559:	      print_error("Error:" + e.message)
560:	      return
561:	    end
562:	
563:	    # send STARTDT_CON to activate connection
564:	    response = send_frame(startcon)

Could not connect to 104 service


Here is a relevant code snippet related to the "Could not connect to 104 service" error message:

561:	    end
562:	
563:	    # send STARTDT_CON to activate connection
564:	    response = send_frame(startcon)
565:	    if response.nil?
566:	      print_error("Could not connect to 104 service")
567:	      return
568:	    else
569:	      parse_response(response)
570:	    end
571:	

Invalid ACTION


Here is a relevant code snippet related to the "Invalid ACTION" error message:

572:	    # send the 104 command
573:	    case action.name
574:	    when "SEND_COMMAND"
575:	      func_send_command
576:	    else
577:	      print_error("Invalid ACTION")
578:	    end
579:	
580:	    # send STOPDT_CON to terminate connection
581:	    response = send_frame(stopcon)
582:	    if response.nil?

Terminating Connection


Here is a relevant code snippet related to the "Terminating Connection" error message:

578:	    end
579:	
580:	    # send STOPDT_CON to terminate connection
581:	    response = send_frame(stopcon)
582:	    if response.nil?
583:	      print_error("Terminating Connection")
584:	      return
585:	    else
586:	      print_status("Terminating Connection")
587:	      parse_response(response)
588:	    end

Error


Here is a relevant code snippet related to the "Error" error message:

586:	      print_status("Terminating Connection")
587:	      parse_response(response)
588:	    end
589:	
590:	    begin
591:	      disconnect
592:	    rescue StandardError => e
593:	      print_error("Error:" + e.message)
594:	    end
595:	  end
596:	end

Go back to menu.


Go back to menu.

See Also


Check also the following modules related to this module:

Authors


  • Michael John <mjohn.info[at]gmail.com>

Version


This page has been produced using Metasploit Framework version 6.1.27-dev. For more modules, visit the Metasploit Module Library.

Go back to menu.