• Python: Running Ping, Traceroute and More


    Last year I needed to figure out a way to get the following information with Python: get the route table, capture the data from pinging a series of IPs, run tracert and get information about the NIC(s) installed. This all needed to be done on a Windows machine as it was part of a diagnostics script to try to figure out why the machine (usually a laptop) wouldn’t connect to our VPN. I ended up creating a wxPython GUI to make it easy for the user to run, but these scripts will work just fine without wx. Let’s see what they look like!

    The Main Script

    To start with, we’ll look at the entire script and then go over each important piece. If you’d like to use the code below, you will need wxPython and thePyWin32 package.

    import os
    import subprocess
    import sys
    import time
    import win32com.client
    import win32net
    import wx
     
    filename = r"C:logs
    ic-diag.log"
     
    class RedirectText:
        def __init__(self,aWxTextCtrl):
            self.out=aWxTextCtrl
     
            if not os.path.exists(r"C:logs"):
                os.mkdir(r"C:logs")
            self.filename = open(filename, "w")
     
        def write(self,string):
            self.out.WriteText(string)
            if self.filename.closed:
                pass
            else:
                self.filename.write(string)
     
    class MyForm(wx.Frame):
     
        #---------------------------------------------------------------------- 
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, "Diagnostic Tool")
     
            # Add a panel so it looks the correct on all platforms
            panel = wx.Panel(self, wx.ID_ANY)
            log = wx.TextCtrl(panel, wx.ID_ANY, size=(300,100),
                              style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
            # log.Disable()
            btn = wx.Button(panel, wx.ID_ANY, 'Run Diagnostics')
            self.Bind(wx.EVT_BUTTON, self.onRun, btn)
     
            # Add widgets to a sizer        
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5)
            sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
            panel.SetSizer(sizer)
     
            # redirect text here
            self.redir=RedirectText(log)
            sys.stdout=self.redir
     
        #----------------------------------------------------------------------    
        def runDiagnostics(self):
            """
            Run some diagnostics to get the machine name, ip address, mac,
            gateway, DNS, route tables, etc
            """
            # create the route table:
            # based on the following list comp from http://win32com.goermezer.de/content/view/220/284/
            # route_table = [elem.strip().split() for elem in os.popen("route print").read().split("Metric
    ")[1].split("
    ") if re.match("^[0-9]", elem.strip())]
            route_table = []
            proc = subprocess.Popen("route print", shell=True,
                            stdout=subprocess.PIPE)
            while True:
                line = proc.stdout.readline()
                route_table.append(line.strip().split())
                if not line: break
            proc.wait()
     
            print "Log Created at %s" % time.ctime()
            print "----------------------------------------------------------------------------------------------"
            info = win32net.NetWkstaGetInfo(None, 102)
            self.compname = info["computername"]
            print "Computer name: %s
    " % self.compname
     
            print "----------------------------------------------------------------------------------------------"
            print "Route Table:"
            print "%20s	 %15s	 %15s	 %15s	 %s" % ("Network Destination", "Netmask",
                                              "Gateway", "Interface", "Metric")
            for route in route_table:
                if len(route) == 5:
                    dst, mask, gateway, interface, metric = route
                    print "%20s	 %15s	 %15s	 %15s	 %s" % (dst, mask, gateway, interface, metric)
     
            print "----------------------------------------------------------------------------------------------
    "
            ips = ["65.55.17.26", "67.205.46.185", "67.195.160.76"]
            for ip in ips:
                self.pingIP(ip)
                print
                self.tracertIP(ip)
                print "
    ----------------------------------------------------------"
            self.getNICInfo()
            print "############ END OF LOG ############"
     
        #----------------------------------------------------------------------   
        def pingIP(self, ip):
            proc = subprocess.Popen("ping %s" % ip, shell=True, 
                                    stdout=subprocess.PIPE) 
            print
            while True:
                line = proc.stdout.readline()                        
                wx.Yield()
                if line.strip() == "":
                    pass
                else:
                    print line.strip()
                if not line: break
            proc.wait()
     
        #----------------------------------------------------------------------
        def tracertIP(self, ip):
            proc = subprocess.Popen("tracert -d %s" % ip, shell=True, 
                                    stdout=subprocess.PIPE)
            print 
            while True:
                line = proc.stdout.readline()
                wx.Yield()
                if line.strip() == "":
                    pass
                else:
                    print line.strip()
                if not line: break
            proc.wait()
     
        #----------------------------------------------------------------------            
        def getNICInfo(self):
            """
    
    http://www.microsoft.com/technet/scriptcenter/scripts/python/pyindex.mspx?mfr=true
    
            """
            print "
    Interface information:
    "
            strComputer = "."
            objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
            objSWbemServices = objWMIService.ConnectServer(strComputer,"rootcimv2")
            colItems = objSWbemServices.ExecQuery("Select * from Win32_NetworkAdapterConfiguration")
            numOfNics = len(colItems)
            count = 1
            for objItem in colItems:
                # if the IP interface is enabled, grab its info
                print "***Interface %s of %s***" % (count, numOfNics)
                if objItem.IPEnabled == True:                
                    print "Arp Always Source Route: ", objItem.ArpAlwaysSourceRoute
                    print "Arp Use EtherSNAP: ", objItem.ArpUseEtherSNAP
                    print "Caption: ", objItem.Caption
                    print "Database Path: ", objItem.DatabasePath
                    print "Dead GW Detect Enabled: ", objItem.DeadGWDetectEnabled
                    z = objItem.DefaultIPGateway
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "Default IP Gateway: ", x
                    print "Default TOS: ", objItem.DefaultTOS
                    print "Default TTL: ", objItem.DefaultTTL
                    print "Description: ", objItem.Description
                    print "DHCP Enabled: ", objItem.DHCPEnabled
                    print "DHCP Lease Expires: ", objItem.DHCPLeaseExpires
                    print "DHCP Lease Obtained: ", objItem.DHCPLeaseObtained
                    print "DHCP Server: ", objItem.DHCPServer
                    print "DNS Domain: ", objItem.DNSDomain
                    z = objItem.DNSDomainSuffixSearchOrder
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "DNS Domain Suffix Search Order: ", x
                    print "DNS Enabled For WINS Resolution: ", objItem.DNSEnabledForWINSResolution
                    print "DNS Host Name: ", objItem.DNSHostName
                    z = objItem.DNSServerSearchOrder
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "DNS Server Search Order: ", x
                    print "Domain DNS Registration Enabled: ", objItem.DomainDNSRegistrationEnabled
                    print "Forward Buffer Memory: ", objItem.ForwardBufferMemory
                    print "Full DNS Registration Enabled: ", objItem.FullDNSRegistrationEnabled
                    z = objItem.GatewayCostMetric
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "Gateway Cost Metric: ", x
                    print "IGMP Level: ", objItem.IGMPLevel
                    print "Index: ", objItem.Index
                    z = objItem.IPAddress
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IP Address: ", x
                    print "IP Connection Metric: ", objItem.IPConnectionMetric
                    print "IP Enabled: ", objItem.IPEnabled
                    print "IP Filter Security Enabled: ", objItem.IPFilterSecurityEnabled
                    print "IP Port Security Enabled: ", objItem.IPPortSecurityEnabled
                    z = objItem.IPSecPermitIPProtocols
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IP Sec Permit IP Protocols: ", x
                    z = objItem.IPSecPermitTCPPorts
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IP Sec Permit TCP Ports: ", x
                    z = objItem.IPSecPermitUDPPorts
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IPSec Permit UDP Ports: ", x
                    z = objItem.IPSubnet
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IP Subnet: ", x
                    print "IP Use Zero Broadcast: ", objItem.IPUseZeroBroadcast
                    print "IPX Address: ", objItem.IPXAddress
                    print "IPX Enabled: ", objItem.IPXEnabled
                    z = objItem.IPXFrameType
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IPX Frame Type: ", x
                    print "IPX Media Type: ", objItem.IPXMediaType
                    z = objItem.IPXNetworkNumber
                    if z is None:
                        a = 1
                    else:
                        for x in z:
                            print "IPX Network Number: ", x
                    print "IPX Virtual Net Number: ", objItem.IPXVirtualNetNumber
                    print "Keep Alive Interval: ", objItem.KeepAliveInterval
                    print "Keep Alive Time: ", objItem.KeepAliveTime
                    print "MAC Address: ", objItem.MACAddress
                    print "MTU: ", objItem.MTU
                    print "Num Forward Packets: ", objItem.NumForwardPackets
                    print "PMTUBH Detect Enabled: ", objItem.PMTUBHDetectEnabled
                    print "PMTU Discovery Enabled: ", objItem.PMTUDiscoveryEnabled
                    print "Service Name: ", objItem.ServiceName
                    print "Setting ID: ", objItem.SettingID
                    print "Tcpip Netbios Options: ", objItem.TcpipNetbiosOptions
                    print "Tcp Max Connect Retransmissions: ", objItem.TcpMaxConnectRetransmissions
                    print "Tcp Max Data Retransmissions: ", objItem.TcpMaxDataRetransmissions
                    print "Tcp Num Connections: ", objItem.TcpNumConnections
                    print "Tcp Use RFC1122 Urgent Pointer: ", objItem.TcpUseRFC1122UrgentPointer
                    print "Tcp Window Size: ", objItem.TcpWindowSize
                    print "WINS Enable LMHosts Lookup: ", objItem.WINSEnableLMHostsLookup
                    print "WINS Host Lookup File: ", objItem.WINSHostLookupFile
                    print "WINS Primary Server: ", objItem.WINSPrimaryServer
                    print "WINS Scope ID: ", objItem.WINSScopeID
                    print "WINS Secondary Server: ", objItem.WINSSecondaryServer
                    print "-------------------------------------------------------
    "
                else:
                    print "Interface is disabled!
    "
                count += 1
     
        #----------------------------------------------------------------------
        def onRun(self, event):
            self.runDiagnostics()
            self.redir.filename.close()
            # Restore stdout to normal
            sys.stdout = sys.__stdout__
     
    #----------------------------------------------------------------------         
    # Run the program
    if __name__ == "__main__":
        app = wx.PySimpleApp()
        frame = MyForm().Show()
        app.MainLoop()

    As with most Python programs, this one starts out with various imports. Next we create a a simple class (RedirectText) that we will use to help us redirect stdout to a wx.TextCtrl and a log file. This works by passing in an instance of wx.TextCtrl and then setting “sys.stdout” to point to it (see the __init__ method in the MyForm class). Following the RedirectText class, we have the MyForm class which is where we create out wxPython GUI. There’s actually not much to the GUI itself. Just a multi-line text control and a button on a panel, but that’s all we need. The rest of the class is made up of methods that gather all our required information and log it to the screen and to a file.

    Let’s take a look at those methods now! Note that these methods are called from therunDiagnostics method which is launched from the onRun button event handler.

    Getting the Route Table (AKA: IP Routes)

    When I looked into how to do this, I found the following script on another blog:

    import os, re
    route_table = [elem.strip().split() for elem in os.popen("route print").read().split("Metric
    ")[1].split("
    ") if re.match("^[0-9]", elem.strip())]

    I found that rather hard to follow, so I re-wrote it (or found another example and forgot to make a note of it) like this:

    route_table = []
    proc = subprocess.Popen("route print", shell=True,
                    stdout=subprocess.PIPE)
    while True:
        line = proc.stdout.readline()
        route_table.append(line.strip().split())
        if not line: break
    proc.wait()
     
    print "----------------------------------------------------------------------------------------------"
    print "Route Table:"
    print "%20s	 %15s	 %15s	 %15s	 %s" % ("Network Destination", "Netmask",
                                      "Gateway", "Interface", "Metric")
    for route in route_table:
        if len(route) == 5:
            dst, mask, gateway, interface, metric = route
            print "%20s	 %15s	 %15s	 %15s	 %s" % (dst, mask, gateway, interface, metric)

    I find the code above much easier to read and understand. All it does is use the subprocess module to run “route print” and write the result to stdout. Don’t be confused by the proc.stdout above. That’s the process’s stdout, not the normal stdout. We want to redirect that data to the normal stdout! To do that, we read the proc’s stdout (or some might say, the PIPE) and append each line of data to a list. Then we create a nice custom output using Python’s string formatting. Now let’s take a look at how to use Python to run Ping and Tracert.

    Running Ping / Tracert with Python

    Pinging with Python is pretty easy. We just need the subprocess module to do it as you can see from this snippet:

    def pingIP(self, ip):
        proc = subprocess.Popen("ping %s" % ip, shell=True, 
                                stdout=subprocess.PIPE) 
        print
        while True:
            line = proc.stdout.readline()                        
            wx.Yield()
            if line.strip() == "":
                pass
            else:
                print line.strip()
            if not line: break
        proc.wait()

    In this code, we use wx.Yield to send the ping results to our text control in real time. If we didn’t, then we wouldn’t receive any of the ping results until ping had finished running. Note that we also use an infinite loop to grab the results. Once the results stop coming, we break out of the loop. If you look at the tracert code, you’ll see that the only difference is in out subprocess.Popen command. This would be a good candidate for refactoring, but I’ll leave that as an exercise for the reader.

    Getting NIC Information with Python

    Microsoft has a whole set of Python scripts on their Technet sub-site and I ended up using on them to get all kinds of good information on the Network Interface Cards (NIC) in our PCs. I won’t reproduce the code here since it’s long and we already have it above. However, it’s pretty easy to follow and I suspect that you could use WMI to get the same information if you know what you’re doing. The main part that we were interested in was the MAC and IP addresses. Let’s just extract that info from the long code and see how easy it is to get:

    strComputer = "."
    objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
    objSWbemServices = objWMIService.ConnectServer(strComputer,"rootcimv2")
    colItems = objSWbemServices.ExecQuery("Select * from Win32_NetworkAdapterConfiguration")
    numOfNics = len(colItems)
     
    for objItem in colItems:
        z = objItem.IPAddress
        if z is None:
            a = 1
        else:
            for x in z:
                 print "IP Address: ", x
        print "MAC Address: ", objItem.MACAddress

    Pretty easy, huh? And look! You use what looks like SQL syntax to run the query. This is why I think you can probably use WMI (in fact, that may be what it’s doing in an obtuse manner). Anyway, that’s really all there is to it.

    Wrapping Up

    Now you know the secrets to get various bits of networking information from your PC and how to redirect subprocess’s PIPEs to a log file and a wxPython text control. How you choose to use this information is up to you.

  • 相关阅读:
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp 8 Web基础
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp7 网络欺诈防范
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp6 MSF基础应用
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp5 信息搜集与漏洞扫描
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp4 恶意代码分析
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp3 免杀原理与实践
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp2 后门原理与实践
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp1 PC平台逆向破解
    2019-2020-1 20175312 20175333 实验五 通讯协议设计
    2019-2020-2 20175320 《网络对抗技术》免考实践报告 手工实现对PE文件的shellcode注入
  • 原文地址:https://www.cnblogs.com/dengyigod/p/3304574.html
Copyright © 2020-2023  润新知