Introduction: ProjectMF Installation (Phone Phreaking)

About: Me? Oh, I like bunny rabbits with floppy ears and chestnut fur.


A faceless friend in an IRC channel back in 2006 gave me the mp3 of the amazing ProjectMF HOPE presentation given by Mark Abene (Phiber Optik). Since then, I have been fascinated by the project, but lacked the technical knowledge to set a server up or even make the hardware blue box. Having access to old phone switching equipment and being able to use a blue-box to make calls, hijack trunks, tandem stacking, and much more is an invaluable thrill for anyone who is as fascinated by the phone system as I am. I recently, with the help of the project lead Don Froula, returned to the project and successfully set up my own Asterisk switch after I was able to easily create a tone-synthesisblue box with the Arduino.

The Arduino-based Blue/Red Box: Arduino-Based Blue Box (Phone Phreaking) by WeakNetLabs


ProjectMF is a a project started by Mark Abene (Phiber Optik), a brilliant programmer, hacker and phone phreak. This project takes the standard Asterisk installation and modifies it and it's Zaptel telephony drivers to recognize in-band signalling. In-band signalling is the use of the mouth-piece of a telephone receiver to send tones to phone switching hardware to control it as if the user were an inward operator.

"Project MF is a living, breathing simulation of analog SF/MF telephone signaling just as it was used in the telephone network of the 1950s through the 1980s. It lets you "blue box" telephone calls just like the phone phreaks of yesteryear ... except that it's totally legal!" -

ProjectMF was presented back in 2006 at the Sixth HOPE (Hackers on Planet Earth) conference and hasn't had many people involved due to it's slight complex setup and installation process. This tutorial will show you step by step exactly how I was able to get the system up and running with a lot of help from Don Froula (DF99).

Demonstration Videos:

My channel, (Accidentally meeting DF99 while phone phreaking in his switch)

DF99's ProjectMF demonstration video:

Hardware Requirements

The hardware required for the project is quite simple. The only thing I had to actually purchase online was the cross over Ethernet cable. Three Ethernet adapters are required for connectivity to the switch and for connectivity between the two Zaptel channel groups which run T1-over-Ethernet using the corss over cable. When you call into a ProjectMF switch, your call is looped over one of the trunks before terminating back to the same switch. This is how single and multi-frequency in-band-signalling works in the ProjectMF switch.

  1. Linux Server (simple computer to install Linux onto)
  2. 3 Ethernet Adapters
  3. 1 Crossover Ethernet Cable MUST be crossover)

Software Requirements

The software required for the project is kind of dated. I only needed,

  1. A fresh Debian Etch installation
  2. The file containing the pre-patched Asterisk and Zaptel software which can be found here
  3. The audio files for playing telephony switching, dialing and ringing sounds found here

VoIP Requirements

A VoIP provider is required for dialing into the switch from any telephone network that can be authenticated against, such as Vitelity.Net (Recommended)


This tutorial assumes that the reader has some experience with the Linux Bash command shell and is familiar with some of the terms involved with VoIP networking and set-up.

Step 1: OS Installation and Setup


Download Debian Etch Live disk from the Debian Archive:

Boot into installation and make sure that all three Ethernet adapters are present, if not, this setup won't be possible. Plug the cross-over cable into the second and third Ethernet NICs leaving the first plugged directly into your router, gateway or internet source as shown the picture of my box above. In the image, the green integrated Ethernet port (NIC-1) goes to the Internet source, and the two red arrows signify the crossover cable plugged into NIC-2 and NIC-3.

OS Installation

When asked to use a mirror, choose “yes” and scroll all the way to the top of the locations list and choose to enter the information manually.

Use the following repository: 

And on the next screen,


Step 2: Server Installation

Boot into the freshly installed OS and change the way the kernel boots by adding


to the kernel line in the menu.list file (or a clock issue will arise when trying to start the ztdummy kernel module):

