Setting up SMS Sending and Receiving using a USB GSM Dongle by ZTE — Selective Intellect

04 Feb.,2024

 

Disable Unnecessary Modem Properties

The USB GSM modem, MF190, comes with properties like appearing as a CD-ROM drive on Linux or as a mass storage device or both. In our case, on Kali Linux, this device appeared as 3 different devices: a CD-ROM device /dev/sr1, a mass storage device /dev/sdc and a USB modem /dev/ttyUSB2. These device names can be extracted from the dmesg output as below as soon as you plugin the USB device to your computer.

$ sudo dmesg | tail -n 1000
[1800781.986806] usb 1-2.4.2: new high-speed USB device number 7 using ehci-pci                                                                                                                      
[1800782.197336] usb 1-2.4.2: New USB device found, idVendor=19d2, idProduct=2000, bcdDevice= 0.00                                                                                                   
[1800782.197343] usb 1-2.4.2: New USB device strings: Mfr=3, Product=2, SerialNumber=4                                                                                                               
[1800782.197347] usb 1-2.4.2: Product: ZTE WCDMA Technologies MSM                                                                                                                                    
[1800782.197350] usb 1-2.4.2: Manufacturer: ZTE,Incorporated                                                                                                                                         
[1800782.197352] usb 1-2.4.2: SerialNumber: MF1900ZTED010000                                                                                                                                         
[1800782.199979] usb-storage 1-2.4.2:1.0: USB Mass Storage device detected                                                                                                                           
[1800782.201943] scsi host3: usb-storage 1-2.4.2:1.0                                                                                                                                                 
[1800783.221344] scsi 3:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2                                                                                                        
[1800783.225970] sr 3:0:0:0: [sr1] scsi-1 drive                                                                                                                                                      
[1800783.243508] sr 3:0:0:0: Attached scsi CD-ROM sr1                                                                                                                                                
[1800783.243741] sr 3:0:0:0: Attached scsi generic sg4 type 5                                                                                                                                        
[1800784.752096] usb 1-2.4.2: USB disconnect, device number 7                                                                                                                                        
[1800785.078898] usb 1-2.4.2: new high-speed USB device number 8 using ehci-pci                                                                                                                      
[1800785.290082] usb 1-2.4.2: New USB device found, idVendor=19d2, idProduct=0117, bcdDevice= 0.00                                                                                                   
[1800785.290090] usb 1-2.4.2: New USB device strings: Mfr=3, Product=2, SerialNumber=4                                                                                                               
[1800785.290093] usb 1-2.4.2: Product: ZTE WCDMA Technologies MSM                                                                                                                                    
[1800785.290096] usb 1-2.4.2: Manufacturer: ZTE,Incorporated                                                                                                                                         
[1800785.290099] usb 1-2.4.2: SerialNumber: MF1900ZTED010000                                                                                                                                         
[1800785.293883] usb-storage 1-2.4.2:1.3: USB Mass Storage device detected                                                                                                                           
[1800785.294205] scsi host3: usb-storage 1-2.4.2:1.3                                                                                                                                                 
[1800785.974549] usbcore: registered new interface driver option                                                                                                                                     
[1800785.976340] usbserial: USB Serial support registered for GSM modem (1-port)                                                                                                                     
[1800785.977650] option 1-2.4.2:1.0: GSM modem (1-port) converter detected                                                                                                                           
[1800785.977975] usb 1-2.4.2: GSM modem (1-port) converter now attached to ttyUSB0                                                                                                                   
[1800785.978392] option 1-2.4.2:1.1: GSM modem (1-port) converter detected                                                                                                                           
[1800785.978596] usb 1-2.4.2: GSM modem (1-port) converter now attached to ttyUSB1                                                                                                                   
[1800785.979220] option 1-2.4.2:1.2: GSM modem (1-port) converter detected                                                                                                                           
[1800785.979462] usb 1-2.4.2: GSM modem (1-port) converter now attached to ttyUSB2                                                                                                                   
[1800786.324071] scsi 3:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2                                                                                                        
[1800786.325395] scsi 3:0:0:1: Direct-Access     ZTE      MMC Storage      2.31 PQ: 0 ANSI: 2                                                                                                        
[1800786.331560] sr 3:0:0:0: [sr1] scsi-1 drive                                                                                                                                                      
[1800786.359076] sr 3:0:0:0: Attached scsi CD-ROM sr1                                                                                                                                                
[1800786.359210] sr 3:0:0:0: Attached scsi generic sg4 type 5                                                                                                                                        
[1800786.359645] sd 3:0:0:1: Attached scsi generic sg5 type 0                                                                                                                                        
[1800786.373392] sd 3:0:0:1: [sdc] 7716864 512-byte logical blocks: (3.95 GB/3.68 GiB)                                                                                                               
[1800786.375021] sd 3:0:0:1: [sdc] Write Protect is off                                                                                                                                              
[1800786.375026] sd 3:0:0:1: [sdc] Mode Sense: 0f 0e 00 00                                                                                                                                           
[1800786.375768] sd 3:0:0:1: [sdc] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA                                                                                             
[1800786.416178]  sdc: sdc1                                                                                                                                                                          
[1800786.435203] sd 3:0:0:1: [sdc] Attached SCSI removable disk

