Last active
November 24, 2022 18:27
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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