Author Archive for


Android: Connecting apps to Tor hidden services

I’ve had to re-learn how to do this every time I setup a new phone, so I’m putting the instructions here for me to find next time it comes around.

Things you’ll need:

  1. Root access to your Andorid device (free in CyanogenMod!)
  2. Orbot app
  3. Hosts Editor app


  • Setup Orbot to do Transparent Proxying. Then, hit Select Apps to pick the apps you want to go through Tor.
  • Scroll down to the bottom of the Orbot Settings menu, and pick Torrc Custom Config. Here, we’re going to add custom entries for each hidden service we want to connect to:
MapAddress hiddenserviceaddress1.onion
MapAddress hiddenserviceaddress2.onion
  • Restart Orbot

At this point any proxied app should be able to connect to and reach the service. But it’s nice to be able to connect to the name, so let’s keep going

  • Go into Hosts Editor
  • Create entries that match our MapAddress entries
  • Make sure Hosts Editor retains the entries after it’s done, you might have to manually tell SuperUser to Allow it.
  • Now in your app, you can connect to hidden services by connecting to the .onion address.

This method should survive updates to the Orbot app (previous methods did not) but the hosts files entries may not survive an OTA Android update.


GPG-Encrypting your incoming mail using Postfix and Google Apps

I’ve recently chosen to take more control over my data when it’s stored in the cloud. Some big parts of that data are my email accounts. Like most geeks, I have a few “vanity” domains that I receive email at. Also like most geeks, I host them on Google Apps. So, I’ve decided to encrypt all incoming emails before they get stored on Google’s servers.

I searched around for methods of implementing this, but many used Exim or Procmail. I’m partial to Postfix myself, I like they’re privilege separation model. I was running up blanks, until I stumbled upon This project is a very straightforward filter to GPG encrypt mail if a recipient’s key is locally stored. Getting this operational on Ubuntu was easy.

Creating a mail forwarder

First, I installed Postfix with a blank configuration. Then, to create a basic forwarder configuration I made /etc/postfix/

myhostname = forwarder.DOMAIN.COM
mydomain = localhost
myorigin = $mydomain
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, $mydomain
mynetworks_style = host
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
append_dot_mydomain = no
readme_directory = no
relay_domains = DOMAIN.COM
transport_maps = hash:/etc/postfix/transport

Next I needed to make /etc/postfix/transport:


And due a slight bug in Ubuntu’s blank configuration, I needed to make an aliases db:

echo 'postmaster: root' >> /etc/aliases

Restart Postfix:

service postfix restart

At this point I changed my DNS to point the MX record to this server. I sent a test email to ensure fowarding worked.

Installing the GPG encryption filter

You’ll want to install gpg, then install GPG-Mailgate:

cd /root
hg clone
cd gpg-mailgate

From here I mostly followed the steps from INSTALL, but they’re a bit dated and didn’t quite work for me. Here’s the short version, my apologies for the lazy instructions, make sure you replace the python version below with the version that’s live on your system:

cp -R GnuPG /usr/lib/python2.6/
vi /usr/lib/python2.6/GnuPG/

Above, we need to add “–trust-model always” to the command in line 43. Otherwise GPG throws an error about not trusting the key and fails to encrypt messages.

cp gpg-mailgate.conf.sample /etc/gpg-mailgate.conf
vi /etc/gpg-mailgate.conf

In /etc/gpg-mailgate.conf, modify the domains variable to include all domains you want to encrypt messages for. Then, if you have mail aliases, you’ll probably want to add entries under [keymap] in the format email = longKeyID. Leave keyhome as default.

After this is done, we need to get the public keys we want to use for encryption. We can take advantage of Postfix’s privilege separation here:

adduser -s /bin/false -d /var/gpg -M gpgmap
mkdir -p /var/gpg/.gnupg
chown -R gpgmap /var/gpg
chmod 700 /var/gpg/.gnupg

The next command needs to be repeated for each email address you want to encrypt mails for. If you want an email alias encrypted with a key, use the keymap section of the config file above.

sudo -u gpgmap /usr/bin/gpg --homedir /var/gpg/.gnupg --keyserver hkp:// --search myemail@DOMAIN.COM

Then, we’ll need to tell Postfix to have a filter that calls the external script, and a channel to accept mail from the script after it’s encrypted. The following goes in /etc/postfix/, keep in mind that I’m using a different username than the INSTALL directions do (this part gets a bit wide, you may need to expand your viewing window):

