Laden...

PING einer hosts ohne admin rechte

Erstellt von maik vor 17 Jahren Letzter Beitrag vor 15 Jahren 8.787 Views
M
maik Themenstarter:in
170 Beiträge seit 2005
vor 17 Jahren
PING einer hosts ohne admin rechte

hi!

ich habe bereits eine klasse gefunden, welche das pingen unterstützt, dennoch geht diese nur, wenn ich administrator auf dem rechner bin...

geht das auch ohne admin rechte?
ich benutze das .NET Framework 1.1 und kann auch nicht auf das 2.0 switchen!

hier mal der bisherige code:


public class Ping
{
	private const int SOCKET_ERROR = -1;        
	private const int ICMP_ECHO = 8;
	private const int TIMEOUT = 1000;

	/// <summary>
	///		This method takes the "hostname" of the server
	///		and then it ping's it and shows the response time
	/// </summary>
	public static bool PingHost(string host)
	{
		//Declare the IPHostEntry 
		IPHostEntry serverHE, fromHE;
		int nBytes = 0;
		int dwStart = 0, dwStop = 0;
		//Initilize a Socket of the Type ICMP
		Socket socket = 
			new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);

		// Get the server endpoint
		try
		{
			serverHE = Dns.GetHostByName(host);	
		}
		catch(Exception)
		{
			Trace.WriteLine("Host not found"); // fail
			return false;
		}

		// Convert the server IP_EndPoint to an EndPoint
		IPEndPoint ipepServer = new IPEndPoint(serverHE.AddressList[0], 0);
		EndPoint epServer = (ipepServer);	