You can also use lsusb to check that the device has been loaded.

$ lsusb | grep -i zte
Bus 001 Device 008: ID 19d2:0117 ZTE WCDMA Technologies MSM MF667

The device seems to show MF667 but the labeling says MF190. Either way, they support the same commands for sending and receiving SMS.

For this post, we will disable both the CD-ROM and mass storage feature. It may so happen that you may want to take advantage of the mass storage feature to save messages or to use the USB GSM modem to receive files over GSM and that is out of the scope of this post.

  • First eject the CD-ROM from the host machine

    $ sudo eject /dev/sr1
  • Then connect to the USB modem using a serial program like minicom and run the following commands to disable the CD-ROM features. The first command makes the device online and the second command disables the CD-ROM auto-run feature.

$ minicom -b 115200 /dev/ttyUSB2
AT+ZOPRT=5 
AT+ZCDRUN=8

Now the device is ready for sending and receiving messages and phone calls. For this post, we will not be making any phone calls.

Install Perl Modules

Once the device has been setup and configured, let us try to use it using a Perl script. The GSM device acts like a modem with a serial port so the dependency that you need to install using the cpanm tool is primarily Device::Gsm which will install other dependencies like Device::Modem and Device::SerialPort. Of course, you could also use a Python script to connect to the modem, but we love writing Perl.

$ cpanm Device::Gsm Device::Modem Device::SerialPort

Sending Messages

Sending messages can be done very easily using the Device::Gsm module as shown below in the perl script. The $modem, $text and $recipient variables must be edited as per your needs. The phone number must have no spaces, must include the country code and the + sign in front of it.

Once you create a Device::Gsm object, then you connect to the modem over the serial port /dev/ttyUSB2 with a baud rate of 115200. Once that connection works, you can then send a message using the send_sms function which is obvious in the below code.

use strict;
 use warnings;
 use Device::Gsm;
 ## setup the USB GSM modem                                                                                                                                                                       
 my $modem = '/dev/ttyUSB2'; # or other like /dev/modem                                                                                                                                           
 my $gsm = Device::Gsm->new(port => $modem, log => 'file,/tmp/gsm.log',                                                                                                                           
                loglevel => 'info');                                                                                                                                                                 
 $gsm->connect(115200) or die "Failed to connect to $modem";                                                                                                                                      
 ## my message                                                                                                                                                                                    
 my $text = "This is a test message";                                                                                                                                                             
 ## my phone number                                                                                                                                                                               
 my $recipient = '+12012012010'; # the full phone number you want to use                                                                                                                          
 ## send the message                                                                                                                                                                              
 my $sent = $gsm->send_sms(                                                                                                                                                                       
        content => substr($text, 0, 140),                                                                                                                                                            
        recipient => $recipient,                                                                                                                                                                     
  );                                                                                                                                                                                               
 die "Unable to send message to $recipient ", scalar localtime unless $sent;                                                                                                                      
 print "Sent message to $recipient at ", scalar localtime, "\n";

Receiving Messages

Receiving messages is similarly done. You must connect to the modem at a baud rate of 115200 and then invoke the messages() function with the storage option defined as ME which stands for the phone memory, which is where the messages are stored by default on this ZTE device.

If you have messages stored in memory, the for loop will get invoked and each message which is an instance of Device::Gsm::Sms can then be handled or printed or processed or stored in a database etc. In the code below, we delete the message if the status is UNREAD, but that is where the processing by the user can be done.

