Manipulating UDP sender's address

Is there a way, in general, to “fake” a sender’s IP address when sending
a UDP packet? I need to receive a UDP packet on one port and redirect it
to another “pretending” that it is from the original sender.

Even if it is not possible from Ruby now, I would appreciate any
pointers so that I can make an extension to do it (if at all possible).

Gennady.

Spoofing seems to work pretty good in Ruby (see below). You would have
to recalculate the ip header checksum (and probably also the udp
checksum), if you want to change the source address of a given packet .

BTW, the ipchecksum algorithm is really beautiful in Ruby:

def ipchecksum(data)
checksum = data.unpack(“n*”).inject(0) { |s, x| s + x }
((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end

Here comes my little hack:

require ‘socket’

class UDPSpoofer

@@id = 1234 - 1

def initialize
    @s = Socket.new(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
    @s.setsockopt(Socket::IPPROTO_IP, Socket::IP_HDRINCL, 1)
end

def send(src, sport, dst, dport, payload = '')
    dst_numeric = dst.split(/\./).map { |x| x.to_i }
    to = [ Socket::AF_INET,
        dport, dst_numeric, '' ].flatten.pack('snCCCCa8')
    packet = make_ip_header([
        [ '01000101', 'B8' ],                # version, hlen
        [ 0, 'C' ],                          # tos
        [ 28 + payload.size, 'n' ],          # total len
        [ @@id += 1, 'n' ],                  # id
        [ 0, 'n' ],                          # flags, offset
        [ 64, 'C' ],                         # ttl
        [ 17, 'C' ],                         # protocol
        [ 0, 'n' ],                          # checksum
        [ ip2long(src), 'N' ],               # source
        [ ip2long(dst), 'N' ],               # destination
    ])
    packet << make_udp_header([
        [ sport, 'n'],                        # source port
        [ dport, 'n' ],                       # destination port
        [ 8 + payload.size, 'n' ],            # len
        [ 0, 'n' ]                            # checksum (mandatory)
    ])
    packet << payload
    @s.send(packet, 0, to)
end

private

def ip2long(ip)
    long = 0
    ip.split(/\./).reverse.each_with_index do |x, i|
        long += x.to_i << (i * 8)
    end
    long
end

def ipchecksum(data)
    checksum = data.unpack("n*").inject(0) { |s, x| s + x }
    ((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end

def make_ip_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data_str = data.pack(template)
    checksum = ipchecksum(data_str)
    data[-3] = checksum
    data.pack(template)
end

def make_udp_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data.pack(template)
end

def ip2long(ip)
    long = 0
    ip.split(/\./).reverse.each_with_index do |x, i|
        long += x.to_i << (i * 8)
    end
    long
end

def ipchecksum(data)
    checksum = data.unpack("n*").inject(0) { |s, x| s + x }
    ((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end

def make_ip_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data_str = data.pack(template)
    checksum = ipchecksum(data_str)
    data[-3] = checksum
    data.pack(template)
end

def make_udp_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data.pack(template)
end

end

us = UDPSpoofer.new
loop do # fire!
us.send(‘192.168.1.66’, 666, ‘192.168.1.1’, 42, ‘i am on the ether’)
end

···

On 2004-03-17 04:14:18 +0900, Gennady wrote:

Is there a way, in general, to “fake” a sender’s IP address when
sending a UDP packet? I need to receive a UDP packet on one port and
redirect it to another “pretending” that it is from the original
sender.

Even if it is not possible from Ruby now, I would appreciate any
pointers so that I can make an extension to do it (if at all possible).


lambda { |c| lambda { |f| f[f] } [ lambda { |f| c[lambda { |x| f[f] } ] }] }

“Florian Frank” flori@nixe.ping.de wrote in message

Here comes my little hack:

require ‘socket’

class UDPSpoofer

@@id = 1234 - 1

def initialize
    @s = Socket.new(Socket::PF_INET, Socket::SOCK_RAW,

Socket::IPPROTO_RAW)

    @s.setsockopt(Socket::IPPROTO_IP, Socket::IP_HDRINCL, 1)

^^^^^^^^^^^^^^^^^^
Where is this constant defined ? When I run this I get:

···

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\atest>ruby -v
ruby 1.8.1 (2004-01-27) [i386-mswin32]

C:\atest>ruby udp_spoofer.rb
udp_spoofer.rb:17:in initialize': uninitialized constant Socket::IP_HDRINCL (NameError) from udp_spoofer.rb:122:in new’
from udp_spoofer.rb:122

C:\atest>

Hi, Florian

Thank you so very much!!! I expected only some tips, but got a complete
working solution. It is amazing, I am impressed. It works like a charm.

I am so sorry I could not thank you immediately, I was out for several
days.

Thanks a lot once again,
Gennady.

P.S.
BTW, in your post’s UDPSpoofer there’re 2 identical sets of methods
ip2long, ipchecksum, make_ip_header, make_udp_header :wink:

Florian Frank wrote:

···

On 2004-03-17 04:14:18 +0900, Gennady wrote:

Is there a way, in general, to “fake” a sender’s IP address when
sending a UDP packet? I need to receive a UDP packet on one port and
redirect it to another “pretending” that it is from the original
sender.

Even if it is not possible from Ruby now, I would appreciate any
pointers so that I can make an extension to do it (if at all possible).

Spoofing seems to work pretty good in Ruby (see below). You would have
to recalculate the ip header checksum (and probably also the udp
checksum), if you want to change the source address of a given packet .

BTW, the ipchecksum algorithm is really beautiful in Ruby:

def ipchecksum(data)
checksum = data.unpack(“n*”).inject(0) { |s, x| s + x }
((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end

Here comes my little hack:

require ‘socket’

class UDPSpoofer

@@id = 1234 - 1

def initialize
    @s = Socket.new(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
    @s.setsockopt(Socket::IPPROTO_IP, Socket::IP_HDRINCL, 1)
end

def send(src, sport, dst, dport, payload = '')
    dst_numeric = dst.split(/\./).map { |x| x.to_i }
    to = [ Socket::AF_INET,
        dport, dst_numeric, '' ].flatten.pack('snCCCCa8')
    packet = make_ip_header([
        [ '01000101', 'B8' ],                # version, hlen
        [ 0, 'C' ],                          # tos
        [ 28 + payload.size, 'n' ],          # total len
        [ @@id += 1, 'n' ],                  # id
        [ 0, 'n' ],                          # flags, offset
        [ 64, 'C' ],                         # ttl
        [ 17, 'C' ],                         # protocol
        [ 0, 'n' ],                          # checksum
        [ ip2long(src), 'N' ],               # source
        [ ip2long(dst), 'N' ],               # destination
    ])
    packet << make_udp_header([
        [ sport, 'n'],                        # source port
        [ dport, 'n' ],                       # destination port
        [ 8 + payload.size, 'n' ],            # len
        [ 0, 'n' ]                            # checksum (mandatory)
    ])
    packet << payload
    @s.send(packet, 0, to)
end

private

def ip2long(ip)
    long = 0
    ip.split(/\./).reverse.each_with_index do |x, i|
        long += x.to_i << (i * 8)
    end
    long
end

def ipchecksum(data)
    checksum = data.unpack("n*").inject(0) { |s, x| s + x }
    ((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end

def make_ip_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data_str = data.pack(template)
    checksum = ipchecksum(data_str)
    data[-3] = checksum
    data.pack(template)
end

def make_udp_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data.pack(template)
end

def ip2long(ip)
    long = 0
    ip.split(/\./).reverse.each_with_index do |x, i|
        long += x.to_i << (i * 8)
    end
    long
end

def ipchecksum(data)
    checksum = data.unpack("n*").inject(0) { |s, x| s + x }
    ((checksum >> 16) + (checksum & 0xffff)) ^ 0xffff
end

def make_ip_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data_str = data.pack(template)
    checksum = ipchecksum(data_str)
    data[-3] = checksum
    data.pack(template)
end

def make_udp_header(parts)
    template = ''
    data = []
    parts.each do |part|
        data += part[0..-2]
        template << part[-1]
    end
    data.pack(template)
end

end

us = UDPSpoofer.new
loop do # fire!
us.send(‘192.168.1.66’, 666, ‘192.168.1.1’, 42, ‘i am on the ether’)
end

The raw sockets are pretty new in Windows XP. They are perhaps not yet
fully supported. It could also be possible that the Ruby configure
script makes an error here. You could perhaps find out if you’d look
into your header files.

···

On 2004-03-17 22:14:39 +0900, Shashank Date wrote:

Where is this constant defined ? When I run this I get:


DATA.rewind and puts DATA.read[/\x4a.*/] # This prints: Just another Ruby Hacker
END

Thank you so very much!!! I expected only some tips, but got a complete
working solution. It is amazing, I am impressed. It works like a charm.

Cool.

P.S.
BTW, in your post’s UDPSpoofer there’re 2 identical sets of methods
ip2long, ipchecksum, make_ip_header, make_udp_header :wink:

Woah! I think that must have happened, because I copied and pasted them
from the public part of the class to below the “private” part twice
after I was done. The good side is that, the script is much shorter now.
:wink:

···

On Fri, 2004-03-19 at 17:25, Gennady wrote:


="puts’=‘+.inspect+‘;’+";puts’='+.inspect+‘;’+_