gpg-mailgate    unix    -       n       n       -       -       pipe
        flags= user=gpgmap argv=/usr/local/bin/ inet    n       -       n       -       10      smtpd
        -o content_filter=
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
        -o smtpd_helo_restrictions=
        -o smtpd_client_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks=
        -o smtpd_authorized_xforward_hosts=

And then we tell Postfix to use the filter by running this quick command to add a line to /etc/postfix/

echo 'content_filter = gpg-mailgate' >> /etc/postfix/

Restart Postfix:

service postfix restart

With all that, you should find that a test email sent to the email address you specified ends up in your Google inbox encrypted with your gpg key. This works perfectly with a PGP-capable IMAP client, such as Thunderbird or K-9 Mail on Android.


As an added bonus, I threw together an apparmor profile. If your system uses AppArmor, you can place the following in /etc/apparmor.d/ — keep in mind that you’ll need to match the version of python below with the version used on your system.

#include <tunables/global>

/usr/local/bin/ {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/python>

  /usr/bin/python2.6 ix,
  /usr/include/python2.6/pyconfig.h r,
  /usr/lib/python2.6/GnuPG/__init__.pyc r,
  /usr/local/bin/ r,
  /usr/bin/gpg Cx -> gpg,

  /etc/gpg-mailgate.conf r,
  /etc/default/apport r,
  /tmp/gpg-mailgate.log rw,

  profile gpg {
    #include <abstractions/base>
    #include <abstractions/nameservice>
    /usr/bin/gpg r,

    /var/gpg/.gnupg/* r,
    /var/gpg/.gnupg/.* w,
    /var/gpg/.gnupg/trustdb.gpg w,
    /var/gpg/.gnupg/random_seed wk,

Then just run the following to activate the profile:

aa-enforce /etc/apparmor.d/

I found that I still get one apparmor warning, about it wanting to unlink the GnuPG library, which I thought was odd so I didn’t write a rule for it. If this bothers you, add a ‘d’ beside the ‘r’ for that line. Obviously debugging AppArmor is out of scope for this blog post, but there are plenty of useful resources that are just a Google search away.

Edit: I am not at all confident that this AppArmor profile improves the security of using the gpg-mailgate script. Use at your own risk, etc.

Anyways, there you have it. Now all your mail is encrypted before it hits Google’s server for data mining. There’s probably a double-encryption bug that needs to be worked out, and outgoing mail won’t be stored encrypted, but we can at least regain a little bit of control over the data we store in the cloud.


TextSecure 201

This post is about Whisper SystemsTextSecure app for Android (currently version 0.5.7, available through the market). It’s an encrypted SMS client that supports both local encrypted storage and over-the-wire encryption of messages. Wire encryption is done using a modified version of Off-The-Record (OTR) messaging, in use by Pidgin and Adium chat clients.

This post assumes some knowledge of OTR, and will go through how to take advantage of TextSecure’s security features. While some of these instructions are available through TextSecure’s wiki, I found them to be terse and not quite usable as-is for everyone.

After installing TextSecure, you’ll be prompted to enter a password. This password is used to encrypt your local message database and your keys. It will then generate your keys.

To see your public key, you can go to Settings->View My Identity Key. If you have your address book synchronized with Gmail or Google Apps, highly recommend you create an address book entry for yourself, and go to Settings->Choose Identity, then Settings->Export My Identity Key. This creates an entry in your address book with your public key. The entry is an IM-type entry with key TextSecure-IdentityKey and the value is the base64’d (public) identity key.

For normal operation, you can text as normal. It’s a regular SMS app. However, if your SMS buddy also has TextSecure, this the app will detect it and ask if you’d like to initiate a key exchange. After a successful key exchange, you should see a red lock at the top of your chat window, and a lock beside each sent & received SMS message. This is the equivalent of OTR’s “Unverified” status. It means that the current chat is encrypted, but we’re not sure if there is someone doing a Man-in-the-Middle attack or not.

TextSecure offers a few ways to handle key verification. The simplest is to, from the chat window, select Menu->Secure Session Options->Verify Recipient Identity. This is useful if you have the other person’s identity key in text format. If you are in person, there’s a slightly cooler way to verify: both parties should click Compare, with one of them picking Get My Key Scanned and the other picking Scan their key to compare. This will allow you to scan QR codes to verify. After verification, switch roles so the other person verifies too.

There’s another way to verify identity keys, but it’s slightly more complicated. You’ll recall how we exported our public key into our address book. We can also import from the address book. Go into Google Contacts and find your entry; it should have an entry titled TextSecure-IdentityKey. Copy the base64 text, and send that to the other person through a secure channel: OTR-encrypted chat or PGP-signed mail are good examples of this. Now, taking the other person’s base64’d key, go to their entry in your address book. Click the Add button, and select Instant Messaging. With that new field, pull it down so the left-hand side says Custom, and type in TextSecure-IdentityKey. The right-hand side should be the base64’d text they sent you. Now that you have their key, go back into TextSecure. Go to Settings->Import Contact’s Key and find their address book entry. You’ll be prompted to verify, so compare these numbers against what you’ve got in the message screen. This may seem like a long-way around just to verify, but may be very useful if you use an app such as Bump to transfer address book entries to other people. If someone has given you a base64’d key, and you’re having difficulty importing into the address book, you can manually verify this by issuing a simple *nix command:

echo '<base64 string>' | base64 -d | xxd
echo '<base64 string>' | base64 -d | hexdump -C

(One of my systems had hexdump and not xxd for some reason)

No matter how you verify, you should see a blue lock at the top of the messaging screen when you have a verified key for that person. This is equivalent to Pidgin-OTR’s “Private” designation.

A note for those with multiple devices. You probably don’t want to have multiple identity keys floating around, it gets annoying for verification. My suggestion is to select one of your devices that you want to copy the key from, and use TextSecure’s Export To SD Card feature. Now, on the second (or additional) device, you can copy the exported directory to that device’s sd card, and select Import From SD Card. This will wipe any TextSecure settings on the second device, but will import your private keys, your SMS messages, and your friends’ identity keys. Once these two devices are running, I recommend using the address book for tracking identity keys, so they can be easily imported into both devices.

Finally, a note to my fellow Canadians: Bell Mobility mangles multi-part SMS messages, resulting in broken key exchange messages. TextSecure *will not work* on Bell Mobility.


Things I Learned About My Nexus S

[This was written August 14th, but I got lazy and didn’t post it. Please keep that in mind when the tense doesn’t make sense.]

If you follow my twitter, you’ll notice that in the past week I’ve been complaining about my phone. So, I wanted to write some things down that may help others in the future.

I have a Nexus S purchased from Koodo running on Bell Canada. In the US, I was using a prepaid AT&T SIM card. I was/am running WhisperCore 0.5.2 which runs Android 2.3.4 underneath.


  • On a full charge, my phone normally gets me through 14-18 hours of occasional use.


  • Purchased an AT&T prepaid SIM on Thursday. 100MB and 7 days of talk & text.
  • On Saturday night, just after midnight, my phone ran out of data. This meant I had used 100MB of data in under 3 days. Unlikely, but possible.
  • Despite charging it overnight, on Sunday my phone died around 4pm. Highly unusual.
  • Sunday night I plugged it in again, yet on Monday my phone died while at the airport. What the hell!?
  • Monday I noticed that my search button kept being “pressed”, the backlight on the button dims and the phone vibrates. This triggered the Voice Search feature.
  • I used WhisperCore’s firewall to block the HTTP requests being made by the search application. From then on it just hangs and then fails.
  • Debug logs showed that *something* was triggering a android.intent.action.SEARCH_LONG_PRESS action. This was causing Voice Search to launch.
  • Deciding that my phone had malware on it, I wiped the data from it. Phantom search button problem still occurs.
  • I used Clockworkmod ROM Manager to restore back to Android 2.3.1 (all I could find at the time).
  • Now my SIM card isn’t working. Other SIM cards didn’t work either. No clue what happened.
At this point my phone has Baseband I9020XXKD1 and Bootloader I9020XXKA3.
  • I tried to flash a new ROM (Clockworkmod again) and bricked it. Stuck at the Google boot-up logo.
  • I found the official 2.3.4 ROM from Google’s site, and installed it. It worked, SIM cart and everything! Except…
  • The Phantom Search Button problem still occured!
  • I read some forums and found that people tried different radios to fix a similar problem.
  • I found a site that had the I9020XXKB3 Baseband, and used ‘fastboot flash radio’ to flash it.
  • Phantom Search Button problem has disappeared!
Today [August 14th] I’m back to WhisperCore 0.5.2 and everything is working. I have no idea what happened

LIGATT’s LocatePC — an update

It would seem my blog saw a spike in traffic over the past 24 hours, as some people on twitter found my review of Ligatt’s LocatePC. It could perhaps be related to this Full Disclosure post about an SQL injection vulnerability in the LocatePC software. Reading that post renewed my interest in analyzing LocatePC, so I thought I’d provide an update to the current status of version 1.05 of Ligatt Security’s software. It’s worth noting that since my last blog post on the matter, Ligatt now also offers an OSX version of LocatePC which I have not looked at.

Note: At no time did I run LocatePC. This examination is based purely on reversing the binaries available on the Ligatt Security website which are free to download.

The biggest change to note between 1.01 and 1.05 is that LocatePC actually connects back to their servers. Interaction between the software and the back-end database is actually occurring now when it wasn’t last June.

Second biggest change: it’s no longer using direct MySQL connections to interact with the database. Good work! I’ll happily take credit for that improvement in the software. Instead of a direct link to the database, it’s now using a web-based API that passes XML messages between client and server. It’s doing this over HTTPS, which should prevent any eavesdroppers from sniffing the traffic it sends.

I think enumeration of an API to be a pretty fun way to spend a couple of hours. Each API request is of the format { procedure, values, types } where “procedure” is a specific stored procedure in the MySQL back-end, “types” is an array of values “string”, “num” or “base64”, and “values” is an array of the data being described by types; the arrays “types” and “values” are the same length.

Comparing this to the old version of LocatePC, it seems that every query that was being done was replaced with an API call. This API is quite easily accessible, as demonstrated by the Full Disclosure post which connects directly to their API server. Most of the calls require some sort of shared secret to insert or retrieve data:

  • Registering a new user requires a license key
  • Registering a new install requires a user and password associated with a license key
  • Checking most information for an existing install requires knowing the 32-character secret (mentioned in the previous post)

However there looks to be a weak link in this chain of secrets. “spSelectProgramLoginByMacs” takes as an argument a string with one or more MAC addresses, and returns the 32-character shared secret used to uniquely identify a LocatePC installation. With the 32-character string, combined with knowledge of the MAC, one can execute any command that the LocatePC software itself could. Oh, and if you don’t have the correct MAC you can always run “spSelectUserMacByProgramLogin” which takes the 32-character identifier and returns the MAC address of the machine.

What this boils down to is the privacy and security of a LocatePC user is protected only by the secrecy of every one of their MAC addresses. And the LocatePC database not being compromised. And the user using unguessable username password combinations. And their registration code not being public. And them trusting the employees of Ligatt Security.

A list of stored procedures used by LocatePC follows. I leave it as an exercise to the reader to find nefarious combinations of functions, because frankly I’m bored of this shitty software.

  • spBackupPassword
  • spConfigCheckLogin
  • spConfigCheckLoginWithPlog
  • spDeleteDirectoryContents
  • spDeleteUserByAllMacs
  • spDeleteWatchedDirectory
  • spDelMacExe
  • spGetPermitKeylogWebcam
  • spInsertCheckinRow
  • spInsertKeylog
  • spInsertMacExe
  • spInsertUser
  • spInsertWatchedDirectory
  • spIsCamOn
  • spIsKeyloggerOn
  • spIsProgramLoginUnique
  • spIsUninstallOn
  • spSelectCheckIn
  • spSelectCurrentVersionIfNewer
  • spSelectCustomerJobs
  • spSelectCustomerTypes
  • spSelectFilesToDelete
  • spSelectFilesToUpload
  • spSelectFromMacexe
  • spSelectNewFiles <– this one takes no arguments are returns the URL for the latest version of LocatePC
  • spSelectOneUserWithRegCode
  • spSelectPasscodeAndHotkey
  • spSelectProgramLoginByMacs
  • spSelectRegCodeUninstall
  • spSelectShutdown
  • spSelectUserMacByProgramLogin
  • spSelectUserMessage
  • spSelectWatchedDirectories
  • spSelectWaysToHearAboutUs
  • spUploadImage
  • spUnsetUninstall
  • spUpdateCheckin
  • spUpdateDirError
  • spUpdateDirUploadTime
  • spUpdateHotkey
  • spUpdateLastLogin
  • spUpdateMacExe
  • spUpdatePasscode
  • spUpdatePermitKeylogWebcam
  • spUploadDirItem
  • spUploadFile
  • spUploadFileError

LocatePC – the LIGATT trojan

This is my first malware analysis, so feedback is welcome and encouraged. For now, it’s still legal to reverse engineer software in Canada, so until Bill C-32 gets passed I’m going to keep doing it.
I selected LocatePC, which was found on the LIGATT Security website. Downloading the ZIP file gives us two executables, the first is the installer, the other is the actual trojan. Both files are written in C#, compiled as .NET assembly. This software is a commercial product designed to stay resident on someone’s computer, and allow them to be notified in the event their computer is stolen. Both executables suffer from severe flaws, both in security and in usability. In cases where I’ve deemed appropriate, I’ve censored information; these omissions are left as an exercise for the reader to uncover.
The Installer
Upon launch, the installer immediately establishes a connection to a remote MySQL server:
new MySqlConnection(“Server=; Port=3306; Database=locate_pc; User=****; Password=****; Encrypt=true”);
This is a rookie coding mistake: hard-coding credentials into an application. With this information, anyone could login to that MySQL database and manipulate the data. Fortunately for LIGATT, a firewall is preventing the software from making a connection to the database. This causes the installer to immediately quit, giving the user a “Communication error” alert box.
Now, at this point it’s clear that the software doesn’t work. But using some reverse engineering, we can see what the rest of the program does. There’s no sense leaving any of it uncovered.
So, assuming we can connect to the database, the installer then fetches a list of all MAC addresses on this machine. This list of MACs is used right away to check the database to identify whether the trojan is installed on the computer. The installer then asks the user for a registration code, and if they don’t have one they are directed to purchase one from the LIGATT website. Once a valid registration code is given, it checks to ensure it has not expired, and that the maximum number of licenses have not been used.
We are then presented with a nice Menu, giving us the option to install the trojan. Upon clicking it, the installer creates a new directory (INSTALLDIR) to install the trojan to, with the following format:
C:\Windows\<random existing directory>\<random 32-bit int>\
The directory is assigned to be readable & writeable by Everyone, and is given the hidden attribute. It then selects a name for the trojan (EXENAME), from the following list:
wingfuw winnmji winvmnw winhkip winfmvy winttkz windcmv winvtek winpfbp winzfdn winvqun winvwkx winqjbi wingroi winnzfv winhlng winybpn winhcwt winecmz winqrxi winxpju winriia winhiwf winayct winfkcd windpxb winebte winbhpu winjcdy winsicz winfzyn winrgri winmylp winonfq winpqjf wincmws winmsex winvgsi winesrl winewiv winveha winufbq winrzcg windtup winxtlk windiqu winsggx winzqei winpesf winairh winfomi winecfi winvljm winpnvz winuyyb winznpy winvxhf winycqe winlqlx winuilq winleud wingfnh windmci winrseu winqecu winedhi winnwmb winpamg windhwh winvqby winqmhu winhxzu winnics winpixl windevl winxdsi winggjm winszpd wingoyy winykec winqmrp winejgy winvtzu winqbtd winwpxd winjjep winlcgv winydrq winevmy winxolq winzuew winbvzd winekyb winatwy wintkjg winvgon winjqyt winwazf winrymo winguwl winpxwi wincmst winfkow winvgze winqgzc winhxpu winnyeu winutki winbrur winszra winydvf wintgkd winwapw winvmcy winohmp winrgzv winddwr wincnpf winncjg winaslp winlnyy winotfu winrpva winadqw winywgb winoeye winzmoo winloxz winabhl winxyje winoplo winlztk winmpti winopnn wingorv winvwuw winfung winuznj winjcbc winsvfr winerno winhgdg winoifn winktkk winsnya winbhya winidhb winkvls winnqcp winhnld
It then grabs “LocatePC.exe” from the current directory, and copies it to “INSTALLDIR\EXENAME.exe”; the installer then updates the database with the MAC address of our machine, the installation directory, and the executable’s name.
At this point, the installer presents us with a registration process. It asks for typical information: username, password, address, email, etc. In addition, the user selects a “boss-key”, a key combination used to show or hide the trojan menu. It also grabs the external IP of the machine from This information is then inserted into the database. The password the user gives is then stored in “INSTALLDIR\EXENAME”, a file with no extension. The boss-key is written to “INSTALLDIR\_EXENAME.resx”.
A unique random 32-character alphanumeric string is generated. This used to uniquely identify the trojan install within the database later. This string is stored in “INSTALLDIR\EXENAME.0” (that’s a zero on the end, fonts are annoying).
The installer creates an entry in HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run\ for the newly installed trojan executable. Finally, a browser windows is spawned to the LIGATT LocatePC page, and the trojan is launched.
The Trojan
First things first, the trojan makes a connection to the MySQL database with the same credentials used above. If it’s unable to connect, it quits. It then grabs its name and installation directory from the command-line arguments list.
Now, I found this next part interesting. It creates a mutex called “LocatePC Lite”, creating it if it doesn’t exist. If it’s unable to grab the mutex (because another process holds it) then it quits. This ensures that only one copy of the trojan is running!
After that, we grab the 32-character string from “INSTALLDIR\EXENAME.0”, and look that up in the database, giving us information about the license, version, username, password. The trojan then uses this information to update the “last_login” on the account, with the current time, software version, and the mac address of the machine.
The program then opens up “INSTALLDIR\_EXENAME.resx” to get the boss-key, and registers that with the windows HotKey interface; it is then tied to a small windows that allows the user to quit the trojan or click an “About” link taking them to the LIGATT website.
Now, the trojan spawns a new thread. This thread performs all the actions listed below.
  • Check the database for whether we should uninstall ourselves. If so, deletes the entire INSTALLDIR directory, and removes the relevant registry key.
  • Check the database for whether we should update ourselves. If so, downloads the new version, replaces the executable, spawns a thread with the new executable and closes this thread.
  • Grab system information, mostly from WMI. This includes things like all IP and MAC addresses, OS version, motherboard serial number, bios version, etc. All of this information is then inserted into the database and associated with the registration code
  • Check the database for whether we should keylog. If so, record all keystrokes to the database.
  • Check the database for whether we should shutdown the PC. If so, do so.
  • Check the database for whether we should display a custom message. Message box appears with the message if there is one.
  • Check the database for whether we should activate the webcam. If so, takes a photo now and every 30 minutes, upload the jpg capture to the database.

Final Thoughts

The product ideas are good. That is, recording keystrokes, IP addresses, and webcam images are a good way to retrieve a laptop. However the actual design is severely flawed: all interactions require the database, and both programs fail if the database is inaccessible. In addition, there are several occurrences within the code of MySQL queries being made without parameterization; this could lead to SQL Injection from inside the application. As mentioned above, if the database were actually accessible for the program, it would also be accessible for anyone able to extract the credentials from the executables; this would allow an attacker to extract all information stored about the LocatePC clients, including full registration information.
Something else emerges quickly from that last thought. A more dedicated attacker could modify the database to set all instances of the trojan to enable keylogging, and then extract this information from all those computers via the database. One could argue that this was part of the design of LocatePC from the beginning: having a client pay to install a keylogger on their computer and commit identity theft with the data obtained. That’s a pretty good scam.
EDIT: clarified the section about the trojan connecting to the database, and where it gets its name from.

Copyright Protection

Wikipedia defines Copyright as:

[T]he set of exclusive rights granted to the author or creator of an original work, including the right to copy, distribute and adapt the work. These rights can be licensed, transferred and/or assigned. – source:

What that means is that the creator of a piece of original work has the right to do whatever they want with it. Copyright infringement, as Wikipedia goes on to define in the same page, is any use of that work that violates the creator’s exclusive rights. If someone is violating your rights by misusing your intellectual property, nobody but you can stop them.

Let’s focus on written works for a moment. There is international law that protects you, the author, from people reproducing your works without your consent. In fact, as soon as you record the original work to a physical medium, you are automatically entitled to those rights without the need for registration of any kind.

(Disclaimer: I’m not a lawyer, and nothing I say should ever be interpreted as legal advice. Always talk to a lawyer before undertaking any legal action.)

For discussion’s sake, let’s say someone copies a large section of an article you wrote, and includes it as a chapter in his book. Your first step should be to have a lawyer draft a Cease and Desist letter, stating that:

  • You are the copyright holder
  • He is infringing, and how he is doing so
  • You want the infringement to stop, including destruction of all copies and master copies, and a time frame you want it done in
  • You want to be given the profits the infringer has made from using your work, again with a time frame
  • Failure to comply within the timeframe given may result in further legal action

These are all totally reasonable demands to make of someone stealing your intellectual property, and it’s backed by The Berne Convention for the Protection of Literary and Artistic Works, which has been ratified in 164 countries.

So what if they don’t reply within the timeframe, or just tell you to shove it? Note that the above letter merely states “may result in further legal action”. At this point, a common consideration is legal cost: “What if I have to go to court? I don’t have that kind of money”. In most countries, winning a lawsuit means the losing party pays your legal costs, which is distinct from paying damages. If you think your works aren’t worth the potential legal costs, ask yourself this: Is your name worth it? Is your brand worth it? If you allow copyright infringement to continue, more people will steal your work, and your name or brand associated with that work. You may even lose your copyright.

If you don’t take action to protect your copyrighted works, you are implicitly giving everyone permission to steal your works, and you forfeit any right to complain about it on the internet.