diff --git a/docs/API.md b/docs/API.md index b6f4db6f..83a85ac1 100755 --- a/docs/API.md +++ b/docs/API.md @@ -21,7 +21,6 @@ You can access the following files: | `notification_text.html` | The full HTML of the last email notification. | | `notification_json_final.json` | The json version of the last notification (e.g. used for webhooks - [sample JSON](https://github.com/jokob-sk/NetAlertX/blob/main/front/report_templates/webhook_json_sample.json)). | | `table_devices.json` | The current (at the time of the last update as mentioned above on this page) state of all of the available Devices detected by the app. | - | `table_pholus_scan.json` | The latest state of the [pholus](https://github.com/jokob-sk/NetAlertX/tree/main/pholus) (A multicast DNS and DNS Service Discovery Security Assessment Tool) scan results. | | `table_plugins_events.json` | The list of the unprocessed (pending) notification events (plugins_events DB table). | | `table_plugins_history.json` | The list of notification events history. | | `table_plugins_objects.json` | The content of the plugins_objects table. Find more info on the [Plugin system here](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins)| diff --git a/docs/DATABASE.md b/docs/DATABASE.md index 60665c0f..de4beb47 100755 --- a/docs/DATABASE.md +++ b/docs/DATABASE.md @@ -14,7 +14,6 @@ | Events | Used to collect connection/disconnection events. | ![Screen4][screen4] | | Online_History | Used to display the `Device presence` chart | ![Screen6][screen6] | | Parameters | Used to pass values between the frontend and backend. | ![Screen7][screen7] | - | Pholus_Scan | Scan results of the Pholus python network penetration script. | ![Screen8][screen8] | | Plugins_Events | For capturing events exposed by a plugin via the `last_result.log` file. If unique then saved into the `Plugins_Objects` table. Entries are deleted once processed and stored in the `Plugins_History` and/or `Plugins_Objects` tables. | ![Screen10][screen10] | | Plugins_History | History of all entries from the `Plugins_Events` table | ![Screen11][screen11] | | Plugins_Language_Strings | Language strings collected from the plugin `config.json` files used for string resolution in the frontend. | ![Screen12][screen12] | @@ -29,7 +28,6 @@ [screen4]: /docs/img/DATABASE/Events.png [screen6]: /docs/img/DATABASE/Online_History.png [screen7]: /docs/img/DATABASE/Parameters.png - [screen8]: /docs/img/DATABASE/Pholus_Scan.png [screen10]: /docs/img/DATABASE/Plugins_Events.png [screen11]: /docs/img/DATABASE/Plugins_History.png [screen12]: /docs/img/DATABASE/Plugins_Language_Strings.png diff --git a/front/devices.php b/front/devices.php index e3d565b0..82d7258b 100755 --- a/front/devices.php +++ b/front/devices.php @@ -15,6 +15,7 @@
+
@@ -62,40 +64,6 @@ - -
diff --git a/front/php/components/graph_online_history.php b/front/php/components/graph_online_history.php new file mode 100755 index 00000000..916c1a02 --- /dev/null +++ b/front/php/components/graph_online_history.php @@ -0,0 +1,42 @@ + + + + \ No newline at end of file diff --git a/front/php/server/util.php b/front/php/server/util.php index fbef9d1a..68532cf1 100755 --- a/front/php/server/util.php +++ b/front/php/server/util.php @@ -258,7 +258,7 @@ function cleanLog($logFile) $path = ""; - $allowedFiles = ['app.log', 'app_front.log', 'IP_changes.log', 'stdout.log', 'stderr.log', "pholus_lastrun.log", 'app.php_errors.log', 'execution_queue.log']; + $allowedFiles = ['app.log', 'app_front.log', 'IP_changes.log', 'stdout.log', 'stderr.log', 'app.php_errors.log', 'execution_queue.log']; if(in_array($logFile, $allowedFiles)) { diff --git a/front/php/templates/language/en_us.json b/front/php/templates/language/en_us.json index 9f0aa0cc..712bfad9 100755 --- a/front/php/templates/language/en_us.json +++ b/front/php/templates/language/en_us.json @@ -578,7 +578,7 @@ "REPORT_TITLE": "Report", "RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address.", "Reports_Sent_Log": "Sent Reports Log", - "SCAN_SUBNETS_description": "Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) rely on scanning specific network interfaces and subnets. Check the subnets documentation for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface.

An alternative to on-network scanners is to enable some other Device scanners/importers that don't rely on NetAlertX having access to the network (UNIFI, dhcp.leases, PiHole, etc.).

Note: The scan time itself depends on the number of IP addresses to check, so set this up carefully with the appropriate network mask and interface.", + "SCAN_SUBNETS_description": "Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG) rely on scanning specific network interfaces and subnets. Check the subnets documentation for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface.

An alternative to on-network scanners is to enable some other Device scanners/importers that don't rely on NetAlertX having access to the network (UNIFI, dhcp.leases, PiHole, etc.).

Note: The scan time itself depends on the number of IP addresses to check, so set this up carefully with the appropriate network mask and interface.", "SCAN_SUBNETS_name": "Networks to scan", "SYSTEM_TITLE": "System Information", "Setting_Override": "Override value", diff --git a/front/php/templates/language/es_es.json b/front/php/templates/language/es_es.json index d045db07..cb008018 100755 --- a/front/php/templates/language/es_es.json +++ b/front/php/templates/language/es_es.json @@ -631,7 +631,7 @@ "REPORT_WEBHOOK_name": "Habilitar webhooks", "RandomMAC_hover": "Autodetectado - indica si el dispositivo aleatoriza su dirección MAC.", "Reports_Sent_Log": "Registro de informes enviados", - "SCAN_SUBNETS_description": "La mayoría de los escáneres en red (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) se basan en el escaneo de interfaces de red y subredes específicas. Consulte la documentación sobre subredes para obtener ayuda sobre esta configuración, especialmente VLANs, qué VLANs son compatibles, o cómo averiguar la máscara de red y su interfaz.

Una alternativa a los escáneres en red es habilitar algunos otros escáneres/importadores de dispositivos que no dependen de que NetAlertX tenga acceso a la red (UNIFI, dhcp.leases, PiHole, etc.).

Nota: El tiempo de escaneo en sí depende del número de direcciones IP a comprobar, así que configure esto cuidadosamente con la máscara de red y la interfaz adecuadas.", + "SCAN_SUBNETS_description": "La mayoría de los escáneres en red (ARP-SCAN, NMAP, NSLOOKUP, DIG) se basan en el escaneo de interfaces de red y subredes específicas. Consulte la documentación sobre subredes para obtener ayuda sobre esta configuración, especialmente VLANs, qué VLANs son compatibles, o cómo averiguar la máscara de red y su interfaz.

Una alternativa a los escáneres en red es habilitar algunos otros escáneres/importadores de dispositivos que no dependen de que NetAlertX tenga acceso a la red (UNIFI, dhcp.leases, PiHole, etc.).

Nota: El tiempo de escaneo en sí depende del número de direcciones IP a comprobar, así que configure esto cuidadosamente con la máscara de red y la interfaz adecuadas.", "SCAN_SUBNETS_name": "Subredes para escanear", "SMTP_FORCE_SSL_description": "Forzar SSL al conectarse a su servidor SMTP", "SMTP_FORCE_SSL_name": "Forzar SSL", diff --git a/front/php/templates/language/it_it.json b/front/php/templates/language/it_it.json old mode 100644 new mode 100755 index b7b5c810..a3e60759 --- a/front/php/templates/language/it_it.json +++ b/front/php/templates/language/it_it.json @@ -578,7 +578,7 @@ "REPORT_TITLE": "Rapporto", "RandomMAC_hover": "Rilevato automaticamente: indica se il dispositivo genera il suo indirizzo MAC casualmente.", "Reports_Sent_Log": "Log rapporti inviati", - "SCAN_SUBNETS_description": "La maggior parte degli scanner di rete (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) si basano sulla scansione di interfacce di rete e sottoreti specifiche. Consulta la documentazione sulle sottoreti per assistenza su questa impostazione, in particolare VLAN, quali VLAN sono supportate o come individuare la maschera di rete e l'interfaccia.

Un'alternativa agli scanner in rete è abilitare altri scanner/importatori di dispositivi che non si affidano a NetAlertX che hanno accesso alla rete (UNIFI, dhcp.leases , PiHole, ecc.).

Nota: il tempo di scansione stesso dipende dal numero di indirizzi IP da controllare, quindi impostalo attentamente con la maschera di rete e l'interfaccia appropriate.", + "SCAN_SUBNETS_description": "La maggior parte degli scanner di rete (ARP-SCAN, NMAP, NSLOOKUP, DIG) si basano sulla scansione di interfacce di rete e sottoreti specifiche. Consulta la documentazione sulle sottoreti per assistenza su questa impostazione, in particolare VLAN, quali VLAN sono supportate o come individuare la maschera di rete e l'interfaccia.

Un'alternativa agli scanner in rete è abilitare altri scanner/importatori di dispositivi che non si affidano a NetAlertX che hanno accesso alla rete (UNIFI, dhcp.leases , PiHole, ecc.).

Nota: il tempo di scansione stesso dipende dal numero di indirizzi IP da controllare, quindi impostalo attentamente con la maschera di rete e l'interfaccia appropriate.", "SCAN_SUBNETS_name": "Reti da scansionare", "SYSTEM_TITLE": "Informazioni sistema", "Setting_Override": "Sovrascrivi valore", diff --git a/front/php/templates/language/nb_no.json b/front/php/templates/language/nb_no.json index 16f3f5f0..9ae97bb3 100755 --- a/front/php/templates/language/nb_no.json +++ b/front/php/templates/language/nb_no.json @@ -578,7 +578,7 @@ "REPORT_TITLE": "Rapport", "RandomMAC_hover": "Autodetektert - indikerer om enheten randomiserer MAC-adressen sin.", "Reports_Sent_Log": "Sendte rapport logger", - "SCAN_SUBNETS_description": "De fleste skannere på nettet (ARP-Scan, NMAP, NSlookup, Dig, Pholus) er avhengige av å skanne spesifikke nettverksgrensesnitt og undernett. Sjekk subnett dokumentasjonen for hjelp på denne innstillingen, spesielt VLAN-er, hvilke VLAN-er som støttes, eller hvordan du kan finne ut nettverksmasken og grensesnittet ditt.

Et alternativ til skannere på nettet er å aktivere noen andre enhetsskannere/importører som ikke er avhengige av NetalertX med tilgang til nettverket (UniFi, DHCP-Leaser, Pihole, osv.).

Merk: Selve skanningstiden avhenger av antall IP -adresser som skal sjekkes, så sett dette opp nøye med riktig nettverksmaske og grensesnitt.", + "SCAN_SUBNETS_description": "De fleste skannere på nettet (ARP-Scan, NMAP, NSlookup, Dig) er avhengige av å skanne spesifikke nettverksgrensesnitt og undernett. Sjekk subnett dokumentasjonen for hjelp på denne innstillingen, spesielt VLAN-er, hvilke VLAN-er som støttes, eller hvordan du kan finne ut nettverksmasken og grensesnittet ditt.

Et alternativ til skannere på nettet er å aktivere noen andre enhetsskannere/importører som ikke er avhengige av NetalertX med tilgang til nettverket (UniFi, DHCP-Leaser, Pihole, osv.).

Merk: Selve skanningstiden avhenger av antall IP -adresser som skal sjekkes, så sett dette opp nøye med riktig nettverksmaske og grensesnitt.", "SCAN_SUBNETS_name": "", "SYSTEM_TITLE": "Systeminformasjon", "Setting_Override": "Overstyr verdi", diff --git a/front/php/templates/language/pl_pl.json b/front/php/templates/language/pl_pl.json index 61d693d2..ed493707 100755 --- a/front/php/templates/language/pl_pl.json +++ b/front/php/templates/language/pl_pl.json @@ -578,7 +578,7 @@ "REPORT_TITLE": "Zgłoszenie", "RandomMAC_hover": "Auto wykrywanie - oznacza czy urządzenie randomizuje swój adres MAC.", "Reports_Sent_Log": "Wyślij zgłoszenie logów", - "SCAN_SUBNETS_description": "Większość skanerów sieciowych (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) opiera się na konkretnych interfejsach sieciowych oraz podsieci. Sprawdź dokumentacji podsieci jeżeli potrzebujesz pomocy w ustawieniach, a szczególnie z VLAN'ami, jakie VLAN'y są wspierane oraz jak rozgryźć maskę podsieci twojego interfejsu.

Alternatywą do skanerów sieciowych jest uruchomienie innego Skanera Urządzeń/Importera który nie polega by NetAlertX miał dostęp do sieci (UNIFI, dhcp.leases, PiHole, itp.).

Notatka: Czas skanu zależy od liczby adresów IP do sprawdzenia, więc ustaw go tak by skanował odpowiedni interfejs i maskę sieciową.", + "SCAN_SUBNETS_description": "Większość skanerów sieciowych (ARP-SCAN, NMAP, NSLOOKUP, DIG) opiera się na konkretnych interfejsach sieciowych oraz podsieci. Sprawdź dokumentacji podsieci jeżeli potrzebujesz pomocy w ustawieniach, a szczególnie z VLAN'ami, jakie VLAN'y są wspierane oraz jak rozgryźć maskę podsieci twojego interfejsu.

Alternatywą do skanerów sieciowych jest uruchomienie innego Skanera Urządzeń/Importera który nie polega by NetAlertX miał dostęp do sieci (UNIFI, dhcp.leases, PiHole, itp.).

Notatka: Czas skanu zależy od liczby adresów IP do sprawdzenia, więc ustaw go tak by skanował odpowiedni interfejs i maskę sieciową.", "SCAN_SUBNETS_name": "", "SYSTEM_TITLE": "Informacje o Systemie", "Setting_Override": "Nadpisz wartość", diff --git a/front/php/templates/language/ru_ru.json b/front/php/templates/language/ru_ru.json index d8aa5862..63bc3855 100755 --- a/front/php/templates/language/ru_ru.json +++ b/front/php/templates/language/ru_ru.json @@ -578,7 +578,7 @@ "REPORT_TITLE": "Отчет", "RandomMAC_hover": "Автоматически обнаружено — указывает, рандомизирует ли устройство свой MAC-адрес.", "Reports_Sent_Log": "Отправленные уведомления", - "SCAN_SUBNETS_description": "Большинство сетевых сканеров (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) полагаются на сканирование определенных сетевых интерфейсов и подсетей. Дополнительную информацию по этому параметру можно найти в документации по подсетям, особенно VLAN, какие VLAN поддерживаются или как разобраться в маске сети и своем интерфейсе.

Альтернативой сетевым сканерам является включение некоторых других сканеров/импортеров устройств, которые не полагаются на NetAlertX, имеющий доступ к сети (UNIFI, dhcp.leases , PiHole и др.).

Примечание. Само время сканирования зависит от количества проверяемых IP-адресов, поэтому тщательно настройте его, указав соответствующую маску сети и интерфейс.", + "SCAN_SUBNETS_description": "Большинство сетевых сканеров (ARP-SCAN, NMAP, NSLOOKUP, DIG) полагаются на сканирование определенных сетевых интерфейсов и подсетей. Дополнительную информацию по этому параметру можно найти в документации по подсетям, особенно VLAN, какие VLAN поддерживаются или как разобраться в маске сети и своем интерфейсе.

Альтернативой сетевым сканерам является включение некоторых других сканеров/импортеров устройств, которые не полагаются на NetAlertX, имеющий доступ к сети (UNIFI, dhcp.leases , PiHole и др.).

Примечание. Само время сканирования зависит от количества проверяемых IP-адресов, поэтому тщательно настройте его, указав соответствующую маску сети и интерфейс.", "SCAN_SUBNETS_name": "Сети для сканирования", "SYSTEM_TITLE": "Системная информация", "Setting_Override": "Переопределить значение", diff --git a/front/php/templates/language/zh_cn.json b/front/php/templates/language/zh_cn.json index 06c0266f..2a626a53 100755 --- a/front/php/templates/language/zh_cn.json +++ b/front/php/templates/language/zh_cn.json @@ -578,7 +578,7 @@ "REPORT_TITLE": "报告", "RandomMAC_hover": "自动检测 - 表示设备是否随机化其 MAC 地址。", "Reports_Sent_Log": "已发送报告日志", - "SCAN_SUBNETS_description": "大多数网络扫描器(ARP-SCAN、NMAP、NSLOOKUP、DIG、PHOLUS)依赖于扫描特定的网络接口和子网。查看子网文档以获取有关此设置的帮助,尤其是 VLAN、支持哪些 VLAN,或者如何确定网络掩码和接口。

网络扫描器的替代方法是启用一些其他不依赖于 NetAlertX 访问网络的设备扫描器/导入器(UNIFI、dhcp.leases、PiHole 等)。

注意:扫描时间本身取决于要检查的 IP 地址数量,因此请使用适当的网络掩码和接口仔细设置。", + "SCAN_SUBNETS_description": "大多数网络扫描器(ARP-SCAN、NMAP、NSLOOKUP、DIG)依赖于扫描特定的网络接口和子网。查看子网文档以获取有关此设置的帮助,尤其是 VLAN、支持哪些 VLAN,或者如何确定网络掩码和接口。

网络扫描器的替代方法是启用一些其他不依赖于 NetAlertX 访问网络的设备扫描器/导入器(UNIFI、dhcp.leases、PiHole 等)。

注意:扫描时间本身取决于要检查的 IP 地址数量,因此请使用适当的网络掩码和接口仔细设置。", "SCAN_SUBNETS_name": "", "SYSTEM_TITLE": "系统信息", "Setting_Override": "覆盖值", diff --git a/front/plugins/README.md b/front/plugins/README.md index 3153ed3b..ee13e064 100755 --- a/front/plugins/README.md +++ b/front/plugins/README.md @@ -45,7 +45,6 @@ Device-detecting plugins insert values into the `CurrentScan` database table. T | `NTFPRCS` | ⚙ | Notification processing | | Yes | Template | [notification_processing](/front/plugins/notification_processing/)| | `NTFY` | ▶️ | NTFY notifications | | | Script | [_publisher_ntfy](/front/plugins/_publisher_ntfy/) | | `OMDSDN` | 📥 | OMADA TP-Link import | 🖧 🔄 | | Script | [omada_sdn_imp](/front/plugins/omada_sdn_imp/) | -| `PHOLUS` | ♻ | Pholus name resolution | | | Script | [pholus_scan](/front/plugins/pholus_scan/) | | `PIHOLE` | 🔍/📥 | Pi-hole device import & sync | | | SQLite DB | [pihole_scan](/front/plugins/pihole_scan/) | | `PUSHSAFER` | ▶️ | Pushsafer notifications | | | Script | [_publisher_pushsafer](/front/plugins/_publisher_pushsafer/) | | `PUSHOVER` | ▶️ | Pushover notifications | | | Script | [_publisher_pushover](/front/plugins/_publisher_pushover/) | diff --git a/front/plugins/arp_scan/README.md b/front/plugins/arp_scan/README.md index c1fe57e2..2f6fe160 100755 --- a/front/plugins/arp_scan/README.md +++ b/front/plugins/arp_scan/README.md @@ -1,6 +1,6 @@ ## Overview -Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG, PHOLUS) rely on scanning specific network interfaces and subnets. Check the [subnets documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md) for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface. +Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG) rely on scanning specific network interfaces and subnets. Check the [subnets documentation](https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md) for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface. An alternative to on-network scanners is to enable some other Device scanners/importers that don't rely on NetAlertX having access to the network (UNIFI, dhcp.leases, PiHole, etc.). diff --git a/front/plugins/db_cleanup/README.md b/front/plugins/db_cleanup/README.md index eb87639d..c896aeb4 100755 --- a/front/plugins/db_cleanup/README.md +++ b/front/plugins/db_cleanup/README.md @@ -13,8 +13,6 @@ The database cleanup plugin (DBCLNP) helps maintain the system by removing outda - **`DAYS_TO_KEEP_EVENTS`**: Specifies the number of days to retain event logs. Event entries older than the given number of days will be automatically deleted during cleanup. Recommended value: `30` days. -- **`PHOLUS_DAYS_DATA`**: - Deletes all data older than specified number of days for teh Pholus plugin used for name discovery. Recommended value: `30` days. By fine-tuning these settings, you ensure that the database remains optimized, preventing performance degradation in the NetAlertX system. diff --git a/front/plugins/db_cleanup/script.py b/front/plugins/db_cleanup/script.py index 20bb7ce2..ea7c8817 100755 --- a/front/plugins/db_cleanup/script.py +++ b/front/plugins/db_cleanup/script.py @@ -36,14 +36,13 @@ def main(): HRS_TO_KEEP_NEWDEV = int(get_setting_value("HRS_TO_KEEP_NEWDEV")) HRS_TO_KEEP_OFFDEV = int(get_setting_value("HRS_TO_KEEP_OFFDEV")) DAYS_TO_KEEP_EVENTS = int(get_setting_value("DAYS_TO_KEEP_EVENTS")) - PHOLUS_DAYS_DATA = get_setting_value("PHOLUS_DAYS_DATA") CLEAR_NEW_FLAG = get_setting_value("CLEAR_NEW_FLAG") mylog('verbose', [f'[{pluginName}] In script']) # Execute cleanup/upkeep - cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, HRS_TO_KEEP_OFFDEV, PLUGINS_KEEP_HIST, CLEAR_NEW_FLAG) + cleanup_database(fullDbPath, DAYS_TO_KEEP_EVENTS, HRS_TO_KEEP_NEWDEV, HRS_TO_KEEP_OFFDEV, PLUGINS_KEEP_HIST, CLEAR_NEW_FLAG) mylog('verbose', [f'[{pluginName}] Cleanup complete']) @@ -52,7 +51,7 @@ def main(): #=============================================================================== # Cleanup / upkeep database #=============================================================================== -def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP_NEWDEV, HRS_TO_KEEP_OFFDEV, PLUGINS_KEEP_HIST, CLEAR_NEW_FLAG): +def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, HRS_TO_KEEP_NEWDEV, HRS_TO_KEEP_OFFDEV, PLUGINS_KEEP_HIST, CLEAR_NEW_FLAG): """ Cleaning out old records from the tables that don't need to keep all data. """ @@ -163,29 +162,6 @@ def cleanup_database (dbPath, DAYS_TO_KEEP_EVENTS, PHOLUS_DAYS_DATA, HRS_TO_KEEP cursor.execute(query) - - # ----------------------------------------------------- - # Cleanup Pholus_Scan - if PHOLUS_DAYS_DATA != "" and PHOLUS_DAYS_DATA != 0: - mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all older than ' + str(PHOLUS_DAYS_DATA) + ' days (PHOLUS_DAYS_DATA setting)']) - # todo: improvement possibility: keep at least N per mac - cursor.execute (f"""DELETE FROM Pholus_Scan - WHERE Time <= date('now', '-{str(PHOLUS_DAYS_DATA)} day')""") - - - - # ----------------------------------------------------- - # De-Dupe (de-duplicate - remove duplicate entries) from the Pholus_Scan table - mylog('verbose', [f'[{pluginName}] Pholus_Scan: Delete all duplicates']) - cursor.execute ("""DELETE FROM Pholus_Scan - WHERE rowid > ( - SELECT MIN(rowid) FROM Pholus_Scan p2 - WHERE Pholus_Scan.MAC = p2.MAC - AND Pholus_Scan.Value = p2.Value - AND Pholus_Scan.Record_Type = p2.Record_Type - );""") - - # ----------------------------------------------------- # De-dupe (de-duplicate) from the Plugins_Objects table # TODO This shouldn't be necessary - probably a concurrency bug somewhere in the code :( diff --git a/front/plugins/pholus_scan/README.md b/front/plugins/pholus_scan/README.md deleted file mode 100755 index 1d2e9945..00000000 --- a/front/plugins/pholus_scan/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Overview - -A plugin to resolve `(unknown)` device names. It uses the [Pholus](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/pholus_scan/pholus) sniffing tool. - -### Usage - -- Go to settings and find Pholus (Name discovery) in the list of settings. -- Enable the plugin by changing the `RUN` parameter from disabled to one you prefer (`schedule`, `always_after_scan`, `on_new_device`). -- Specify the `PHOLUS_RUN_TIMEOUT` (Will be divided by the number of subnets specified in the Arp-Scan (Network scan) plugin setting `SCAN_SUBNETS`) -- SAVE -- Wait for the next scan to finish - - diff --git a/front/plugins/pholus_scan/config.json b/front/plugins/pholus_scan/config.json deleted file mode 100755 index 0ee12eef..00000000 --- a/front/plugins/pholus_scan/config.json +++ /dev/null @@ -1,517 +0,0 @@ -{ - "code_name": "pholus_scan", - "unique_prefix": "PHOLUS", - "plugin_type": "other", - "enabled": true, - "data_source": "script", - "mapped_to_table": "Pholus_Scan", - "data_filters": [ - { - "compare_column": "Object_PrimaryID", - "compare_operator": "==", - "compare_field_id": "txtMacFilter", - "compare_js_template": "'{value}'.toString()", - "compare_use_quotes": true - } - ], - "show_ui": true, - "localized": ["display_name", "description", "icon"], - "display_name": [ - { - "language_code": "en_us", - "string": "Pholus (Name discovery)" - }, - { - "language_code": "es_es", - "string": "Pholus (Descubrimiento de nombre)" - } - ], - "icon": [ - { - "language_code": "en_us", - "string": "" - }, - { - "language_code": "es_es", - "string": "" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "This plugin is to execute a Pholus (name discovery) on the local network" - }, - { - "language_code": "es_es", - "string": "Este plugin sirve para ejecutar un escaneo Pholus (descubrimiento de nombres) en la red local" - } - ], - "params": [ - { - "name": "subnets", - "type": "setting", - "value": "SCAN_SUBNETS", - "base64": true - }, - { - "name": "timeout", - "type": "setting", - "value": "PHOLUS_RUN_TIMEOUT" - } - ], - "settings": [ - { - "function": "RUN", - "type": { - "dataType": "string", - "elements": [ - { "elementType": "select", "elementOptions": [], "transformers": [] } - ] - }, - "default_value": "disabled", - "options": [ - "disabled", - "once", - "schedule", - "always_after_scan", - "on_new_device" - ], - "localized": ["name", "description"], - "events": ["run"], - "name": [ - { - "language_code": "en_us", - "string": "When to run" - }, - { - "language_code": "es_es", - "string": "Cuando ejecutar" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Pholus is a sniffing tool to discover additional information about the devices on the network, including the device name. If enabled this will execute the scan before every network scan cycle until there are no (unknown) or (name not found) devices. Please be aware it can spam the network with unnecessary traffic. Depends on the SCAN_SUBNETS setting. For a scheduled or one-off scan, check the PHOLUS_RUN setting.Specify when your Name-discovery scan will run. Typical setting would be on_new_device or schedule and then you specify a cron-like schedule in the PHOLUS_RUN_SCHDsetting." - }, - { - "language_code": "es_es", - "string": "Pholus es una herramienta de rastreo para descubrir información adicional sobre los dispositivos en la red, incluido el nombre del dispositivo. Si está habilitado, ejecutará el escaneo antes de cada ciclo de escaneo de red hasta que no haya dispositivos (unknown) o (name not found). Tenga en cuenta que puede enviar spam a la red con tráfico innecesario. Depende de la configuración de SCAN_SUBNETS. Para un análisis programado o único, verifique la configuración de PHOLUS_RUN." - } - ] - }, - { - "function": "CMD", - "type": { - "dataType": "string", - "elements": [ - { - "elementType": "input", - "elementOptions": [{ "readonly": "true" }], - "transformers": [] - } - ] - }, - "default_value": "python3 /app/front/plugins/pholus_scan/script.py userSubnets={subnets} timeoutSec={timeout}", - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Command" - }, - { - "language_code": "es_es", - "string": "Comando" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Command to run. This should not be changed" - }, - { - "language_code": "es_es", - "string": "Comando para ejecutar. Esto no debe ser cambiado" - } - ] - }, - { - "function": "RUN_TIMEOUT", - "type": { - "dataType": "integer", - "elements": [ - { - "elementType": "input", - "elementOptions": [{ "type": "number" }], - "transformers": [] - } - ] - }, - "default_value": 300, - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Run timeout" - }, - { - "language_code": "es_es", - "string": "Tiempo límite de ejecución" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Network scan time in seconds. Pholus scan will always run this long. The longer it runs the more device names might be resolved. Will be divided by the number of subnets." - }, - { - "language_code": "es_es", - "string": "Tiempo de escaneo de red en segundos. El escaneo de Pholus siempre durará este tiempo. Cuanto más tiempo se ejecute, más nombres de dispositivos se podrán resolver. Se dividirá por el número de subredes." - } - ] - }, - { - "function": "RUN_SCHD", - "type": { - "dataType": "string", - "elements": [ - { "elementType": "input", "elementOptions": [], "transformers": [] } - ] - }, - "default_value": "30 3 * * *", - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Schedule" - }, - { - "language_code": "es_es", - "string": "Schedule" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Only enabled if you select schedule in the PHOLUS_RUN setting. Make sure you enter the schedule in the correct cron-like format (e.g. validate at crontab.guru). For example entering 30 3 * * * will run the scan at 3:30 am. Will be run NEXT time the time passes.
" - }, - { - "language_code": "es_es", - "string": "Solo está habilitado si selecciona schedule en la configuración PHOLUS_RUN. Asegúrese de ingresar la programación en el formato cron correcto (por ejemplo, validar en crontab.guru). Por ejemplo, al ingresar 30 3 * * * se ejecutará el escaneo a las 3:30 am. Se ejecutará la PRÓXIMA vez que pase el tiempo.
" - } - ] - }, - { - "function": "DAYS_DATA", - "type": { - "dataType": "integer", - "elements": [ - { - "elementType": "input", - "elementOptions": [{ "type": "number" }], - "transformers": [] - } - ] - }, - "default_value": 30, - "options": [], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Retention of data" - }, - { - "language_code": "es_es", - "string": "Retención de datos" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "How many days of Pholus scan entries should be kept (globally, not device specific!) Enter 0 to disable." - }, - { - "language_code": "es_es", - "string": "Cuántos días de entradas de escaneo de Pholus deben conservarse (globalmente, ¡no específico del dispositivo!). Introduzca 0 para desactivar." - } - ] - }, - { - "function": "WATCH", - "type": { - "dataType": "array", - "elements": [ - { - "elementType": "select", - "elementOptions": [{ "multiple": "true" }], - "transformers": [] - } - ] - }, - "default_value": ["Watched_Value1", "Watched_Value2"], - "options": [ - "Watched_Value1", - "Watched_Value2", - "Watched_Value3", - "Watched_Value4" - ], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Watched" - }, - { - "language_code": "es_es", - "string": "Watched" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "Send a notification if selected values change. Use CTRL + Click to select/deselect. " - }, - { - "language_code": "es_es", - "string": "Enviar una notificación si los valores seleccionados cambian. Utilice CTRL + Clic para seleccionar/deseleccionar. " - } - ] - }, - { - "function": "REPORT_ON", - "type": { - "dataType": "array", - "elements": [ - { - "elementType": "select", - "elementOptions": [{ "multiple": "true" }], - "transformers": [] - } - ] - }, - "default_value": ["new"], - "options": [ - "new", - "watched-changed", - "watched-not-changed", - "missing-in-last-scan" - ], - "localized": ["name", "description"], - "name": [ - { - "language_code": "en_us", - "string": "Report on" - }, - { - "language_code": "es_es", - "string": "Informar sobre" - } - ], - "description": [ - { - "language_code": "en_us", - "string": "When should notification be sent out." - }, - { - "language_code": "es_es", - "string": "Cuándo debe enviarse una notificación." - } - ] - } - ], - "database_column_definitions": [ - { - "column": "Index", - "css_classes": "col-sm-2", - "show": true, - "type": "none", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Index" - } - ] - }, - { - "column": "Object_PrimaryID", - "mapped_to_column": "MAC", - "css_classes": "col-sm-2", - "show": true, - "type": "device_name_mac", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "MAC" - }, - { - "language_code": "es_es", - "string": "MAC" - } - ] - }, - { - "column": "Object_SecondaryID", - "mapped_to_column": "IP_v4_or_v6", - "css_classes": "col-sm-2", - "show": true, - "type": "label", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "IP" - }, - { - "language_code": "es_es", - "string": "IP" - } - ] - }, - { - "column": "Watched_Value1", - "mapped_to_column": "Info", - "css_classes": "col-sm-2", - "show": true, - "type": "label", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Info" - }, - { - "language_code": "es_es", - "string": "Info" - } - ] - }, - { - "column": "Watched_Value2", - "mapped_to_column": "Record_Type", - "css_classes": "col-sm-2", - "show": true, - "type": "label", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Type" - }, - { - "language_code": "es_es", - "string": "Tipo" - } - ] - }, - { - "column": "Watched_Value3", - "mapped_to_column": "Value", - "css_classes": "col-sm-2", - "show": true, - "type": "label", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Info" - }, - { - "language_code": "es_es", - "string": "Info" - } - ] - }, - { - "column": "DateTimeCreated", - "mapped_to_column": "Time", - "css_classes": "col-sm-2", - "show": true, - "type": "label", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Created" - }, - { - "language_code": "es_es", - "string": "Creado" - } - ] - }, - { - "column": "DateTimeChanged", - "css_classes": "col-sm-2", - "show": true, - "type": "label", - "default_value": "", - "options": [], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Changed" - }, - { - "language_code": "es_es", - "string": "Cambiado" - } - ] - }, - { - "column": "Status", - "css_classes": "col-sm-1", - "show": true, - "type": "replace", - "default_value": "", - "options": [ - { - "equals": "watched-not-changed", - "replacement": "
" - }, - { - "equals": "watched-changed", - "replacement": "
" - }, - { - "equals": "new", - "replacement": "
" - }, - { - "equals": "missing-in-last-scan", - "replacement": "
" - } - ], - "localized": ["name"], - "name": [ - { - "language_code": "en_us", - "string": "Status" - }, - { - "language_code": "es_es", - "string": "Estado" - } - ] - } - ] -} diff --git a/front/plugins/pholus_scan/pholus/AAtlasis - An Attack-in-Depth Analysis of multicast DNS and DNS Service Discovery_wp.pdf b/front/plugins/pholus_scan/pholus/AAtlasis - An Attack-in-Depth Analysis of multicast DNS and DNS Service Discovery_wp.pdf deleted file mode 100755 index 5be30795..00000000 Binary files a/front/plugins/pholus_scan/pholus/AAtlasis - An Attack-in-Depth Analysis of multicast DNS and DNS Service Discovery_wp.pdf and /dev/null differ diff --git a/front/plugins/pholus_scan/pholus/README.md b/front/plugins/pholus_scan/pholus/README.md deleted file mode 100755 index 165c1349..00000000 --- a/front/plugins/pholus_scan/pholus/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# INFO -For anyone reading, `pholus.py` is not actively developed as this project only uses `pholus3.py`. - -# Pholus -A multicast DNS and DNS Service Discovery Security Assessment Tool -It can perform recconnaisance, Denial of Service, Man in the Middle attacks - -## Scan passively -Scan passively (for amount of timeout) -python pholus3.py eth0 -stimeout 60 - -## Discovery of available services -Sends a DNS query for PTR records with the name "_services._dns-sd._udp."; -this yields a set of PTR records where the rdata of each PTR record is the two-label - name plus the same domain, e.g., "_http._tcp.". -By sending such a query, we can automatically discover all the services advertised in the network. - -python pholus3.py eth0 -sscan - -#If you want to perform the scan both for IPv4 and IPv6: -python pholus3.py eth0 -sscan -4 -6 - -#You can also spoof the souce address to perform this reconnaissance in a stealthy way. -python pholus3.py eth0 -sscan -s4 192.168.2.30 - -## Send mdns request -python pholus3.py eth0 --request - -## Perform a scan using reverse mDNS by providing a subnet -python pholus3.py eth0 -rdns_scanning 192.168.2.0/24 - -## Send automatically fake responses -python pholus3.py eth0 -afre -stimeout 100 - -## further MiTM (and other) capabilities -use --help to identify specific spoofing capabilities for MiTM purposes, eg -printer) - -## Read a pcap file and pring mDNS info (no sudo/root required) -python pholus3.py ../mdns_traffic.pcap --readpcap diff --git a/front/plugins/pholus_scan/pholus/licence.txt b/front/plugins/pholus_scan/pholus/licence.txt deleted file mode 100755 index 645791be..00000000 --- a/front/plugins/pholus_scan/pholus/licence.txt +++ /dev/null @@ -1,23 +0,0 @@ -__copyright__ = """Copyright (C) 2016 Antonios Atlasis - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2 of the License, or (at your -option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -This tool may be used for legal purposes only. Users take full responsibility -for any actions performed using this tool. If these terms are not acceptable to -you, then do not use this tool. - -You are encouraged to send comments, improvements or suggestions to -aatlasis@secfu.net -""" diff --git a/front/plugins/pholus_scan/pholus/pholus.py b/front/plugins/pholus_scan/pholus/pholus.py deleted file mode 100755 index fccd1d0a..00000000 --- a/front/plugins/pholus_scan/pholus/pholus.py +++ /dev/null @@ -1,975 +0,0 @@ -#!/usr/bin/python -from scapy.all import * -import argparse -import re -import binascii -import random -import multiprocessing -import logging -import itertools -from scapy.utils import PcapWriter - -sys.setrecursionlimit(30000) -logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#supress Scapy warnings` - -##################################################### -### DEFINE AN IPV4 RANGE FOR IN-ADDR.ARPA QUERIES ### -##################################################### -def ip_range(input_string): - octets = input_string.split('.') - octets.reverse() - chunks = [map(int, octet.split('-')) for octet in octets] - ranges = [range(c[0], c[1] + 1) if len(c) == 2 else c for c in chunks] - for address in itertools.product(*ranges): - address = address + ('in-addr','arpa') - yield '.'.join(map(str, address)) - -###################################### -### OBTAIN THE SYSTEM IPV6 ADDRESS ### -###################################### -def get_my_ipv6_addr(interface): - myip="" - try: - for ifaces in scapy.arch.linux.in6_getifaddr(): #in6_getifaddr() #return a list of IPs - ifaces, etc - if ifaces[2]==interface: - if not myip: - myip=ifaces[0] - elif myip[0:6] == "fe80::": - myip=ifaces[0] - return myip - except: - print "The interface",interface,"does not exist. Please, try again." - exit(0) - -###################################### -### OBTAIN THE SYSTEM IPV4 ADDRESS ### -###################################### -def get_my_ipv4_addr(interface): - myip="" - try: - myip=scapy.arch.get_if_addr(interface) - return myip - except: - print "The interface",interface,"does not exist. Please, try again." - exit(0) - -########################## -##### SNIFFER CLASS ##### -########################## -class Sniffer(): - def __init__ (self,filter,interface,sniffer_timeout,queue,dns,show_ttl,dos_ttl, conflict, ttl,d4, d6, target_mac, auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,hlimit,workstation,printer,googlecast,airtv,flood,flooding_timeout,flooding_interval, v4, v6): - self.filter = filter - self.interface = interface - self.sniffer_timeout=sniffer_timeout - self.queue=queue - self.dns=dns - self.show_ttl=show_ttl - self.dos_ttl=dos_ttl - self.conflict=conflict - self.ttl=ttl - self.d4=d4 - self.d6=d6 - self.target_mac=target_mac - self.auto_fake_responses=auto_fake_responses - self.source_IPv6=source_IPv6 - self.source_IPv4=source_IPv4 - self.target_mac1=target_mac1 - self.target_mac2=target_mac2 - self.source_mac=source_mac - self.hlimit=hlimit - self.workstation=workstation - self.printer=printer - self.airtv=airtv - self.googlecast=googlecast - self.flood=flood - self.flooding_interval=flooding_interval - self.flooding_timeout=flooding_timeout - self.v4=v4 - self.v6=v6 - sniff(filter=self.filter, iface=self.interface, prn=self.handler, store=0, timeout=self.sniffer_timeout) - def handler(self,packets): - ext_handler(packets,self.queue,self.dns,self.show_ttl,1,self.dos_ttl,self.conflict, self.ttl,self.interface,self.d4,self.d6,self.target_mac,self.auto_fake_responses,self.source_IPv6,self.source_IPv4,self.target_mac1,self.target_mac2,self.source_mac,self.hlimit,self.workstation,self.printer,self.googlecast,self.airtv,self.flood,self.flooding_timeout,self.flooding_interval,self.v4,self.v6) - -################################## -##### OFFLINE SNIFFER CLASS ##### -################################## -class Sniffer_Offline(): - def __init__ (self,interface,queue,show_ttl,d4, d6, target_mac,auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,hlimit): - self.interface = interface - self.queue=queue - self.show_ttl=show_ttl - self.d4=d4 - self.d6=d6 - self.target_mac=target_mac - self.auto_fake_responses=auto_fake_responses - self.source_IPv6=source_IPv6 - self.source_IPv4=source_IPv4 - self.target_mac1=target_mac1 - self.target_mac2=target_mac2 - self.source_mac=source_mac - self.hlimit=hlimit - sniff(filter="udp and (port 5353 or port 53)", offline=self.interface, prn=self.handler, timeout=1) - def handler(self,packets): - ext_handler(packets,self.queue,False,self.show_ttl,1,False,False,4500,self.interface,self.d4,self.d6,self.target_mac,False,self.source_IPv6,self.source_IPv4,self.target_mac1,self.target_mac2,self.source_mac,self.hlimit,False,False,False,False,10.0,0.1,True,False) - -######################################################################## -### THE HANDLER THAT THE TWO SNIFFERS CALL - THIS MAKES THE MAIN JOB ### -######################################################################## -def ext_handler(packets,queue,unidns,show_ttl,print_res,dos_ttl,conflict,ttl,interface,d4,d6,target_mac,auto_fake_responses,source_IPv6,source_IPv4,target_mac1,target_mac2,source_mac,hlimit,workstation,printer,googlecast,airtv,flood,flooding_timeout,flodding_interval,v4,v6): - dns_type = {12: "PTR", 28: "AAAA", 13: "HINFO",33: "SRV", 1: "A", 255: "* (ANY)", 16: "TXT", 15: "MX", 6: "SOA", 256: "URI", 5: "CNAME",39: "DNAME"} - Ether_src=packets.getlayer(Ether).src - IP_src=None - if packets.haslayer(IPv6): - IP_src=packets.getlayer(IPv6).src - elif packets.haslayer(IP): - IP_src=packets.getlayer(IP).src - res0= Ether_src + " " + IP_src - #try: - if packets.haslayer(DNS): - dns=packets.getlayer(DNS) - if (conflict or dos_ttl) and dns.ancount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.an) - #new_DNS_packet=DNS(id=dns[DNS].id,qr=dns[DNS].qr,opcode=dns[DNS].opcode,aa=dns[DNS].aa,tc=dns[DNS].tc,rd=dns[DNS].rd,ra=dns[DNS].ra,z=dns[DNS].z,ad=dns[DNS].ad,cd=dns[DNS].cd,rcode=dns[DNS].rcode,qdcount=dns[DNS].qdcount,ancount=dns[DNS].ancount,nscount=dns[DNS].nscount,arcount=dns[DNS].arcount,qd=dns[DNS].qd) - if conflict: - new_DNS_packet=DNS(id=dns[DNS].id,qr=dns[DNS].qr,opcode=dns[DNS].opcode,aa=dns[DNS].aa,tc=dns[DNS].tc,rd=dns[DNS].rd,ra=dns[DNS].ra,z=dns[DNS].z,ad=dns[DNS].ad,cd=dns[DNS].cd,rcode=dns[DNS].rcode,qdcount=0,ancount=dns[DNS].ancount,nscount=0,arcount=0,qd=dns[DNS].qd) - if target_mac: - new_packet=Ether(src=source_mac,dst=target_mac) - else: - new_packet=Ether(src=source_mac,dst=packets[Ether].dst) - if packets.haslayer(IPv6): - if d6: - new_packet=new_packet/IPv6(src=source_IPv6,dst=d6,hlim=packets[IPv6].hlim) - else: - new_packet=new_packet/IPv6(src=source_IPv6,dst=packets[IPv6].dst,hlim=packets[IPv6].hlim) - else: - if d4: - new_packet=new_packet/IP(src=source_IPv4,dst=d4,ttl=packets[IP].ttl) - else: - new_packet=new_packet/IP(src=source_IPv4,dst=packets[IP].dst,ttl=packets[IP].ttl) - for p in DNSBlocks: - if isinstance(p,DNSRR): - new_DNS_packet=new_DNS_packet/p - elif dos_ttl: - new_DNS_packet=DNS(id=dns[DNS].id,qr=dns[DNS].qr,opcode=dns[DNS].opcode,aa=dns[DNS].aa,tc=dns[DNS].tc,rd=dns[DNS].rd,ra=dns[DNS].ra,z=dns[DNS].z,ad=dns[DNS].ad,cd=dns[DNS].cd,rcode=dns[DNS].rcode,qdcount=0,ancount=dns[DNS].ancount,nscount=0,arcount=dns[DNS].arcount,qd=dns[DNS].qd) - DNSBlocks.append(dns.ar) - if target_mac: - new_packet=Ether(src=source_mac,dst=target_mac) - else: - new_packet=Ether(src=packets[Ether].src,dst=packets[Ether].dst) - if packets.haslayer(IPv6): - if d6: - new_packet=new_packet/IPv6(src=packets[IPv6].src,dst=d6,hlim=packets[IPv6].hlim) - else: - new_packet=new_packet/IPv6(src=packets[IPv6].src,dst=packets[IPv6].dst,hlim=packets[IPv6].hlim) - else: - if d4: - new_packet=new_packet/IP(src=packets[IP].src,dst=d4,ttl=packets[IP].ttl) - else: - new_packet=new_packet/IP(src=packets[IP].src,dst=packets[IP].dst,ttl=packets[IP].ttl) - for p in DNSBlocks: - if isinstance(p,DNSRR): - new_p=DNSRR() - new_p.ttl=0 - new_p.rrname=p.rrname - new_p.type=p.type - new_p.rclass=p.rclass - new_p.rdlen=p.rdlen - new_p.rdata=p.rdata - new_DNS_packet=new_DNS_packet/new_p - if unidns: - new_packet=new_packet/UDP(dport=53)/new_DNS_packet - else: - new_packet=new_packet/UDP(dport=5353,sport=5353)/new_DNS_packet - for x in range(0,2):#Send each packet twice - sendp(new_packet,iface=interface) - elif auto_fake_responses or (not (dos_ttl or conflict)): - ## IF THIS IS A QUERY ## - if dns.opcode==0: - res0 = res0 + " QUERY" - if dns.qdcount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.qd) - for block in DNSBlocks: - while isinstance(block,DNSQR): - dnsqr=block.getlayer(DNSQR) - ### IF WE NEED TO AUTO RESPOND WITH A FAKE | DOS RESPONSE ### - if auto_fake_responses: - myttl=int(ttl) - if (("in-addr.arpa" in dnsqr.qname) or ("ip6.arpa" in dnsqr.name)) and workstation: - #ip=dnsqr.qname.split(".") - #qname = ip[3]+"."+ip[2]+"."+ip[1]+"."+ip[0] - #print "Fake IP =",qname - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=0)/DNSRR(rrname=dnsqr.qname,ttl=myttl,rdata='mitsos.local',type="PTR") - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=0)/DNSRR(rrname=dnsqr.qname,ttl=myttl,rdata='mitsos.local',type="PTR") - elif ("_workstation._tcp." in dnsqr.qname) and workstation: - qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=3)/DNSRR(rrname="_workstation._tcp.local",ttl=myttl,rdata="mitsos._workstation._tcp.local",type="PTR",rclass=32769)/DNSRR(rrname=qname,ttl=myttl,type="TXT",rclass=32769)/DNSRR(rrname="mitsos.local",ttl=myttl,rdata=source_IPv4,type="A",rclass=32769) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=3)/DNSRR(rrname="_workstation._tcp.local",ttl=myttl,rdata="mitsos._workstation._tcp.local",type="PTR",rclass=32769)/DNSRR(rrname=qname,ttl=myttl,type="TXT",rclass=32769)/DNSRR(rrname="mitsos.local",ttl=myttl,rdata=source_IPv4,type="A",rclass=32769) - elif (("_pdl-datastream._tcp." in dnsqr.qname) or ("_ipp._tcp." in dnsqr.qname)) and printer: - qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - #make the SRV additional record - port=9100 - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight=0 - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority=0 - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - #for explanation, check http://stackoverflow.com/questions/26933016/rdata-field-of-a-dns-sd-ptr-packet-sent-via-scapy-results-in-an-unknown-extended - sublabels = "HP10000.local".split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - srv_rrname=data+label_data - txt_record="" - rdata=['txtvers=1','qtotal=1','pdl=application/vnd.hp-PCL','ty=MyOfficejet100000','product=(Trexa gureue)','priority=0','adminur=http://'+source_IPv4] - for r in rdata: - length=hex(len(r))[2:] - #check http://code.activestate.com/recipes/576617-converting-arbitrary-size-python-integers-to-packe/ - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt= DNSRR(rrname="MyOfficejet10000._pdl-datasream._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - pkt=dnsrr_packet - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="MyOffice10000."+qname,type="PTR",rclass=32769)/DNSRR(rrname="HP10000.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4)/DNSRR(rrname="MyOffice100000."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/pkt - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="MyOffice10000."+qname,type="PTR",rclass=32769)/DNSRR(rrname="HP10000.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4)/DNSRR(rrname="MyOffice100000."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/pkt - elif ("_googlecast._tcp." in dnsqr.qname) and googlecast: - qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - #make the SRV additional record - port=8009 - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight=0 - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority=0 - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - sublabels = "32799abf-18ea-631d-62ae-390515bb47c5.local".split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - srv_rrname=data+label_data - txt_record="" - rdata=['id=32799abf-18ea-631d-62ae-390515bb47c5','rm=','ve=05','md=Chromecast Ultra','ic=/setup/icon.png','fn=LivingRoom','ca=4101','st=0','bs=FA8FCA7EO948','rs=0'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt= DNSRR(rrname="Chromecast-Ultra-32799abf-18ea-631d-62ae-390515bb47c5."+qname,type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - pkt=dnsrr_packet - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="Chromecast-Ultra-32799abf-18ea-631d-62ae-390515bb47c5."+qname,type="PTR")/pkt/DNSRR(rrname="ChromecastUltra."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="32799abf-18ea-631d-62ae-390515bb47c5.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="Chromecast-Ultra-32799abf-18ea-631d-62ae-390515bb47c5."+qname,type="PTR")/pkt/DNSRR(rrname="ChromecastUltra."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="32799abf-18ea-631d-62ae-390515bb47c5.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4) - elif ("_airplay." in dnsqr.qname) and airtv: - qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - - txt_record="" - rdata=['model=J33AP'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt= DNSRR(rrname="Apple TV-mitsos._device-info._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - pkt=dnsrr_packet - - txt_record="" - rdata=['deviceid=9C:20:7B:AD:6B:E4','features=0x5A7FFFF7,0xE','flags=0x44','model=AppleTV3,1','pk=ab69a89af6fe7ff1fd803f74c6681d786aff1e6bc52087e49cc8f22585916ccd','pi=a62a851e-d024-439f-9ee0-01ef1b23d6ca','srcvers=220.68','vv=2'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt2= DNSRR(rrname="Apple TV-mitsos._airplay._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt2.rdlen-=1 - mylength=len(pkt2.rrname)+12 - dnsrr_packet=str(pkt2)[0:mylength]+str(pkt2)[mylength+1::] - pkt2=dnsrr_packet - - txt_record="" - rdata=['cn=0,1,2,3','da=true','et=0,3,5','ft=0x5A7FFFF7,0xE','md=0,1,2','am=AppleTV3,1','pk=ab69a89af6fe7ff1fd803f74c6681d786aff1e6bc52087e49cc8f22585916ccd','sf=0x44','tp=UDP','vn=65537','vs=220.68','vv=2'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt3= DNSRR(rrname="9C207BAD6BE4@Apple TV-mitsos._raop._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt3.rdlen-=1 - mylength=len(pkt3.rrname)+12 - dnsrr_packet=str(pkt3)[0:mylength]+str(pkt3)[mylength+1::] - pkt3=dnsrr_packet - - #make the SRV additional record - port=7000 - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight=0 - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority=0 - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - sublabels = "Apple-TV.local".split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - srv_rrname=data+label_data - - if unidns: - dns_packet=UDP(dport=53) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=3,arcount=6)/DNSRR(rrname=qname,ttl=myttl,rdata="Apple TV-mitsos._device-info."+qname,type="PTR")/pkt/DNSRR(rrname="_raop._tcp.local",ttl=myttl,rdata="9C207BAD6BE4@Apple TV-mitsos._raop._tcp.local",type="PTR")/pkt2/pkt3/DNSRR(rrname="Apple TV-mitsos."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="9C207BAD6BE4@Apple TV-mitsos._raop._tcp.local",ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="Apple-TV.local",ttl=myttl,rdata=source_IPv4,type="A",rclass=32769)/DNSRR(rrname="Apple-TV.local",ttl=myttl,rdata=source_IPv6,type="AAAA",rclass=32769) - else: - qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - print "Query Name = ",qname," Type=",dnsqr.qtype - if unidns: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1)/DNSRR(rrname=qname,ttl=myttl,rdata=source_IPv4,type="A") - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1)/DNSRR(rrname=qname,ttl=myttl,rdata=source_IPv4,type="A") - send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,d4,source_IPv6,d6,interface,hlimit,dns_packet,False,10.0,0.1)#CHANGE DEFAULT VALUES - #CHANGE: SEND IT TWICE, IF NOT FLOOD - #if not flood: - # for x in range(0,10):#Send each packet twice - # send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,d4,source_IPv6,d6,interface,hlimit,dns_packet,False,10.0,0.1)#CHANGE DEFAULT VALUES - ### END "IF WE NEED TO AUTO RESPOND WITH A FAKE RESPONSE - ### NEXT LINES ARE ONLY USED TO PRINT RESULTS ### - if dnsqr.qclass==32769: - res = res0 + " Question: "+dnsqr.qname + " " + dns_type[dnsqr.qtype] +" QU Class:IN" - elif dnsqr.qclass==1: - res = res0 + " Question: "+dnsqr.qname + " "+ dns_type[dnsqr.qtype] + " QM Class:IN" - elif dnsqr.qclass==255: - res = res0 + " Question: "+dnsqr.qname + " "+ dns_type[dnsqr.qtype] + " QM Class:ANY" - else: - print "DNSQR:" - print "-----" - print dnsqr.show() - print "DEBUGGING IS NEEDED" - exit(0) - if print_res==1: - print res - queue.put(res) - block = block.payload - if dns.arcount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.ar) - for block in DNSBlocks: - if block.haslayer(DNSRROPT): - while isinstance(block,DNSRROPT):#Somewhat equivalent: while not isinstance(an, NoPayload): - dnsrropt=block.getlayer(DNSRROPT) - #print "DNS OPT Resource Record" - if dnsrropt.rrname == ".": - rrname = "" - else: - rrname = dnsrropt.rrname - if dnsrropt.type==41: - ARtype="OPT" - else: - ARtype=str(dnsrropt.type) - res = res0 + " Additional_Record: " + rrname + " " + ARtype - if dnsrropt.haslayer(EDNS0TLV): - edns0tlv=dnsrropt.getlayer(EDNS0TLV) - if edns0tlv.optcode==4: - optcode="Reserved" - else: - optcode=str(edns0tlv.optcode) - res = res + " EDNS0TLV: " + optcode + " " + str(edns0tlv.optdata).encode("HEX") - if print_res==1: - print res - queue.put(res) - block = block.payload - elif block.haslayer(DNSRR): - while isinstance(block,DNSRR):#Somewhat equivalent: while not isinstance(an, NoPayload): - dnsrr=block.getlayer(DNSRR) - if dnsrr.rclass==32769: - res = res0 + " DNS Resource Record: "+ dnsrr.rrname + " " + dns_type[dnsrr.type] +" QU Class:IN "+dnsrr.rdata - elif dnsrr.rclass==1: - res = res0 + " DNS Resource Record: "+dnsrr.rrname + " "+ dns_type[dnsrr.type] + " QM Class:IN "+dnsrr.rdata - elif dnsrr.qclass==255: - res = res0 + " Question: "+dnsrr.qname + " "+ dns_type[dnsrr.qtype] + " QM Class:ANY" - else: - print "DNSRR:" - print "-----" - print dnsrr.show() - print "DEBUGGING IS NEEDED HERE" - exit(0) - if dnsrr.type==33:#SRV Record - priority=str(dnsrr.rdata)[0].encode("HEX")+str(dnsrr.rdata)[1].encode("HEX") - weight=str(dnsrr.rdata)[2].encode("HEX")+str(dnsrr.rdata)[3].encode("HEX") - port_number=str(dnsrr.rdata)[4].encode("HEX")+str(dnsrr.rdata)[5].encode("HEX") - res = res0 + " Additional_Record: "+dnsrr.rrname + " " + dns_type[dnsrr.type]+" " + str(dnsrr.rclass) + " priority="+str(int(priority,16))+" weight="+str(int(weight,16))+" port="+str(int(port_number,16))+" target="+str(dnsrr.rdata)[6::] - else: - rdata=dnsrr.rdata - if "._tcp." not in rdata and "._udp." not in rdata: - if rdata == "_dhnap.": - rdata=dnsrr.rdata+"_tcp." - res = res0 + " Additional_Record: "+dnsrr.rrname + " " + dns_type[dnsrr.type]+" " + str(dnsrr.rclass) + ' "' +rdata+'"' - if show_ttl: - res = res + " TTL:"+str(dnsrr.ttl) - if print_res==1: - print res - queue.put(res) - block = block.payload - if dns.ancount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.an) - for block in DNSBlocks: - while isinstance(block,DNSRR): - dnsrr=block.getlayer(DNSRR) - if dnsrr.rclass==1: - rclass="Class:IN" - else: - rclass="Class:"+str(dnsrr.rclass) - rdata=dnsrr.rdata - if dnsrr.type==33:#SRV Record - priority=str(dnsrr.rdata)[0].encode("HEX")+str(dnsrr.rdata)[1].encode("HEX") - weight=str(dnsrr.rdata)[2].encode("HEX")+str(dnsrr.rdata)[3].encode("HEX") - port_number=str(dnsrr.rdata)[4].encode("HEX")+str(dnsrr.rdata)[5].encode("HEX") - res = res0 + " Answer: "+dnsrr.rrname + " " + dns_type[dnsrr.type]+" " + rclass + " priority="+str(int(priority,16))+" weight="+str(int(weight,16))+" port="+str(int(port_number,16))+" target="+str(dnsrr.rdata)[6::] - else: - if "._tcp." not in rdata and "._udp." not in rdata: - if rdata == "_dhnap.": - rdata=dnsrr.rdata+"_tcp." - res = res0 + " Answer: "+dnsrr.rrname + " " + dns_type[dnsrr.type]+" " + rclass + ' "' +rdata+'"' - if show_ttl: - res = res + " TTL:"+str(dnsrr.ttl) - if print_res==1: - print res - queue.put(res) - block = block.payload - if dns.nscount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.ns) - for block in DNSBlocks: - while isinstance(block,DNSRR): - dnsrr=block.getlayer(DNSRR) - if dnsrr.rclass==1: - rclass="Class:IN" - else: - rclass="Class:"+str(dnsrr.rclass) - res = res0 + " Auth_NS: "+dnsrr.rrname + " " + dns_type[dnsrr.type]+" " + rclass + ' "' +dnsrr.rdata+'"' - if show_ttl: - res = res + " TTL:"+str(dnsrr.ttl) - if print_res==1: - print res - queue.put(res) - block = block.payload - else: - print "not a DNS Query", dns.summary() - #except Exception,e: - # print "Exception",str(e),packets.summary() - -######################################## -########### REQUEST FUNCTION ########### -######################################## -def requests(interface,v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,d4,d6,hlimit,unidns,domain,query,types_of_queries,add_domain,query_class,flood,flooding_interval,flooding_timeout): - if add_domain: - print "Sending mdns requests" - domain_list = domain.split(",") - query_list = query.split(",") - if add_domain: - the_query=query_list[0]+"."+domain_list[0] - else: - types_of_queries="ALL"#implies that first a generic scan has beem performed - the_query=query_list[0] - dns_query=DNSQR(qname=the_query,qtype=types_of_queries,qclass=int(query_class)) - for j in range(1,len(query_list)): - if add_domain: - the_query=query_list[j]+"."+domain_list[0] - else: - the_query=query_list[j] - dns_query=dns_query/DNSQR(qname=the_query,qtype=types_of_queries,qclass=int(query_class)) - if add_domain: - for i in range(1,len(domain_list)): - for j in query_list: - the_query=j+"."+domain_list[i] - dns_query=dns_query/DNSQR(qname=the_query,qtype=types_of_queries,qclass=int(query_class)) - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=0,qd=dns_query) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=0,qd=dns_query) - send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,d4,source_IPv6,d6,interface,hlimit,dns_packet,flood,flooding_timeout,flooding_interval) - -######################################## -######################################## -######################################## -def send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,dst_ipv4,source_IPv6,dst_ipv6,interface,hlimit,payload,flood,flooding_timeout,flooding_interval): - if v4 or not v6: - packet=IP(src=source_IPv4,dst=dst_ipv4,ttl=hlimit,proto="udp")/payload - if len(packet)>1500: - frags=fragment(packet) - packets=[] - for frag in frags: - pkt1=Ether(src=source_mac,dst=target_mac1)/frag - packets.append(pkt1) - if flood: - counter=0.0 - print "Stop flooding after ",flooding_timeout," sec." - while(counter1500: - frags2=fragment6(IPv6(src=source_IPv6,dst=dst_ipv6,hlim=hlimit)/IPv6ExtHdrFragment()/payload,1480) - packets=[] - for frag2 in frags2: - pkt2=Ether(src=source_mac,dst=target_mac2)/frag2 - packets.append(pkt2) - if flood: - counter=0.0 - print "Stop flooding after ",flooding_timeout," sec." - while(counter> 32 & 0xffff ^ 0x0200 - high1 = mac_value >> 24 & 0xff - low1 = mac_value >> 16 & 0xff - low2 = mac_value & 0xffff - source_IPv6 = 'fe80::{:04x}:{:02x}ff:fe{:02x}:{:04x}'.format(high2, high1, low1, low2) - else: - source_IPv6=values.source6 - if not values.source4: - source_IPv4=get_my_ipv4_addr(values.interface) - else: - source_IPv4=values.source4 - print "source MAC address:",source_mac,"source IPv4 Address:",source_IPv4,"source IPv6 address:",source_IPv6 - ######################################################################################################### - if values.target_mac: - target_mac1=values.target_mac - target_mac2=values.target_mac - else: - target_mac2="33:33:00:00:00:02" - target_mac1="01:00:5e:00:00:fb" - ############################################Sniffing requirements######################################## - q = multiprocessing.Queue() - if values.dos_ttl or values.auto_fake_responses: - if values.auto_fake_responses: - print "Send fake responses to requests" - if values.target_mac: - myfilter = "not ether src " + source_mac + " and not ether dst " + values.target_mac +" and udp and port 5353" - else: - myfilter = "not ether src " + source_mac + " and udp and port 5353" - elif values.target_mac: - print "Performing implicit DoS by sending automated spoofed DNS Answers with TTL=0" - myfilter = "not ether dst " + values.target_mac + " and udp and port 5353" - else: - print "Performing implicit DoS by sending automated spoofed DNS Answers with TTL=0" - myfilter = "udp and port 5353" - print "Sniffer filter is:",myfilter - print "I will sniff for",values.sniffer_timeout,"seconds, unless interrupted by Ctrl-C" - print "Press Ctrl-C to exit" - try: - Sniffer(myfilter, values.interface, float(values.sniffer_timeout),q,values.dns,values.show_ttl, values.dos_ttl, values.conflict, values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6) - except KeyboardInterrupt: - print "Exiting on user's request" - exit(0) - exit(0) - myfilter = "not ether src " + source_mac + " and udp and port 5353" - print "Sniffer filter is:",myfilter - print "I will sniff for",values.sniffer_timeout,"seconds, unless interrupted by Ctrl-C" - pr = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q,values.dns,values.show_ttl, values.dos_ttl, values.conflict, values.ttl,values.d4,values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2, source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr.daemon = True - pr.start() - print "------------------------------------------------------------------------" - time.sleep(1)#to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - ########################################################################################################## - if values.request: - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,values.query,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - elif values.response: - #qr=1=>Response, aa=1=>Server is an authority for the domain, rd=0=> Do not query recursively - if values.dns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0) - #dns_packet=UDP(dport=53)/DNS(opcode=0,qr=1,aa=1,qdcount=0,ancount=len(responses),qd=dns_response) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0) - #dns_packet=UDP(sport=5353,dport=5353)/DNS(opcode=0,qr=1,aa=1,qdcount=0,ancount=len(responses),qd=dns_response) - responses = values.dns_response.split(",") - no_of_answers=0 - no_of_additional_records=0 - dnsar=None - for r in responses: - values_of_responses = r.split("/") - dnsrr=DNSRR() - port=0 - weight=0 - priority=0 - no_of_answers+=1 - this_is_a_dns_ar=False - #rdata=None - rdata=[] - for dns_values in values_of_responses: - #print dns_values - value = dns_values.split("==") - if value[0]=="Type": - dnsrr.type=value[1] - elif value[0]=="Name": - dnsrr.rrname=value[1] - elif value[0]=="Target": - rdata.append(value[1]) - #rdata=value[1] - elif value[0]=="TTL": - dnsrr.ttl=int(value[1]) - elif value[0]=="Flush": - if value[1]=="True": - dnsrr.rclass=32769 - elif value[0]=="Priority": - priority=int(value[1]) - elif value[0]=="Weight": - weight=int(value[1]) - elif value[0]=="Port": - port=int(value[1]) - elif value[0]=="AR": - if value[1]=="True": - no_of_additional_records+=1 - this_is_a_dns_ar=True - if dnsrr.type==33: - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - #http://stackoverflow.com/questions/26933016/rdata-field-of-a-dns-sd-ptr-packet-sent-via-scapy-results-in-an-unknown-extended - sublabels = rdata[0].split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - dnsrr.rdata=data+label_data - elif dnsrr.type==16: - txt_record="" - for r in rdata: - length=hex(len(r))[2:] - #check http://code.activestate.com/recipes/576617-converting-arbitrary-size-python-integers-to-packe/ - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - dnsrr.rdata=txt_record - #pkt= DNSRR(rrname="MyOfficejet10000._pdl-datasream._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - #pkt.rdlen-=1 - #mylength=len(pkt.rrname)+12 - #dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - #pkt=dnsrr_packet - ################## - pkt=dnsrr - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - ################## - #mylength=len(dnsrr.rrname)+12 - #dnsrr_packet=str(dnsrr)[0:mylength]+str(dnsrr)[mylength+1::] - dnsrr=dnsrr_packet - else: - #print rdata - dnsrr.rdata=rdata[0] - if not this_is_a_dns_ar: - dns_packet=dns_packet/dnsrr - else: - if not dnsar: - dnsar=dnsrr - else: - dnsar=dnsar/dnsrr - if dnsar: - dns_packet=dns_packet/dnsar - dns_packet[DNS].ancount=no_of_answers-no_of_additional_records - dns_packet[DNS].arcount=no_of_additional_records - send_packets(values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,values.d4,source_IPv6,values.d6,values.interface,values.hlimit,dns_packet,values.flood,values.flooding_timeout,values.flooding_interval) - elif values.rdns_scanning: - dns_query=None - for address in ip_range(values.rdns_scanning): - the_query=address - if not dns_query: - dns_query=DNSQR(qname=the_query,qtype=values.qtype,qclass=values.q_class) - else: - dns_query=dns_query/DNSQR(qname=the_query,qtype=values.qtype,qclass=values.q_class) - if values.dns: - dns_packet=UDP(dport=53)/DNS(qr=0,qd=dns_query) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=0,qd=dns_query) - send_packets(values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,values.d4,source_IPv6,values.d6,values.interface,values.hlimit,dns_packet,values.flood,values.flooding_timeout,values.flooding_interval) - elif values.service_scan: - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,values.query,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - ############################################################################################ - ############################################################################################ - if pr: - try: - pr.join() - except KeyboardInterrupt: - print "Exiting on user's request" - exit(0) - - #### AFTER EXITING, PRINT THE RESULTS #### - results=[] - while not q.empty(): - results.append(q.get()) - if values.rdns_scanning: - targets=[] - q2 = multiprocessing.Queue() - pr2 = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q2,values.dns,values.show_ttl, values.dos_ttl,values.conflict, values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr2.daemon = True - pr2.start() - time.sleep(1) #to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - for r in results: - r2=r.split(" ") - service=r2[7].strip('"') - if service.endswith('local.'): - service=service[:-6] - if service.endswith('.'): - service=service[:-1] - if (r2[1],service) not in targets: - targets.append((r2[1],service)) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,service,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - if pr2: - try: - pr2.join() - except KeyboardInterrupt: - print "Exiting on user's request" - while not q2.empty(): - results.append(q2.get()) - elif values.service_scan: - targets=[] - q2 = multiprocessing.Queue() - pr2 = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q2,values.dns,values.show_ttl, values.dos_ttl,values.conflict, values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr2.daemon = True - pr2.start() - time.sleep(1) #to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - for r in results: - r2=r.split(" ") - service=r2[7].strip('"')[:-1] - if (r2[1],service) not in targets: - print (r2[1],service) - targets.append((r2[1],service)) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,service,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - if pr2: - try: - pr2.join() - except KeyboardInterrupt: - print "Exiting on user's request" - while not q2.empty(): - results.append(q2.get()) - targets2=[] - q3 = multiprocessing.Queue() - pr3 = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q3,values.dns,values.show_ttl, values.dos_ttl, values.conflict,values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr3.daemon = True - pr3.start() - time.sleep(1) #to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - for r in results: - r2=r.split(" ") - service=r2[4] - if service.endswith('local.'): - service=service[:-6] - if service.endswith('.'): - service=service[:-1] - if (r2[1],service) not in targets and (r2[1],service) not in targets2 and "_services._dns-sd._udp" not in service: - targets2.append((r2[1],service)) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,service,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - if pr3: - try: - pr3.join() - except KeyboardInterrupt: - print "Exiting on user's request" - while not q3.empty(): - results.append(q3.get()) - print "\n*********************************************RESULTS*********************************************" - for r in results: - print r - -if __name__ == '__main__': - main() diff --git a/front/plugins/pholus_scan/pholus/pholus3.py b/front/plugins/pholus_scan/pholus/pholus3.py deleted file mode 100755 index b5e4bb90..00000000 --- a/front/plugins/pholus_scan/pholus/pholus3.py +++ /dev/null @@ -1,1190 +0,0 @@ -#!/usr/bin/python -from scapy.all import * -import argparse -import re -import binascii -import random -import multiprocessing -import logging -import itertools -import codecs -import ipaddress -import os -import sys -import datetime -from scapy.utils import PcapWriter - - -sys.setrecursionlimit(30000) -logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#supress Scapy warnings` - -logPath = '/app/front/log' -# DEBUG -isDebug = False - - -#=============================================================================== -# UTIL -#=============================================================================== - -#------------------------------------------------------------------------------- -def timeNow(): - return datetime.datetime.now().replace(microsecond=0) - -def write_file (pPath, pText): - # Write the text depending using the correct python version - if sys.version_info < (3, 0): - file = io.open (pPath , mode='w', encoding='utf-8') - file.write ( pText.decode('unicode_escape') ) - file.close() - else: - file = open (pPath, 'w', encoding='utf-8') - file.write (pText) - file.close() - -# Empty the last run log file -write_file(logPath + "/pholus_lastrun.log", "") - -def file_print(*args): - - result = '' - - file = open(logPath + "/pholus_lastrun.log", "a") - for arg in args: - result += str(arg) - print(result) - file.write(result + '\n') - file.close() - -# Empty the last run log file -write_file(logPath + "/pholus_subp_pr.log", "") - -# For separate logging of the multiprocess subprocess -def file_print_pr(*args): - if isDebug == False: - return - - result = '' - - file = open(logPath + "/pholus_subp_pr.log", "a") - for arg in args: - result += str(arg) - print(result) - file.write(result + '\n') - file.close() - -def sanitize_string(input): - if isinstance(input, bytes): - input = input.decode('utf-8') - value = b_to_str(re.sub('[^a-zA-Z0-9-_\s]', '', str(input))) - return value - -#------------------------------------------------------------------------------- -NoneType = type(None) - -def b_to_str(value): - # if value is of other type than string, convert to string - if value is None: - return str("") - elif isinstance(value, type(None)): - return str("") - elif isinstance(value, NoneType): - return str("") - elif isinstance(value, str): - return str(value+"") - elif isinstance(value, int): - b_to_str(str(value)) - elif isinstance(value, bool): - b_to_str(str(value)) - elif isinstance(value, bytes): - b_to_str(value.decode('utf-8')) - elif isinstance(value, list): - for one in value: - b_to_str(one) - else: - return str(value) - - - #------------------------------------------------------------------------------- - -###################################### -### OBTAIN THE SYSTEM IPV6 ADDRESS ### -###################################### -def get_my_ipv6_addr(interface): - myip="" - try: - for ifaces in scapy.arch.linux.in6_getifaddr(): #in6_getifaddr() #return a list of IPs - ifaces, etc - if ifaces[2]==interface: - if not myip: - myip=ifaces[0] - elif myip[0:6] == "fe80::": - myip=ifaces[0] - return myip - except: - file_print("The interface",interface,"does not exist. Please, try again.") - exit(0) - -###################################### -### OBTAIN THE SYSTEM IPV4 ADDRESS ### -###################################### -def get_my_ipv4_addr(interface): - myip="" - try: - myip=scapy.arch.get_if_addr(interface) - return myip - except: - file_print("The interface",interface,"does not exist. Please, try again.") - exit(0) - -########################## -##### SNIFFER CLASS ##### -########################## -class Sniffer(): - def __init__ (self,filter,interface,sniffer_timeout,queue,dns,show_ttl,dos_ttl, conflict, ttl,d4, d6, target_mac, auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,hlimit,workstation,printer,googlecast,airtv,flood,flooding_timeout,flooding_interval, v4, v6): - file_print_pr("[DEBUG] sniffer_args: ", filter," ",interface," ",sniffer_timeout," ",queue," ",dns," ",show_ttl," ",dos_ttl," ", conflict," ", ttl," ",d4," ", d6," ", target_mac," ", auto_fake_responses," ",source_IPv6," ", source_IPv4," ", target_mac1," ", target_mac2," ",source_mac," ",hlimit," ",workstation," ",printer," ",googlecast," ",airtv," ",flood," ",flooding_timeout," ",flooding_interval," ", v4," ", v6) - self.filter = filter - self.interface = interface - file_print_pr("[DEBUG] sniffer_timeout: ", sniffer_timeout) - self.sniffer_timeout=sniffer_timeout - self.queue=queue - self.dns=dns - self.show_ttl=show_ttl - self.dos_ttl=dos_ttl - self.conflict=conflict - self.ttl=ttl - self.d4=d4 - self.d6=d6 - self.target_mac=target_mac - self.auto_fake_responses=auto_fake_responses - self.source_IPv6=source_IPv6 - self.source_IPv4=source_IPv4 - self.target_mac1=target_mac1 - self.target_mac2=target_mac2 - self.source_mac=source_mac - self.hlimit=hlimit - self.workstation=workstation - self.printer=printer - self.airtv=airtv - self.googlecast=googlecast - self.flood=flood - self.flooding_interval=flooding_interval - self.flooding_timeout=flooding_timeout - self.v4=v4 - self.v6=v6 - sniff(filter=self.filter, iface=self.interface, prn=self.handler, store=0, timeout=self.sniffer_timeout) - def handler(self,packets): - ext_handler(packets,self.queue,self.dns,self.show_ttl,1,self.dos_ttl,self.conflict, self.ttl,self.interface,self.d4,self.d6,self.target_mac,self.auto_fake_responses,self.source_IPv6,self.source_IPv4,self.target_mac1,self.target_mac2,self.source_mac,self.hlimit,self.workstation,self.printer,self.googlecast,self.airtv,self.flood,self.flooding_timeout,self.flooding_interval,self.v4,self.v6) - -################################## -##### OFFLINE SNIFFER CLASS ##### -################################## -class Sniffer_Offline(): - def __init__ (self,interface,queue,show_ttl,d4, d6, target_mac,auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,hlimit): - file_print_pr("[DEBUG] Timestamp 1: ", timeNow()) - self.interface = interface - self.queue=queue - self.show_ttl=show_ttl - self.d4=d4 - self.d6=d6 - self.target_mac=target_mac - self.auto_fake_responses=auto_fake_responses - self.source_IPv6=source_IPv6 - self.source_IPv4=source_IPv4 - self.target_mac1=target_mac1 - self.target_mac2=target_mac2 - self.source_mac=source_mac - self.hlimit=hlimit - sniff(filter="udp and (port 5353 or port 53)", offline=self.interface, prn=self.handler, timeout=1) - def handler(self,packets): - ext_handler(packets,self.queue,False,self.show_ttl,1,False,False,4500,self.interface,self.d4,self.d6,self.target_mac,False,self.source_IPv6,self.source_IPv4,self.target_mac1,self.target_mac2,self.source_mac,self.hlimit,False,False,False,False,False,10.0,0.1,True,False) - -######################################################################## -### THE HANDLER THAT THE TWO SNIFFERS CALL - THIS MAKES THE MAIN JOB ### -######################################################################## -def ext_handler(packets,queue,unidns,show_ttl,print_res,dos_ttl,conflict,ttl,interface,d4,d6,target_mac,auto_fake_responses,source_IPv6,source_IPv4,target_mac1,target_mac2,source_mac,hlimit,workstation,printer,googlecast,airtv,flood,flooding_timeout,flodding_interval,v4,v6): - - file_print_pr("[DEBUG] Timestamp 2: ", timeNow()) - file_print_pr("[DEBUG] 3 ") - - dns_type = {12: "PTR", 28: "AAAA", 13: "HINFO",33: "SRV", 1: "A", 255: "* (ANY)", 16: "TXT", 15: "MX", 6: "SOA", 256: "URI", 5: "CNAME",39: "DNAME"} - Ether_src=packets.getlayer(Ether).src - IP_src=None - if packets.haslayer(IPv6): - IP_src=packets.getlayer(IPv6).src - elif packets.haslayer(IP): - IP_src=packets.getlayer(IP).src - else: - file_print_pr("[DEBUG] Timestamp 4: ", timeNow()) - - res0= Ether_src + " | " + IP_src.ljust(27) - if packets.haslayer(DNS): - file_print_pr("[DEBUG] Timestamp 5: ", timeNow()) - dns=packets.getlayer(DNS) - if (conflict or dos_ttl) and dns.ancount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.an) - if conflict: - new_DNS_packet=DNS(id=dns[DNS].id,qr=dns[DNS].qr,opcode=dns[DNS].opcode,aa=dns[DNS].aa,tc=dns[DNS].tc,rd=dns[DNS].rd,ra=dns[DNS].ra,z=dns[DNS].z,ad=dns[DNS].ad,cd=dns[DNS].cd,rcode=dns[DNS].rcode,qdcount=0,ancount=dns[DNS].ancount,nscount=0,arcount=0,qd=dns[DNS].qd) - if target_mac: - new_packet=Ether(src=source_mac,dst=target_mac) - else: - new_packet=Ether(src=source_mac,dst=packets[Ether].dst) - if packets.haslayer(IPv6): - if d6: - new_packet=new_packet/IPv6(src=source_IPv6,dst=d6,hlim=packets[IPv6].hlim) - else: - new_packet=new_packet/IPv6(src=source_IPv6,dst=packets[IPv6].dst,hlim=packets[IPv6].hlim) - else: - if d4: - new_packet=new_packet/IP(src=source_IPv4,dst=d4,ttl=packets[IP].ttl) - else: - new_packet=new_packet/IP(src=source_IPv4,dst=packets[IP].dst,ttl=packets[IP].ttl) - for p in DNSBlocks: - if isinstance(p,DNSRR): - new_DNS_packet=new_DNS_packet/p - elif dos_ttl: - new_DNS_packet=DNS(id=dns[DNS].id,qr=dns[DNS].qr,opcode=dns[DNS].opcode,aa=dns[DNS].aa,tc=dns[DNS].tc,rd=dns[DNS].rd,ra=dns[DNS].ra,z=dns[DNS].z,ad=dns[DNS].ad,cd=dns[DNS].cd,rcode=dns[DNS].rcode,qdcount=0,ancount=dns[DNS].ancount,nscount=0,arcount=dns[DNS].arcount,qd=dns[DNS].qd) - DNSBlocks.append(dns.ar) - if target_mac: - new_packet=Ether(src=source_mac,dst=target_mac) - else: - new_packet=Ether(src=packets[Ether].src,dst=packets[Ether].dst) - if packets.haslayer(IPv6): - if d6: - new_packet=new_packet/IPv6(src=packets[IPv6].src,dst=d6,hlim=packets[IPv6].hlim) - else: - new_packet=new_packet/IPv6(src=packets[IPv6].src,dst=packets[IPv6].dst,hlim=packets[IPv6].hlim) - else: - if d4: - new_packet=new_packet/IP(src=packets[IP].src,dst=d4,ttl=packets[IP].ttl) - else: - new_packet=new_packet/IP(src=packets[IP].src,dst=packets[IP].dst,ttl=packets[IP].ttl) - for p in DNSBlocks: - if isinstance(p,DNSRR): - new_p=DNSRR() - new_p.ttl=0 - new_p.rrname=p.rrname - new_p.type=p.type - new_p.rclass=p.rclass - new_p.rdlen=p.rdlen - new_p.rdata=p.rdata - new_DNS_packet=new_DNS_packet/new_p - if unidns: - new_packet=new_packet/UDP(dport=53)/new_DNS_packet - else: - new_packet=new_packet/UDP(dport=5353,sport=5353)/new_DNS_packet - for x in range(0,2):#Send each packet twice - file_print_pr("[DEBUG] Timestamp 6: ", timeNow()) - sendp(new_packet,iface=interface) - file_print_pr("[DEBUG] Timestamp 7: ", timeNow()) - - elif auto_fake_responses or (not (dos_ttl or conflict)): - ## IF THIS IS A QUERY ## - file_print_pr("[DEBUG] Timestamp 8: ", timeNow()) - if dns.opcode==0: - res0 = res0 + "" - if dns.qdcount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.qd) - for block in DNSBlocks: - while isinstance(block,DNSQR): - dnsqr=block.getlayer(DNSQR) - ### IF WE NEED TO AUTO RESPOND WITH A FAKE | DOS RESPONSE ### - if auto_fake_responses: - myttl=int(ttl) - if isinstance(dnsqr.qname,bytes): - qname=dnsqr.qname.decode("utf-8") - else: - qname=dnsqr.qname - if isinstance(dnsqr.name,bytes): - name=dnsqr.name.decode("utf-8") - else: - name=dnsqr.name - if (("in-addr.arpa" in qname) or ("ip6.arpa" in name)) and workstation: - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=0)/DNSRR(rrname=dnsqr.qname,ttl=myttl,rdata='mitsos.local',type="PTR") - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=0)/DNSRR(rrname=dnsqr.qname,ttl=myttl,rdata='mitsos.local',type="PTR") - elif ("_workstation._tcp." in qname) and workstation: - #qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=3)/DNSRR(rrname="_workstation._tcp.local",ttl=myttl,rdata="mitsos._workstation._tcp.local",type="PTR",rclass=32769)/DNSRR(rrname=qname,ttl=myttl,type="TXT",rclass=32769)/DNSRR(rrname="mitsos.local",ttl=myttl,rdata=source_IPv4,type="A",rclass=32769) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=3)/DNSRR(rrname="_workstation._tcp.local",ttl=myttl,rdata="mitsos._workstation._tcp.local",type="PTR",rclass=32769)/DNSRR(rrname=qname,ttl=myttl,type="TXT",rclass=32769)/DNSRR(rrname="mitsos.local",ttl=myttl,rdata=source_IPv4,type="A",rclass=32769) - elif (("_pdl-datastream._tcp." in qname) or ("_ipp._tcp." in qname)) and printer: - #qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - #make the SRV additional record - port=9100 - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight=0 - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority=0 - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - #for explanation, check http://stackoverflow.com/questions/26933016/rdata-field-of-a-dns-sd-ptr-packet-sent-via-scapy-results-in-an-unknown-extended - sublabels = "HP10000.local".split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - srv_rrname=data+label_data - txt_record="" - rdata=['txtvers=1','qtotal=1','pdl=application/vnd.hp-PCL','ty=MyOfficejet100000','product=(Trexa gureue)','priority=0','adminur=http://'+source_IPv4] - #file_print(type(rdata)) - for r in rdata: - length=hex(len(r))[2:] - #check http://code.activestate.com/recipes/576617-converting-arbitrary-size-python-integers-to-packe/ - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt= DNSRR(rrname="MyOfficejet10000._pdl-datasream._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - pkt=dnsrr_packet - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="MyOffice10000."+qname,type="PTR",rclass=32769)/DNSRR(rrname="HP10000.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4)/DNSRR(rrname="MyOffice100000."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/pkt - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="MyOffice10000."+qname,type="PTR",rclass=32769)/DNSRR(rrname="HP10000.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4)/DNSRR(rrname="MyOffice100000."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/pkt - elif ("_googlecast._tcp." in qname) and googlecast: - #qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - #make the SRV additional record - port=8009 - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight=0 - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority=0 - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - sublabels = "32799abf-18ea-631d-62ae-390515bb47c5.local".split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - srv_rrname=data+label_data - txt_record="" - rdata=['id=32799abf-18ea-631d-62ae-390515bb47c5','rm=','ve=05','md=Chromecast Ultra','ic=/setup/icon.png','fn=LivingRoom','ca=4101','st=0','bs=FA8FCA7EO948','rs=0'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt= DNSRR(rrname="Chromecast-Ultra-32799abf-18ea-631d-62ae-390515bb47c5."+qname,type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - pkt=dnsrr_packet - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="Chromecast-Ultra-32799abf-18ea-631d-62ae-390515bb47c5."+qname,type="PTR")/pkt/DNSRR(rrname="ChromecastUltra."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="32799abf-18ea-631d-62ae-390515bb47c5.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1,arcount=3)/DNSRR(rrname=qname,ttl=myttl,rdata="Chromecast-Ultra-32799abf-18ea-631d-62ae-390515bb47c5."+qname,type="PTR")/pkt/DNSRR(rrname="ChromecastUltra."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="32799abf-18ea-631d-62ae-390515bb47c5.local",ttl=myttl,type="A",rclass=32769,rdata=source_IPv4) - elif ("_airplay." in qname) and airtv: - #qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - - txt_record="" - rdata=['model=J33AP'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt= DNSRR(rrname="Apple TV-mitsos._device-info._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - pkt=dnsrr_packet - - txt_record="" - rdata=['deviceid=9C:20:7B:AD:6B:E4','features=0x5A7FFFF7,0xE','flags=0x44','model=AppleTV3,1','pk=ab69a89af6fe7ff1fd803f74c6681d786aff1e6bc52087e49cc8f22585916ccd','pi=a62a851e-d024-439f-9ee0-01ef1b23d6ca','srcvers=220.68','vv=2'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt2= DNSRR(rrname="Apple TV-mitsos._airplay._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt2.rdlen-=1 - mylength=len(pkt2.rrname)+12 - dnsrr_packet=str(pkt2)[0:mylength]+str(pkt2)[mylength+1::] - pkt2=dnsrr_packet - - txt_record="" - rdata=['cn=0,1,2,3','da=true','et=0,3,5','ft=0x5A7FFFF7,0xE','md=0,1,2','am=AppleTV3,1','pk=ab69a89af6fe7ff1fd803f74c6681d786aff1e6bc52087e49cc8f22585916ccd','sf=0x44','tp=UDP','vn=65537','vs=220.68','vv=2'] - for r in rdata: - length=hex(len(r))[2:] - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - pkt3= DNSRR(rrname="9C207BAD6BE4@Apple TV-mitsos._raop._tcp.local",type="TXT",ttl=myttl,rclass=32769,rdata=txt_record) - pkt3.rdlen-=1 - mylength=len(pkt3.rrname)+12 - dnsrr_packet=str(pkt3)[0:mylength]+str(pkt3)[mylength+1::] - pkt3=dnsrr_packet - - #make the SRV additional record - port=7000 - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight=0 - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority=0 - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - sublabels = "Apple-TV.local".split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - srv_rrname=data+label_data - - if unidns: - dns_packet=UDP(dport=53) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=3,arcount=6)/DNSRR(rrname=qname,ttl=myttl,rdata="Apple TV-mitsos._device-info."+qname,type="PTR")/pkt/DNSRR(rrname="_raop._tcp.local",ttl=myttl,rdata="9C207BAD6BE4@Apple TV-mitsos._raop._tcp.local",type="PTR")/pkt2/pkt3/DNSRR(rrname="Apple TV-mitsos."+qname,ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="9C207BAD6BE4@Apple TV-mitsos._raop._tcp.local",ttl=myttl,type="SRV",rclass=32769,rdata=srv_rrname)/DNSRR(rrname="Apple-TV.local",ttl=myttl,rdata=source_IPv4,type="A",rclass=32769)/DNSRR(rrname="Apple-TV.local",ttl=myttl,rdata=source_IPv6,type="AAAA",rclass=32769) - else: - if isinstance(dnsqr.qname,bytes): - qname=dnsqr.qname.decode("utf-8") - else: - qname=dnsqr.qname - if qname.endswith('.'): - qname=qname[:-1] - #file_print("Query Name = ",qname," Type=",dnsqr.qtype) - if unidns: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1)/DNSRR(rrname=qname,ttl=myttl,rdata=source_IPv4,type="A") - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0,ancount=1)/DNSRR(rrname=qname,ttl=myttl,rdata=source_IPv4,type="A") - file_print_pr("[DEBUG] Timestamp 9: ", timeNow()) - send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,d4,source_IPv6,d6,interface,hlimit,dns_packet,False,10.0,0.1)#CHANGE DEFAULT VALUES - file_print_pr("[DEBUG] Timestamp 10: ", timeNow()) - ### END "IF WE NEED TO AUTO RESPOND WITH A FAKE RESPONSE - ### NEXT LINES ARE ONLY USED TO PRINT RESULTS ### - if dnsqr.qclass==32769: - res = res0 + " | Question | "+dnsqr.qname.decode("utf-8") + " " + dns_type[dnsqr.qtype] +" QU Class:IN" - elif dnsqr.qclass==1: - res = res0 + " | Question | "+dnsqr.qname.decode("utf-8") + " "+ dns_type[dnsqr.qtype] + " QM Class:IN" - elif dnsqr.qclass==255: - res = res0 + " | Question | "+dnsqr.qname.decode("utf-8") + " "+ dns_type[dnsqr.qtype] + " QM Class:ANY" - else: - file_print("DNSQR:") - file_print("-----") - file_print(dnsqr.show()) - file_print("DEBUGGING IS NEEDED") - exit(0) - if print_res==1: - file_print(res) - queue.put(res) - block = block.payload - if dns.arcount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.ar) - for block in DNSBlocks: - if block.haslayer(DNSRROPT): - while isinstance(block,DNSRROPT):#Somewhat equivalent: while not isinstance(an, NoPayload): - dnsrropt=block.getlayer(DNSRROPT) - #print "DNS OPT Resource Record" - if dnsrropt.rrname == ".": - rrname = "" - else: - rrname = dnsrropt.rrname - if dnsrropt.type==41: - ARtype="OPT" - else: - ARtype=str(dnsrropt.type) - res = res0 + " | Additional_Record | " + rrname.decode("utf-8") + " " + ARtype - file_print_pr("[DEBUG] Timestamp 11: ", timeNow()) - if dnsrropt.haslayer(EDNS0TLV): - edns0tlv=dnsrropt.getlayer(EDNS0TLV) - if edns0tlv.optcode==4: - optcode="Reserved" - else: - optcode=str(edns0tlv.optcode) - res = res + " EDNS0TLV: " + optcode + " " + codecs.encode(edns0tlv.optdata, 'hex_codec').decode("utf-8") - if print_res==1: - file_print(res) - queue.put(res) - block = block.payload - elif block.haslayer(DNSRR): - while isinstance(block,DNSRR):#Somewhat equivalent: while not isinstance(an, NoPayload): - dnsrr=block.getlayer(DNSRR) - if dnsrr.rclass==32769: - - str_res0 = str(b_to_str(res0)) + "" - str_rrname = str(b_to_str(dnsrr.rrname)) + "" - str_type = str(b_to_str(dns_type[dnsrr.type])) + "" - str_rdata = str(b_to_str(dnsrr.rdata)) + "" - - res = str_res0 + " | DNS Resource Record | " + str_rrname + " " + str_type + " QU Class:IN " + str_rdata - elif dnsrr.rclass==1: - - str_res0 = str(b_to_str(res0)) + "" - str_rrname = str(b_to_str(dnsrr.rrname)) + "" - str_type = str(b_to_str(dns_type[dnsrr.type])) + "" - str_rdata = str(b_to_str(dnsrr.rdata)) + "" - - res = str_res0 + " | DNS Resource Record | " + str_rrname + " " + str_type + " QM Class:IN " + str_rdata - elif dnsrr.qclass==255: - - str_res0 = str(b_to_str(res0)) + "" - str_qname = str(b_to_str(dnsrr.qname)) + "" - str_qtype = str(b_to_str(dns_type[dnsrr.qtype])) + "" - - res = str_res0 + " | Question | " + str_qname + " " + str_qtype + " QM Class:ANY" - else: - file_print("DNSRR:") - file_print("-----") - file_print(dnsrr.show()) - file_print("DEBUGGING IS NEEDED HERE") - exit(0) - if dnsrr.type==33:#SRV Record - - str_res0 = str(b_to_str(res0)) + "" - str_rrname = str(b_to_str(dnsrr.rrname)) + "" - str_type = str(b_to_str(dns_type[dnsrr.type])) + "" - str_rclass = str(b_to_str(dnsrr.rclass)) + "" - - priority=str(dnsrr.rdata)[0].encode("HEX")+str(dnsrr.rdata)[1].encode("HEX") - weight=str(dnsrr.rdata)[2].encode("HEX")+str(dnsrr.rdata)[3].encode("HEX") - port_number=str(dnsrr.rdata)[4].encode("HEX")+str(dnsrr.rdata)[5].encode("HEX") - - res = str_res0 + " | Additional_Record | "+ str_rrname + " " + str_type+" " + str_rclass + " priority="+str(int(priority,16))+" weight="+str(int(weight,16))+" port="+str(int(port_number,16))+" target="+str(dnsrr.rdata)[6::] - else: - rdata=dnsrr.rdata - if isinstance(rdata,bytes): - rdata = rdata.decode("utf-8") - if "._tcp." not in rdata and "._udp." not in rdata: - if rdata == "_dhnap.": - rdata=rdata+"_tcp." - - str_res0 = str(b_to_str(res0)) + "" - str_rrname = str(b_to_str(dnsrr.rrname)) + "" - str_type = str(b_to_str(dns_type[dnsrr.type])) + "" - str_rdata = str(b_to_str(dnsrr.rdata)) + "" - str_rclass = str(b_to_str(dnsrr.rclass)) + "" - file_print_pr("[DEBUG] Timestamp 12: ", timeNow()) - res = str_res0 + " | Additional_Record | "+str_rrname + " " + str_type+" " + str_rclass + ' "' +str_rdata+'"' - if show_ttl: - res = res + " TTL:"+str(dnsrr.ttl) - if print_res==1: - file_print(res) - file_print_pr("[DEBUG] Timestamp 13: ", timeNow()) - queue.put(res) - block = block.payload - file_print_pr("[DEBUG] Timestamp 14: ", timeNow()) - - if dns.ancount>0: - DNSBlocks = [ ] - DNSBlocks.append(dns.an) - for block in DNSBlocks: - file_print_pr("[DEBUG] Timestamp 15: ", timeNow()) - while isinstance(block,DNSRR): - dnsrr=block.getlayer(DNSRR) - if dnsrr.rclass==1: - rclass="Class:IN" - file_print_pr("[DEBUG] Timestamp 16: ", timeNow()) - else: - rclass="Class:"+str(dnsrr.rclass) - rdata=dnsrr.rdata - if isinstance(rdata,bytes): - rdata = rdata.decode("utf-8") - if dnsrr.type==33:#SRV Record - priority=str(dnsrr.rdata)[0].encode("HEX")+str(dnsrr.rdata)[1].encode("HEX") - weight=str(dnsrr.rdata)[2].encode("HEX")+str(dnsrr.rdata)[3].encode("HEX") - port_number=str(dnsrr.rdata)[4].encode("HEX")+str(dnsrr.rdata)[5].encode("HEX") - res = res0 + " | Answer | "+dnsrr.rrname + " " + dns_type[dnsrr.type]+" " + rclass + " priority="+str(int(priority,16))+" weight="+str(int(weight,16))+" port="+str(int(port_number,16))+" target="+str(dnsrr.rdata)[6::] - else: - if "._tcp." not in rdata and "._udp." not in rdata: - if rdata == "_dhnap.": - rdata=dnsrr.rdata+"_tcp." - if isinstance(rdata,list): - rdata = b" ".join(rdata).decode("utf-8") - res = res0 + " | Answer | "+dnsrr.rrname.decode("utf-8") + " " + dns_type[dnsrr.type]+" " + rclass + ' "' +rdata+'"' - file_print_pr("[DEBUG] Timestamp 17: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 18: ", timeNow()) - if show_ttl: - res = res + " TTL:"+str(dnsrr.ttl) - if print_res==1: - file_print(res) - file_print_pr("[DEBUG] Timestamp 19: ", timeNow()) - queue.put(res) - block = block.payload - file_print_pr("[DEBUG] Timestamp 20: ", timeNow()) - if dns.nscount>0: #MAYBE HERE - file_print_pr("[DEBUG] Timestamp 21: ", timeNow()) - DNSBlocks = [ ] - DNSBlocks.append(dns.ns) - file_print_pr("[DEBUG] Timestamp 22: ", timeNow()) - for block in DNSBlocks: - file_print_pr("[DEBUG] Timestamp 23: ", timeNow()) - while isinstance(block,DNSRR): - dnsrr=block.getlayer(DNSRR) - if dnsrr.rclass==1: - rclass="Class:IN" - file_print_pr("[DEBUG] Timestamp 24: ", timeNow()) - else: - rclass="Class:"+str(dnsrr.rclass) - - str_res0 = str(b_to_str(res0)) + "" - str_rrname = str(b_to_str(dnsrr.rrname)) + "" - str_type = str(b_to_str(dns_type[dnsrr.type])) + "" - str_rdata = str(b_to_str(dnsrr.rdata)) + "" - str_rclass = str(b_to_str(rclass)) + "" - - res = str_res0 + " Auth_NS: "+str_rrname + " " +str_type+" " + str_rclass + ' "' +str_rdata+'"' - if show_ttl: - res = res + " TTL:"+str(dnsrr.ttl) - if print_res==1: - file_print(res) - file_print_pr("[DEBUG] Timestamp 25: ", timeNow()) - queue.put(res) - block = block.payload - file_print_pr("[DEBUG] Timestamp 26: ", timeNow()) - else: - file_print_pr("[DEBUG] Timestamp 27: ", timeNow()) - else: - file_print_pr("[DEBUG] Timestamp 28: ", timeNow()) - else: - file_print_pr("[DEBUG] Timestamp 29: ", timeNow()) - else: - file_print_pr("[DEBUG] Timestamp 30: ", timeNow()) - - file_print_pr("[DEBUG] Timestamp 31: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 32: ", timeNow(), " ", res0) - file_print_pr("[DEBUG] Timestamp 33: ", timeNow(), " ", res) - - -######################################## -########### REQUEST FUNCTION ########### -######################################## -def requests(interface,v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,d4,d6,hlimit,unidns,domain,query,types_of_queries,add_domain,query_class,flood,flooding_interval,flooding_timeout): - if add_domain: - file_print("Sending mdns requests") - domain_list = domain.split(",") - query_list = query.split(",") - if add_domain: - the_query=query_list[0]+"."+domain_list[0] - else: - types_of_queries="ALL"#implies that first a generic scan has beem performed - the_query=query_list[0] - dns_query=DNSQR(qname=the_query,qtype=types_of_queries,qclass=int(query_class)) - for j in range(1,len(query_list)): - if add_domain: - the_query=query_list[j]+"."+domain_list[0] - else: - the_query=query_list[j] - dns_query=dns_query/DNSQR(qname=the_query,qtype=types_of_queries,qclass=int(query_class)) - if add_domain: - for i in range(1,len(domain_list)): - for j in query_list: - the_query=j+"."+domain_list[i] - dns_query=dns_query/DNSQR(qname=the_query,qtype=types_of_queries,qclass=int(query_class)) - if unidns: - dns_packet=UDP(dport=53)/DNS(qr=0,qd=dns_query) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=0,qd=dns_query) - send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,d4,source_IPv6,d6,interface,hlimit,dns_packet,flood,flooding_timeout,flooding_interval) - -######################################## -######## SEND PACKETS FUNCTION ######### -######################################## -def send_packets(v4,v6,source_mac,target_mac1,target_mac2,source_IPv4,dst_ipv4,source_IPv6,dst_ipv6,interface,hlimit,payload,flood,flooding_timeout,flooding_interval): - if v4 or not v6: - packet=IP(src=source_IPv4,dst=dst_ipv4,ttl=hlimit,proto="udp")/payload - if len(packet)>1500: - frags=fragment(packet) - packets=[] - for frag in frags: - pkt1=Ether(src=source_mac,dst=target_mac1)/frag - packets.append(pkt1) - if flood: - counter=0.0 - file_print("Stop flooding after ",flooding_timeout," sec.") - while(counter1500: - frags2=fragment6(IPv6(src=source_IPv6,dst=dst_ipv6,hlim=hlimit)/IPv6ExtHdrFragment()/payload,1480) - packets=[] - for frag2 in frags2: - pkt2=Ether(src=source_mac,dst=target_mac2)/frag2 - packets.append(pkt2) - if flood: - counter=0.0 - file_print("Stop flooding after ",flooding_timeout," sec.") - while(counterResponse, aa=1=>Server is an authority for the domain, rd=0=> Do not query recursively - file_print_pr("[DEBUG] Timestamp 43: ", timeNow()) - if values.dns: - dns_packet=UDP(dport=53)/DNS(qr=1,aa=1,rd=0) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=1,aa=1,rd=0) - file_print_pr("[DEBUG] Timestamp 44: ", timeNow()) - responses = values.dns_response.split(",") - no_of_answers=0 - no_of_additional_records=0 - dnsar=None - for r in responses: - values_of_responses = r.split("/") - dnsrr=DNSRR() - port=0 - weight=0 - priority=0 - no_of_answers+=1 - this_is_a_dns_ar=False - rdata=[] - for dns_values in values_of_responses: - #print dns_values - value = dns_values.split("==") - if value[0]=="Type": - dnsrr.type=value[1] - elif value[0]=="Name": - dnsrr.rrname=value[1] - elif value[0]=="Target": - rdata.append(value[1]) - elif value[0]=="TTL": - dnsrr.ttl=int(value[1]) - elif value[0]=="Flush": - if value[1]=="True": - dnsrr.rclass=32769 - elif value[0]=="Priority": - priority=int(value[1]) - elif value[0]=="Weight": - weight=int(value[1]) - elif value[0]=="Port": - port=int(value[1]) - elif value[0]=="AR": - if value[1]=="True": - no_of_additional_records+=1 - this_is_a_dns_ar=True - if dnsrr.type==33: - port='{0:016b}'.format(port) - port="{0:0>4X}".format(int(port, 2)) - weight='{0:016b}'.format(weight) - weight="{0:0>4X}".format(int(weight, 2)) - priority='{0:016b}'.format(priority) - priority="{0:0>4X}".format(int(priority, 2)) - data=priority.decode("hex")+weight.decode("hex")+port.decode("hex") - #http://stackoverflow.com/questions/26933016/rdata-field-of-a-dns-sd-ptr-packet-sent-via-scapy-results-in-an-unknown-extended - sublabels = rdata[0].split(".") + [""] - label_format = "" - for s in sublabels: - label_format = '%s%dp' % (label_format, len(s) + 1) - label_data = struct.pack(label_format, *sublabels) - dnsrr.rdata=data+label_data - elif dnsrr.type==16: - txt_record="" - for r in rdata: - length=hex(len(r))[2:] - #check http://code.activestate.com/recipes/576617-converting-arbitrary-size-python-integers-to-packe/ - if len(r) > 255: - s=struct.Struct('I')# CHECK IT - else: - s=struct.Struct('B') - value=(len(r),) - packed_data=s.pack(*value) - txt_record=txt_record+packed_data+r - dnsrr.rdata=txt_record - ################## - pkt=dnsrr - pkt.rdlen-=1 - mylength=len(pkt.rrname)+12 - dnsrr_packet=str(pkt)[0:mylength]+str(pkt)[mylength+1::] - ################## - dnsrr=dnsrr_packet - else: - dnsrr.rdata=rdata[0] - if not this_is_a_dns_ar: - dns_packet=dns_packet/dnsrr - else: - if not dnsar: - dnsar=dnsrr - else: - dnsar=dnsar/dnsrr - if dnsar: - dns_packet=dns_packet/dnsar - dns_packet[DNS].ancount=no_of_answers-no_of_additional_records - dns_packet[DNS].arcount=no_of_additional_records - send_packets(values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,values.d4,source_IPv6,values.d6,values.interface,values.hlimit,dns_packet,values.flood,values.flooding_timeout,values.flooding_interval) - elif values.rdns_scanning: - file_print_pr("[DEBUG] Timestamp 45: ", timeNow()) - dns_query=None - ipn = ipaddress.ip_network(values.rdns_scanning, strict=False) - for ip in ipn.hosts(): - the_query = ip.reverse_pointer - if not dns_query: - dns_query=DNSQR(qname=the_query,qtype=values.qtype,qclass=values.q_class) - else: - dns_query=dns_query/DNSQR(qname=the_query,qtype=values.qtype,qclass=values.q_class) - if values.dns: - dns_packet=UDP(dport=53)/DNS(qr=0,qd=dns_query) - else: - dns_packet=UDP(sport=5353,dport=5353)/DNS(qr=0,qd=dns_query) - send_packets(values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,values.d4,source_IPv6,values.d6,values.interface,values.hlimit,dns_packet,values.flood,values.flooding_timeout,values.flooding_interval) - file_print_pr("[DEBUG] Timestamp 46: ", timeNow()) - elif values.service_scan: - file_print_pr("[DEBUG] Timestamp 47: ", timeNow()) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,values.query,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - file_print_pr("[DEBUG] Timestamp 48: ", timeNow()) - ############################################################################################ - ############################################################################################ - if pr: - file_print_pr("[DEBUG] Timestamp 49: ", timeNow()) - try: - file_print_pr("[DEBUG] Timestamp 50: ", timeNow()) #HERE STUCK - pr.join(20) - if pr.is_alive(): - file_print("SUB-PROCESS KILLED TIMESTAMP: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 51: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 52: ", timeNow()) - except KeyboardInterrupt: - file_print("Exiting on user's request 2") - exit(0) - - file_print_pr("[DEBUG] Timestamp 53: ", timeNow()) - - #### AFTER EXITING, PRINT THE RESULTS #### - results=[] - while not q.empty(): - results.append(q.get()) - if values.rdns_scanning: - targets=[] - q2 = multiprocessing.Queue() - file_print_pr("[DEBUG] Timestamp 54: ", timeNow()) - pr2 = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q2,values.dns,values.show_ttl, values.dos_ttl,values.conflict, values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr2.daemon = True - pr2.start() - time.sleep(1) #to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - file_print_pr("[DEBUG] Timestamp 55: ", timeNow()) - for r in results: - r2=r.split(" ") - service=r2[7].strip('"') - if service.endswith('local.'): - service=service[:-6] - if service.endswith('.'): - service=service[:-1] - if (r2[1],service) not in targets: - targets.append((r2[1],service)) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,service,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - if pr2: - file_print_pr("[DEBUG] Timestamp 56: ", timeNow()) - try: - file_print_pr("[DEBUG] Timestamp 57: ", timeNow()) - pr2.join(15) - if pr.is_alive(): - file_print("SUB-PROCESS KILLED TIMESTAMP: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 58: ", timeNow()) - except KeyboardInterrupt: - file_print("Exiting on user's request 3") - while not q2.empty(): - results.append(q2.get()) - elif values.service_scan: - targets=[] - q2 = multiprocessing.Queue() - file_print_pr("[DEBUG] Timestamp 59: ", timeNow()) - pr2 = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q2,values.dns,values.show_ttl, values.dos_ttl,values.conflict, values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr2.daemon = True - pr2.start() - time.sleep(1) #to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - file_print_pr("[DEBUG] Timestamp 60: ", timeNow()) - for r in results: - r2=r.split(" ") - service=r2[7].strip('"')[:-1] - if (r2[1],service) not in targets: - file_print((r2[1],service)) - targets.append((r2[1],service)) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,service,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - if pr2: - try: - file_print_pr("[DEBUG] Timestamp 61: ", timeNow()) - pr2.join(15) - if pr.is_alive(): - file_print("SUB-PROCESS KILLED TIMESTAMP: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 62: ", timeNow()) - except KeyboardInterrupt: - file_print("Exiting on user's request 4") - while not q2.empty(): - results.append(q2.get()) - targets2=[] - q3 = multiprocessing.Queue() - file_print_pr("[DEBUG] Timestamp 63: ", timeNow()) - pr3 = multiprocessing.Process(target=Sniffer, args=(myfilter, values.interface, float(values.sniffer_timeout),q3,values.dns,values.show_ttl, values.dos_ttl, values.conflict,values.ttl,values.d4, values.d6, values.target_mac, values.auto_fake_responses,source_IPv6, source_IPv4, target_mac1, target_mac2,source_mac,values.hlimit,values.workstation,values.printer,values.googlecast,values.airtv,values.flood,values.flooding_timeout,values.flooding_interval,values.v4,values.v6)) - pr3.daemon = True - pr3.start() - time.sleep(1) #to make sure than sniffer has started before we proceed, otherwise you may miss some traffic - file_print_pr("[DEBUG] Timestamp 64: ", timeNow()) - for r in results: - r2=r.split(" ") - service=r2[4] - if service.endswith('local.'): - service=service[:-6] - if service.endswith('.'): - service=service[:-1] - if (r2[1],service) not in targets and (r2[1],service) not in targets2 and "_services._dns-sd._udp" not in service: - targets2.append((r2[1],service)) - requests(values.interface,values.v4,values.v6,source_mac,target_mac1,target_mac2,source_IPv4,source_IPv6,values.d4,values.d6,values.hlimit,values.dns,values.domain,service,values.qtype,True,q_class,values.flood,values.flooding_interval,values.flooding_timeout) - if pr3: - try: - file_print_pr("[DEBUG] Timestamp 65: ", timeNow()) - pr3.join(15) - if pr.is_alive(): - file_print("SUB-PROCESS KILLED TIMESTAMP: ", timeNow()) - file_print_pr("[DEBUG] Timestamp 66: ", timeNow()) - except KeyboardInterrupt: - file_print("Exiting on user's request 5") - while not q3.empty(): - results.append(q3.get()) - file_print("\n*********************************************RESULTS*********************************************") - for r in results: - file_print(r) - -if __name__ == '__main__': - main() diff --git a/front/plugins/pholus_scan/script.py b/front/plugins/pholus_scan/script.py deleted file mode 100755 index 66185878..00000000 --- a/front/plugins/pholus_scan/script.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env python - -import os -import pathlib -import argparse -import sys -import re -import base64 -import subprocess -from time import strftime - - -# Register NetAlertX directories -INSTALL_PATH="/app" -sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"]) - -from logger import mylog -from plugin_helper import Plugin_Object, Plugin_Objects -from helper import timeNowTZ, get_setting_value -from const import logPath, applicationPath -import conf -from pytz import timezone - -# Make sure the TIMEZONE for logging is correct -conf.tz = timezone(get_setting_value('TIMEZONE')) - -CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) -LOG_FILE = os.path.join(CUR_PATH, 'script.log') -RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') -fullPholusPath = os.path.join(CUR_PATH, 'pholus/pholus3.py') - -pluginName = 'PHOLUS' - -def main(): - - # the script expects a parameter in the format of userSubnets=subnet1,subnet2,... - parser = argparse.ArgumentParser(description='Import devices from settings') - parser.add_argument('userSubnets', nargs='+', help="list of subnets with options") - parser.add_argument('timeoutSec', nargs='+', help="timeout") - values = parser.parse_args() - - # Assuming Plugin_Objects is a class or function that reads data from the RESULT_FILE - # and returns a list of objects called 'devices'. - plugin_objects = Plugin_Objects(RESULT_FILE) - - # Print a message to indicate that the script is starting. - mylog('verbose',[f'[{pluginName}] In script']) - - # Assuming 'values' is a dictionary or object that contains a key 'userSubnets' - # which holds a list of user-submitted subnets. - # Printing the userSubnets list to check its content. - mylog('verbose',[f'[{pluginName}] Subnets: ', values.userSubnets]) - mylog('verbose',[f'[{pluginName}] len Subnets: ', len(values.userSubnets)]) - - # Extract the base64-encoded subnet information from the first element of the userSubnets list. - # The format of the element is assumed to be like 'userSubnets=b'. - userSubnetsParamBase64 = values.userSubnets[0].split('userSubnets=b')[1] - timeoutSec = values.timeoutSec[0].split('=')[1] - - # Printing the extracted base64-encoded subnet information. - mylog('verbose', [f'[{pluginName}] { userSubnetsParamBase64 }']) - mylog('verbose', [f'[{pluginName}] { timeoutSec }']) - - # Decode the base64-encoded subnet information to get the actual subnet information in ASCII format. - userSubnetsParam = base64.b64decode(userSubnetsParamBase64).decode('ascii') - - # Print the decoded subnet information. - mylog('verbose', [f'[{pluginName}] userSubnetsParam { userSubnetsParam } ']) - - # Check if the decoded subnet information contains multiple subnets separated by commas. - # If it does, split the string into a list of individual subnets. - # Otherwise, create a list with a single element containing the subnet information. - if ',' in userSubnetsParam: - subnets_list = userSubnetsParam.split(',') - else: - subnets_list = [userSubnetsParam] - - # Execute the ARP scanning process on the list of subnets (whether it's one or multiple subnets). - # The function 'execute_arpscan' is assumed to be defined elsewhere in the code. - all_entries = execute_pholus_scan(subnets_list, timeoutSec) - - - for entry in all_entries: - plugin_objects.add_object( - # "Info", "Time", "MAC", "IP_v4_or_v6", "Record_Type", "Value" - primaryId = entry[2], - secondaryId = entry[3], - watched1 = entry[0], - watched2 = entry[4], - watched3 = entry[5], - watched4 = '', - extra = entry[0], - foreignKey = entry[2]) - - plugin_objects.write_result_file() - - return 0 - - -def execute_pholus_scan(userSubnets, timeoutSec): - # output of possible multiple interfaces - result_list = [] - - timeoutPerSubnet = float(timeoutSec) / len(userSubnets) - - mylog('verbose', [f'[{pluginName}] { timeoutPerSubnet } ']) - - # scan each interface - for interface in userSubnets: - - temp = interface.split("--interface=") - - if len(temp) != 2: - mylog('verbose', [f'[{pluginName}] Skip scan (need interface in format "192.168.1.0/24 --inteface=eth0"), got: ', interface]) - return - - mask = temp[0].strip() - interface = temp[1].strip() - - pholus_output_list = execute_pholus_on_interface (interface, timeoutPerSubnet, mask) - - mylog('verbose', [f'[{pluginName}] { pholus_output_list } ']) - - - result_list += pholus_output_list - - - mylog('verbose', [f'[{pluginName}] Pholus output number of entries:', len(result_list)]) - mylog('verbose', [f'[{pluginName}] List:', result_list]) - - return result_list - -def execute_pholus_on_interface(interface, timeoutSec, mask): - - - # logging & updating app state - - mylog('verbose', [f'[{pluginName}] Scan: Pholus for ', str(timeoutSec), 's ('+ str(round(int(timeoutSec) / 60, 1)) +'min)']) - mylog('verbose', [f'[{pluginName}] Pholus scan on [interface] ', interface, ' [mask] ' , mask]) - - # the scan always lasts 2x as long, so the desired user time from settings needs to be halved - adjustedTimeout = str(round(int(timeoutSec) / 2, 0)) - - # python3 -m trace --trace /app/pholus/pholus3.py eth1 -rdns_scanning 192.168.1.0/24 -stimeout 600 - pholus_args = ['python3', fullPholusPath, interface, "-rdns_scanning", mask, "-stimeout", adjustedTimeout] - - # Execute command - output = "" - - try: - # try runnning a subprocess with a forced (timeout + 30 seconds) in case the subprocess hangs - output = subprocess.check_output (pholus_args, universal_newlines=True, stderr=subprocess.STDOUT, timeout=(timeoutSec + 30)) - except subprocess.CalledProcessError as e: - # An error occured, handle it - mylog('verbose', [f'[{pluginName}]', e.output]) - mylog('verbose', [f'[{pluginName}] ⚠ ERROR - Pholus Scan - check logs']) - except subprocess.TimeoutExpired as timeErr: - mylog('verbose', [f'[{pluginName}] Pholus TIMEOUT - the process forcefully terminated as timeout reached']) - - if output == "": # check if the subprocess failed - mylog('verbose', [f'[{pluginName}] Scan: Pholus FAIL - check logs']) - else: - mylog('verbose', [f'[{pluginName}] Scan: Pholus SUCCESS']) - - # check the last run output - f = open(logPath + '/pholus_lastrun.log', 'r+') - newLines = f.read().split('\n') - f.close() - - # cleanup - select only lines containing a separator to filter out unnecessary data - newLines = list(filter(lambda x: '|' in x, newLines)) - - # build SQL query parameters to insert into the DB - params = [] - - for line in newLines: - columns = line.split("|") - if len(columns) == 4: - # "Info", "Time", "MAC", "IP_v4_or_v6", "Record_Type", "Value" - params.append( [interface + " " + mask, timeNowTZ() , columns[0].replace(" ", ""), columns[1].replace(" ", ""), columns[2].replace(" ", ""), columns[3]]) - - return params - - - - - - -#=============================================================================== -# BEGIN -#=============================================================================== -if __name__ == '__main__': - main() diff --git a/front/presence.php b/front/presence.php index a73e85b3..76020c53 100755 --- a/front/presence.php +++ b/front/presence.php @@ -14,6 +14,7 @@ @@ -124,41 +125,6 @@
- - - diff --git a/front/settings.php b/front/settings.php index 5b0e2648..443f4859 100755 --- a/front/settings.php +++ b/front/settings.php @@ -835,7 +835,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX if(!canReadAndWriteConfig) { showMessage (getString("settings_readonly"), 10000, "modal_red"); - console.log(`app.conf seems to be read only (canRWConfig: ${canReadAndWriteConfig}`); + console.log(`app.conf seems to be read only (canRWConfig: ${canReadAndWriteConfig})`); } else { // check if config file has been updated diff --git a/server/database.py b/server/database.py index 2ff34aaf..55cb5492 100755 --- a/server/database.py +++ b/server/database.py @@ -476,10 +476,6 @@ class DB(): self.sql.execute(""" DROP VIEW IF EXISTS Sessions_Devices;""") self.sql.execute("""CREATE VIEW Sessions_Devices AS SELECT * FROM Sessions LEFT JOIN "Devices" ON ses_MAC = devMac;""") - - - - # ------------------------------------------------------------------------- # Settings table setup # ------------------------------------------------------------------------- @@ -505,24 +501,9 @@ class DB(): """) - # ------------------------------------------------------------------------- - # Pholus_Scan table setup - # ------------------------------------------------------------------------- - # Create Pholus_Scan table if missing - mylog('verbose', ["[upgradeDB] Re-creating Pholus_Scan table"]) - self.sql.execute("""CREATE TABLE IF NOT EXISTS "Pholus_Scan" ( - "Index" INTEGER, - "Info" TEXT, - "Time" TEXT, - "MAC" TEXT, - "IP_v4_or_v6" TEXT, - "Record_Type" TEXT, - "Value" TEXT, - "Extra" TEXT, - PRIMARY KEY("Index" AUTOINCREMENT) - ); - """) + mylog('verbose', ["[upgradeDB] Removing Pholus_Scan table"]) + self.sql.execute("""DROP TABLE IF EXISTS Pholus_Scan""") # ------------------------------------------------------------------------- diff --git a/server/device.py b/server/device.py index af876119..a256799c 100755 --- a/server/device.py +++ b/server/device.py @@ -4,7 +4,7 @@ import subprocess import conf import os import re -from helper import timeNowTZ, get_setting, get_setting_value, list_to_where, resolve_device_name_dig, resolve_device_name_pholus, get_device_name_nbtlookup, get_device_name_nslookup, get_device_name_mdns, check_IP_format, sanitize_SQL_input +from helper import timeNowTZ, get_setting, get_setting_value, list_to_where, resolve_device_name_dig, get_device_name_nbtlookup, get_device_name_nslookup, get_device_name_mdns, check_IP_format, sanitize_SQL_input from logger import mylog, print_log from const import vendorsPath, vendorsPathNewest, sql_generateGuid @@ -501,7 +501,6 @@ def update_devices_names (db): foundmDNSLookup = 0 foundNsLookup = 0 foundNbtLookup = 0 - foundPholus = 0 # Gen unknown devices sql.execute ("SELECT * FROM Devices WHERE devName IN ('(unknown)','', '(name not found)') AND devLastIP <> '-'") @@ -515,15 +514,6 @@ def update_devices_names (db): # Devices without name mylog('verbose', f'[Update Device Name] Trying to resolve devices without name. Unknown devices count: {len(unknownDevices)}') - # get names from Pholus scan - sql.execute ('SELECT * FROM Pholus_Scan where "Record_Type"="Answer"') - pholusResults = list(sql.fetchall()) - db.commitDB() - - # Number of entries from previous Pholus scans - mylog('verbose', ['[Update Device Name] Pholus entries from prev scans: ', len(pholusResults)]) - - for device in unknownDevices: newName = nameNotFound @@ -548,26 +538,12 @@ def update_devices_names (db): if newName != nameNotFound: foundNsLookup += 1 - # Resolve device name with NSLOOKUP plugin data + # Resolve device name with NBTLOOKUP plugin data if newName == nameNotFound: newName = get_device_name_nbtlookup(db, device['devMac'], device['devLastIP']) if newName != nameNotFound: foundNbtLookup += 1 - - - # Resolve with Pholus - if newName == nameNotFound: - - # Try MAC matching - newName = resolve_device_name_pholus (device['devMac'], device['devLastIP'], pholusResults, nameNotFound, False) - # Try IP matching - if newName == nameNotFound: - newName = resolve_device_name_pholus (device['devMac'], device['devLastIP'], pholusResults, nameNotFound, True) - - # count - if newName != nameNotFound: - foundPholus += 1 # if still not found update name so we can distinguish the devices where we tried already if newName == nameNotFound : @@ -579,11 +555,11 @@ def update_devices_names (db): if device['devName'] != nameNotFound: recordsNotFound.append (["(name not found)", device['devMac']]) else: - # name was found with DiG or Pholus + # name was found recordsToUpdate.append ([newName, device['devMac']]) # Print log - mylog('verbose', [f'[Update Device Name] Names Found (DiG/mDNS/NSLOOKUP/NBTSCAN/Pholus): {len(recordsToUpdate)} ({foundDig}/{foundmDNSLookup}/{foundNsLookup}/{foundNbtLookup}/{foundPholus})'] ) + mylog('verbose', [f'[Update Device Name] Names Found (DiG/mDNS/NSLOOKUP/NBTSCAN): {len(recordsToUpdate)} ({foundDig}/{foundmDNSLookup}/{foundNsLookup}/{foundNbtLookup})'] ) mylog('verbose', [f'[Update Device Name] Names Not Found : {notFound}'] ) # update not found devices with (name not found) diff --git a/server/helper.py b/server/helper.py index 086587ef..dcc57af0 100755 --- a/server/helper.py +++ b/server/helper.py @@ -695,89 +695,9 @@ def resolve_device_name_dig (pMAC, pIP): #------------------------------------------------------------------------------- -# DNS record (Pholus/Name resolution) cleanup methods +# DNS record (Name resolution) cleanup methods #------------------------------------------------------------------------------- -#------------------------------------------------------------------------------- -# Disclaimer - I'm interfacing with a script I didn't write (pholus3.py) so it's possible I'm missing types of answers -# it's also possible the pholus3.py script can be adjusted to provide a better output to interface with it -# Hit me with a PR if you know how! :) -def resolve_device_name_pholus (pMAC, pIP, allRes, nameNotFound, match_IP = False): - - pholusMatchesIndexes = [] - - result = nameNotFound - - # Collect all Pholus entries with matching MAC and of type Answer - index = 0 - for result in allRes: - # limiting entries used for name resolution to the ones containing the current IP (v4 only) - if ((match_IP and result["IP_v4_or_v6"] == pIP ) or ( result["MAC"] == pMAC )) and result["Record_Type"] == "Answer" and '._googlezone' not in result["Value"]: - # found entries with a matching MAC address, let's collect indexes - pholusMatchesIndexes.append(index) - - index += 1 - - # return if nothing found - if len(pholusMatchesIndexes) == 0: - return nameNotFound - - # we have some entries let's try to select the most useful one - # Do I need to pre-order allRes to have the most valuable onse on the top? - - for i in pholusMatchesIndexes: - if not checkIPV4(allRes[i]['IP_v4_or_v6']): - continue - - value = allRes[i]["Value"] - - # airplay matches contain a lot of information - # Matches for example: - # Brand Tv (50)._airplay._tcp.local. TXT Class:32769 "acl=0 deviceid=66:66:66:66:66:66 features=0x77777,0x38BCB46 rsf=0x3 fv=p20.T-FFFFFF-03.1 flags=0x204 model=XXXX manufacturer=Brand serialNumber=XXXXXXXXXXX protovers=1.1 srcvers=777.77.77 pi=FF:FF:FF:FF:FF:FF psi=00000000-0000-0000-0000-FFFFFFFFFF gid=00000000-0000-0000-0000-FFFFFFFFFF gcgl=0 pk=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - if '._airplay._tcp.local. TXT Class:32769' in value: - return cleanDeviceName(value.split('._airplay._tcp.local. TXT Class:32769')[0], match_IP) - - # second best - contains airplay - # Matches for example: - # _airplay._tcp.local. PTR Class:IN "Brand Tv (50)._airplay._tcp.local." - if '_airplay._tcp.local. PTR Class:IN' in value and ('._googlecast') not in value: - return cleanDeviceName(value.split('"')[1], match_IP) - - # Contains PTR Class:32769 - # Matches for example: - # 3.1.168.192.in-addr.arpa. PTR Class:32769 "MyPc.local." - if 'PTR Class:32769' in value: - return cleanDeviceName(value.split('"')[1], match_IP) - - # Contains AAAA Class:IN - # Matches for example: - # DESKTOP-SOMEID.local. AAAA Class:IN "fe80::fe80:fe80:fe80:fe80" - if 'AAAA Class:IN' in value: - return cleanDeviceName(value.split('.local.')[0], match_IP) - - # Contains _googlecast._tcp.local. PTR Class:IN - # Matches for example: - # _googlecast._tcp.local. PTR Class:IN "Nest-Audio-ff77ff77ff77ff77ff77ff77ff77ff77._googlecast._tcp.local." - if '_googlecast._tcp.local. PTR Class:IN' in value and ('Google-Cast-Group') not in value: - return cleanDeviceName(value.split('"')[1], match_IP) - - # Contains A Class:32769 - # Matches for example: - # Android.local. A Class:32769 "192.168.1.6" - if ' A Class:32769' in value: - return cleanDeviceName(value.split(' A Class:32769')[0], match_IP) - - # Contains PTR Class:IN - # Matches for example: - # _esphomelib._tcp.local. PTR Class:IN "ceiling-light-1._esphomelib._tcp.local." - if 'PTR Class:IN' in value and len(value.split('"')) > 1: - return cleanDeviceName(value.split('"')[1], match_IP) - - return nameNotFound - - - -#------------------------------------------------------------------------------- import dns.resolver def cleanDeviceName(str, match_IP):