diff --git a/lib/rex/post/meterpreter/channels/datagram.rb b/lib/rex/post/meterpreter/channels/datagram.rb index fc8c2e3323..9fb64d2765 100644 --- a/lib/rex/post/meterpreter/channels/datagram.rb +++ b/lib/rex/post/meterpreter/channels/datagram.rb @@ -33,8 +33,10 @@ class Datagram < Rex::Post::Meterpreter::Channel 'udp' end - def recvfrom_nonblock(length,flags = nil) - return [super(length, flags)[0], super(length, flags)[0]] + def recvfrom_nonblock(length, flags = 0) + data = super(length, flags)[0] + sockaddr = super(length, flags)[0] + [data, sockaddr] end def send(buf, flags, saddr) @@ -53,17 +55,12 @@ class Datagram < Rex::Post::Meterpreter::Channel ) if peerhost && peerport - # Maxlen here is 65507, to ensure we dont overflow, we need to write twice - # If the other side has a full 64k, handle by splitting up the datagram and - # writing multiple times along with the sockaddr. Consumers calling recvfrom - # repeatedly will buffer up all the pieces. - while data.length > 65507 - rsock.syswrite(data[0..65506]) - rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport)) - data = data - data[0..65506] - end - rsock.syswrite(data) - rsock.syswrite(Rex::Socket.to_sockaddr(peerhost,peerport)) + # A datagram can be maximum 65507 bytes, truncate longer messages + rsock.syswrite(data[0..65506]) + + # We write the data and sockaddr data to the local socket, the pop it + # back in recvfrom_nonblock. + rsock.syswrite(Rex::Socket.to_sockaddr(peerhost, peerport)) return true else return false