Deobfuscate JavaScript from the command line made easy

When you work in the security industry, you sometimes receive targeted email attacks. By that, we mean we receive a specially crafted email from a known sender (someone you know and is also working in the security industry), with a subject tied to a work you may be doing, and containing just a link to a document for review. That’s not too bad, but by quickly analyzing the email headers you know the sender is spoofed. Anyway, we wanted to have a look at this nasty link. Who knows, the malware might be new?


As always with Metabrik, you have to install the required Briks for the task. Please install The Metabrik Platform first if you don’t have it yet. Once done, you have to load and configure required Briks:

use brik::tool
run brik::tool install client::www
run brik::tool install string::javascript

Ready to start digging

Now you have the base Briks installed, just copy the link and save it to a Variable in The Metabrik Shell:

my $link = 'hxxp://<redacted1>.com/88976189rYfhZ2Gt4YzhBrkeSFzi8naiaZFnnNtEzDQAd5kfzRFGz2FkF4Z8HrNbiKzT66hDTZ42Rb6aSAHdkbsS5bRDtsEE5/R29tb1I=/kZYR29tb1I=/'

Chances are this link will redirect a few times before stopping to the malware loader. Use the get Command to analyse what you have in this page:

run client::www get $link

You see, there is a JavaScript redirection pointing to another page on the same website. Let’s see what it shows:

my $link2 = 'hxxp://<redacted1>.com/wt/reports/go.php?p=/88976189rYfhZ2Gt4YzhBrkeSFzi8naiaZFnnNtEzDQAd5kfzRFGz2FkF4Z8HrNbiKzT66hDTZ42Rb6aSAHdkbsS5bRDtsEE5/R29tb1I=/kZYR29tb1I=/'
run client:www get $link2

As you can see, we now have a 404 error. At the time of writing, the malicious website is not leading us to the malcode anymore. Fortunately, we did took some notes during the first analysis. You will have to trust us when we say that at some point, we came to a final go.php script rendering HTML stating:

<meta http-equiv='refresh' content='3;url='><br><center><b>Only available for Windows</b></center>

No worry, just change the user agent and start again, this time with the trace_redirect Command:

set client::www user_agent "Mozilla/5.0 (Windows NT x.y; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0"
run client::www reset_user_agent
run client::www trace_redirect $link2
    code => 302,
    location => "hxxp://<redacted2>.com/s/index.php?q=/88976189rYfhZ2Gt4YzhBrkeSFzi8naiaZFnnNtEzDQAd5kfzRFGz2FkF4Z8HrNbiKzT66hDTZ42Rb6aSAHdkbsS5bRDtsEE5/R29tb1I=/kZYR29tb1I=/",
    uri => "hxxp://<redacted1>.com/wt/reports/go.php?p=/88976189rYfhZ2Gt4YzhBrkeSFzi8naiaZFnnNtEzDQAd5kfzRFGz2FkF4Z8HrNbiKzT66hDTZ42Rb6aSAHdkbsS5bRDtsEE5/R29tb1I=/kZYR29tb1I=/",
    code => 200,
    uri => "hxxp://<redacted2>.com/s/index.php?q=/88976189rYfhZ2Gt4YzhBrkeSFzi8naiaZFnnNtEzDQAd5kfzRFGz2FkF4Z8HrNbiKzT66hDTZ42Rb6aSAHdkbsS5bRDtsEE5/R29tb1I=/kZYR29tb1I=/",

We end up with the target malicious loader link. Let’s save the last element uri key from last run Command into $link3 Variable:

my $link3 = $RUN->[-1]{uri}
run client::www get $link3
  code => 200,
  content => "<title>Doc file 'GomoR' doc</title> <body bgcolor='#ffffff'>
