Personal tools
You are here: Home Technical analysis of 2X/Terminal-Services.Net's GPL violation
Document Actions

Technical analysis of 2X/Terminal-Services.Net's GPL violation

Introduction

The UK based company 2X Software Ltd. violates the GPL by not providing source code for two of its products, LinRDP and DOSRDP. These products were acquired into 2X Software Ltd. when it merged with the company Terminal-Services.net.

LinRDP and DOSRDP are derived from rdesktop (http://www.rdesktop.org), an application that allows UNIX clients to connect to RDP servers. rdesktop is licenced under the GPL which requires any derived works to make the source code readily available.

Both Terminal-Services.Net and 2X Software Ltd. have been contacted on several occasions with requests for the source code. They have at no point outright refused this request, but they have kept on stalling, asking for more time. It has now been more than two years since the initial request so it is evident that they have no intention of complying with the GPL.

This document describes the technical details of the violation with complete instructions on how to repeat the analysis. As you will see, there is no doubt that Terminal-Services.Net has severely infringed on the copyright of the rdesktop authors and that 2X Software Ltd. continues to violate the GPL by not releasing the source. They have not yet denied that they have taken code from rdesktop. This document makes sure they will not do so in the future.

Prerequisites

To perform the analysis, a number of tools and programs are required.

Preparing the binary

The infringing binaries are not plain ELF or DOS MZ executables, but compressed versions. To be able to perform any analysis, these must first be decompressed.

To decompress the Linux binary, which is compressed using UPX, do the following:

$ upx -d lindesk
                     Ultimate Packer for eXecutables
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
UPX 1.25         Markus F.X.J. Oberhumer & Laszlo Molnar        Jun 29th 2004

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
    353216 <-    103196   29.22%    linux/386    lindesk

Unpacked 1 file.

The DOS binary is compressed using PKLITE. There doesn't seem to be any decompressors for UNIX, so you'll need a DOS/Windows machine or Wine to uncompress the binary.

The UNP tool can successfully decompress the file:

H:\TERMI~PT.NET\DOSRD~8G>unp G2.EXE G2_REAL.EXE

UNP 4.12 Executable file restore utility, written by Ben Castricum, 05/19/97

processing file : G2.EXE
DOS file size   : 127106
file-structure  : executable (EXE)
EXE part sizes  : header 160 bytes, image 72773 bytes, overlay 54173 bytes
processed with  : PKLITE V1.50 <L>
action          : decompressing... done
new file size   : 277533
writing to file : G2_REAL.EXE

Signs of infringment

There are so many commonalities between rdesktop and the infringing programs that there is no doubt about where the code comes from. We'll start off with the blatantly obvious and move on to the plausibly deniable.

The most common way of finding infringment is looking at the embedded strings, something that holds true for this project aswell.

Isolating relevant strings

First we'll start by isolating actual, static string data. This is contained in the ".rodata" segment of an ELF binary:

$ objdump -h lindesk

lindesk:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn

...

 13 .rodata       00008640  08088320  08088320  00040320  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

...

$ dd if=lindesk of=lindesk.rodata bs=1 count=34368 skip=262944
34368+0 records in
34368+0 records out

We do this to avoid false strings in the code segments and to avoid the names of external symbols. Since this is a dynamically linked executable it isn't likely that we have any strings from external libraries in here.

We repeat the procedure with rdesktop (your offsets may vary here depending on your compiler and environment):

$ objdump -h rdesktop

rdesktop:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn

...

 13 .rodata       00002671  0806772c  0806772c  0001f72c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

...

$ dd if=rdesktop of=rdesktop.rodata bs=1 count=9841 skip=128812
9841+0 records in
9841+0 records out

To produce text files with just the strings we pipe these dumps through the strings program:

$ strings lindesk.rodata > lindesk.strings

$ strings rdesktop.rodata > rdesktop.strings

The DOS format isn't as flexible so there we'll have to deal with the junk:

$ strings G2_REAL.EXE > G2.strings

lindesk - The Linux client

We'll start off by looking at the Linux client. Since rdesktop is written for UNIX, this is the version that contains the most obvious examples of infringment.

Program parameters

We start off by comparing the usage output (we run the program instead of looking at the strings dump to make sure we get the order right):

$ ./lindesk -h
linux  client for windows terminal services.
See http://www.terminal-services.net / for more information.

Usage: ./lindesk [options] server[:port]
   -u:  user name
   -d:  domain
   -s:  start program
   -c:  start directory
   -p:  password
   -n:  client hostname
   -z0: disable sound
   -z1: normal quaility sound
   -z2: high quaility sound
   -t:  color depth
   -f:  full-screen mode
   -g:  desktop width & height (WxH)
   -k:  keyboard language layout 1033=en_us,1034=Spanish,1031=Germany,1036=French
   -k help: keyboard language layout seting
   -K:  disable grab keyboard
   -i: ="printer name;printer driver;local print command"
   -D: ="map drive path;drive name"
   -M: ="map drive path(with auto mount);drive name"
   -S: ="Serial port name;local serial path"
   example:
   lindesk -g800x600 -k1034 -z2 -t16 -i="printer;EPSON Stylus C41 Series;lpr -l -p" -D="/root;H" -M="/mnt/cdrom;F" -S="COM1;/dev/ttyS0" 192.168.0.1

$ ./rdesktop -h
rdesktop: A Remote Desktop Protocol client.
Version 1.4.1. Copyright (C) 1999-2005 Matt Chapman.
See http://www.rdesktop.org/ for more information.

Usage: ./rdesktop [options] server[:port]
   -u: user name
   -d: domain
   -s: shell
   -c: working directory
   -p: password (- to prompt)
   -n: client hostname
   -k: keyboard layout on server (en-us, de, sv, etc.)
   -g: desktop geometry (WxH)
   -f: full-screen mode
   -b: force bitmap updates
   -L: local codepage
   -B: use BackingStore of X-server (if available)
   -e: disable encryption (French TS)
   -E: disable encryption from client to server
   -m: do not send motion events
   -C: use private colour map
   -D: hide window manager decorations
   -K: keep window manager key bindings
   -S: caption button size (single application mode)
   -T: window title
   -N: enable numlock syncronization
   -X: embed into another window with a given id.
   -a: connection colour depth
   -z: enable rdp compression
   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)
   -P: use persistent bitmap caching
   -r: enable specified device redirection (this flag can be repeated)
         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1
             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1
         '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share
             or   'floppy=/mnt/floppy,cdrom=/mnt/cdrom'
         '-r clientname=<client name>': Set the client name displayed
             for redirected disks
         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1
             or      LPT1=/dev/lp0,LPT2=/dev/lp1
         '-r printer:mydeskjet': enable printer redirection
             or      mydeskjet="HP LaserJet IIIP" to enter server driver as well
         '-r sound:[local|off|remote]': enable sound redirection
                     remote would leave sound on server
   -0: attach to console
   -4: use RDP version 4
   -5: use RDP version 5 (default)