		// Set the receiving endpoint to the client machine
		fromHE = Dns.GetHostByName(Dns.GetHostName());
		IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0], 0);        
		EndPoint EndPointFrom = (ipEndPointFrom);

		int PacketSize = 0;
		IcmpPacket packet = new IcmpPacket();
		// Construct the packet to send
		packet.Type = ICMP_ECHO; //8
		packet.SubCode = 0;
		packet.CheckSum = UInt16.Parse("0");
		packet.Identifier   = UInt16.Parse("45"); 
		packet.SequenceNumber  = UInt16.Parse("0"); 
		int PingData = 32; // sizeof(IcmpPacket) - 8;
		packet.Data = new Byte[PingData];
		//Initilize the Packet.Data
		for (int i = 0; i < PingData; i++)
		{
			packet.Data[i] = (byte)'#';
		}
	            
		//Variable to hold the total Packet size
		PacketSize = PingData + 8;
		Byte [] icmp_pkt_buffer = new Byte[ PacketSize ]; 
		Int32 Index = 0;
		//Call a Method Serialize which counts
		//The total number of Bytes in the Packet
		Index = Serialize(  
			packet, 
			icmp_pkt_buffer, 
			PacketSize, 
			PingData );
		//Error in Packet Size
		if( Index == -1 )
		{
			Trace.WriteLine("Error in Making Packet");
			return false;
		}
        
		// now get this critter into a UInt16 array
	        
		//Get the Half size of the Packet
		Double double_length = Convert.ToDouble(Index);
		Double dtemp = Math.Ceiling( double_length / 2);
		int cksum_buffer_length = Convert.ToInt32(dtemp);
		//Create a Byte Array
		UInt16 [] cksum_buffer = new UInt16[cksum_buffer_length];
		//Code to initialize the Uint16 array 
		int icmp_header_buffer_index = 0;
		for( int i = 0; i < cksum_buffer_length; i++ ) 
		{
			cksum_buffer[i] = 
				BitConverter.ToUInt16(icmp_pkt_buffer,icmp_header_buffer_index);
			icmp_header_buffer_index += 2;
		}
		//Call a method which will return a checksum             
		UInt16 u_cksum = GenerateChecksum(cksum_buffer, cksum_buffer_length);
		//Save the checksum to the Packet
		packet.CheckSum  = u_cksum; 
	          
		// Now that we have the checksum, serialize the packet again
		Byte [] sendbuf = new Byte[ PacketSize ]; 
		//again check the packet size
		Index = Serialize(  
			packet, 
			sendbuf, 
			PacketSize, 
			PingData );
		//if there is a error report it
		if( Index == -1 )
		{
			Trace.WriteLine("Error in Making Packet");
			return false;
		}
	              

		dwStart = System.Environment.TickCount; // Start timing
		//send the Pack over the socket
		if ((nBytes = socket.SendTo(sendbuf, PacketSize, 0, epServer)) == SOCKET_ERROR) 
		{		
			Trace.WriteLine("Socket Error cannot Send Packet");
		}
		// Initialize the buffers. The receive buffer is the size of the
		// ICMP header plus the IP header (20 bytes)
		Byte [] ReceiveBuffer = new Byte[256]; 
		nBytes = 0;
		//Receive the bytes
		bool recd =false, err=true;
		int timeout=0 ;

		//loop for checking the time of the server responding 
		while(!recd)
		{
			nBytes = socket.ReceiveFrom(ReceiveBuffer, 256, 0, ref EndPointFrom);
			if (nBytes == SOCKET_ERROR) 
			{
				Trace.WriteLine("Host not Responding") ;
				recd=true ;
				break;
			}
			else if(nBytes>0)
			{
				dwStop = System.Environment.TickCount - dwStart; // stop timing
				Trace.WriteLine("Reply from "+epServer.ToString()+" in "
					+dwStop+"MS :Bytes Received"+nBytes);
				recd=true;
				err = false;
				break;
			}
			timeout=System.Environment.TickCount - dwStart;
			if(timeout>TIMEOUT)
			{
				Trace.WriteLine("Time Out") ;
				recd=true;
			}
		}
	          
		//close the socket
		socket.Close();
		if(!err)
			return true;
		else
			return false;
	}

	/// <summary>
	///  This method get the Packet and calculates the total size 
	///  of the Pack by converting it to byte array
	/// </summary>
	public static Int32 Serialize(IcmpPacket packet, Byte[] Buffer,
		Int32 PacketSize, Int32 PingData )
	{
		Int32 cbReturn = 0;
		// serialize the struct into the array
		int Index=0;

		Byte [] b_type = new Byte[1];
		b_type[0] = (packet.Type);

		Byte [] b_code = new Byte[1];
		b_code[0] = (packet.SubCode);

		Byte [] b_cksum = BitConverter.GetBytes(packet.CheckSum);
		Byte [] b_id = BitConverter.GetBytes(packet.Identifier);
		Byte [] b_seq = BitConverter.GetBytes(packet.SequenceNumber);
	      
		// Console.WriteLine("Serialize type ");
		Array.Copy( b_type, 0, Buffer, Index, b_type.Length );
		Index += b_type.Length;
	      
		// Console.WriteLine("Serialize code ");
		Array.Copy( b_code, 0, Buffer, Index, b_code.Length );
		Index += b_code.Length;

		// Console.WriteLine("Serialize cksum ");
		Array.Copy( b_cksum, 0, Buffer, Index, b_cksum.Length );
		Index += b_cksum.Length;

		// Console.WriteLine("Serialize id ");
		Array.Copy( b_id, 0, Buffer, Index, b_id.Length );
		Index += b_id.Length;

		Array.Copy( b_seq, 0, Buffer, Index, b_seq.Length );
		Index += b_seq.Length;

		// copy the data	        
		Array.Copy( packet.Data, 0, Buffer, Index, PingData );
		Index += PingData;
		if( Index != PacketSize/* sizeof(IcmpPacket)  */) 
		{
			cbReturn = -1;
			return cbReturn;
		}

		cbReturn = Index;
		return cbReturn;
	}
	
	/// <summary>
	///		This Method has the algorithm to make a checksum 
	/// </summary>
	public static UInt16 GenerateChecksum( UInt16[] buffer, int size )
	{
		Int32 cksum = 0;
		int counter;
		counter = 0;

		while ( size > 0 ) 
		{
			//UInt16 val = buffer[counter];

			cksum += Convert.ToInt32( buffer[counter] );
			counter += 1;
			size -= 1;
		}

		cksum = (cksum >> 16) + (cksum & 0xffff);
		cksum += (cksum >> 16);
		return (UInt16)(~cksum);
	}
} // class Ping

/// <summary>
///		Class that holds the Pack information
/// </summary>
public class IcmpPacket 
{ 
	private Byte  _type;
	private Byte  _subCode;
	private UInt16 _checkSum;
	private UInt16 _identifier;
	private UInt16 _sequenceNumber;
	private Byte [] _data;