<iframe src='' height='100%' width='100%' scrolling='no' border=0></iframe>
<iframe src='view/' height=3 width=3></iframe>
<meta http-equiv='refresh' content='5;url='>",
  headers => {
    "client-date" => "Mon, 13 Feb 2017 07:20:55 GMT",
    "client-peer" => "XX.YY.ZZ.79:80",
    "client-response-num" => 1,
    "connection" => "close",
    "content-encoding" => "gzip",
    "content-length" => 206,
    "content-type" => "text/html; charset=UTF-8",
    "date" => "Mon, 13 Feb 2017 07:20:54 GMT",
    "server" => "Apache",
    "vary" => "Accept-Encoding",

The code is not far away now. There is this relative URL named view/ from the URI hxxp://<redacted2>.com/s/. Let’s download the code with wget:

wget 'hxxp://<redacted2>.com/s/view/'

Now for the fun part

Let’s have a look at this so-called ZIP file with file::type Brik:

use file::type
run file::type get_types
mkdir zip
cd zip/
unzip ../
ls GomoR.doc.*
run file::type get_types $RUN

As it appeared as a legit ZIP file, we unzipped it and then analyzed files contained in the archive. We have a .js. This is our malcode loader. Let’s show it:

less GomoR.doc.js

Typical obfuscated JavaScript code. As we are lazy and don’t want to do the manual deobfuscation, let’s use the file::text Brik along with string::javascript Brik:

use file::text
use string::javascript
run file::text read GomoR.doc.js
run string::javascript deobfuscate $RUN

It is nearly readable. Save it to a file and display it with less:

run file::text write $RUN gomor.js
less gomor.js

Far better. We finally have the link to our malicious code \o/


We have shown how to use The Metabrik Platform as the primary way of digging into a suspicious link. Now, we want to dig into this executable and we, of course, have Briks for that. Well, sort of. Some are not yet written but in the pipe. Come see us at next TROOPERS conference, we have been scheduled for a one hour talk and we will demonstrate what can be done to reverse engineer (or at least dig a little bit into the malware) with no l33t skills.

Creating your own Briks or modifying existing ones

Starting from Metabrik 1.24, you have an easy way to create and use your own Briks. You can even modify existing ones and they will have precedence over the system ones. Let’s dig into that awesome features in this post.

Update to latest version

As always, you should be running the latest version. To update, it is as simple as running in the Shell:

use brik::tool
run brik::tool update

You should even put “use brik::tool” in your $HOME .metabrik_rc file so it is loaded at every start. Do the same for brik::search Brik, you will see how useful it can be.

After the update, you can either restart Metabrik or use the “reuse” Command:


You should also add an alias for your prefered editor. Starting from Metabrik 1.23 version, the default is to capture external programs output, it won’t really work with editors like vi. In the end, you should have some lines like below in your .metabrik_rc file:

use brik::tool
use brik::search
alias vi "run shell::command system vi"
alias search "run brik::search"

Creating a skeleton of a new Brik

The brik::tool Brik has many useful Commands. One is used to create a skeleton of a new Brik for you. Try help to see others:

help brik::tool
[+] set brik::tool datadir <datadir>
[+] set brik::tool repository <Repository>
[+] run brik::tool clone <Brik> [ <Repository> ]
[+] run brik::tool create_brik <Brik> [ <Repository> ]
[+] run brik::tool create_tool <> [ <Repository> ]
[+] run brik::tool get_brik_hierarchy <Brik>
[+] run brik::tool get_brik_hierarchy_recursive <Brik>
[+] run brik::tool get_brik_module_file <Brik> [ <directory_list> ]
[+] run brik::tool get_need_packages [ <Brik> ]
[+] run brik::tool get_need_packages_recursive <Brik>
[+] run brik::tool get_require_briks [ <Brik> ]
[+] run brik::tool get_require_briks_recursive [ <Brik> ]
[+] run brik::tool get_require_modules [ <Brik> ]
[+] run brik::tool get_require_modules_recursive <Brik>
[+] run brik::tool install <Brik>
[+] run brik::tool install_all_need_packages
[+] run brik::tool install_all_require_modules
[+] run brik::tool install_needed_packages <Brik>
[+] run brik::tool install_required_modules <Brik>
[+] run brik::tool test_repository
[+] run brik::tool update
[+] run brik::tool update_core
[+] run brik::tool update_repository
[+] run brik::tool view_brik_source <Brik>

Let’s create our first Brik named my::first and start editing it like:

run brik::tool create_brik my::first
vi $RUN

The first thing you may notice is that the create_brik Command has created a new .pm file and the associated full hierarchy to access the file. We used a run Command, so $RUN Variable is set and we can use it to directly edit the new Brik.

We created an alias for the vi external command, so it worked like a charm here. If you had an error, please go back and read on how to add the corresponding alias in your .metabrik_rc file 🙂

We will not dive into how to actually write the code for a working Brik here. You have many examples already online on the trac server. But creating the path and the file is actually not enough to be able to use your Brik yet.

Another useful Command is view_brik_source. You can easily see source code for any Brik by using this Command. Example:

run brik::tool view_source_code core::context

But well, core::context Brik contains all the magic behind Metabrik and is by far the most difficult to read for non-Perl programmers (and maybe even Perl ones?).

Making the Brik useable

The file is created and you want to use it. If you do it now, you will have an error. Well, in fact, you will be able to load it but the system cannot find it automatically yet. So you have to update your running context like:

run core::context update_available

This Command will go through all directories containing potential Briks to make them accessible to other Briks. You can then search for yours by Tag, for instance:

search tag my
[+] Used:
[+] Not used:
[+]    my::first [first, my, unstable, used]

And finally use it and ask for help on how to use it:

use my::first
help my::first
[+] set my::first datadir  
[+] run my::first install

As you can see, we can search for existing Briks by Tag. A Tag is created based on the Brik name and other properties like is it used or not. You can manually add Tags to your Briks by editing the Tag Property.

And what about modifying an existing Brik?

Ah yes. First thing is to find where the Brik you want to modify is stored on your system. It is usually somewhere in /usr. In our example, we want to modify system::os Brik to add support for a new operating system:

find /usr -name
my $os = $RUN->[0]
get core::global repository
my $local = $GET

We found our Brik and saved it on a Variable. To copy it to the correct Repository, we have to create the subdirectories in the good way. The local Repository is the good place to do that, so we fetch it by using the core::global Brik and save its path to $local Variable. We did also saved the path to original Brik into the $os Variable.

The name of the directory has to follow the Brik name, and be put in a parent lib/Metabrik directory. So, the Brik named system::os will end up in the lib/Metabrik/System directory. You will have to mix Perl code with Metabrik Commands to do so. Then, copy the file and change its permission:

my $dir = local.'/lib/Metabrik/System'   # Perl code
mkdir -p $dir  # A Metabrik Command, called for you with "run shell::command capture"
cp $os $dir  # Also A Metabrik Command, called for you with "run shell::command capture"
my $file = "$dir/"  # Perl code
chmod 644 $file  # And a last Metabrik Command.
run core::context update_available

EDIT: There is now a Command to clone an existing Brik, so you may skip all these steps. Simply call clone Command like the following snippet. The new file will be created and you can start editing it:

run brik::tool clone system::os
vi $RUN

You can now modify the code of this Brik. When you want to test it, just use the reuse Command:


That’s all for today, happy coding 🙂

Building a Docker image to run Metabrik… from Metabrik

Today, we will show how we can use the system::docker Brik to build a Metabrik Docker image. Of course, you have to have installed Metabrik first, but it is as easy as following the online guide. Alternatively, you can use the publicly available Docker image, which is quite an inception concept.

Installing the Docker image from the hub

Installing Docker is also simple. Run the following command as a standard user:

wget -qO- | sh

Then, you may fetch the Metabrik Docker image and run it:

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

And building your own image from your system

You may also start from a fresh Metabrik installation. If you want to customize your very own Docker image, you can download the Dockerfile from the trac server. Once you have it, put it in its own directory and start Metabrik.

$ mkdir ~/docker-metabrik
$ mv ~/Downloads/Dockerfile ~/docker-metabrik/

Once Metabrik is running, you have to use the system::docker Brik and change to the docker directory.

messiah:~> cd ~/docker-metabrik
messiah:~/docker-metabrik> use system::docker
[-] system::docker: brik_check_require_binaries: binary [wget] not found in PATH
[-] system::docker: brik_preinit: brik_checks failed
[-] core::context: call: use: unable to use Brik [system::docker]

But you got an error, cause some dependencies are not available yet. No worries, there is a dependencies handling feature in Metabrik for every Brik. Load the brik::tool Brik and install the system::docker one like:

messiah:~/docker-metabrik> use brik::tool 
[-] core::context: call: use: Brik [brik::tool] already used
messiah:~/docker-metabrik> run brik::tool install $USE
messiah:~/docker-metabrik> use system::docker
messiah:~/docker-metabrik> run system::docker install
[!] system::docker: brik_init: you have to execute install Command now
apparmor is enabled in the kernel, but apparmor_parser missing
+ sh -c sleep 3; apt-get update

Ready to build the Docker image

Everything is set-up, we can start building.

get system::docker
set system::docker username $username
set system::docker password $password
set system::docker email $email
run system::docker login

run system::docker get_image_id metabrik
run system::docker delete $RUN # Delete previous latest tag
run system::docker build metabrik .
run system::docker tag $RUN metabrik/metabrik:latest

run system::docker push metabrik/metabrik:latest

Automating it from a Metascript

If you have to repeat this task, you will of course want to write a script. And you can do it as a Metascript. Create a file called build-metabrik-docker-image.meta containing:

use system::file
use system::docker

my $email = 'EMAIL'
my $username = 'USERNAME'
my $password = 'PASSWORD'

set system::docker email $email
set system::docker username $username
set system::docker password $password
run system::docker login
if ($ERR) { exit 0; }

get core::global homedir
my $dir = $GET."/metabrik-docker/"
run system::file mkdir $dir
get core::global repository
my $file = $GET."/../Dockerfile"
run system::file copy $file $dir

run system::docker get_image_id metabrik
run system::docker delete $RUN # Delete previous latest tag
run system::docker build metabrik $dir
run system::docker tag metabrik metabrik/metabrik:latest

run system::docker push metabrik/metabrik:latest

exit 1

And run it:

metabrik --script metabrik-docker-image.meta


Using just a single Brik for a quick program

Today, we will show you how to use just a single Brik to build a standalone program without installing a multitude of packages or modules. To achieve that, we will use the brik::tool which is a helper to install dependencies, et use the classic lookup::iplocation Brik as the single Brik to use.

Note: you will need version 1.22 for this to work.

Install or update The Metabrik Platform

Installing should be as easy as running:

sudo cpan install Metabrik
sudo cpan install Metabrik::Repository

If that does not work for you, you can follow more complete installation instructions.

Then, you can update the platform at any time to latest repository version with this one-liner:

perl -MMetabrik::Core::Context -e 'Metabrik::Core::Context->new_brik_run("brik::tool", "update")'

You could put an alias in your shell to help doing so in the future:

alias update-metabrik="perl -MMetabrik::Core::Context -e 'Metabrik::Core::Context->new_brik_run(
\"brik::tool\", \"update\")'"

Installing a Brik dependencies

As a Brik may have some package(s) or module(s) dependencies, we’ve put some effort into simplifying their installation. There is a brik::tool install Command dedicated to that. It will even know when to use sudo for you. Use this one-liner to install dependencies for our example lookup::iplocation Brik:

perl -MMetabrik::Core::Context -e 'Metabrik::Core::Context->new_brik_run("brik::tool", "install", "lookup::iplocation")'

You could also have used The Metabrik Shell by launching

messiah:~> run brik::tool install lookup::iplocation

Creating a meta-tool

Now everything is in place, you need to know which Commands are available for the lookup::iplocation Brik. The easiest way is to use The Metabrik Shell help Command. And don’t forget to use <tab> keystroke to use completion at each step:

messiah:~> use lookup::iplocation
[*] core::shell: use: Brik [lookup::iplocation] success
messiah:~> help lookup::iplocation
[+] set lookup::iplocation datadir <datadir>
[+] run lookup::iplocation from_ip <ip_address>
[+] run lookup::iplocation from_ipv4 <ipv4_address>
[+] run lookup::iplocation from_ipv6 <ipv6_address>
[+] run lookup::iplocation organization_name <ip_address>
[+] run lookup::iplocation subnet4 <ipv4_address>
[+] run lookup::iplocation update

Two Commands are of interest here: update and from_ip. The first one let’s you get latest versions of the Maxmind IP geolocation database.

You now know what you want to do, let’s use another brik::tool Command to create a meta-tool skeleton:

perl -MMetabrik::Core::Context -e 'Metabrik::Core::Context->new_brik_run("brik::tool", "create_tool", "")'

Or from The Metabrik Shell by launching

messiah:~> run brik::tool create_tool

And you populate the generated content skeleton with required code to call update and from_ip Commands:

#!/usr/bin/env perl
# $Id$
use strict;
use warnings;

my $ip = shift or die("$0 ");

# Uncomment to use a custom repository
#use lib qw(/lib);

use Data::Dumper;
use Metabrik::Core::Context;
use Metabrik::Lookup::Iplocation;

my $con = Metabrik::Core::Context->new or die("core::context");

# Init other Briks here
my $li = Metabrik::Lookup::Iplocation->new_from_brik_init($con) or die("lookup::iplocation");
$li->update or die("update failed");

# Put Metatool code here
print Dumper($li->from_ip($ip))."\n";


And voilà. Test your program:

[+] mirror: file [/home/gomor/metabrik/lookup-iplocation/GeoIPv6.dat.gz] not modified since last check
[+] mirror: file [/home/gomor/metabrik/lookup-iplocation/GeoIP.dat.gz] not modified since last check
[+] mirror: file [/home/gomor/metabrik/lookup-iplocation/GeoIPCity.dat.gz] not modified since last check
[+] mirror: file [/home/gomor/metabrik/lookup-iplocation/GeoIPASNum.dat.gz] not modified since last check
$VAR1 = {
          'country_code3' => 'USA',
          'metro_code' => 506,
          'city' => 'Norwell',
          'dma_code' => 506,
          'country_code' => 'US',
          'postal_code' => '02061',
          'country_name' => 'United States',
          'continent_code' => 'NA',
          'region_name' => 'Massachusetts',
          'longitude' => '-70.8228',
          'region' => 'MA',
          'area_code' => 781,
          'latitude' => '42.1508'

Alternatively, for a so simple task, you could have used The Metabrik Shell:

messiah:~> use lookup::iplocation
[*] core::shell: use: Brik [lookup::iplocation] success
messiah:~> run lookup::iplocation update
messiah:~> run lookup::iplocation from_ip
  area_code      => 781,
  city           => "Norwell",
  continent_code => "NA",
  country_code   => "US",
  country_code3  => "USA",
  country_name   => "United States",
  dma_code       => 506,
  latitude       => 42.1508,
  longitude      => -70.8228,
  metro_code     => 506,
  postal_code    => "02061",
  region         => "MA",
  region_name    => "Massachusetts",


We have shown how to get up-to-date with The Metabrik Platform and how to develop a meta-tool. Helped with that, you can start to develop programs using the 200+ available Briks. For instance, try to add lookup::threatlist support to as an exercise.

Malware analysis with VM instrumentation, WMI, winexe, Volatility and Metabrik

In this article, we will show how to take advantage of Metabrik to automate some malware analysis tasks. The goal will be to execute a malware in a virtual machine (VM), just after you saved a snapshot of Windows operating system. In our example, this snapshot only includes running processes, but you will see you can do more than just that. Here, we introduce remote::wmi, remote::winexe and system::virtualbox Briks.

We will also introduce the forensic::volatility Brik which can help you perform dynamic malware analysis and extract IOCs, for instance.

Tip: you can use <tab> keystroke to complete Brik names and Commands while using The Metabrik Shell.

Setting up the environment

wmic and winexe are programs that have to be compiled by yourself. Fortunately, Metabrik makes this process as easy as running the install Command. Since wmic and winexe programs ship with the same software suite, you just have to run install Command for one of remote::wmi or remote::winexe Briks. We don’t run the install Command with system::virtualbox Brik, because we suppose you already have some VitualBox VMs installed.

use brik::tool
use remote::wmi
use remote::winexe
use forensic::volatility
help remote::wmi
help remote::winexe
help forensic::volatility
run brik::tool install_needed_packages remote::wmi
run brik::tool install_needed_packages remote::volatility


Your VM also has to be configured to allow WMI accesses for a given user, and have the WINEXESVC service started. Some help on how to do that can be found in remote::wmi and remote::winexe Briks source code.

Starting a VM and taking a snapshot

Our environment is up and running. Let’s start a VM and take a snapshot before we execute a malware within it remotely. For the purpose of this exercise, the malware will simply be calc.exe program.

use system::virtualbox
help system::virtualbox
run system::virtualbox list


Let’s start our Windows machine in headless mode: we don’t want to speak with this kind of GUI.

set system::virtualbox type headless
run system::virtualbox start 602782ec-40c0-42ba-ad63-4e56a8bd5657
run system::virtualbox snapshot_live 602782ec-40c0-42ba-ad63-4e56a8bd5657 "before calc.exe"



I know the IP address of the machine, but you could have found it by using ARP scanning on vboxnet0 interface thanks to the network::arp Brik.

my $win = ''
my $user = 'Administrator'
my $password = 'YOUR_SECRET'
set remote::wmi host $win
set remote::wmi user $user
set remote::wmi password $password
set remote::winexe host $win
set remote::winexe user $user
set remote::winexe password $password
run remote::wmi get_win32_process
for (@$RUN) {
print $_->{Name}."\n";

You should see no calc.exe right now.


Now, launch the calc.exe program and search in the process list if you can find it. Note that you will have to run Ctrl+C keystrokes because the program will block here. But calc.exe should still be running on the remote host.

run remote::winexe execute "cmd.exe /c calc.exe"
run remote::wmi get_win32_process
my @processes = map { $_->{Name} } @$RUN
my $found = grep { /calc.exe/ } @processes

In the below screenshot, you will see 2 as a result to the grep command. That’s because we ran two times the execute Command with calc.exe during our testing.


Now, we will restore the VM to its default state, when calc.exe “malware” was not yet run.

run system::virtualbox stop 602782ec-40c0-42ba-ad63-4e56a8bd5657
run system::virtualbox snapshot_restore 602782ec-40c0-42ba-ad63-4e56a8bd5657 "before calc.exe"
run system::virtualbox start 602782ec-40c0-42ba-ad63-4e56a8bd5657
run remote::wmi get_win32_process
my @processes = map { $_->{Name} } @$RUN
my $found = grep { /calc.exe/ } @processes

All clear. No more calc.exe process.

You spoke about Volatility?

Yes. And that’s where it starts to get interesting. You can do the same processes analysis with Volatility (and of course much more). To use Volatility, you need a dump of the system’s memory. To acquire this dump, it’s as simple as using the system::virtualbox dumpguestcore Command. Then, you have to extract the memory dump that is part of the generated core file. You will use the extract_memdump_from_dumpguestcore Command.

Then, you will be able to perform forensic stuff on this memory dump, for instance to search if calc.exe has been popped. If you go back to the original subject -malware analysis-, you will find the Volatility is the tool of choice to check what a malware you just run with remote::winexe Brik did to processes, network handles or registry. That’s a perfect combination of tools to extract IOCs from a malware.

run system::virtualbox dumpguestcore 602782ec-40c0-42ba-ad63-4e56a8bd5657 dump.core
run system::virtualbox extract_memdump_from_dumpguestcore dump.core dump.volatility



EDIT: on some versions of VirtualBox, you will have to use the dumpvmcore Command instead of dumguestcore.

We have a dump usable by Volatility. Let’s dig into it with forensic::volatility Brik:

use forensic::volatility
set forensic::volatility input dump.volatility
run forensic::volatility imageinfo
set forensic::volatility profile $RUN->[0]
run forensic::volatility pslist



And voilà.

A feature of WINEXESVC: get a remote shell on Windows

One last screenshot in regards to remote::winexe Brik: how to get a Windows remote shell:

run remote::winexe execute cmd.exe



We have seen that we can easily perform malware analysis on a Windows machine by using a combination of Briks. By combining features of different tools (VirtualBox, winexe and Volatility) we can, for instance, analyse consequences of running a malware on a machine. Extracting IOCs from a malware is something useful if you want to find which machines were infected on your information systems from a particuliar sample. You could then use remote::wmi Brik to scan your network for these specific patterns.

Extracting IOCs is a huge topic in itself, and we just scratched the surface here by using a dynamic method associated with a “scapegoat” VM. Another way of extracting IOCs is to use static analysis, but that’s a complete different story.

We urge you to play with Volatility (and of course Metabrik), you will see how powerful it could be. Enjoy.

Solving a forensic challenge with Metabrik and Scalpel

I recently discovered the wonderful world of forensic and challenges (read: today). So I decided to add some new Briks just to solve some of them. Let’s dig into the “Find the dog” challenge step-by-step. I will also show how I improved the Scalpel tool by wrapping it with other Briks.

Getting the files

The one from this Metabrik Example is called “Find the dog“, or “Trouvez le chien” in French. Once downloaded and extracted, you got these files:

cd /home/gomor/hgwork/metabrik/challenges/trouvez-le-chien/
my $files = $RUN

First things to do is to check for MIME types of these files. You can also check for the MAGIC types:

use file::type
run file::type get_mime_type $files
run file::type get_magic_type $files

You have a txt file (you should read it for the story behind the dog theft) and a gzip file. Let’s uncompress this one:

use file::compress
run file::compress uncompress $files->[0]
my $file = $RUN
run file::type get_mime_type $file
run file::type get_magic_type $file

Wonderful. It appears to be some kind of filesystem. Let’s analyse that with Scalpel, a filesystem image forensic tool written in Python.

Introducing Scalpel

To use Scalpel, you usually have to create a scalpel.conf file containing metadata on how to extract (or carve) files. For instance, if you want to find and extract ZIP files, you search for the string PK\x03\x04 in a bytestream.

If you want to only check for some files (say odt files), you have to comment out all the lines from that conf file, except the one for odt documents. If you want to search for all file formats, you have to uncomment all the lines. That is the first thing I changed when writing the forensic::scalpel Brik: use a Command to help you generate the configuration file with only what you want to search for.

The other limitation of the tool is its inability to identify extracted files using the libmagic (check for MIME types or MAGIC types). Thus, I added this feature within forensic::scalpel Brik to just do that: separate verified files from unverified ones.

So, let’s dig into this new Brik. It is made upon 4 existing Briks: shell::command, file::find, file::text and of course the file::type one. As you can see, new Briks can be written with already existing Briks.

We will use it to extract files from the challenge (remember, you have to find where is the dog). Because I already know the result (spoiler), I will only search for odt files from the filesystem image challenge:

use forensic::scalpel
run forensic::scalpel generate_conf "[ 'odt' ]"
run forensic::scalpel scan $file
my $verified = $RUN->{verified}

We just wanted to keep verified files. Yes, the ones that went through the file::type Brik and its MIME type identification. Read: the feature lacking from Scalpel.

We now have two odt files, let’s open them with LibreOffice (exercise for the reader).

my $files = join(' ', @$verified)
libreoffice $files

You have a picture of a dog, and a message saying: “Free Britany, or we kill the dog“. We must locate those miscreants. This is a picture, is there some EXIF metadata? Use the image::exif Brik to discover. But first, we have to extract this picture. odt files are simple ZIP files, we use the file::compress Brik again:

run file::compress uncompress $verified->[0]
my $pic = './Pictures/1000000000000CC0000009XXXXXXXXXX.jpg'
run file::type get_mime_type $pic

use image::exif
run image::exif get_metadata $pic


Lots of metadata. But more interestingly, you have the latitude and longitude of the camera which took the picture. Bingo. Sarge, we found the evil doers, let’s go catch them now. Over.


By using a few Briks, we have shown how to solve a simple challenge. As you can see, you can nearly automate it from the beginning to the end. Exercise yourself with Metabrik by downloading the docker image. Enjoy.

EDIT 2015/12/17: some Commands have moved from system::file to file::type, thus some Commands have been renamed in this post, but screen captures remain the same as before.

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 🙂

IP location with Metabrik: different ways of doing it

We just released a new Brik: lookup::iplocation. Thanks to this Brik, you will be able to easily geo-locate any IP address. Well, it has to be in MaxMind’s database for that to work, of course. In this post, we propose to explore different ways of using a Metabrik Brik with this lookup::iplocation example.

Using The Metabrik Shell

Of course, the simplest way of doing is using The Metabrik Shell (which is just a simple Brik called core::shell). A screenshot is what best demonstrates the power of Metabrik.

The first call to ‘use lookup::location‘ fails because we currently lack one Perl module: Geo::IP. Metabrik tells you so and you can install it by using the perl::module Brik.

Then, you want to update the Geo::IP database. If you don’t, you will not have the required data to perform the lookup. You have to call ‘run lookup::location update‘.

Finally, you can geo-locate the IP address by calling ‘run lookup::location from_ip <IP>‘.


Using a Metabrik script

Before being able to execute Metabrik scripts (.meta files), you have to initiate the .metabrik_script_rc file. Just edit it using vi, for instance, and put in the lines below:

vi ~/.metabrik_script_rc
set core::shell echo 0
my $home = $ENV{HOME}
my $repository = "$HOME/metabrik/repository/lib"
push @INC, $repository
run core::context update_available

Now you are ready to write your very own Metabrik script. Create one using vi and put in this content:

vi iplocation-script.meta
use lookup::iplocation
if ($ERR) { exit }

run lookup::iplocation update
if ($ERR) { exit }

run lookup::iplocation from_ip
if ($ERR) { exit }

use Data::Dumper
print Dumper($RUN)

You can mix Metabrik Commands with Perl code. Wonderful, isn’t it? Ah, maybe you want to execute it:

metabrik --script iplocation-script.meta

The third way: use a Perl script

And finally, this is Perl. You can use a Brik as a plain Perl module if you want to. Try that:

use strict;
use warnings;

use Data::Dumper;
use Metabrik::Core::Context;
use Metabrik::Lookup::Iplocation;

my $context = Metabrik::Core::Context->new;
$context->brik_init or die("[FATAL] context init failed\n");

my $li = Metabrik::Lookup::Iplocation->new_from_brik_init($context)
   or exit(1);

   or exit(2);

my $info = $li->from_ip("")
   or exit(3);

print Dumper($info);


You see you can play with Metabrik in different ways. Even though Metabrik has been thought as a shell from the beginning, you are not bound to it in any way. And you, what is your favorite way of using Briks?

Playing With Ten Million Passwords And Logins

A researcher has released a database of ten million logins and passwords. We will show how we can play with it with Metabrik.

Fetching the data

You have to find the data by yourself, go check it from Mark Burnett post: Today I Am Releasing Ten Million Passwords.

Loading Metabrik Briks

Note: You will need Metabrik 1.06+ to run this example. Check it out via the Mercurial repository.

Note: When you are using the Shell, do not forget that you can use key to auto-complete Commands and Variables.

The file is a zip archive, so you will use the file::compress Brik. The uncompressed file being a text file, you will need to parse it in a low-level way: file::read Brik will be used.

Meta:~> use file::compress
[*] core::shell: use: Brik [file::compress] success
Meta:~> use file::read
[*] core::shell: use: Brik [file::read] success


Let’s read the data and do some statistics

Uncompress the archive

So, we have first to uncompress the archive. By default, uncompressed data will be put in the Brik home directory: ~/metabrik/file-compress.

Meta:~> run file::compress unzip ~/Downloads/
Meta:~> l /home/gomor/metabrik/file-compress/10-million-combos.txt
  "-rw-r--r-- 1 gomor gomor 194130539 Feb  9 12:59 /home/gomor/metabrik/file-compress/10-million-combos.txt",


Read and parse

# No need to print anything by default during processing
set core::shell echo 0

# Configure the file::read Brik
set file::read input ~/metabrik/file-compress/10-million-combos.txt
set file::read encoding ascii
set file::read strip_crlf 1

# Start using it
run file::read open

Now, file is open, and we can start reading and parsing it. What we want here is to perform some statistics, like getting the top used passwords. To that end, we will mix Metabrik Commands with Perl code. The Shell allows you to do that in a simplified way that going to write a Perl script or program.

my $stats = {}   # Declare a variable to store results

# Get access to Perl object, this is a performance hack for power users.
run file::read brik_self
my $read = $RUN

my $count = 0
# Alternatively (but slower), we could have replaced the following line by:
# while ('run file::read read_line') {
while (my $line = $read->read_line) {
   my ($l, $p) = split(/\t/, $line);
   if (! ($count % 10_000)) {  # Print count every 10_000 lines
      print "$count\n";
   last if $read->eof;

# Get top 20 passwords
my $top = 20;
for my $k (reverse sort { $stats->{$a} <=> $stats->{$b} } keys %$stats) {
   print "$k => ".$stats->{$k}."\n";
   last if $top == 0;


And top 20 is…

  • 123456 => 55893
  • password => 19580
  • 12345678 => 13582
  • qwerty => 13137
  • 123456789 => 11696
  • 12345 => 10938
  • 1234 => 6432
  • 111111 => 5682
  • 1234567 => 4796
  • dragon => 3927
  • 123123 => 3845
  • baseball => 3565
  • abc123 => 3511
  • football => 3494
  • monkey => 3246
  • letmein => 3118
  • 696969 => 3050
  • shadow => 2956
  • master => 2931
  • 666666 => 2905

And what about a Script?

Yes, you can write a Metabrik Script to perform this task. Just copy and past this data into a file named top20-password.brik for instance:

use file::read
set file::read input ./10-million-combos.txt
set file::read encoding ascii
set file::read strip_crlf 1
run file::read open

set core::log level 0

run file::read brik_self
my $read = $RUN

my $stats = {}
my $count = 0
while (my $line = $read->read_line) {
   my ($l, $p) = split(/\t/, $line);
   if (! ($count % 10_000)) {
      print "$count\n";
   last if $read->eof;

my $top = 20;
for my $k (reverse sort { $stats->{$a} <=> $stats->{$b} } keys %$stats) {
   print "$k => ".$stats->{$k}."\n";
   last if $top == 0;


And run the script:

$ metabrik --script top20-password.brik


That’s all for today. Follow @metabrik on twitter.

Metabrik Example: Searching CVE Database

In this Metabrik Example, we will show you how to search entries in the CVE database and how to save it to a CSV file.

Loading required data

First thing to do is to load the required Briks, and ask for help on their usage. Don’t forget you can use so you have completion and you don’t have to type every single caracter.

Meta:~/metabrik> use database::nvd
Meta:~/metabrik> help database::nvd


Meta:~/metabrik> run database::nvd update recent
Meta:~/metabrik> run database::nvd load recent


Now, you have all XML data from the recent CVE feed loaded into memory. You can start your searches. As another effect, the loading result is saved as XML data into $RUN variable. You can verify that by just typing $RUN at the prompt.

Let’s search the database

Meta:~/metabrik> run database::nvd search_all
Meta:~/metabrik> my $all = $RUN
Meta:~/metabrik> my $a = []
Meta:~/metabrik> for my $e (@$all) {
   push @$a, { cve => $e->{cve_id},
      published => $e->{published_datetime}
Meta:~/metabrik> $a
    cve => "CVE-2014-9365",
    published => "2014-12-12T06:59:07.063-05:00",
    cve => "CVE-2014-9385",
    published => "2014-12-15T13:59:27.723-05:00",
    cve => "CVE-2014-7268",
    published => "2014-12-19T06:59:04.447-05:00",


How to save the result in CSV format

We have found what we were searching for: the list of recent CVE IDs and their published date and time. Now, let’s save that to a CSV file. But how? Let’s call for help. You can have help by just typing help followed by the name of a Brik. Here, the one we want is file::csv.

Meta:~/metabrik> use file::csv
Meta:~/metabrik> help file::csv


Don’t fear the output, default values are usually ok for standard usage. set Commands are used to modify the default behaviour, we won’t touch anything in this example. Try the write Command as follows, and verify file was correctly written:

Meta:~/metabrik> run file::csv write $a /tmp/cve.csv
Meta:~/metabrik> run shell::command capture cat /tmp/cve.csv


You can download Metabrik from there: Downloads.

The source code for database::nvd Brik can be found here: Database/

That’s all for today. Follow @metabrik on twitter.