aboutsummaryrefslogtreecommitdiffstats
path: root/autoscan/autoscan.py
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2013-07-23 05:57:00 +0200
committerLaurent Ghigonis <laurent@p1sec.com>2013-07-23 05:57:00 +0200
commitc04de5a558d6ce26d229bee44445c67e9b9d49ae (patch)
treeca9e8850343223e72858e9befc5c6c9265bbd4bf /autoscan/autoscan.py
parentautoscan: works :) (diff)
downloadlaurent-tools-c04de5a558d6ce26d229bee44445c67e9b9d49ae.tar.xz
laurent-tools-c04de5a558d6ce26d229bee44445c67e9b9d49ae.zip
autoscan: improve monitor mode
Diffstat (limited to 'autoscan/autoscan.py')
-rwxr-xr-xautoscan/autoscan.py125
1 files changed, 76 insertions, 49 deletions
diff --git a/autoscan/autoscan.py b/autoscan/autoscan.py
index 182b8ba..4736869 100755
--- a/autoscan/autoscan.py
+++ b/autoscan/autoscan.py
@@ -3,23 +3,6 @@
# autoscan - automatic fingerprint of visited networks
# 2013, Laurent Ghigonis <laurent@gouloum.fr>
-# Usage: autoscan.py [-d] [interfaces]
-# by default, monitor all network interfaces
-# Should work on all Linux versions
-
-# Each time network connectivity become available after a cut-off,
-# run some tests and store results in
-# YYYYMMDD_hhmmss_interface/testname/output"
-# * ifconfig
-# * if WIFI, iwconfig
-# * /etc/resolv.conf
-# * 15s pcap
-# * route -n
-# * traceroute
-# * local net IP scan
-# * public IP (curl ifconfig.me)
-# * ping 8.8.8.8
-
import sys
import os
import time
@@ -31,11 +14,12 @@ import shutil
import errno
class Autoscan_iface(object):
- def __init__(self, iface, logpath=".", pubip="8.8.8.8", verbose=0):
+ def __init__(self, iface, logpath=".", target_pubip="8.8.8.8", verbose=0, noexplore=False):
self.iface = iface
self.logpath = logpath
self.verbose = verbose
- self.pubip = pubip
+ self.target_pubip = target_pubip
+ self.noexplore = noexplore
self.date = None # set by _do_tests()
if 'SUDO_UID' in os.environ and 'SUDO_GID' in os.environ:
self.perm_uid = int(os.environ['SUDO_UID'])
@@ -48,38 +32,70 @@ class Autoscan_iface(object):
self.found_pubip = None
self.found_dns = list()
+ def run_now(self):
+ self._do_tests()
+
def monitor(self):
+ self._wait_up()
self._do_tests()
while True:
self._wait_down()
self._wait_up()
self._do_tests()
- def run_now(self):
- self._do_tests()
-
def _wait_up(self):
+ if self.verbose >= 1:
+ print("[>] _wait_up")
while True:
out, err, code = self._exec(
['ifconfig', self.iface])
+ # iface up
up = re.search(r'UP', out)
ip4 = re.search(r'inet (\S+)', out)
ip6 = re.search(r'inet6 (\S+)', out)
- if up and (ip4 or ip6):
+ if up and ip4: # XXX no ip6 because too fast
break
- time.sleep(1)
+ # loop
+ time.sleep(0.5)
+ time.sleep(3) # XXX wait for network to be configured
def _wait_down(self):
+ if self.verbose >= 1:
+ print("[>] _wait_down")
+ last_ip4 = None
+ last_ip6 = None
+ last_t = None
while True:
out, err, code = self._exec(
['ifconfig', self.iface])
+ # iface down
up = re.search(r'UP', out)
if not up:
break
- # XXX also consider sleep as interface down
- time.sleep(1)
+ # iface ip change
+ ip4 = re.search(r'inet (\S+)', out)
+ if ip4: ip4 = ip4.group(1)
+ if (not ip4 and last_ip4) or \
+ (ip4 and last_ip4 and ip4 != last_ip4):
+ break
+ last_ip4 = ip4
+ ip6 = re.search(r'inet6 (\S+)', out)
+ if ip6: ip6 = ip6.group(1)
+ if (not ip6 and last_ip6) or \
+ (ip6 and last_ip6 and ip6 != last_ip6):
+ break
+ last_ip6 = ip6
+ # sleep detection
+ t = time.clock()
+ if last_t and (t - last_t > 1):
+ break
+ last_t = t
+ # loop
+ time.sleep(0.5)
def _do_tests(self):
+ if self.verbose >= 1:
+ print("[>] _do_tests")
self.date = time.strftime("%Y%m%d_%H%M%S", time.gmtime())
self._do_tests_run(self._test_pcap)
self._do_tests_run(self._test_ifconfig)
@@ -90,16 +106,10 @@ class Autoscan_iface(object):
self._do_tests_run(self._test_pubip_ping)
self._do_tests_run(self._test_pubip_traceroute)
self._do_tests_run(self._test_resolv_traceroute)
- self._do_tests_run(self._test_explor_traceroute)
- self._do_tests_run(self._test_explor_scan)
- if self.found_pubip:
- suffix = self.found_pubip
- else:
- suffix = self.found_ip4
- newpath = self._storepath_get() + "_" + suffix
- if self.verbose >= 1:
- print "[*] %s" % newpath
- os.rename(self._storepath_get(), newpath)
+ if not self.noexplore:
+ self._do_tests_run(self._test_explor_traceroute)
+ self._do_tests_run(self._test_explor_scan)
+ self._storepath_rename()
def _do_tests_run(self, func):
try:
@@ -167,35 +177,34 @@ class Autoscan_iface(object):
def _test_pubip_get(self):
out, err, code = self._exec(
['curl', '--retry', '3', 'ifconfig.me'])
- self._store("pubip_get/ip", out)
- self.found_pubip = out.strip()
+ if re.search(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', out):
+ self._store("pubip_get/ip", out)
+ self.found_pubip = out.strip()
+ else:
+ self._store("pubip_get/out", out)
+ self.found_pubip = None
def _test_pubip_ping(self):
out, err, code = self._exec(
- ['ping', '-W', '3', '-c', '1', self.pubip])
+ ['ping', '-W', '3', '-c', '1', self.target_pubip])
self._store("pubip_ping/code", code)
self._store("pubip_ping/out", out)
+ def _test_pubip_traceroute(self):
+ self._store("pubip_traceroute/out",
+ self._util_traceroute(self.target_pubip))
+
def _test_resolv_traceroute(self):
for dns in self.found_dns:
self._store("resolv_traceroute/out",
self._util_traceroute(dns))
- def _test_pubip_traceroute(self):
- self._store("pubip_traceroute/out",
- self._util_traceroute(self.pubip))
-
def _test_explor_traceroute(self):
targets = ["192.168.0.1", "192.168.1.1", "192.168.2.1", "10.0.0.1", "172.16.0.1"]
for t in targets:
self._store("explor_traceroute/out_%s" % t,
self._util_traceroute(t))
- def _util_traceroute(self, target):
- out, err, code = self._exec(
- ['traceroute', target])
- return out
-
def _test_explor_scan(self):
target = re.sub('\.[0-9]+$', '', self.found_ip4) + "/24" # XXX v6
out, err, code = self._exec(
@@ -229,6 +238,22 @@ class Autoscan_iface(object):
subprocess.check_output(['chown', '-R', '%s:%s' % (self.perm_uid, self.perm_gid), self.logpath]) # pythonic way is awefull
return path
+ def _storepath_rename(self):
+ if self.found_pubip:
+ suffix = self.found_pubip
+ else:
+ suffix = self.found_ip4
+ newpath = self._storepath_get() + "_" + suffix
+ if self.verbose >= 1:
+ print "[*] %s" % newpath
+ os.rename(self._storepath_get(), newpath)
+
+ def _util_traceroute(self, target):
+ out, err, code = self._exec(
+ ['traceroute', target])
+ return out
+
+
if not os.geteuid() == 0:
sys.exit('must be root')
@@ -245,6 +270,8 @@ parser.add_argument("-f", "--foreground", action="store_true",
help="Run in foreground for monitor mode, do not daemonize")
parser.add_argument("-o", "--outdir", action="store", default=".",
help="Use DIR as output directory")
+parser.add_argument("-x", "--noexplore", action="store_true",
+ help="Do not run explore tests (traceroute to arbitrary local ranges + nmap scan)")
parser.add_argument("-p", "--pubip", action="store", default="8.8.8.8",
help="Use target IP for public IP tests")
parser.add_argument("-v", "--verbose", action="store_true",
@@ -264,7 +291,7 @@ if not args.runnow and not args.monitor:
for iface in args.interfaces:
if os.fork() == 0:
autoscan = Autoscan_iface(iface, args.outdir, args.pubip,
- args.verbose)
+ args.verbose, args.noexplore)
if args.runnow:
autoscan.run_now()
else: