diff --git a/CHANGES b/CHANGES index eb71c3d..8ab42ea 100644 --- a/CHANGES +++ b/CHANGES @@ -174,4 +174,5 @@ v 0.1.6 Continue with STA functionality no device currently present on the machine and one identifying when the specified dev's driver does not support nl80211 o fixed TypeError resulting from raising pyric.error incorrectly - o moved phyadd to _depr_phyadd issue #23 \ No newline at end of file + o made phyadd which accepts only the physical index and returns a card with + correct dev (w.r.t https://wraithwireless.wordpress.com/2016/07/24/linux-kernel-bug/) \ No newline at end of file diff --git a/README.md b/README.md index 1ef301f..dd77563 100644 --- a/README.md +++ b/README.md @@ -425,10 +425,10 @@ True Card(phy=0,dev=mon0,ifindex=4) >>> pyw.winterfaces() ['mon0', 'wlan0'] ->>> for iface in pyw.ifaces(w0): # delete all interfaces -... print iface -... if not iface[0].dev == m0.dev: # that are not our monitor -... pyw.devdel(iface[0]) # on the this phy +>>> for card,_ in pyw.ifaces(w0): # delete all interfaces +... print card +... if not card.dev == m0.dev: # that are not our monitor +... pyw.devdel(card) # on the this phy ... (Card(phy=0,dev=mon0,ifindex=4), 'monitor') (Card(phy=0,dev=wlan0,ifindex=3), 'managed') @@ -553,28 +553,10 @@ def pymon(card, start=True, ch=None): NOTE: After a recent kernel upgrade (see my post at https://wraithwireless.wordpress.com/2016/07/24/linux-kernel-bug/ for more details) -devadd became unusable. I have currently put a workaround in place and there are -now two methods to create a new card: phyadd and devadd. The function phyadd uses the -physical number of card and does not work as expected. In short, it will create a new -radio but not with the specified name. The function devadd uses the ifindex and works -as expected. For those individuals who system's start without devices the following -will work. - -```python -phys = pyw.phylist() -cards = [] -for i, phy in enumerate(phys): - dcard = pyw.phyadd(phy, "wlan{0}".format(i),'managed') - card = pyw.devadd(card,"wlan{0}".format(i),'managed') - pyw.devdel(dcard) - cards.append(card) -``` - -What this does is create a new card, dcard, for each phy using the phy as an -identifier. Then, because dcard does not have the name wlan but a system -generated one, we use it to create a new one, card with devadd which will have the -correct dev name. We finish up by deleting dcard and appending card to our list -of cards. +devadd became unusable. ATT, I have "fixed" devadd. Basically the original used +the physical index (iw phy interface add ...). Now, it uses the ifindex. +The function phyadd which only accepts the physical index (phy) is now implemented +to allow users whose systems start with any devs. #### vi. STA Related Functions I have recently begun adding STA functionality to PyRIC. These are not necessarily diff --git a/docs/PyRIC.pdf b/docs/PyRIC.pdf index 49b8306..99397ab 100644 Binary files a/docs/PyRIC.pdf and b/docs/PyRIC.pdf differ diff --git a/docs/PyRIC.tex b/docs/PyRIC.tex index 554ef8e..1c65ce1 100644 --- a/docs/PyRIC.tex +++ b/docs/PyRIC.tex @@ -19,8 +19,8 @@ % % __name__ = 'User Guide' %__license__ = 'GPLv3' -%__version__ = '0.0.5' -%__date__ = 'July 2016' +%__version__ = '0.0.6' +%__date__ = 'August 2016' %__author__ = 'Dale Patterson' %__maintainer__ = 'Dale Patterson' %__email__ = 'wraith.wireless@yandex.com' @@ -196,15 +196,16 @@ \subsection{Cards} A Card is merely a wrapper around a tuple t = (phy index,device name,ifindex). Since the underlying Netlink calls sometimes require the physical index, sometimes the device name, and sometimes the ifindex, pyw functions\footnote{Not all functions -accept a Card, devinfo() accept either a Card or a dev, devadd accepts either a Card -or a ifindex and phyadd accepts a card or a physical index} take a Card object which +accept only a Card, devinfo() accepts either a Card or a dev, devadd accepts either a +Card or a ifindex and phyadd accepts only a physical index} take a Card object which doesn't require callers to know which identifier to use for each function. There are four primary methods to creating a Card: \begin{enumerate} \item \textbf{pyw.getcard} returns a Card object from a given dev, \item \textbf{pyw.devinfo} returns the dict info where info['card'] is the Card -object. This function will take either a card or a dev -\item \textbf{pyw.devadd} returns a new Card object, +object. (This function will take either a card or a ifindex), +\item \textbf{pyw.devadd} returns a new Card object (this function will only take +a phy), \item \textbf{pyw.ifaces} returns a list of tuples t = (Card,mode) sharing the same phy as a given dev. \end{enumerate} @@ -328,76 +329,56 @@ \subsection{Interacting with the Wireless Core and Wireless NICs: pyw.py} language=Python] 1: import pyric # pyric error (and ecode EUNDEF) 2: from pyric import pyw # for iw functionality - 3: import pyric.utils.hardware as hw # for chipset/driver - 4: from pyric.utils.channels import rf2ch # rf to channel conversion - 5: - 6: dev = 'wlan0' - 7: ifaces = pyw.interfaces() - 8: wifaces = pyw.winterfaces() - 9: if dev not in ifaces: -10: print "Device {0} is not valid, use one of {1}".format(dev,ifaces) -11: return -12: elif dev not in wifaces: -13: print "Device {0} is not wireless, use one of {1}".format(dev,wifaces) -14: -15: print "Regulatory Domain currently: ", pyw.regget() -16: dinfo = pyw.devinfo(dev) -17: card = dinfo['card'] -18: pinfo = pyw.phyinfo(card) -19: driver = hw.ifdriver(card.dev) -20: chipset = hw.ifchipset(driver) -21: -22: pyw.down(card) -23: pyw.macset(card,'00:03:93:57:54:46') -24: -25: msg = "Using {0} currently in mode: {1}\n".format(card,dinfo['mode']) -26: msg += "\tDriver: {0} Chipset: {1}\n".format(driver,chipset) -27: if dinfo['mode'] == 'managed': -28: msg += "\ton channel {0} width {1}\n".format(rf2ch(dinfo['RF']), -29: dinfo['CHW']) -30: msg += "\tSupports modes {0}\n".format(pinfo['modes']) -31: msg += "\tSupports commands {0}".format(pinfo['commands']) -32: msg += "\thw addr {0}".format(pyw.macget(card)) -33: print msg -34: -35: pdev = 'pent0' -36: for iface in pyw.ifaces(card): -37: pyw.devdel(iface[0]) -38: pcard = pyw.devadd(card, pdev, 'monitor') -39: pyw.up(pcard) -40: pyw.chset(pcard,6,None) -41: -42: # DO STUFF HERE -43: -44: pyw.devdel(pcard) -45: -46: card = pyw.devadd(card,card.dev,dinfo['mode']) -47: pyw.macset(card,dinfo['mac']) -48: pyw.up(card) + 3: from pyric.utils.channels import rf2ch # rf to channel conversion + 4: + 5: dev = 'wlan0' + 6: dinfo = pyw.devinfo(dev) + 7: card = dinfo['card'] + 8: + 9: pyw.down(card) +10: pyw.macset(card,'00:03:93:57:54:46') +11: +12: pdev = 'pent0' +13: pcard = pyw.devadd(card, pdev, 'monitor') +14: for iface in pyw.ifaces(card): +15: if iface[0].dev != pcard.dev: +16: pyw.devdel(iface[0]) +17: pyw.up(pcard) +18: +19: pyw.chset(pcard,6,None) +20: +21: # DO stuff here +22: +23: card = pyw.devadd(pcard,card.dev,dinfo['mode']) +24: pyw.devdel(pcard) +25: pyw.macset(card,dinfo['mac']) +26: pyw.up(card) \end{lstlisting} -Listing \ref{lst:pentest} attempts to show most of the available pyw functions -in use and is the basic shell used in another project, Wraith\cite{wraith}, to -instantiate a wireless (802.11) sensor - (for a full listing of all pyw functions -see Appendix \ref{sec:pywapi}) - with scanning capabilities. Lines 1 and 2 should -always be included as they import the pyric error and pyw functions. Line 3 -imports hardware which provides the ifchipset and ifdriver functions and Line 4 -imports the rf2ch conversion function. \\ - -In lines 6 through 13, the device wlan0 is confirmed wireless and lines 16 through -20 a Card object for 'wlan0' is created and details about the interface are printed. -Next, the mac address of wlan0 is changed on lines 23. Note, the device is brought -down first. \\ - -More information on the device is printed in lines 25 through 33. Starting on -line 35, a device named 'pent0' is created in monitor mode. First in lines 36 -and 37, all interfaces on the same phy are deleted \footnote{we have found that -it is better to delete all interfaces on the same phy ensuring that external -processes don't interfere with the new device} before creating the new device, -bringing the card up and setting it to channel 6 NOHT.\\ - -Restoring the device starts on line 45, where the virtual interface is deleted, -the previous interface is restored and the mac address is reset. +Listing \ref{lst:pentest} shows basic pyw functions and is the basic shell used in +another project, Wraith\cite{wraith}, to instantiate a wireless (802.11) sensor - +(for a full listing of all pyw functions see Appendix \ref{sec:pywapi}) - with +scanning capabilities. \\ + +Lines 1 and 2 should always be included as they import the pyric error and pyw +functions. Line 3 imports the rf2ch conversion function. \\ + +In lines 5 through 10, a Card is created from the device wlan0. The info dict is save +IOT to restore later. Next, the mac address of wlan0 is changed. Note, the device has +to be brought down first. \\ + +Starting on line 12, a device named 'pent0' is created in monitor mode. First, a new +Card, pcard is create in monitor mode. Then, all interfaces on the same phy are +deleted \footnote{we have found that it is better to delete all interfaces on the +same phy ensuring that external processes don't interfere with the new device}. The +new Card is brought up and set to channel 6 NOHT.\\ + +Restoring the device starts on line 23, where the virtual interface is deleted, +the previous interface is restored, the mac address is reset and the old Card is +brought up. \\ + +An extended version of Listing \ref{lst:pentest} can be found in the examples +directory. \subsubsection{One-time vs Persistent Sockets} The example in Listing \ref{lst:pentest} uses one-time sockets (netlink and @@ -833,8 +814,8 @@ \subsection{Functions} \item modeget(card[nlsock]): (iw dev card. info | grep mode), type: netlink, get card's mode \item devset(card,ndev,[nlsock]): (N/A) sets the dev (name) of card to ndev -\item phyadd(card (or phy),vnic,mode,[flags],[nlsock]): (iw phy card. interface -add type flags )\footnote{There is a bug in some kernel v4.4.0-x +\item phyadd(phy,vnic,mode,[flags],[nlsock]): (iw phy interface add +type flags )\footnote{There is a bug in some kernel v4.4.0-x where the given dev name is ignored and a system chosen one is used instead. See https://wraithwireless.wordpress.com. Whenever possible, use devadd to create interfaces instead.}, type: netlink, creates a new virtual interface with dev vdev, @@ -842,7 +823,8 @@ \subsection{Functions} \item devadd(card (or ifindex),vnic,mode,[flags],[nlsock]): (iw phy card. interface add type flags ), type: netlink, creates a new virtual interface with dev vdev, in mode and using flags. Note: flags are only supported -when creating a monitor mode +when creating a monitor mode. This function accepts either a Card object or a +ifindex. \item devdel(card,[nlsock]): (iw card. del), type: netlink, deletes card \begin{itemize} \item isconnected(card, [nlsock]): (iw dev card. info | grep channel), type: diff --git a/examples/pentest.py b/examples/pentest.py index c4212b1..74e16f9 100644 --- a/examples/pentest.py +++ b/examples/pentest.py @@ -50,16 +50,14 @@ def execute(dev): # prepare a virtual interface named pent0 in monitor mode # delete all ifaces on the phy to avoid interference + # bring the card up when down print('Preparing pent0 for monitor mode') pdev = 'pent0' + pcard = pyw.devadd(card, pdev, 'monitor') for iface in pyw.ifaces(card): + if iface[0].dev != pcard.dev: print("deleting {0} in mode {1}".format(iface[0],iface[1])) pyw.devdel(iface[0]) - - # not we use the card that was deleted here. We can do this because - # devadd uses the physical index so even though the ifindex and dev are - # no longer valid, the physical index still is - pcard = pyw.devadd(card, pdev, 'monitor') pyw.up(pcard) print("Using", pcard) @@ -78,11 +76,10 @@ def execute(dev): pass # restore original - print("Restoring...\ndeleting ", pcard) - pyw.devdel(pcard) - print('Restoring', card, 'mode =', dinfo['mode'], 'mac =', dinfo['mac']) - card = pyw.devadd(card,card.dev,dinfo['mode']) + card = pyw.devadd(pcard,card.dev,dinfo['mode']) + print('Deleting', pcard) + pyw.devdel(pcard) pyw.macset(card,dinfo['mac']) pyw.up(card) print("card ", card, " restored") diff --git a/pyric/__init__.py b/pyric/__init__.py index 36dcfdd..89a4a4e 100644 --- a/pyric/__init__.py +++ b/pyric/__init__.py @@ -40,7 +40,7 @@ __name__ = 'pyric' __license__ = 'GPLv3' __version__ = '0.1.6' -__date__ = 'June 2016' +__date__ = 'August 2016' __author__ = 'Dale Patterson' __maintainer__ = 'Dale Patterson' __email__ = 'wraith.wireless@yandex.com' diff --git a/pyric/pyw.py b/pyric/pyw.py index 2fe2c99..8659b73 100644 --- a/pyric/pyw.py +++ b/pyric/pyw.py @@ -1601,6 +1601,68 @@ def devdel(card, *argv): except nl.error as e: raise pyric.error(e.errno, e.strerror) +def phyadd(phy, vdev, mode, flags=None, *argv): + """ + REQUIRES ROOT PRIVILEGES + adds a virtual interface on device having type mode (iw phy + interface add type + :param phy: physical index + :param vdev: device name of new interface + :param mode: 'name' of mode to operate in (must be one of in {'unspecified'| + 'ibss'|'managed'|'AP'|'AP VLAN'|'wds'|'monitor'|'mesh'|'p2p'} + :param flags: list of monitor flags (can only be used if creating monitor + mode) oneof {'invalid'|'fcsfail'|'plcpfail'|'control'|'other bss' + |'cook'|'active'} + :param argv: netlink socket at argv[0] (or empty) + :returns: the new Card + NOTE: due to a recent bug in kernel 4.4.0-x where x is APX 28, nl80211 + commands to add interface are not "respected" by the kernel. Namely, + the vdev is not used and the kernel adds a card with a "predictable" + name and furthermore, the new card has a different hw address (1 up from + the original card) + """ + if mode not in IFTYPES: raise pyric.error(pyric.EINVAL, 'Invalid mode') + if flags: + if mode != 'monitor': + raise pyric.error(pyric.EINVAL, 'Can only set flags in monitor mode') + for flag in flags: + if flag not in MNTRFLAGS: + raise pyric.error(pyric.EINVAL, 'Invalid flag: {0}'.format(flag)) + else: flags = [] + + try: + nlsock = argv[0] + except IndexError: + return _nlstub_(phyadd, phy, vdev, mode, flags) + + try: + msg = nl.nlmsg_new(nltype=_familyid_(nlsock), + cmd=nl80211h.NL80211_CMD_NEW_INTERFACE, + flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) + nl.nla_put_u32(msg, phy, nl80211h.NL80211_ATTR_WIPHY) + nl.nla_put_string(msg, vdev, nl80211h.NL80211_ATTR_IFNAME) + nl.nla_put_u32(msg, IFTYPES.index(mode), nl80211h.NL80211_ATTR_IFTYPE) + for flag in flags: + nl.nla_put_u32(msg, + MNTRFLAGS.index(flag), + nl80211h.NL80211_ATTR_MNTR_FLAGS) + nl.nl_sendmsg(nlsock, msg) + rmsg = nl.nl_recvmsg(nlsock) # success returns new device attributes + except AttributeError as e: + raise pyric.error(pyric.EINVAL, e) + except nl.error as e: + raise pyric.error(e.errno, e.strerror) + + # get card & determine if we got a card with the specified name + card = Card(nl.nla_find(rmsg, nl80211h.NL80211_ATTR_WIPHY), + nl.nla_find(rmsg, nl80211h.NL80211_ATTR_IFNAME), + nl.nla_find(rmsg, nl80211h.NL80211_ATTR_IFINDEX)) + if card.dev != vdev: + newcard = devadd(card,vdev,mode,flags) + devdel(card) + card = newcard + return card + ################################################################################ #### STA FUNCTIONS #### ################################################################################ @@ -2356,67 +2418,4 @@ def _fut_chset(card, ch, chw, *argv): nl.nla_put_u32(msg, channels.ch2rf(ch), nl80211h.NL80211_ATTR_WIPHY_FREQ) nl.nla_put_u32(msg, channels.CHTYPES.index(chw), nl80211h.NL80211_ATTR_WIPHY_CHANNEL_TYPE) nl.nl_sendmsg(nlsock, msg) - _ = nl.nl_recvmsg(nlsock) - -def _depr_phyadd(card, vdev, mode, flags=None, *argv): - """ - REQUIRES ROOT PRIVILEGES - adds a virtual interface on device having type mode (iw phy - interface add type - :param card: Card object or physical index - :param vdev: device name of new interface - :param mode: 'name' of mode to operate in (must be one of in {'unspecified'| - 'ibss'|'managed'|'AP'|'AP VLAN'|'wds'|'monitor'|'mesh'|'p2p'} - :param flags: list of monitor flags (can only be used if creating monitor - mode) oneof {'invalid'|'fcsfail'|'plcpfail'|'control'|'other bss' - |'cook'|'active'} - :param argv: netlink socket at argv[0] (or empty) - :returns: the new Card - NOTE: due to a recent bug in kernel 4.4.0-x where x is APX 28, nl80211 - commands to add interface are not "respected" by the kernel. Namely, - the vdev is not used and the kernel adds a card with a "predictable" - name and furthermore, the new card has a different hw address (1 up from - the original card) - """ - if mode not in IFTYPES: raise pyric.error(pyric.EINVAL, 'Invalid mode') - if flags: - if mode != 'monitor': - raise pyric.error(pyric.EINVAL, 'Can only set flags in monitor mode') - for flag in flags: - if flag not in MNTRFLAGS: - raise pyric.error(pyric.EINVAL, 'Invalid flag: {0}'.format(flag)) - else: flags = [] - - try: - nlsock = argv[0] - except IndexError: - return _nlstub_(phyadd, card, vdev, mode, flags) - - # if we have a Card, pull out phy index - try: - phy = card.phy - except AttributeError: - phy = card - - try: - msg = nl.nlmsg_new(nltype=_familyid_(nlsock), - cmd=nl80211h.NL80211_CMD_NEW_INTERFACE, - flags=nlh.NLM_F_REQUEST | nlh.NLM_F_ACK) - nl.nla_put_u32(msg, phy, nl80211h.NL80211_ATTR_WIPHY) - nl.nla_put_string(msg, vdev, nl80211h.NL80211_ATTR_IFNAME) - nl.nla_put_u32(msg, IFTYPES.index(mode), nl80211h.NL80211_ATTR_IFTYPE) - for flag in flags: - nl.nla_put_u32(msg, - MNTRFLAGS.index(flag), - nl80211h.NL80211_ATTR_MNTR_FLAGS) - nl.nl_sendmsg(nlsock, msg) - rmsg = nl.nl_recvmsg(nlsock) # success returns new device attributes - except AttributeError as e: - raise pyric.error(pyric.EINVAL, e) - except nl.error as e: - raise pyric.error(e.errno, e.strerror) - - # return the new Card with info from the results msg - return Card(nl.nla_find(rmsg, nl80211h.NL80211_ATTR_WIPHY), - nl.nla_find(rmsg, nl80211h.NL80211_ATTR_IFNAME), - nl.nla_find(rmsg, nl80211h.NL80211_ATTR_IFINDEX)) \ No newline at end of file + _ = nl.nl_recvmsg(nlsock) \ No newline at end of file