	/// <summary>
	/// Type of message.
	/// </summary>
	public Byte Type
	{
		set { this._type = value; }
		get { return this._type; }
	}

	/// <summary>
	/// Type of sub code.
	/// </summary>
	public Byte SubCode
	{
		set { this._subCode = value; }
		get { return this._subCode; }
	}

	/// <summary>
	/// Ones complement checksum of struct.
	/// </summary>
	public UInt16 CheckSum
	{
		set { this._checkSum = value; }
		get { return this._checkSum; }
	}

	/// <summary>
	/// Packet identifier.
	/// </summary>
	public UInt16 Identifier
	{
		set { this._identifier = value; }
		get { return this._identifier; }
	}

	/// <summary>
	/// Packet sequence number.
	/// </summary>
	public UInt16 SequenceNumber
	{
		set { this._sequenceNumber = value; }
		get { return this._sequenceNumber; }
	}

	/// <summary>
	/// Packet data.
	/// </summary>
	public Byte[] Data
	{
		set { this._data = value; }
		get { return this._data; }
	}

} // class IcmpPacket

4.221 Beiträge seit 2005
vor 17 Jahren

Was passiert ?

Fehlermeldung ?

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

M
maik Themenstarter:in
170 Beiträge seit 2005
vor 17 Jahren

System.Net.Sockets.SocketException: Der Zugriff auf einen Socket war aufgrund der Zugriffsrechte des Sockets unzulässig!

Und auf Rechnern wo ich ADMIN bin da geht das, nur wenn ich keiner bin, dann kommt dieser Fehler!

4.221 Beiträge seit 2005
vor 17 Jahren

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

M
maik Themenstarter:in
170 Beiträge seit 2005
vor 17 Jahren

ah ok! und von welchem SocketType aus kann ich es dann schicken, oder generell nur über eine API?

S
8.746 Beiträge seit 2005
vor 17 Jahren

In .NET 2.0 gibts unter System.Net.NetworkInformation eine Ping-Klasse.

*EDIT*

Sorry, 1.1, jetzt erst gesehen.

M
maik Themenstarter:in
170 Beiträge seit 2005
vor 17 Jahren

hm... ja was kann ich jetzt mach in dem von programmierhans geposteten link steht auch nicht wirklich ein anhaltspunkt!

Original von Programmierhans
Das hatten wir schonmal


>

185 Beiträge seit 2005
vor 17 Jahren

Hallo,

das Problem hatte ich auch schon mal.
Das habe ich fefunden, funktioniert problemlos


		// Methode zum Ausführen des Ping-Befehls
	public static bool Ping(string host, int timeout)
	{
		// DNS-Abfrage zur Ermittlung der IP-Adresse des Zielhosts
		// starten
		IPHostEntry ipHostEntry = Dns.Resolve(host);
		IPAddress ip = ipHostEntry.AddressList[0];

		// Port 7 des Hosts auswählen
		IPEndPoint ipEndPoint = new IPEndPoint(ip, 7);

		// Einen Socket für das ICMP-Protokoll erzeugen
		Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);

		// ICMP-Packet (ICMP-Type = 8: Echo Request)
		byte[] icmpPacket = {8, 0, 0xF7, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
		int result = socket.SendTo(icmpPacket, icmpPacket.Length, SocketFlags.None, ipEndPoint);

		ArrayList receivedData = new ArrayList();
		receivedData.Add(socket);
		Socket.Select(receivedData, null, null, timeout*1000);
		byte[] receiveICMPPacket = new byte[200];
		int bytes = 0;

		if (receivedData.Count > 0)
		{
			// Daten jetzt auslesen
			bytes = socket.Receive(receiveICMPPacket, receiveICMPPacket.Length, SocketFlags.None);
			if (getICMPChecksum(receiveICMPPacket) == 0)
				return true;
			else
				return false;
		}
		else
			return false;

	}
		static ushort getICMPChecksum(byte[] icmpP)
		{
			byte[] buffer;
			if ((icmpP.Length % 2) > 0)
			{
				buffer = new byte[icmpP.Length +1];
				icmpP.CopyTo(buffer, 0);
				buffer[buffer.Length - 1] = 0;
			}
			else
			{
				buffer = new byte[icmpP.Length];
				icmpP.CopyTo(buffer, 0);
			}
			int checksum = 0;
			for (int i = 0; i < buffer.Length; i += 2)
			{
				byte firstByte = buffer[i+1];
				byte secondByte = buffer[i];
				ushort word = secondByte;
				word = (ushort)((word << 8) + firstByte);
				checksum += word;
			}
			checksum = (checksum >> 16) + (checksum & 0xFFFF);
			checksum += (checksum >> 16);

			// Einerkomplement
			return (ushort)(~checksum);
		}

