Hackers do the Haka – Part 1

Haka is an open source network security oriented language that allows writing security rules and protocol dissectors. In this first part of a two-part series, we will focus on writing security rules.

What is Haka

Haka is an open source security oriented language that allows specifying and applying security policies on live captured traffic. Haka is based on Lua. It is a simple, lightweight (~200 kB) and fast (a JiT compiler is available) scripting language.

The scope of Haka is twofold. First of all, it enables the specification of security rules to filter unwanted streams and report malicious activities. Haka provides a simple API for advanced packet and stream manipulation. One can drop packets or create new ones and inject them. Haka also supports on-the-fly packet modification. This is one of the main features of Haka since all complex tasks such as resizing packets, setting correctly sequence numbers are done transparently to the user. This is done live without the need of a proxy.

Secondly, Haka is endowed with a grammar allowing the specification of protocols and their underlying state machine. Haka supports both type of protocols : binary-based protocols (e.g. dns) and text-based protocols (e.g. http). The specification covers packet-based protocols such as ip as well as stream-based protocols like http.

Haka is embedded into a modular framework. It includes several packet capture modules (pcap, nfqueue) that enable end users to apply their security policy on live captured traffic or to replay it on a packet trace file. The framework provides also logging (syslog) and alerting modules (syslog, elasticsearch). Alerts follow an IDMEF-like format. Finally, the framework has auxiliary modules such as a pattern matching engine and an instruction disassembler module. These modules allow writing fine-grained security rules to detect obfuscated malware for instance. Haka was designed in a modular fashion enabling users to extend it with additional modules.


Haka Tool Suite

Haka provides a collection of four tools:

    • haka. It is the main program of the collection. It is intended to be used as a daemon to monitor packets in the background. Packets are dissected and filtered according to the specified security policy file. Haka takes as input a configuration file. For example, the following configuration sample file instructs Haka to capture packets from the interface eth0 using nfqueue module and to filter them using the policy file myrules.lua. This script file loads typically user-defined or built-in protocol dissectors and defines a set of security rules. Additionally, users can select the alerting and reporting module to be used and set some specific module options:
      # Select the haka configuration file to use
      configuration = "myrules.lua"
      # Optionally select the number of thread to use
      # By default, all system thread will be used
      #thread = 4
      # Select the capture model, nfqueue or pcap
      module = "packet/nfqueue"
      # Select the interfaces to listen to
      #interfaces = "any"
      interfaces = "eth0"
      # Select packet dumping for nfqueue
      #dump = yes
      #dump_input = "/tmp/input.pcap"
      #dump_output = "/tmp/output.pcap"
      # Select the log module
      module = "log/syslog"
      # Set the default logging level
      #level = "info,packet=debug"
      # Select the alert module
      module = "alert/syslog"
      #module = "alert/file"
      #module = "alert/elasticsearch"
      # Disable alert on standard output
      #alert_on_stdout = no
    • hakactl. This tool allows controling a running Haka daemon. One can get live statistics on captured packets, inspect logs or simply shutdown/restart the daemon.
    • hakapcap. This tool allows replaying a policy file offline on a packet capture trace using the pcap module. For instance, this is useful to perform network forensics.
    • hakabana. This tool allows visualizing and monitoring network traffic in real time using Kibana and Elasticsearch. Hakabana consists in a set of custom security rules that pushes information about the traffic that passes though Haka on an elastisserach server and made them available through a Kibana dashboard. An additional dashboard is also available to visualize Haka alerts.

Kibana dashboard to visualize alertsKibana dashboard to monitor network trafic

Writing security rules

Haka provides a simple way to write security rules in order to filter, modify, create and inject packets and streams. When a flow is detected as malicious, users can report an alert or drop the flow. Users can define even more complex scenarios to mitigate the impact of an attack. For instance, one can alter http requests to force obsolete browsers to update or forge specific packets to fool scanning port tools.

Packet Filtering

The following rule is a basic packet filtering rule that blocks all connections from a given network address.

local ipv4 = require("protocol/ipv4")
local tcp = require("protocol/tcp_connection")