root@projectMF:~# vim /boot/grub/menu.lst

The line to edit begins with

kernel /boot/vmlinuz-2.6.18-6-686 root=/dev/sda1 ro 

Now we can reboot. When the system comes back up, comment out (add a leading ‘#’ symbol) the CD ROM source in the file /etc/apt/sources.list Install some compilation dependencies,

root@projectMF:~# apt-get update  <br>root@projectMF:~# apt-get install mpg123 libnewt-dev libssl-dev linux-headers-`uname -r` zlib1g-dev bison procps mpg123-oss-i486 make build-essential ncurses-dev unzip vim

Make a space for building ProjectMF and download the necessary files,

root@projectMF:~# mkdir /mnt/usb <br>root@projectMF:~# mkdir -p /appdev/projectMF 
root@projectMF:~# cd /appdev/projectMF/ 
root@projectMF:~# wget  <a href="" rel="nofollow"> </a>  
root@projectMF:~# wget   <a href="" rel="nofollow"> </a>  
root@projectMF:~# unzip 
root@projectMF:~# unzip

Please note: the files in the file are pre-patched with the necessary changes to work with ProjectMF. No other patching is necessary to work with Debian Etch and the default kernel.

Unpack the Zaptel source code, compile and install,

root@projectMF:~# tar vzxf zaptel-1.2.9_patched.tar.gz <br>root@projectMF:~# cd zaptel-1.2.9 
root@projectMF:~# make clean 
root@projectMF:~# make linux26 
root@projectMF:~# make install 
root@projectMF:~# cp ztcfg-dude /sbin/  

Unpack Asterisk, compile and install,

root@projectMF:~# tar vzxf asterisk-1.2.12_patched.tar.gz 
root@projectMF:~# cd asterisk-1.2.12 
root@projectMF:~# make mpg123 
root@projectMF:~# make install 
root@projectMF:~# make samples  

Now unpack the add-ons and sounds directories and install each,

root@projectMF:~# tar vzxf asterisk-addons-1.2.4.tar.gz 
root@projectMF:~# cd asterisk-addons-1.2.4 
root@projectMF:~# make install 
root@projectMF:~# cd .. 
root@projectMF:~# tar vzxf asterisk-sounds-1.2.1.tar.gz 
root@projectMF:~# cd asterisk-sounds-1.2.1 
root@projectMF:~# make install

This should be enough to get us ready for configuration.

Step 3: Configuration

Next we need to edit the files:

  1. /etc/zaptel.conf
  2. /etc/asterisk/zapata.conf
  3. /etc/asterisk/extensions.conf (more on this file in the Post Configuration section below)
  4. etc/asterisk/sip.conf

If using as your VoIP provider, you can get the information for these files by clicking on Support->Asterisk Support as seen in the screenshot above.

Click on the “sip.conf” and “extensions.conf” links just after “Asterisk via Registration” on the next page for the data to be placed into your files. The line suggested by for SIP registration is in the following format,

register => : 

where username and password are those you previously specified in the sub account in This line must be placed under the “General” section and can be safely placed under the line,


The rest of the sip.conf data from can safely be placed at the bottom of the sip.conf file. The “/etc/” file should be similar to the following,

loadzone = us<br>defaultzone=us

The "goody" configuration is actually done here, by setting rxflag of first trunk group opposite of the txflag of second trunk group. This causes trunks 1-24 to ignore 2600 coming from 25-48. That also means 1-24 doesn't detect the reverse wink (although it is heard when blowing off the call), but dials regardless of receiving the wink a second or two after seizing the trunk by removing 2600 in the forward direction.

Remember to replace the lines. The reason behind using the MAC of eth1 for eth0 and vice-versa is for the cross-over networking communication. The /etc/asterisk/Zapata.conf file should look like so,




; How long generated tones (DTMF and MF) will be played on the channel
; (in milliseconds)
; toneduration=150

This file is critical for proper wink timing and clear audio on the trunk groups, as well as to "goody" the trunk operation so that you don't get disconnected after the party or recording you reach on the trunks hangs up. It also defines our “default” and “from-internal” contexts. The wink timing is defined here and sounds best at 350 after testing. The “toneduration” sets the internal MF tone duration when setting up the initial boxable call through the trunks. This is normally inaudible, unless monitoring call setup with ZapBarge() when extension 2600 is dialed to initiate the ring-back dummy call that can be boxed.

Step 4: Start Up

Next, we need to bring up the Ethernet devices that are looped with the cross-over cable. In my case it was eth1 and eth2, and eth0 was my connection to the internet.

root@projectMF:~# ifconfig eth1 up <br>root@projectMF:~# ifconfig eth2 up 

Now we start the kernel modules for zaptel and ztdummy in this specific order:

root@projectMF:~# modprobe zaptel <br>root@projectMF:~# modprobe ztdummy <br>root@projectMF:~# modprobe ztdummy <br>root@projectMF:~# ztcfg-dude 

Don’t worry about the "sf" errors ztdummy shows the first time. Now we can run ZTtool and it should say that the two looped Ethernet adapters are “OK” Now we can start Asterisk with:

root@projectMF:~# screen asterisk -vvvvvvvvvvvvvvvvvvv 

When dialing our DID number, we should see the connection being made in in the output from the above command in our terminal. Note: This process can easily be scripted as something like,

#!/bin/bash <br>ifconfig eth1 up <br>ifconfig eth1 up <br>modprobe zaptel <br>modprobe ztdummy <br>modprobe ztdummy <br>ztcfg-dude <br>screen asterisk –vvvvvvvvvvvvvvv 

And then called from the /etc/rc.local file which is ran by root upon system start-up to have the ProjectMF start as we reboot. Note, that some sleep() delays may be needed as the order of this is critical as Zaptel needs to be up and running before ztdummy, ztcfg-dude, and Asterisk are started.

Step 5: Post Configuration

Each time we edit the /etc/asterisk/extensions.conf file, we need to restart Asterisk. The following lines in this file determine how Asterisk handles an incoming call, where is the DID number given to us by

Configuration Contexts in Extensions.conf

There are three contexts that need to be specified in square brackets – default, inbound, and from-internal. The default context are extensions that can be dialed without going over an SF trunk. It is also referenced in the /etc/asterisk/sip.conf file as “Default context for incoming calls.” This context is only used if a specific context is not specified within the sip.conf device/provider entry. Only numbers in the default context can be dialed directly via the DID DISA.

Inbound is the context that we use for an inbound numbers. It is the context used when trunks 25-48 receive a call from trunks 1-24 ("g1") for instance,

[inbound]<br>exten => ,1,Answer<br>exten => ,2,DISA(1234|default)<br>exten => ,3,Hangup

is a single instance in the inbound context that will respond to incoming calls to the DID. DISA in this example, is “Direct Inward System Access” and will answer the call with a dial tone to which the code as specified above “1234” will be given a new dial tone. If we create an extension 999 as,

exten => 999,1,Wait(1)<br>exten => 999,2,Playback(660927ring,noanswer)<br>exten => 999,5,HangUp

We can then create a connection to a Zaptel channel, using the Dial() function, as,


This would connect to the Zaptel channel in extension 999. We can set this function to run when a specific extension is dialed from our DISA connection, as something like the extension 2600 as,

exten => 2600,1,Answer<br>exten => 2600,2,Dial(ZAP/g1/999)<br>exten => 2600,3,HangUp

Where 2600 is our extension number which answers, creates a Zaptel connection to group 1 with the next available pair on our trunk. This extension MUST be under the default context as the DISA command for the DID entry points to that context. With our new Zaptel channel connection, we can now dial from-internal numbers using our Blue Box. Both the “from-internal” and “default” contexts are defined also in the Zapata.conf file as we saw in Step 3 - Configuration.

Playing Audio

If we want to play tones or other audio clips, we need to first create them. Sounds in Asterisk are best played as GSM files, which we can easily make by converting WAV files using sox.

root@projectMF:~# sox <input file.wav> -r 8000 -c 1 -s -w resample -ql

MP3 files can also be encoded to WAV using the lame-mp3 LINUX utility which will need to be installed from external sources, as

lame --decode soundfile1.mp3 soundfile1.wav

or, again we can script this process as the following,

for i in *.mp3; do lame --decode $i `basename $i.mp3`.wav; done

Then we simply place the new GSM/WAV files into the /var/lib/asterisk/sounds/ directory. We can now use the Playback() or ControlPlayback() functions in the /etc/asterisk/extensions.conf file to play them. For example, we can set up extension 112 to play a ringing sound and then classtrack1HQ.gsm file with the following code as,

; Evan Doorbell recording:<br>exten => 112,1,Playback(ring08)<br>exten => 112,2,ControlPlayback(classtack1HQ,30000,#,*,0)<br>exten => 112,3,Wait(1)<br>exten => 112,4,HangUp

We can change all .wav files in the current directory with this simple Bash one-liner:

root@projectMF:~# for i in *;do j=$(echo $i|sed 's/wav$/gsm/'); sox $i -r 8000 -c 1 -s -w $j resample -ql; done

Then simply do,

root@projectMF:~# cp *.gsm /var/lib/asterisk/sounds/

To copy them into the Asterisk sound resources directory.

If - Else Logic

If / Else logic is possible using the extensions.conf file in a ternary-like fashion. For instance, we can gather input from the user’s keypad, check it, and if it’s what we want go to a labeled exten line. Let’s take a look at an example.

exten => 9935,1,Answer                                         ;Answer Call!<br>exten => 9935,n(ring),PlayBack(ringback)                       ; rang once
exten => 9935,n(begin),Read(datulogin,440long,,2)              ; play "dial tone" 440hz A4 Note - 7 seconds timeout
exten => 9935,n,GoToIf($["${datulogin}" = "1111"]?getnum:)     ; password is "1111" (default)
exten => 9935,n,GoToIf($["${datulogin}" = "*2222222"]?datuadmin:end); if not 1111, or 222222 - end
exten => 9935,n(getnum),Read(datulogin,440long,10,10); get subscriber line number
exten => 9935,n,PlayBack(datu_connectedto)                     ; say "connected to"
exten => 9935,n(readnum),SayDigits(${datulogin})               ; say digits pressed (needs to be in DATU voice, will implement later)
exten => 9935,n,PlayBack(datu_ok)                              ; "OK"
exten => 9935,n,PlayBack(datu_opt_audiom)                      ; "AUDIO MONITOR"
exten => 9935,n,Wait(1)                                        ; pause
exten => 9935,n,PlayBack(am_10sec)
exten => 9935,n,PlayBack(datu_614hz)                           ; play double beeps
exten => 9935,n,Read(temp,,2,0,1,60)                           ; If no function is selected

The above code for extensions.conf simulates a Direct Access Test Unit. Notice how the numbers usually used for ordering the exten lines are now ‘n.’ Also, we now have labels after the ‘n’s as “ring”, “begin,” “getnum” and “readnum.” These labels are referred to by the GoTo() and GoToIf() functions. We use the Read() function to play a sound and listen for user input. The user input is then stored into the variable name specified. A general definition of read() can be as,


Where "filename" is the GSM audio file to be played. In our case, we play the 440Hz tone and wait for user input. Let’s take a quick look at GoToIf().


If expression is true, GoToIf() will go to the "somelabel" label and executes that new line. If it is not true, it goes to the otherlabel label and executes the new line. If otherlabel was not defined, Asterisk would have just continued down to the next line. This is how simple if/else logica can be used in Asterisk for ProjectMF.

Step 6: Minimal Extensions Configuration File

This is a minimal extensions.conf file to be used with your new ProjectMF server.

[default]<br>exten => 2600,1,Answer<br>exten => 2600,2,Dial(ZAP/g1/999)<br>exten => 2600,3,HangUp<br>
[from-internal]<br>;Dummy ring recording - could also be just Answer, then Hangup - no audio feedback, but you will be on a trunk and the "goody" feature will keep you on the trunk after Hangup.<br>exten => 999,1,Wait(1)<br>exten => 999,2,Playback(660927ring,noanswer)<br>exten => 999,3,Playback(660927ring,noanswer)<br>exten => 999,4,Playback(660927ring,noanswer)<br>exten => 999,5,HangUp<br>; Evan Doorbell recording - or something useful to blue box to<br>exten => 112,1,Playback(ring08)<br>exten => 112,2,ControlPlayback(classtack1HQ,30000,#,*,0)<br>exten => 112,3,Wait(1)<br>exten => 112,4,HangUp<br><br>[inbound]<br>;"XXXXXXXXXX" is the DID number from Vitelity - sip.conf entry must specify the "inbound" context<br>exten => XXXXXXXXXX,1,Answer<br>exten => XXXXXXXXXX,2,DISA(1234|default)<br>exten => XXXXXXXXXX,3,Hangup


Let’s take a quick look at a few functions and their meanings. A more exhaustive list can obviously be found online using a search engine.

  • Wait(n) – pause an ‘n’ number of seconds
  • PlayBack(filename) – play a GSM file
  • ControlPlayBack(filename,length (ms),”FWD” key,”BACK” key,timeout)
  • Dial(Type,group (if type is ZAP),number) – dials a number
  • HangUp – terminates the call
  • MeetMe(EXT NUM,(options,)) – Create a conference call extension
  • ZapBarge(Channel num) – monitor a Zaptel channel

Step 7: Troubleshooting

One thing to note here, running Asterisk with the “-vvvvvvvvvvvv” arguments will display all
errors that are caught in which we can use to search Google for resolutions. Also, if we’ve come this far in the configuration and setup, we are doing really good as this is no easy task.

1 – SF tones are not being recognized by the Zaptel trunk.

Try moving the speaker of the Blue Box away from the mouth piece of the phone. The tones do not have to be played at a high volume to be recognized by the switch. Also, make sure that you are not using a speaker phone or cell phone to send the tones as this sometimes can be problematic in sound quality. Check your speaker for damage as well. A damaged speaker could produce poor quality sounds which won't be recognized by the server.

2 – ZTtool lists the devices as “RED.”

This could simply mean that the devices are not enabled. Try to enable them with syntax similar to “ifconfig ethx up” This could also mean that you forgot to run the “ztcfg-dude” program.

3 – ifconfig does not list all of my devices.

Either the drivers are not installed into Debian Etch, or try adding the “-a” argument to list all devices.

4 – The GSM file being played is intelligible and distorted

This usually means that the encoding process done on the file was of the wrong type. Try to re-encode the WAV files into GSM using the formula above in Section 6. Post Configuration, sub-section Playing Audio.

Step 8: Acknowledgments and Further Reading

Thank You

Thank you Mark Abene for making ProjectMF! Thank you DF99 for the exhaustive help while setting up my server and also help with the writing of this document.

Thank you for reading! For more information, please check the website and I am available via email - which you can get from my weblog WeakNet Labs.

Further Reading / Listening

My first tutorial on Making an Arduino- Based Blue Box



The History of Phone Phreaking Site -

Phil Lapsley's extremely informative Book -

Phone Trips - Recordings narrated by Evan Doorbell -

Even Doorbell's Telephone World -

My Weblog (with some phone phreaking hardware tutorials) - WeakNet Labs

My YouTube Channel (videos of phreaking) - HH89HH89