Some similarities, some differences. Highly suspicious but not that conclusive since the commonalities are fairly common expressions.

But lets have a look at the string passed to getopt():

  • lindesk: "u:d:s:S:c:p:n:k:g:t:z:i:fbeEmCKT:D:M:0h?"
  • rdesktop: "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?"

Now things aren't that innocent anymore. Feel free to note that many of the options in lindesk's string isn't even mentioned in the usage output.

If we check out an older version of rdesktop.c, closer to the time that lindesk was first seen, we see this string:

  • old rdesktop (Thu Oct 9 04:21:19 2003 UTC): "u:d:s:S:c:p:n:k:g:a:fbeEmCKT:D045h"

The chance of getting almost identical order of getopt() flags and flags that are only present in rdesktop is left as an exercise to the reader.

Keysym mappings

A large portion of the strings in lindesk are mappings between X11 keysyms and scan codes:

dead_cedilla 0x29
ssharp 0x28 altgr
Cacute 0x28 shift
Cyrillic_SOFTSIGN 0x32 shift altgr
F6 0x40 localstate
s 0x1f addupper

These can not be found in the rdesktop binary, but they can be found in included keysyms files included with rdesktop:

keymaps/sl:dead_cedilla 0x29
keymaps/sl:ssharp 0x28 altgr
keymaps/sl:Cacute 0x28 shift
keymaps/ru:Cyrillic_SOFTSIGN 0x32 shift altgr
keymaps/common:F6 0x40 localstate
keymaps/common:s 0x1f addupper