local net = ipv4.network("")

    hook = tcp.events.new_connection,
    eval = function (flow, pkt)
        haka.log("tcp connection %s:%i -> %s:%i",
            flow.srcip, flow.srcport,
            flow.dstip, flow.dstport)

        if net:contains(flow.dstip) then
                severity = "low",
                description = "connection refused",
                start_time = pkt.ip.raw.timestamp

The first lines load the required protocol dissectors, namely, ipv4 and tcp connection dissectors. The first one handles ipv4 packets. The latter is a stateful tcp dissector that maintains a connection table and manages tcp streams. The next line, defines the network address that must be blocked.

The security rule is defined through haka.rule keyword. A security rule is made of a hook and a evaluation function eval. The hook is an event that will trigger the evaluation of the security rule. In this example, the security rule will be evaluated at each tcp connection establishment attempt. The parameters passed to the evaluation function depend on the event. In the case of new_connection event, eval takes two parameters: flow and pkt. The first one holds details about the connection and the latter is a table containing all tcp (and lower layer) packet fields.

In the core of the security rule, we log (haka.log) first some information about the current connection. Then, we check if the source address  belongs to the range of non-authorized IP addresses defined previously. If this test succeeds, we raise an alert (haka.alert) and drop the connection.  Note that we reported only few details in the alert. One can add more information such as the source and the targeted service.

We use hakapcap tool to test our rule filter.lua on a pcap trace file filter.pcap:

$ hakapcap filter.lua filter.pcap

Hereafter, is the output of Haka which dumps some info about loaded dissectors and registered rules. The output shows that Haka succeeded to block connections targeting address:


In the above example, we have defined a single rule to block connections. One can write a complete firewall-like rule set using the haka.group keyword. In this configuration case, one can choose a default behavior (e.g. block all connections) if none of the security rule belonging to the group explicitly authorizes the traffic.

Packet Injection

In Haka, one can create new packets and inject them. The following rule crafts an RST packet in order to fool a Xmas nmap scan. As as result, nmap will conclude that all ports are closed on target side.

raw = require("protocol/raw")
ipv4 = require("protocol/ipv4")
tcp = require("protocol/tcp")