MartinH

M
267 Beiträge seit 2005
vor 17 Jahren

Hallo MartinH,

ich muss leider sagen, dass dein Code auch nur mit Admin Rechten läuft...

Mfg
Tobias

No Risk, No Fun

M
maik Themenstarter:in
170 Beiträge seit 2005
vor 15 Jahren

Der Post ist jetzt zwar schon ewig alt, aber vor .NET 2.0 und mit Windows 2000 kann man das ganze auch über ICMP API von MS lösen. Ist die selbe Schnittstelle, die auch "ping.exe" verwendet. Damit ist es auch möglich **OHNE **Admin-Rechte einen PING abzusetzen...

Hier die Lösung:


public class ICMPPing
{
  #region Win32 Structure Definitions
  
  [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
  private struct ICMP_OPTIONS
  {
    public Byte Ttl;
    public Byte Tos;
    public Byte Flags;
    public Byte OptionsSize;
    public IntPtr OptionsData;
  };
  
  [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
  private struct ICMP_ECHO_REPLY
  {
    public int Address;
    public int Status;
    public int RoundTripTime;
    public Int16 DataSize;
    public Int16 Reserved;
    public IntPtr DataPtr;
    public ICMP_OPTIONS Options;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=250)]
    public String Data;
  }
  
  #endregion

  #region Win32 API Method Definitions
  
  [DllImport("icmp.dll", SetLastError=true)]
  private static extern IntPtr IcmpCreateFile();
  
  [DllImport("icmp.dll", SetLastError=true)]
  private static extern bool IcmpCloseHandle(IntPtr handle);
  
  [DllImport("icmp.dll", SetLastError=true)]
  private static extern Int32 IcmpSendEcho(IntPtr icmpHandle, Int32 destinationAddress, 
    String requestData, Int16 requestSize, ref ICMP_OPTIONS requestOptions, 
    ref ICMP_ECHO_REPLY replyBuffer, Int32 replySize, Int32 timeout);
  
  #endregion

  #region Public Methods
  
  public static bool Ping(string host, int timeout)
  {
    IntPtr handle;
    Int32 ipAddress;
    String data;
    ICMP_OPTIONS options = new ICMP_OPTIONS();
    ICMP_ECHO_REPLY reply = new ICMP_ECHO_REPLY();
    Int32 replies;
    
    IPHostEntry foundHost;
    try
    {
      foundHost = Dns.GetHostByName(host);
      if (foundHost == null || foundHost.AddressList == null || 
      foundHost.AddressList.Length == 0 || foundHost.AddressList[0] == null)
      throw new Exception();
    }
    catch
    {
      Trace.Write("The specified host '" + host + "' could not be found in the network.");
      return false;
    }
    
    IPAddress ip = foundHost.AddressList[0];
    
    handle = IcmpCreateFile();
    ipAddress = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
    data = "x";
    options.Ttl = 255;
    
    replies = IcmpSendEcho(handle, ipAddress, data, (Int16) data.Length, ref options, 
                           ref reply, Marshal.SizeOf(reply), timeout);
    
    IcmpCloseHandle(handle);
    
    //replies enthaelt die Anzahl an Antworten des gepingten Hosts, der zurückgelieferte Status 
    //enthaelt eine Win32 Fehlernummer, sofern ein Fehler aufgetreten ist...
    //Alle Fehlercodes koennen der Struktur "ICMP_ECHO_REPLY" im "Ipexport.h" header file entnommen werden!
    if (replies > 0 && reply.Status == 0)
      return true;
    return false;
  }
  #endregion
}

Cheerio!
Maik