feat(Features): 🚧 Hidden Dragon Work

Many changes performed in development of Hidden Dragon

hdragon command is broken for development
This commit is contained in:
anoduck 2024-03-12 18:03:38 -04:00
parent 4418d3c65d
commit f2c940ae37
19 changed files with 496 additions and 88 deletions

View file

@ -18,4 +18,21 @@ So, if my attention span holds up, this should be something worth while.
What set aside the original AT&T Unix from other operating systems of the time was Dennis Ritchie's
unwavering dedication to thoroughly well-written documentation, and project transparency. As also
the creator of the "C" programming language, Ritchie created most of the codebase for modern
computing. We should all keep the importance of documentation in mind in our endeavours.
computing. In honor of this spirit of dedication to documentation, we all should struggle to make
our own documentation worth it.
Well, that was a load of long winded bullshittery, let get to the good stuff.
### Acquiring Access Point Information
I do not claim to be any whiz at anything concerning network security, but what little I have
learned proves that nothing happens like it does in the movies. There are are very intelligent and
adept programmers out there, but it took them years if not a lifetime to obtain this knowledge, and
more often than not, they had a hell of a lot of help to get there. The point of mentioning this is
to stress the amount of effort real network security requires. You really have to invest time and
effort into studying your target, and this will take a lot of time.
The Hidden Dragon feature takes an approach that has to have been exploited by several hundred chaps
before us. It is to acquire the name of local access points in your target area. You can do this by
performing wardriving on your own, or you can acquire a list of access points from publicly
available sources, such as wigle.

View file

