fix: on_internet_available plugins callback is now called for both MANU and AUTO mode (fixes #210)
This commit is contained in:
parent
1c526b0bf1
commit
55d99836e7
@ -9,7 +9,6 @@ if __name__ == '__main__':
|
|||||||
import pwnagotchi.utils as utils
|
import pwnagotchi.utils as utils
|
||||||
import pwnagotchi.plugins as plugins
|
import pwnagotchi.plugins as plugins
|
||||||
|
|
||||||
from pwnagotchi.log import SessionParser
|
|
||||||
from pwnagotchi.identity import KeyPair
|
from pwnagotchi.identity import KeyPair
|
||||||
from pwnagotchi.agent import Agent
|
from pwnagotchi.agent import Agent
|
||||||
from pwnagotchi.ui.display import Display
|
from pwnagotchi.ui.display import Display
|
||||||
@ -51,22 +50,23 @@ if __name__ == '__main__':
|
|||||||
elif args.do_manual:
|
elif args.do_manual:
|
||||||
logging.info("entering manual mode ...")
|
logging.info("entering manual mode ...")
|
||||||
|
|
||||||
log = SessionParser(config)
|
agent.last_session.parse()
|
||||||
|
|
||||||
logging.info(
|
logging.info(
|
||||||
"the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)" % (
|
"the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)" % (
|
||||||
log.duration_human,
|
agent.last_session.duration_human,
|
||||||
log.epochs,
|
agent.last_session.epochs,
|
||||||
log.train_epochs,
|
agent.last_session.train_epochs,
|
||||||
log.avg_reward,
|
agent.last_session.avg_reward,
|
||||||
log.min_reward,
|
agent.last_session.min_reward,
|
||||||
log.max_reward))
|
agent.last_session.max_reward))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
display.on_manual_mode(log)
|
display.on_manual_mode(agent.last_session)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
if Agent.is_connected():
|
if Agent.is_connected():
|
||||||
plugins.on('internet_available', display, keypair, config, log)
|
plugins.on('internet_available', agent)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.info("entering auto mode ...")
|
logging.info("entering auto mode ...")
|
||||||
@ -104,5 +104,9 @@ if __name__ == '__main__':
|
|||||||
# WiFi electromagnetic fields affect time like gravitational fields
|
# WiFi electromagnetic fields affect time like gravitational fields
|
||||||
# affect ours ... neat ^_^
|
# affect ours ... neat ^_^
|
||||||
agent.next_epoch()
|
agent.next_epoch()
|
||||||
|
|
||||||
|
if Agent.is_connected():
|
||||||
|
plugins.on('internet_available', agent)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception("main loop exception")
|
logging.exception("main loop exception")
|
||||||
|
@ -9,6 +9,7 @@ import _thread
|
|||||||
|
|
||||||
import pwnagotchi.utils as utils
|
import pwnagotchi.utils as utils
|
||||||
import pwnagotchi.plugins as plugins
|
import pwnagotchi.plugins as plugins
|
||||||
|
from pwnagotchi.log import LastSession
|
||||||
from pwnagotchi.bettercap import Client
|
from pwnagotchi.bettercap import Client
|
||||||
from pwnagotchi.mesh.utils import AsyncAdvertiser
|
from pwnagotchi.mesh.utils import AsyncAdvertiser
|
||||||
from pwnagotchi.ai.train import AsyncTrainer
|
from pwnagotchi.ai.train import AsyncTrainer
|
||||||
@ -35,6 +36,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer):
|
|||||||
self._last_pwnd = None
|
self._last_pwnd = None
|
||||||
self._history = {}
|
self._history = {}
|
||||||
self._handshakes = {}
|
self._handshakes = {}
|
||||||
|
self.last_session = LastSession(self._config)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_connected():
|
def is_connected():
|
||||||
@ -48,6 +50,9 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer):
|
|||||||
def config(self):
|
def config(self):
|
||||||
return self._config
|
return self._config
|
||||||
|
|
||||||
|
def view(self):
|
||||||
|
return self._view
|
||||||
|
|
||||||
def supported_channels(self):
|
def supported_channels(self):
|
||||||
return self._supported_channels
|
return self._supported_channels
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ from file_read_backwards import FileReadBackwards
|
|||||||
LAST_SESSION_FILE = '/root/.pwnagotchi-last-session'
|
LAST_SESSION_FILE = '/root/.pwnagotchi-last-session'
|
||||||
|
|
||||||
|
|
||||||
class SessionParser(object):
|
class LastSession(object):
|
||||||
EPOCH_TOKEN = '[epoch '
|
EPOCH_TOKEN = '[epoch '
|
||||||
EPOCH_PARSER = re.compile(r'^.+\[epoch (\d+)\] (.+)')
|
EPOCH_PARSER = re.compile(r'^.+\[epoch (\d+)\] (.+)')
|
||||||
EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=([^\s]+)')
|
EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=([^\s]+)')
|
||||||
@ -70,27 +70,27 @@ class SessionParser(object):
|
|||||||
if started_at is None:
|
if started_at is None:
|
||||||
started_at = stopped_at
|
started_at = stopped_at
|
||||||
|
|
||||||
if SessionParser.DEAUTH_TOKEN in line and line not in cache:
|
if LastSession.DEAUTH_TOKEN in line and line not in cache:
|
||||||
self.deauthed += 1
|
self.deauthed += 1
|
||||||
cache[line] = 1
|
cache[line] = 1
|
||||||
|
|
||||||
elif SessionParser.ASSOC_TOKEN in line and line not in cache:
|
elif LastSession.ASSOC_TOKEN in line and line not in cache:
|
||||||
self.associated += 1
|
self.associated += 1
|
||||||
cache[line] = 1
|
cache[line] = 1
|
||||||
|
|
||||||
elif SessionParser.HANDSHAKE_TOKEN in line and line not in cache:
|
elif LastSession.HANDSHAKE_TOKEN in line and line not in cache:
|
||||||
self.handshakes += 1
|
self.handshakes += 1
|
||||||
cache[line] = 1
|
cache[line] = 1
|
||||||
|
|
||||||
elif SessionParser.TRAINING_TOKEN in line:
|
elif LastSession.TRAINING_TOKEN in line:
|
||||||
self.train_epochs += 1
|
self.train_epochs += 1
|
||||||
|
|
||||||
elif SessionParser.EPOCH_TOKEN in line:
|
elif LastSession.EPOCH_TOKEN in line:
|
||||||
self.epochs += 1
|
self.epochs += 1
|
||||||
m = SessionParser.EPOCH_PARSER.findall(line)
|
m = LastSession.EPOCH_PARSER.findall(line)
|
||||||
if m:
|
if m:
|
||||||
epoch_num, epoch_data = m[0]
|
epoch_num, epoch_data = m[0]
|
||||||
m = SessionParser.EPOCH_DATA_PARSER.findall(epoch_data)
|
m = LastSession.EPOCH_DATA_PARSER.findall(epoch_data)
|
||||||
for key, value in m:
|
for key, value in m:
|
||||||
if key == 'reward':
|
if key == 'reward':
|
||||||
reward = float(value)
|
reward = float(value)
|
||||||
@ -101,7 +101,7 @@ class SessionParser(object):
|
|||||||
elif reward > self.max_reward:
|
elif reward > self.max_reward:
|
||||||
self.max_reward = reward
|
self.max_reward = reward
|
||||||
|
|
||||||
elif SessionParser.PEER_TOKEN in line:
|
elif LastSession.PEER_TOKEN in line:
|
||||||
m = self._peer_parser.findall(line)
|
m = self._peer_parser.findall(line)
|
||||||
if m:
|
if m:
|
||||||
name, pubkey, rssi, sid, pwnd_tot, uptime = m[0]
|
name, pubkey, rssi, sid, pwnd_tot, uptime = m[0]
|
||||||
@ -134,6 +134,30 @@ class SessionParser(object):
|
|||||||
self.duration_human = ', '.join(self.duration_human)
|
self.duration_human = ', '.join(self.duration_human)
|
||||||
self.avg_reward /= (self.epochs if self.epochs else 1)
|
self.avg_reward /= (self.epochs if self.epochs else 1)
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
if os.path.exists(self.path):
|
||||||
|
with FileReadBackwards(self.path, encoding="utf-8") as fp:
|
||||||
|
for line in fp:
|
||||||
|
line = line.strip()
|
||||||
|
if line != "" and line[0] != '[':
|
||||||
|
continue
|
||||||
|
lines.append(line)
|
||||||
|
if LastSession.START_TOKEN in line:
|
||||||
|
break
|
||||||
|
lines.reverse()
|
||||||
|
|
||||||
|
if len(lines) == 0:
|
||||||
|
lines.append("Initial Session");
|
||||||
|
|
||||||
|
self.last_session = lines
|
||||||
|
self.last_session_id = hashlib.md5(lines[0].encode()).hexdigest()
|
||||||
|
self.last_saved_session_id = self._get_last_saved_session_id()
|
||||||
|
|
||||||
|
self._parse_stats()
|
||||||
|
self.parsed = True
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.voice = Voice(lang=config['main']['lang'])
|
self.voice = Voice(lang=config['main']['lang'])
|
||||||
@ -150,28 +174,10 @@ class SessionParser(object):
|
|||||||
self.last_peer = None
|
self.last_peer = None
|
||||||
self._peer_parser = re.compile(
|
self._peer_parser = re.compile(
|
||||||
'detected unit (.+)@(.+) \(v.+\) on channel \d+ \(([\d\-]+) dBm\) \[sid:(.+) pwnd_tot:(\d+) uptime:(\d+)\]')
|
'detected unit (.+)@(.+) \(v.+\) on channel \d+ \(([\d\-]+) dBm\) \[sid:(.+) pwnd_tot:(\d+) uptime:(\d+)\]')
|
||||||
|
self.last_session = []
|
||||||
lines = []
|
self.last_session_id = None
|
||||||
|
self.last_saved_session_id = None
|
||||||
if os.path.exists(self.path):
|
self.parsed = False
|
||||||
with FileReadBackwards(self.path, encoding="utf-8") as fp:
|
|
||||||
for line in fp:
|
|
||||||
line = line.strip()
|
|
||||||
if line != "" and line[0] != '[':
|
|
||||||
continue
|
|
||||||
lines.append(line)
|
|
||||||
if SessionParser.START_TOKEN in line:
|
|
||||||
break
|
|
||||||
lines.reverse()
|
|
||||||
|
|
||||||
if len(lines) == 0:
|
|
||||||
lines.append("Initial Session");
|
|
||||||
|
|
||||||
self.last_session = lines
|
|
||||||
self.last_session_id = hashlib.md5(lines[0].encode()).hexdigest()
|
|
||||||
self.last_saved_session_id = self._get_last_saved_session_id()
|
|
||||||
|
|
||||||
self._parse_stats()
|
|
||||||
|
|
||||||
def is_new(self):
|
def is_new(self):
|
||||||
return self.last_session_id != self.last_saved_session_id
|
return self.last_session_id != self.last_saved_session_id
|
||||||
|
@ -12,6 +12,9 @@ class AsyncAdvertiser(object):
|
|||||||
self._keypair = keypair
|
self._keypair = keypair
|
||||||
self._advertiser = None
|
self._advertiser = None
|
||||||
|
|
||||||
|
def keypair(self):
|
||||||
|
return self._keypair
|
||||||
|
|
||||||
def start_advertising(self):
|
def start_advertising(self):
|
||||||
_thread.start_new_thread(self._adv_worker, ())
|
_thread.start_new_thread(self._adv_worker, ())
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ def on_loaded():
|
|||||||
logging.info("AUTO-BACKUP: Successfuly loaded.")
|
logging.info("AUTO-BACKUP: Successfuly loaded.")
|
||||||
|
|
||||||
|
|
||||||
def on_internet_available(display, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
global STATUS
|
global STATUS
|
||||||
|
|
||||||
if READY:
|
if READY:
|
||||||
@ -42,6 +42,8 @@ def on_internet_available(display, keypair, config, log):
|
|||||||
|
|
||||||
files_to_backup = " ".join(OPTIONS['files'])
|
files_to_backup = " ".join(OPTIONS['files'])
|
||||||
try:
|
try:
|
||||||
|
display = agent.view()
|
||||||
|
|
||||||
logging.info("AUTO-BACKUP: Backing up ...")
|
logging.info("AUTO-BACKUP: Backing up ...")
|
||||||
display.set('status', 'Backing up ...')
|
display.set('status', 'Backing up ...')
|
||||||
display.update()
|
display.update()
|
||||||
|
@ -23,13 +23,15 @@ def on_loaded():
|
|||||||
READY = True
|
READY = True
|
||||||
|
|
||||||
|
|
||||||
def on_internet_available(display, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
global STATUS
|
global STATUS
|
||||||
|
|
||||||
if READY:
|
if READY:
|
||||||
if STATUS.newer_then_days(OPTIONS['interval']):
|
if STATUS.newer_then_days(OPTIONS['interval']):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
display = agent.view()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
display.set('status', 'Updating ...')
|
display.set('status', 'Updating ...')
|
||||||
display.update()
|
display.update()
|
||||||
|
@ -20,7 +20,7 @@ def on_loaded():
|
|||||||
|
|
||||||
|
|
||||||
# called in manual mode when there's internet connectivity
|
# called in manual mode when there's internet connectivity
|
||||||
def on_internet_available(ui, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,16 +22,16 @@ def on_loaded():
|
|||||||
logging.info("api plugin loaded.")
|
logging.info("api plugin loaded.")
|
||||||
|
|
||||||
|
|
||||||
def get_api_token(log, keys):
|
def get_api_token(last_session, keys):
|
||||||
global AUTH
|
global AUTH
|
||||||
|
|
||||||
if AUTH.newer_then_minutes(25) and AUTH.data is not None and 'token' in AUTH.data:
|
if AUTH.newer_then_minutes(25) and AUTH.data is not None and 'token' in AUTH.data:
|
||||||
return AUTH.data['token']
|
return AUTH.data['token']
|
||||||
|
|
||||||
if AUTH.data is None:
|
if AUTH.data is None:
|
||||||
logging.info("api: enrolling unit ...")
|
logging.info("grid: enrolling unit ...")
|
||||||
else:
|
else:
|
||||||
logging.info("api: refreshing token ...")
|
logging.info("grid: refreshing token ...")
|
||||||
|
|
||||||
identity = "%s@%s" % (pwnagotchi.name(), keys.fingerprint)
|
identity = "%s@%s" % (pwnagotchi.name(), keys.fingerprint)
|
||||||
# sign the identity string to prove we own both keys
|
# sign the identity string to prove we own both keys
|
||||||
@ -43,16 +43,16 @@ def get_api_token(log, keys):
|
|||||||
'public_key': keys.pub_key_pem_b64,
|
'public_key': keys.pub_key_pem_b64,
|
||||||
'signature': signature_b64,
|
'signature': signature_b64,
|
||||||
'data': {
|
'data': {
|
||||||
'duration': log.duration,
|
'duration': last_session.duration,
|
||||||
'epochs': log.epochs,
|
'epochs': last_session.epochs,
|
||||||
'train_epochs': log.train_epochs,
|
'train_epochs': last_session.train_epochs,
|
||||||
'avg_reward': log.avg_reward,
|
'avg_reward': last_session.avg_reward,
|
||||||
'min_reward': log.min_reward,
|
'min_reward': last_session.min_reward,
|
||||||
'max_reward': log.max_reward,
|
'max_reward': last_session.max_reward,
|
||||||
'deauthed': log.deauthed,
|
'deauthed': last_session.deauthed,
|
||||||
'associated': log.associated,
|
'associated': last_session.associated,
|
||||||
'handshakes': log.handshakes,
|
'handshakes': last_session.handshakes,
|
||||||
'peers': log.peers,
|
'peers': last_session.peers,
|
||||||
'uname': subprocess.getoutput("uname -a")
|
'uname': subprocess.getoutput("uname -a")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,13 +63,13 @@ def get_api_token(log, keys):
|
|||||||
|
|
||||||
AUTH.update(data=r.json())
|
AUTH.update(data=r.json())
|
||||||
|
|
||||||
logging.info("api: done")
|
logging.info("grid: done")
|
||||||
|
|
||||||
return AUTH.data["token"]
|
return AUTH.data["token"]
|
||||||
|
|
||||||
|
|
||||||
def parse_pcap(filename):
|
def parse_pcap(filename):
|
||||||
logging.info("api: parsing %s ..." % filename)
|
logging.info("grid: parsing %s ..." % filename)
|
||||||
|
|
||||||
net_id = os.path.basename(filename).replace('.pcap', '')
|
net_id = os.path.basename(filename).replace('.pcap', '')
|
||||||
|
|
||||||
@ -91,15 +91,15 @@ def parse_pcap(filename):
|
|||||||
try:
|
try:
|
||||||
info = extract_from_pcap(filename, [WifiInfo.BSSID, WifiInfo.ESSID])
|
info = extract_from_pcap(filename, [WifiInfo.BSSID, WifiInfo.ESSID])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("api: %s" % e)
|
logging.error("grid: %s" % e)
|
||||||
|
|
||||||
return info[WifiInfo.ESSID], info[WifiInfo.BSSID]
|
return info[WifiInfo.ESSID], info[WifiInfo.BSSID]
|
||||||
|
|
||||||
|
|
||||||
def api_report_ap(log, keys, token, essid, bssid):
|
def api_report_ap(last_session, keys, token, essid, bssid):
|
||||||
while True:
|
while True:
|
||||||
token = AUTH.data['token']
|
token = AUTH.data['token']
|
||||||
logging.info("api: reporting %s (%s)" % (essid, bssid))
|
logging.info("grid: reporting %s (%s)" % (essid, bssid))
|
||||||
try:
|
try:
|
||||||
api_address = 'https://api.pwnagotchi.ai/api/v1/unit/report/ap'
|
api_address = 'https://api.pwnagotchi.ai/api/v1/unit/report/ap'
|
||||||
headers = {'Authorization': 'access_token %s' % token}
|
headers = {'Authorization': 'access_token %s' % token}
|
||||||
@ -111,21 +111,23 @@ def api_report_ap(log, keys, token, essid, bssid):
|
|||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
if r.status_code == 401:
|
if r.status_code == 401:
|
||||||
logging.warning("token expired")
|
logging.warning("token expired")
|
||||||
token = get_api_token(log, keys)
|
token = get_api_token(last_session, keys)
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise Exception("(status %d) %s" % (r.status_code, r.text))
|
raise Exception("(status %d) %s" % (r.status_code, r.text))
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("api: %s" % e)
|
logging.error("grid: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def on_internet_available(ui, keys, config, log):
|
def on_internet_available(agent):
|
||||||
global REPORT
|
global REPORT
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
config = agent.config()
|
||||||
|
keys = agent.keypair()
|
||||||
|
|
||||||
pcap_files = glob.glob(os.path.join(config['bettercap']['handshakes'], "*.pcap"))
|
pcap_files = glob.glob(os.path.join(config['bettercap']['handshakes'], "*.pcap"))
|
||||||
num_networks = len(pcap_files)
|
num_networks = len(pcap_files)
|
||||||
@ -134,10 +136,10 @@ def on_internet_available(ui, keys, config, log):
|
|||||||
num_new = num_networks - num_reported
|
num_new = num_networks - num_reported
|
||||||
|
|
||||||
if num_new > 0:
|
if num_new > 0:
|
||||||
logging.info("api: %d new networks to report" % num_new)
|
|
||||||
token = get_api_token(log, keys)
|
|
||||||
|
|
||||||
if OPTIONS['report']:
|
if OPTIONS['report']:
|
||||||
|
logging.info("grid: %d new networks to report" % num_new)
|
||||||
|
token = get_api_token(agent.last_session, agent.keypair())
|
||||||
|
|
||||||
for pcap_file in pcap_files:
|
for pcap_file in pcap_files:
|
||||||
net_id = os.path.basename(pcap_file).replace('.pcap', '')
|
net_id = os.path.basename(pcap_file).replace('.pcap', '')
|
||||||
do_skip = False
|
do_skip = False
|
||||||
@ -151,11 +153,11 @@ def on_internet_available(ui, keys, config, log):
|
|||||||
if net_id not in reported and not do_skip:
|
if net_id not in reported and not do_skip:
|
||||||
essid, bssid = parse_pcap(pcap_file)
|
essid, bssid = parse_pcap(pcap_file)
|
||||||
if bssid:
|
if bssid:
|
||||||
if api_report_ap(log, keys, token, essid, bssid):
|
if api_report_ap(agent.last_session, keys, token, essid, bssid):
|
||||||
reported.append(net_id)
|
reported.append(net_id)
|
||||||
REPORT.update(data={'reported': reported})
|
REPORT.update(data={'reported': reported})
|
||||||
else:
|
else:
|
||||||
logging.info("api: reporting disabled")
|
logging.debug("grid: reporting disabled")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception("error while enrolling the unit")
|
logging.exception("error while enrolling the unit")
|
||||||
|
@ -55,11 +55,14 @@ def _upload_to_ohc(path, timeout=30):
|
|||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
||||||
def on_internet_available(display, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
"""
|
"""
|
||||||
Called in manual mode when there's internet connectivity
|
Called in manual mode when there's internet connectivity
|
||||||
"""
|
"""
|
||||||
if READY:
|
if READY:
|
||||||
|
display = agent.view()
|
||||||
|
config = agent.config()
|
||||||
|
|
||||||
handshake_dir = config['bettercap']['handshakes']
|
handshake_dir = config['bettercap']['handshakes']
|
||||||
handshake_filenames = os.listdir(handshake_dir)
|
handshake_filenames = os.listdir(handshake_dir)
|
||||||
handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')]
|
handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')]
|
||||||
|
@ -14,8 +14,12 @@ def on_loaded():
|
|||||||
|
|
||||||
|
|
||||||
# called in manual mode when there's internet connectivity
|
# called in manual mode when there's internet connectivity
|
||||||
def on_internet_available(ui, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
if log.is_new() and log.handshakes > 0:
|
config = agent.config()
|
||||||
|
display = agent.view()
|
||||||
|
last_session = agent.last_session
|
||||||
|
|
||||||
|
if last_session.is_new() and last_session.handshakes > 0:
|
||||||
try:
|
try:
|
||||||
import tweepy
|
import tweepy
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -26,20 +30,20 @@ def on_internet_available(ui, keypair, config, log):
|
|||||||
|
|
||||||
picture = '/dev/shm/pwnagotchi.png'
|
picture = '/dev/shm/pwnagotchi.png'
|
||||||
|
|
||||||
ui.on_manual_mode(log)
|
display.on_manual_mode(last_session)
|
||||||
ui.update(force=True)
|
display.update(force=True)
|
||||||
ui.image().save(picture, 'png')
|
display.image().save(picture, 'png')
|
||||||
ui.set('status', 'Tweeting...')
|
display.set('status', 'Tweeting...')
|
||||||
ui.update(force=True)
|
display.update(force=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
auth = tweepy.OAuthHandler(OPTIONS['consumer_key'], OPTIONS['consumer_secret'])
|
auth = tweepy.OAuthHandler(OPTIONS['consumer_key'], OPTIONS['consumer_secret'])
|
||||||
auth.set_access_token(OPTIONS['access_token_key'], OPTIONS['access_token_secret'])
|
auth.set_access_token(OPTIONS['access_token_key'], OPTIONS['access_token_secret'])
|
||||||
api = tweepy.API(auth)
|
api = tweepy.API(auth)
|
||||||
|
|
||||||
tweet = Voice(lang=config['main']['lang']).on_log_tweet(log)
|
tweet = Voice(lang=config['main']['lang']).on_last_session_tweet(last_session)
|
||||||
api.update_with_media(filename=picture, status=tweet)
|
api.update_with_media(filename=picture, status=tweet)
|
||||||
log.save_session_id()
|
last_session.save_session_id()
|
||||||
|
|
||||||
logging.info("tweeted: %s" % tweet)
|
logging.info("tweeted: %s" % tweet)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -196,7 +196,7 @@ def _send_to_wigle(lines, api_key, timeout=30):
|
|||||||
raise re_e
|
raise re_e
|
||||||
|
|
||||||
|
|
||||||
def on_internet_available(display, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
from scapy.all import RadioTap, Dot11Elt, Dot11Beacon, rdpcap, Scapy_Exception, Dot11, Dot11ProbeResp, Dot11AssoReq, \
|
from scapy.all import RadioTap, Dot11Elt, Dot11Beacon, rdpcap, Scapy_Exception, Dot11, Dot11ProbeResp, Dot11AssoReq, \
|
||||||
Dot11ReassoReq, Dot11EltRSN, Dot11EltVendorSpecific, Dot11EltMicrosoftWPA
|
Dot11ReassoReq, Dot11EltRSN, Dot11EltVendorSpecific, Dot11EltMicrosoftWPA
|
||||||
"""
|
"""
|
||||||
@ -206,6 +206,9 @@ def on_internet_available(display, keypair, config, log):
|
|||||||
global SKIP
|
global SKIP
|
||||||
|
|
||||||
if READY:
|
if READY:
|
||||||
|
config = agent.config()
|
||||||
|
display = agent.view()
|
||||||
|
|
||||||
handshake_dir = config['bettercap']['handshakes']
|
handshake_dir = config['bettercap']['handshakes']
|
||||||
all_files = os.listdir(handshake_dir)
|
all_files = os.listdir(handshake_dir)
|
||||||
all_gps_files = [os.path.join(handshake_dir, filename)
|
all_gps_files = [os.path.join(handshake_dir, filename)
|
||||||
|
@ -54,11 +54,14 @@ def _upload_to_wpasec(path, timeout=30):
|
|||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
||||||
def on_internet_available(display, keypair, config, log):
|
def on_internet_available(agent):
|
||||||
"""
|
"""
|
||||||
Called in manual mode when there's internet connectivity
|
Called in manual mode when there's internet connectivity
|
||||||
"""
|
"""
|
||||||
if READY:
|
if READY:
|
||||||
|
config = agent.config()
|
||||||
|
display = agent.view()
|
||||||
|
|
||||||
handshake_dir = config['bettercap']['handshakes']
|
handshake_dir = config['bettercap']['handshakes']
|
||||||
handshake_filenames = os.listdir(handshake_dir)
|
handshake_filenames = os.listdir(handshake_dir)
|
||||||
handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')]
|
handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')]
|
||||||
|
@ -163,17 +163,17 @@ class View(object):
|
|||||||
self.set('status', self._voice.on_ai_ready())
|
self.set('status', self._voice.on_ai_ready())
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def on_manual_mode(self, log):
|
def on_manual_mode(self, last_session):
|
||||||
self.set('mode', 'MANU')
|
self.set('mode', 'MANU')
|
||||||
self.set('face', faces.SAD if log.handshakes == 0 else faces.HAPPY)
|
self.set('face', faces.SAD if last_session.handshakes == 0 else faces.HAPPY)
|
||||||
self.set('status', self._voice.on_log(log))
|
self.set('status', self._voice.on_last_session_data(last_session))
|
||||||
self.set('epoch', "%04d" % log.epochs)
|
self.set('epoch', "%04d" % last_session.epochs)
|
||||||
self.set('uptime', log.duration)
|
self.set('uptime', last_session.duration)
|
||||||
self.set('channel', '-')
|
self.set('channel', '-')
|
||||||
self.set('aps', "%d" % log.associated)
|
self.set('aps', "%d" % last_session.associated)
|
||||||
self.set('shakes', '%d (%s)' % (log.handshakes, \
|
self.set('shakes', '%d (%s)' % (last_session.handshakes, \
|
||||||
utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
|
utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
|
||||||
self.set_closest_peer(log.last_peer, log.peers)
|
self.set_closest_peer(last_session.last_peer, last_session.peers)
|
||||||
|
|
||||||
def is_normal(self):
|
def is_normal(self):
|
||||||
return self._state.get('face') not in (
|
return self._state.get('face') not in (
|
||||||
|
@ -125,23 +125,23 @@ class Voice:
|
|||||||
def on_rebooting(self):
|
def on_rebooting(self):
|
||||||
return self._("Ops, something went wrong ... Rebooting ...")
|
return self._("Ops, something went wrong ... Rebooting ...")
|
||||||
|
|
||||||
def on_log(self, log):
|
def on_last_session_data(self, last_session):
|
||||||
status = self._('Kicked {num} stations\n').format(num=log.deauthed)
|
status = self._('Kicked {num} stations\n').format(num=last_session.deauthed)
|
||||||
status += self._('Made {num} new friends\n').format(num=log.associated)
|
status += self._('Made {num} new friends\n').format(num=last_session.associated)
|
||||||
status += self._('Got {num} handshakes\n').format(num=log.handshakes)
|
status += self._('Got {num} handshakes\n').format(num=last_session.handshakes)
|
||||||
if log.peers == 1:
|
if last_session.peers == 1:
|
||||||
status += self._('Met 1 peer')
|
status += self._('Met 1 peer')
|
||||||
elif log.peers > 0:
|
elif last_session.peers > 0:
|
||||||
status += self._('Met {num} peers').format(num=log.peers)
|
status += self._('Met {num} peers').format(num=last_session.peers)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def on_log_tweet(self, log):
|
def on_last_session_tweet(self, last_session):
|
||||||
return self._(
|
return self._(
|
||||||
'I\'ve been pwning for {duration} and kicked {deauthed} clients! I\'ve also met {associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet').format(
|
'I\'ve been pwning for {duration} and kicked {deauthed} clients! I\'ve also met {associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet').format(
|
||||||
duration=log.duration_human,
|
duration=last_session.duration_human,
|
||||||
deauthed=log.deauthed,
|
deauthed=last_session.deauthed,
|
||||||
associated=log.associated,
|
associated=last_session.associated,
|
||||||
handshakes=log.handshakes)
|
handshakes=last_session.handshakes)
|
||||||
|
|
||||||
def hhmmss(self, count, fmt):
|
def hhmmss(self, count, fmt):
|
||||||
if count > 1:
|
if count > 1:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user