use strict;
    use warnings;
    use Device::Gsm;
    use Device::Gsm::Sms;
    ## setup the USB GSM modem                                                                                                                                                                       
    my $modem = '/dev/ttyUSB2'; # or other like /dev/modem                                                                                                                                           
    my $gsm = Device::Gsm->new(port => $modem, log => 'file,/tmp/gsm.log',                                                                                                                           
               loglevel => 'info');                                                                                                                                                                 
    $gsm->connect(115200) or die "Failed to connect to $modem";                        
    ## get the messages from the local storage 'ME'                                                                                                                                                  
    my @messages = $gsm->messages('ME');                                                                                                                                                             
    printf "You have %d messages\n", scalar(@messages);                                                                                                                                              
    my $idx = 0;                                                                                                                                                                                     
    foreach my $msg (@messages) {                                                                                                                                                                    
        next unless defined $msg;                                                                                                                                                                    
        print '-' x 60, "\n", "MESSAGE N. $idx\n";                                                                                                                                                   
        print 'Type   ',($msg->type() eq Device::Gsm::Sms::SMS_SUBMIT ? 'SUBMIT' : 'DELIVER'), "\n";                                                                                                 
        print 'Status ', $msg->status(), "\n";                                                                                                                                                       
        print 'From   ', $msg->sender(), "\n";                                                                                                                                                       
        print 'To     ', $msg->recipient(), "\n";                                                                                                                                                    
        print 'Time   ', $msg->time(), "\n";                                                                                                                                                         
        print 'Text   [', $msg->text(), "]\n";                                                                                                                                                       
        ## if the message is unread, delete it now since you may have read it or                                                                                                                     
        if ($msg->status() =~ /UNREAD/) {                                                                                                                                                            
            ### DO SOME PROCESSING HERE                                                                                                                                                              
            print "DELETING SMS FROM STORAGE!!\n";                                                                                                                                                   
            $msg->delete();                                                                                                                                                                          
        }                                                                                                                                                                                            
        $idx++;                                                                                                                                                                                      
    }

The received messages will look like the below:

------------------------------------------------------------                                                                                                                                         
MESSAGE N. 0                                                                                                                                                                                         
Type   DELIVER                                                                                                                                                                                       
Status REC UNREAD                                                                                                                                                                                    
From   LYCAMOBILE                                                                                                                                                                                    
To                                                                                                                                                                                                   
Text   [Dear customer ,Your $19 INTERNATIONAL PLAN has been renewed succesfully.it is good through 09/16/2021. Visit https://www.lycamobile.us/login for details.]                                   
------------------------------------------------------------                                                                                                                                         
MESSAGE N. 1                                                                                                                                                                                         
Type   DELIVER                                                                                                                                                                                       
Status REC UNREAD                                                                                                                                                                                    
From   LYCAMOBILE                                                                                                                                                                                    
To                                                                                                                                                                                                   
Text   [ Thank you for using Lycamobile.]                                                                                                                                                            
------------------------------------------------------------                                        
------------------------------------------------------------                                                                                                                                         
MESSAGE N. 2                                                                                                                                                                                         
Type   DELIVER                                                                                                                                                                                       
Status REC UNREAD                                                                                                                                                                                    
From   +12012012010                                                                                                                                                                                  
To                                                                                                                                                                                                   
Text   [Test]                                                                                                                                                                                        
------------------------------------------------------------                                                                                                                                         
MESSAGE N. 3                                                                                                                                                                                         
Type   DELIVER                                                                                                                                                                                       
Status REC UNREAD                                                                                                                                                                                    
From   +12012012010                                                                                                                                                                                  
To                                                                                                                                                                                                   
Text   [Got it]                                                                                                                                                                                      
------------------------------------------------------------

Sending & Receiving Together

The below script lets you send a message to a recipient and receive replies by checking every 5 seconds. The most important thing to note is that you have to reconnect to the GSM modem if you have sent a message and then want to receive new messages. This forces the modem to exit the sending state and enter a receiving state.

The rest of the code is similar to the above code blocks in the earlier sections. This script was tested on Kali Linux and it works as of this writing.

#!/usr/bin/env perl                                                                                                                                                                                  
use strict;                                                                                                                                                                                          
use warnings;                                                                                                                                                                                        
use sigtrap qw/handler signal_handler normal-signals/;                                                                                                                                               

use Device::Gsm;                                                                                                                                                                                     
use Device::Gsm::Sms;                                                                                                                                                                                
use Data::Dumper;                                                                                                                                                                                    

sub usage {                                                                                                                                                                                          
    die << "..."                                                                                                                                                                                     
Usage: $0 <phone number like +12125432109> <message>                                                                                                                                                 
Press Ctrl-C to exit program.                                                                                                                                                                        
...                                                                                                                                                                                                  
}                                                                                                                                                                                                    

sub send_sms {                                                                                                                                                                                       
    my ($gsm, $text, $recipient) = @_;                                                                                                                                                               
    return unless length($text // '');                                                                                                                                                               
    return unless $recipient;                                                                                                                                                                        
    my $sent = $gsm->send_sms(                                                                                                                                                                       
        content => substr($text, 0, 140),                                                                                                                                                            
        recipient => $recipient,                                                                                                                                                                     
    );                                                                                                                                                                                               
    die "Unable to send message to $recipient ", scalar localtime unless $sent;                                                                                                                      
    print "Sent message to $recipient at ", scalar localtime, "\n";                                                                                                                                  
}                                                                                                                                                                                                    

sub receive_messages {                                                                                                                                                                               
    my $gsm = shift;                                                                                                                                                                                 
    my @messages = $gsm->messages('ME');                                                                                                                                                             
    printf "You have %d messages\n", scalar(@messages);                                                                                                                                              
    my $idx = 0;                                                                                                                                                                                     
    foreach my $msg (@messages) {                                                                                                                                                                    
        next unless defined $msg;                                                                                                                                                                    
        print '-' x 60, "\n", "MESSAGE N. $idx\n";                                                                                                                                                   
        print 'Type   ',($msg->type() eq Device::Gsm::Sms::SMS_SUBMIT ? 'SUBMIT' : 'DELIVER'), "\n";                                                                                                 
        print 'Status ', $msg->status(), "\n";                                                                                                                                                       
        print 'From   ', $msg->sender(), "\n";                                                                                                                                                       
        print 'To     ', $msg->recipient(), "\n";                                                                                                                                                    
        print 'Time   ', $msg->time(), "\n";                                                                                                                                                         
        print 'Text   [', $msg->text(), "]\n";                                                                                                                                                       
        if ($msg->status() =~ /UNREAD/) {                                                                                                                                                            
            print "DELETING SMS FROM STORAGE!!\n";                                                                                                                                                   
            $msg->delete();                                                                                                                                                                          
        }                                                                                                                                                                                            
        $idx++;                                                                                                                                                                                      
    }                                                                                                                                                                                                
}       
sub signal_handler {                                                                                                                                                                                 
    die "Signal caught: $!";                                                                                                                                                                         
}                                                                                                                                                                                                    

usage() unless scalar(@ARGV);                                                                                                                                                                        
usage() unless defined $ARGV[0];#TODO: verify phone number format                                                                                                                                    
usage() unless length($ARGV[1] // '');                                                                                                                                                               
warn "Message to be sent is longer than 140 chars and will be truncated" if length($ARGV[1]) > 140;                                                                                                  
my $recipient = shift(@ARGV);                                                                                                                                                                        
my $message = shift(@ARGV);                                                                                                                                                                          
print "Using phone number $recipient for recipient\n";                                                                                                                                               
my $modem = '/dev/modem';                                                                                                                                                                            
$modem = '/dev/ttyACM0' if -e '/dev/ttyACM0';                                                                                                                                                        
$modem = '/dev/ttyUSB2' if -e '/dev/ttyUSB2';                                                                                                                                                        
my %log = (log => 'file,/tmp/gsm.log', loglevel => 'debug');                                                                                                                                         
my $gsm = Device::Gsm->new(port => $modem, %log);                                                                                                                                                    
$gsm->connect(115200) or die "Failed to connect to $modem";                                                                                                                                          
send_sms($gsm, $message, $recipient);                                                                                                                                                                
while (1) {                                                                                                                                                                                          
    $gsm->connect(115200);                                                                                                                                                                           
    if ($gsm->is_active()) {                                                                                                                                                                         
        receive_messages($gsm);                                                                                                                                                                      
        sleep 5;                                                                                                                                                                                     
    } else {                                                                                                                                                                                         
        warn "GSM modem is not active";                                                                                                                                                              
        last;                                                                                                                                                                                        
    }                                                                                                                                                                                                
}                                                                                                                                                                                                    
__END__                                                                                                                                                                                              
###                                                                                                                                                                                                  
###                                                                                                                                                                                                  
### COPYRIGHT: 2013-2021 Selective Intellect LLC. All Rights Reserved.

Want more information on gsm modems? Click the link below to contact us.