@ -182,6 +182,13 @@ options:
A single or comma seperated list of channels.
```
## Citations
```text
Hansen, Y. (2018). Python Scapy Dot11. Createspace Independent Publishing Platform.
rpp0. (2024, January 23). rpp0/scapy-fakeap. GitHub. https://github.com/rpp0/scapy-fakeap
```
## Author

12
ap_db-rearrange.awk Normal file
View file

@ -0,0 +1,12 @@
BEGIN {
FS=OFS=",";
RS="\n";
outfile = "ap_db.csv";
}
NR !=1 {
!$1 and $1 !=0 {print "NULL"}
srand() $0;
}
print > outfile

View file

@ -10,7 +10,30 @@
# ---------------------------------------
* Changelog
** unreleased
***
*** 2024.03.11
- Using standard csv to rearrange network database
- Created bare knuckle dhcp server
- Added function for dhcp to assign more than one IP address.
- Added Eap file
- Corrected reading of version file from __version__.py
- for some reason still using semver to parse version
- corrected parsing of configuration file when there is none.
- renamed access point database csv to netdb_file
- Renamed DataFrame class to CtigerDataFrame to avoid confusion
- Corrected dual loading of ap network dataframe
- added contents of rpy.py to mkintf
*** 2024.02.24
- Created awk script to rearrange ap_db file.
- Further flushing out of args to pass to hidden dragon.
- Polished up TapIF Class
- Removed mon_type from list of arguments for Hidden Dragon.
*** 2024.02.23
- Added two additional dataclasses to the data module.
- Log level selection no longer produces errors
- Added new ascii art to crouching tiger.
*** 2024.02.22
**** feat(Features): 🚩 Begin development of Hidden Dragon
- Reconfigured logging to allow dynamic level setting
- Setup log to Rotate using logging.handlers.RotateLogging (or something like that.)
- Created HDragon class in preparation for creation of hidden_dragon module.

View file

@ -6,6 +6,6 @@
from ctiger.attack import Attack
from ctiger.mac_purge import Purge
from ctiger.proclog import ProcLog
from ctiger.dataframe import DataFrame
from ctiger.dataframe import CtigerDataFrame
from ctiger.netdev import NetDev
from ctiger.__version__ import version

View file

@ -50,9 +50,8 @@ channel_list = list(default=list(1, 6, 11))
# Hidden Dragon Settings
# -----------------------
[DRAGON]
if_type = option('create', 'switch', default='switch')
ap_iface = string(default='mon0')
ap_db = string(default='ap_database.csv')
netdb_file = string(default='net_database.csv')
dragon_results = string(default='dragon_results.csv')
# -----------------------------------------------------------
"""
@ -97,9 +96,8 @@ class ProcArgs:
log.info('Beginning Hidden Dragon')
log.debug('args: {0}'.format(args))
dragon = Dragon()
dragon.hidden_dragon(mon_type=args.mon_type,
ap_iface=args.ap_iface,
ap_db=args.ap_db,
dragon.hidden_dragon(ap_iface=args.ap_iface,
netdb_file=args.netdb_file,
results=args.results,
log=log)
case _:
@ -142,41 +140,38 @@ class ProcArgs:
if not os.path.isfile(config_file):
if not os.path.exists(os.path.dirname(config_file)):
os.mkdir(os.path.dirname(config_file))
config = ConfigObj(config_file, configspec=spec)
config.filename = config_file
validator = validate.Validator()
config.validate(validator, copy=True)
config.write()
print("configuration file written to ", config_path)
sys.exit()
else:
config = ConfigObj(config_file, configspec=spec)
config.filename = config_file
validator = validate.Validator()
test = config.validate(validator, preserve_errors=True)
if not test:
print("Configuration file is invalid")
sys.exit()
# Versioning
if os.path.exists('VERSION.md'):
with open('VERSION.md', 'r') as f:
raw_vers = f.read()
versionMd = str(raw_vers)
pyver = Version.parse(_version,
optional_minor_and_patch=True)
txtver = Version.parse(versionMd,
optional_minor_and_patch=True)
sem_vers = max(pyver, txtver)
if sem_vers != pyver:
with open('__version__.py', 'w') as wrt:
wrt.write("__version__ = '{}'\n".format(str(sem_vers)))
wrt.close()
f.close()
version = str(sem_vers)
else:
sem_vers = Version.parse(_version,
optional_minor_and_patch=True)
version = str(sem_vers)
print("Crouching Tiger version: ", version)
config.validate(validator, copy=True)
config.write()
print("configuration file written to ", config_path)
sys.exit()
config = ConfigObj(config_file, configspec=spec)
validator = validate.Validator()
test = config.validate(validator, preserve_errors=True)
if not test:
print("Configuration file is invalid")
sys.exit()
# Versioning
global version
if os.path.exists('../VERSION.md'):
with open('../VERSION.md', 'r') as f:
raw_vers = f.read()
versionMd = str(raw_vers)
pyver = Version.parse(_version, optional_minor_and_patch=True)
txtver = Version.parse(versionMd, optional_minor_and_patch=True)
sem_vers = max(pyver, txtver)
if sem_vers != pyver:
with open('__version__.py', 'w') as wrt:
wrt.write("__version__ = '{}'\n".format(str(sem_vers)))
wrt.close()
f.close()
version = str(sem_vers)
else:
sem_vers = Version.parse(_version, optional_minor_and_patch=True)
version = str(sem_vers)
print("Crouching Tiger version: ", version)
##################
# ArgParse Setup #
@ -204,7 +199,7 @@ class ProcArgs:
'\n')
# options parser
ap.add_argument('-v', '--version', action='version',
version=f'%(prog)s {version}')
version=f'Crouching Tiger version: {version}')
ap.add_argument('-i', '--interface', dest='name',
default=config['interface'],
help='Interface(s) to scan on')
@ -254,15 +249,11 @@ class ProcArgs:
# Dragon Subcommands
hd_parse = subparse.add_parser('dragon', help='Perform Dragon')
hd_parse.add_argument('-t', '--type', dest='mon_type',
choices=['create', 'switch'],
default=config['DRAGON']['if_type'],
help='Create new monitor inf or switch mode.')
hd_parse.add_argument('-a', '--ap_iface', dest='ap_iface',
default=config['DRAGON']['ap_iface'],
help='Interface to use for AP')
hd_parse.add_argument('-d', '--ap_db', dest='ap_db',
default=config['DRAGON']['ap_db'],
hd_parse.add_argument('-d', '--netdb_file', dest='netdb_file',
default=config['DRAGON']['netdb_file'],
help='Database file of APs')
hd_parse.add_argument('-r', '--results', dest='results',
default=config['DRAGON']['dragon_results'],

View file

@ -1 +1 @@
version = "0.4.2"
version = "0.4.3"

View file

@ -11,7 +11,7 @@ from scapy.layers.eap import EAPOL
from scapy.utils import PcapWriter
from random import choice
import pandas as pd
from .dataframe import DataFrame
from .dataframe import CtigerDataFrame
from time import sleep
import os
import threading

View file

@ -5,9 +5,38 @@
import os
import pandas as pd
import csv
from warnings import warn
class DataFrame:
class CtigerDataFrame:
def load_apnetworks(self, netdb_file, log) -> pd.DataFrame:
self.netdb_file = netdb_file
self.log = log
log.debug('netdb_file type: {0}'.format(type(netdb_file)))
if os.path.isfile(netdb_file):
log.info('Loading networks from: {}'.format(netdb_file))
network_df = pd.DataFrame(columns=['SSID', 'Mac', 'Crypto',
'Channel', 'Last Update',
'Latitude', 'Longitude'])
network_df.set_index("SSID", inplace=True)
netdict = csv.DictReader(open(netdb_file), delimiter=',')
# SSID,NetID,Encryption,Channel,Last Update,Latitude,Longitude
for entry in netdict:
if entry.get('SSID') == '':
BSSID = entry.get('NetID')
entry['SSID'] = BSSID
network_df.loc[entry['SSID']] = [entry['NetID'], entry['Encryption'], entry['Channel'], entry['Last Update'], entry['Latitude'], entry['Longitude']]
return network_df
else:
warn(message='Could not load file', category=None, stacklevel=1)
exit(1)
def gen_resdf(self, log):
resdf = pd.DataFrame(columns=['BSSID', 'SSID', 'dBm_Signal', 'Channel', 'Crypto'])
resdf.set_index("BSSID", inplace=True)
return resdf
def load_df(self, valid_file, log):
self.valid_file = valid_file

View file

@ -2,7 +2,9 @@
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# from .hidden_dragon import __main__
from .hidden_dragon.__main__ import HiddenDragon
from ctiger.dataframe import CtigerDataFrame
import os
class Dragon:
@ -20,7 +22,20 @@ class Dragon:
\/_/\ \/ \ \ __ \ \ \ __\
\ \_\ \ \_\ \_\ \ \_____\
\/_/ \/_/\/_/ \/_____/
______________
,===:'., `-._
`:.`---.__ `-._
`:. `--. `.
\. `. `.
(,,(, \. `. ____,-`.,
(,' `/ \. ,--.___`.'
, ,' ,--. `, \.;' `
`{D, { \ : \;
V,,' / / //
j;; / ,' ,-//. ,---. ,
\;' / ,' / _ \ / _ \ ,'/
\ `' / \ `' / \ `.' /
`.___,' `.__,' `.__,'
) (
( /( ( ( )\ )
)\()) ( )\ ) )\ ) ( (()/( ( ) ( (
@ -32,13 +47,19 @@ class Dragon:
|___/
""")
def hidden_dragon(self, mon_type, ap_iface, ap_db, results, log):
def hidden_dragon(self, ap_iface, netdb_file, results, log):
log.info('Starting Hidden Dragon')
netdb_file = os.path.abspath(netdb_file)
print("""
You have configured Hidden Dragon to run with these options:
mon_type: {0}
ap_iface: {1}
ap_db: {2}
results: {3}
ap_iface: {0}
ap_db: {1}
results: {2}
Have a good day, and thanks for all the fish!
""".format(mon_type, ap_iface, ap_db, results))
""".format(ap_iface, netdb_file, results))
dataframe = CtigerDataFrame()
apnetwork_df = dataframe.load_apnetworks(netdb_file, log)
results_df = dataframe.gen_resdf(log)
HD = HiddenDragon()
HD.start(ap_iface=ap_iface, net_db=apnetwork_df,
results=results_df, log=log)

View file

@ -2,14 +2,18 @@
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
from threading import Thread
from .data import apData
from .mk_inf import TunIf
from ctiger.dataframe import CtigerDataFrame
def main(ap, log):
iface = TunIf(ap=ap, apData=apData, log=log)
pass
class HiddenDragon(Thread):
def __init__(self):
Thread.__init__(self)
if __name__ == '__main__':
main(ap, log)
def start(self, ap_iface, net_db, log):
DF = CtigerDataFrame()
resdf = DF.gen_resdf(log)
iface = TunIf(ap=ap_iface, apData=apData, log=log)
pass

View file

@ -10,3 +10,7 @@ from scapy.layers.dot11 import RadioTap, conf as scapyconf
from scapy.layers.inet import TCP
class wifiAP:
def pass_proxy(self, ip, port):
pass

View file

@ -0,0 +1,60 @@
# Copyright (c) 2024 Anoduck
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
import threading
from scapy.layers.inet import ARP
from scapy.sendrecv import AsyncSniffer
from scapy.sendrecv import sendp
from scapy.utils import PcapWriter
from ctiger.dataframe import CtigerDataFrame
from ctiger.netdev import NetDev
from ctiger.proclog import ProcLog
class Arp(NetDev):
def __init__(self, args):
super().__init__(args)
self.arp = ARP()
self.arp.op = 2
self.arp.hwdst = "ff:ff:ff:ff:ff:ff"
def send(self, pkt):
sendp(pkt, iface=self.interface, verbose=False)
def arp_handler(self, pkt):
self.arp_handler.handle_arp(pkt)
def sniff(self, stop_filter, iface):
AsyncSniffer(
stop_filter=stop_filter,
filter="arp",
iface=iface,
prn=self.arp_handler,
store=0,
timeout=0.01)
class ARPHandler():
def __init__(self):
self.mutex = threading.Lock()
self.arp_table = {}
def add_entry(self, client_ip, client_mac):
self.mutex.acquire()
if client_ip not in self.arp_table:
self.arp_table[client_ip] = client_mac
self.mutex.release()
def get_entry(self, client_ip):
self.mutex.acquire()
try:
temp = self.arp_table[client_ip]
except KeyError:
temp = None
printd("Could not find IP %s in ARP table." %
client_ip, Level.WARNING)
self.mutex.release()
return temp

View file

@ -3,16 +3,18 @@
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
from dataclasses import dataclass
from random import choice
from dataclasses import dataclass, field
from typing import List
DNS_SERVERS = ["8.8.8.8", "9.9.9.9", "1.1.1.1",
"208.67.222.222", "208.67.220.220",
"8.26.56.26", "8.20.247.20",
"89.0.142.86"]
@dataclass
class apData:
dns_servers: list = ["8.8.8.8", "9.9.9.9", "1.1.1.1",
"208.67.222.222", "208.67.220.220",
"8.26.56.26", "8.20.247.20", "89.0.142.86"]
DEFAULT_DNS_SERVER: str = choice(dns_servers)
DNS_SERVERS: List[str] = field(default_factory=lambda: DNS_SERVERS)
RSN: str = "\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x01\x28\x00"
AP_WLAN_TYPE_OPEN: int = 0
@ -41,4 +43,41 @@ class apData:
IFF_TAP: int = 0x0002 # Should we want to tunnel layer 2...
IFF_NO_PI: int = 0x1000
TUNSETIFF: int = 0x400454ca
IP_ADDRESS: str = "10.0.0.2"
IP_ADDRESS: str = "10.0.2.1"
NETMASK: str = "255.255.255.192"
IP_NETWORK: str = "10.0.2"
NET_BROADCAST: str = "10.0.2.63"
DHCP_MIN: str = "10.0.2.2"
DHCP_MAX: str = "10.0.2.62"
DHCP_EXPIRY: int = 28800
@dataclass
class EAPCode:
REQUEST: int = 1
RESPONSE: int = 2
SUCCESS: int = 3
FAILURE: int = 4
@dataclass
class EAPType:
IDENTITY: int = 1
NOTIFICATION: int = 2
NAK: int = 3
MD5_CHALLENGE: int = 4
OTP: int = 5
GENERIC_TOKEN_CARD: int = 6
EAP_TLS: int = 13
EAP_LEAP: int = 17
EAP_SIM: int = 18
TTLS: int = 21
PEAP: int = 25
MSCHAP_V2: int = 29
EAP_CISCO_FAST: int = 43
EAP_MSCHAPV2: int = 44
EAP_TLV: int = 45
@classmethod
def convert_type(cls, type_value):
for key, value in vars(cls).iteritems():
if value == type_value:
return str(key)

View file

@ -0,0 +1,89 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2024 Anoduck
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
"""# DHCP Server specifically for wifi
1. Craft DHCP Packets: Use Scapy to craft DHCP packets for the various stages of the DHCP process,
including Discover, Offer, Request, Acknowledgement, and more as needed. Scapy provides a
flexible way to build and manipulate network packets, including DHCP packets.
2. Bind a Socket: Create a raw socket to send and receive UDP packets using Python's socket module.
This allows you to send and receive DHCP messages on the network.
server_mac
3. Listen for DHCP Requests: Listen for DHCP client requests (DHCP Discover) on the network using
the raw socket. When a DHCP Discover packet is received, parse the packet using Scapy to extract
relevant information such as the client's MAC address and requested parameters.
4. Craft DHCP Offer: Upon receiving a DHCP Discover, craft a DHCP Offer packet using Scapy to
allocate an available IP address and other configuration parameters to the client. Send the DHCP
Offer packet using the raw socket to the client's broadcast address.
5. Handle DHCP Request: If the client sends a DHCP Request for the offered parameters, process the
request and send a DHCP Acknowledgement (ACK) packet to finalize the configuration.
6. Error Handling and Lease Management: Implement error handling for invalid requests and manage IP
address lease allocation to ensure that IP addresses are properly assigned and reclaimed.
"""
# from scapy.all import *
from scapy.layers.dhcp import DHCP
from scapy.layers.inet import IP, UDP
from scapy.layers.dot11 import Dot11
from scapy.layers.dhcp import BOOTP
from scapy.sendrecv import sniff, sendp
import subprocess
from random import choice
import time
import socket
import fcntl
import struct
from ctiger.hidden_dragon import ap
from data import apData
# Define the DHCP server IP and the network ifname to listen on
server_ip = apData.IP_ADDRESS # "10.0.2.1"
ifname = "wlan0"
class apDHCP:
def __init__(self) -> None:
self.server_ip = apData.IP_ADDRESS
self.netmask = apData.NETMASK
self.broadcast = apData.NET_BROADCAST
self.host_min = apData.DHCP_MIN
self.host_max = apData.DHCP_MAX
self.ip_net = apData.IP_NETWORK
def get_if_hwaddr(self, ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
return ''.join(['%02x' % ord(char) for char in info[18:24]])
# Create a DHCP packet handler
def handle_dhcp_packet(self, packet):
if DHCP in packet:
# Check if the packet is a DHCP Discover
if packet[DHCP].options[0][1] == 1:
# Craft DHCP Offer
min_host = self.host_min.split('.')[3]
max_host = self.host_max.split('.')[3]
cli_int = choice(range(int(min_host), int(max_host)))
client_ip = self.ip_net + '.' + str(cli_int)
dhcp_offer = Dot11(src=self.server_mac, dst="ff:ff:ff:ff:ff:ff") / IP(src=server_ip, dst="self.broadcast") / UDP(sport=67, dport=68) / BOOTP(op=2, yiaddr=client_ip, siaddr=server_ip, chaddr=packet[Dot11].src) / DHCP(options=[("message-type", "offer"), ("subnet_mask", self.netmask), "end"])
sendp(dhcp_offer, iface=ifname, verbose=0)
print("Sent DHCP Offer to", packet[Dot11].src)
# Wait for DHCP Request
dhcp_request = sniff(iface=ifname, filter="udp and (port 67 or 68)", count=1)
if DHCP in dhcp_request[0]:
# Craft DHCP Acknowledgement
dhcp_ack = Dot11(src=self.server_mac, dst=dhcp_request[0][Dot11].src) / IP(src=server_ip, dst="self.broadcast") / UDP(sport=67, dport=68) / BOOTP(op=2, yiaddr=client_ip, siaddr=server_ip, chaddr=dhcp_request[0][Dot11].src) / DHCP(options=[("message-type", "ack"), ("subnet_mask", self.netmask), "end"])
sendp(dhcp_ack, iface=ifname, verbose=0)
print("Sent DHCP Acknowledgement to", dhcp_request[0][Dot11].src)
def start_dhcp(self):
self.server_mac = self.get_if_hwaddr(ifname)
# Start sniffing DHCP traffic
sniff(iface=ifname, filter="udp and (port 67 or 68)", prn=self.handle_dhcp_packet)

View file

@ -0,0 +1,24 @@
# Copyright (c) 2024 Anoduck
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
import threading
class EAPHandler():
def __init__(self):
self.id = 0
self.mutex = threading.Lock()
def next_id(self):
self.mutex.acquire()
self.id = (self.id + 1)
temp = self.id
self.mutex.release()
return temp
def reset_id(self):
self.mutex.acquire()
self.id = 0
self.mutex.release()

View file

@ -7,21 +7,24 @@ import struct
import os
import threading
import subprocess
from scapy.arch import str2mac, get_if_raw_hwaddr
from scapy.layers.inet import IP
from .data import apData
from ctiger import NetDev
from warnings import warn
class TunIf(threading.Thread):
def __init__(self, ap, apData, name="fakeap", log):
def __init__(self, ap, apData, log, name="fakeap"):
threading.Thread.__init__(self)
self.apData = apData
self.log = log
self.dev = apData.dev
if len(name) > apData.IFNAMSIZ:
raise Exception(
"Tun interface name cannot be larger than " + str(apData.IFNAMSIZ))
"Tun interface name cannot be larger than " + str(
apData.IFNAMSIZ))
self.name = name
self.setDaemon(True)
@ -36,13 +39,13 @@ class TunIf(threading.Thread):
# Assign IP and bring interface up
# set_ip_address(name, self.ap.ip)
# def set_ip_address(dev, ip):
if subprocess.call(['ip', 'addr', 'add', apData.ip, 'dev', apData.dev]):
print("Failed to assign IP address {} to {}.".format(apData.ip, apData.dev))
if subprocess.call(['ip', 'link', 'set', 'dev', apData.dev, 'up']):
print("Failed to bring device %s up." % dev, Level.CRITICAL)
if subprocess.call(['ip', 'addr', 'add', apData.ip, 'dev', self.dev]):
warn("Failed to assign IP address {} to {}.".format(apData.ip,
self.dev))
if subprocess.call(['ip', 'link', 'set', 'dev', self.dev, 'up']):
warn("Failed to bring device {} up.".format(self.dev))
print("Created TUN interface %s at %s. Bind it to your services as needed." % (
name, self.ap.ip))
log.info("Created TUN interface {} at {}".format(self.name, self.ap.ip))
def write(self, pkt):
os.write(self.fd.fileno(), str(pkt[IP])) # Strip layer 2
@ -58,3 +61,88 @@ class TunIf(threading.Thread):
while True:
raw_packet = self.read()
self.ap.callbacks.cb_tint_read(raw_packet)
class RouteTraffic(threading.Thread):
def __init__(self, apIface, apData, log) -> None:
if subprocess.call(['iptables', '--table', 'nat', '--append',
'POSTROUTING', '--out-interface', apIface, '-j',
'MASQUERADE']):
warn("Failed to setup postrouting for {}.".format(apIface))
if subprocess.call(['iptables', '--append', 'FORWARD',
'--in-interface', apData.dev, '-j', 'ACCEPT']):
warn("Failed to setup forwarding for {}.".format(apData.dev))
if subprocess.call(['sysctl', '-w', 'net.ipv4.ip_forward=1']):
warn("Failed to enable IP forwarding.")
log.info("Created route traffic for {}".format(apIface))
pass
def set_monitor_mode(wlan_dev, enable=True):
monitor_dev = None
if enable:
result = subprocess.check_output(['airmon-ng', 'start', wlan_dev])
if not "monitor mode enabled on" in result:
printd(clr(Color.RED, "ERROR: Airmon could not enable monitor mode on device %s. Make sure you are root, and that"
"your wlan card supports monitor mode." % wlan_dev), Level.CRITICAL)
exit(1)
monitor_dev = re.search(
r"monitor mode enabled on (\w+)", result).group(1)
printd("Airmon set %s to monitor mode on %s" %
(wlan_dev, monitor_dev), Level.INFO)
else:
subprocess.check_output(['airmon-ng', 'stop', wlan_dev])
return monitor_dev
def set_ip_address(dev, ip):
if subprocess.call(['ip', 'addr', 'add', ip, 'dev', dev]):
printd("Failed to assign IP address %s to %s." %
(ip, dev), Level.CRITICAL)
if subprocess.call(['ip', 'link', 'set', 'dev', dev, 'up']):
printd("Failed to bring device %s up." % dev, Level.CRITICAL)
def clear_ip_tables():
if subprocess.call(['iptables', '--flush']):
printd("Failed to flush iptables.", Level.CRITICAL)
if subprocess.call(['iptables', '--table', 'nat', '--flush']):
printd("Failed to flush iptables NAT.", Level.CRITICAL)
if subprocess.call(['iptables', '--delete-chain']):
printd("Failed to delete iptables chain.", Level.CRITICAL)
if subprocess.call(['iptables', '--table', 'nat', '--delete-chain']):
printd("Failed to delete iptables NAT chain.", Level.CRITICAL)
def hex_offset_to_string(byte_array):
temp = byte_array.replace("\n", "")
temp = temp.replace(" ", "")
return temp.decode("hex")
def get_frequency(channel):
if channel == 14:
freq = 2484
else:
freq = 2407 + (channel * 5)
freq_string = struct.pack("<h", freq)
return freq_string
def mac_to_bytes(mac):
return ''.join(chr(int(x, 16)) for x in mac.split(':'))
def bytes_to_mac(byte_array):
return ':'.join("{:02x}".format(ord(byte)) for byte in byte_array)
# Scapy sees mon0 interface as invalid address family, so we write our own
def if_hwaddr(iff):
return str2mac(get_if_raw_hwaddr(iff)[1])

View file

@ -11,7 +11,7 @@ import threading
from random import choice
from time import sleep
import os
from .dataframe import DataFrame
from .dataframe import CtigerDataFrame
from .netdev import NetDev
@ -113,7 +113,7 @@ class Purge(object):
self.valid_file = valid_file
self.channels = channels
self.log = log
df = DataFrame()
df = CtigerDataFrame()
log.info('mac revealer started')
log.info('setting up class attributes')
self.scan_df = df.get_df()

View file

@ -13,17 +13,17 @@ class ProcLog:
def get_log(self, log_file, lev):
self.log_file = log_file
self.lev = 'debug'
self.lev = lev
if not os.path.exists(log_file):
open(log_file, 'a').close()
log = logging.getLogger(__name__)
if log.hasHandlers():
log.handlers.clear()
log_levels = {'info': logging.INFO,
'debug': logging.DEBUG,
'error': logging.ERROR}
if lev in log_levels.keys():
set_level = log_levels[lev]
log_levels = {'INFO': logging.INFO,
'DEBUG': logging.DEBUG,
'ERROR': logging.ERROR}
if self.lev in log_levels.keys():
set_level = log_levels[self.lev]
log.setLevel(set_level)
else:
warn('Invalid level. Defaulting to debug')