class TurboRex::Windows::ALPC::Transport
Constants
- DupObjectTypes
- Flags
- ImpersonationLevel
- Length
- MaxMessageLength
- MaxPoolUsage
- MaxSectionSize
- MaxTotalSectionSize
- MaxViewSize
- MemoryBandwidth
Public Class Methods
new(opts = {})
click to toggle source
# File lib/turborex/windows/alpc.rb, line 119 def initialize(opts = {}) @conn_handle = nil @communication_handle = [] end
Public Instance Methods
accept(opts = {})
click to toggle source
# File lib/turborex/windows/alpc.rb, line 324 def accept(opts = {}) communication_handle = APIProxy.alloc_c_type('HANDLE') alpc_port_attr = APIProxy.alloc_c_struct('ALPC_PORT_ATTRIBUTES') alpc_port_attr.Flags = 0 alpc_port_attr.MaxMessageLength = 0x1000 alpc_port_attr.MemoryBandwidth = 0 alpc_port_attr.MaxPoolUsage = 0xFFFFFFFF alpc_port_attr.MaxSectionSize = 0xFFFFFFFF alpc_port_attr.MaxViewSize = 0xFFFFFFFF alpc_port_attr.MaxTotalSectionSize = 0xFFFFFFFF alpc_port_attr.DupObjectTypes = 0xFFFFFFFF port_context = opts[:port_context] || 0 flags = opts[:flags] || 0 uniq_process = opts[:uniq_process] uniq_thread = opts[:uniq_thread] message_id = opts[:message_id] accept = 1 port_message = opts[:port_message] if port_message.nil? raise TurboRex::Exception::ALPC::ReplyMessageMismatch if uniq_process.nil? || uniq_thread.nil? || message_id.nil? port_message = PortMessage.new(alloc_size: 1) port_message.client_id = [uniq_process, uniq_thread] port_message.message_id = message_id end accept = 0 if opts[:refuse] ntstatus = APIProxy.ntalpcacceptconnectport(communication_handle, @conn_handle, flags, 0, alpc_port_attr, port_context, port_message.message, 0, accept) unless opts[:refuse] @communication_handle << communication_handle[0] [communication_handle[0], TinySDK.format_hex_ntstatus(ntstatus)] else TinySDK.format_hex_ntstatus(ntstatus) end end
close()
click to toggle source
# File lib/turborex/windows/alpc.rb, line 376 def close APIProxy.ntalpcdisconnectport(@conn_handle, 0) Metasm::WinAPI.closehandle @conn_handle @conn_handle = nil @communication_handle = [] end
connect(opts = {}, &block)
click to toggle source
# File lib/turborex/windows/alpc.rb, line 257 def connect(opts = {}, &block) unless wport_name = TurboRex::Windows::Utils.multibyte_to_widechar(opts[:port_name]) raise "Unable to convert characters to utf-16le encoding." end dest_str = APIProxy.alloc_c_ptr('UNICODE_STRING') APIProxy.rtlinitunicodestring(dest_str, wport_name) handle = APIProxy.alloc_c_type('HANDLE') alpc_port_attr = APIProxy.alloc_c_struct('ALPC_PORT_ATTRIBUTES') alpc_port_attr.Flags = TurboRex::Windows::ALPC::ALPC_PORFLG_ALLOW_LPC_REQUESTS alpc_port_attr.MaxMessageLength = 0x1000 alpc_port_attr.MemoryBandwidth = 0 alpc_port_attr.MaxPoolUsage = 0xFFFFFFFF alpc_port_attr.MaxSectionSize = 0xFFFFFFFF alpc_port_attr.MaxViewSize = 0xFFFFFFFF alpc_port_attr.MaxTotalSectionSize = 0xFFFFFFFF alpc_port_attr.DupObjectTypes = 0xFFFFFFFF alpc_port_attr.SecurityQos.Length = alpc_port_attr.SecurityQos.sizeof alpc_port_attr.SecurityQos.ImpersonationLevel = opts[:impersonation_level] || TurboRex::Windows::Constants::SecurityIdentification # timeout #large_integer = APIProxy.alloc_c_struct('LARGE_INTEGER') #large_integer.HighPart #large_integer.LowPart kport_message = PortMessage.new(payload: opts[:payload], alloc_size: (opts[:alloc_size]||3800)) obj_attr = opts[:obj_attr] || 0 flags = opts[:flags] || TurboRex::Windows::ALPC::ALPC_MSGFLG_SYNC_REQUEST # Don't use the ALPC_MSGFLG_SYNC_REQUEST flag when specific attributes timeout = opts[:timeout] || 0 retry_count = opts[:retry_count] || 0 buf_len = nil if message_size = kport_message.message_size buf_len = APIProxy.alloc_c_type('SIZE_T') buf_len[0] = message_size end out_msg_attr = 0 in_msg_attr = 0 if opts[:client_obj_attr] # perform to call NtAlpcConnectPortEx raise NotImplementedError else ntstatus = APIProxy.ntalpcconnectport(handle, dest_str, obj_attr, alpc_port_attr, flags, 0, kport_message.message, buf_len, out_msg_attr, in_msg_attr, timeout) kport_message.refresh_message formatted_status = TinySDK.format_hex_ntstatus(ntstatus) if formatted_status == 0xC0000041 puts "[-] The server refused the connection.(STATUS_PORT_CONNECTION_REFUSED)" retry_count.times do |i| puts "[*] Retrying..." ntstatus = APIProxy.ntalpcconnectport(handle, dest_str, obj_attr, alpc_port_attr, flags, 0, kport_message.message, buf_len, out_msg_attr, in_msg_attr, timeout) break unless TinySDK.format_hex_ntstatus(ntstatus) == 0xC0000041 end elsif !TinySDK.nt_success?(ntstatus) raise TurboRex::Exception::NotNTSuccess.new("0x#{formatted_status.to_s(16).upcase}") end end @communication_handle << handle[0] return handle[0], kport_message end
listen(conn_handle, opts = {}) { |port_message, buf_len, message_attr, format_hex_ntstatus(ntstatus, hex_str: true)| ... }
click to toggle source
# File lib/turborex/windows/alpc.rb, line 124 def listen(conn_handle, opts = {}, &block) @conn_handle = conn_handle #port_message = APIProxy.alloc_c_struct('PORT_MESSAGE') port_message = APIProxy.alloc_c_ary('BYTE', 0x1000) message_attr = MessageAttribute.new.struct buf_len = APIProxy.alloc_c_type('SIZE_T') buf_len[0] = port_message.sizeof retry_count = 0 while true begin # call NtAlpcSendWaitReceivePort will cause interpreter blocks, until you kill it. ntstatus = APIProxy.ntalpcsendwaitreceiveport(@conn_handle, opts[:flag] || 0, 0, 0, port_message, buf_len, message_attr, 0) yield(port_message, buf_len, message_attr, TinySDK.format_hex_ntstatus(ntstatus, hex_str: true)) if block_given? unless TinySDK.nt_success? ntstatus unless buf_len[0] == port_message.sizeof port_message = APIProxy.alloc_c_ary('BYTE', buf_len[0]) raise TurboRex::Exception::ALPC::BufferTooSmall else raise end end rescue => e if e.is_a? TurboRex::Exception::ALPC::BufferTooSmall raise TurboRex::Exception::ALPC::TooManyRetries if retry_count >= 2 retry_count += 1 retry else raise TurboRex::Exception::UnknownError end end kport_message = PortMessage.new(raw_message: port_message) break if (kport_message.type & 0xFFF) == TurboRex::Windows::ALPC::LPC_CONNECTION_REQUEST end return kport_message end
recv(handle, opts = {})
click to toggle source
# File lib/turborex/windows/alpc.rb, line 185 def recv(handle, opts = {}) port_message = opts.fetch(:port_message) { APIProxy.alloc_c_ary('BYTE', 0x1000) } buf_len = opts.fetch(:buf_len) { APIProxy.alloc_c_type('SIZE_T') } buf_len[0] = port_message.sizeof #message_attr = opts.fetch(:message_attr) { APIProxy.alloc_c_struct('ALPC_MESSAGE_ATTRIBUTES') } message_attr = MessageAttribute.new.struct flag = opts[:flag] || 0 retry_count = opts[:retry_count] || 0 timeout = opts[:timeout] || 0 begin ntstatus = APIProxy.ntalpcsendwaitreceiveport(handle, flag, 0, 0, port_message, buf_len, message_attr, timeout) unless TinySDK.nt_success? ntstatus unless buf_len[0] == port_message.sizeof port_message = APIProxy.alloc_c_ary('BYTE', buf_len[0]) raise TurboRex::Exception::ALPC::BufferTooSmall else raise end end rescue => e if e.is_a? TurboRex::Exception::ALPC::BufferTooSmall raise TurboRex::Exception::ALPC::TooManyRetries if retry_count >= 2 retry_count += 1 retry else raise TurboRex::Exception::NotNTSuccess.new(TinySDK.format_hex_ntstatus(ntstatus, hex_str: true)) end end PortMessage.new(raw_message: port_message) end
refuse_connect(opts = {})
click to toggle source
# File lib/turborex/windows/alpc.rb, line 371 def refuse_connect(opts = {}) opts[:refuse] = true accept(opts) end
send(handle, port_message, message_attr, opts = {})
click to toggle source
# File lib/turborex/windows/alpc.rb, line 170 def send(handle, port_message, message_attr, opts = {}) flag = opts[:flag] || 0 timeout = opts[:timeout] || 0 #buf_len = opts.fetch(:buf_len) { APIProxy.alloc_c_type('SIZE_T') } #buf_len = port_message.sizeof ntstatus = APIProxy.ntalpcsendwaitreceiveport(handle, flag, port_message, message_attr, 0, 0, 0, timeout) unless TinySDK.nt_success?(ntstatus) raise TurboRex::Exception::NotNTSuccess.new TinySDK.format_hex_ntstatus(ntstatus, hex_str: true) end TinySDK.format_hex_ntstatus ntstatus end
send_recv(handle, send_message, send_message_attr, recv_message_attr, opts = {})
click to toggle source
# File lib/turborex/windows/alpc.rb, line 218 def send_recv(handle, send_message, send_message_attr, recv_message_attr, opts = {}) port_message = opts.fetch(:port_message) { APIProxy.alloc_c_ary('BYTE', 0x1000) } buf_len = opts.fetch(:buf_len) { APIProxy.alloc_c_type('SIZE_T') } buf_len[0] = port_message.sizeof message_attr = recv_message_attr flag = opts[:flag] || TurboRex::Windows::ALPC::ALPC_MSGFLG_SYNC_REQUEST retry_count = opts[:retry_count] || 0 timeout = opts[:timeout] || 0 begin ntstatus = APIProxy.ntalpcsendwaitreceiveport(handle, flag, send_message, send_message_attr, port_message, buf_len, recv_message_attr, timeout) unless TinySDK.nt_success? ntstatus unless buf_len[0] == port_message.sizeof port_message = APIProxy.alloc_c_ary('BYTE', buf_len[0]) raise TurboRex::Exception::ALPC::BufferTooSmall else raise end end rescue => e if e.is_a? TurboRex::Exception::ALPC::BufferTooSmall raise TurboRex::Exception::ALPC::TooManyRetries if retry_count >= 2 retry_count += 1 retry else raise TurboRex::Exception::NotNTSuccess.new(TinySDK.format_hex_ntstatus(ntstatus, hex_str: true)) end end PortMessage.new(raw_message: port_message) end