Merge pull request #22 from petterreinholdtsen/no-root-required

Rewrite to not require privileged network interface access
This commit is contained in:
Oros42 2017-09-04 13:13:06 +02:00 committed by GitHub
commit 977fed1c4d

View file

@ -64,6 +64,7 @@ import ctypes
from scapy.all import sniff, UDP from scapy.all import sniff, UDP
import json import json
from optparse import OptionParser from optparse import OptionParser
import socket
imsitracker = None imsitracker = None
@ -277,7 +278,7 @@ class gsmtap_hdr(ctypes.BigEndianStructure):
) )
# return mcc mnc, lac, cell, country, brand, operator # return mcc mnc, lac, cell, country, brand, operator
def find_cell(gsm, x, t = None): def find_cell(gsm, udpdata, t = None):
# find_cell() update all following variables # find_cell() update all following variables
global mcc global mcc
global mnc global mnc
@ -317,33 +318,32 @@ def find_cell(gsm, x, t = None):
0040 f8 02 01 9c 0040 f8 02 01 9c
""" """
if gsm.sub_type == 0x01: # Channel Type == BCCH (0) if gsm.sub_type == 0x01: # Channel Type == BCCH (0)
p=str(x) p=udpdata
if ord(p[0x3c]) == 0x1b: # Message Type: System Information Type 3 if ord(p[0x12]) == 0x1b: # Message Type: System Information Type 3
# FIXME # FIXME
m=hex(ord(p[0x3f])) m=hex(ord(p[0x15]))
if len(m)<4: if len(m)<4:
mcc=m[2]+'0' mcc=m[2]+'0'
else: else:
mcc=m[3]+m[2] mcc=m[3]+m[2]
mcc+=str(ord(p[0x40]) & 0x0f) mcc+=str(ord(p[0x16]) & 0x0f)
# FIXME not works with mnc like 005 or 490 # FIXME not works with mnc like 005 or 490
m=hex(ord(p[0x41])) m=hex(ord(p[0x17]))
if len(m)<4: if len(m)<4:
mnc=m[2]+'0' mnc=m[2]+'0'
else: else:
mnc=m[3]+m[2] mnc=m[3]+m[2]
lac=ord(p[0x42])*256+ord(p[0x43]) lac=ord(p[0x18])*256+ord(p[0x19])
cell=ord(p[0x3d])*256+ord(p[0x3e]) cell=ord(p[0x13])*256+ord(p[0x14])
t.current_cell(mcc, mnc, lac, cell) t.current_cell(mcc, mnc, lac, cell)
def find_imsi(x, t=None): def find_imsi(udpdata, t=None):
if t is None: if t is None:
t = imsitracker t = imsitracker
# Create object representing gsmtap header in UDP payload # Create object representing gsmtap header in UDP payload
udpdata = str(x[UDP].payload)
gsm = gsmtap_hdr.from_buffer_copy(udpdata) gsm = gsmtap_hdr.from_buffer_copy(udpdata)
#print gsm #print gsm
@ -352,15 +352,15 @@ def find_imsi(x, t=None):
# FIXME : when you change the frequency, this informations is # FIXME : when you change the frequency, this informations is
# not immediately updated. So you could have wrong values when # not immediately updated. So you could have wrong values when
# printing IMSI :-/ # printing IMSI :-/
find_cell(gsm, x, t=t) find_cell(gsm, udpdata, t=t)
else: # Channel Type != BCCH (0) else: # Channel Type != BCCH (0)
p=str(x) p=udpdata
tmsi1="" tmsi1=""
tmsi2="" tmsi2=""
imsi1="" imsi1=""
imsi2="" imsi2=""
if ord(p[0x3c]) == 0x21: # Message Type: Paging Request Type 1 if ord(p[0x12]) == 0x21: # Message Type: Paging Request Type 1
if ord(p[0x3e]) == 0x08 and (ord(p[0x3f]) & 0x1) == 0x1: # Channel 1: TCH/F (Full rate) (2) if ord(p[0x14]) == 0x08 and (ord(p[0x15]) & 0x1) == 0x1: # Channel 1: TCH/F (Full rate) (2)
# Mobile Identity 1 Type: IMSI (1) # Mobile Identity 1 Type: IMSI (1)
""" """
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f
@ -372,9 +372,9 @@ def find_imsi(x, t=None):
0050 2b 0050 2b
XX XX XX XX XX XX XX XX = IMSI XX XX XX XX XX XX XX XX = IMSI
""" """
imsi1=p[0x3f:][:8] imsi1=p[0x15:][:8]
# ord(p[0x3a]) == 0x59 = l2 pseudo length value: 22 # ord(p[0x10]) == 0x59 = l2 pseudo length value: 22
if ord(p[0x3a]) == 0x59 and ord(p[0x48]) == 0x08 and (ord(p[0x49]) & 0x1) == 0x1: # Channel 2: TCH/F (Full rate) (2) if ord(p[0x10]) == 0x59 and ord(p[0x1E]) == 0x08 and (ord(p[0x1F]) & 0x1) == 0x1: # Channel 2: TCH/F (Full rate) (2)
# Mobile Identity 2 Type: IMSI (1) # Mobile Identity 2 Type: IMSI (1)
""" """
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f
@ -387,8 +387,8 @@ def find_imsi(x, t=None):
YY YY YY YY YY YY YY YY = IMSI 1 YY YY YY YY YY YY YY YY = IMSI 1
XX XX XX XX XX XX XX XX = IMSI 2 XX XX XX XX XX XX XX XX = IMSI 2
""" """
imsi2=p[0x49:][:8] imsi2=p[0x1F:][:8]
elif ord(p[0x3a]) == 0x59 and ord(p[0x48]) == 0x08 and (ord(p[0x49]) & 0x1) == 0x1: # Channel 2: TCH/F (Full rate) (2) elif ord(p[0x10]) == 0x59 and ord(p[0x1E]) == 0x08 and (ord(p[0x1F]) & 0x1) == 0x1: # Channel 2: TCH/F (Full rate) (2)
# Mobile Identity - Mobile Identity 2 - IMSI # Mobile Identity - Mobile Identity 2 - IMSI
""" """
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f
@ -401,11 +401,11 @@ def find_imsi(x, t=None):
YY YY YY YY YY YY YY YY = IMSI 1 YY YY YY YY YY YY YY YY = IMSI 1
XX XX XX XX = TMSI XX XX XX XX = TMSI
""" """
tmsi1=p[0x4a:][:4] tmsi1=p[0x20:][:4]
t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p) t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p)
elif ord(p[0x45]) == 0x08 and (ord(p[0x46]) & 0x1) == 0x1: # Channel 2: TCH/F (Full rate) (2) elif ord(p[0x1B]) == 0x08 and (ord(p[0x1C]) & 0x1) == 0x1: # Channel 2: TCH/F (Full rate) (2)
# Mobile Identity 2 Type: IMSI (1) # Mobile Identity 2 Type: IMSI (1)
""" """
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f
@ -418,11 +418,11 @@ def find_imsi(x, t=None):
yy yy yy yy = TMSI/P-TMSI - Mobile Identity 1 yy yy yy yy = TMSI/P-TMSI - Mobile Identity 1
XX XX XX XX XX XX XX XX = IMSI XX XX XX XX XX XX XX XX = IMSI
""" """
tmsi1=p[0x40:][:4] tmsi1=p[0x16:][:4]
imsi2=p[0x46:][:8] imsi2=p[0x1C:][:8]
t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p) t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p)
elif ord(p[0x3e]) == 0x05 and (ord(p[0x3f]) & 0x07) == 4: # Mobile Identity - Mobile Identity 1 - TMSI/P-TMSI elif ord(p[0x14]) == 0x05 and (ord(p[0x15]) & 0x07) == 4: # Mobile Identity - Mobile Identity 1 - TMSI/P-TMSI
""" """
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00
@ -434,16 +434,16 @@ def find_imsi(x, t=None):
XX XX XX XX = TMSI/P-TMSI - Mobile Identity 1 XX XX XX XX = TMSI/P-TMSI - Mobile Identity 1
YY YY YY YY = TMSI/P-TMSI - Mobile Identity 2 YY YY YY YY = TMSI/P-TMSI - Mobile Identity 2
""" """
tmsi1=p[0x40:][:4] tmsi1=p[0x16:][:4]
if ord(p[0x45]) == 0x05 and (ord(p[0x46]) & 0x07) == 4: # Mobile Identity - Mobile Identity 2 - TMSI/P-TMSI if ord(p[0x1B]) == 0x05 and (ord(p[0x1C]) & 0x07) == 4: # Mobile Identity - Mobile Identity 2 - TMSI/P-TMSI
tmsi2=p[0x47:][:4] tmsi2=p[0x1D:][:4]
else: else:
tmsi2="" tmsi2=""
t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p) t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p)
elif ord(p[0x3c]) == 0x22: # Message Type: Paging Request Type 2 elif ord(p[0x12]) == 0x22: # Message Type: Paging Request Type 2
if ord(p[0x47]) == 0x08 and (ord(p[0x48]) & 0x1) == 0x1: # Mobile Identity 3 Type: IMSI (1) if ord(p[0x1D]) == 0x08 and (ord(p[0x1E]) & 0x1) == 0x1: # Mobile Identity 3 Type: IMSI (1)
""" """
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00
@ -456,11 +456,23 @@ def find_imsi(x, t=None):
zz zz zz zz = TMSI/P-TMSI - Mobile Identity 2 zz zz zz zz = TMSI/P-TMSI - Mobile Identity 2
XX XX XX XX XX XX XX XX = IMSI XX XX XX XX XX XX XX XX = IMSI
""" """
tmsi1=p[0x3e:][:4] tmsi1=p[0x14:][:4]
tmsi2=p[0x42:][:4] tmsi2=p[0x18:][:4]
imsi2=p[0x48:][:8] imsi2=p[0x1E:][:8]
t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p) t.register_imsi(imsi1, imsi2, tmsi1, tmsi2, p)
def udpserver(port, prn):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', port)
sock.bind(server_address)
while True:
udpdata, address = sock.recvfrom(4096)
if prn:
prn(udpdata)
def find_imsi_from_pkg(p):
udpdata = str(p[UDP].payload)
find_imsi(udpdata)
if __name__ == '__main__': if __name__ == '__main__':
imsitracker = tracker() imsitracker = tracker()
@ -469,6 +481,7 @@ if __name__ == '__main__':
parser.add_option("-i", "--iface", dest="iface", default="lo", help="Interface (default : lo)") parser.add_option("-i", "--iface", dest="iface", default="lo", help="Interface (default : lo)")
parser.add_option("-m", "--imsi", dest="imsi", default="", type="string", help='IMSI to track (default : None, Example: 123456789101112 or "123 45 6789101112")') parser.add_option("-m", "--imsi", dest="imsi", default="", type="string", help='IMSI to track (default : None, Example: 123456789101112 or "123 45 6789101112")')
parser.add_option("-p", "--port", dest="port", default="4729", type="int", help="Port (default : 4729)") parser.add_option("-p", "--port", dest="port", default="4729", type="int", help="Port (default : 4729)")
parser.add_option("-s", "--sniff", action="store_true", dest="sniff", help="sniff on interface instead of listening on port (require root/suid access)")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
imsitracker.show_all_tmsi=options.show_all_tmsi imsitracker.show_all_tmsi=options.show_all_tmsi
@ -491,4 +504,7 @@ if __name__ == '__main__':
exit(1) exit(1)
imsitracker.track_this_imsi(imsi_to_track) imsitracker.track_this_imsi(imsi_to_track)
imsitracker.header() imsitracker.header()
sniff(iface=options.iface, filter="port {} and not icmp and udp".format(options.port), prn=find_imsi, store=0) if options.sniff:
sniff(iface=options.iface, filter="port {} and not icmp and udp".format(options.port), prn=find_imsi_from_pkg, store=0)
else:
udpserver(port=options.port, prn=find_imsi)