ARP-Tabelle auslesen - gelöst



  • Problem I: ARP-Tabelle auslesen (gelöst)
    Problem II (siehe 2. Beitrag) MAC-Adresse in Variable speichern (gelöst)

    Ich versuche als Übung um die Windows API zu verstehen, ein Konsolen Programm zu schreiben, mit dem ich die ARP-Tabelle auslesen kann. Ich habe leider keine Erfahrung mit der WindowsAPI. Auch nach längerem recherchieren verstehe ich jedoch nicht wie ich an diese Aufgabe heran gehen soll.

    Auf MSDN bin ich auf folgende Website gestoßen:
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa366398(v=vs.85).aspx

    Den Informationen entnehme ich das ich die Funktion "GetIpNetTable" benötige.
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa365956(v=vs.85).aspx

    Jedoch verstehe ich nicht wie ich diese Funktion verwenden kann`?
    Ich habe nur diese Funktion als einzigen Hinweis. Nach mehreren Stunden habe ich mir aus einigen anderen Beispielprogrammen Code kopiert und mir folgenden Code zusammengestöpselt:

    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
    
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <iphlpapi.h>	//Benötige ich laut MSDN zum ermitteln der ARP Tabelle
    #include <stdio.h>
    #include <time.h>
    
    #include<iostream>
    using namespace std;
    
    // Need to link with Iphlpapi.lib and Ws2_32.lib
    #pragma comment(lib, "iphlpapi.lib")
    #pragma comment(lib, "ws2_32.lib")
    
    #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
    #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
    /* Note: could also use malloc() and free() */
    
    int main()
    {
    
        /* Some general variables */
        ULONG ulOutBufLen;
        DWORD dwRetVal;
    	//unsigned int i;
    
    	/* variables used for GetIpNetParams */
        PMIB_IPNETTABLE *pIpNetTable;
        //PULONG *pdwSize;
    	BOOL bOrder = true;
    
    	//DWORD GetIpNetTable
    	//(
    	//	_Out_    PMIB_IPNETTABLE pIpNetTable,
    	//	_Inout_  PULONG pdwSize,
    	//	_In_     BOOL bOrder
    	//);
    
    //========================================================================== GetNetworkParams() ==========================================================================
    
        printf("------------------------\n");
        printf("This is GetIpNetTable\n");
        printf("------------------------\n");
    
        pIpNetTable = (PMIB_IPNETTABLE *)		MALLOC(sizeof (PMIB_IPNETTABLE));
    
        if (pIpNetTable == NULL)
    	{
            cout<<"Error allocating memory needed to call GetIpNetTable\n";
    			cin.get();
            return 1;
        }
        ulOutBufLen = sizeof (PMIB_IPNETTABLE);
    
        if (GetIpNetTable((PMIB_IPNETTABLE)pIpNetTable, &ulOutBufLen, bOrder) == ERROR_BUFFER_OVERFLOW)
    	{
            FREE(pIpNetTable);
            pIpNetTable = (PMIB_IPNETTABLE *)	 MALLOC(sizeof(ulOutBufLen));
    
            if (pIpNetTable == NULL) 
    		{
                printf("Error allocating memory needed to call GetIpNetTable\n");
    				cin.get();
                return 1;
            }
        }
    
    	dwRetVal = GetIpNetTable((PMIB_IPNETTABLE) pIpNetTable, &ulOutBufLen, bOrder);
    
    	if (dwRetVal != NO_ERROR)
    	{
            cout<<"GetNetworkParams failed with error %d\n", dwRetVal;
            if (pIpNetTable)
                FREE(pIpNetTable);
    
            return 1;
    	}
    	else if (dwRetVal == ERROR_INSUFFICIENT_BUFFER)
    	{
    		cout<<"ERROR_INSUFFICIENT_BUFFER";
    	}
    	else if (dwRetVal == ERROR_INVALID_PARAMETER)
    	{
    		cout<<"ERROR_INVALID_PARAMETER";
    	}
    	else if (dwRetVal == ERROR_NO_DATA)
    	{
    		cout<<"ERROR_NO_DATA";
    	}
    	else if (dwRetVal == ERROR_NOT_SUPPORTED)
    	{
    		cout<<"ERROR_NOT_SUPPORTED";
    
        } 
    	else 
    	{
    		cout<<"Unknown"<<endl;
        }
    
        /* Free allocated memory no longer needed */
        if (pIpNetTable) {
            FREE(pIpNetTable);
            pIpNetTable = NULL;
        }
    
    	cin.get(); cin.get();
    
    	return 0;
    
    }
    

    Edit: Habe ein paar Fehler im Code soeben behoben (habe diese Version im Forum natürlich angepasst), das Problem besteht jedoch weiterhin.

    Ich bekomme jedoch ständig nur "unknown" ausgegeben. Wo liegt der Fehler ?

    Ich habe auch schon versucht die Tutorials auf dieser Website auf die ich im FAQ Bereich aufmerksam gemacht worden bin, zu erledigen. Jedoch scheinen diese Tutorials veraltet zu sein, denn keines hat bisher funktioniert.
    http://www.win-api.de/

    Vielen Dank im voraus für jede Hilfe!



  • Ich konnte eine Lösung für das Problem finden.
    http://www.codeproject.com/Articles/5960/More-on-using-IP-Helper-API-s

    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif
    
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <iphlpapi.h>	//Benötige ich laut MSDN zum ermitteln der ARP Tabelle
    #include <stdio.h>
    #include <time.h>
    
    #include<iostream>
    using namespace std;
    
    // Need to link with Iphlpapi.lib and Ws2_32.lib
    #pragma comment(lib, "iphlpapi.lib")
    #pragma comment(lib, "ws2_32.lib")
    
    #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
    #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
    /* Note: could also use malloc() and free() */
    
    int main()
    {
    
        /* Some general variables */
        DWORD	dword_RetVal;
    	PBYTE	pbyte_Buffer = NULL;
    	ULONG	ulong_SIZE;
    
    //========================================================================== GetNetworkParams() ==========================================================================
    
        PMIB_IPNETTABLE pIPNetTable = NULL;
        PMIB_IPNETROW   pIPNetRow;
        in_addr         ia;
        char            *szTypes[4] = {"Other", "Invalid", "Dynamic", "Static"};
    
        GetIpNetTable ((PMIB_IPNETTABLE) pbyte_Buffer, &ulong_SIZE, TRUE);
    
        pbyte_Buffer = new BYTE[ulong_SIZE];
    
        if (NULL != pbyte_Buffer)
        {
            dword_RetVal = GetIpNetTable((PMIB_IPNETTABLE) pbyte_Buffer, &ulong_SIZE, TRUE);
    
    		if (dword_RetVal == NO_ERROR)
            {
                pIPNetTable = (PMIB_IPNETTABLE) pbyte_Buffer;
    
                for (int x = 0; x < pIPNetTable->dwNumEntries; x++)
                {
                    pIPNetRow = &(pIPNetTable->table[x]);
    
                    printf("             Index: %lu\r\n", pIPNetRow->dwIndex);
    
                    printf("MAC address length: %lu\r\n", pIPNetRow->dwPhysAddrLen);
    
                    printf("       MAC address: %02x-%02x-%02x-%02x-%02x-%02x\r\n", 
                        pIPNetRow->bPhysAddr[0],
                        pIPNetRow->bPhysAddr[1],
                        pIPNetRow->bPhysAddr[2],
                        pIPNetRow->bPhysAddr[3],
                        pIPNetRow->bPhysAddr[4],
                        pIPNetRow->bPhysAddr[5]);
    
                    ia.S_un.S_addr = pIPNetRow->dwAddr;
    
                    printf("        IP address: %s\r\n", inet_ntoa(ia));
    
                    printf("              Type: %s\r\n", szTypes[pIPNetRow->dwType - 1]);
                }
            }
            else
            {
                printf("GetIpNetTable() failed.  Result = %lu\r\n", dword_RetVal);
            }
    
            delete [] pbyte_Buffer;
        }
    
    	cin.get(); cin.get();
    
        return TRUE;
    }
    

    Wie kann ich die MAC-Adresse in einer Variable speichern ?
    Mein Ziel ist es zwei MAC-Adressen miteinander zu vergleichen.

    Bitte um Hilfe.



  • Ohne mir das jetzt genau angeschaut zu haben. Die MAC Adresse ist doch schon in der Variable pIPNetRow. Der Member bPhysAddr ist ein Byte Array (mit 6 Elementen), der die MAC Adresse enthält. Die kannst du dir dann auch im Speicher halten, wenn du willst.



  • Danke für deine Antwort! Das weiss ich. Nur fehlt mir leider das Wissen wie ich dieses Byte Array in einem normalem char Array abspeichern kann.

    Mein Ziel ist es alle MAC-Adressen am Ende miteinander vergleichen zu können um zu sehen ob zwei gleiche MAC-Adressen vorhanden sind.

    Hier ist mein Ansatz: (funktionert natürlich nicht, da bPhysAddr zwei Chars enthält. Ich muss herausfinden wie ich auf die einzelnen Bytes von bPhysAddr zugreifen kann)

    char myarr[80];
    
    	myarr[0] = pIPNetRow->bPhysAddr[0];
    	myarr[1] = pIPNetRow->bPhysAddr[1];
    	myarr[2] = pIPNetRow->bPhysAddr[2];
    	myarr[3] = pIPNetRow->bPhysAddr[3];
    	myarr[4] = pIPNetRow->bPhysAddr[4];
    	myarr[5] = pIPNetRow->bPhysAddr[5];
    
    	for (int i = 0; i<6; i++)
    	{
    		cout<<"myarr["<<i<<"] = "<< myarr[i] <<endl;
    	}
    

    Danke für jeden Versuch.



  • Du kannst doch auch mit memcmp arrays vergleichen.

    typedef BYTE[6] MAC;
    MAC array1;
    MAC array2; 
    //....
    if (memcmp(array1,array2,sizeof(MAC)) == 0)
    {
      //identisch...
    }
    else
    {
      //nicht indetisch
    }
    


  • Burkhi schrieb:

    Du kannst doch auch mit memcmp arrays vergleichen.

    typedef BYTE[6] MAC;
    MAC array1;
    MAC array2; 
    //....
    if (memcmp(array1,array2,sizeof(MAC)) == 0)
    {
      //identisch...
    }
    else
    {
      //nicht indetisch
    }
    

    Danke für deine Antwort!
    Zuerst muss ich jedoch wissen wie ich die MAC Adresse in diesem Array speichern kann. Etwa mit: MAC array1 = pIPNetRow->bPhysAddr ?

    Dein Code funktioniert außerdem nicht. Folgender Fehler erscheint:

    "Der Bezeichner MAC ist nicht definiert"
    

    typedef Byte[6] MAC; habe ich außerhalb von main platziert

    Ich verwende Visual Studio 2010

    Edit: Mir ist aufgefallen das bei meiner Methode für 01 ein ☺ Smiley gespeichert wird. Weshalb wird das ASCII Zeichen angezeigt anstatt die Zahl?

    http://www.pasteall.org/pic/show.php?id=80131



  • Du stellst dich schon etwas dämlich an 😃

    Vergleiche, bevor du pbyte_Buffer aufräumst: memcmp(pIPNetRow->bPhysAddr, myarr, 6)
    Oder wenn du es unbedingt speichern (kopieren) willst: memcpy(myarr2, pIPNetRow->bPhysAddr, 6)

    Das Zeichen wird angezeigt, da std::cout erkennt, dass du einen char-Typ ausgibst.
    Du könntest zB. vorher casten: std::cout << static_cast<unsigned int>(mycharvar)



  • Sag mal, brauchst du (bezahlte) Direkthilfe (Skype etc.)? 🙂



  • MAC Adresse als lesbare Zeichen speichern geht auch so:

    char ziel[32];
    
    sprintf(ziel, "%02X-%02X-%02X-%02X-%02X-%02X-%02X", pIPNetRow->bPhysAddr[0], pIPNetRow->bPhysAddr[1], pIPNetRow->bPhysAddr[2], pIPNetRow->bPhysAddr[3], pIPNetRow->bPhysAddr[4], pIPNetRow->bPhysAddr[5]);
    

    Damit wäre das Problem umgangen:

    Edit: Mir ist aufgefallen das bei meiner Methode für 01 ein ☺ Smiley gespeichert wird. Weshalb wird das ASCII Zeichen angezeigt anstatt die Zahl?

    Mit "-" getrennt, kannste natürlich auch weglassen.



  • Hi schrieb:

    Du stellst dich schon etwas dämlich an 😃

    Ich habe zu keinem Zeitpunkt erwähnt das ich mich in C++ besonders auskenne, wenn ich keine Hilfe bräuchte, dann würde ich wohl kaum einen Post in diesem Forum veröffentlichen! Das Beleidigen bringt keinem was. 👎

    Bezahlte Hilfe ?
    Wird jetzt sogar schon Geld verlangt eine so simple Frage beantwortet zu bekommen? Traurig. Ich dachte dies ist ein Forum wo man sich gegenseitig hilft.

    Danke aber für den restlichen Teil deines Posts, war hilfreich 🙂

    @HiHo,

    Vielen Dank! Genau danach habe ich gesucht !! Schon wieder etwas neues dazu gelernt 🙂 THX 👍



  • Das war nicht als Beleidigung gedacht. Schon gar nicht mit dem Smilie hinten dran.
    Außerdem ist jeder mal irgendwo "dämlich" (denkt nicht ausreichend nach) :p
    Das war sehr sanft, freundlich und etwas "anspornend" gemeint.
    Aber vielleicht liegt's an meinem Autismus, hahahah!

    Nein, traurig ist da gar nichts. Könnte ja sein, dass du noch viel mehr Fragen hast, und diese gerne viel schneller/direkter beantwortet hättest.
    Dafür könnte dann einiges meiner Zeit draufgehen.
    War außerdem nur ein Angebot.

    🙄

    PS: Wenn du C++ verwendest, vergiss das grausige "sprintf" und guck dir "stringstreams" an.



  • Hi schrieb:

    Das war nicht als Beleidigung gedacht. Schon gar nicht mit dem Smilie hinten dran.
    Außerdem ist jeder mal irgendwo "dämlich" (denkt nicht ausreichend nach) :p
    Das war sehr sanft, freundlich und etwas "anspornend" gemeint.
    Aber vielleicht liegt's an meinem Autismus, hahahah!

    Nein, traurig ist da gar nichts. Könnte ja sein, dass du noch viel mehr Fragen hast, und diese gerne viel schneller/direkter beantwortet hättest.
    Dafür könnte dann einiges meiner Zeit draufgehen.
    War außerdem nur ein Angebot.

    🙄

    PS: Wenn du C++ verwendest, vergiss das grausige "sprintf" und guck dir "stringstreams" an.

    Tut mir leid, hab wohl etwas überreagiert. Ich hatte mich eben auf die antworten so sehr gefreut und musste dann im ersten Satz gleich eine Beleidigung lesen. Sprintf ist ganz gut, aber danke für den Tipp! 🙂

    Ich konnte mein Ziel einen Arp-Table Watcher zu erstellen das Man-in-the-Middle Attacks feststellen kann, endlich erreichen 🙂 Keine Ahnung ob es solch ein Programm schon gibt (sehr wahrscheinlich schon) aber es ging mir sowieso in erster Linie nur darum etwas zu lernen und Erfahrung mit der Windows API zu sammeln.

    Danke nochmal für eure Hilfe 👍



  • EdwardBlack schrieb:

    Ich hatte mich eben auf die antworten so sehr gefreut und musste dann im ersten Satz gleich eine Beleidigung lesen.

    Willkommen im Internet.

    🤡

    *SCNR*


Anmelden zum Antworten