This is a unique syntax developed for rdesktop and not inherited from some previous source. Although the syntax is simple it is not probable that lindesk would happen to develop the exact same keywords and the same order of multiple keywords.

Swedish strings in lindesk

lindesk contains two strings in Swedish (meaning "normal time" and "summer time"):

GTB, normaltid
GTB, sommartid

Very strange for a company based in Malta that, until recently, had no connection with Sweden (they now have a Swedish reseller).

The same strings appear in rdesktop and was added there by a developer here at Cendio AB. This string was seen during reverse engineering of Microsoft's RDP client and its meaning is not fully understood. It only appears if you're running a Swedish version of Windows though.

So if Terminal-Services.Net got this string through similar reverse engineering, they must have been running a Swedish Windows. Not impossible but not very probable for a company based in Malta.

Assorted strings

It should be fairly obvious where lindesk got most of its code from by now, but we'll do a few more just to drive the point home.

  • lindesk: "We don't support INCR transfers at this time. Try cutting less data."
  • rdesktop/xclip.c (until Mon Jun 27 12:18:48 2005 UTC): "warning("We don't support INCR transfers at this time. Try cutting less data.\n");"
  • lindesk: "Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints"
  • rdesktop/xwin.c: "warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");"
  • lindesk: "this shouldn't be happening"
  • rdesktop/vnc/vnc.c: "error("this shouldn't be happening\n");"

G2.EXE - The DOS client

The DOS client isn't as rich with rdesktop strings as lindesk. This is understandable since the strings we've found so far are related to X11 or getopt() (which is part of glibc).

Swedish strings in G2

There is one part that is present in both the DOS and Linux client though, the suspicious Swedish strings. Considering how these strings were found, it is likely that the DOS client is also derived from rdesktop.

Symbol names

The linker used for the DOS executable doesn't seem to strip symbols from the final binary so the file is filled with names of global functions and variables.

Comparing with rdesktop, we can find a lot of common names:

_iso_init
_iso_send
_iso_recv
_iso_disconnect
_cache_put_cursor
_cache_get_cursor
_cache_get_text
_cache_put_text
_cache_put_font
_cache_get_font
_rdp_connect
_rdp_disconnect
_licence_generate_keys
_licence_process
_sec_hash_48
_sec_hash_16
_buf_out_uint32
_sec_sign
_sec_init
_sec_send
_sec_recv
_sec_connect
_sec_disconnect
_mcs_init
_mcs_send
_mcs_recv
_mcs_connect
_mcs_disconnect
_MD5_Init
_MD5_Update
_MD5_Final
_xtcp_init
_xtcp_send
_xtcp_recv
_xtcp_connect
_generate_random
_bitmap_decompress
_ui_set_colourmap
_ui_draw_glyph
_ui_draw_text
_ui_set_cursor
_ui_rect
_ui_line
_ui_patblt
_RC4_set_key
_SHA1_Init
_SHA1_Update
_SHA1_Final

That's 48 occurences right there. For those of you unfamiliar with C name mangling, all symbols get prefixed with "_" by the C compiler. So to find "_ui_set_cursor" you search for "ui_set_cursor".

The "xtcp_*" can not be found in rdesktop, but if you remove the "x" then all four can be found. It is likely that these were renamed to avoid conflicts with the TCP library required for the DOS client.

There is also a series of symbol names that match global variables in rdesktop:

_rdp_shareid
_next_packet
_licence_issued
_out_sig
_crypt_hwid
_hwid
_decrypt_token
_out_token
_sealed_buffer
_username
_hostname
_password
_keylayout
_bitmap_compression
_orders
_encryption
_desktop_save

That's another 17 common names there. rdesktop recently added the prefix "g_" to all global names, so take this into account when comparing.

Conclusions

There is no doubt in our minds that 2X infringes on the copyright of the rdesktop authors and violates the GPL by not releasing the source code. The number of identical strings in rdesktop and their products are to numerous to write off as coincidence.