I'm trying to send a spoofed time to a Windows machine when it requests time from the NTP server.
My server so far will display packets and send back data, however I can't seem to figure out exactly what I need to send to give Windows a fake time. I've tried capturing legitimate packets to send but failed.
In this example I'm just sending white space, I'm trying to figure out what data to send to tell the computer for example the time is 10:00AM when it's actually 12PM.
I intend to spoof DNS queries on a LAN to redirect them to this server which will respond with an incorrect time.
I've heard it can be done but have never seen a tool to do it, so that's what I'm trying to do now.
require 'socket'
class UDPServer
def initialize(port)
#port = port
end
def start
#socket = UDPSocket.new
#socket.bind('', #port)
data = " "
while true
packet = #socket.recvfrom(1024)
puts packet
#socket.send("${data}", 0, '10.0.0.16', "#{#port}")
end
end
end
server = UDPServer.new(123)
server.start
It can be done. You need to reply to the clients requests. In that reply, you will need to use the (you code does not do that):
T1 = client timestamp at time of departure of request packet from client
and
T2 = server timestamp at time of ARRIVAL of request packet at server
and
T3 = server timestamp at time of departure of REPLY packet from server (ca be thee same s T2).
I don't see that done in you code. Also, the rest of the pkt need to be "OK"--not sure if yours is (seems like no).
Related
I've read some things suggesting that because of the design of TCP this might not be possible (such as: Java socket API: How to tell if a connection has been closed?), but I'm trying to find explicit confirmation. I have a basic TCP server that accepts connections, and a client that initiates a connection, sends a message, and then closes the connection. Is there a way for the server to know that the client closed the connection?
I found some suggestions to look into checking the file descriptors for the sockets (source: How to check if a given file descriptor stored in a variable is still valid?), using the kernel select command (source: https://bytes.com/topic/c/answers/866296-detecting-if-file-descriptor-closed) as well as using recv to check if the client returns 0 (source: http://man7.org/linux/man-pages/man2/recv.2.html#RETURN_VALUE), but these do not seem to work, at least not when called by Ruby. To test this, I wrote a basic server and client:
test_server.rb
require 'socket'
require 'fcntl'
TIMEOUT = 5
server = TCPServer.new('localhost', 8080)
puts "Starting server"
loop do
client = server.accept
puts "New client: #{client}"
puts "** before closed #{Time.now.to_i} closed=#{client.closed?}"
result = IO.select([client], nil, nil, TIMEOUT)
puts "select result=#{result}"
fd = client.fcntl(Fcntl::F_GETFD, 0)
puts "client fd=#{fd}"
stuff = client.recv(30)
puts "received '#{stuff}'"
begin
r = client.recv(1)
rescue => e
end
puts "received #{r} nil?=#{r.nil?}"
sleep 3
puts "** after closed #{Time.now.to_i} closed=#{client.closed?}"
result = IO.select([client], nil, nil, TIMEOUT)
puts "select result=#{result}"
fd = client.fcntl(Fcntl::F_GETFD, 0)
puts "client fd=#{fd}"
begin
r = client.recv(1)
rescue => e
end
puts "received #{r} nil?=#{r.nil?}"
puts "done!"
end
test_client.rb
require 'socket'
class Client
def initialize
#socket = tcp_socket
end
def tcp_socket
Thread.current[:socket] = TCPSocket.new("localhost", 8080)
end
def send(s, args={})
puts "sending str '#{s}'"
nbytes = #socket.send(s, 0)
puts "received #{nbytes} bytes"
sleep 1
#socket.close
puts "done at #{Time.now.to_i}: #{#socket.closed?}"
end
end
msg = 'hello world this is my message'
server = Client.new
server.send(msg)
The client sends a 30-byte message, waits 1s, then closes the connection.
The server accepts the connection, calls select and fcntl on it to check its status, receives the message, tries to read 1 more byte, sleeps for 3 seconds, then calls select and fcntl and again tries to read 1 byte. The intent here is to check if anything changes that the server can see before and after the client closed the connection (hence the 3-second sleep). The result I get from running the server and then the client code is:
Starting server
New client: #<TCPSocket:0x00007fa0930f0880>
** before closed 1578005539 closed=false
select result=[[#<TCPSocket:fd 10>], [], []]
client fd=1
received 'hello world this is my message'
received nil?=false
** after closed 1578005543 closed=false
select result=[[#<TCPSocket:fd 10>], [], []]
client fd=1
received nil?=false
done!
Before and after the client closed the connection, select still sees the socket as readable, the underlying file descriptor does not change, and recv returns empty string (It's possible the kernel call is returning 0 as specified in the man-page but Ruby is capturing that, and if so I don't know how to see it.). Thus none of these seem to be a reliable indicator of whether the connection was closed from the other side. Is there something I'm missing?
I have seen some other suggestions to incorporate a regular heartbeat back to the client, but I'm wondering if there's a way to avoid that. Reason is that I'm trying to accommodate a case where the client may be sending a message in several pieces separated by a delay (e.g. 100 bytes at 1 second each byte). If the server sends a heartbeat message in the middle of that operation and listens for an OK, I presume the client has to be listening for the heartbeat as well and send its OK back, separate from the ongoing message send, and in my test case, I can't change the client to do that.
I have seen some other suggestions to incorporate a regular heartbeat back to the client, but I'm wondering if there's a way to avoid that.
A heartbeat (ping) is the only viable solution.
There is no way to reliably know if the connection is live except by trying to send data over the wire.
Since TCP/IP doesn't require any traffic when data isn't being sent (or received), there's no way for the TCP stack (not even in the OS kernel) to know if the connection is "live" without attempting to exchange data over the wire.
Some connections will close gracefully, allowing the TCP stack to recognize that the connection was closed - but this isn't always true (you can read more about "half-open" or "half-closed" connections).
For this reason, all servers implement a timeout / ping mechanism to test for lost connectivity.
I'm trying to accommodate a case where the client may be sending a message in several pieces separated by a delay (e.g. 100 bytes at 1 second each byte)...
Remember that TCP/IP is a stream based protocol, not a message based protocol.
This means that your 100 bytes might arrive fragmented or they might be combined with a previous message.
If you're sending messages (rather than streaming data), you need - by design - to mark message boundaries.
Since these message boundaries must be marked, it becomes relatively easy to add a message type marker (to mark ping/pong messages).
You can observer the WebSocket protocol message format to learn more about message based protocol design using a TCP/IP (streamed) connection.
I have an asic computer in my house that I don't really have control over, but I can talk to its API over TCP (CGminer OS). I'm trying to record data from it:
socket = TCPSocket.open(address, port)
loop do
sleep 1
socket.write(command)
response = socket.read
end
The first iteration of this loop returns the data as expected, the second is an empty string. I'm pretty clueless about sockets and not sure what I need to do. I know I can reopen the socket each iteration if I have to, I'm just hoping I don't need to.
Solution is to just reopen the socket.
loop do
socket = TCPSocket.open(address, port)
response = socket.read
socket.close
end
I'm investigating man-in-the-middle attacks and trying to pipe raw HTTPS data (that is, before decryption) to and from a pair of sockets. For now, I just want to listen to the encrypted traffic, so I want any data going out to go from my web browser, through my script, and out to the intended recipient, and any data coming in to do the reverse. Ideally I'd just like to connect the incoming and outgoing sockets together and have them transfer data between each other automatically, but I haven't seen a way to do it in Ruby so I have been using the following, which I took from How can I create a two-way SSL socket in Ruby .
Here is my code:
def socketLoop(incoming, outgoing)
loop do
puts "selecting"
ready = IO.select([outgoing, incoming])
if ready[0].include?(incoming)
data_to_send = incoming.read_nonblock(32768)
outgoing.write(data_to_send)
puts "sent out"
puts data_to_send
end
if ready[0].include?(outgoing)
data_received = outgoing.read_nonblock(32768)
incoming.write(data_received)
puts "read in"
puts data_received
break if outgoing.nil? || outgoing.closed? || outgoing.eof?
end
end
end
server = TCPServer.open(LISTENING_PORT)
loop {
Thread.start(server.accept){ |incoming|
outgoing = TCPSocket.new(TARGET_IP, TARGET_PORT)
socketLoop(incoming, outgoing)
outgoing.close # Disconnect from target
incoming.close # Disconnect from the client
}
}
It works beautifully for HTTP but for HTTPS, my browser keeps spinning, and the output seems to indicate that at least part of a certificate has been sent over, but not much more. I presume I was being naïve to think that it would work for SSL, but as far as I know it uses TCP as the transport layer so I'm not sure why it doesn't work. Is it possible to get the raw data in this way? Is it an issue with my Ruby or have I made some wrong assumptions? I'd prefer not to use a system-wide packet sniffer if possible. If it would not be easy in Ruby, I'd be very grateful for any pointers in another language too.
Thanks a lot for your help!
EDIT: It seems that I can do this easily with netcat -
sudo nc -l 443 0<backpipe | nc $TARGET_IP 443 >backpipe
so I am rather embarassed that I didn't think of something so simple in the first place, however I would still be interested to see what I was not doing right in Ruby.
So, I'm trying to simulate some basic HTTP persistent connections using sockets and Ruby - for a college class.
The point is to build a server - able to handle multiple clients - that receives a file path and gives back the file content - just like an HTTP GET.
The current server implementation loops listening for clients, fires a new thread when there's an incoming connection and reads the file paths from this socket. It's very dumb, but it works fine when working with non-presistent connections - one request per connection.
But they should be persistent.
Which means the client shouldn't worry about closing the connection. In the non-persistent version the servers echoes the response and close the connection - goodbye client, farewell.
But being persistent means the server thread should loop and wait for more incoming requests until... well until there's no more requests. How does the server knows that? It doesn't! Some sort of timeout is needed. I tried to do that with Ruby's Timeout, but it didn't work.
Googling for some solutions - besides being thoroughly advised to avoid using Timeout module - I've seen a lot of posts about the IO.select method, that should handle this socket waiting issue way better than using threads and stuff (which really sounds cool, considering how Ruby threads (don't) work). I'm trying to understand here how IO.select works, but still wasn't able to make it work in the current scenario.
So I aske basically two things:
how can I efficiently work this timeout issue on the server-side, either using some thread based solution, low-level socket options or some IO.select magic?
how can the client side know that the server has closed its side of the connection?
Here's the current code for the server:
require 'date'
module Sockettp
class Server
def initialize(dir, port = Sockettp::DEFAULT_PORT)
#dir = dir
#port = port
end
def start
puts "Starting Sockettp server..."
puts "Serving #{#dir.yellow} on port #{#port.to_s.green}"
Socket.tcp_server_loop(#port) do |socket, client_addrinfo|
handle socket, client_addrinfo
end
end
private
def handle(socket, addrinfo)
Thread.new(socket) do |client|
log "New client connected"
begin
loop do
if client.eof?
puts "#{'-' * 100} end connection"
break
end
input = client.gets.chomp
body = content_for(input)
response = {}
if body
response.merge!({
status: 200,
body: body
})
else
response.merge!({
status: 404,
body: Sockettp::STATUSES[404]
})
end
log "#{addrinfo.ip_address} #{input} -- #{response[:status]} #{Sockettp::STATUSES[response[:status]]}".send(response[:status] == 200 ? :green : :red)
client.puts(response.to_json)
end
ensure
socket.close
end
end
end
def content_for(path)
path = File.join(#dir, path)
return File.read(path) if File.file?(path)
return Dir["#{path}/*"] if File.directory?(path)
end
def log(msg)
puts "#{Thread.current} -- #{DateTime.now.to_s} -- #{msg}"
end
end
end
Update
I was able to simulate the timeout behaviour using the IO.select method, but the implementation doesn't feel good when combining with a couple of threads for accepting new connections and another couple for handling requests. The concurrency makes the situation mad and unstable, and I'm probably not sticking with it unless I can figure out a better way of using this solution.
Update 2
Seems like Timeout is still the best way to handle this. I'm sticking with it till find a better option.
I still don't know how to deal with zombie client connections.
Solution
I endend up using IO.select (got inspired when looking at the webrick code). You cha check the final version here (lib/http/server/client_handler.rb)
You should implement something like heartbeat packets.Client side should send special packets to after few secs/mins to ensure that server doesn't time out the connection on the client end.You just avoid doing anything in this call.
What I need to do:
Send a packet to pool.ntp.org (and I am assuming I get a packet back automatically).
The following just does not work for me. I have no solid idea of what I am doing, so for now I would be satisfied if I could reach the address and get the packet back. The code below just hangs. Any and all help would be appreciated.
require 'socket'
sock = UDPSocket.new
sock.connect("pool.ntp.org", 123)
sock.recvfrom(10)
The documentation on UDPSocket states:
connect(host, port)
Connects udpsocket to host:port.
This makes possible to send without destination address.
That means that you may use send(mesg, flags) form of the send, nothing more. You need to send a request message to the NTP server to get a reply
You can see the NTPv4 protocol specification here: RFC 5905