haka.rule {
    hook = tcp.events.receive_packet,
    eval = function(pkt)
        local flags = pkt.flags
        -- test for xmas nmap scans
        if flags.fin and flags.psh and flags.urg then
            -- raw packet
            local rstpkt = raw.create()

            -- ip packet
            rstpkt = ipv4.create(rstpkt)
            rstpkt.ttl = pkt.ip.ttl
            rstpkt.dst = pkt.ip.src
            rstpkt.src = pkt.ip.dst

            -- tcp packet
            rstpkt = tcp.create(rstpkt)
            rstpkt.srcport = pkt.dstport
            rstpkt.dstport = pkt.srcport
            rstpkt.flags.rst = true
            rstpkt.flags.ack = true
            rstpkt.ack_seq = pkt.seq + 1

            -- inject forged packet and
            -- drop malicious scanning packet

Packet Altering

Packet modification is one of the most advanced feature of Haka. Haka handles automatically all internal modifications at stream and packet level: resizing and fragmenting packets, resetting sequence numbers, etc. The following example shows how easy it is to access and modify protocol fields. This rule alters some headers of http protocol. More precisely, the user-agent header will be modified (or added to the list of headers if not set), and the accept-encoding header will be removed.

local http = require("protocol/http")


    hook = http.events.request,
    eval = function (flow, request)
        request.headers["User-Agent"] = "HAKA User Agent"
        request.headers["Accept-Encoding"] = nil

blurring-the-web and inject_ponies are funny scripts that alter http response traffic in order to blur and pollute (inject garbage) requested web pages, respectively:


Stream Filtering

Before presenting stream filtering, we will present first how Haka manages packets and streams internally. In Haka, all packets and streams are represented by virtual buffers (see figure below). Virtual buffers are a unified view of non-adjacent blocks of memory. They allow an easy and efficient modification of memory data. Virtual buffers use scattered lists to represent non-contiguous chunks which avoids allocating and copying superfluous block of memory. Haka provides iterators to navigate through these blocks of memory. These iterators could be blocking which would enable some functions to suspend and then resume transparently their execution when more data is available on the stream for instance.

vbufferThe following rule collects http streams and dumps them on stdout. This rule is equivalent to the “follow tcp stream” feature of Wireshark.

local ipv4 = require('protocol/ipv4')
local tcp_connection = require('protocol/tcp_connection')

    hook = tcp_connection.events.receive_data,
        options = {
            streamed = true
    eval = function (flow, iter, dir)
        local data = flow.ccdata or {}
        flow.ccdata = data

        while iter:wait() do
            data[#data+1] = iter:sub('available'):asstring()
        haka.log("%s -> %s:\n", flow.srcip, flow.dstip)

Interactive Packet Filtering

Wait, it’s like gdb but for packets !! – Anonymous Haka user

This is my favorite feature of Haka. It allows inspecting the traffic packet per packet. All the magic starts with the following rule which will prompt a shell for each http POST request.

local http = require("protocol/http")


haka.rule {
    hook = http.events.request_data,
    eval = function (http, data)
        haka.interactive_rule("interactive mode")(http, data)

haka.rule {
    hook = http.events.request,
    eval = function (http, request)

The shell gives access to the full Haka API to play with packet content: accessing and modifying packet fields, dropping packets, logging suspicious events, alerting, etc. The Lua console supports auto-completion and therefore is a good starting point to dive into the Haka API.

As shown by the following output, Haka breaks on the first POST request. Http data are available through the inputs variable. In this example, we alter the user credentials on the fly.


Note that it is best to use the interactive rule on pcap files as the edition will add a substantial delay.

Advanced Stream Filtering

Haka features a pattern matching engine and disassembler modules. These two modules are stream-based which enables us to detect a malicious payload scattered over multiple packets for instance. The following rule, uses a regular expression to detect a nop sled. We enable the streamed option which means that the matching function will block and wait for data to be available to proceed with matching. If a nop sled is detected, we raise an alert and dump the shellcode instruction. Note that the pattern matching function updates the iterator position which points afterwards to the shellcode.

local tcp = require("protocol/tcp_connection")

local rem = require("regexp/pcre")
local re = rem.re:compile("%x90{100,}")

local asm = require("misc/asm")
local dasm = asm.new_disassembler("x86", "32")

    hook = tcp.events.receive_data,
        options = {
            streamed = true,
    eval = function (flow, iter, direction)
        if re:match(iter, false) then
            -- raise an alert
                description = "nop sled detected",
            -- dump instructions following nop sled

Replaying this rule on the well-known network forensic challenge results on the following output. More details about disassembling network traffic into instruction are available here.


To be continued …


Low-cost point of sales (PoS) hacking

Hacking point of sales (PoS) systems is a very trendy topic. A lot of PoS malware can be found in the wild (jackPOS, gamaPOS, Backoff, FighterPOS…). At every big breach of PoS systems, media talk about sophisticated attacks involving high skills and great tools. But sometimes, it can be very easy to compromise a PoS and no particular skills are required to steal sensitive information, such as credit card numbers.
During our investigation, we caught a very interesting case of “low-cost” PoS hacking. This article tries to unveil the inner process of infection.

Everything started with a Win32.Ardamax sample found in the wild. Ardamax is a classical sample which is a commercial keylogger available on the Internet.
After reversing this sample, it appears that the malware uploads data on a FTP server hosted in Germany, on server4you. This FTP can easily be accessed (login and password are embedded in the sample) and contains victims’ uploaded data.
This FTP seems to be used since the 9th of October 2014. The server is full of samples, tools and exfiltrated data.
We cannot publish the original sample, because Server4you has not shutdown the server yet.
Exfiltration server
This repository contains the original Win32.Ardamax sample, malwares (Darkomet, Andromeda, Gorynych…), some memory scrappers to retrieve credit card numbers and websites crawlers scan results.
On the same repository, we can find screenshots, microphone recordings, webcam pictures as well as keystroke recordings for each single infected computer.
Keylog result
Crooks have access to about fifteen point of sales computers as well as to some SCADA systems.

Belgium SCADA
Belgium SCADA
Cinema PoS
Cinema PoS
Brazilian gas pump
Brazilian gas pump

We spent a lot of time contacting CERTs and companies for cleaning computers but day after day new infected point of sales data were uploaded to the FTP repository.
How were crooks able to continuously find new targets to infect?
Amongst uploaded data, some screenshots caught our attention: somebody was using a VNC brute force tool against a large range of IP addresses.

The tool used by crooks can be retrieved from an archive uploaded to the VirusTotal website:
It seems they are using infected computers to brute force VNC servers with weak passwords . When a new VNC connection is established, a new payload is downloaded through a regular browser and installed on the newly infected machine. No exploit or sophisticated techniques are employed.

Gorynych installation
Gorynych installation

Once the payload is downloaded, any installed antivirus is configured to ignore it or is even completely uninstalled. This requires administration rights on the computer, but obviously this is quite a common situation on point of sales systems.

This day, it is Gorynych which was spreading: https://www.virustotal.com/fr/file/406c30d40f3837615e3b393edc1d6667213c3d287ec006be6198d68124041d43/analysis/
Last but not least, crooks used compromised computers to administrate the Gorynych panel:

During several days we followed the whole stealing process. Crooks infected point of sales and used mainstream memory scrappers like SearchforCC for credit card numbers exfiltration.
As we can see, there is no need of sophisticated attacks or processes to infect systems. With a little more time, crooks would be able to infect a much larger range of systems. With a short list of 152 weak passwords, an attacker is able to control a lot of point of sales systems. In this case, crooks access from small and medium-sized enterprises to companies with 500 million dollars in annual sales.
This kind of campaign would not be so easy to carry out if:
• Point of sales computers were not directly connected to the Internet;
• Strong VNC passwords were used;
• Administrator accounts were not used to connect to sensitive systems.
This kind of negligence can result in a huge waste of money and a very bad image for the compromised company.


Payload found on the FTP site

1edc2a1c19a6deb330f21eb0f70d6161 a.exe
6b5ea21045e2c689f6f00e6979955e29 al.exe
4645b7883d5c8fee6579cc79dee5f683 ares.exe
9d87838b7de92cfa5675a34f11d3e7e1 b1.exe
af13c28f32b47423bfebb98de3a7d193 b2.exe
bf395a47eac637f0b2b765ba91d914c7 b3.exe
af36ed9267379f86fc12cc0cfc43938e bm.exe
57138e9fd20b9b93129ed599062bd379 cn.exe
f8058abb53ae90512b3da787bb25a21e dx.exe
0762764e298c369a2de8afaec5174ed9 fgdump.exe
9e76d363a7f93a2ef22483ce1866e8ee gt.exe
413ba3a4705504e528ce05c095cbc8a5 loader.exe
abd788f868ff4a96b91846dd46c9e701 mircpsy.exe
255daa6722de6ad03545070dfbef3330 mmon.exe
cc074e5542c0daca3d9b261dc642bfaa n.exe
85e5727d23ab417a1d05ce656de358b6 new(1)text.exe
79c8661bd5e69df5bb94032a356adc33 nyf1.exe
f461873a10a4b49197a822db88b707fa PowerGrep4.exe
467dc270f0d0619dbd1dfcc554da5f8b private.exe
10c7cdc821291921a957b94b101524af prv.exe
619e2172359cfff98f3124bdd4d9eeb5 q.exe
7c44933863109c101a52c04544626b7f r.exe
780fe52363ec0745da43fc6776f0be8c Spark.exe
af5aac5ef503c929db12d8e031788321 spy.exe.exe
2976768953979e045c1b5773de29e230 sweet.exe
5f6158cbfc5b2f80ad2ebcbeebfd1562 t2s.exe
30a9088df5a7586ca418cb1600ac8683 x64.exe
ef295b49ac6d6e6a4a43b5af75584830 zip.exe

Related servers