Skip to content

Instantly share code, notes, and snippets.

@drygdryg
Last active November 24, 2022 18:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drygdryg/8b372f6ec86fde2b8431e4e4d437f8e8 to your computer and use it in GitHub Desktop.
Save drygdryg/8b372f6ec86fde2b8431e4e4d437f8e8 to your computer and use it in GitHub Desktop.
A simple script for extracting RouterOS version from MikroTik Wi-Fi equipment over the air
#!/usr/bin/env python3
import subprocess
import sys
import re
import codecs
def ifaceUp(iface, down=False):
if down:
action = 'down'
else:
action = 'up'
cmd = 'ip link set {} {}'.format(iface, action)
res = subprocess.run(cmd, shell=True, stdout=sys.stdout, stderr=sys.stdout)
if res.returncode == 0:
return True
else:
return False
if __name__ == '__main__':
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <interface>")
exit(1)
interface = sys.argv[1]
if not ifaceUp(interface):
print(f'Unable to up interface "{interface}"')
exit(1)
cmd = 'iw dev {} scan -u'.format(interface)
proc = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, encoding='utf-8', errors='ignore')
lines = [line.strip('\t') for line in proc.stdout.splitlines()]
networks = []
for line in lines:
if match := re.match(r'BSS (\S+) ?\(on (\w+)\)', line): # Handle network
networks.append({'bssid': match.group(1)})
elif match := re.match(r'SSID: (.*)', line): # Handle ESSID
networks[-1]['essid'] = codecs.decode(match.group(1), "unicode-escape", errors='replace').encode("latin-1").decode("utf-8")
elif match := re.match(r'signal: ([+-]?(?:[0-9]*[.])?[0-9]+) dBm', line): # Handle signal level
networks[-1]['pwr'] = int(float(match.group(1)))
elif match := re.match(r'DS Parameter set: channel (\d+)', line):
networks[-1]['channel'] = int(match.group(1))
elif match := re.match(r'Vendor specific: OUI ((?:[0-9A-Fa-f]{2}:){2}[0-9A-Fa-f]{2}), data: ((?:[0-9A-Fa-f]{2} ?)*)', line):
oui = bytes.fromhex(match.group(1).replace(':', ''))
data = bytes.fromhex(match.group(2))
if oui == b'\x00\x0c\x42':
# Extract RouterOS version from an Information Element with Routerboard's OUI
if (not data[9:13]) or (data[9:13] == b'\x00\x00\x00\x00'):
continue
routeros_version_str = "{12}.{11}.{9}, {10}".format(*data)
networks[-1]['routeros_version'] = routeros_version_str
# Sort network list by signal level
networks.sort(key=lambda network: network['pwr'], reverse=True)
# Print network list
print('{:<18} {:<3} {:<4} {:<18} {}'.format('BSSID', 'CH', 'PWR', 'RouterOS version', 'ESSID'))
for network in networks:
if 'routeros_version' in network:
print('{:<18} {:<3} {:<4} {:<18} {}'.format(
network['bssid'], network['channel'],
network['pwr'], network['routeros_version'], network['essid'])
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment