From aa89d902e507e9c62863a01ef74d89ca3c655071 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Tue, 19 Nov 2024 15:56:14 -0500 Subject: [PATCH] Handle numeric addresses in .rex_getaddrinfo This makes the implementation more consistent with Addrinfo.getaddrinfo. --- lib/rex/socket.rb | 42 ++++++++++++++++++++++++++++------------- spec/rex/socket_spec.rb | 31 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/lib/rex/socket.rb b/lib/rex/socket.rb index 3a1ee0d..28039c2 100644 --- a/lib/rex/socket.rb +++ b/lib/rex/socket.rb @@ -940,26 +940,42 @@ def self.rex_gethostbyname(name, resolver: @@resolver) # @param resolver [Rex::Proto::DNS::CachedResolver] Resolver to query for the name # @return [Array] Array mimicking the native getaddrinfo return type def self.rex_getaddrinfo(name, resolver: @@resolver) - v4, v6 = self.rex_resolve_hostname(name, resolver: resolver) - # Build response array getaddrinfo = [] - v4.each do |a4| + + if name =~ /^\d+$/ && name.to_i.between?(0, 0xffffffff) getaddrinfo << Addrinfo.new( - self.to_sockaddr(a4.address.to_s, 0), + self.to_sockaddr(name.to_i, 0), ::Socket::AF_INET, ::Socket::SOCK_STREAM, - ::Socket::IPPROTO_TCP, - ) unless v4.empty? - end - v6.each do |a6| + ::Socket::IPPROTO_TCP + ) + elsif name =~ /^0x[0-9a-fA-F]+$/ && name.to_i(16).between?(0, 0xffffffff) getaddrinfo << Addrinfo.new( - self.to_sockaddr(a6.address.to_s, 0), - ::Socket::AF_INET6, + self.to_sockaddr(name.to_i(16), 0), + ::Socket::AF_INET, ::Socket::SOCK_STREAM, - ::Socket::IPPROTO_TCP, - ) unless v6.empty? + ::Socket::IPPROTO_TCP + ) + else + v4, v6 = self.rex_resolve_hostname(name, resolver: resolver) + v4.each do |a4| + getaddrinfo << Addrinfo.new( + self.to_sockaddr(a4.address.to_s, 0), + ::Socket::AF_INET, + ::Socket::SOCK_STREAM, + ::Socket::IPPROTO_TCP + ) unless v4.empty? + end + v6.each do |a6| + getaddrinfo << Addrinfo.new( + self.to_sockaddr(a6.address.to_s, 0), + ::Socket::AF_INET6, + ::Socket::SOCK_STREAM, + ::Socket::IPPROTO_TCP + ) unless v6.empty? + end end - return getaddrinfo + getaddrinfo end diff --git a/spec/rex/socket_spec.rb b/spec/rex/socket_spec.rb index 1bd619a..26915bf 100644 --- a/spec/rex/socket_spec.rb +++ b/spec/rex/socket_spec.rb @@ -198,6 +198,37 @@ it { expect { subject }.to raise_exception(::SocketError, 'getaddrinfo: nodename nor servname provided, or not known') } end + + context 'when passed in a numeric hostname' do + let(:mock_resolver) { double('Resolver', send: nil) } + + before(:each) do + described_class._install_global_resolver(mock_resolver) + expect(mock_resolver).not_to receive(:send) + end + + context 'when passed in a decimal hostname' do + let(:hostname) { '0' } + let(:response_addresses) { ['0.0.0.0'] } + + it { is_expected.to be_an(Array) } + it { expect(subject.size).to eq(1) } + it "should return the ASCII addresses" do + expect(subject).to include("0.0.0.0") + end + end + + context 'when passed in a decimal hostname' do + let(:hostname) { '0x0' } + let(:response_addresses) { ['0.0.0.0'] } + + it { is_expected.to be_an(Array) } + it { expect(subject.size).to eq(1) } + it "should return the ASCII addresses" do + expect(subject).to include("0.0.0.0") + end + end + end end describe '.portspec_to_portlist' do